@im-nobsidian/core 0.2.1 → 0.3.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/config.ts","../src/constants/paths.ts","../src/config/manager.ts","../src/utils/id.ts","../src/state/migrations/001-initial.ts","../src/state/migrations/002-file-registry.ts","../src/state/migrations/003-stat-cache.ts","../src/state/state-db.ts","../src/notion/property-mapper.ts","../src/utils/logger.ts","../src/notion/client.ts","../src/notion/block-builder.ts","../src/utils/hash.ts","../src/sync/change-detector.ts","../src/constants/markers.ts","../src/converter/pipeline.ts","../src/converter/pre-processors/frontmatter.ts","../src/converter/pre-processors/wikilink.ts","../src/converter/pre-processors/callout.ts","../src/converter/pre-processors/math.ts","../src/converter/pre-processors/embed.ts","../src/converter/pre-processors/preserve-marker.ts","../src/converter/pre-processors/unsupported-block-stripper.ts","../src/utils/frontmatter.ts","../src/converter/pre-processors/properties-table.ts","../src/converter/pre-processors/html-annotation.ts","../src/converter/link-restore.ts","../src/converter/post-processors/mention-to-wikilink.ts","../src/converter/post-processors/preserve-marker-injector.ts","../src/converter/post-processors/callout-restorer.ts","../src/converter/post-processors/color-annotator.ts","../src/converter/post-processors/frontmatter-generator.ts","../src/converter/post-processors/local-image-restorer.ts","../src/converter/post-processors/properties-table-restorer.ts","../src/converter/pipeline-factory.ts","../src/converter/rich-text-converter.ts","../src/converter/block-converter.ts","../src/sync/image-handler.ts","../src/sync/file-handler.ts","../src/sync/conflict-detector.ts","../src/utils/sanitize.ts","../src/utils/db-row-path.ts","../src/utils/wikilink-title.ts","../src/view/base-file-generator.ts","../src/view/sidecar-generator.ts","../src/sync/stale-db-artifacts.ts","../src/converter/enhanced-md-converter.ts","../src/sync/database-syncer.ts","../src/conflict/merger.ts","../src/conflict/resolver.ts","../src/utils/pool.ts","../src/sync/frontmatter-link-resolver.ts","../src/sync/orchestrator.ts","../src/sync/node-vault-fs.ts","../src/converter/pre-processors/inline-db.ts","../src/structure/tree-mapper.ts","../src/watcher/file-watcher.ts","../src/watcher/watch-sync-service.ts","../src/view/filter-engine.ts","../src/view/view-data-provider.ts","../src/view/entry-editor.ts","../src/view/color-map.ts","../src/audit/fidelity.ts"],"names":["stat","url","fetch","readFile","content","WIKILINK_REGEX","matter","escapeRegex","createHash","Sema","EXTENSION_TO_MIME","EMOJI_TYPE_MAP","i","j","extractAliases","title","existing","pathParts","join","mkdir","writeFile","extractTitleFromPath"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\n\nconst DatabaseSyncSchema = z.object({\n databaseId: z.string(),\n localFolder: z.string(),\n propertyMapping: z.record(z.string()).optional(),\n pullFilter: z.unknown().optional(),\n titleProperty: z.string().default(\"Name\"),\n});\n\nexport type DatabaseSyncConfig = z.infer<typeof DatabaseSyncSchema>;\n\nexport const ConfigSchema = z.object({\n version: z.literal(1),\n notion: z.object({\n token: z.string().startsWith(\"ntn_\"),\n rootPageId: z.string(),\n workspaceId: z.string().optional(),\n parentMode: z.enum([\"page\", \"database\"]).default(\"page\"),\n databaseId: z.string().optional(),\n databases: z.array(DatabaseSyncSchema).default([]),\n }),\n sync: z.object({\n direction: z.enum([\"push\", \"pull\", \"both\"]).default(\"both\"),\n conflictStrategy: z\n .enum([\"local-first\", \"remote-first\", \"manual\", \"duplicate\"])\n .default(\"manual\"),\n autoSync: z.boolean().default(false),\n autoSyncInterval: z.number().min(30).max(3600).default(300),\n deleteSync: z.boolean().default(false),\n syncFiles: z.boolean().default(true),\n }),\n paths: z.object({\n include: z.array(z.string()).default([\"**/*\"]),\n exclude: z.array(z.string()).default([]),\n attachments: z.string().default(\"attachments\"),\n }),\n conversion: z.object({\n preferMarkdownApi: z.boolean().default(true),\n preserveMarkers: z.boolean().default(true),\n frontmatterMapping: z.boolean().default(true),\n imageDownload: z.enum([\"immediate\", \"lazy\", \"skip\"]).default(\"immediate\"),\n }),\n advanced: z.object({\n // Notion API 클라이언트 동시성/타임아웃\n concurrency: z.number().min(1).max(10).default(3),\n timeoutMs: z.number().min(5000).max(60000).default(30000),\n // 페이지네이션/블록 배치 (Notion API children append 상한 = 100)\n pageSize: z.number().min(1).max(100).default(100),\n batchSize: z.number().min(1).max(100).default(100),\n // Rate limit 게이트 (요청 간 최소 간격, ms)\n rateLimitIntervalMs: z.number().min(0).max(5000).default(350),\n // API 재시도 (지수 백오프: retryBaseDelayMs * retryBackoffFactor^attempt)\n maxRetries: z.number().min(0).max(10).default(5),\n retryBaseDelayMs: z.number().min(100).max(10000).default(1000),\n retryBackoffFactor: z.number().min(1).max(10).default(2),\n // 오케스트레이터 단계 간 재시도 대기 (ms)\n retryWaitMs: z.number().min(0).max(30000).default(2000),\n // 미디어(이미지/파일) 다운로드 동시성/재시도\n mediaConcurrency: z.number().min(1).max(10).default(3),\n mediaMaxRetries: z.number().min(0).max(10).default(3),\n mediaRetryBaseMs: z.number().min(100).max(10000).default(1000),\n // 비마크다운 파일(첨부) 업로드/다운로드 동시성\n fileConcurrency: z.number().min(1).max(10).default(2),\n // 다운로드 파일 크기 상한 (bytes, 기본 100MB)\n maxFileSizeBytes: z\n .number()\n .min(1024)\n .default(100 * 1024 * 1024),\n }),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport const DEFAULT_CONFIG: Config = {\n version: 1,\n notion: {\n token: \"\",\n rootPageId: \"\",\n parentMode: \"page\",\n databases: [],\n },\n sync: {\n direction: \"both\",\n conflictStrategy: \"manual\",\n autoSync: false,\n autoSyncInterval: 300,\n deleteSync: false,\n syncFiles: true,\n },\n paths: {\n include: [\"**/*\"],\n exclude: [],\n attachments: \"attachments\",\n },\n conversion: {\n preferMarkdownApi: true,\n preserveMarkers: true,\n frontmatterMapping: true,\n imageDownload: \"immediate\",\n },\n advanced: {\n concurrency: 3,\n timeoutMs: 30000,\n pageSize: 100,\n batchSize: 100,\n rateLimitIntervalMs: 350,\n maxRetries: 5,\n retryBaseDelayMs: 1000,\n retryBackoffFactor: 2,\n retryWaitMs: 2000,\n mediaConcurrency: 3,\n mediaMaxRetries: 3,\n mediaRetryBaseMs: 1000,\n fileConcurrency: 2,\n maxFileSizeBytes: 100 * 1024 * 1024,\n },\n};\n","/**\n * 내부 메타데이터 경로 단일 진실원(SSOT).\n *\n * `.im-nobsidian` 디렉터리·하위 파일명·ignore 파일·gitignore 항목을 한곳에서 정의한다.\n * 디렉터리/파일명을 바꾸거나 리브랜딩할 때 이 파일만 수정하면 전 패키지에 반영된다.\n */\n\n/** 내부 메타데이터 디렉터리명 (vault 루트 기준). */\nexport const INTERNAL_DIR = \".im-nobsidian\";\n\n/** 동기화 설정 파일명. */\nexport const CONFIG_FILE = \"config.json\";\n\n/** SQLite 상태 DB 파일명. */\nexport const STATE_DB_FILE = \"sync.db\";\n\n/** DB 뷰 메타데이터 파일명. */\nexport const DB_VIEWS_FILE = \"db-views.json\";\n\n/** 동기화 제외 패턴 파일명 (디렉터리 외부, vault 루트 직속). */\nexport const IGNORE_FILE = \".im-nobsidian-ignore\";\n\n/** `.gitignore`에 추가하는 항목. */\nexport const GITIGNORE_ENTRY = `${INTERNAL_DIR}/`;\n\n/** vault 상대 POSIX 경로 — DB 뷰 메타데이터. */\nexport const DB_VIEWS_PATH = `${INTERNAL_DIR}/${DB_VIEWS_FILE}`;\n\n/** vault 상대 POSIX 경로 — 상태 DB. */\nexport const STATE_DB_PATH = `${INTERNAL_DIR}/${STATE_DB_FILE}`;\n\n/** 파일 감시에서 제외할 내부 디렉터리 glob. */\nexport const INTERNAL_DIR_GLOB = `**/${INTERNAL_DIR}/**`;\n\n/**\n * 주어진 vault 상대 경로(POSIX)가 내부 메타데이터 디렉터리에 속하는지 판별한다.\n */\nexport function isInternalPath(path: string): boolean {\n return path === INTERNAL_DIR || path.startsWith(`${INTERNAL_DIR}/`);\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { ConfigSchema, DEFAULT_CONFIG } from \"../types/config.js\";\nimport type { Config } from \"../types/config.js\";\nimport { INTERNAL_DIR, CONFIG_FILE, STATE_DB_FILE, GITIGNORE_ENTRY } from \"../constants/paths.js\";\n\nexport class ConfigManager {\n private config: Config | null = null;\n\n constructor(private readonly vaultRoot: string) {}\n\n get configDir(): string {\n return join(this.vaultRoot, INTERNAL_DIR);\n }\n\n get configPath(): string {\n return join(this.configDir, CONFIG_FILE);\n }\n\n get dbPath(): string {\n return join(this.configDir, STATE_DB_FILE);\n }\n\n async load(): Promise<Config> {\n try {\n const raw = await readFile(this.configPath, \"utf-8\");\n const parsed = JSON.parse(raw);\n this.config = ConfigSchema.parse(parsed);\n return this.config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`설정 파일의 JSON 형식이 올바르지 않습니다: ${this.configPath}`);\n }\n if (error instanceof Error && error.name === \"ZodError\") {\n throw new Error(`설정 파일 검증 실패: ${error.message}`);\n }\n throw new Error(\n `설정 파일을 찾을 수 없습니다: ${this.configPath}\\n'im-nobsidian init'을 먼저 실행하세요.`,\n );\n }\n }\n\n async save(config: Config): Promise<void> {\n await mkdir(this.configDir, { recursive: true });\n const content = JSON.stringify(config, null, 2);\n await writeFile(this.configPath, content, \"utf-8\");\n this.config = config;\n }\n\n async init(params: { token: string; rootPageId: string }): Promise<Config> {\n const config: Config = {\n ...DEFAULT_CONFIG,\n notion: {\n ...DEFAULT_CONFIG.notion,\n token: params.token,\n rootPageId: params.rootPageId,\n },\n };\n\n await this.save(config);\n await this.ensureGitignore();\n return config;\n }\n\n getConfig(): Config {\n if (!this.config) {\n throw new Error(\"설정이 로드되지 않았습니다. load()를 먼저 호출하세요.\");\n }\n return this.config;\n }\n\n private async ensureGitignore(): Promise<void> {\n const gitignorePath = join(this.vaultRoot, \".gitignore\");\n const entry = GITIGNORE_ENTRY;\n\n try {\n const content = await readFile(gitignorePath, \"utf-8\");\n if (!content.includes(entry)) {\n await writeFile(gitignorePath, `${content.trimEnd()}\\n${entry}\\n`, \"utf-8\");\n }\n } catch {\n await writeFile(gitignorePath, `${entry}\\n`, \"utf-8\");\n }\n }\n\n async isInitialized(): Promise<boolean> {\n try {\n const { stat } = await import(\"node:fs/promises\");\n await stat(this.configPath);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport function generateId(): string {\n return randomUUID();\n}\n\nexport function normalizeNotionId(id: string): string {\n const raw = id.replace(/-/g, \"\");\n if (raw.length !== 32) return id;\n return `${raw.slice(0, 8)}-${raw.slice(8, 12)}-${raw.slice(12, 16)}-${raw.slice(16, 20)}-${raw.slice(20)}`;\n}\n\nexport function notionIdsEqual(a: string, b: string): boolean {\n return a.replace(/-/g, \"\") === b.replace(/-/g, \"\");\n}\n\n/**\n * 멘션 위키링크용 정규 id — 하이픈 제거 + 소문자. 오케스트레이터의 멘션 해소 정규식\n * (`[[notion:<32hex>]]`)이 인식하는 유일한 형태다. 블록 폴백 경로(formatMention)와\n * markdown-api 경로(convertPageMentions)가 동일 형태로 수렴하도록 한다(rank20/I3).\n */\nexport function compactNotionId(id: string): string {\n return id.replace(/-/g, \"\").toLowerCase();\n}\n","export const INITIAL_MIGRATION = `\nCREATE TABLE IF NOT EXISTS sync_state (\n id TEXT PRIMARY KEY,\n obsidian_path TEXT NOT NULL,\n notion_page_id TEXT,\n notion_parent_id TEXT,\n content_hash TEXT NOT NULL,\n notion_last_edited TEXT,\n local_last_modified TEXT NOT NULL,\n sync_direction TEXT NOT NULL DEFAULT 'both',\n file_type TEXT NOT NULL DEFAULT 'file',\n status TEXT NOT NULL DEFAULT 'pending',\n base_snapshot BLOB,\n version INTEGER NOT NULL DEFAULT 1,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\n CONSTRAINT chk_sync_direction CHECK (sync_direction IN ('push', 'pull', 'both')),\n CONSTRAINT chk_file_type CHECK (file_type IN ('file', 'folder-note', 'folder-only', 'db-row')),\n CONSTRAINT chk_status CHECK (status IN ('synced', 'pending', 'conflict', 'error'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_sync_state_path ON sync_state(obsidian_path);\nCREATE UNIQUE INDEX IF NOT EXISTS idx_sync_state_notion ON sync_state(notion_page_id) WHERE notion_page_id IS NOT NULL;\nCREATE INDEX IF NOT EXISTS idx_sync_state_status ON sync_state(status);\nCREATE INDEX IF NOT EXISTS idx_sync_state_parent ON sync_state(notion_parent_id);\n\nCREATE TABLE IF NOT EXISTS wikilink_map (\n obsidian_path TEXT PRIMARY KEY,\n notion_page_id TEXT NOT NULL UNIQUE,\n title TEXT NOT NULL,\n aliases TEXT DEFAULT '[]',\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_wikilink_title ON wikilink_map(title);\nCREATE INDEX IF NOT EXISTS idx_wikilink_notion ON wikilink_map(notion_page_id);\n\nCREATE TABLE IF NOT EXISTS pending_operations (\n id TEXT PRIMARY KEY,\n sync_state_id TEXT NOT NULL REFERENCES sync_state(id) ON DELETE CASCADE,\n operation TEXT NOT NULL,\n direction TEXT NOT NULL,\n payload TEXT,\n retry_count INTEGER NOT NULL DEFAULT 0,\n error_message TEXT,\n status TEXT NOT NULL DEFAULT 'pending',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT,\n\n CONSTRAINT chk_operation CHECK (operation IN ('create', 'update', 'delete', 'move')),\n CONSTRAINT chk_direction CHECK (direction IN ('push', 'pull')),\n CONSTRAINT chk_op_status CHECK (status IN ('pending', 'processing', 'completed', 'failed'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_pending_status ON pending_operations(status, created_at);\n\nCREATE TABLE IF NOT EXISTS image_registry (\n id TEXT PRIMARY KEY,\n sync_state_id TEXT NOT NULL REFERENCES sync_state(id) ON DELETE CASCADE,\n notion_file_url TEXT NOT NULL,\n local_path TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n file_size INTEGER NOT NULL,\n mime_type TEXT NOT NULL,\n expires_at TEXT,\n downloaded_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_image_hash ON image_registry(content_hash);\nCREATE INDEX IF NOT EXISTS idx_image_sync ON image_registry(sync_state_id);\n\nCREATE TABLE IF NOT EXISTS sync_metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n\nINSERT OR IGNORE INTO sync_metadata (key, value) VALUES ('schema_version', '1');\n`;\n","export const FILE_REGISTRY_MIGRATION = `\nCREATE TABLE IF NOT EXISTS file_registry (\n id TEXT PRIMARY KEY,\n local_path TEXT NOT NULL,\n notion_page_id TEXT NOT NULL,\n file_upload_id TEXT NOT NULL,\n file_type TEXT NOT NULL DEFAULT 'file',\n file_hash TEXT NOT NULL,\n file_size INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\n CONSTRAINT chk_file_type CHECK (file_type IN ('image', 'pdf', 'video', 'audio', 'file'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_file_registry_path ON file_registry(local_path);\nCREATE INDEX IF NOT EXISTS idx_file_registry_page ON file_registry(notion_page_id);\n\nUPDATE sync_metadata SET value = '2' WHERE key = 'schema_version';\n`;\n","export const STAT_CACHE_MIGRATION = `\nALTER TABLE sync_state ADD COLUMN local_mtime TEXT;\nALTER TABLE sync_state ADD COLUMN local_file_size INTEGER;\n\nUPDATE sync_metadata SET value = '3' WHERE key = 'schema_version';\n`;\n","import Database from \"better-sqlite3\";\nimport type { SyncRecord, SyncStatus, WikilinkEntry, PreserveMarker } from \"../types/index.js\";\nimport { generateId } from \"../utils/id.js\";\nimport { INITIAL_MIGRATION } from \"./migrations/001-initial.js\";\nimport { FILE_REGISTRY_MIGRATION } from \"./migrations/002-file-registry.js\";\nimport { STAT_CACHE_MIGRATION } from \"./migrations/003-stat-cache.js\";\nimport type { IStateDB } from \"./state-db-interface.js\";\n\nexport class StateDB implements IStateDB {\n private readonly db: Database.Database;\n\n private constructor(db: Database.Database) {\n this.db = db;\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"foreign_keys = ON\");\n }\n\n static open(dbPath: string): StateDB {\n const db = new Database(dbPath);\n const stateDb = new StateDB(db);\n stateDb.migrate();\n return stateDb;\n }\n\n private migrate(): void {\n const version = this.getSchemaVersion();\n if (version < 1) {\n this.db.exec(INITIAL_MIGRATION);\n }\n if (version < 2) {\n this.db.exec(FILE_REGISTRY_MIGRATION);\n }\n if (version < 3) {\n this.db.exec(STAT_CACHE_MIGRATION);\n }\n }\n\n private getSchemaVersion(): number {\n try {\n const row = this.db\n .prepare(\"SELECT value FROM sync_metadata WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined;\n return row ? Number(row.value) : 0;\n } catch {\n return 0;\n }\n }\n\n close(): void {\n this.db.close();\n }\n\n // --- sync_state ---\n\n getByPath(path: string): SyncRecord | null {\n const row = this.db.prepare(\"SELECT * FROM sync_state WHERE obsidian_path = ?\").get(path) as\n | RawSyncRow\n | undefined;\n return row ? this.mapRow(row) : null;\n }\n\n getByNotionId(pageId: string): SyncRecord | null {\n const row = this.db.prepare(\"SELECT * FROM sync_state WHERE notion_page_id = ?\").get(pageId) as\n | RawSyncRow\n | undefined;\n return row ? this.mapRow(row) : null;\n }\n\n getByStatus(status: SyncStatus): SyncRecord[] {\n const rows = this.db\n .prepare(\"SELECT * FROM sync_state WHERE status = ?\")\n .all(status) as RawSyncRow[];\n return rows.map((r) => this.mapRow(r));\n }\n\n getAll(): SyncRecord[] {\n const rows = this.db.prepare(\"SELECT * FROM sync_state\").all() as RawSyncRow[];\n return rows.map((r) => this.mapRow(r));\n }\n\n upsert(record: UpsertSyncRecord): SyncRecord {\n const existing = this.getByPath(record.obsidianPath);\n\n if (existing) {\n this.db\n .prepare(\n `UPDATE sync_state SET\n notion_page_id = ?, notion_parent_id = ?, content_hash = ?,\n notion_last_edited = ?, local_last_modified = ?,\n sync_direction = ?, file_type = ?, status = ?,\n base_snapshot = ?, local_mtime = ?, local_file_size = ?,\n version = version + 1, updated_at = datetime('now')\n WHERE id = ?`,\n )\n .run(\n record.notionPageId ?? null,\n record.notionParentId ?? null,\n record.contentHash,\n record.notionLastEdited ?? null,\n record.localLastModified,\n record.syncDirection,\n record.fileType,\n record.status,\n record.baseSnapshot ?? null,\n record.localMtime ?? null,\n record.localFileSize ?? null,\n existing.id,\n );\n return this.getByPath(record.obsidianPath)!;\n }\n\n const id = generateId();\n this.db\n .prepare(\n `INSERT INTO sync_state\n (id, obsidian_path, notion_page_id, notion_parent_id, content_hash,\n notion_last_edited, local_last_modified, sync_direction, file_type,\n status, base_snapshot, local_mtime, local_file_size, version)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)`,\n )\n .run(\n id,\n record.obsidianPath,\n record.notionPageId ?? null,\n record.notionParentId ?? null,\n record.contentHash,\n record.notionLastEdited ?? null,\n record.localLastModified,\n record.syncDirection,\n record.fileType,\n record.status,\n record.baseSnapshot ?? null,\n record.localMtime ?? null,\n record.localFileSize ?? null,\n );\n return this.getByPath(record.obsidianPath)!;\n }\n\n updateStatus(id: string, status: SyncStatus): void {\n this.db\n .prepare(\"UPDATE sync_state SET status = ?, updated_at = datetime('now') WHERE id = ?\")\n .run(status, id);\n }\n\n updateHash(id: string, hash: string, snapshot?: Buffer | null): void {\n if (snapshot !== undefined) {\n this.db\n .prepare(\n \"UPDATE sync_state SET content_hash = ?, base_snapshot = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(hash, snapshot, id);\n } else {\n this.db\n .prepare(\n \"UPDATE sync_state SET content_hash = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(hash, id);\n }\n }\n\n setNotionLastEdited(id: string, lastEdited: string): void {\n this.db\n .prepare(\n \"UPDATE sync_state SET notion_last_edited = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(lastEdited, id);\n }\n\n updateStatCache(id: string, mtime: string, fileSize: number): void {\n this.db\n .prepare(\n \"UPDATE sync_state SET local_mtime = ?, local_file_size = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(mtime, fileSize, id);\n }\n\n setNotionParentId(id: string, parentId: string): void {\n this.db\n .prepare(\n \"UPDATE sync_state SET notion_parent_id = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(parentId, id);\n }\n\n updatePath(id: string, newPath: string): void {\n this.db\n .prepare(\"UPDATE sync_state SET obsidian_path = ?, updated_at = datetime('now') WHERE id = ?\")\n .run(newPath, id);\n }\n\n delete(id: string): void {\n this.db.prepare(\"DELETE FROM sync_state WHERE id = ?\").run(id);\n }\n\n // --- wikilink_map ---\n\n resolveWikilink(text: string): WikilinkEntry | null {\n const byTitle = this.db.prepare(\"SELECT * FROM wikilink_map WHERE title = ?\").get(text) as\n | RawWikilinkRow\n | undefined;\n\n if (byTitle) return this.mapWikilinkRow(byTitle);\n\n const byAlias = this.db\n .prepare(\"SELECT * FROM wikilink_map WHERE aliases LIKE ?\")\n .get(`%\"${text}\"%`) as RawWikilinkRow | undefined;\n\n if (byAlias) return this.mapWikilinkRow(byAlias);\n\n const byFilename = this.db\n .prepare(\"SELECT * FROM wikilink_map WHERE obsidian_path LIKE ?\")\n .get(`%/${text}.md`) as RawWikilinkRow | undefined;\n\n return byFilename ? this.mapWikilinkRow(byFilename) : null;\n }\n\n resolvePageId(pageId: string): WikilinkEntry | null {\n const row = this.db\n .prepare(\"SELECT * FROM wikilink_map WHERE notion_page_id = ?\")\n .get(pageId) as RawWikilinkRow | undefined;\n return row ? this.mapWikilinkRow(row) : null;\n }\n\n upsertWikilink(entry: WikilinkEntry): void {\n this.db\n .prepare(\n `INSERT OR REPLACE INTO wikilink_map (obsidian_path, notion_page_id, title, aliases, updated_at)\n VALUES (?, ?, ?, ?, datetime('now'))`,\n )\n .run(entry.obsidianPath, entry.notionPageId, entry.title, JSON.stringify(entry.aliases));\n }\n\n deleteWikilink(obsidianPath: string): void {\n this.db.prepare(\"DELETE FROM wikilink_map WHERE obsidian_path = ?\").run(obsidianPath);\n }\n\n // --- sync_metadata ---\n\n getMeta(key: string): string | null {\n const row = this.db.prepare(\"SELECT value FROM sync_metadata WHERE key = ?\").get(key) as\n | { value: string }\n | undefined;\n return row?.value ?? null;\n }\n\n setMeta(key: string, value: string): void {\n this.db\n .prepare(\"INSERT OR REPLACE INTO sync_metadata (key, value) VALUES (?, ?)\")\n .run(key, value);\n }\n\n // --- file_registry ---\n\n isFileRegistered(localPath: string): boolean {\n const row = this.db.prepare(\"SELECT 1 FROM file_registry WHERE local_path = ?\").get(localPath);\n return !!row;\n }\n\n getFileRegistry(localPath: string): FileRegistryEntry | null {\n const row = this.db\n .prepare(\"SELECT * FROM file_registry WHERE local_path = ?\")\n .get(localPath) as RawFileRegistryRow | undefined;\n return row ? this.mapFileRegistryRow(row) : null;\n }\n\n getFilesByPageId(notionPageId: string): FileRegistryEntry[] {\n const rows = this.db\n .prepare(\"SELECT * FROM file_registry WHERE notion_page_id = ?\")\n .all(notionPageId) as RawFileRegistryRow[];\n return rows.map((r) => this.mapFileRegistryRow(r));\n }\n\n registerFile(entry: RegisterFileInput): void {\n const id = generateId();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO file_registry\n (id, local_path, notion_page_id, file_upload_id, file_type, file_hash, file_size)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n entry.localPath,\n entry.notionPageId,\n entry.fileUploadId,\n entry.fileType,\n entry.fileHash,\n entry.fileSize,\n );\n }\n\n deleteFileRegistry(localPath: string): void {\n this.db.prepare(\"DELETE FROM file_registry WHERE local_path = ?\").run(localPath);\n }\n\n private mapFileRegistryRow(row: RawFileRegistryRow): FileRegistryEntry {\n return {\n id: row.id,\n localPath: row.local_path,\n notionPageId: row.notion_page_id,\n fileUploadId: row.file_upload_id,\n fileType: row.file_type,\n fileHash: row.file_hash,\n fileSize: row.file_size,\n };\n }\n\n // --- pending_operations (I12 크래시 복구 WAL) ---\n\n recordPendingOperation(input: RecordPendingInput): string {\n const id = generateId();\n this.db\n .prepare(\n `INSERT INTO pending_operations\n (id, sync_state_id, operation, direction, payload, status)\n VALUES (?, ?, ?, ?, ?, 'pending')`,\n )\n .run(id, input.syncStateId, input.operation, input.direction, input.payload ?? null);\n return id;\n }\n\n getIncompletePendingOperations(): PendingOperation[] {\n const rows = this.db\n .prepare(\n \"SELECT * FROM pending_operations WHERE status IN ('pending', 'processing') ORDER BY created_at ASC\",\n )\n .all() as RawPendingRow[];\n return rows.map((r) => this.mapPendingRow(r));\n }\n\n getIncompleteOpByState(\n syncStateId: string,\n operation: PendingOperation[\"operation\"],\n ): PendingOperation | null {\n const row = this.db\n .prepare(\n `SELECT * FROM pending_operations\n WHERE sync_state_id = ? AND operation = ? AND status IN ('pending', 'processing')\n ORDER BY created_at ASC LIMIT 1`,\n )\n .get(syncStateId, operation) as RawPendingRow | undefined;\n return row ? this.mapPendingRow(row) : null;\n }\n\n markPendingCompleted(id: string): void {\n this.db\n .prepare(\n \"UPDATE pending_operations SET status = 'completed', completed_at = datetime('now') WHERE id = ?\",\n )\n .run(id);\n }\n\n markPendingFailed(id: string, errorMessage: string): void {\n this.db\n .prepare(\n \"UPDATE pending_operations SET status = 'failed', retry_count = retry_count + 1, error_message = ?, completed_at = datetime('now') WHERE id = ?\",\n )\n .run(errorMessage, id);\n }\n\n clearCompletedOperations(): void {\n this.db.prepare(\"DELETE FROM pending_operations WHERE status IN ('completed', 'failed')\").run();\n }\n\n private mapPendingRow(row: RawPendingRow): PendingOperation {\n return {\n id: row.id,\n syncStateId: row.sync_state_id,\n operation: row.operation as PendingOperation[\"operation\"],\n direction: row.direction as PendingOperation[\"direction\"],\n payload: row.payload,\n retryCount: row.retry_count,\n errorMessage: row.error_message,\n status: row.status as PendingOperation[\"status\"],\n createdAt: row.created_at,\n completedAt: row.completed_at,\n };\n }\n\n // --- preserve markers ---\n\n storePreserveMarkers(path: string, markers: PreserveMarker[]): void {\n if (markers.length === 0) {\n this.db.prepare(\"DELETE FROM sync_metadata WHERE key = ?\").run(`preserve_markers:${path}`);\n return;\n }\n this.setMeta(`preserve_markers:${path}`, JSON.stringify(markers));\n }\n\n getPreserveMarkers(path: string): PreserveMarker[] {\n const value = this.getMeta(`preserve_markers:${path}`);\n if (!value) return [];\n try {\n return JSON.parse(value) as PreserveMarker[];\n } catch {\n return [];\n }\n }\n\n // --- transaction ---\n\n transaction<T>(fn: () => T): T {\n return this.db.transaction(fn)();\n }\n\n // --- private ---\n\n private mapRow(row: RawSyncRow): SyncRecord {\n return {\n id: row.id,\n obsidianPath: row.obsidian_path,\n notionPageId: row.notion_page_id,\n notionParentId: row.notion_parent_id,\n contentHash: row.content_hash,\n notionLastEdited: row.notion_last_edited,\n localLastModified: row.local_last_modified,\n syncDirection: row.sync_direction as SyncRecord[\"syncDirection\"],\n fileType: row.file_type as SyncRecord[\"fileType\"],\n status: row.status as SyncRecord[\"status\"],\n baseSnapshot: row.base_snapshot,\n localMtime: row.local_mtime,\n localFileSize: row.local_file_size,\n version: row.version,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n private mapWikilinkRow(row: RawWikilinkRow): WikilinkEntry {\n return {\n obsidianPath: row.obsidian_path,\n notionPageId: row.notion_page_id,\n title: row.title,\n aliases: JSON.parse(row.aliases || \"[]\") as string[],\n };\n }\n}\n\nexport interface UpsertSyncRecord {\n readonly obsidianPath: string;\n readonly notionPageId?: string | null;\n readonly notionParentId?: string | null;\n readonly contentHash: string;\n readonly notionLastEdited?: string | null;\n readonly localLastModified: string;\n readonly syncDirection: SyncRecord[\"syncDirection\"];\n readonly fileType: SyncRecord[\"fileType\"];\n readonly status: SyncRecord[\"status\"];\n readonly baseSnapshot?: Buffer | null;\n readonly localMtime?: string | null;\n readonly localFileSize?: number | null;\n}\n\ninterface RawSyncRow {\n id: string;\n obsidian_path: string;\n notion_page_id: string | null;\n notion_parent_id: string | null;\n content_hash: string;\n notion_last_edited: string | null;\n local_last_modified: string;\n sync_direction: string;\n file_type: string;\n status: string;\n base_snapshot: Buffer | null;\n local_mtime: string | null;\n local_file_size: number | null;\n version: number;\n created_at: string;\n updated_at: string;\n}\n\ninterface RawWikilinkRow {\n obsidian_path: string;\n notion_page_id: string;\n title: string;\n aliases: string;\n updated_at: string;\n}\n\ninterface RawFileRegistryRow {\n id: string;\n local_path: string;\n notion_page_id: string;\n file_upload_id: string;\n file_type: string;\n file_hash: string;\n file_size: number;\n}\n\nexport interface FileRegistryEntry {\n readonly id: string;\n readonly localPath: string;\n readonly notionPageId: string;\n readonly fileUploadId: string;\n readonly fileType: string;\n readonly fileHash: string;\n readonly fileSize: number;\n}\n\nexport interface RegisterFileInput {\n readonly localPath: string;\n readonly notionPageId: string;\n readonly fileUploadId: string;\n readonly fileType: string;\n readonly fileHash: string;\n readonly fileSize: number;\n}\n\ninterface RawPendingRow {\n id: string;\n sync_state_id: string;\n operation: string;\n direction: string;\n payload: string | null;\n retry_count: number;\n error_message: string | null;\n status: string;\n created_at: string;\n completed_at: string | null;\n}\n\n/** I12 크래시 복구 WAL 항목. push/pull 적용 전 기록되고, 적용 완료 시 completed 로 마감된다. */\nexport interface PendingOperation {\n readonly id: string;\n readonly syncStateId: string;\n readonly operation: \"create\" | \"update\" | \"delete\" | \"move\";\n readonly direction: \"push\" | \"pull\";\n readonly payload: string | null;\n readonly retryCount: number;\n readonly errorMessage: string | null;\n readonly status: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n readonly createdAt: string;\n readonly completedAt: string | null;\n}\n\nexport interface RecordPendingInput {\n readonly syncStateId: string;\n readonly operation: PendingOperation[\"operation\"];\n readonly direction: PendingOperation[\"direction\"];\n readonly payload?: string | null;\n}\n","type NotionPropertySchema = {\n id: string;\n type: string;\n name: string;\n};\n\ntype NotionPropertyValue = Record<string, unknown>;\n\n// ISO-8601 date / datetime. **양끝 앵커 필수** — 앵커가 없으면 \"2026-05-29 마감\" 처럼\n// 날짜로 시작하는 일반 텍스트가 date 로 오분류되어 본문이 유실되고 Notion 에 잘못된\n// 날짜가 전송된다. 초/밀리초/타임존(Z, ±HH:MM)까지 허용해 read→write 라운드트립을 보존.\nconst DATE_REGEX =\n /^\\d{4}-\\d{2}-\\d{2}(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,3})?)?(?:Z|[+-]\\d{2}:?\\d{2})?)?$/;\nconst WIKILINK_REGEX = /^\\[\\[(.+?)(?:\\|.+?)?\\]\\]$/;\n\n/**\n * Notion 은 비어 있는 배열형 속성값을 문서화된 `[]` 가 아니라 빈 객체 `{}` 로\n * 돌려주는 경우가 있다(특히 data source 분리 모델의 일부 행). `as Array<…>` 캐스트는\n * 이 불일치를 숨기고, 뒤따르는 `.map` 호출이 \"X.map is not a function\" 으로 그 행\n * 전체를 pull 실패시켜 **영구 데이터 손실 + 멱등성(churn) 위반**을 만든다.\n * 모든 배열 추출은 이 가드를 통과시켜, 배열이 아니면 안전하게 빈 배열로 강등한다.\n */\nfunction asArray<T>(value: unknown): T[] {\n return Array.isArray(value) ? (value as T[]) : [];\n}\n\nexport interface WikilinkResolver {\n resolve(title: string): string | null;\n resolvePageId(pageId: string): string | null;\n}\n\nexport class PropertyMapper {\n private schema: Map<string, NotionPropertySchema> = new Map();\n private wikilinkResolver: WikilinkResolver | null = null;\n\n setWikilinkResolver(resolver: WikilinkResolver): void {\n this.wikilinkResolver = resolver;\n }\n\n loadSchema(properties: Record<string, { id: string; type: string }>): void {\n this.schema.clear();\n for (const [name, prop] of Object.entries(properties)) {\n this.schema.set(name, { id: prop.id, type: prop.type, name });\n }\n }\n\n toNotionProperties(\n frontmatter: Record<string, unknown>,\n title: string,\n ): Record<string, NotionPropertyValue> {\n const result: Record<string, NotionPropertyValue> = {\n title: { title: [{ text: { content: title } }] },\n };\n\n for (const [key, value] of Object.entries(frontmatter)) {\n if (key === \"title\") continue;\n if (value === null || value === undefined) continue;\n\n const schemaProp = this.schema.get(key);\n if (schemaProp) {\n const converted = this.convertBySchema(schemaProp.type, value);\n if (converted) result[key] = converted;\n } else {\n const inferred = this.inferAndConvert(value);\n if (inferred) result[key] = inferred;\n }\n }\n\n return result;\n }\n\n fromNotionProperties(notionProps: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, rawProp] of Object.entries(notionProps)) {\n const prop = rawProp as { type: string; [k: string]: unknown };\n if (prop.type === \"title\") continue;\n const value = this.extractValue(prop);\n if (value !== undefined) {\n result[key] = value;\n }\n }\n\n return result;\n }\n\n private convertBySchema(type: string, value: unknown): NotionPropertyValue | null {\n switch (type) {\n case \"rich_text\":\n return { rich_text: [{ text: { content: String(value) } }] };\n\n case \"number\": {\n // 숫자로 변환 불가한 값(NaN/Infinity)은 전송하지 않는다. {number: NaN} 은\n // JSON 직렬화 시 null 로 바뀌어 기존 값을 소리 없이 비워버린다.\n const num = typeof value === \"number\" ? value : Number(value);\n return Number.isFinite(num) ? { number: num } : null;\n }\n\n case \"select\": {\n // 빈 이름은 Notion API 가 거부한다. 공백뿐이면 스킵(기존 값 보존).\n const name = String(value);\n return name.trim() ? { select: { name } } : null;\n }\n\n case \"multi_select\": {\n const items = Array.isArray(value)\n ? value\n : String(value)\n .split(\",\")\n .map((s) => s.trim());\n // 빈 옵션 이름 제거 — \"a,,b\" 나 후행 콤마로 생긴 빈 항목은 Notion 이 거부한다.\n const names = items.map((name: unknown) => String(name)).filter((name) => name.trim());\n return { multi_select: names.map((name) => ({ name })) };\n }\n\n case \"checkbox\":\n return { checkbox: Boolean(value) };\n\n case \"date\": {\n if (typeof value === \"object\" && value !== null && \"start\" in value) {\n const obj = value as { start: string; end?: string | null };\n return { date: { start: obj.start, end: obj.end ?? null } };\n }\n const dateStr = String(value);\n if (DATE_REGEX.test(dateStr)) {\n return { date: { start: dateStr, end: null } };\n }\n return null;\n }\n\n case \"url\":\n return { url: String(value) };\n\n case \"email\":\n return { email: String(value) };\n\n case \"phone_number\":\n return { phone_number: String(value) };\n\n case \"status\": {\n // select 와 동일 — 빈 상태 이름은 Notion 이 거부한다.\n const name = String(value);\n return name.trim() ? { status: { name } } : null;\n }\n\n case \"relation\": {\n const items = Array.isArray(value) ? value : [value];\n const ids: Array<{ id: string }> = [];\n for (const item of items) {\n const str = String(item);\n const match = str.match(WIKILINK_REGEX);\n if (match?.[1] && this.wikilinkResolver) {\n const pageId = this.wikilinkResolver.resolve(match[1]);\n if (pageId) ids.push({ id: pageId });\n } else if (str.match(/^[0-9a-f-]{32,36}$/)) {\n ids.push({ id: str });\n }\n }\n return ids.length > 0 ? { relation: ids } : null;\n }\n\n case \"people\": {\n const users = Array.isArray(value) ? value : [value];\n const peopleArr = users\n .map((u) => {\n const s = String(u);\n if (s.match(/^[0-9a-f-]{32,36}$/)) return { object: \"user\" as const, id: s };\n return null;\n })\n .filter(Boolean);\n return peopleArr.length > 0 ? { people: peopleArr } : null;\n }\n\n case \"files\": {\n const fileList = Array.isArray(value) ? value : [value];\n // 빈 URL 파일 항목은 Notion 이 거부하므로 제거한다(잘못된 첨부 전송 방지).\n const filesArr = fileList\n .map((f) => {\n if (typeof f === \"object\" && f !== null && \"url\" in f) {\n const obj = f as { name?: string; url: string };\n const url = String(obj.url ?? \"\");\n if (!url) return null;\n return { type: \"external\", name: obj.name ?? \"file\", external: { url } };\n }\n const url = String(f);\n if (!url) return null;\n return { type: \"external\", name: url, external: { url } };\n })\n .filter(Boolean);\n return { files: filesArr };\n }\n\n case \"created_time\":\n case \"last_edited_time\":\n case \"created_by\":\n case \"last_edited_by\":\n case \"formula\":\n case \"rollup\":\n case \"unique_id\":\n case \"verification\":\n return null;\n\n default:\n return { rich_text: [{ text: { content: String(value) } }] };\n }\n }\n\n private inferAndConvert(value: unknown): NotionPropertyValue | null {\n if (typeof value === \"boolean\") {\n return { checkbox: value };\n }\n if (typeof value === \"number\") {\n return { number: value };\n }\n if (Array.isArray(value)) {\n return {\n multi_select: value.map((v) => ({ name: String(v) })),\n };\n }\n if (typeof value === \"string\") {\n if (DATE_REGEX.test(value)) {\n return { date: { start: value, end: null } };\n }\n if (value.startsWith(\"http://\") || value.startsWith(\"https://\")) {\n return { url: value };\n }\n return { rich_text: [{ text: { content: value } }] };\n }\n return null;\n }\n\n private extractValue(prop: { type: string; [k: string]: unknown }): unknown {\n switch (prop.type) {\n case \"rich_text\": {\n const arr = asArray<{ plain_text: string }>(prop.rich_text);\n return arr.map((t) => t.plain_text).join(\"\") || null;\n }\n case \"number\":\n return prop.number;\n case \"select\": {\n const sel = prop.select as { name: string } | null;\n return sel?.name ?? null;\n }\n case \"multi_select\": {\n return asArray<{ name: string }>(prop.multi_select).map((s) => s.name);\n }\n case \"checkbox\":\n return prop.checkbox;\n case \"date\": {\n const dateObj = prop.date as { start: string; end?: string | null } | null;\n if (!dateObj) return null;\n if (dateObj.end) return { start: dateObj.start, end: dateObj.end };\n return dateObj.start;\n }\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 \"status\": {\n const status = prop.status as { name: string } | null;\n return status?.name ?? null;\n }\n case \"created_time\":\n return prop.created_time;\n case \"last_edited_time\":\n return prop.last_edited_time;\n case \"people\": {\n return asArray<{ name?: string; id: string }>(prop.people).map((p) => p.name ?? p.id);\n }\n case \"files\": {\n const files = asArray<{\n name: string;\n type: string;\n file?: { url: string };\n external?: { url: string };\n }>(prop.files);\n // Obsidian Bases 의 카드 `image:` 는 스칼라 문자열(외부 URL 또는 [[wikilink]])만\n // 렌더한다 — [{name,url}] 객체 배열은 표시되지 않는다. 따라서 URL 문자열로 직렬화한다.\n // 단일 파일 → 스칼라(갤러리 커버 렌더), 복수 → URL 배열(데이터 보존).\n // toNotionProperties 의 files 케이스가 문자열/문자열배열을 모두 받으므로 라운드트립 안전.\n const urls = files\n .map((f) => (f.type === \"file\" ? f.file?.url : f.external?.url))\n .filter((u): u is string => typeof u === \"string\" && u.length > 0);\n if (urls.length === 0) return [];\n return urls.length === 1 ? urls[0] : urls;\n }\n case \"formula\": {\n const formula = prop.formula as { type: string; [k: string]: unknown } | undefined;\n if (!formula) return null;\n return formula[formula.type];\n }\n case \"relation\": {\n const rel = asArray<{ id: string }>(prop.relation);\n if (rel.length === 0) return [];\n return rel.map((r) => {\n if (this.wikilinkResolver) {\n const title = this.wikilinkResolver.resolvePageId(r.id);\n if (title) return `[[${title}]]`;\n }\n return r.id;\n });\n }\n case \"rollup\": {\n const rollup = prop.rollup as { type: string; [k: string]: unknown } | undefined;\n if (!rollup) return null;\n if (rollup.type === \"array\") {\n const arr = asArray<{ type: string; [k: string]: unknown }>(rollup.array);\n return arr.map((item) => this.extractValue(item));\n }\n return rollup[rollup.type] ?? null;\n }\n case \"unique_id\": {\n const uid = prop.unique_id as { prefix?: string; number?: number } | undefined;\n // number 가 없으면(빈 객체 등) \"undefined\" 문자열이 새는 것을 막는다.\n if (!uid || typeof uid.number !== \"number\") return null;\n return uid.prefix ? `${uid.prefix}-${uid.number}` : String(uid.number);\n }\n case \"created_by\":\n case \"last_edited_by\": {\n const user = prop[prop.type] as { name?: string; id: string } | undefined;\n return user?.name ?? user?.id ?? null;\n }\n case \"verification\": {\n const v = prop.verification as { state: string } | undefined;\n return v?.state ?? null;\n }\n default:\n return null;\n }\n }\n}\n","export interface Logger {\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n debug(message: string, ...args: unknown[]): void;\n}\n\nconst consoleLogger: Logger = {\n warn: (msg, ...args) => console.warn(msg, ...args),\n error: (msg, ...args) => console.error(msg, ...args),\n info: (msg, ...args) => console.info(msg, ...args),\n debug: () => {},\n};\n\nlet currentLogger: Logger = consoleLogger;\n\nexport function setLogger(logger: Logger): void {\n currentLogger = logger;\n}\n\nexport function getLogger(): Logger {\n return currentLogger;\n}\n","import { Client, LogLevel } from \"@notionhq/client\";\nimport { Sema } from \"async-sema\";\nimport type {\n BlockObjectResponse,\n PageObjectResponse,\n PartialBlockObjectResponse,\n PageMarkdownResponse,\n} from \"@notionhq/client/build/src/api-endpoints.js\";\nimport type {\n DataSourceViewObjectResponse,\n ListDatabaseViewsResponse,\n} from \"@notionhq/client/build/src/api-endpoints/views.js\";\nimport { PropertyMapper, type WikilinkResolver } from \"./property-mapper.js\";\nimport type { ViewConfig, DatabaseViewsConfig, PageCover, PageIcon } from \"../types/view.js\";\nimport type { Config } from \"../types/config.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { normalizeNotionId } from \"../utils/id.js\";\n\n/**\n * Notion SDK 의 404(`object_not_found`) 판별 — 링크드 DB·미공유 데이터 소스·삭제된\n * 페이지/DB 의 **권위적 신호**다. 그래야 일시적/실제 오류(검증·rate limit·5xx)와 구분해\n * 행 동기화 불가를 정직히 강등(스택트레이스 대신 1줄 + denylist)할 수 있다.\n * SDK 의 `APIResponseError` 는 `code`/`status` 를 노출한다.\n */\nexport function isNotionObjectNotFound(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n const e = error as { code?: unknown; status?: unknown };\n return e.code === \"object_not_found\" || e.status === 404;\n}\n\n/**\n * 서브트리 직접 순회(getChildPagesRecursive) 비용이 시간 예산을 초과했을 때 던지는 신호.\n * 순회 비용은 **서브트리 전체 블록 수**에 비례(중첩 페이지 무손실 탐색을 위해 모든 블록을\n * 깊이 순회)하므로, 콘텐츠가 많은 대규모 서브트리에서는 워크스페이스 search 기반 디스커버리\n * (비용이 워크스페이스 페이지 수에 비례·예측가능)가 더 저렴하다. 이 오류를 받은 호출측은\n * search 기반 폴백(getPagesUnderRootViaSearch)으로 전환한다. 작은 볼트는 예산 안에서\n * 순회가 끝나 폴백 없이 빠르게 완료된다(이중 전략의 분기점).\n */\nexport class DiscoveryTooLargeError extends Error {\n constructor(elapsedMs: number) {\n super(`subtree discovery exceeded time budget (${elapsedMs}ms)`);\n this.name = \"DiscoveryTooLargeError\";\n }\n}\n\nexport interface NotionClientOptions {\n readonly token: string;\n readonly concurrency?: number;\n readonly timeoutMs?: number;\n readonly rateLimitIntervalMs?: number;\n readonly maxRetries?: number;\n readonly retryBaseDelayMs?: number;\n readonly retryBackoffFactor?: number;\n readonly pageSize?: number;\n readonly batchSize?: number;\n readonly fetch?: typeof globalThis.fetch;\n}\n\nexport class NotionClient {\n private readonly client: Client;\n private readonly sema: Sema;\n private readonly propertyMapper = new PropertyMapper();\n\n private readonly minRequestInterval: number;\n private readonly maxRetries: number;\n private readonly retryBaseDelayMs: number;\n private readonly retryBackoffFactor: number;\n private readonly defaultPageSize: number;\n private readonly batchSize: number;\n\n constructor(options: NotionClientOptions) {\n this.client = new Client({\n auth: options.token,\n timeoutMs: options.timeoutMs ?? 30000,\n logLevel: LogLevel.ERROR,\n ...(options.fetch ? { fetch: options.fetch } : {}),\n });\n this.sema = new Sema(options.concurrency ?? 3);\n this.minRequestInterval = options.rateLimitIntervalMs ?? 350;\n this.maxRetries = options.maxRetries ?? 5;\n this.retryBaseDelayMs = options.retryBaseDelayMs ?? 1000;\n this.retryBackoffFactor = options.retryBackoffFactor ?? 2;\n this.defaultPageSize = options.pageSize ?? 100;\n this.batchSize = options.batchSize ?? 100;\n }\n\n /** config.advanced 의 운영 튜닝값으로 클라이언트를 생성한다 (매직넘버 단일 진실원). */\n static fromConfig(config: Config, fetch?: typeof globalThis.fetch): NotionClient {\n const a = config.advanced;\n return new NotionClient({\n token: config.notion.token,\n concurrency: a.concurrency,\n timeoutMs: a.timeoutMs,\n rateLimitIntervalMs: a.rateLimitIntervalMs,\n maxRetries: a.maxRetries,\n retryBaseDelayMs: a.retryBaseDelayMs,\n retryBackoffFactor: a.retryBackoffFactor,\n pageSize: a.pageSize,\n batchSize: a.batchSize,\n ...(fetch ? { fetch } : {}),\n });\n }\n\n getInternalClient(): Client {\n return this.client;\n }\n\n // ─── Page CRUD ───\n\n async getPage(pageId: string): Promise<PageObjectResponse> {\n return this.withRateLimit(\n () => this.client.pages.retrieve({ page_id: pageId }) as Promise<PageObjectResponse>,\n );\n }\n\n async createPage(params: {\n parentId: string;\n parentType: \"page\" | \"database\";\n title: string;\n properties?: Record<string, unknown>;\n children?: BlockObjectResponse[];\n }): Promise<PageObjectResponse> {\n const parent =\n params.parentType === \"database\"\n ? { database_id: params.parentId }\n : { page_id: params.parentId };\n\n const properties =\n params.parentType === \"page\"\n ? { title: { title: [{ text: { content: params.title } }] } }\n : ((params.properties as never) ?? {\n title: { title: [{ text: { content: params.title } }] },\n });\n\n return this.withRateLimit(\n () =>\n this.client.pages.create({\n parent,\n properties: properties as never,\n children: params.children as never,\n }) as Promise<PageObjectResponse>,\n );\n }\n\n async createPageWithMarkdown(params: {\n parentId: string;\n parentType: \"page\" | \"database\";\n title: string;\n markdown: string;\n properties?: Record<string, unknown>;\n }): Promise<PageObjectResponse> {\n const parent =\n params.parentType === \"database\"\n ? { database_id: params.parentId }\n : { page_id: params.parentId };\n\n const properties =\n params.parentType === \"page\"\n ? { title: { title: [{ text: { content: params.title } }] } }\n : ((params.properties as never) ?? {\n title: { title: [{ text: { content: params.title } }] },\n });\n\n return this.withRateLimit(\n () =>\n this.client.pages.create({\n parent,\n properties: properties as never,\n markdown: params.markdown,\n }) as Promise<PageObjectResponse>,\n );\n }\n\n async updatePageProperties(\n pageId: string,\n properties: Record<string, unknown>,\n ): Promise<PageObjectResponse> {\n return this.withRateLimit(\n () =>\n this.client.pages.update({\n page_id: pageId,\n properties: properties as never,\n }) as Promise<PageObjectResponse>,\n );\n }\n\n // ─── Markdown API ───\n\n async getPageMarkdown(pageId: string): Promise<PageMarkdownResponse> {\n return this.withRateLimit(() => this.client.pages.retrieveMarkdown({ page_id: pageId }));\n }\n\n async replacePageMarkdown(pageId: string, markdown: string): Promise<PageMarkdownResponse> {\n return this.withRateLimit(() =>\n this.client.pages.updateMarkdown({\n page_id: pageId,\n type: \"replace_content\",\n replace_content: {\n new_str: markdown,\n allow_deleting_content: true,\n },\n }),\n );\n }\n\n async updatePageMarkdownPartial(\n pageId: string,\n patches: Array<{ oldStr: string; newStr: string; replaceAll?: boolean }>,\n ): Promise<PageMarkdownResponse> {\n return this.withRateLimit(() =>\n this.client.pages.updateMarkdown({\n page_id: pageId,\n type: \"update_content\",\n update_content: {\n content_updates: patches.map((p) => ({\n old_str: p.oldStr,\n new_str: p.newStr,\n replace_all_matches: p.replaceAll ?? false,\n })),\n allow_deleting_content: true,\n },\n }),\n );\n }\n\n // ─── Page Move ───\n\n async movePage(\n pageId: string,\n newParentId: string,\n newParentType: \"page\" | \"database\",\n ): Promise<PageObjectResponse> {\n const parent =\n newParentType === \"database\" ? { database_id: newParentId } : { page_id: newParentId };\n return this.withRateLimit(\n () =>\n this.client.pages.update({\n page_id: pageId,\n parent,\n } as never) as Promise<PageObjectResponse>,\n );\n }\n\n // ─── Database / DataSource ───\n\n /**\n * 데이터베이스 1개를 신 모델(2025-09-03 data source 분리)로 조회한다.\n * - title: database 객체에 그대로 존재한다.\n * - properties(스키마): 신 모델에선 data source 에 있으므로 1차 data source 를 조회해 채운다.\n * data source 접근 불가(링크드 DB 등)면 database 객체의 properties 로 폴백한다(제목은 보존).\n *\n * 폐기한 레거시 raw fetch(`GET /v1/databases/{id}`, Notion-Version 2022-06-28)는 신 모델로\n * 업그레이드된 다수 DB에 400 을 반환해 자동 발견 DB 가 통째 드롭(내용 손실)되던 원인이었다.\n * SDK(`databases.retrieve`/`dataSources.retrieve`)는 동일 토큰으로 정상 동작한다.\n */\n private async fetchDatabaseModern(databaseId: string): Promise<Record<string, unknown>> {\n const db = (await this.withRateLimit(() =>\n this.client.databases.retrieve({ database_id: databaseId }),\n )) as unknown as {\n title?: unknown;\n properties?: Record<string, unknown>;\n data_sources?: Array<{ id: string; name?: string }>;\n };\n\n // 신 모델(2025-09-03): 한 database 가 2개 이상의 data source 를 가질 수 있고, 각 data\n // source 가 자체 스키마(properties)를 갖는다. 1차 data source 만 읽으면 2번째+ 의 컬럼이\n // 침묵 유실되므로 접근 가능한 전 data source 의 properties 를 union 병합한다(이름 충돌은\n // 첫 정의 우선 — 동일 컬럼이 여러 소스에 중복돼도 안정적). 어떤 data source 도 접근\n // 불가하면 database 객체의 properties 로 폴백(제목은 이미 확보).\n const dataSources = db.data_sources ?? [];\n const merged: Record<string, unknown> = {};\n let anyAccessible = false;\n for (const ds of dataSources) {\n try {\n const dsObj = (await this.withRateLimit(() =>\n this.client.dataSources.retrieve({ data_source_id: ds.id }),\n )) as unknown as { properties?: Record<string, unknown> };\n if (dsObj.properties && Object.keys(dsObj.properties).length > 0) {\n anyAccessible = true;\n for (const [name, prop] of Object.entries(dsObj.properties)) {\n if (!(name in merged)) merged[name] = prop;\n }\n }\n } catch {\n // 접근 불가 data source 건너뜀 — 나머지 소스로 계속.\n }\n }\n\n const properties: Record<string, unknown> = anyAccessible ? merged : (db.properties ?? {});\n return { title: db.title, properties };\n }\n\n async getDatabaseTitle(databaseId: string): Promise<string> {\n const db = await this.fetchDatabaseModern(databaseId);\n const titleArr = db.title as Array<{ plain_text: string }> | undefined;\n return titleArr?.[0]?.plain_text ?? \"\";\n }\n\n /**\n * 발견된 DB 가 **동기화 가능한지**(접근 가능한 data source 가 있는지) 1회 호출로 판별한다.\n * 신 모델(2025-09-03)에서 링크드 DB·미공유 데이터 소스·삭제 DB 는 `data_sources` 가\n * 비어, 행 조회(`dataSources.query`)가 404 로 실패하고 그 전에 생성된 빈 폴더/`.base` 만\n * 남긴다. 발견 단계에서 미리 걸러 **빈 폴더/.base 오염 + 매 pull 의 404 노이즈**를 차단한다.\n * 제목은 함께 반환해 호출처가 추가 조회 없이 폴더명을 잡게 한다.\n */\n async getDatabaseSyncability(databaseId: string): Promise<{ title: string; queryable: boolean }> {\n const db = (await this.withRateLimit(() =>\n this.client.databases.retrieve({ database_id: databaseId }),\n )) as unknown as {\n title?: Array<{ plain_text: string }>;\n data_sources?: Array<{ id: string }>;\n };\n const title = Array.isArray(db.title) ? (db.title[0]?.plain_text ?? \"\") : \"\";\n return { title, queryable: (db.data_sources?.length ?? 0) > 0 };\n }\n\n async getDatabaseSchema(\n databaseId: string,\n ): Promise<Record<string, { id: string; type: string }>> {\n const db = await this.fetchDatabaseModern(databaseId);\n const properties = db.properties as Record<string, { id: string; type: string }> | undefined;\n if (!properties) return {};\n const schema: Record<string, { id: string; type: string }> = {};\n for (const [name, prop] of Object.entries(properties)) {\n schema[name] = { id: prop.id, type: prop.type };\n }\n return schema;\n }\n\n async getDatabaseSchemaFull(databaseId: string): Promise<\n Record<\n string,\n {\n id: string;\n type: string;\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n }\n >\n > {\n const db = await this.fetchDatabaseModern(databaseId);\n const properties = db.properties as Record<string, Record<string, unknown>> | undefined;\n if (!properties) return {};\n\n const schema: Record<\n string,\n {\n id: string;\n type: string;\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n }\n > = {};\n\n for (const [name, prop] of Object.entries(properties)) {\n const entry: {\n id: string;\n type: string;\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n } = {\n id: prop.id as string,\n type: prop.type as string,\n };\n\n if (prop.type === \"select\" || prop.type === \"multi_select\") {\n const typeData = prop[prop.type as string] as\n | {\n options?: Array<{ name: string; color?: string }>;\n }\n | undefined;\n if (typeData?.options) {\n entry.options = typeData.options.map((o) => ({ name: o.name, color: o.color }));\n }\n }\n\n if (prop.type === \"status\") {\n const statusData = prop.status as\n | {\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; option_ids?: string[] }>;\n }\n | undefined;\n if (statusData?.options) {\n entry.options = statusData.options.map((o) => ({ name: o.name, color: o.color }));\n }\n if (statusData?.groups) {\n entry.groups = statusData.groups.map((g) => ({\n name: g.name,\n color: g.color,\n optionIds: g.option_ids,\n }));\n }\n }\n\n schema[name] = entry;\n }\n\n return schema;\n }\n\n /** 특정 data source 1개를 직접 쿼리한다(저수준). 다중 data source 순회의 빌딩블록. */\n private async queryDataSource(\n dataSourceId: string,\n options?: { startCursor?: string; pageSize?: number; filter?: unknown },\n ): Promise<{ results: PageObjectResponse[]; nextCursor: string | null }> {\n const response = await this.withRateLimit(() =>\n this.client.dataSources.query({\n data_source_id: dataSourceId,\n start_cursor: options?.startCursor,\n page_size: options?.pageSize ?? this.defaultPageSize,\n filter: options?.filter as never,\n }),\n );\n return {\n results: response.results as PageObjectResponse[],\n nextCursor: response.next_cursor,\n };\n }\n\n /**\n * database 의 1차 data source 1페이지를 쿼리한다(증분 detect 등 단일 소스 경로용).\n * 전 행을 빠짐없이 받으려면 {@link queryAllDatabasePages} 를 쓴다(전 data source 순회).\n */\n async queryDatabase(\n databaseId: string,\n options?: { startCursor?: string; pageSize?: number; filter?: unknown },\n ): Promise<{ results: PageObjectResponse[]; nextCursor: string | null }> {\n const dsId = await this.getDataSourceId(databaseId);\n return this.queryDataSource(dsId, options);\n }\n\n /**\n * database 의 **모든 data source** 행을 빠짐없이 조회한다(2025-09-03 신 모델).\n * 한 database 가 2개 이상의 data source(각자 행 집합)를 가질 수 있어, 1차 data source 만\n * 페이지네이션하면 2번째+ 의 행이 통째 침묵 유실된다. 전 data source 를 순회·페이지네이션\n * 하고 page_id 로 디듀프(소스 간 동일 페이지 방어)한 뒤 합친다. 다중 소스면 1회 경고해\n * \"소스별 탭 구분이 한 폴더로 병합\"되는 점을 비침묵으로 알린다.\n */\n async queryAllDatabasePages(databaseId: string, filter?: unknown): Promise<PageObjectResponse[]> {\n const metas = await this.getDataSourceMetas(databaseId);\n if (metas.length > 1) {\n const label = metas.map((m) => m.name || m.id).join(\", \");\n getLogger().warn(\n `[Notion] DB ${databaseId} 에 data source ${metas.length}개 발견 — 전 소스 행을 한 폴더로 병합 동기화합니다 (${label}). 소스별 탭 구분은 .base 뷰에 보존되지 않습니다.`,\n );\n }\n\n const all: PageObjectResponse[] = [];\n const seen = new Set<string>();\n for (const meta of metas) {\n let cursor: string | undefined;\n do {\n const response = await this.queryDataSource(meta.id, {\n startCursor: cursor,\n pageSize: this.defaultPageSize,\n filter,\n });\n for (const page of response.results) {\n const key = normalizeNotionId(page.id);\n if (seen.has(key)) continue;\n seen.add(key);\n all.push(page);\n }\n cursor = response.nextCursor ?? undefined;\n } while (cursor);\n }\n\n return all;\n }\n\n /** database 의 1차 data source id(없으면 databaseId 폴백). 단일 소스 경로 호환용. */\n async getDataSourceId(databaseId: string): Promise<string> {\n const metas = await this.getDataSourceMetas(databaseId);\n return metas[0]?.id ?? databaseId;\n }\n\n /**\n * database 의 전 data source 메타(id + 이름)를 반환한다. data source 가 없으면(레거시/단일)\n * databaseId 자체를 단일 소스로 폴백해 호출처가 항상 ≥1 개를 받게 한다.\n */\n async getDataSourceMetas(databaseId: string): Promise<Array<{ id: string; name: string }>> {\n const db = (await this.withRateLimit(() =>\n this.client.databases.retrieve({ database_id: databaseId }),\n )) as unknown as { data_sources?: Array<{ id: string; name?: string }> };\n const list = db.data_sources ?? [];\n if (list.length === 0) return [{ id: databaseId, name: \"\" }];\n return list.map((ds) => ({ id: ds.id, name: ds.name ?? \"\" }));\n }\n\n async archivePage(pageId: string): Promise<void> {\n await this.withRateLimit(() => this.client.pages.update({ page_id: pageId, archived: true }));\n }\n\n async getFileBlockUrl(blockId: string): Promise<string | null> {\n try {\n const block = await this.withRateLimit(() =>\n this.client.blocks.retrieve({ block_id: blockId }),\n );\n const b = block as unknown as {\n type: string;\n file?: { file?: { url: string }; external?: { url: string } };\n pdf?: { file?: { url: string }; external?: { url: string } };\n video?: { file?: { url: string }; external?: { url: string } };\n audio?: { file?: { url: string }; external?: { url: string } };\n image?: { file?: { url: string }; external?: { url: string } };\n };\n const media = b.file ?? b.pdf ?? b.video ?? b.audio ?? b.image;\n return media?.file?.url ?? media?.external?.url ?? null;\n } catch {\n return null;\n }\n }\n\n async getBlock(blockId: string): Promise<BlockObjectResponse> {\n return this.withRateLimit(() =>\n this.client.blocks.retrieve({ block_id: blockId }),\n ) as Promise<BlockObjectResponse>;\n }\n\n // ─── Block CRUD ───\n\n async listChildren(\n blockId: string,\n options?: { startCursor?: string; pageSize?: number },\n ): Promise<{\n results: (BlockObjectResponse | PartialBlockObjectResponse)[];\n nextCursor: string | null;\n }> {\n const response = await this.withRateLimit(() =>\n this.client.blocks.children.list({\n block_id: blockId,\n start_cursor: options?.startCursor,\n page_size: options?.pageSize ?? this.defaultPageSize,\n }),\n );\n return {\n results: response.results,\n nextCursor: response.next_cursor,\n };\n }\n\n async fetchAllChildren(blockId: string): Promise<BlockObjectResponse[]> {\n const blocks: BlockObjectResponse[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await this.listChildren(blockId, { startCursor: cursor });\n blocks.push(...response.results.filter((b): b is BlockObjectResponse => \"type\" in b));\n cursor = response.nextCursor ?? undefined;\n } while (cursor);\n\n return blocks;\n }\n\n private static readonly CONTAINER_BLOCK_TYPES = new Set([\n \"column_list\",\n \"column\",\n \"callout\",\n \"toggle\",\n \"quote\",\n ]);\n\n async fetchAllChildrenDeep(blockId: string): Promise<BlockObjectResponse[]> {\n const directChildren = await this.fetchAllChildren(blockId);\n const allBlocks: BlockObjectResponse[] = [...directChildren];\n\n const toExpand = directChildren.filter((b) => {\n if (!b.has_children) return false;\n if (b.type === \"child_page\" || b.type === \"child_database\") return false;\n if (NotionClient.CONTAINER_BLOCK_TYPES.has(b.type)) return true;\n if (b.type === \"synced_block\") {\n const sb = b as unknown as { synced_block: { synced_from: { block_id: string } | null } };\n return sb.synced_block?.synced_from === null;\n }\n return true;\n });\n\n for (const container of toExpand) {\n try {\n const nested = await this.fetchAllChildrenDeep(container.id);\n allBlocks.push(...nested);\n } catch {\n // 접근 권한 없는 블록 무시\n }\n }\n\n return allBlocks;\n }\n\n async appendChildren(blockId: string, children: unknown[]): Promise<void> {\n const batchSize = this.batchSize;\n for (let i = 0; i < children.length; i += batchSize) {\n const batch = children.slice(i, i + batchSize);\n await this.withRateLimit(() =>\n this.client.blocks.children.append({\n block_id: blockId,\n children: batch as never,\n }),\n );\n }\n }\n\n async deleteBlock(blockId: string): Promise<void> {\n await this.withRateLimit(() => this.client.blocks.delete({ block_id: blockId }));\n }\n\n // ─── File Upload ───\n\n async uploadFile(fileData: Blob, filename: string, contentType: string): Promise<string> {\n const upload = await this.withRateLimit(() =>\n this.client.fileUploads.create({ filename, content_type: contentType }),\n );\n\n const fileUploadId = (upload as unknown as { id: string }).id;\n\n const sendResult = await this.withRateLimit(() =>\n this.client.fileUploads.send({\n file_upload_id: fileUploadId,\n file: { data: fileData, filename },\n }),\n );\n\n const status = (sendResult as unknown as { status: string }).status;\n if (status === \"pending\") {\n await this.withRateLimit(() =>\n this.client.fileUploads.complete({ file_upload_id: fileUploadId }),\n );\n }\n\n return fileUploadId;\n }\n\n // ─── Search & Navigation ───\n\n async search(params: {\n query?: string;\n filter?: { property: \"object\"; value: \"page\" | \"data_source\" };\n startCursor?: string;\n pageSize?: number;\n }): Promise<{ results: PageObjectResponse[]; nextCursor: string | null }> {\n const response = await this.withRateLimit(() =>\n this.client.search({\n query: params.query,\n filter: params.filter,\n start_cursor: params.startCursor,\n page_size: params.pageSize ?? this.defaultPageSize,\n }),\n );\n return {\n results: response.results as PageObjectResponse[],\n nextCursor: response.next_cursor,\n };\n }\n\n async searchRecentPages(since: string): Promise<Array<{ id: string; last_edited_time: string }>> {\n const results: Array<{ id: string; last_edited_time: string }> = [];\n let cursor: string | undefined;\n const sinceDate = new Date(since);\n\n outer: do {\n const response = await this.withRateLimit(() =>\n this.client.search({\n filter: { property: \"object\", value: \"page\" },\n sort: { direction: \"descending\", timestamp: \"last_edited_time\" },\n start_cursor: cursor,\n page_size: this.defaultPageSize,\n }),\n );\n\n for (const page of response.results) {\n const p = page as PageObjectResponse;\n if (new Date(p.last_edited_time) <= sinceDate) {\n break outer;\n }\n results.push({ id: p.id, last_edited_time: p.last_edited_time });\n }\n\n cursor = response.next_cursor ?? undefined;\n } while (cursor);\n\n return results;\n }\n\n async getChildPages(parentId: string): Promise<PageObjectResponse[]> {\n const blocks = await this.fetchAllChildrenDeep(parentId);\n const childPageBlocks = blocks.filter((b) => b.type === \"child_page\");\n\n if (childPageBlocks.length === 0) return [];\n\n const pages = await Promise.all(childPageBlocks.map((b) => this.getPage(b.id)));\n // 휴지통/아카이브된 페이지 제외: 부모 블록에는 child_page 참조가 남아 있어도\n // 대상 페이지가 삭제(in_trash)·보관(archived)된 경우 블록 조회 시 object_not_found가\n // 발생하므로 동기화 대상에서 사전 제거한다. (재귀 스캔의 무한·실패 전파 차단)\n return pages.filter((p) => !NotionClient.isTrashedOrArchived(p));\n }\n\n /** 페이지가 휴지통(in_trash)이거나 보관(archived) 상태인지 판정한다. */\n private static isTrashedOrArchived(page: PageObjectResponse): boolean {\n // in_trash는 런타임 응답에는 존재하나 SDK 타입에 미선언 → 안전 캐스트로 접근\n const inTrash = (page as { in_trash?: boolean }).in_trash === true;\n return inTrash || page.archived === true;\n }\n\n async getChildDatabaseIds(parentId: string): Promise<string[]> {\n const children = await this.fetchAllChildren(parentId);\n return children.filter((b) => b.type === \"child_database\").map((b) => b.id);\n }\n\n /**\n * root 서브트리를 직접 BFS 순회해 하위 페이지를 모두 수집한다(중첩 깊이 무관·무손실).\n * 비용은 서브트리 전체 블록 수에 비례한다.\n *\n * @param opts.deadlineMs `Date.now()` 기준 마감 시각. 각 페이지 처리 전 초과를 검사해\n * 초과 시 {@link DiscoveryTooLargeError}를 던진다(대규모 서브트리 → search 폴백 유도).\n * 미지정 시 무제한(기존 동작 유지 — 테스트 mock 경로는 영향 없음).\n */\n async getChildPagesRecursive(\n parentId: string,\n opts?: { deadlineMs?: number },\n ): Promise<PageObjectResponse[]> {\n const all: PageObjectResponse[] = [];\n let currentLevel: string[] = [parentId];\n const start = Date.now();\n\n while (currentLevel.length > 0) {\n const nextLevel: string[] = [];\n\n for (const id of currentLevel) {\n if (opts?.deadlineMs !== undefined && Date.now() > opts.deadlineMs) {\n throw new DiscoveryTooLargeError(Date.now() - start);\n }\n let children: PageObjectResponse[];\n try {\n children = await this.getChildPages(id);\n } catch (error) {\n // 한 서브트리가 접근 불가(공유 해제·삭제 등)여도 전체 스캔이 중단되지 않도록\n // 해당 노드만 건너뛴다. 형제·다른 가지의 페이지 손실을 방지한다.\n getLogger().warn(\n `[Im-Nobsidian] 하위 페이지 스캔 건너뜀 (${id}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n continue;\n }\n for (const child of children) {\n all.push(child);\n nextLevel.push(child.id);\n }\n }\n\n currentLevel = nextLevel;\n }\n\n return all;\n }\n\n /** 워크스페이스에서 통합에 공유된 모든 페이지를 bulk search 로 열거한다(100/요청). */\n async searchAllPages(): Promise<PageObjectResponse[]> {\n const pages: PageObjectResponse[] = [];\n let cursor: string | undefined;\n do {\n const r = await this.search({\n filter: { property: \"object\", value: \"page\" },\n startCursor: cursor,\n });\n pages.push(...r.results);\n cursor = r.nextCursor ?? undefined;\n } while (cursor);\n return pages;\n }\n\n /**\n * root 하위 페이지를 **search 기반**으로 디스커버리한다(대규모 서브트리용 폴백).\n *\n * 전략: 워크스페이스 전체 페이지를 1회 bulk search 로 열거(비용 ∝ 워크스페이스 페이지 수,\n * 예측가능·유한)한 뒤, 각 페이지의 부모 체인을 따라 root 도달 여부를 판정한다. page_id\n * 부모는 메모리 맵으로 추가 호출 없이 즉시 해석하고, block_id 부모(컬럼·토글 등 레이아웃에\n * 중첩된 페이지)만 getBlock 으로 소유 페이지를 해석(memo)한다. search 는 중첩 깊이와 무관하게\n * 모든 페이지를 반환하므로 직접 순회와 동일하게 **무손실**이다.\n *\n * getChildPagesRecursive 와 동일 집합을 보장하기 위해:\n * - DB 행(parent=data_source_id/database_id)은 child_page 로 도달 불가 → 제외\n * - 휴지통/보관(in_trash/archived) 페이지 제외\n * - root 자신은 제외(직접 순회도 root 의 *자식*부터 수집)\n */\n async getPagesUnderRootViaSearch(rootId: string): Promise<PageObjectResponse[]> {\n const all = await this.searchAllPages();\n const rootN = normalizeNotionId(rootId);\n const byId = new Map<string, PageObjectResponse>();\n for (const p of all) byId.set(normalizeNotionId(p.id), p);\n\n type Parent = {\n type: string;\n page_id?: string;\n block_id?: string;\n data_source_id?: string;\n database_id?: string;\n };\n\n // block_id → 소유 페이지 id(없으면 null). 같은 블록 재해석을 막는 memo.\n const blockOwner = new Map<string, string | null>();\n const resolveBlockOwner = async (blockId: string): Promise<string | null> => {\n let bid = blockId;\n const seen = new Set<string>();\n for (let i = 0; i < 20 && bid && !seen.has(bid); i++) {\n seen.add(bid);\n const cached = blockOwner.get(bid);\n if (cached !== undefined) return cached;\n let bp: Parent;\n try {\n bp = ((await this.getBlock(bid)) as unknown as { parent: Parent }).parent;\n } catch {\n blockOwner.set(bid, null);\n return null;\n }\n if (bp.type === \"page_id\" && bp.page_id) {\n const owner = bp.page_id;\n blockOwner.set(blockId, owner);\n return owner;\n }\n if (bp.type === \"block_id\" && bp.block_id) {\n bid = bp.block_id;\n continue;\n }\n blockOwner.set(blockId, null);\n return null; // data_source_id/database_id/workspace → 페이지 소유자 아님\n }\n return null;\n };\n\n // pageId(normalized) → root 하위 여부. 체인 전체를 한 번에 memo 한다.\n const memo = new Map<string, boolean>();\n const isUnderRoot = async (startId: string): Promise<boolean> => {\n const chain: string[] = [];\n let cur: string | null = normalizeNotionId(startId);\n const seen = new Set<string>();\n let result = false;\n while (cur && !seen.has(cur)) {\n if (cur === rootN) {\n result = true;\n break;\n }\n const cached = memo.get(cur);\n if (cached !== undefined) {\n result = cached;\n break;\n }\n seen.add(cur);\n chain.push(cur);\n const pg = byId.get(cur);\n if (!pg) break; // 부모가 열거 집합 밖(root 위/미공유) → root 하위 아님\n const parent = pg.parent as Parent;\n if (parent.type === \"page_id\" && parent.page_id) {\n cur = normalizeNotionId(parent.page_id);\n } else if (parent.type === \"block_id\" && parent.block_id) {\n const owner = await resolveBlockOwner(parent.block_id);\n cur = owner ? normalizeNotionId(owner) : null;\n } else {\n cur = null; // workspace/data_source_id/database_id → 체인 종료\n }\n }\n for (const c of chain) memo.set(c, result);\n return result;\n };\n\n const out: PageObjectResponse[] = [];\n for (const p of all) {\n const pid = normalizeNotionId(p.id);\n if (pid === rootN) continue; // root 자신 제외\n const ptype = (p.parent as Parent).type;\n if (ptype === \"data_source_id\" || ptype === \"database_id\") continue; // DB 행 제외\n if (NotionClient.isTrashedOrArchived(p)) continue;\n if (await isUnderRoot(p.id)) out.push(p);\n }\n return out;\n }\n\n // ─── Views API ───\n\n async listDatabaseViews(databaseId: string): Promise<ViewConfig[]> {\n const allViews: ViewConfig[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await this.withRateLimit(() =>\n this.client.views.list({\n database_id: databaseId,\n start_cursor: cursor,\n page_size: this.defaultPageSize,\n }),\n );\n\n const viewRefs = (response as ListDatabaseViewsResponse).results;\n for (const ref of viewRefs) {\n try {\n const detail = await this.getView(ref.id as string);\n if (detail) allViews.push(detail);\n } catch {\n // 뷰 상세 조회 실패 시 스킵\n }\n }\n\n cursor = (response as ListDatabaseViewsResponse).next_cursor as string | undefined;\n } while (cursor);\n\n return allViews;\n }\n\n async getView(viewId: string): Promise<ViewConfig | null> {\n const view = await this.withRateLimit(() => this.client.views.retrieve({ view_id: viewId }));\n\n const v = view as DataSourceViewObjectResponse;\n if (!v.type) return null;\n\n return parseViewResponse(v);\n }\n\n async getDatabaseViewsConfig(databaseId: string): Promise<DatabaseViewsConfig> {\n const views = await this.listDatabaseViews(databaseId);\n return {\n databaseId,\n lastSynced: new Date().toISOString(),\n views,\n };\n }\n\n // ─── Cover / Icon Extraction ───\n\n extractCover(page: PageObjectResponse): PageCover | null {\n const raw = page as unknown as {\n cover?: {\n type: string;\n file?: { url: string; expiry_time?: string };\n external?: { url: string };\n };\n };\n if (!raw.cover) return null;\n\n if (raw.cover.type === \"file\" && raw.cover.file) {\n return {\n type: \"file\",\n url: raw.cover.file.url,\n expiryTime: raw.cover.file.expiry_time,\n };\n }\n if (raw.cover.type === \"external\" && raw.cover.external) {\n return { type: \"external\", url: raw.cover.external.url };\n }\n return null;\n }\n\n extractIcon(page: PageObjectResponse): PageIcon | null {\n const raw = page as unknown as {\n icon?: {\n type: string;\n emoji?: string;\n external?: { url: string };\n file?: { url: string; expiry_time?: string };\n icon?: { name: string; color?: string };\n };\n };\n if (!raw.icon) return null;\n\n switch (raw.icon.type) {\n case \"emoji\":\n return { type: \"emoji\", value: raw.icon.emoji! };\n case \"external\":\n return { type: \"external\", value: raw.icon.external!.url };\n case \"file\":\n return { type: \"file\", value: raw.icon.file!.url };\n case \"icon\":\n return { type: \"icon\", value: raw.icon.icon!.name, color: raw.icon.icon!.color };\n default:\n return null;\n }\n }\n\n // ─── Property Extraction ───\n\n extractTitle(page: PageObjectResponse): string {\n const props = page.properties as Record<\n string,\n { type: string; title?: Array<{ plain_text?: string }> }\n >;\n for (const prop of Object.values(props)) {\n // 빈 제목 행은 Notion 이 title 을 배열이 아닌 빈 객체({})로 돌려주기도 한다.\n // Array.isArray 가드 없이 .map 을 호출하면 \"title.map is not a function\" 으로\n // 그 행 전체가 pull 실패→손실되고 매 pull 마다 churn 이 남는다(멱등성 위반).\n if (prop.type === \"title\" && Array.isArray(prop.title)) {\n const joined = prop.title.map((t) => t.plain_text ?? \"\").join(\"\");\n if (joined) return joined;\n }\n }\n return \"제목 없음\";\n }\n\n /**\n * 페이지 모드 pull(extractProperties)의 relation/people 속성을 raw Notion UUID 가\n * 아니라 [[제목]] 위키링크로 해소하도록 resolver 를 주입한다. 주입하지 않으면 매\n * pull 마다 relation 이 raw UUID 로 재생성돼, 후처리(resolveNotionLinks)에만 의존하는\n * 2-write churn 이 남는다(M1). DB 모드는 orchestrator/DatabaseSyncer 의 자체 mapper 가\n * 이미 resolver 를 주입받아 면역이다.\n */\n setWikilinkResolver(resolver: WikilinkResolver): void {\n this.propertyMapper.setWikilinkResolver(resolver);\n }\n\n extractProperties(page: PageObjectResponse): Record<string, unknown> {\n return this.propertyMapper.fromNotionProperties(page.properties as Record<string, unknown>);\n }\n\n // ─── Internal ───\n\n private lastRequestTime = 0;\n\n private async withRateLimit<T>(fn: () => Promise<T>): Promise<T> {\n await this.sema.acquire();\n try {\n const now = Date.now();\n const elapsed = now - this.lastRequestTime;\n if (elapsed < this.minRequestInterval) {\n await sleep(this.minRequestInterval - elapsed);\n }\n this.lastRequestTime = Date.now();\n return await this.executeWithRetry(fn);\n } finally {\n this.sema.release();\n }\n }\n\n private async executeWithRetry<T>(fn: () => Promise<T>, attempt: number = 0): Promise<T> {\n try {\n return await fn();\n } catch (error: unknown) {\n if (isRetryable(error) && attempt < this.maxRetries) {\n const baseDelay =\n extractRetryAfter(error) ??\n this.retryBaseDelayMs * Math.pow(this.retryBackoffFactor, attempt);\n const jitter = baseDelay * (0.5 + Math.random() * 0.5);\n await sleep(jitter);\n return this.executeWithRetry(fn, attempt + 1);\n }\n throw error;\n }\n }\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n const code = (error as { code?: string }).code;\n if (code === \"notionhq_client_request_timeout\" || code === \"ECONNRESET\" || code === \"ETIMEDOUT\") {\n return true;\n }\n if (!(\"status\" in error)) return false;\n const status = (error as { status: number }).status;\n return status === 429 || status === 502 || status === 503 || status === 504;\n}\n\nfunction extractRetryAfter(error: unknown): number | null {\n if (typeof error === \"object\" && error !== null && \"headers\" in error) {\n const headers = (error as { headers: Record<string, string> }).headers;\n const retryAfter = headers?.[\"retry-after\"];\n if (retryAfter) return Number(retryAfter) * 1000;\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction parseViewResponse(v: DataSourceViewObjectResponse): ViewConfig {\n const config: ViewConfig = {\n id: v.id as string,\n name: v.name,\n type: v.type,\n dataSourceId: v.data_source_id,\n filter: v.filter,\n sorts: v.sorts?.map((s) => {\n if (\"property\" in s) {\n return { property: s.property, direction: s.direction };\n }\n return { timestamp: s.timestamp, direction: s.direction };\n }),\n ...extractViewTypeConfig(v.configuration),\n };\n return config;\n}\n\ntype MutableViewConfig = {\n -readonly [K in keyof ViewConfig]: ViewConfig[K];\n};\n\nfunction extractViewTypeConfig(\n cfg: DataSourceViewObjectResponse[\"configuration\"],\n): Partial<MutableViewConfig> {\n if (!cfg) return {};\n\n const result: Partial<MutableViewConfig> = {};\n\n if (\"properties\" in cfg && cfg.properties) {\n result.properties = cfg.properties.map((p) => ({\n propertyId: p.property_id,\n propertyName: p.property_name,\n visible: p.visible,\n width: p.width,\n wrap: p.wrap,\n }));\n }\n\n if (\"group_by\" in cfg && cfg.group_by) {\n const gb = cfg.group_by;\n result.groupBy = {\n type: gb.type,\n propertyId: gb.property_id,\n propertyName: \"property_name\" in gb ? (gb.property_name as string) : undefined,\n sort:\n \"sort\" in gb && gb.sort\n ? ((gb.sort as { type: string }).type as \"manual\" | \"ascending\" | \"descending\")\n : undefined,\n hideEmptyGroups: \"hide_empty_groups\" in gb ? (gb.hide_empty_groups as boolean) : undefined,\n };\n }\n\n if (\"cover\" in cfg && cfg.cover) {\n result.cover = {\n type: cfg.cover.type,\n propertyId: cfg.cover.property_id,\n };\n }\n\n if (\"cover_size\" in cfg) result.coverSize = cfg.cover_size;\n if (\"cover_aspect\" in cfg) result.coverAspect = cfg.cover_aspect;\n\n if (\"date_property_id\" in cfg) {\n result.datePropertyId = cfg.date_property_id;\n result.datePropertyName = cfg.date_property_name;\n }\n\n if (\"view_range\" in cfg) result.viewRange = cfg.view_range;\n\n return result;\n}\n","const VALID_COLORS = new Set([\n \"default\",\n \"gray\",\n \"brown\",\n \"orange\",\n \"yellow\",\n \"green\",\n \"blue\",\n \"purple\",\n \"pink\",\n \"red\",\n \"gray_background\",\n \"brown_background\",\n \"orange_background\",\n \"yellow_background\",\n \"green_background\",\n \"blue_background\",\n \"purple_background\",\n \"pink_background\",\n \"red_background\",\n]);\n\ntype NotionColor = string;\n\nfunction safeColor(color: string): NotionColor {\n return VALID_COLORS.has(color) ? color : \"default\";\n}\n\nexport interface RichTextSegment {\n content: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n code?: boolean;\n color?: string;\n link?: string;\n}\n\nexport interface NotionRichText {\n type: \"text\";\n text: { content: string; link?: { url: string } | null };\n annotations: {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n code: boolean;\n color: string;\n };\n}\n\nexport interface NotionEquationRichText {\n type: \"equation\";\n equation: { expression: string };\n}\n\nexport interface NotionMentionRichText {\n type: \"mention\";\n mention:\n | { type: \"page\"; page: { id: string } }\n | { type: \"date\"; date: { start: string; end?: string } }\n | { type: \"user\"; user: { id: string } }\n | { type: \"database\"; database: { id: string } };\n}\n\nexport type RichTextItem = NotionRichText | NotionEquationRichText | NotionMentionRichText;\n\nexport interface NotionBlock {\n object?: \"block\";\n type: string;\n [key: string]: unknown;\n}\n\nexport class NotionBlockBuilder {\n // ─── Rich Text ──────────────────────────────────────────\n\n static richText(content: string, options?: Partial<RichTextSegment>): NotionRichText[] {\n const textObj: { content: string; link?: { url: string } | null } = { content };\n if (options?.link) {\n textObj.link = { url: options.link };\n }\n return [\n {\n type: \"text\",\n text: textObj,\n annotations: {\n bold: options?.bold ?? false,\n italic: options?.italic ?? false,\n underline: options?.underline ?? false,\n strikethrough: options?.strikethrough ?? false,\n code: options?.code ?? false,\n color: safeColor(options?.color ?? \"default\"),\n },\n },\n ];\n }\n\n static richTextArray(segments: RichTextSegment[]): NotionRichText[] {\n return segments.map((seg) => {\n const textObj: { content: string; link?: { url: string } | null } = {\n content: seg.content,\n };\n if (seg.link) {\n textObj.link = { url: seg.link };\n }\n return {\n type: \"text\" as const,\n text: textObj,\n annotations: {\n bold: seg.bold ?? false,\n italic: seg.italic ?? false,\n underline: seg.underline ?? false,\n strikethrough: seg.strikethrough ?? false,\n code: seg.code ?? false,\n color: safeColor(seg.color ?? \"default\"),\n },\n };\n });\n }\n\n static richTextEquation(expression: string): NotionEquationRichText[] {\n return [{ type: \"equation\", equation: { expression } }];\n }\n\n static richTextMentionPage(pageId: string): NotionMentionRichText[] {\n return [{ type: \"mention\", mention: { type: \"page\", page: { id: pageId } } }];\n }\n\n static richTextMentionDate(start: string, end?: string): NotionMentionRichText[] {\n const date: { start: string; end?: string } = { start };\n if (end) date.end = end;\n return [{ type: \"mention\", mention: { type: \"date\", date } }];\n }\n\n // ─── Basic Blocks ───────────────────────────────────────\n\n static paragraph(richText: RichTextItem[], color?: string): NotionBlock {\n return {\n object: \"block\",\n type: \"paragraph\",\n paragraph: { rich_text: richText, color: safeColor(color ?? \"default\") },\n };\n }\n\n static heading(\n level: 1 | 2 | 3,\n richText: RichTextItem[],\n options?: { color?: string; isToggleable?: boolean; children?: NotionBlock[] },\n ): NotionBlock {\n const key = `heading_${level}`;\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(options?.color ?? \"default\"),\n is_toggleable: options?.isToggleable ?? false,\n };\n if (options?.isToggleable && options?.children) {\n data.children = options.children;\n }\n return { object: \"block\", type: key, [key]: data };\n }\n\n static callout(\n richText: RichTextItem[],\n icon?: string,\n options?: { color?: string; children?: NotionBlock[] },\n ): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n icon: { type: \"emoji\", emoji: icon ?? \"\\u{1F4CC}\" },\n color: safeColor(options?.color ?? \"default\"),\n };\n if (options?.children) {\n data.children = options.children;\n }\n return { object: \"block\", type: \"callout\", callout: data };\n }\n\n static toggle(richText: RichTextItem[], children?: NotionBlock[], color?: string): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return { object: \"block\", type: \"toggle\", toggle: data };\n }\n\n static bulletedListItem(\n richText: RichTextItem[],\n children?: NotionBlock[],\n color?: string,\n ): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return {\n object: \"block\",\n type: \"bulleted_list_item\",\n bulleted_list_item: data,\n };\n }\n\n static numberedListItem(\n richText: RichTextItem[],\n children?: NotionBlock[],\n color?: string,\n ): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return {\n object: \"block\",\n type: \"numbered_list_item\",\n numbered_list_item: data,\n };\n }\n\n static toDo(richText: RichTextItem[], checked?: boolean, color?: string): NotionBlock {\n return {\n object: \"block\",\n type: \"to_do\",\n to_do: {\n rich_text: richText,\n checked: checked ?? false,\n color: safeColor(color ?? \"default\"),\n },\n };\n }\n\n static quote(richText: RichTextItem[], children?: NotionBlock[], color?: string): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return { object: \"block\", type: \"quote\", quote: data };\n }\n\n static divider(): NotionBlock {\n return { object: \"block\", type: \"divider\", divider: {} };\n }\n\n static code(code: string, language?: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: NotionBlockBuilder.richText(code),\n language: language ?? \"plain text\",\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"code\", code: data };\n }\n\n static equationBlock(expression: string): NotionBlock {\n return {\n object: \"block\",\n type: \"equation\",\n equation: { expression },\n };\n }\n\n // ─── Media Blocks ───────────────────────────────────────\n\n static image(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"image\", image: data };\n }\n\n static bookmark(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = { url };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"bookmark\", bookmark: data };\n }\n\n static video(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"video\", video: data };\n }\n\n static audio(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"audio\", audio: data };\n }\n\n static fileBlock(url: string, name?: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (name) data.name = name;\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"file\", file: data };\n }\n\n static pdf(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"pdf\", pdf: data };\n }\n\n static embed(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = { url };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"embed\", embed: data };\n }\n\n // ─── Advanced Blocks ────────────────────────────────────\n\n static tableOfContents(color?: string): NotionBlock {\n return {\n object: \"block\",\n type: \"table_of_contents\",\n table_of_contents: { color: safeColor(color ?? \"default\") },\n };\n }\n\n static breadcrumb(): NotionBlock {\n return { object: \"block\", type: \"breadcrumb\", breadcrumb: {} };\n }\n\n static columnList(columns: NotionBlock[][]): NotionBlock {\n const children = columns.map((colBlocks) => ({\n object: \"block\" as const,\n type: \"column\" as const,\n column: { children: colBlocks },\n }));\n return {\n object: \"block\",\n type: \"column_list\",\n column_list: { children },\n };\n }\n\n static syncedBlockOriginal(children: NotionBlock[]): NotionBlock {\n return {\n object: \"block\",\n type: \"synced_block\",\n synced_block: { synced_from: null, children },\n };\n }\n\n static syncedBlockDuplicate(originalBlockId: string): NotionBlock {\n return {\n object: \"block\",\n type: \"synced_block\",\n synced_block: { synced_from: { block_id: originalBlockId } },\n };\n }\n\n static linkToPage(pageId: string): NotionBlock {\n return {\n object: \"block\",\n type: \"link_to_page\",\n link_to_page: { type: \"page_id\", page_id: pageId },\n };\n }\n\n static table(rows: string[][], hasColumnHeader?: boolean, hasRowHeader?: boolean): NotionBlock {\n if (rows.length === 0) rows = [[\"\", \"\"]];\n const width = rows[0]!.length;\n const tableRows = rows.map((row) => {\n const cells = row.map((cell) => NotionBlockBuilder.richText(cell));\n while (cells.length < width) {\n cells.push(NotionBlockBuilder.richText(\"\"));\n }\n return {\n object: \"block\" as const,\n type: \"table_row\" as const,\n table_row: { cells },\n };\n });\n return {\n object: \"block\",\n type: \"table\",\n table: {\n table_width: width,\n has_column_header: hasColumnHeader ?? true,\n has_row_header: hasRowHeader ?? false,\n children: tableRows,\n },\n };\n }\n}\n","import { createHash } from \"node:crypto\";\n\nexport function computeHash(content: string): string {\n return createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n}\n\nexport function computeBufferHash(buffer: Buffer): string {\n return createHash(\"sha256\").update(buffer).digest(\"hex\");\n}\n","import type { LocalChange } from \"../types/sync.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { FileStatInfo } from \"./vault-fs.js\";\nimport { computeHash } from \"../utils/hash.js\";\n\nexport interface FileInfo {\n readonly path: string;\n readonly content: string;\n readonly mtime: string;\n}\n\nexport class ChangeDetector {\n constructor(private readonly stateDb: IStateDB) {}\n\n async detectLocalChangesFast(\n stats: FileStatInfo[],\n readFile: (path: string) => Promise<string>,\n ): Promise<LocalChange[]> {\n const changes: LocalChange[] = [];\n const existingPaths = new Set<string>();\n\n for (const file of stats) {\n existingPaths.add(file.path);\n const record = this.stateDb.getByPath(file.path);\n\n if (!record) {\n const content = await readFile(file.path);\n changes.push({\n path: file.path,\n type: \"created\",\n currentHash: computeHash(content),\n previousHash: null,\n });\n continue;\n }\n\n if (record.localMtime === file.mtime && record.localFileSize === file.size) {\n continue;\n }\n\n const content = await readFile(file.path);\n const currentHash = computeHash(content);\n if (record.contentHash !== currentHash) {\n changes.push({\n path: file.path,\n type: \"modified\",\n currentHash,\n previousHash: record.contentHash,\n });\n }\n }\n\n const syncedRecords = this.stateDb.getByStatus(\"synced\");\n for (const record of syncedRecords) {\n if (!existingPaths.has(record.obsidianPath)) {\n if (record.fileType === \"folder-note\" || record.fileType === \"folder-only\") {\n if (!record.obsidianPath.endsWith(\".md\")) continue;\n }\n changes.push({\n path: record.obsidianPath,\n type: \"deleted\",\n currentHash: \"\",\n previousHash: record.contentHash,\n });\n }\n }\n\n return this.detectMoves(changes);\n }\n\n detectLocalChanges(currentFiles: FileInfo[]): LocalChange[] {\n const changes: LocalChange[] = [];\n const existingPaths = new Set<string>();\n\n for (const file of currentFiles) {\n existingPaths.add(file.path);\n const record = this.stateDb.getByPath(file.path);\n\n if (!record) {\n changes.push({\n path: file.path,\n type: \"created\",\n currentHash: computeHash(file.content),\n previousHash: null,\n });\n continue;\n }\n\n if (record.localMtime && record.localMtime === file.mtime) {\n continue;\n }\n\n const currentHash = computeHash(file.content);\n if (record.contentHash !== currentHash) {\n changes.push({\n path: file.path,\n type: \"modified\",\n currentHash,\n previousHash: record.contentHash,\n });\n }\n }\n\n const syncedRecords = this.stateDb.getByStatus(\"synced\");\n for (const record of syncedRecords) {\n if (!existingPaths.has(record.obsidianPath)) {\n if (record.fileType === \"folder-note\" || record.fileType === \"folder-only\") {\n if (!record.obsidianPath.endsWith(\".md\")) continue;\n }\n changes.push({\n path: record.obsidianPath,\n type: \"deleted\",\n currentHash: \"\",\n previousHash: record.contentHash,\n });\n }\n }\n\n return this.detectMoves(changes);\n }\n\n private detectMoves(changes: LocalChange[]): LocalChange[] {\n const result: LocalChange[] = [];\n const created = changes.filter((c) => c.type === \"created\");\n const deleted = changes.filter((c) => c.type === \"deleted\");\n const others = changes.filter((c) => c.type !== \"created\" && c.type !== \"deleted\");\n\n const matchedCreated = new Set<string>();\n const matchedDeleted = new Set<string>();\n\n for (const del of deleted) {\n const match = created.find(\n (c) => c.currentHash === del.previousHash && !matchedCreated.has(c.path),\n );\n if (match) {\n matchedCreated.add(match.path);\n matchedDeleted.add(del.path);\n result.push({\n path: match.path,\n type: \"moved\",\n currentHash: match.currentHash,\n previousHash: del.previousHash,\n movedFrom: del.path,\n });\n }\n }\n\n for (const c of created) {\n if (!matchedCreated.has(c.path)) result.push(c);\n }\n for (const d of deleted) {\n if (!matchedDeleted.has(d.path)) result.push(d);\n }\n result.push(...others);\n\n return result;\n }\n}\n","/**\n * 보존 마커(preserve marker) 단일 진실원(SSOT).\n *\n * 변환 불가 요소를 라운드트립 보존하기 위해 본문에 삽입하는 마커가 공유하는\n * 브랜드 토큰을 한곳에서 정의한다. 리브랜딩 시 {@link MARKER_BRAND}만 바꾸면\n * 모든 빌더·정규식에 반영된다.\n *\n * 주의: 마커 포맷(공백 유무)은 기존 vault·Notion에 이미 기록된 데이터와의 호환을\n * 위해 변경하지 않는다. 두 포맷이 공존한다 — 공백형(`%% brand:... %%`)과\n * 압축형(`%%brand:...%%`).\n */\n\n/** 모든 보존 마커가 공유하는 브랜드 토큰. */\nexport const MARKER_BRAND = \"im-nobsidian\";\n\n// ─── 의사 프로토콜 (링크 보존) ───\n\n/** 위키링크 보존용 의사 프로토콜 prefix: `im-nobsidian://wikilink/`. */\nexport const WIKILINK_PROTOCOL = `${MARKER_BRAND}://wikilink/`;\n\n/** 임베드 보존용 의사 프로토콜 prefix: `im-nobsidian://embed/`. */\nexport const EMBED_PROTOCOL = `${MARKER_BRAND}://embed/`;\n\n// ─── 공백형 마커 `%% im-nobsidian:BODY %%` ───\n\n/** 공백형 HTML 주석 마커 생성: `%% im-nobsidian:BODY %%`. */\nexport function spacedMarker(body: string): string {\n return `%% ${MARKER_BRAND}:${body} %%`;\n}\n\n/** 공백형 마커 종료 토큰: `%% im-nobsidian:end %%`. */\nexport const SPACED_END = spacedMarker(\"end\");\n\n// ─── 압축형 마커 `%%im-nobsidian:BODY%%` ───\n\n/** 압축형 마커 생성: `%%im-nobsidian:BODY%%`. */\nexport function compactMarker(body: string): string {\n return `%%${MARKER_BRAND}:${body}%%`;\n}\n\n/** 토글 블록 보존 마커 (enhanced-md-converter / block-converter 공유). */\nexport const TOGGLE_START = compactMarker(\"toggle:start\");\nexport const TOGGLE_END = compactMarker(\"toggle:end\");\n\n/** 컬럼 레이아웃 보존 마커 (block-converter). */\nexport const COLUMN_LIST_START = compactMarker(\"column-list:start\");\nexport const COLUMN_LIST_END = compactMarker(\"column-list:end\");\nexport const COLUMN_SEP = compactMarker(\"column\");\n\n/** 목차(table of contents) 블록 보존 마커. */\nexport const TOC_MARKER = compactMarker(\"toc\");\n\n/**\n * breadcrumb 블록 보존 마커. Notion breadcrumb 은 마크다운 표현이 없어 pull 시\n * 빈 문자열로 소실됐다 — 이 마커로 자리를 남겨 push 시 breadcrumb 블록으로 복원한다.\n */\nexport const BREADCRUMB_MARKER = compactMarker(\"breadcrumb\");\n\n/** YAML 프로퍼티 테이블 보존 태그 (yaml 코드블록 내 주석): `# im-nobsidian:properties`. */\nexport const PROPERTIES_TAG = `# ${MARKER_BRAND}:properties`;\n\n// ─── 정규식 헬퍼 ───\n\n/**\n * 정규식 패턴에 직접 삽입할 수 있는 브랜드 토큰.\n * 브랜드에 정규식 특수문자가 없어(하이픈은 문자클래스 밖에서 리터럴) 이스케이프 없이 사용 가능.\n * 사용 예: `new RegExp(`%% ${MARKER_BRAND_RE}:end %%`, \"g\")`\n */\nexport const MARKER_BRAND_RE = MARKER_BRAND;\n","import type {\n ConversionContext,\n ConversionPath,\n ConversionResult,\n Processor,\n ProcessorInput,\n ProcessorMetadata,\n} from \"../types/convert.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { MARKER_BRAND_RE } from \"../constants/markers.js\";\n\nconst INLINE_DB_PROBE = new RegExp(`%% ${MARKER_BRAND_RE}:inline-db`);\nconst TOGGLE_HEADING_PROBE = new RegExp(`%% ${MARKER_BRAND_RE}:toggle-heading`);\n\nexport class ConversionPipeline {\n private readonly preProcessors: Processor[] = [];\n private readonly postProcessors: Processor[] = [];\n\n registerPreProcessor(processor: Processor): void {\n this.preProcessors.push(processor);\n this.preProcessors.sort((a, b) => a.order - b.order);\n }\n\n registerPostProcessor(processor: Processor): void {\n this.postProcessors.push(processor);\n this.postProcessors.sort((a, b) => a.order - b.order);\n }\n\n selectPath(content: string): ConversionPath {\n const hasInlineDb = INLINE_DB_PROBE.test(content);\n const hasColumnLayout = />\\s*\\[!col\\]/.test(content);\n const hasToggleHeading = TOGGLE_HEADING_PROBE.test(content);\n\n if (hasInlineDb || hasColumnLayout || hasToggleHeading) {\n return \"block-api\";\n }\n\n return \"markdown-api\";\n }\n\n convertToNotion(markdown: string, context: ConversionContext): ConversionResult {\n let input: ProcessorInput = {\n content: markdown,\n metadata: {},\n context,\n };\n\n for (const processor of this.preProcessors) {\n try {\n const output = processor.process(input);\n input = {\n content: output.content,\n metadata: output.metadata,\n context,\n };\n } catch (error) {\n getLogger().warn(`[${processor.name}] Pre-processor failed:`, error);\n }\n }\n\n return {\n content: input.content,\n properties: (input.metadata.properties as Record<string, unknown>) ?? {},\n images: input.metadata.images ?? [],\n preserveMarkers: input.metadata.preserveMarkers ?? [],\n };\n }\n\n convertToMarkdown(\n content: string,\n context: ConversionContext,\n metadata?: ProcessorMetadata,\n ): string {\n let input: ProcessorInput = {\n content,\n metadata: metadata ?? {},\n context,\n };\n\n for (const processor of this.postProcessors) {\n try {\n const output = processor.process(input);\n input = {\n content: output.content,\n metadata: output.metadata,\n context,\n };\n } catch (error) {\n getLogger().warn(`[${processor.name}] Post-processor failed:`, error);\n }\n }\n\n return input.content;\n }\n}\n","import matter from \"gray-matter\";\nimport type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\n\nexport class FrontmatterExtractor implements Processor {\n readonly name = \"FrontmatterExtractor\";\n readonly order = 10;\n\n process(input: ProcessorInput): ProcessorOutput {\n const { data, content } = matter(input.content);\n\n return {\n content: content.trim(),\n metadata: {\n ...input.metadata,\n properties: data,\n },\n };\n }\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n WikilinkEntry,\n PreserveMarker,\n} from \"../../types/convert.js\";\nimport { WIKILINK_PROTOCOL } from \"../../constants/markers.js\";\n\nconst WIKILINK_REGEX = /(?<!!)\\[\\[([^\\]|]+)(?:\\|([^\\]]+))?\\]\\]/g;\n\nexport type WikilinkResolverFn = (text: string) => WikilinkEntry | null;\n\nexport class WikilinkResolver implements Processor {\n readonly name = \"WikilinkResolver\";\n readonly order = 20;\n\n constructor(private readonly resolve?: WikilinkResolverFn) {}\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const preserveMarkers: PreserveMarker[] = input.metadata.preserveMarkers\n ? [...input.metadata.preserveMarkers]\n : [];\n\n const resolved = input.content.replace(\n WIKILINK_REGEX,\n (_match, target: string, display?: string) => {\n const label = display ?? target;\n\n if (this.resolve) {\n const entry = this.resolve(target);\n if (entry) {\n return `<mention-page id=\"${entry.notionPageId}\">${label}</mention-page>`;\n }\n }\n\n preserveMarkers.push({\n type: \"wikilink\",\n params: display ? { text: target, display } : { text: target },\n startIndex: 0,\n });\n\n const encodedTarget = encodeURIComponent(target);\n return `[${label}](${WIKILINK_PROTOCOL}${encodedTarget})`;\n },\n );\n\n return {\n content: resolved,\n metadata: { ...input.metadata, preserveMarkers },\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { spacedMarker } from \"../../constants/markers.js\";\n\nconst CALLOUT_REGEX = /^> \\[!(\\w+)\\]([+-])?\\s*(.*)?$/gm;\n\nconst CALLOUT_EMOJI_MAP: Record<string, string> = {\n note: \"\\u{1F4DD}\",\n abstract: \"\\u{1F4CB}\",\n summary: \"\\u{1F4CB}\",\n info: \"\\u{2139}\\u{FE0F}\",\n tip: \"\\u{1F4A1}\",\n hint: \"\\u{1F4A1}\",\n success: \"\\u{2705}\",\n check: \"\\u{2705}\",\n question: \"\\u{2753}\",\n faq: \"\\u{2753}\",\n warning: \"\\u{26A0}\\u{FE0F}\",\n caution: \"\\u{26A0}\\u{FE0F}\",\n failure: \"\\u{274C}\",\n fail: \"\\u{274C}\",\n danger: \"\\u{1F525}\",\n error: \"\\u{1F525}\",\n bug: \"\\u{1F41B}\",\n example: \"\\u{1F4CC}\",\n quote: \"\\u{1F4AC}\",\n cite: \"\\u{1F4AC}\",\n};\n\nexport class CalloutTransformer implements Processor {\n readonly name = \"CalloutTransformer\";\n readonly order = 30;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.path === \"markdown-api\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content.replace(\n CALLOUT_REGEX,\n (_match, type: string, foldable: string | undefined, title: string | undefined) => {\n const emoji = CALLOUT_EMOJI_MAP[type.toLowerCase()] ?? \"\\u{1F4DD}\";\n const titleText = title?.trim() || type;\n const foldMeta = foldable\n ? `\\n${spacedMarker(`callout:type=${type}&foldable=${foldable === \"+\" ? \"open\" : \"closed\"}`)}`\n : `\\n${spacedMarker(`callout:type=${type}`)}`;\n\n return `> ${emoji} **${titleText}**${foldMeta}`;\n },\n );\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\n\nconst BLOCK_MATH_REGEX = /\\$\\$([\\s\\S]+?)\\$\\$/g;\nconst INLINE_MATH_REGEX = /(?<![\\\\$])\\$([^\\n$]+?)\\$(?!\\$)/g;\n\nexport class MathNormalizer implements Processor {\n readonly name = \"MathNormalizer\";\n readonly order = 50;\n\n process(input: ProcessorInput): ProcessorOutput {\n let content = input.content;\n\n content = content.replace(BLOCK_MATH_REGEX, (_match, equation: string) => {\n return `$$\\n${equation.trim()}\\n$$`;\n });\n\n content = content.replace(INLINE_MATH_REGEX, (_match, equation: string) => {\n return `$${equation.trim()}$`;\n });\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport type { ImageReference } from \"../../types/convert.js\";\nimport { EMBED_PROTOCOL, spacedMarker } from \"../../constants/markers.js\";\n\nconst OBSIDIAN_EMBED_REGEX = /!\\[\\[([^\\]]+)\\]\\]/g;\nconst MARKDOWN_IMAGE_REGEX = /!\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n\nconst VIDEO_HOSTS = [\"youtube.com\", \"youtu.be\", \"vimeo.com\"];\n\nexport class EmbedResolver implements Processor {\n readonly name = \"EmbedResolver\";\n readonly order = 60;\n\n process(input: ProcessorInput): ProcessorOutput {\n const images: ImageReference[] = input.metadata.images ? [...input.metadata.images] : [];\n const isPush = input.context.direction === \"push\";\n\n let content = input.content.replace(OBSIDIAN_EMBED_REGEX, (_match, target: string) => {\n if (isImageFile(target)) {\n images.push({ url: target, localPath: target, isExternal: false });\n if (isPush && !isExternalUrl(target)) {\n const fileName = target.split(\"/\").pop() ?? target;\n return `> 📎 ${fileName}\\n> ${spacedMarker(`local-image:${target}`)}`;\n }\n return `![${target}](${encodeURI(target)})`;\n }\n const encoded = encodeURIComponent(target);\n return `[${target}](${EMBED_PROTOCOL}${encoded})`;\n });\n\n content = content.replace(MARKDOWN_IMAGE_REGEX, (_match, alt: string, url: string) => {\n if (isVideoUrl(url)) {\n return `${spacedMarker(`embed:type=video&url=${encodeURIComponent(url)}`)}\\n[${alt || \"Video\"}](${url})`;\n }\n if (isExternalUrl(url)) {\n images.push({ url, isExternal: true });\n }\n return `![${alt}](${url})`;\n });\n\n return {\n content,\n metadata: { ...input.metadata, images },\n };\n }\n}\n\nfunction isImageFile(path: string): boolean {\n return /\\.(png|jpg|jpeg|gif|svg|webp|bmp|ico)$/i.test(path);\n}\n\nfunction isVideoUrl(url: string): boolean {\n return VIDEO_HOSTS.some((host) => url.includes(host));\n}\n\nfunction isExternalUrl(url: string): boolean {\n return url.startsWith(\"http://\") || url.startsWith(\"https://\");\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport type { PreserveMarker } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst MARKER_REGEX = new RegExp(`%% ${MARKER_BRAND_RE}:(\\\\w[\\\\w-]*):([^\\\\s]+?) %%`, \"g\");\n\nexport class PreserveMarkerCollector implements Processor {\n readonly name = \"PreserveMarkerCollector\";\n readonly order = 70;\n\n process(input: ProcessorInput): ProcessorOutput {\n const markers: PreserveMarker[] = input.metadata.preserveMarkers\n ? [...input.metadata.preserveMarkers]\n : [];\n\n const matches = [...input.content.matchAll(MARKER_REGEX)];\n for (const match of matches) {\n markers.push({\n type: match[1]!,\n params: parseMarkerParams(match[2]!),\n startIndex: match.index!,\n });\n }\n\n return {\n content: input.content,\n metadata: { ...input.metadata, preserveMarkers: markers },\n };\n }\n}\n\nfunction parseMarkerParams(paramString: string): Record<string, string> {\n const params: Record<string, string> = {};\n for (const pair of paramString.split(\"&\")) {\n const eqIdx = pair.indexOf(\"=\");\n if (eqIdx > 0) {\n params[pair.slice(0, eqIdx)] = decodeURIComponent(pair.slice(eqIdx + 1));\n }\n }\n return params;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\n\nconst UNSUPPORTED_CALLOUT_REGEX = /> \\[!im-nobsidian-unsupported\\][^\\n]*\\n(?:>[^\\n]*\\n)*/g;\n\nexport class UnsupportedBlockStripper implements Processor {\n readonly name = \"UnsupportedBlockStripper\";\n readonly order = 5;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content.replace(UNSUPPORTED_CALLOUT_REGEX, \"\");\n\n return {\n content: content.replace(/\\n{3,}/g, \"\\n\\n\"),\n metadata: input.metadata,\n };\n }\n}\n","import matter from \"gray-matter\";\n\n/**\n * gray-matter 의 `matter.stringify(file, data)` 는 `file` 이 **문자열**이면 내부에서\n * `matter(file)` 로 본문을 먼저 파싱한다. 본문이 `---` 로 시작하면(Notion divider,\n * 수평선, `---` 로 여는 구획 등) 그 `---…---` 블록을 frontmatter 로 오인해 YAML 로\n * 파싱하다 throw 하고, 결과적으로 frontmatter 생성이 통째로 스킵되어 **속성이 유실**된다.\n *\n * 객체 형태(`{ content }`)로 넘기면 이 재파싱을 건너뛰므로 본문이 무엇으로 시작하든\n * 안전하다. 모든 frontmatter 직렬화는 반드시 이 함수를 거쳐 footgun 을 한 곳에 봉인한다.\n */\nexport function stringifyFrontmatter(content: string, data: Record<string, unknown>): string {\n return matter.stringify({ content } as unknown as Parameters<typeof matter.stringify>[0], data);\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { PROPERTIES_TAG } from \"../../constants/markers.js\";\nimport { stringifyFrontmatter } from \"../../utils/frontmatter.js\";\n\nexport class PropertiesTableInjector implements Processor {\n readonly name = \"PropertiesTableInjector\";\n readonly order = 15;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n if (input.context.parentMode === \"database\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const properties = input.metadata.properties as Record<string, unknown> | undefined;\n if (!properties || Object.keys(properties).length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n const filteredProps: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(properties)) {\n filteredProps[key] = value;\n }\n\n if (Object.keys(filteredProps).length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n const yamlStr = stringifyFrontmatter(\"\", filteredProps).trim();\n const yamlBody = yamlStr.slice(4, -3).trim();\n const codeBlock = \"```yaml\\n\" + PROPERTIES_TAG + \"\\n\" + yamlBody + \"\\n```\";\n\n const content = codeBlock + \"\\n\\n---\\n\\n\" + input.content;\n\n return { content, metadata: input.metadata };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE, compactMarker } from \"../../constants/markers.js\";\n\n/** `<u>밑줄</u>` (Obsidian·HTML 관용) — push 시 underline 마커로 승격. */\nconst UNDERLINE_REGEX = /<u>([\\s\\S]*?)<\\/u>/g;\n\n/**\n * 색상 span(`<span class=\"notion-red\">` / `notion-yellow-bg`) — pull(notion-to-md) 경로가 만든\n * 레거시 표현. 1번 그룹=베이스 색, 2번 그룹=배경(`-bg`) 여부.\n */\nconst COLOR_SPAN_REGEX = /<span class=\"notion-(\\w+)(-bg)?\">([\\s\\S]*?)<\\/span>/g;\n\n/** 공백형 색상 보존마커 `%% im-nobsidian:color:X %%...%% im-nobsidian:end %%` (block 경로 산출물). */\nconst SPACED_COLOR_REGEX = new RegExp(\n `%% ${MARKER_BRAND_RE}:color:(\\\\w+(?:_background)?) %%([\\\\s\\\\S]*?)%% ${MARKER_BRAND_RE}:end %%`,\n \"g\",\n);\n\n/**\n * 인라인 annotation(underline·color) 무손실 보존기 — push 전처리(order 5).\n *\n * 과거에는 underline/color 표기를 **제거**(strip)했으나, 그러면 Notion 으로 push 할 때\n * 서식이 영구 소실됐다(I3 손실점). Notion 의 Enhanced Markdown 은 underline/color 를\n * `<span underline=\"true\">` / `<span color=\"X\">` 로 **무손실 표현**하므로, 여기서는 제거 대신\n * 프로젝트 정본인 **compact 보존마커**(`%%im-nobsidian:underline%%…%%/underline%%`,\n * `%%im-nobsidian:color:C%%…%%/color%%`)로 **승격**만 한다. 실제 Notion span 복원은\n * push 직전 단일 SSOT 인 {@link obsidianToNotionEnhanced} 가 담당한다.\n *\n * 입력 표기는 pull 경로별로 다르다.\n * - Markdown API 경로: 이미 compact 마커 → 무변경 통과(여기 정규식에 걸리지 않음).\n * - notion-to-md(block) 경로: `<u>` + 공백형 색상 마커 → compact 마커로 정규화.\n * - 사용자가 직접 작성한 `<u>` / 레거시 `<span class=\"notion-*\">` → compact 마커로 승격.\n *\n * compact 마커는 공백이 없어 PreserveMarkerCollector(공백형만 수집)·기타 전처리기를\n * 무손상 통과한다(기존 underline/color 왕복이 이를 실증).\n */\nexport class InlineAnnotationPreserver implements Processor {\n readonly name = \"InlineAnnotationPreserver\";\n readonly order = 5;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n let content = input.content;\n\n // 공백형 색상 마커 → compact 색상 마커 (색상값은 그대로 보존)\n content = content.replace(\n SPACED_COLOR_REGEX,\n (_m, color: string, text: string) => `${compactMarker(`color:${color}`)}${text}%%/color%%`,\n );\n\n // <u>…</u> → underline 마커\n content = content.replace(\n UNDERLINE_REGEX,\n (_m, text: string) => `${compactMarker(\"underline\")}${text}%%/underline%%`,\n );\n\n // <span class=\"notion-X[-bg]\"> → compact 색상 마커 (-bg → _background)\n content = content.replace(\n COLOR_SPAN_REGEX,\n (_m, base: string, bg: string | undefined, text: string) => {\n const color = bg ? `${base}_background` : base;\n return `${compactMarker(`color:${color}`)}${text}%%/color%%`;\n },\n );\n\n return { content, metadata: input.metadata };\n }\n}\n","import { WIKILINK_PROTOCOL, EMBED_PROTOCOL } from \"../constants/markers.js\";\n\n/**\n * Pull 시 Notion 측 링크 표현을 Obsidian 위키링크/임베드로 복원하는 공유 로직.\n *\n * 본문(MentionToWikilink)과 프론트매터 속성 값(FrontmatterGenerator) 양쪽이\n * 동일한 규칙을 써야 하므로 한곳에서 정의한다. 마커가 없는 문자열에는 무영향(no-op).\n */\n\n/** Notion 페이지 링크 → `[[display]]`. */\nconst NOTION_LINK_REGEX =\n /\\[([^\\]]+)\\]\\((?:https:\\/\\/(?:www\\.)?notion\\.so\\/|notion:\\/\\/)([a-f0-9-]+)\\)/g;\n\n/** 위키링크 보존 마커 → `[[target]]` 또는 `[[target|display]]`. */\nconst WIKILINK_PRESERVE_REGEX = new RegExp(`\\\\[([^\\\\]]+)\\\\]\\\\(${WIKILINK_PROTOCOL}([^)]+)\\\\)`, \"g\");\n\n/** 임베드 보존 마커 → `![[target]]`. */\nconst EMBED_PRESERVE_REGEX = new RegExp(`\\\\[([^\\\\]]+)\\\\]\\\\(${EMBED_PROTOCOL}([^)]+)\\\\)`, \"g\");\n\n/** 문자열에서 링크 보존 마커를 위키링크/임베드로 복원한다. */\nexport function restoreLinkMarkers(text: string): string {\n let out = text.replace(NOTION_LINK_REGEX, (_match, display: string) => `[[${display}]]`);\n\n out = out.replace(WIKILINK_PRESERVE_REGEX, (_match, display: string, encodedTarget: string) => {\n const target = decodeURIComponent(encodedTarget);\n return target === display ? `[[${target}]]` : `[[${target}|${display}]]`;\n });\n\n out = out.replace(EMBED_PRESERVE_REGEX, (_match, _display: string, encodedTarget: string) => {\n const target = decodeURIComponent(encodedTarget);\n return `![[${target}]]`;\n });\n\n return out;\n}\n\n/**\n * 프론트매터 속성 값(문자열/배열) 안의 링크 보존 마커를 재귀적으로 복원한다.\n * 숫자·불리언·날짜 등 비문자열 값은 그대로 둔다.\n */\nexport function restoreLinkMarkersInValue(value: unknown): unknown {\n if (typeof value === \"string\") return restoreLinkMarkers(value);\n if (Array.isArray(value)) return value.map((v) => restoreLinkMarkersInValue(v));\n return value;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { restoreLinkMarkers } from \"../link-restore.js\";\n\nexport class MentionToWikilink implements Processor {\n readonly name = \"MentionToWikilink\";\n readonly order = 10;\n\n process(input: ProcessorInput): ProcessorOutput {\n return { content: restoreLinkMarkers(input.content), metadata: input.metadata };\n }\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n PreserveMarker,\n} from \"../../types/convert.js\";\nimport { spacedMarker } from \"../../constants/markers.js\";\n\nexport class PreserveMarkerInjector implements Processor {\n readonly name = \"PreserveMarkerInjector\";\n readonly order = 100;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const markers = input.metadata.preserveMarkers;\n if (!markers || markers.length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n let content = input.content;\n\n const missingMarkers = markers.filter((m) => !content.includes(this.formatMarker(m)));\n\n if (missingMarkers.length === 0) {\n return { content, metadata: input.metadata };\n }\n\n // 유실 마커를 원래 위치(startIndex) 기준으로 재삽입한다.\n // startIndex 오름차순으로 처리하면 앞선 마커가 먼저 복원되어, 각 마커의 절대 startIndex 가\n // 현재 문자열에서도 유효하다 — 변환이 주변 텍스트를 보존한 채 마커만 제거한 경우 원본\n // 전체 문자열을 정확히 재구성한다(위치 무손실). startIndex 가 현재 길이를 넘으면(stale\n // offset) 말미로 degrade 하는 것이 최후 보루다. 과거엔 항상 말미로 모아(append) 본문\n // 중간의 위치를 잃고도 '개수 보존'으로 위장했다 — 그 결함을 제거한다.\n const sorted = [...missingMarkers].sort((a, b) => a.startIndex - b.startIndex);\n for (const m of sorted) {\n const markerText = this.formatMarker(m);\n const at = Math.max(0, Math.min(m.startIndex, content.length));\n content = content.slice(0, at) + markerText + content.slice(at);\n }\n\n return { content, metadata: input.metadata };\n }\n\n private formatMarker(marker: PreserveMarker): string {\n const params = Object.entries(marker.params)\n .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)\n .join(\"&\");\n return spacedMarker(`${marker.type}:${params}`);\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst EMOJI_TYPE_MAP: Record<string, string> = {\n \"\\u{1F4DD}\": \"note\",\n \"\\u{1F4CB}\": \"abstract\",\n \"\\u{2139}\\u{FE0F}\": \"info\",\n \"\\u{1F4A1}\": \"tip\",\n \"\\u{2705}\": \"success\",\n \"\\u{2753}\": \"question\",\n \"\\u{26A0}\\u{FE0F}\": \"warning\",\n \"\\u{274C}\": \"failure\",\n \"\\u{1F525}\": \"danger\",\n \"\\u{1F41B}\": \"bug\",\n \"\\u{1F4CC}\": \"example\",\n \"\\u{1F4AC}\": \"quote\",\n};\n\nconst CALLOUT_PRESERVE_REGEX = new RegExp(\n `%% ${MARKER_BRAND_RE}:callout:type=(\\\\w+)(?:&foldable=(open|closed))? %%`,\n \"g\",\n);\n\nexport class CalloutRestorer implements Processor {\n readonly name = \"CalloutRestorer\";\n readonly order = 20;\n\n process(input: ProcessorInput): ProcessorOutput {\n let content = input.content;\n\n content = content.replace(CALLOUT_PRESERVE_REGEX, (_match, type: string, foldable?: string) => {\n if (foldable) {\n const foldChar = foldable === \"open\" ? \"+\" : \"-\";\n return `[!${type}]${foldChar}`;\n }\n return `[!${type}]`;\n });\n\n for (const [emoji, type] of Object.entries(EMOJI_TYPE_MAP)) {\n const pattern = new RegExp(`> ${escapeRegex(emoji)} \\\\*\\\\*(.+?)\\\\*\\\\*`, \"g\");\n content = content.replace(pattern, (_match, title: string) => {\n if (title.toLowerCase() === type) {\n return `> [!${type}]`;\n }\n return `> [!${type}] ${title}`;\n });\n }\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst COLOR_MARKER_REGEX = new RegExp(\n `%% ${MARKER_BRAND_RE}:color:(\\\\w+(?:_background)?) %%([\\\\s\\\\S]*?)%% ${MARKER_BRAND_RE}:end %%`,\n \"g\",\n);\n\nexport class ColorAnnotator implements Processor {\n readonly name = \"ColorAnnotator\";\n readonly order = 30;\n\n process(input: ProcessorInput): ProcessorOutput {\n const content = input.content.replace(\n COLOR_MARKER_REGEX,\n (_match, color: string, text: string) => {\n const cssClass = color.endsWith(\"_background\")\n ? `notion-${color.replace(\"_background\", \"-bg\")}`\n : `notion-${color}`;\n return `<span class=\"${cssClass}\">${text}</span>`;\n },\n );\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { restoreLinkMarkersInValue } from \"../link-restore.js\";\nimport { stringifyFrontmatter } from \"../../utils/frontmatter.js\";\n\nexport class FrontmatterGenerator implements Processor {\n readonly name = \"FrontmatterGenerator\";\n readonly order = 90;\n\n process(input: ProcessorInput): ProcessorOutput {\n const properties = input.metadata.properties as Record<string, unknown> | undefined;\n\n if (!properties || Object.keys(properties).length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n // Pull 시 속성 값에 박힌 위키링크/임베드 보존 마커를 [[...]] 로 복원한다.\n const restoreMarkers = input.context.direction === \"pull\";\n const normalized = normalizeProperties(properties, restoreMarkers);\n const content = stringifyFrontmatter(input.content, normalized);\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n\nfunction normalizeProperties(\n props: Record<string, unknown>,\n restoreMarkers: boolean,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(props)) {\n const restored = restoreMarkers ? restoreLinkMarkersInValue(value) : value;\n const normalized = normalizeValue(restored);\n if (normalized !== undefined) {\n result[key] = normalized;\n }\n }\n\n return result;\n}\n\nfunction normalizeValue(value: unknown): unknown {\n if (value instanceof Date) {\n return normalizeDate(value.toISOString());\n }\n\n if (typeof value === \"string\") {\n return normalizeDate(value);\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) return undefined;\n return value;\n }\n\n if (typeof value === \"object\" && value !== null && \"start\" in value) {\n const dateObj = value as { start: string; end?: string | null };\n const normalized = {\n start: normalizeDate(dateObj.start),\n ...(dateObj.end ? { end: normalizeDate(dateObj.end) } : {}),\n };\n return normalized;\n }\n\n return value;\n}\n\nconst MIDNIGHT_RE = /T00:00:00(?:\\.\\d{3})?(?:Z|[+-]\\d{2}:\\d{2})/;\n\nfunction normalizeDate(dateStr: string): string {\n if (typeof dateStr !== \"string\") return dateStr;\n if (MIDNIGHT_RE.test(dateStr)) {\n return dateStr.split(\"T\")[0] ?? dateStr;\n }\n return dateStr;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst LOCAL_IMAGE_MARKER_REGEX = new RegExp(\n `>\\\\s*📎\\\\s*[^\\\\n]*\\\\n>\\\\s*%%\\\\s*${MARKER_BRAND_RE}:local-image:([^\\\\s]+)\\\\s*%%`,\n \"g\",\n);\n\nexport class LocalImageRestorer implements Processor {\n readonly name = \"LocalImageRestorer\";\n readonly order = 15;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content.replace(LOCAL_IMAGE_MARKER_REGEX, (_match, target: string) => {\n return `![[${target}]]`;\n });\n\n return { content, metadata: input.metadata };\n }\n}\n","import matter from \"gray-matter\";\nimport type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst YAML_PROPERTIES_REGEX = new RegExp(\n \"```yaml\\\\n# \" + MARKER_BRAND_RE + \":properties\\\\n([\\\\s\\\\S]*?)```\\\\n*(?:---\\\\n*)?\",\n);\n\nconst LEGACY_TABLE_REGEX =\n /^\\s*\\| Property\\s*\\| Value\\s*\\|\\n\\s*\\|\\s*-{3,}\\s*\\|\\s*-{3,}\\s*\\|\\n((?:\\|[^\\n]+\\|\\n?)+)\\n*---\\n*/;\n\nexport class PropertiesTableRestorer implements Processor {\n readonly name = \"PropertiesTableRestorer\";\n readonly order = 5;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const yamlMatch = input.content.match(YAML_PROPERTIES_REGEX);\n if (yamlMatch) {\n return this.restoreFromYaml(input, yamlMatch);\n }\n\n const tableMatch = input.content.match(LEGACY_TABLE_REGEX);\n if (tableMatch) {\n return this.restoreFromTable(input, tableMatch);\n }\n\n return { content: input.content, metadata: input.metadata };\n }\n\n private restoreFromYaml(input: ProcessorInput, match: RegExpMatchArray): ProcessorOutput {\n const yamlContent = match[1]!;\n const fakeDocument = `---\\n${yamlContent}---\\n`;\n\n let parsed: Record<string, unknown>;\n try {\n const result = matter(fakeDocument);\n parsed = result.data;\n } catch {\n return { content: input.content, metadata: input.metadata };\n }\n\n const properties: Record<string, unknown> = {\n ...(input.metadata.properties as Record<string, unknown> | undefined),\n ...parsed,\n };\n\n const content = input.content.replace(YAML_PROPERTIES_REGEX, \"\").trimStart();\n\n return {\n content,\n metadata: { ...input.metadata, properties },\n };\n }\n\n private restoreFromTable(input: ProcessorInput, match: RegExpMatchArray): ProcessorOutput {\n const rows = match[1]!.trim().split(\"\\n\");\n const properties: Record<string, unknown> = {\n ...(input.metadata.properties as Record<string, unknown> | undefined),\n };\n\n for (const row of rows) {\n const cells = row\n .split(\"|\")\n .map((c) => c.trim())\n .filter(Boolean);\n if (cells.length >= 2) {\n const key = cells[0]!;\n const rawValue = cells[1]!;\n properties[key] = parseLegacyValue(rawValue);\n }\n }\n\n const content = input.content.replace(LEGACY_TABLE_REGEX, \"\").trimStart();\n\n return {\n content,\n metadata: { ...input.metadata, properties },\n };\n }\n}\n\nfunction parseLegacyValue(raw: string): unknown {\n if (raw === \"\" || raw === \"null\") return null;\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n\n const unquoted = stripQuotes(raw);\n const num = Number(unquoted);\n if (!isNaN(num) && unquoted.trim() !== \"\") return num;\n\n if (unquoted.includes(\", \")) {\n const parts = unquoted.split(\", \");\n const looksLikeArray = parts.every((p) => p.split(/\\s+/).length <= 3);\n if (looksLikeArray) {\n return parts.map((v) => {\n const n = Number(v);\n return !isNaN(n) && v.trim() !== \"\" ? n : v;\n });\n }\n }\n\n if (unquoted.startsWith(\"{\") || unquoted.startsWith(\"[\")) {\n try {\n return JSON.parse(unquoted);\n } catch {\n return unquoted;\n }\n }\n\n return unquoted;\n}\n\nfunction stripQuotes(s: string): string {\n if ((s.startsWith('\"') && s.endsWith('\"')) || (s.startsWith(\"'\") && s.endsWith(\"'\"))) {\n return s.slice(1, -1);\n }\n return s;\n}\n","import { ConversionPipeline } from \"./pipeline.js\";\nimport { FrontmatterExtractor } from \"./pre-processors/frontmatter.js\";\nimport { WikilinkResolver, type WikilinkResolverFn } from \"./pre-processors/wikilink.js\";\nimport { CalloutTransformer } from \"./pre-processors/callout.js\";\nimport { MathNormalizer } from \"./pre-processors/math.js\";\nimport { EmbedResolver } from \"./pre-processors/embed.js\";\nimport { PreserveMarkerCollector } from \"./pre-processors/preserve-marker.js\";\nimport { UnsupportedBlockStripper } from \"./pre-processors/unsupported-block-stripper.js\";\nimport { PropertiesTableInjector } from \"./pre-processors/properties-table.js\";\nimport { InlineAnnotationPreserver } from \"./pre-processors/html-annotation.js\";\nimport { MentionToWikilink } from \"./post-processors/mention-to-wikilink.js\";\nimport { PreserveMarkerInjector } from \"./post-processors/preserve-marker-injector.js\";\nimport { CalloutRestorer } from \"./post-processors/callout-restorer.js\";\nimport { ColorAnnotator } from \"./post-processors/color-annotator.js\";\nimport { FrontmatterGenerator } from \"./post-processors/frontmatter-generator.js\";\nimport { LocalImageRestorer } from \"./post-processors/local-image-restorer.js\";\nimport { PropertiesTableRestorer } from \"./post-processors/properties-table-restorer.js\";\n\nexport interface PipelineOptions {\n readonly wikilinkResolver?: WikilinkResolverFn;\n}\n\nexport function createDefaultPipeline(options?: PipelineOptions): ConversionPipeline {\n const pipeline = new ConversionPipeline();\n\n pipeline.registerPreProcessor(new InlineAnnotationPreserver());\n pipeline.registerPreProcessor(new UnsupportedBlockStripper());\n pipeline.registerPreProcessor(new FrontmatterExtractor());\n pipeline.registerPreProcessor(new PropertiesTableInjector());\n pipeline.registerPreProcessor(new WikilinkResolver(options?.wikilinkResolver));\n pipeline.registerPreProcessor(new CalloutTransformer());\n pipeline.registerPreProcessor(new MathNormalizer());\n pipeline.registerPreProcessor(new EmbedResolver());\n pipeline.registerPreProcessor(new PreserveMarkerCollector());\n\n pipeline.registerPostProcessor(new PropertiesTableRestorer());\n pipeline.registerPostProcessor(new LocalImageRestorer());\n pipeline.registerPostProcessor(new PreserveMarkerInjector());\n pipeline.registerPostProcessor(new MentionToWikilink());\n pipeline.registerPostProcessor(new CalloutRestorer());\n pipeline.registerPostProcessor(new ColorAnnotator());\n pipeline.registerPostProcessor(new FrontmatterGenerator());\n\n return pipeline;\n}\n","/**\n * Notion rich_text → Markdown 인라인 변환 (순수 함수).\n *\n * 블록 변환(block-converter)에서 분리해 단위 테스트 가능하게 한다. 인라인 서식,\n * 수식, 멘션, 색상 보존 마커 등 rich_text 한 배열을 마크다운 문자열로 환원하는\n * 책임만 가진다(SRP). Notion API·notion-to-md 에 의존하지 않는다.\n */\nimport { compactMarker } from \"../constants/markers.js\";\nimport { compactNotionId } from \"../utils/id.js\";\n\n/** caption 등 서식 없는 rich_text 의 최소 형태. */\nexport type RichTextItem = { plain_text: string; href?: string | null };\n\n/** annotations·equation·mention 까지 담은 완전한 rich_text 형태. */\nexport interface RichTextAnnotated extends RichTextItem {\n annotations?: Record<string, unknown>;\n type?: string;\n equation?: { expression: string };\n mention?: {\n type: string;\n page?: { id: string };\n date?: { start: string; end?: string | null };\n user?: { id: string; name?: string };\n database?: { id: string };\n };\n}\n\n/** rich_text 배열을 서식 없는 평문으로 환원한다(caption 등에 사용). */\nexport function richTextToPlain(richText: RichTextItem[] | undefined): string {\n if (!richText) return \"\";\n return richText.map((t) => t.plain_text).join(\"\");\n}\n\n/**\n * rich_text 배열을 마크다운으로 환원한다. 인라인 코드/굵게/기울임/취소선/밑줄/링크/\n * 색상(보존 마커)/수식/멘션을 모두 처리한다.\n */\nexport function richTextToMarkdown(richText: RichTextAnnotated[] | undefined): string {\n if (!richText) return \"\";\n return richText\n .map((t) => {\n if (t.type === \"equation\" && t.equation) {\n return `$${t.equation.expression}$`;\n }\n\n if (t.type === \"mention\" && t.mention) {\n return formatMention(t.mention, t.plain_text);\n }\n\n let text = t.plain_text;\n const a = t.annotations;\n if (a?.code) text = `\\`${text}\\``;\n if (a?.bold) text = `**${text}**`;\n if (a?.italic) text = `*${text}*`;\n if (a?.strikethrough) text = `~~${text}~~`;\n if (a?.underline) text = `<u>${text}</u>`;\n if (t.href) text = `[${text}](${t.href})`;\n\n const color = a?.color as string | undefined;\n if (color && color !== \"default\") {\n // 압축형 정본(`%%im-nobsidian:color:X%%text%%/color%%`)으로 통일한다.\n // enhanced-md-converter 의 restoreColorSpans 가 이 형태만 인식하므로, 공백형을\n // 내보내면 블록 폴백 경로의 색상이 push 시 silent 손실된다(rank15/I3).\n text = `${compactMarker(`color:${color}`)}${text}%%/color%%`;\n }\n\n return text;\n })\n .join(\"\");\n}\n\n/**\n * 멘션을 마크다운으로 환원한다. page·database 는 위키링크, date 는 날짜 문자열,\n * user 는 `@이름`. 그 외(link_preview·template_mention·custom_emoji 등)는 빈 문자열로\n * 버리면 본문이 소실되므로 Notion 이 채워주는 plain_text(예: URL, \"@오늘\")로 보존한다.\n */\nexport function formatMention(\n mention: NonNullable<RichTextAnnotated[\"mention\"]>,\n plainText: string,\n): string {\n switch (mention.type) {\n case \"page\":\n // 블록 폴백 경로도 markdown-api 경로(convertPageMentions)와 동일한 정규형\n // `[[notion:<32hex>]]` 로 내보낸다. 과거의 `[[<하이픈 id>]]` 는 오케스트레이터의\n // 멘션 해소 정규식과 맞지 않아 제목으로 복원되지 못하고 고아 위키링크로 남았다(rank20/I3).\n return mention.page ? `[[notion:${compactNotionId(mention.page.id)}]]` : plainText;\n case \"date\": {\n if (!mention.date) return plainText;\n const start = mention.date.start;\n return mention.date.end ? `${start} → ${mention.date.end}` : start;\n }\n case \"user\":\n return mention.user?.name ? `@${mention.user.name}` : plainText || \"@user\";\n case \"database\":\n return mention.database ? `[[notion:${compactNotionId(mention.database.id)}]]` : plainText;\n default:\n return plainText;\n }\n}\n","import { markdownToBlocks } from \"@tryfabric/martian\";\nimport { NotionToMarkdown } from \"notion-to-md\";\nimport type { Client } from \"@notionhq/client\";\nimport type { BlockObjectResponse } from \"@notionhq/client/build/src/api-endpoints.js\";\nimport { NotionBlockBuilder } from \"../notion/block-builder.js\";\nimport type { NotionBlock } from \"../notion/block-builder.js\";\nimport { richTextToPlain, richTextToMarkdown } from \"./rich-text-converter.js\";\nimport type { RichTextItem } from \"./rich-text-converter.js\";\nimport {\n MARKER_BRAND,\n compactMarker,\n TOGGLE_START,\n TOGGLE_END,\n COLUMN_LIST_START,\n COLUMN_SEP,\n COLUMN_LIST_END,\n TOC_MARKER,\n BREADCRUMB_MARKER,\n} from \"../constants/markers.js\";\n\nconst TRULY_UNSUPPORTED_BLOCK_TYPES = [\"unsupported\", \"template\"] as const;\n\nconst DIVIDER_PLACEHOLDER = \"​%%IM-NOBSIDIAN_DIVIDER%%​\";\n\nconst VIDEO_URL_PATTERNS = [\n /^https?:\\/\\/(www\\.)?youtube\\.com\\/watch/,\n /^https?:\\/\\/youtu\\.be\\//,\n /^https?:\\/\\/(www\\.)?vimeo\\.com\\//,\n /^https?:\\/\\/(www\\.)?dailymotion\\.com\\//,\n /^https?:\\/\\/(www\\.)?loom\\.com\\/share\\//,\n];\n\nconst EMBED_URL_PATTERNS = [\n /^https?:\\/\\/(www\\.)?figma\\.com\\//,\n /^https?:\\/\\/docs\\.google\\.com\\//,\n /^https?:\\/\\/drive\\.google\\.com\\//,\n /^https?:\\/\\/(www\\.)?miro\\.com\\//,\n /^https?:\\/\\/(www\\.)?twitter\\.com\\//,\n /^https?:\\/\\/(www\\.)?x\\.com\\//,\n /^https?:\\/\\/codepen\\.io\\//,\n /^https?:\\/\\/gist\\.github\\.com\\//,\n /^https?:\\/\\/(www\\.)?spotify\\.com\\//,\n /^https?:\\/\\/(www\\.)?soundcloud\\.com\\//,\n];\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport class BlockConverter {\n private n2m: NotionToMarkdown | null = null;\n private client: Client | null = null;\n\n initNotionToMd(client: Client): void {\n this.client = client;\n this.n2m = new NotionToMarkdown({ notionClient: client });\n this.registerCustomTransformers();\n }\n\n private registerCustomTransformers(): void {\n if (!this.n2m) return;\n\n for (const blockType of TRULY_UNSUPPORTED_BLOCK_TYPES) {\n this.n2m.setCustomTransformer(blockType, (block) => {\n const id = block.id ?? \"unknown\";\n return Promise.resolve(\n `> [!${MARKER_BRAND}-unsupported] Notion 전용 블록\\n> type: ${blockType}, id: ${id}\\n> ${compactMarker(`unsupported:type=${blockType}&id=${id}`)}`,\n );\n });\n }\n\n this.registerToggleTransformer();\n this.registerColumnTransformer();\n this.registerSyncedBlockTransformer();\n this.registerBookmarkTransformer();\n this.registerVideoTransformer();\n this.registerAudioTransformer();\n this.registerFileTransformer();\n this.registerChildPageTransformer();\n this.registerChildDatabaseTransformer();\n this.registerLinkToPageTransformer();\n this.registerTocTransformer();\n this.registerBreadcrumbTransformer();\n this.registerLinkPreviewTransformer();\n this.registerPdfTransformer();\n this.registerEmbedTransformer();\n this.registerCalloutTransformer();\n this.registerToggleHeadingTransformers();\n this.registerNumberedListTransformer();\n }\n\n /**\n * `numbered_list_item` 을 `1.` 마크다운으로 내보내 **번호 목록 타입을 보존**한다(I2 블록 라운드트립).\n *\n * notion-to-md 기본 렌더는 `md.bullet(text, block.numbered_list_item.number)` 를 쓰는데\n * Notion API 는 list item 에 `.number` 를 채워주지 않아 `undefined` → 불릿(`- `)으로 **강등**된다.\n * 그러면 블록 폴백 경로(notionBlocksToMarkdown)로 pull 한 뒤 다시 push 하면 numbered_list_item 이\n * bulleted_list_item 으로 **타입 유실**된다(기본 markdown-api 경로는 영향 없음).\n *\n * 항상 `1.` 로 내보내면 마크다운이 시각적으로 자동 재번호하므로 표시는 동일하고, martian 이 다시\n * numbered_list_item 으로 파싱해 타입이 보존된다. 커스텀 트랜스포머 등록은 notion-to-md 의 기본\n * 자식 처리를 끄므로(라이브러리 설계), 자식은 toggle/callout 과 동일하게 직접 fetch·들여쓰기한다.\n */\n private registerNumberedListTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n this.n2m.setCustomTransformer(\"numbered_list_item\", async (block) => {\n const b = block as unknown as {\n numbered_list_item: { rich_text: RichTextItem[] };\n } & BlockObjectResponse;\n const text = richTextToMarkdown(b.numbered_list_item?.rich_text as never);\n let result = `1. ${text}`;\n if (b.has_children) {\n const children = await n2m.pageToMarkdown(b.id);\n const childMd =\n (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n if (childMd.trim()) {\n const indented = childMd\n .split(\"\\n\")\n .map((l: string) => (l.trim() ? ` ${l}` : \"\"))\n .join(\"\\n\")\n .trimEnd();\n result += \"\\n\" + indented;\n }\n }\n return result;\n });\n }\n\n private registerToggleTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n this.n2m.setCustomTransformer(\"toggle\", async (block) => {\n const b = block as unknown as { toggle: { rich_text: RichTextItem[] } } & BlockObjectResponse;\n const title = richTextToMarkdown(b.toggle?.rich_text as never);\n const children = b.has_children ? await n2m.pageToMarkdown(b.id) : [];\n const childMd = (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n const indented = childMd\n .split(\"\\n\")\n .map((line: string) => (line.trim() ? ` ${line}` : \" \"))\n .join(\"\\n\")\n .trimEnd();\n return `${TOGGLE_START}\\n- ${title}\\n${indented}\\n${TOGGLE_END}`;\n });\n }\n\n private registerToggleHeadingTransformers(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n\n for (const level of [1, 2, 3] as const) {\n const headingKey = `heading_${level}` as const;\n this.n2m.setCustomTransformer(headingKey, async (block) => {\n const b = block as unknown as {\n [K in typeof headingKey]: { rich_text: RichTextItem[]; is_toggleable?: boolean };\n } & BlockObjectResponse;\n const headingData = b[headingKey];\n const text = richTextToMarkdown(headingData?.rich_text as never);\n const prefix = \"#\".repeat(level);\n\n if (headingData?.is_toggleable && b.has_children) {\n const children = await n2m.pageToMarkdown(b.id);\n const childMd =\n (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n return `${prefix} ${text}\\n\\n${childMd.trimEnd()}`;\n }\n\n return `${prefix} ${text}`;\n });\n }\n }\n\n private registerColumnTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n const client = this.client!;\n\n this.n2m.setCustomTransformer(\"column_list\", async (block) => {\n const b = block as BlockObjectResponse;\n const response = await client.blocks.children.list({ block_id: b.id });\n const columns = response.results as BlockObjectResponse[];\n const parts: string[] = [];\n\n for (let i = 0; i < columns.length; i++) {\n const col = columns[i]!;\n const children = await n2m.pageToMarkdown(col.id);\n const childMd =\n (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n parts.push(`${COLUMN_SEP}\\n${childMd.trimEnd()}`);\n }\n\n return `${COLUMN_LIST_START}\\n${parts.join(\"\\n\")}\\n${COLUMN_LIST_END}`;\n });\n\n this.n2m.setCustomTransformer(\"column\", async () => \"\");\n }\n\n private registerSyncedBlockTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n const client = this.client!;\n\n this.n2m.setCustomTransformer(\"synced_block\", async (block) => {\n const b = block as unknown as {\n synced_block: { synced_from: { block_id: string } | null };\n } & BlockObjectResponse;\n\n const sourceId = b.synced_block?.synced_from?.block_id ?? b.id;\n\n const response = await client.blocks.children.list({ block_id: sourceId });\n const mdBlocks: unknown[] = [];\n for (const child of response.results as BlockObjectResponse[]) {\n const result = await n2m.blockToMarkdown(child as never);\n if (result) mdBlocks.push(result);\n }\n const childMd = n2m.toMarkdownString(mdBlocks as never).parent ?? \"\";\n return childMd.trimEnd();\n });\n }\n\n private registerBookmarkTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"bookmark\", async (block) => {\n const b = block as unknown as {\n bookmark: { url: string; caption?: RichTextItem[] };\n };\n const url = b.bookmark?.url ?? \"\";\n const caption = richTextToPlain(b.bookmark?.caption);\n if (caption) {\n return `[${caption}](${url})`;\n }\n return `[${url}](${url})`;\n });\n }\n\n private registerVideoTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"video\", async (block) => {\n const b = block as unknown as {\n video: {\n type: string;\n external?: { url: string };\n file?: { url: string };\n caption?: RichTextItem[];\n };\n };\n const url = b.video?.type === \"external\" ? b.video.external?.url : b.video?.file?.url;\n const caption = richTextToPlain(b.video?.caption);\n return `![${caption || \"video\"}](${url ?? \"\"})`;\n });\n }\n\n private registerAudioTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"audio\", async (block) => {\n const b = block as unknown as {\n audio: {\n type: string;\n external?: { url: string };\n file?: { url: string };\n caption?: RichTextItem[];\n };\n };\n const url = b.audio?.type === \"external\" ? b.audio.external?.url : b.audio?.file?.url;\n const caption = richTextToPlain(b.audio?.caption);\n return `![${caption || \"audio\"}](${url ?? \"\"})`;\n });\n }\n\n private registerFileTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"file\", async (block) => {\n const b = block as unknown as {\n file: {\n type: string;\n external?: { url: string };\n file?: { url: string };\n caption?: RichTextItem[];\n name?: string;\n };\n };\n const url = b.file?.type === \"external\" ? b.file.external?.url : b.file?.file?.url;\n const name = b.file?.name ?? richTextToPlain(b.file?.caption) ?? \"file\";\n return `[${name}](${url ?? \"\"})`;\n });\n }\n\n private registerChildPageTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"child_page\", async (block) => {\n const b = block as unknown as { child_page: { title: string } };\n const title = b.child_page?.title ?? \"Untitled\";\n return `[[${title}]]`;\n });\n }\n\n private registerChildDatabaseTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"child_database\", async (block) => {\n const b = block as unknown as {\n child_database: { title: string };\n } & BlockObjectResponse;\n const title = b.child_database?.title ?? \"Database\";\n return `> [!database] ${title}\\n> ${compactMarker(`child-database:id=${b.id}&title=${encodeURIComponent(title)}`)}`;\n });\n }\n\n private registerLinkToPageTransformer(): void {\n if (!this.n2m) return;\n const client = this.client!;\n this.n2m.setCustomTransformer(\"link_to_page\", async (block) => {\n const b = block as unknown as {\n link_to_page: { type: string; page_id?: string; database_id?: string };\n };\n const pageId = b.link_to_page?.page_id ?? b.link_to_page?.database_id;\n if (!pageId) return \"\";\n try {\n const page = await client.pages.retrieve({ page_id: pageId });\n const p = page as {\n properties: Record<string, { type: string; title?: Array<{ plain_text: string }> }>;\n };\n for (const prop of Object.values(p.properties)) {\n if (prop.type === \"title\" && prop.title?.[0]?.plain_text) {\n return `[[${prop.title[0].plain_text}]]`;\n }\n }\n } catch {\n // fallback\n }\n return `[[${pageId}]]`;\n });\n }\n\n private registerTocTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"table_of_contents\", async () => {\n return TOC_MARKER;\n });\n }\n\n private registerBreadcrumbTransformer(): void {\n if (!this.n2m) return;\n // breadcrumb 은 마크다운 표현이 없다. 빈 문자열로 버리면 라운드트립에서 소실되므로\n // 보존 마커를 남겨 push 시 breadcrumb 블록으로 복원한다(convertSingleLineMarker).\n this.n2m.setCustomTransformer(\"breadcrumb\", async () => BREADCRUMB_MARKER);\n }\n\n private registerLinkPreviewTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"link_preview\", async (block) => {\n const b = block as unknown as { link_preview: { url: string } };\n const url = b.link_preview?.url ?? \"\";\n return `[${url}](${url})`;\n });\n }\n\n private registerPdfTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"pdf\", async (block) => {\n const b = block as unknown as {\n pdf: {\n type: string;\n file?: { url: string };\n external?: { url: string };\n caption?: RichTextItem[];\n };\n };\n const url = b.pdf?.type === \"file\" ? (b.pdf.file?.url ?? \"\") : (b.pdf?.external?.url ?? \"\");\n const caption = b.pdf?.caption ? richTextToMarkdown(b.pdf.caption as never) : \"\";\n return `[📄 ${caption || \"PDF\"}](${url})`;\n });\n }\n\n private registerEmbedTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"embed\", async (block) => {\n const b = block as unknown as {\n embed: { url: string; caption?: RichTextItem[] };\n };\n const url = b.embed?.url ?? \"\";\n const caption = b.embed?.caption ? richTextToMarkdown(b.embed.caption as never) : \"\";\n return `[${caption || url}](${url})`;\n });\n }\n\n private registerCalloutTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n this.n2m.setCustomTransformer(\"callout\", async (block) => {\n const b = block as unknown as {\n callout: { rich_text: RichTextItem[]; icon?: { type: string; emoji?: string } };\n } & BlockObjectResponse;\n const text = richTextToMarkdown(b.callout?.rich_text as never);\n const emoji = b.callout?.icon?.emoji ?? \"\";\n\n const children = b.has_children ? await n2m.pageToMarkdown(b.id) : [];\n const childMd = (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n\n const EMOJI_TO_TYPE: Record<string, string> = {\n \"\\u{1F4DD}\": \"note\",\n \"\\u{1F4CB}\": \"abstract\",\n \"\\u{2139}\\u{FE0F}\": \"info\",\n \"\\u{1F4A1}\": \"tip\",\n \"\\u{2705}\": \"success\",\n \"\\u{2753}\": \"question\",\n \"\\u{26A0}\\u{FE0F}\": \"warning\",\n \"\\u{274C}\": \"failure\",\n \"\\u{1F525}\": \"danger\",\n \"\\u{1F41B}\": \"bug\",\n \"\\u{1F4CC}\": \"example\",\n \"\\u{1F4AC}\": \"quote\",\n };\n const calloutType = EMOJI_TO_TYPE[emoji] ?? \"note\";\n\n let result = `> [!${calloutType}] ${text}`;\n if (childMd?.trim()) {\n const lines = childMd\n .trim()\n .split(\"\\n\")\n .map((l: string) => (l.trim() ? `> ${l}` : \">\"));\n result += \"\\n\" + lines.join(\"\\n\");\n }\n return result;\n });\n }\n\n markdownToNotionBlocks(markdown: string): unknown[] {\n const preprocessed = this.preProcessMarkdown(markdown);\n const blocks = markdownToBlocks(preprocessed) as Array<Record<string, unknown>>;\n const processed = this.postProcessBlocks(blocks);\n return normalizeBlocksForNotion(processed as Array<Record<string, unknown>>);\n }\n\n private toggleContents: Map<number, string> = new Map();\n private columnContents: Map<number, string[]> = new Map();\n private toggleCounter = 0;\n private columnCounter = 0;\n\n private preProcessMarkdown(markdown: string): string {\n this.toggleContents.clear();\n this.columnContents.clear();\n this.toggleCounter = 0;\n this.columnCounter = 0;\n\n let processed = this.extractToggleBlocks(markdown);\n processed = this.extractColumnBlocks(processed);\n processed = this.replaceDividers(processed);\n processed = processed.replace(/<unknown[^>]*\\/>/g, \"\");\n processed = this.stripInlineAnnotationMarkers(processed);\n return processed;\n }\n\n /**\n * compact underline/color 보존마커를 평문으로 강등 — block(martian) 폴백 경로 전용.\n *\n * 무손실 underline/color 복원은 기본 경로인 Markdown API({@link obsidianToNotionEnhanced})가\n * 전담한다. martian 은 이 서식을 표현할 수 없으므로, Markdown API 가 실패해 이 폴백을 탈 때는\n * 마커 텍스트가 본문에 리터럴로 새지 않도록 텍스트만 남기고 마커를 제거한다(서식 degrade).\n */\n private stripInlineAnnotationMarkers(markdown: string): string {\n return markdown\n .replace(new RegExp(`%%${MARKER_BRAND}:underline%%([\\\\s\\\\S]*?)%%\\\\/underline%%`, \"g\"), \"$1\")\n .replace(new RegExp(`%%${MARKER_BRAND}:color:[^%]+%%([\\\\s\\\\S]*?)%%\\\\/color%%`, \"g\"), \"$1\");\n }\n\n private replaceDividers(markdown: string): string {\n const lines = markdown.split(\"\\n\");\n const result: string[] = [];\n let inCodeBlock = false;\n\n for (const line of lines) {\n if (line.trimStart().startsWith(\"```\")) {\n inCodeBlock = !inCodeBlock;\n }\n\n if (!inCodeBlock && /^---\\s*$/.test(line.trim())) {\n result.push(DIVIDER_PLACEHOLDER);\n } else {\n result.push(line);\n }\n }\n\n return result.join(\"\\n\");\n }\n\n private extractToggleBlocks(markdown: string): string {\n const startRe = new RegExp(`^${escapeRegex(TOGGLE_START)}$`, \"gm\");\n const endRe = new RegExp(`^${escapeRegex(TOGGLE_END)}$`, \"gm\");\n let result = markdown;\n let match: RegExpExecArray | null;\n\n while ((match = startRe.exec(result)) !== null) {\n endRe.lastIndex = match.index;\n const endMatch = endRe.exec(result);\n if (!endMatch) break;\n\n const content = result.slice(match.index + match[0].length + 1, endMatch.index).trimEnd();\n const id = this.toggleCounter++;\n this.toggleContents.set(id, content);\n\n const placeholder = `%%IM-NOBSIDIAN_TOGGLE_${id}%%`;\n result =\n result.slice(0, match.index) +\n placeholder +\n result.slice(endMatch.index + endMatch[0].length);\n\n startRe.lastIndex = match.index + placeholder.length;\n }\n\n return result;\n }\n\n private extractColumnBlocks(markdown: string): string {\n const startRe = new RegExp(`^${escapeRegex(COLUMN_LIST_START)}$`, \"gm\");\n const endRe = new RegExp(`^${escapeRegex(COLUMN_LIST_END)}$`, \"gm\");\n let result = markdown;\n let match: RegExpExecArray | null;\n\n while ((match = startRe.exec(result)) !== null) {\n endRe.lastIndex = match.index;\n const endMatch = endRe.exec(result);\n if (!endMatch) break;\n\n const inner = result.slice(match.index + match[0].length + 1, endMatch.index);\n const columns = inner\n .split(new RegExp(`^${escapeRegex(COLUMN_SEP)}$`, \"m\"))\n .map((c) => c.trim())\n .filter(Boolean);\n\n const id = this.columnCounter++;\n this.columnContents.set(id, columns);\n\n const placeholder = `%%IM-NOBSIDIAN_COLLIST_${id}%%`;\n result =\n result.slice(0, match.index) +\n placeholder +\n result.slice(endMatch.index + endMatch[0].length);\n\n startRe.lastIndex = match.index + placeholder.length;\n }\n\n return result;\n }\n\n private postProcessBlocks(blocks: Array<Record<string, unknown>>): unknown[] {\n const result: unknown[] = [];\n\n for (const block of blocks) {\n const toggleConverted = this.convertTogglePlaceholder(block);\n if (toggleConverted) {\n result.push(toggleConverted);\n continue;\n }\n\n const columnConverted = this.convertColumnPlaceholder(block);\n if (columnConverted) {\n result.push(columnConverted);\n continue;\n }\n\n const dividerConverted = this.convertDividerPlaceholder(block);\n if (dividerConverted) {\n result.push(dividerConverted);\n continue;\n }\n\n const markerConverted = this.convertSingleLineMarker(block);\n if (markerConverted) {\n result.push(markerConverted);\n continue;\n }\n\n const videoConverted = this.convertImageToVideoOrEmbed(block);\n if (videoConverted) {\n result.push(videoConverted);\n continue;\n }\n\n // martian 의 blockquote 자식-중첩을 평탄화해 본문을 quote.rich_text 로 복원한 뒤,\n // 이모지 접두사 quote 의 callout 변환을 적용한다(평탄화 전에는 rich_text 가 비어 no-op).\n const flattened = this.flattenMartianBlockquote(block);\n const calloutConverted = this.convertQuoteToCallout(flattened);\n result.push(calloutConverted);\n }\n\n return result;\n }\n\n private convertTogglePlaceholder(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const text = para?.rich_text?.[0]?.text?.content ?? \"\";\n\n const toggleMatch = text.match(/%%IM-NOBSIDIAN_TOGGLE_(\\d+)%%/);\n if (!toggleMatch) return null;\n\n const id = parseInt(toggleMatch[1]!, 10);\n const content = this.toggleContents.get(id);\n if (content === undefined) return null;\n\n const titleMatch = content.match(/^- (.+)$/m);\n const title = titleMatch?.[1] ?? \"Toggle\";\n\n const childLines = content.split(\"\\n\").slice(1);\n const childMd = childLines\n .map((l) => (l.startsWith(\" \") ? l.slice(2) : l))\n .join(\"\\n\")\n .trim();\n\n const children = childMd ? (markdownToBlocks(childMd) as Array<Record<string, unknown>>) : [];\n\n return NotionBlockBuilder.toggle(\n NotionBlockBuilder.richText(title),\n children.length > 0 ? (children as unknown as NotionBlock[]) : undefined,\n );\n }\n\n private convertColumnPlaceholder(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const text = para?.rich_text?.[0]?.text?.content ?? \"\";\n\n const colMatch = text.match(/%%IM-NOBSIDIAN_COLLIST_(\\d+)%%/);\n if (!colMatch) return null;\n\n const id = parseInt(colMatch[1]!, 10);\n const columns = this.columnContents.get(id);\n if (!columns) return null;\n\n const columnBlocks = columns.map((colMd) => {\n const blocks = markdownToBlocks(colMd) as Array<Record<string, unknown>>;\n return this.postProcessBlocks(blocks) as unknown as NotionBlock[];\n });\n\n return NotionBlockBuilder.columnList(columnBlocks);\n }\n\n private convertDividerPlaceholder(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const text = para?.rich_text?.[0]?.text?.content ?? \"\";\n\n if (text.includes(\"%%IM-NOBSIDIAN_DIVIDER%%\")) {\n return NotionBlockBuilder.divider();\n }\n return null;\n }\n\n /**\n * 단일 라인 보존 마커(목차·breadcrumb)를 원래 블록으로 복원한다.\n * pull 시 마크다운 표현이 없는 블록을 `%%im-nobsidian:toc%%` /\n * `%%im-nobsidian:breadcrumb%%` 마커 문단으로 남겨두므로, push 시 이 문단을\n * 감지해 table_of_contents / breadcrumb 블록으로 되돌린다. 그러지 않으면\n * 마커 텍스트가 일반 문단으로 Notion 에 기록되는 잠재 손실이 된다.\n */\n private convertSingleLineMarker(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const texts = para?.rich_text ?? [];\n if (texts.length !== 1) return null;\n\n const text = (texts[0]?.text?.content ?? \"\").trim();\n if (text === TOC_MARKER) {\n return NotionBlockBuilder.tableOfContents();\n }\n if (text === BREADCRUMB_MARKER) {\n return NotionBlockBuilder.breadcrumb();\n }\n return null;\n }\n\n private convertImageToVideoOrEmbed(block: Record<string, unknown>): unknown | null {\n let url = \"\";\n let caption: string | undefined;\n\n if (block.type === \"image\") {\n const img = block.image as\n | {\n external?: { url: string };\n file?: { url: string };\n caption?: Array<{ text?: { content: string } }>;\n }\n | undefined;\n // video/audio/file/pdf 핸들러와 동일하게 external·file(업로드) 양쪽 URL 을 수용한다.\n // file 만 있는 업로드 이미지의 video/embed 승격이 누락되던 비대칭 결함을 봉합(rank17/I3).\n url = img?.external?.url ?? img?.file?.url ?? \"\";\n caption = img?.caption?.[0]?.text?.content;\n } else if (block.type === \"paragraph\") {\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const texts = para?.rich_text ?? [];\n if (texts.length === 1) {\n const content = texts[0]?.text?.content ?? \"\";\n if (/^https?:\\/\\//.test(content)) {\n url = content;\n }\n }\n }\n\n if (!url) return null;\n\n if (VIDEO_URL_PATTERNS.some((p) => p.test(url))) {\n return NotionBlockBuilder.video(url, caption);\n }\n\n if (EMBED_URL_PATTERNS.some((p) => p.test(url))) {\n return NotionBlockBuilder.embed(url, caption);\n }\n\n return null;\n }\n\n /**\n * `@tryfabric/martian` 의 blockquote 표현을 **평탄화**한다(I2/I3 무손실 push).\n *\n * martian 의 parseBlockquote 는 `notion.blockquote([], children)` 로 본문을 quote 의\n * **자식 paragraph** 로 내려보내고 quote.rich_text 를 비운다(라이브러리 설계). 그 결과\n * `> 인용문` 을 push 하면 Notion 에 \"빈 인용 줄 + 들여쓴 자식 문단\"이 만들어지고, 다시\n * pull 하면 `> `(빈 줄) 아래에 자식 문단이 매달려 **원문과 구조가 갈라진다**(라운드트립 손실).\n * 또한 quote.rich_text[0] 이 항상 비어 callout 이모지 감지({@link convertQuoteToCallout})도\n * 무력화됐다.\n *\n * 선두의 연속된 paragraph 자식을 quote.rich_text 로 끌어올리고(문단 사이는 줄바꿈 rich_text\n * 로 연결 — Notion 네이티브 멀티라인 인용 표현), paragraph 가 아닌 자식(중첩 리스트 등)은\n * children 으로 남겨 구조를 보존한다. 이미 rich_text 에 본문이 있거나 끌어올릴 paragraph 가\n * 없으면 원본을 그대로 반환한다(안전 no-op).\n */\n private flattenMartianBlockquote(block: Record<string, unknown>): Record<string, unknown> {\n if (block.type !== \"quote\") return block;\n const quote = block.quote as\n | {\n rich_text?: Array<Record<string, unknown>>;\n children?: Array<Record<string, unknown>>;\n }\n | undefined;\n if (!quote) return block;\n\n const richText = quote.rich_text ?? [];\n const hasText = richText.some((r) => {\n const t = r as { text?: { content?: string }; plain_text?: string };\n return (t.text?.content ?? t.plain_text ?? \"\") !== \"\";\n });\n const children = quote.children ?? [];\n // 본문이 이미 rich_text 에 있거나 끌어올릴 자식이 없으면 변형하지 않는다.\n if (hasText || children.length === 0) return block;\n\n const hoisted: Array<Record<string, unknown>> = [];\n let consumed = 0;\n for (; consumed < children.length; consumed++) {\n const child = children[consumed] as Record<string, unknown>;\n if (child.type !== \"paragraph\") break;\n const para = child.paragraph as { rich_text?: Array<Record<string, unknown>> } | undefined;\n const paraRt = para?.rich_text ?? [];\n if (hoisted.length > 0) {\n // 문단 사이 줄바꿈을 Notion 네이티브 인용처럼 rich_text 줄바꿈으로 보존.\n hoisted.push(\n ...(NotionBlockBuilder.richText(\"\\n\") as unknown as Array<Record<string, unknown>>),\n );\n }\n hoisted.push(...paraRt);\n }\n // 끌어올릴 선두 paragraph 가 하나도 없으면(리스트 등만 존재) 원본 유지.\n if (hoisted.length === 0) return block;\n\n const remaining = children.slice(consumed);\n const newQuote: Record<string, unknown> = { ...quote, rich_text: hoisted };\n if (remaining.length > 0) newQuote.children = remaining;\n else delete newQuote.children;\n return { ...block, quote: newQuote };\n }\n\n private convertQuoteToCallout(block: Record<string, unknown>): unknown {\n if (block.type !== \"quote\") return block;\n\n const quote = block.quote as\n | {\n rich_text: Array<{\n type: string;\n text?: { content: string; link?: unknown };\n annotations?: Record<string, boolean>;\n }>;\n children?: Array<Record<string, unknown>>;\n }\n | undefined;\n if (!quote?.rich_text?.[0]) return block;\n\n const firstText = quote.rich_text[0]?.text?.content ?? \"\";\n\n const KNOWN_CALLOUT_EMOJIS = [\n \"\\u{1F4DD}\",\n \"\\u{1F4CB}\",\n \"\\u{2139}\\u{FE0F}\",\n \"\\u{1F4A1}\",\n \"\\u{2705}\",\n \"\\u{2753}\",\n \"\\u{26A0}\\u{FE0F}\",\n \"\\u{274C}\",\n \"\\u{1F525}\",\n \"\\u{1F41B}\",\n \"\\u{1F4CC}\",\n \"\\u{1F4AC}\",\n ];\n const matchedEmoji = KNOWN_CALLOUT_EMOJIS.find((e) => firstText.startsWith(e));\n if (!matchedEmoji) return block;\n\n const emoji = matchedEmoji;\n const remainingText = firstText.slice(emoji.length).replace(/^\\s+/, \"\");\n\n const newRichText = [...quote.rich_text];\n if (remainingText) {\n newRichText[0] = {\n ...newRichText[0]!,\n text: { content: remainingText, link: null },\n };\n } else {\n newRichText.shift();\n }\n\n return {\n type: \"callout\",\n callout: {\n rich_text: newRichText,\n icon: { type: \"emoji\", emoji },\n children: quote.children ?? [],\n },\n };\n }\n\n async notionBlocksToMarkdown(pageId: string): Promise<string> {\n if (!this.n2m) {\n throw new Error(\n \"NotionToMarkdown이 초기화되지 않았습니다. initNotionToMd()를 먼저 호출하세요.\",\n );\n }\n\n const mdBlocks = await this.n2m.pageToMarkdown(pageId);\n const result = this.n2m.toMarkdownString(mdBlocks);\n return result.parent ?? \"\";\n }\n\n /**\n * **in-memory** 블록 배열을 마크다운으로 변환한다(페이지 fetch 없음). notion-to-md 의\n * blocksToMarkdown 을 직접 호출하므로, `has_children:false` 인 평면 블록은 Notion 클라이언트를\n * 전혀 건드리지 않는다 → 고정 픽스처로 **오프라인 결정론** 블록 라운드트립(I2)을 잠글 수 있는\n * 정식 테스트 시임. children 이 있는 블록(table 행·callout 자식 등)은 클라이언트를 호출하므로\n * 호출 측이 평면 블록만 넣어야 오프라인이 보장된다.\n */\n async notionBlockArrayToMarkdown(blocks: Array<Record<string, unknown>>): Promise<string> {\n if (!this.n2m) {\n throw new Error(\n \"NotionToMarkdown이 초기화되지 않았습니다. initNotionToMd()를 먼저 호출하세요.\",\n );\n }\n const mdBlocks = await this.n2m.blocksToMarkdown(blocks as never);\n return this.n2m.toMarkdownString(mdBlocks).parent ?? \"\";\n }\n}\n\nconst NOTION_MAX_TABLE_ROWS = 100;\nconst NOTION_MAX_LIST_DEPTH = 3;\n\nfunction normalizeBlocksForNotion(\n blocks: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n const result: Array<Record<string, unknown>> = [];\n\n for (const block of blocks) {\n if (block.type === \"table\") {\n result.push(...normalizeTable(block));\n } else if (isListBlock(block)) {\n result.push(flattenListDepth(block, 0));\n } else {\n result.push(block);\n }\n }\n\n return result;\n}\n\nfunction normalizeTable(block: Record<string, unknown>): Array<Record<string, unknown>> {\n const table = block.table as\n | {\n table_width: number;\n has_column_header: boolean;\n has_row_header: boolean;\n children: Array<Record<string, unknown>>;\n }\n | undefined;\n if (!table?.children) return [block];\n\n const rows = table.children;\n if (rows.length === 0) return [block];\n\n let maxCells = table.table_width;\n for (const row of rows) {\n const tr = row.table_row as { cells: unknown[][] } | undefined;\n if (tr?.cells && tr.cells.length > maxCells) {\n maxCells = tr.cells.length;\n }\n }\n\n const normalizedRows = rows.map((row) => {\n const tr = row.table_row as { cells: unknown[][] } | undefined;\n if (!tr?.cells) return row;\n\n const cells = [...tr.cells];\n while (cells.length < maxCells) {\n cells.push([{ type: \"text\", text: { content: \"\" } }]);\n }\n if (cells.length > maxCells) {\n cells.length = maxCells;\n }\n\n return { ...row, table_row: { ...tr, cells } };\n });\n\n if (normalizedRows.length <= NOTION_MAX_TABLE_ROWS) {\n return [\n {\n ...block,\n table: { ...table, table_width: maxCells, children: normalizedRows },\n },\n ];\n }\n\n const tables: Array<Record<string, unknown>> = [];\n const headerRow = table.has_column_header ? normalizedRows[0] : null;\n const dataRows = table.has_column_header ? normalizedRows.slice(1) : normalizedRows;\n const chunkSize = headerRow ? NOTION_MAX_TABLE_ROWS - 1 : NOTION_MAX_TABLE_ROWS;\n\n for (let i = 0; i < dataRows.length; i += chunkSize) {\n const chunk = dataRows.slice(i, i + chunkSize);\n const children = headerRow ? [headerRow, ...chunk] : chunk;\n tables.push({\n type: \"table\",\n table: {\n table_width: maxCells,\n has_column_header: !!headerRow,\n has_row_header: table.has_row_header,\n children,\n },\n });\n }\n\n return tables;\n}\n\nfunction isListBlock(block: Record<string, unknown>): boolean {\n return (\n block.type === \"bulleted_list_item\" ||\n block.type === \"numbered_list_item\" ||\n block.type === \"to_do\"\n );\n}\n\nfunction flattenListDepth(block: Record<string, unknown>, depth: number): Record<string, unknown> {\n const blockType = block.type as string;\n const blockData = block[blockType] as\n | { children?: Array<Record<string, unknown>>; [key: string]: unknown }\n | undefined;\n if (!blockData?.children || blockData.children.length === 0) return block;\n\n if (depth >= NOTION_MAX_LIST_DEPTH - 1) {\n const flattened = collectAllDescendants(blockData.children);\n return {\n ...block,\n [blockType]: { ...blockData, children: flattened },\n };\n }\n\n const normalizedChildren = blockData.children.map((child) => {\n if (isListBlock(child)) {\n return flattenListDepth(child, depth + 1);\n }\n return child;\n });\n\n return {\n ...block,\n [blockType]: { ...blockData, children: normalizedChildren },\n };\n}\n\nfunction collectAllDescendants(\n blocks: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n const result: Array<Record<string, unknown>> = [];\n for (const block of blocks) {\n const blockType = block.type as string;\n const blockData = block[blockType] as\n | { children?: Array<Record<string, unknown>>; [key: string]: unknown }\n | undefined;\n const children = blockData?.children;\n const blockWithoutChildren = children\n ? { ...block, [blockType]: { ...blockData, children: undefined } }\n : block;\n result.push(blockWithoutChildren);\n if (children && children.length > 0) {\n result.push(...collectAllDescendants(children));\n }\n }\n return result;\n}\n","import { createHash } from \"node:crypto\";\nimport { Sema } from \"async-sema\";\nimport type { VaultFS } from \"./vault-fs.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { ImageReference } from \"../types/convert.js\";\nimport { getLogger } from \"../utils/logger.js\";\n\n/** 미디어(이미지/파일) 다운로드 운영 튜닝값. 미지정 시 기존 동작과 동일한 기본값 사용. */\nexport interface MediaOptions {\n readonly concurrency?: number;\n readonly maxRetries?: number;\n readonly retryBaseMs?: number;\n readonly maxFileSizeBytes?: number;\n}\n\nexport interface ImageDownloadResult {\n readonly originalUrl: string;\n readonly localPath: string;\n readonly hash: string;\n readonly size: number;\n}\n\nexport interface ImageUploadResult {\n readonly localPath: string;\n readonly fileUploadId: string;\n /** 업로드한 이미지의 전체 sha256 — file_registry 비교 키(FileHandler 와 동일 산식). */\n readonly fileHash: string;\n readonly fileSize: number;\n}\n\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n \"image/png\": \".png\",\n \"image/jpeg\": \".jpg\",\n \"image/gif\": \".gif\",\n \"image/webp\": \".webp\",\n \"image/svg+xml\": \".svg\",\n \"image/bmp\": \".bmp\",\n \"image/tiff\": \".tiff\",\n};\n\nconst EXTENSION_TO_MIME: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".bmp\": \"image/bmp\",\n \".ico\": \"image/x-icon\",\n \".tiff\": \"image/tiff\",\n};\n\nexport class ImageHandler {\n private readonly customFetch?: typeof globalThis.fetch;\n private readonly concurrency: number;\n private readonly maxRetries: number;\n private readonly retryBaseMs: number;\n private readonly maxFileSizeBytes: number;\n\n constructor(\n private readonly vaultFs: VaultFS,\n private readonly attachmentFolder: string = \"attachments\",\n private readonly notionClient?: NotionClient,\n customFetch?: typeof globalThis.fetch,\n options?: MediaOptions,\n private readonly stateDb?: IStateDB,\n ) {\n this.customFetch = customFetch;\n this.concurrency = options?.concurrency ?? 3;\n this.maxRetries = options?.maxRetries ?? 3;\n this.retryBaseMs = options?.retryBaseMs ?? 1000;\n this.maxFileSizeBytes = options?.maxFileSizeBytes ?? 100 * 1024 * 1024;\n }\n\n private get fetchFn(): typeof globalThis.fetch {\n return this.customFetch ?? globalThis.fetch;\n }\n\n async downloadImage(url: string, pageTitle: string): Promise<ImageDownloadResult> {\n const maxRetries = this.maxRetries;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n if (attempt > 0) {\n await new Promise((r) => setTimeout(r, this.retryBaseMs * attempt));\n getLogger().info(\n `[Im-Nobsidian] 이미지 다운로드 재시도 (${attempt + 1}/${maxRetries}): ${pageTitle}`,\n );\n }\n const response = await this.fetchFn(url);\n if (!response.ok) {\n throw new Error(`이미지 다운로드 실패: ${response.status} ${response.statusText}`);\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"image/png\";\n const extension = IMAGE_EXTENSIONS[contentType] ?? this.guessExtension(url) ?? \".png\";\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\").slice(0, 12);\n const safeName = pageTitle\n .replace(/[^a-zA-Z0-9가-힣\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .slice(0, 50);\n\n const fileName = `${safeName}-${hash}${extension}`;\n const localPath = `${this.attachmentFolder}/${fileName}`;\n\n await this.vaultFs.ensureFolder(this.attachmentFolder);\n await this.vaultFs.writeBinary(localPath, buffer);\n\n return { originalUrl: url, localPath, hash, size: buffer.length };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError!;\n }\n\n async downloadAllImages(\n markdown: string,\n pageTitle: string,\n ): Promise<{ content: string; downloads: ImageDownloadResult[] }> {\n const imageRegex = /!\\[([^\\]]*)\\]\\((https?:\\/\\/[^)]+)\\)/g;\n const matches = [...markdown.matchAll(imageRegex)];\n const notionMatches = matches.filter((m) => m[2] && this.isNotionImageUrl(m[2]));\n\n const internalImageRegex = /!\\[([^\\]]*)\\]\\((file:\\/\\/%7B.*?%7D%7D)\\)/g;\n const internalMatches = [...markdown.matchAll(internalImageRegex)];\n\n if (notionMatches.length === 0 && internalMatches.length === 0) {\n return { content: markdown, downloads: [] };\n }\n\n const sema = new Sema(this.concurrency);\n const downloads: ImageDownloadResult[] = [];\n let result = markdown;\n\n const httpResults = await Promise.allSettled(\n notionMatches.map(async (match) => {\n await sema.acquire();\n try {\n return {\n match,\n download: await this.downloadImage(match[2]!, pageTitle),\n };\n } finally {\n sema.release();\n }\n }),\n );\n\n for (const settled of httpResults) {\n if (settled.status !== \"fulfilled\") continue;\n const { match, download } = settled.value;\n downloads.push(download);\n const obsidianEmbed = `![[${download.localPath}${match[1] ? `|${match[1]}` : \"\"}]]`;\n result = result.replace(match[0]!, obsidianEmbed);\n }\n\n for (const match of internalMatches) {\n await sema.acquire();\n try {\n const fileUrl = match[2]!;\n const parsed = this.parseNotionFileUrl(fileUrl);\n if (!parsed || !this.notionClient) continue;\n\n const realUrl = await this.notionClient.getFileBlockUrl(parsed.blockId);\n if (!realUrl) {\n getLogger().warn(`[Im-Nobsidian] 이미지 Block URL 조회 실패: ${parsed.fileName}`);\n continue;\n }\n\n const download = await this.downloadImage(realUrl, pageTitle);\n downloads.push(download);\n const obsidianEmbed = `![[${download.localPath}${match[1] ? `|${match[1]}` : \"\"}]]`;\n result = result.replace(match[0]!, obsidianEmbed);\n } catch (error) {\n getLogger().warn(`내부 이미지 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n return { content: result, downloads };\n }\n\n async uploadLocalImage(localPath: string): Promise<ImageUploadResult> {\n if (!this.notionClient) {\n throw new Error(\"NotionClient required for image upload\");\n }\n\n const buffer = await this.readImageFromVault(localPath);\n const filename = localPath.split(\"/\").pop() ?? \"image.png\";\n const contentType = this.getContentTypeFromPath(filename);\n const blob = new Blob([buffer], { type: contentType });\n const fileUploadId = await this.notionClient.uploadFile(blob, filename, contentType);\n // FileHandler.pushAllFiles 의 dedup 비교(전체 sha256)와 동일 산식으로 계산해 두 경로가\n // 같은 첨부를 동일 키로 인식하게 한다.\n const fileHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n\n return { localPath, fileUploadId, fileHash, fileSize: buffer.length };\n }\n\n async uploadAndAppendImages(\n pageId: string,\n images: ImageReference[],\n ): Promise<ImageUploadResult[]> {\n if (!this.notionClient) return [];\n\n const localImages = images.filter((img) => !img.isExternal && img.localPath);\n if (localImages.length === 0) return [];\n\n const results: ImageUploadResult[] = [];\n const imageBlocks: unknown[] = [];\n\n for (const img of localImages) {\n try {\n const result = await this.uploadLocalImage(img.localPath!);\n results.push(result);\n imageBlocks.push({\n type: \"image\",\n image: {\n type: \"file_upload\",\n file_upload: { id: result.fileUploadId },\n },\n });\n } catch (error) {\n getLogger().warn(`이미지 업로드 실패 (${img.localPath}):`, error);\n }\n }\n\n if (imageBlocks.length > 0) {\n await this.notionClient.appendChildren(pageId, imageBlocks);\n // 업로드 성공분을 file_registry 에 등록한다. 노트 임베드 이미지는 여기서(노트 페이지에)\n // 처리되므로, 이후 FileHandler.pushAllFiles 가 같은 첨부를 폴더 페이지에 standalone\n // 으로 재업로드하는 중복(I6 \"중복 업로드 0\" 위반)을 공유 레지스트리로 차단한다.\n // 단, replace_content(기본 push)는 노트 블록을 매번 wipe 하므로 임베드 이미지 블록은\n // 노트 본문이 바뀔 때마다 재업로드+재append 가 불가피하다(file_upload 1회용 + atomic\n // replace). 이는 블록 더블링/데이터 손실이 아니며, 무변경 재sync 는 변경감지가 스킵해\n // 재업로드 0 을 보장한다.\n if (this.stateDb) {\n for (const r of results) {\n try {\n this.stateDb.registerFile({\n localPath: r.localPath,\n notionPageId: pageId,\n fileUploadId: r.fileUploadId,\n fileType: \"image\",\n fileHash: r.fileHash,\n fileSize: r.fileSize,\n });\n } catch (error) {\n getLogger().warn(`이미지 레지스트리 등록 실패 (${r.localPath}):`, error);\n }\n }\n }\n }\n\n return results;\n }\n\n private async readImageFromVault(localPath: string): Promise<Buffer> {\n try {\n return await this.vaultFs.readBinary(localPath);\n } catch {\n return await this.vaultFs.readBinary(`${this.attachmentFolder}/${localPath}`);\n }\n }\n\n private getContentTypeFromPath(filename: string): string {\n const ext = filename.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n return (ext && EXTENSION_TO_MIME[ext]) ?? \"application/octet-stream\";\n }\n\n async downloadAllFiles(\n markdown: string,\n pageTitle: string,\n ): Promise<{ content: string; downloads: ImageDownloadResult[] }> {\n const mdLinkRegex = /\\[(?:📎|🎬|🎞|📄|🔊)\\s*([^\\]]*)\\]\\((https?:\\/\\/[^)]+)\\)/g;\n const mdHttpMatches = [...markdown.matchAll(mdLinkRegex)];\n const notionHttpMatches = mdHttpMatches.filter((m) => m[2] && this.isNotionFileUrl(m[2]));\n\n const mdInternalRegex = /\\[(?:📎|🎬|🎞|📄|🔊)\\s*([^\\]]*)\\]\\((file:\\/\\/%7B.*?%7D%7D)\\)/g;\n const mdInternalMatches = [...markdown.matchAll(mdInternalRegex)];\n\n const xmlHttpRegex =\n /<(?:file|video|audio|pdf)\\s+src=\"(https?:\\/\\/[^\"]+)\">([\\s\\S]*?)<\\/(?:file|video|audio|pdf)>/g;\n const xmlHttpMatches = [...markdown.matchAll(xmlHttpRegex)];\n const notionXmlHttpMatches = xmlHttpMatches.filter((m) => m[1] && this.isNotionFileUrl(m[1]));\n\n const xmlInternalRegex =\n /<(?:file|video|audio|pdf)\\s+src=\"(file:\\/\\/%7B.*?%7D%7D)\">([\\s\\S]*?)<\\/(?:file|video|audio|pdf)>/g;\n const xmlInternalMatches = [...markdown.matchAll(xmlInternalRegex)];\n\n const totalMatches =\n notionHttpMatches.length +\n mdInternalMatches.length +\n notionXmlHttpMatches.length +\n xmlInternalMatches.length;\n\n if (totalMatches === 0) {\n return { content: markdown, downloads: [] };\n }\n\n const sema = new Sema(this.concurrency);\n const downloads: ImageDownloadResult[] = [];\n let result = markdown;\n\n for (const match of notionHttpMatches) {\n await sema.acquire();\n try {\n const url = match[2]!;\n const caption = match[1]?.trim() || \"file\";\n const download = await this.downloadFile(url, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `[[${download.localPath}|${caption}]]`;\n result = result.replace(match[0]!, obsidianLink);\n } catch (error) {\n getLogger().warn(`파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n for (const match of mdInternalMatches) {\n await sema.acquire();\n try {\n const fileUrl = match[2]!;\n const parsed = this.parseNotionFileUrl(fileUrl);\n if (!parsed || !this.notionClient) continue;\n\n const blockId = parsed.blockId;\n const fileName = parsed.fileName;\n const realUrl = await this.notionClient.getFileBlockUrl(blockId);\n if (!realUrl) continue;\n\n const caption = fileName || match[1]?.trim() || \"file\";\n const download = await this.downloadFile(realUrl, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `[[${download.localPath}|${caption}]]`;\n result = result.replace(match[0]!, obsidianLink);\n } catch (error) {\n getLogger().warn(`내부 파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n for (const match of notionXmlHttpMatches) {\n await sema.acquire();\n try {\n const url = match[1]!;\n const caption = match[2]?.trim() || \"file\";\n const download = await this.downloadFile(url, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `[[${download.localPath}|${caption}]]`;\n result = result.replace(match[0]!, obsidianLink);\n } catch (error) {\n getLogger().warn(`파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n for (const match of xmlInternalMatches) {\n await sema.acquire();\n try {\n const fileUrl = match[1]!;\n const parsed = this.parseNotionFileUrl(fileUrl);\n if (!parsed || !this.notionClient) continue;\n\n const blockId = parsed.blockId;\n const fileName = parsed.fileName;\n const realUrl = await this.notionClient.getFileBlockUrl(blockId);\n if (!realUrl) continue;\n\n const caption = fileName || match[2]?.trim() || \"file\";\n const download = await this.downloadFile(realUrl, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `[[${download.localPath}|${caption}]]`;\n result = result.replace(match[0]!, obsidianLink);\n } catch (error) {\n getLogger().warn(`내부 파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n return { content: result, downloads };\n }\n\n private parseNotionFileUrl(fileUrl: string): { blockId: string; fileName: string } | null {\n try {\n const decoded = decodeURIComponent(fileUrl.replace(\"file://\", \"\"));\n const json = JSON.parse(decoded) as {\n source?: string;\n permissionRecord?: { id?: string };\n };\n const blockId = json.permissionRecord?.id ?? \"\";\n const source = json.source ?? \"\";\n const fileNameMatch = source.match(/attachment:[^:]+:(.+)$/);\n const fileName = fileNameMatch ? decodeURIComponent(fileNameMatch[1]!) : \"\";\n return blockId ? { blockId, fileName } : null;\n } catch {\n return null;\n }\n }\n\n private async downloadFile(\n url: string,\n _pageTitle: string,\n caption: string,\n ): Promise<ImageDownloadResult> {\n const maxRetries = this.maxRetries;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n if (attempt > 0) {\n await new Promise((r) => setTimeout(r, this.retryBaseMs * attempt));\n getLogger().info(\n `[Im-Nobsidian] 파일 다운로드 재시도 (${attempt + 1}/${maxRetries}): ${caption}`,\n );\n }\n const response = await this.fetchFn(url);\n if (!response.ok) {\n throw new Error(`파일 다운로드 실패: ${response.status} ${response.statusText}`);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n const MAX_FILE_SIZE = this.maxFileSizeBytes;\n if (contentLength && parseInt(contentLength, 10) > MAX_FILE_SIZE) {\n const sizeMB = Math.round(parseInt(contentLength, 10) / 1024 / 1024);\n getLogger().debug(`[Im-Nobsidian] 파일 스킵 — 너무 큼 (${sizeMB}MB): ${caption}`);\n return { originalUrl: url, localPath: \"\", hash: \"\", size: 0 };\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\").slice(0, 12);\n\n const extension = this.guessFileExtension(url, response.headers.get(\"content-type\"));\n const safeName = caption\n .replace(/[^a-zA-Z0-9가-힣\\s._-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .slice(0, 80);\n const fileName = `${safeName}-${hash}${extension}`;\n const localPath = `${this.attachmentFolder}/${fileName}`;\n\n await this.vaultFs.ensureFolder(this.attachmentFolder);\n await this.vaultFs.writeBinary(localPath, buffer);\n\n return { originalUrl: url, localPath, hash, size: buffer.length };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError!;\n }\n\n private isNotionImageUrl(url: string): boolean {\n return this.isNotionFileUrl(url);\n }\n\n private isNotionFileUrl(url: string): boolean {\n return (\n url.includes(\"secure.notion-static.com\") ||\n url.includes(\"prod-files-secure\") ||\n url.includes(\"s3.us-west-2.amazonaws.com/secure.notion-static.com\")\n );\n }\n\n private guessExtension(url: string): string | null {\n const pathname = new URL(url).pathname;\n const ext = pathname.match(/\\.(png|jpg|jpeg|gif|webp|svg|bmp|tiff)(\\?|$)/i);\n return ext ? `.${ext[1]!.toLowerCase()}` : null;\n }\n\n private guessFileExtension(url: string, contentType: string | null): string {\n try {\n const pathname = new URL(url).pathname;\n const extMatch = pathname.match(/\\.([a-zA-Z0-9]{1,10})(?:\\?|$)/);\n if (extMatch) return `.${extMatch[1]!.toLowerCase()}`;\n } catch {\n // URL 파싱 실패 시 MIME 타입으로 폴백\n }\n\n const mimeMap: Record<string, string> = {\n \"application/pdf\": \".pdf\",\n \"application/zip\": \".zip\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": \".xlsx\",\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\": \".pptx\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\": \".docx\",\n \"application/x-hwp\": \".hwp\",\n \"application/gzip\": \".gz\",\n };\n if (contentType && mimeMap[contentType]) return mimeMap[contentType]!;\n return \"\";\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { Sema } from \"async-sema\";\nimport type { VaultFS, NonMdFileInfo } from \"./vault-fs.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport { getLogger } from \"../utils/logger.js\";\n\nexport type NotionBlockType = \"image\" | \"pdf\" | \"video\" | \"audio\" | \"file\";\n\nexport interface FileUploadResult {\n readonly localPath: string;\n readonly fileUploadId: string;\n readonly blockType: NotionBlockType;\n}\n\nexport interface FileDownloadResult {\n readonly url: string;\n readonly localPath: string;\n readonly hash: string;\n readonly size: number;\n}\n\nconst EXTENSION_TO_BLOCK_TYPE: Record<string, NotionBlockType> = {\n \".png\": \"image\",\n \".jpg\": \"image\",\n \".jpeg\": \"image\",\n \".gif\": \"image\",\n \".svg\": \"image\",\n \".webp\": \"image\",\n \".ico\": \"image\",\n \".bmp\": \"image\",\n \".tiff\": \"image\",\n \".tif\": \"image\",\n \".avif\": \"image\",\n \".apng\": \"image\",\n \".heic\": \"image\",\n\n \".pdf\": \"pdf\",\n\n \".mp4\": \"video\",\n \".mov\": \"video\",\n \".webm\": \"video\",\n \".avi\": \"video\",\n \".mkv\": \"video\",\n \".flv\": \"video\",\n \".wmv\": \"video\",\n \".m4v\": \"video\",\n \".mpeg\": \"video\",\n \".ogv\": \"video\",\n \".3gp\": \"video\",\n\n \".mp3\": \"audio\",\n \".wav\": \"audio\",\n \".ogg\": \"audio\",\n \".m4a\": \"audio\",\n \".flac\": \"audio\",\n \".aac\": \"audio\",\n \".wma\": \"audio\",\n \".opus\": \"audio\",\n \".weba\": \"audio\",\n};\n\nconst EXTENSION_TO_MIME: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".bmp\": \"image/bmp\",\n \".ico\": \"image/x-icon\",\n \".tiff\": \"image/tiff\",\n \".tif\": \"image/tiff\",\n \".avif\": \"image/avif\",\n \".heic\": \"image/heic\",\n \".pdf\": \"application/pdf\",\n \".mp4\": \"video/mp4\",\n \".mov\": \"video/quicktime\",\n \".webm\": \"video/webm\",\n \".avi\": \"video/x-msvideo\",\n \".mkv\": \"video/x-matroska\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".ogg\": \"audio/ogg\",\n \".m4a\": \"audio/mp4\",\n \".flac\": \"audio/flac\",\n \".aac\": \"audio/aac\",\n \".docx\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n \".xlsx\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n \".pptx\": \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n \".zip\": \"application/zip\",\n \".gz\": \"application/gzip\",\n \".tar\": \"application/x-tar\",\n \".rar\": \"application/vnd.rar\",\n \".7z\": \"application/x-7z-compressed\",\n \".py\": \"text/x-python\",\n \".js\": \"text/javascript\",\n \".ts\": \"text/typescript\",\n \".json\": \"application/json\",\n \".csv\": \"text/csv\",\n \".txt\": \"text/plain\",\n \".html\": \"text/html\",\n \".xml\": \"application/xml\",\n \".hwp\": \"application/x-hwp\",\n \".xls\": \"application/vnd.ms-excel\",\n \".doc\": \"application/msword\",\n \".ppt\": \"application/vnd.ms-powerpoint\",\n};\n\nexport function getBlockType(filename: string): NotionBlockType {\n const ext = filename.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n if (!ext) return \"file\";\n return EXTENSION_TO_BLOCK_TYPE[ext] ?? \"file\";\n}\n\nexport function getMimeType(filename: string): string {\n const ext = filename.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n if (!ext) return \"application/octet-stream\";\n return EXTENSION_TO_MIME[ext] ?? \"application/octet-stream\";\n}\n\nfunction getFolderPath(filePath: string): string {\n const parts = filePath.split(\"/\");\n return parts.length > 1 ? parts.slice(0, -1).join(\"/\") : \"\";\n}\n\nexport class FileHandler {\n private readonly sema: Sema;\n\n constructor(\n private readonly vaultFs: VaultFS,\n private readonly notionClient: NotionClient,\n private readonly stateDb: IStateDB,\n concurrency: number = 2,\n ) {\n this.sema = new Sema(concurrency);\n }\n\n async pushFilesForFolder(folderPageId: string, folderPath: string): Promise<FileUploadResult[]> {\n const allFiles = await this.vaultFs.listNonMarkdownFiles();\n const folderFiles = allFiles.filter((f) => getFolderPath(f.path) === folderPath);\n\n if (folderFiles.length === 0) return [];\n\n const results: FileUploadResult[] = [];\n\n for (const file of folderFiles) {\n const existing = this.stateDb.getFileRegistry(file.path);\n if (existing) {\n if (existing.fileSize === file.size) continue;\n const buffer = await this.vaultFs.readBinary(file.path);\n const currentHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n if (existing.fileHash === currentHash) continue;\n }\n\n await this.sema.acquire();\n try {\n const result = await this.uploadFile(file, folderPageId);\n if (result) results.push(result);\n } catch (error) {\n getLogger().warn(`파일 업로드 실패 (${file.path}):`, error);\n } finally {\n this.sema.release();\n }\n }\n\n return results;\n }\n\n async pushAllFiles(): Promise<FileUploadResult[]> {\n const allFiles = await this.vaultFs.listNonMarkdownFiles();\n if (allFiles.length === 0) return [];\n\n const filesByFolder = new Map<string, NonMdFileInfo[]>();\n for (const file of allFiles) {\n const folder = getFolderPath(file.path);\n const list = filesByFolder.get(folder) ?? [];\n list.push(file);\n filesByFolder.set(folder, list);\n }\n\n const results: FileUploadResult[] = [];\n\n for (const [folderPath, files] of filesByFolder) {\n const folderRecord = folderPath\n ? this.stateDb.getByPath(folderPath)\n : this.stateDb.getByPath(\"__root__\");\n\n const folderPageId = folderRecord?.notionPageId;\n if (!folderPageId) {\n if (files.length > 0) {\n getLogger().debug(\n `폴더 페이지 없음, 파일 스킵: ${folderPath || \"(루트)\"} (${files.length}개)`,\n );\n }\n continue;\n }\n\n for (const file of files) {\n const existing = this.stateDb.getFileRegistry(file.path);\n if (existing) {\n if (existing.fileSize === file.size) continue;\n const buffer = await this.vaultFs.readBinary(file.path);\n const currentHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n if (existing.fileHash === currentHash) continue;\n }\n\n await this.sema.acquire();\n try {\n const result = await this.uploadFile(file, folderPageId);\n if (result) results.push(result);\n } catch (error) {\n getLogger().warn(`파일 업로드 실패 (${file.path}):`, error);\n } finally {\n this.sema.release();\n }\n }\n }\n\n return results;\n }\n\n async downloadFileBlock(\n url: string,\n filename: string,\n targetFolder: string,\n ): Promise<FileDownloadResult> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`파일 다운로드 실패: ${response.status} ${response.statusText}`);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n const localPath = targetFolder ? `${targetFolder}/${filename}` : filename;\n\n await this.vaultFs.ensureFolder(targetFolder || \".\");\n await this.vaultFs.writeBinary(localPath, buffer);\n\n return { url, localPath, hash, size: buffer.length };\n }\n\n async downloadFileBlocks(\n blocks: Array<{ type: string; url: string; caption?: string }>,\n targetFolder: string,\n ): Promise<FileDownloadResult[]> {\n const results: FileDownloadResult[] = [];\n\n for (const block of blocks) {\n const filename = this.extractFilename(block.url, block.caption);\n if (this.stateDb.isFileRegistered(`${targetFolder}/${filename}`)) continue;\n\n await this.sema.acquire();\n try {\n const result = await this.downloadFileBlock(block.url, filename, targetFolder);\n results.push(result);\n } catch (error) {\n getLogger().warn(`파일 다운로드 실패 (${block.url}):`, error);\n } finally {\n this.sema.release();\n }\n }\n\n return results;\n }\n\n private async uploadFile(\n file: NonMdFileInfo,\n parentPageId: string,\n ): Promise<FileUploadResult | null> {\n const buffer = await this.vaultFs.readBinary(file.path);\n const filename = file.path.split(\"/\").pop() ?? \"file\";\n const contentType = getMimeType(filename);\n const blockType = getBlockType(filename);\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n\n const blob = new Blob([buffer], { type: contentType });\n const fileUploadId = await this.notionClient.uploadFile(blob, filename, contentType);\n\n const block = this.createFileBlock(blockType, fileUploadId);\n await this.notionClient.appendChildren(parentPageId, [block]);\n\n this.stateDb.registerFile({\n localPath: file.path,\n notionPageId: parentPageId,\n fileUploadId,\n fileType: blockType,\n fileHash: hash,\n fileSize: file.size,\n });\n\n getLogger().info(`파일 업로드 완료: ${file.path} → ${blockType} 블록`);\n\n return { localPath: file.path, fileUploadId, blockType };\n }\n\n private createFileBlock(blockType: NotionBlockType, fileUploadId: string): unknown {\n const fileRef = {\n type: \"file_upload\" as const,\n file_upload: { id: fileUploadId },\n };\n\n switch (blockType) {\n case \"image\":\n return { type: \"image\", image: fileRef };\n case \"pdf\":\n return { type: \"pdf\", pdf: fileRef };\n case \"video\":\n return { type: \"video\", video: fileRef };\n case \"audio\":\n return { type: \"audio\", audio: fileRef };\n case \"file\":\n default:\n return { type: \"file\", file: fileRef };\n }\n }\n\n private extractFilename(url: string, caption?: string): string {\n if (caption) {\n const safe = caption.replace(/[^a-zA-Z0-9가-힣._\\s-]/g, \"\").trim();\n if (safe) return safe;\n }\n\n try {\n const pathname = new URL(url).pathname;\n const segments = pathname.split(\"/\");\n const last = segments[segments.length - 1];\n if (last && last.includes(\".\")) return decodeURIComponent(last);\n } catch {\n // fallback\n }\n\n const ext = url.match(/\\.(png|jpg|jpeg|gif|pdf|mp4|mp3|docx|xlsx|zip|webp)(\\?|$)/i);\n return `file-${Date.now()}${ext ? `.${ext[1]}` : \"\"}`;\n }\n}\n","import type { Conflict, ConflictStrategy, RemoteChange, SyncRecord } from \"../types/sync.js\";\nimport { computeHash } from \"../utils/hash.js\";\n\n/**\n * Pull 충돌 해소 시 취할 동작.\n * - `write`: 로컬을 리모트 내용으로 덮어쓴다 (로컬 미수정 또는 remote-first).\n * - `skip`: 로컬을 보존하고 리모트 내용을 버린다 (local-first).\n * - `conflict`: 양쪽 모두 수정됨 → 사용자 해소 대기 (manual/duplicate).\n */\nexport type PullConflictAction = \"write\" | \"skip\" | \"conflict\";\n\nexport interface PullConflictInput {\n /** 동기화 상태 레코드 (마지막 동기화 시점 해시·스냅샷 포함). */\n readonly record: SyncRecord;\n /** 디스크의 현재 로컬 내용 (파일 없으면 \"\"). */\n readonly localContent: string;\n /** Notion에서 가져와 변환한 리모트 내용. */\n readonly remoteContent: string;\n /** 충돌 객체 구성용 리모트 변경 메타. */\n readonly remoteChange: RemoteChange;\n /** 설정된 충돌 해소 전략. */\n readonly strategy: ConflictStrategy;\n}\n\nexport interface PullConflictResult {\n readonly action: PullConflictAction;\n /** action === \"conflict\" 일 때만 채워진다. */\n readonly conflict?: Conflict;\n /** 호출자가 재계산하지 않도록 제공하는 로컬 내용 해시. */\n readonly localHash: string;\n}\n\n/**\n * Pull 시 로컬 수정 여부를 판정하고 충돌 전략에 따라 동작을 결정하는 순수 함수.\n *\n * 마지막 동기화 이후 로컬이 수정되었는지(`localHash !== record.contentHash`)를 기준으로,\n * 수정되지 않았으면 안전하게 덮어쓰고, 수정되었으면 전략에 따라 보존/덮어쓰기/충돌을 반환한다.\n * 이 함수는 어떤 I/O도 수행하지 않으므로 orchestrator(일반 페이지)와 database-syncer(DB 행)가\n * 동일한 충돌 판정 로직을 공유한다.\n */\nexport function resolvePullConflict(input: PullConflictInput): PullConflictResult {\n const { record, localContent, remoteContent, remoteChange, strategy } = input;\n\n const localHash = computeHash(localContent);\n const localModified = localHash !== record.contentHash;\n\n // 로컬이 마지막 동기화 이후 변경되지 않았다면 충돌 없이 덮어쓰기 안전.\n if (!localModified) {\n return { action: \"write\", localHash };\n }\n\n // 로컬이 수정됨 → 전략에 따라 분기.\n if (strategy === \"remote-first\") {\n return { action: \"write\", localHash };\n }\n if (strategy === \"local-first\") {\n return { action: \"skip\", localHash };\n }\n\n // --- manual / duplicate: 충돌로 넘기기 전에 \"거짓 충돌\"부터 걸러낸다 ---\n\n // 양쪽 내용이 이미 동일하면 충돌이 아니다(동일 편집으로 수렴). 덮어써도 무손실이고\n // 상태를 synced 로 정리하므로 write 로 처리한다.\n if (localContent === remoteContent) {\n return { action: \"write\", localHash };\n }\n\n // 리모트 내용이 base(마지막 동기화 스냅샷)와 같으면 리모트는 실제로 변하지 않은 것이다.\n // (notion last_edited 만 갱신된 가짜 변경.) 로컬만 바뀌었으므로 로컬을 보존(skip)한다.\n // 이때 write 로 덮어쓰면 로컬의 새 편집이 옛 내용으로 사라진다 — 반드시 skip.\n const baseContent = record.baseSnapshot?.toString(\"utf-8\") ?? null;\n if (baseContent !== null && remoteContent === baseContent) {\n return { action: \"skip\", localHash };\n }\n\n // manual / duplicate → 충돌로 보존, 사용자 해소 대기.\n const conflict: Conflict = {\n syncRecord: record,\n localChange: {\n path: record.obsidianPath,\n type: \"modified\",\n currentHash: localHash,\n previousHash: record.contentHash,\n },\n remoteChange,\n baseContent,\n localContent,\n remoteContent,\n };\n\n return { action: \"conflict\", conflict, localHash };\n}\n","// eslint-disable-next-line no-control-regex\nconst INVALID_CHARS = /[<>:\"/\\\\|?*\\x00-\\x1f]/g;\n// 파일시스템상으로는 유효하지만 Obsidian 위키링크 문법(`[[제목]]`)을 깨는 문자(대괄호).\n// basename 에 `[`/`]` 가 남으면 그 basename 으로 만든 `[[..]]` 가 첫 `]]` 에서 조기 종료돼\n// 링크가 깨진다(예: 제목 \"Attention [2017]\" → `[[Attention [2017]]]`). 파일명 SSOT 인 이\n// 함수에서 한 번 봉합하면 단일 변환·후처리·relation 경로가 모두 안전해진다(M5). 파일시스템\n// 무효 문자(INVALID_CHARS)와는 관심사가 다르므로 상수를 분리한다. 별칭 구분자 `|` 는 이미\n// INVALID_CHARS 가 처리한다.\nconst WIKILINK_UNSAFE_CHARS = /[[\\]]/g;\nconst TRAILING_DOTS = /\\.+$/;\nconst RESERVED_NAMES = new Set([\n \"CON\",\n \"PRN\",\n \"AUX\",\n \"NUL\",\n \"COM1\",\n \"COM2\",\n \"COM3\",\n \"COM4\",\n \"COM5\",\n \"COM6\",\n \"COM7\",\n \"COM8\",\n \"COM9\",\n \"LPT1\",\n \"LPT2\",\n \"LPT3\",\n \"LPT4\",\n \"LPT5\",\n \"LPT6\",\n \"LPT7\",\n \"LPT8\",\n \"LPT9\",\n]);\n\nexport function sanitizeFileName(name: string): string {\n let sanitized = name\n .replace(INVALID_CHARS, \"_\")\n .replace(WIKILINK_UNSAFE_CHARS, \"_\")\n .replace(TRAILING_DOTS, \"\")\n .trim()\n .slice(0, 200);\n\n if (RESERVED_NAMES.has(sanitized.toUpperCase())) {\n sanitized = `_${sanitized}`;\n }\n\n if (sanitized.length === 0) {\n sanitized = \"_untitled\";\n }\n\n return sanitized;\n}\n","import { notionIdsEqual } from \"./id.js\";\n\n/** {@link resolveDbRowPath} 가 경로 점유 여부를 조회하기 위한 최소 레코드 형태. */\nexport interface PathOwner {\n notionPageId: string | null;\n}\n\n/** {@link selectDbRowFiles} 입력의 최소 형태(경로만 필요). */\nexport interface VaultPathRef {\n readonly path: string;\n}\n\n/**\n * DB 폴더의 **직속(depth 1)** 행 파일만 고른다 — 중첩 하위 폴더는 제외한다.\n *\n * DB 행은 항상 `localFolder/<name>.md` 로 **평탄하게** 기록된다({@link resolveDbRowPath}).\n * 하위 폴더(`localFolder/SubDB/...`)는 **별도 child_database** 이거나 자식 페이지 본문이라\n * 부모 DB 의 행이 아니다. `path.startsWith(prefix)` 단순 매칭은 이 중첩 파일까지 부모 행으로\n * **오포함(over-inclusion)** 한다:\n * - 뷰(I9): 하위 DB 의 행이 부모 갤러리/테이블/보드에 카드로 새어 든다.\n * - push: 하위 DB 행을 부모 DB 로 잘못 밀어 중복 생성·오배치를 낸다.\n * `selectStaleDbArtifacts` 와 동일한 \"직속만 — 중첩 DB 보호\" 규칙(`rel` 에 `/` 없음)을 적용한다.\n * 폴더 경계도 정확히 본다: `localFolder` 가 `databases/tasks` 면 형제 폴더\n * `databases/tasks2/x.md` 는 `databases/tasks/` prefix 에 걸리지 않아 자연히 제외된다.\n *\n * 입력은 이미 마크다운으로 필터된 목록을 가정한다(확장자 재검증 안 함). 결정적: 입력 순서\n * 보존, 부수효과 없음.\n *\n * @param files 볼트의 마크다운 파일 참조 목록(경로 기준)\n * @param localFolder DB 폴더 경로(확장자·후행 슬래시 무관)\n */\nexport function selectDbRowFiles<T extends VaultPathRef>(\n files: ReadonlyArray<T>,\n localFolder: string,\n): T[] {\n const prefix = localFolder.endsWith(\"/\") ? localFolder : `${localFolder}/`;\n return files.filter((file) => {\n if (!file.path.startsWith(prefix)) return false;\n const rel = file.path.slice(prefix.length);\n return rel.length > 0 && !rel.includes(\"/\");\n });\n}\n\n/**\n * DB 행 파일 경로를 충돌 없이 결정한다.\n *\n * 같은 DB 에 동명 페이지(예: 제목이 비어 \"제목 없음\" 으로 수렴하는 행들)가 여럿\n * 있으면 Notion 페이지 ID 조각으로 디스앰비규에이션한다. 단 ID 앞 8 글자는 같은\n * DB 안에서 **유일하지 않다** — 노션 페이지 ID 는 생성 시각 기반이라 앞자리가\n * 비랜덤이어서, 같은 DB 의 두 동명 페이지가 같은 8 글자 prefix 를 갖는 일이 흔하다.\n * 단일 8 글자 접미사만 쓰면 두 페이지가 **동일 경로**로 귀결되어\n * ① 한 페이지가 다른 페이지의 파일을 덮어써 데이터가 유실되고\n * ② 매 pull 마다 두 페이지가 같은 파일을 두고 핑퐁하여 멱등성(churn 0)이 깨진다.\n *\n * 따라서 후보 경로가 *다른* 페이지에 이미 점유되어 있으면 ID 조각을 8→16→32 로\n * 넓혀 유일 경로를 찾는다. 두 페이지의 ID 는 불변이므로 항상 같은 경로로 수렴 →\n * 한 번 배정된 뒤에는 sync_state 에 경로가 고정되어(다음 pull 은 기존 레코드 경로\n * 재사용) churn 이 발생하지 않는다.\n *\n * @param localFolder DB 폴더 경로 (확장자·슬래시 없는 디렉터리)\n * @param safeName sanitize 된 파일명(확장자 제외)\n * @param pageId 대상 Notion 페이지 ID (하이픈 유무 무관)\n * @param lookupByPath 후보 경로의 현재 소유 레코드를 돌려주는 조회 함수(없으면 null)\n */\nexport function resolveDbRowPath(\n localFolder: string,\n safeName: string,\n pageId: string,\n lookupByPath: (path: string) => PathOwner | null,\n): string {\n const ownedBySelf = (candidate: string): boolean => {\n const owner = lookupByPath(candidate);\n // 점유자가 없으면 비어 있는 경로 → 사용 가능.\n // 점유자의 ID 가 비어 있으면(레코드 손상 등) 자기 소유로 단정하지 않고 회피한다.\n if (!owner) return true;\n return owner.notionPageId != null && notionIdsEqual(owner.notionPageId, pageId);\n };\n\n const natural = `${localFolder}/${safeName}.md`;\n if (ownedBySelf(natural)) return natural;\n\n const raw = pageId.replace(/-/g, \"\");\n for (const len of [8, 16, 32]) {\n const candidate = `${localFolder}/${safeName} (${raw.slice(0, len)}).md`;\n if (ownedBySelf(candidate)) return candidate;\n }\n\n // 전체 ID(32 글자)는 전역 유일하므로 위 루프에서 반드시 반환된다.\n // 도달 불가 경로이나 방어적으로 전체 ID 접미사를 반환한다.\n return `${localFolder}/${safeName} (${raw}).md`;\n}\n","/**\n * Obsidian 위키링크가 실제로 해소하는 대상 이름(파일 basename, `.md` 제거)을 경로에서 도출한다.\n *\n * 변환 단일 패스(`resolvePageId` 로 페이지 멘션→`[[제목]]`)와 후처리 패스\n * (`resolveNotionLinks` 의 본문 링크·frontmatter relation 해소)가 **동일한 규칙**으로\n * 위키링크 텍스트를 만들도록 강제하는 SSOT.\n *\n * 과거엔 단일 패스가 StateDB 의 원시 제목(`.title`)을, 후처리 패스가 sanitize 된\n * basename 을 써서 같은 페이지가 서로 다른 `[[..]]` 텍스트로 해소됐다 — 원시 제목에\n * 슬래시·콜론 등 파일명 금지문자가 있으면 단일 패스 링크가 실제 파일을 못 가리키는\n * 깨진/이중 위키링크가 됐다(M4). 두 경로 모두 이 함수를 통과시켜 불일치를 차단한다.\n */\nexport function wikilinkTitleFromPath(obsidianPath: string): string {\n return obsidianPath.replace(/\\.md$/i, \"\").split(\"/\").pop() ?? \"\";\n}\n","import type { DatabaseViewsConfig, ViewConfig } from \"../types/view.js\";\n\nexport interface BasePropertySchema {\n readonly id: string;\n readonly type: string;\n readonly options?: Array<{ name: string; color?: string }>;\n readonly groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n}\n\nexport interface BaseFileOptions {\n readonly databaseId: string;\n readonly databaseName: string;\n readonly schema: Record<string, BasePropertySchema>;\n readonly viewsConfig: DatabaseViewsConfig;\n readonly folderPath: string;\n}\n\nexport type BasesViewType = \"table\" | \"cards\" | \"list\";\n\n/**\n * Notion 뷰 타입 → Obsidian Bases 뷰 타입 매핑(SSOT).\n *\n * `null` = Bases 에 대응 뷰가 없어 `.base` 로 표현 불가. 이 경우 해당 뷰는 `.base` 에서\n * 누락되므로, 사이드카(`<db>.notion.json`)가 원본 뷰 설정을 무손실 보존한다\n * (Notion API 는 뷰 생성/수정을 지원하지 않아 뷰는 pull-authoritative — push 로 되돌릴 수\n * 없으므로 \"조용한 유실 금지\"는 곧 \"보존 + 정직한 degrade 리포트\"를 의미한다).\n */\nexport const NOTION_TO_BASES_VIEW: Record<string, BasesViewType | null> = {\n table: \"table\",\n gallery: \"cards\",\n list: \"list\",\n board: \"cards\",\n calendar: null,\n timeline: null,\n form: null,\n chart: null,\n map: null,\n dashboard: null,\n};\n\n/** Notion 뷰 타입의 Bases 대응 타입을 돌려준다. 미지원/미상 타입은 `null`. */\nexport function basesViewTypeOf(notionType: string): BasesViewType | null {\n return NOTION_TO_BASES_VIEW[notionType] ?? null;\n}\n\nexport class BaseFileGenerator {\n generate(options: BaseFileOptions): string {\n const lines: string[] = [];\n\n lines.push(`# Auto-generated by Im-Nobsidian from Notion DB: ${options.databaseName}`);\n lines.push(`# Database ID: ${options.databaseId}`);\n lines.push(\"\");\n\n this.writeFilters(lines, options.folderPath);\n this.writeFormulas(lines, options.viewsConfig.views);\n this.writePropertyDisplayNames(lines, options.schema);\n this.writeViews(lines, options.viewsConfig.views, options.schema);\n\n // YAML 파일은 말미 개행으로 끝낸다(POSIX 텍스트 관례·diff 안정성).\n return lines.join(\"\\n\") + \"\\n\";\n }\n\n private writeFilters(lines: string[], folderPath: string): void {\n lines.push(\"filters:\");\n lines.push(\" and:\");\n lines.push(` - file.inFolder(\"${folderPath}\")`);\n // `.base` 파일 자신도 폴더에 있어 카드로 잡히므로(빈 카드) markdown 노트만 남긴다.\n lines.push(` - file.ext == \"md\"`);\n lines.push(\"\");\n }\n\n private needsContentCoverFormula(views: ViewConfig[]): boolean {\n return views.some(\n (v) =>\n v.type === \"gallery\" &&\n v.cover &&\n (v.cover.type === \"page_content\" || v.cover.type === \"page_content_first\"),\n );\n }\n\n private writeFormulas(lines: string[], views: ViewConfig[]): void {\n if (!this.needsContentCoverFormula(views)) return;\n\n lines.push(\"formulas:\");\n lines.push(\" coverImage: file.embeds[0]\");\n lines.push(\"\");\n }\n\n private writePropertyDisplayNames(\n lines: string[],\n schema: Record<string, BasePropertySchema>,\n ): void {\n const entries = Object.entries(schema).filter(([, prop]) => prop.type !== \"title\");\n if (entries.length === 0) return;\n\n lines.push(\"properties:\");\n for (const [name] of entries) {\n lines.push(` ${this.yamlKey(name)}:`);\n lines.push(` displayName: ${this.yamlValue(name)}`);\n }\n lines.push(\"\");\n }\n\n private writeViews(\n lines: string[],\n views: ViewConfig[],\n schema: Record<string, BasePropertySchema>,\n ): void {\n const basesViews = views\n .map((v) => this.convertView(v, schema))\n .filter((v): v is NonNullable<typeof v> => v !== null);\n\n if (basesViews.length === 0) {\n lines.push(\"views:\");\n lines.push(\" - type: table\");\n lines.push(\" name: Table\");\n return;\n }\n\n // Obsidian Bases 는 뷰 이름 유일성을 요구한다. Notion 은 이름 없는 뷰를 'Untitled'로\n // 반환하므로(동명 다수 발생) 중복 시 ' 2','3'… 접미사로 유일화한다. 미적용 시 Bases 가\n // 동명 뷰를 하나로 합치거나 무시해 갤러리·표 뷰가 사라진다.\n this.dedupeViewNames(basesViews);\n\n lines.push(\"views:\");\n for (const view of basesViews) {\n lines.push(` - type: ${view.type}`);\n lines.push(` name: ${this.yamlValue(view.name)}`);\n\n if (view.order && view.order.length > 0) {\n lines.push(\" order:\");\n for (const col of view.order) {\n lines.push(` - ${this.propRef(col)}`);\n }\n }\n\n if (view.sort && view.sort.length > 0) {\n lines.push(\" sort:\");\n for (const s of view.sort) {\n // Bases 정렬 항목의 키는 `property`다(`column` 아님 — Obsidian이 무시함).\n lines.push(` - property: ${this.propRef(s.property)}`);\n lines.push(` direction: ${s.direction}`);\n }\n }\n\n if (view.groupBy) {\n lines.push(\" groupBy:\");\n lines.push(` property: ${this.propRef(view.groupBy.property)}`);\n if (view.groupBy.direction) {\n lines.push(` direction: ${view.groupBy.direction}`);\n }\n }\n\n if (view.image) {\n lines.push(` image: ${this.propRef(view.image)}`);\n }\n }\n }\n\n /**\n * 뷰 이름을 Bases 요구사항대로 유일화한다(in-place). 동명 충돌 시 ' 2',' 3'… 를 붙이되\n * 이미 존재하는 이름과 다시 충돌하지 않을 때까지 증가시킨다.\n */\n private dedupeViewNames(views: Array<{ name: string }>): void {\n const used = new Set<string>();\n for (const v of views) {\n let name = v.name;\n if (used.has(name)) {\n let n = 2;\n while (used.has(`${v.name} ${n}`)) n++;\n name = `${v.name} ${n}`;\n }\n used.add(name);\n v.name = name;\n }\n }\n\n private convertView(\n view: ViewConfig,\n schema: Record<string, BasePropertySchema>,\n ): {\n type: BasesViewType;\n name: string;\n order?: string[];\n sort?: Array<{ property: string; direction: string }>;\n groupBy?: { property: string; direction?: string };\n image?: string;\n } | null {\n const basesType = NOTION_TO_BASES_VIEW[view.type];\n if (!basesType) return null;\n\n const result: {\n type: BasesViewType;\n name: string;\n order?: string[];\n sort?: Array<{ property: string; direction: string }>;\n groupBy?: { property: string; direction?: string };\n image?: string;\n } = {\n type: basesType,\n name: view.name || view.type,\n };\n\n if (view.properties && view.properties.length > 0) {\n const visible = view.properties\n .filter((p) => p.visible !== false)\n .map((p) => {\n const name = p.propertyName ?? this.resolvePropertyName(p.propertyId, schema);\n if (!name) return null;\n // title 타입 속성은 카드/표 제목(file.name)과 중복되고, 프론트매터엔\n // title 키가 없어(본문 H1·파일명으로 보존) 빈 컬럼으로 표시되므로 제외한다.\n if (schema[name]?.type === \"title\") return null;\n return this.toNoteRef(name);\n })\n .filter((name): name is string => !!name);\n\n if (visible.length > 0) {\n result.order = [\"file.name\", ...visible];\n }\n }\n\n if (view.sorts && view.sorts.length > 0) {\n result.sort = view.sorts\n .map((s) => {\n let property: string;\n if (s.property) {\n const propName = this.resolvePropertyName(s.property, schema) ?? s.property;\n property = this.toNoteRef(propName);\n } else if (s.timestamp) {\n property = s.timestamp === \"created_time\" ? \"file.ctime\" : \"file.mtime\";\n } else {\n return null;\n }\n return {\n property,\n direction: s.direction === \"ascending\" ? \"ASC\" : \"DESC\",\n };\n })\n .filter((s): s is NonNullable<typeof s> => s !== null);\n }\n\n if (view.groupBy) {\n const propName =\n view.groupBy.propertyName ?? this.resolvePropertyName(view.groupBy.propertyId, schema);\n if (propName) {\n result.groupBy = {\n property: this.toNoteRef(propName),\n direction:\n view.groupBy.sort === \"ascending\"\n ? \"ASC\"\n : view.groupBy.sort === \"descending\"\n ? \"DESC\"\n : undefined,\n };\n }\n }\n\n if (view.type === \"gallery\" && view.cover) {\n if (view.cover.type === \"property\" && view.cover.propertyId) {\n const propName = this.resolvePropertyName(view.cover.propertyId, schema);\n if (propName) result.image = this.toNoteRef(propName);\n } else if (view.cover.type === \"page_cover\") {\n result.image = \"note.cover\";\n } else if (view.cover.type === \"page_content\" || view.cover.type === \"page_content_first\") {\n result.image = \"formula.coverImage\";\n }\n }\n\n return result;\n }\n\n private toNoteRef(propertyName: string): string {\n return propertyName;\n }\n\n /**\n * 속성 참조(order/sort/groupBy/image)를 YAML로 안전하게 출력한다.\n * `file.name`·`formula.coverImage`·`note.cover` 같은 접두사 식별자와 공백 포함 일반 속성명은\n * 평문 스칼라로 안전하므로 그대로 두고, 콜론·해시·따옴표 등 YAML 메타문자가 있을 때만 인용한다.\n */\n private propRef(ref: string): string {\n if (/^[A-Za-z0-9_][A-Za-z0-9_. ]*$/.test(ref) && !ref.endsWith(\" \")) return ref;\n return `\"${ref.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n }\n\n private resolvePropertyName(\n propertyId: string,\n schema: Record<string, BasePropertySchema>,\n ): string | undefined {\n // Notion `views.retrieve` 는 RAW 속성 id(예: `[jiM`)를 주지만\n // `databases.retrieve` 스키마는 URL-인코딩된 id(예: `%5BjiM`)를 준다.\n // 디코드 후 비교하지 않으면 \"title\" 외 모든 속성(cover/order/sort/groupBy)이\n // 매칭에 실패해 갤러리 커버·표시 컬럼이 통째로 사라진다.\n const target = this.decodeId(propertyId);\n for (const [name, prop] of Object.entries(schema)) {\n if (this.decodeId(prop.id) === target) return name;\n }\n return undefined;\n }\n\n private decodeId(id: string): string {\n try {\n return decodeURIComponent(id);\n } catch {\n return id;\n }\n }\n\n private yamlKey(key: string): string {\n if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) return key;\n return `\"${key.replace(/\"/g, '\\\\\"')}\"`;\n }\n\n private yamlValue(value: string): string {\n if (/^[a-zA-Z0-9_-]+$/.test(value)) return value;\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n }\n}\n","import type { DatabaseViewsConfig, ViewConfig } from \"../types/view.js\";\nimport {\n basesViewTypeOf,\n type BasePropertySchema,\n type BasesViewType,\n} from \"./base-file-generator.js\";\n\n/**\n * DB 사이드카(`<db>.notion.json`) — `.base` 로 표현할 수 없는 Notion DB 메타데이터를\n * 무손실 보존하는 단일 파일.\n *\n * ## 왜 필요한가 (I4·I7 \"조용한 유실 금지\")\n *\n * Obsidian Bases(`.base`)는 Notion DB 뷰의 일부만 표현한다:\n * · 미지원 뷰(calendar/timeline/form/chart/map/dashboard)는 `.base` 에서 통째 누락.\n * · 표현되는 뷰도 Notion **필터식·커버 크기/비율·컬럼 width/wrap·빈그룹 숨김** 등은\n * Bases 문법에 대응이 없어 손실된다.\n *\n * Notion API 는 뷰 생성/수정을 지원하지 않으므로(뷰는 pull-authoritative) 이 메타데이터는\n * push 로 Notion 에 되돌릴 수 없다. 따라서 \"무손실\"의 의미는 **로컬에 완전·정직하게\n * 보존하고, 무엇이 degrade 됐는지 명시 리포트**하는 것이다. 사이드카는 이를 `.base` 와\n * 같은 폴더에 co-locate 해 사람이 발견 가능하고 도구가 재사용 가능하게 만든다.\n *\n * ## 멱등성\n *\n * 매 pull 마다 재생성되므로 **결정적**이어야 한다(타임스탬프·실행시각 금지, 키 정렬).\n * 동일 DB 상태 → 동일 바이트 → drift 0 / churn 0.\n */\nexport interface NotionSidecar {\n readonly generator: \"im-nobsidian\";\n readonly schemaVersion: 1;\n readonly databaseId: string;\n readonly databaseName: string;\n /** 속성 스키마 — 이름 정렬. `.base` displayName 만으로는 잃는 타입/옵션을 보존. */\n readonly properties: SidecarProperty[];\n /** 모든 뷰(표현/미표현 공통) — Notion 순서 유지. */\n readonly views: SidecarView[];\n /** 정직한 손실 리포트 — 무엇이 `.base` 에서 누락/degrade 됐는가. */\n readonly degraded: DegradeNote[];\n}\n\nexport interface SidecarProperty {\n readonly name: string;\n readonly id: string;\n readonly type: string;\n /** select/multi_select/status 옵션명(있으면). */\n readonly options?: string[];\n}\n\nexport interface SidecarView {\n readonly id: string;\n readonly name: string;\n readonly notionType: string;\n /** Bases 대응 타입. `null` = `.base` 미표현(사이드카가 유일 보존처). */\n readonly basesType: BasesViewType | null;\n /** 원본 뷰 설정 중 의미 있는 항목(키 정렬). 빈 값은 생략. */\n readonly config: Record<string, unknown>;\n}\n\nexport interface DegradeNote {\n readonly view: string;\n readonly kind: \"view-unrepresentable\" | \"setting-dropped\";\n readonly detail: string;\n}\n\n/** `.base` 가 표현하지 못해 사이드카로만 보존되는 뷰 설정 키 → 사람용 사유. */\nconst DROPPED_SETTING_REASONS: Record<string, string> = {\n filter: \"Notion 필터식은 .base 로 표현되지 않음(폴더 필터만 적용)\",\n coverSize: \"갤러리 커버 크기는 Bases 미지원\",\n coverAspect: \"갤러리 커버 비율은 Bases 미지원\",\n viewRange: \"캘린더 표시 범위(week/month)는 Bases 미지원\",\n columnWidths: \"컬럼 너비(width)는 Bases 미지원\",\n columnWraps: \"컬럼 줄바꿈(wrap)은 Bases 미지원\",\n hideEmptyGroups: \"빈 그룹 숨김은 Bases 미지원\",\n};\n\nexport class SidecarGenerator {\n /**\n * 사이드카 객체를 빌드한다(순수 — I/O 없음). 직렬화는 {@link serialize} 가 담당.\n */\n build(options: {\n databaseId: string;\n databaseName: string;\n schema: Record<string, BasePropertySchema>;\n viewsConfig: DatabaseViewsConfig;\n }): NotionSidecar {\n const degraded: DegradeNote[] = [];\n\n const properties = this.buildProperties(options.schema);\n const views = options.viewsConfig.views.map((v) => this.buildView(v, degraded));\n\n // 정직성·안정성: 리포트를 (뷰명, kind, detail) 로 정렬해 결정적 순서 보장.\n degraded.sort(\n (a, b) =>\n a.view.localeCompare(b.view) ||\n a.kind.localeCompare(b.kind) ||\n a.detail.localeCompare(b.detail),\n );\n\n return {\n generator: \"im-nobsidian\",\n schemaVersion: 1,\n databaseId: options.databaseId,\n databaseName: options.databaseName,\n properties,\n views,\n degraded,\n };\n }\n\n /**\n * 사이드카를 결정적 JSON 문자열로 직렬화한다(키 재귀 정렬 + 말미 개행).\n * 동일 입력 → 동일 바이트 → 멱등(drift/churn 0).\n */\n serialize(sidecar: NotionSidecar): string {\n return stableStringify(sidecar) + \"\\n\";\n }\n\n private buildProperties(schema: Record<string, BasePropertySchema>): SidecarProperty[] {\n return Object.entries(schema)\n .map(([name, prop]): SidecarProperty => {\n const options = prop.options?.map((o) => o.name).filter((n) => n.length > 0);\n return {\n name,\n id: prop.id,\n type: prop.type,\n ...(options && options.length > 0 ? { options } : {}),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n }\n\n private buildView(view: ViewConfig, degraded: DegradeNote[]): SidecarView {\n const basesType = basesViewTypeOf(view.type);\n const viewName = view.name || view.type;\n\n if (basesType === null) {\n degraded.push({\n view: viewName,\n kind: \"view-unrepresentable\",\n detail: `'${view.type}' 뷰는 Obsidian Bases 대응이 없어 .base 에서 누락 — 사이드카로만 보존`,\n });\n }\n\n const config = this.extractConfig(view, basesType, viewName, degraded);\n\n return {\n id: view.id,\n name: viewName,\n notionType: view.type,\n basesType,\n config,\n };\n }\n\n /**\n * 뷰 설정 중 의미 있는 항목을 추출한다. `.base` 가 표현 못하는 항목(필터·커버크기 등)은\n * config 에 보존하면서 동시에 degrade 리포트에 1줄씩 기록한다(표현되는 뷰에 한해 —\n * 미표현 뷰는 이미 view-unrepresentable 로 통째 보고됨).\n */\n private extractConfig(\n view: ViewConfig,\n basesType: BasesViewType | null,\n viewName: string,\n degraded: DegradeNote[],\n ): Record<string, unknown> {\n const config: Record<string, unknown> = {};\n const noteDrop = (key: string): void => {\n if (basesType !== null && DROPPED_SETTING_REASONS[key]) {\n degraded.push({\n view: viewName,\n kind: \"setting-dropped\",\n detail: DROPPED_SETTING_REASONS[key]!,\n });\n }\n };\n\n if (view.filter !== undefined && view.filter !== null) {\n config[\"filter\"] = view.filter;\n noteDrop(\"filter\");\n }\n if (view.sorts && view.sorts.length > 0) config[\"sorts\"] = view.sorts;\n if (view.groupBy) {\n config[\"groupBy\"] = view.groupBy;\n if (view.groupBy.hideEmptyGroups) noteDrop(\"hideEmptyGroups\");\n }\n if (view.cover) config[\"cover\"] = view.cover;\n if (view.coverSize) {\n config[\"coverSize\"] = view.coverSize;\n noteDrop(\"coverSize\");\n }\n if (view.coverAspect) {\n config[\"coverAspect\"] = view.coverAspect;\n noteDrop(\"coverAspect\");\n }\n if (view.datePropertyId) config[\"datePropertyId\"] = view.datePropertyId;\n if (view.datePropertyName) config[\"datePropertyName\"] = view.datePropertyName;\n if (view.viewRange) {\n config[\"viewRange\"] = view.viewRange;\n noteDrop(\"viewRange\");\n }\n\n if (view.properties && view.properties.length > 0) {\n config[\"properties\"] = view.properties;\n if (view.properties.some((p) => p.width !== undefined)) noteDrop(\"columnWidths\");\n if (view.properties.some((p) => p.wrap !== undefined)) noteDrop(\"columnWraps\");\n }\n\n return config;\n }\n}\n\n/**\n * 키를 재귀 정렬한 결정적 JSON 직렬화기. 배열 순서는 보존(뷰/속성의 원본 순서가 유의미),\n * 객체 키만 사전순 정렬해 동일 입력에 동일 바이트를 보장한다.\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortKeys(value), null, 2);\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value !== null && typeof value === \"object\") {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>).sort()) {\n sorted[key] = sortKeys((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n","/**\n * DB 산출물(`.base`/사이드카 `.notion.json`) rename 고아 정리 — 순수 선택 로직.\n *\n * Notion DB 제목이 바뀌면 산출물 파일명(`sanitizeFileName(title)`)이 바뀌어 옛 이름의\n * `.base`·`.notion.json` 이 **같은 폴더에 고아로 잔존**한다. 이는 pull 멱등을 깨고\n * (drift) 삭제 검증에서 부활(resurrection)로 잡히는 결함이다. 본 모듈은 어떤 파일을\n * 삭제 대상으로 고를지를 **부수효과 없이 결정**한다(테스트·재사용 용이).\n */\n\n/** 볼트 파일 참조의 최소 형태(경로만 필요). */\nexport interface VaultFileRef {\n readonly path: string;\n}\n\n/** DB 폴더 직속에서 정리 대상이 되는 산출물 확장자. */\nconst ARTIFACT_SUFFIXES = [\".base\", \".notion.json\"] as const;\n\n/**\n * `localFolder` **직속**의 고아 `.base`/`.notion.json` 경로를 고른다.\n *\n * 규칙:\n * - `localFolder/` 로 시작하고 그 뒤에 `/` 가 없는 **직속 파일만** 대상 — 하위 폴더(중첩 DB)의\n * 산출물은 각자의 DB 동기화가 관리하므로 절대 건드리지 않는다.\n * - 확장자가 `.base` 또는 `.notion.json` 인 것만.\n * - `keepPaths` 에 포함된 **현재 산출물**은 제외.\n *\n * 결정적: 입력 순서를 보존해 반환(멱등·테스트 안정). 부수효과 없음.\n */\nexport function selectStaleDbArtifacts(\n files: ReadonlyArray<VaultFileRef>,\n localFolder: string,\n keepPaths: ReadonlySet<string>,\n): string[] {\n const prefix = `${localFolder}/`;\n const stale: string[] = [];\n for (const file of files) {\n const path = file.path;\n if (!path.startsWith(prefix)) continue;\n const rel = path.slice(prefix.length);\n if (rel.includes(\"/\")) continue; // 폴더 직속만 — 중첩 DB 산출물 보호\n if (!ARTIFACT_SUFFIXES.some((suffix) => rel.endsWith(suffix))) continue;\n if (keepPaths.has(path)) continue;\n stale.push(path);\n }\n return stale;\n}\n","import {\n MARKER_BRAND_RE,\n compactMarker,\n TOGGLE_START,\n TOGGLE_END,\n WIKILINK_PROTOCOL,\n} from \"../constants/markers.js\";\n\nconst NOTION_CALLOUT_RE = /^::: callout\\n([\\s\\S]*?)\\n:::/gm;\nconst NOTION_PAGE_MENTION_RE = /<mention-page id=\"([^\"]+)\">([\\s\\S]*?)<\\/mention-page>/g;\nconst NOTION_USER_MENTION_RE = /<mention-user id=\"[^\"]*\">([^<]*)<\\/mention-user>/g;\nconst NOTION_DATE_MENTION_RE = /<mention-date start=\"([^\"]*)\"(?: end=\"([^\"]*)\")?[^>]*\\/>/g;\nconst NOTION_UNKNOWN_RE = /<unknown id=\"([^\"]*)\"([^>]*)\\/>/g;\nconst NOTION_UNKNOWN_URL_RE = /<unknown url=\"([^\"]*)\"([^>]*)\\/>/g;\n\nconst NOTION_AUDIO_RE = /[\\t ]*<audio src=\"([^\"]*)\">([\\s\\S]*?)<\\/audio>/g;\nconst NOTION_VIDEO_RE = /[\\t ]*<video src=\"([^\"]*)\">([\\s\\S]*?)<\\/video>/g;\nconst NOTION_PDF_RE = /[\\t ]*<pdf src=\"([^\"]*)\">([\\s\\S]*?)<\\/pdf>/g;\nconst NOTION_FILE_RE = /[\\t ]*<file src=\"([^\"]*)\">([\\s\\S]*?)<\\/file>/g;\nconst NOTION_TAB_RE = /<tab title=\"([^\"]*)\">([\\s\\S]*?)<\\/tab>/g;\n\nexport function notionEnhancedToObsidian(enhanced: string): string {\n let result = enhanced;\n\n result = convertSyncedBlockRef(result);\n result = normalizeCodeBlockToggles(result);\n result = convertContainers(result);\n result = convertFencedCallouts(result);\n result = convertPageMentions(result);\n result = convertPageLinks(result);\n result = convertUserMentions(result);\n result = convertDateMentions(result);\n result = convertMediaTags(result);\n result = convertTabBlocks(result);\n result = preserveUnknownBlocks(result);\n result = convertNotionMath(result);\n result = convertNotionTables(result);\n result = convertSpans(result);\n result = convertDatabaseBlocks(result);\n result = cleanInlineColorAttrs(result);\n result = removeEmptyBlocks(result);\n result = unescapePipes(result);\n result = unescapeNotionChars(result);\n result = unescapeWikilinkBrackets(result);\n result = ensureCalloutContinuity(result);\n\n return result;\n}\n\n// Notion markdown API 는 평문 위키링크 `[[..]]` 를 `\\[\\[..\\]\\]` 로 escape 저장한다.\n// (resolved 위키링크는 mention 이 되어 이 경로를 타지 않고, unresolved 만 평문으로 보존됨)\n// pull 시 escape 를 해제해 Obsidian 위키링크 기능과 push↔pull 수렴을 보장한다.\nfunction unescapeWikilinkBrackets(content: string): string {\n return content.replace(/\\\\\\[\\\\\\[([\\s\\S]*?)\\\\\\]\\\\\\]/g, \"[[$1]]\");\n}\n\nexport function obsidianToNotionEnhanced(obsidian: string): string {\n let result = obsidian;\n\n result = convertTogglesToHtml(result);\n result = restoreTabBlocks(result);\n result = convertObsidianCallouts(result);\n result = restoreMediaTags(result);\n result = restoreUnknownBlocks(result);\n result = restoreColorSpans(result);\n result = restoreUnderlineSpans(result);\n result = convertMentionPageIdToUrl(result);\n result = restoreWikilinkPreserveLinks(result);\n\n return result;\n}\n\n// ─── Push 방향: 위키링크 → Notion markdown API 호환 표현 ───\n//\n// 배경: Notion 공식 markdown API(`pages.create({markdown})`, `updateMarkdown`)는\n// - `<mention-page id=\"X\">label</mention-page>` 를 **통째로 삭제**한다(레이블까지 소실).\n// - `<mention-page url=\"https://www.notion.so/<id>\"/>` 만 진짜 page mention 으로 인식한다.\n// - 커스텀 스킴 링크(`[label](im-nobsidian://wikilink/..)`)는 링크를 버리고 텍스트만 남긴다.\n// - 평문 `[[target]]` 는 텍스트로 escape 보존되어 round-trip 시 정확히 복원된다.\n// 따라서 파이프라인(WikilinkResolver)이 만든 표현을 위 규칙에 맞게 한 번 더 변환한다.\n\nconst MENTION_PAGE_ID_RE = /<mention-page id=\"([^\"]+)\">[\\s\\S]*?<\\/mention-page>/g;\nconst WIKILINK_PRESERVE_LINK_RE = new RegExp(\n `\\\\[([^\\\\]]+)\\\\]\\\\(${WIKILINK_PROTOCOL}([^)]+)\\\\)`,\n \"g\",\n);\n\n// resolved 위키링크: id 기반 mention → Notion 이 수용하는 url 기반 mention 으로 변환\nfunction convertMentionPageIdToUrl(content: string): string {\n return content.replace(MENTION_PAGE_ID_RE, (_match, id: string) => {\n const nohyph = id.replace(/-/g, \"\");\n return `<mention-page url=\"https://www.notion.so/${nohyph}\"/>`;\n });\n}\n\n// unresolved 위키링크: preserve-link → 평문 위키링크 (Notion 이 텍스트로 보존, round-trip 수렴)\nfunction restoreWikilinkPreserveLinks(content: string): string {\n return content.replace(WIKILINK_PRESERVE_LINK_RE, (_match, label: string, enc: string) => {\n let target = enc;\n try {\n target = decodeURIComponent(enc);\n } catch {\n // 잘못 인코딩된 경우 원문 유지\n }\n return target === label ? `[[${target}]]` : `[[${target}|${label}]]`;\n });\n}\n\n/**\n * 코드펜스 본문에 나타나는 가장 긴 백틱 런보다 1 이상 긴 펜스를 만든다(최소 3).\n *\n * CommonMark fenced-code 규칙: 본문에 펜스와 같은 길이의 백틱 런이 있으면 그 지점에서\n * 코드블록이 조기 종료된다. 토글/콜아웃 본문에 마크다운 예제(펜스 포함)가 들어가는 경우\n * 3-백틱 고정 펜스는 깨지므로, 본문을 스캔해 안전한 펜스 길이를 동적으로 결정한다.\n */\nfunction fenceFor(body: string): string {\n let longest = 0;\n const re = /`+/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body)) !== null) longest = Math.max(longest, m[0].length);\n return \"`\".repeat(Math.max(3, longest + 1));\n}\n\n/**\n * 컨테이너(토글/콜아웃) 본문을 blockquote(`> `)로 감싸기 전에 적용하는 dedent.\n *\n * Notion Markdown API 는 `<details>`/callout 의 직계 자식을 중첩 깊이만큼 탭으로\n * 들여쓴다. 특히 **코드블록은 펜스 줄만 탭으로 들여쓰고 내부 코드 텍스트는 열 0 에\n * 그대로 둔다(비대칭 들여쓰기)** — 실제 Notion 출력에서 확인된 구조다:\n *\n * ```\n * <details>\n * <summary>제목</summary>\n * \\t```javascript ← 펜스만 탭 들여쓰기\n * 코드 본문 (열 0) ← 내부 텍스트는 들여쓰기 없음\n * \\t```\n * </details>\n * ```\n *\n * 이 들여쓰기를 둔 채 `> ` 를 붙이면 펜스가 `> \\t``` ` 가 되어 CommonMark 펜스 규칙\n * (들여쓰기 ≤3칸, 탭=4칸)을 위반한다. 그러면 코드블록이 열리거나 닫히지 않아 렌더링이\n * 깨지고, 닫는 펜스가 무시되면 이후 본문 전체를 코드로 삼키는 cascade 가 된다(결함①).\n *\n * 공통 선행 들여쓰기만 제거하는 단순 dedent 는 이 비대칭 구조를 고치지 못한다(코드\n * 본문이 열 0 이라 공통 최소값이 0 → 무변경). **테이블도 동일한 비대칭**을 보인다:\n * `<table>` 태그만 깊게 들여쓰고 내부 `<tr>/<td>` 행은 열 0 에 둔다. 이 열 0 행이 공통\n * 최소값을 0 으로 끌어내려, 같은 본문의 형제 줄(리스트·문단)까지 구조적 탭을 못 벗는\n * prefix/탭 폭주가 된다(결함②). 따라서 코드블록·테이블 블록을 인식해 다르게 처리한다:\n * - **경계 줄(코드펜스 / <table>·</table>)**: 선행 들여쓰기를 모두 제거해 열 0 으로 정렬.\n * - **블록 내부(코드 본문 / 테이블 행)**: 의미·열정렬을 위해 원문 그대로 보존.\n * - **그 외(산문)**: 공통 선행 들여쓰기만 제거(중첩 리스트 등 상대 들여쓰기는 보존).\n * 공통 최소값은 **산문 줄만**으로 계산하므로 열 0 의 코드·테이블 행에 오염되지 않는다.\n * 앞뒤 빈 줄은 정리하고, 공백만 있는 줄은 비운다.\n */\nfunction dedentContainerBody(text: string): string {\n const lines = text.split(\"\\n\");\n while (lines.length && lines[0]!.trim() === \"\") lines.shift();\n while (lines.length && lines[lines.length - 1]!.trim() === \"\") lines.pop();\n\n // 1패스: 코드블록·테이블 경계를 추적해 각 줄을 분류한다.\n type LineKind = \"fence\" | \"code\" | \"prose\";\n const kinds: LineKind[] = [];\n let inCode = false;\n let fenceChar = \"\";\n let fenceLen = 0;\n let inTable = false;\n for (const line of lines) {\n const fence = /^[\\t ]*(`{3,}|~{3,})(.*)$/.exec(line);\n if (inCode) {\n if (\n fence &&\n fence[1]![0] === fenceChar &&\n fence[1]!.length >= fenceLen &&\n fence[2]!.trim() === \"\"\n ) {\n inCode = false;\n kinds.push(\"fence\");\n } else {\n kinds.push(\"code\");\n }\n } else if (inTable) {\n const closes = /<\\/table>/.test(line);\n kinds.push(closes ? \"fence\" : \"code\");\n if (closes) inTable = false;\n } else if (fence) {\n inCode = true;\n fenceChar = fence[1]![0]!;\n fenceLen = fence[1]!.length;\n kinds.push(\"fence\");\n } else if (/^[\\t ]*<table[^>]*>/.test(line)) {\n // <table> 태그만 깊게 들여쓰고 내부 행은 열 0 인 비대칭 구조. 한 줄에서 닫히지\n // 않으면 테이블 모드로 진입해 행을 보존, 닫는 </table> 도 경계로 열 0 정렬한다.\n if (!/<\\/table>/.test(line)) inTable = true;\n kinds.push(\"fence\");\n } else {\n kinds.push(\"prose\");\n }\n }\n\n // 2패스: 산문 줄의 공통 선행 들여쓰기 계산(상대 들여쓰기 보존 — textwrap.dedent 의미론).\n let min = Infinity;\n lines.forEach((l, i) => {\n if (kinds[i] !== \"prose\" || l.trim() === \"\") return;\n min = Math.min(min, /^[\\t ]*/.exec(l)![0].length);\n });\n if (!Number.isFinite(min)) min = 0;\n\n // 3패스: 경계(fence)→열0 정렬, 내부(code)→원문 보존, 산문(prose)→공통 들여쓰기 제거.\n return lines\n .map((l, i) => {\n if (l.trim() === \"\") return \"\";\n if (kinds[i] === \"code\") return l;\n if (kinds[i] === \"fence\") return l.replace(/^[\\t ]+/, \"\");\n return l.slice(min);\n })\n .join(\"\\n\");\n}\n\nfunction normalizeCodeBlockToggles(content: string): string {\n // 여는/닫는 펜스의 들여쓰기를 가변(`[\\t ]*`)으로 일반화하고, 펜스 길이(`{3,}`)를\n // 백레퍼런스로 대칭 매칭한다. 중첩 토글(두 탭 들여쓰기)·긴 펜스 케이스도 변환된다.\n return content.replace(\n /^[\\t ]*- (.+)\\n[\\t ]*(`{3,})(\\w*)\\n([\\s\\S]*?)\\n[\\t ]*\\2[\\t ]*$/gm,\n (_match, title: string, _open: string, lang: string, rawBody: string) => {\n const body = dedentContainerBody(rawBody);\n const fence = fenceFor(body);\n return `<details>\\n<summary>${title.trim()}</summary>\\n${fence}${lang}\\n${body}\\n${fence}\\n</details>`;\n },\n );\n}\n\n// ── 컨테이너(토글/콜아웃/칼럼) 통합 변환 ──────────────────────────────────────\n//\n// Notion Markdown API 는 <details>/<callout>/<columns> 를 중첩 깊이만큼 탭으로 들여쓴\n// 직계 자식으로 표현한다. 타입별로 분리된 순차 패스로 처리하면 두 문제가 생긴다:\n// (1) 교차 중첩(콜아웃-in-칼럼-in-토글)을 한 패스가 다룰 수 없다.\n// (2) 안쪽 컨테이너를 먼저 풀며 그 선행 들여쓰기를 열 0 으로 당기면, 부모 본문의\n// 들여쓰기가 불균등해져 dedent 공통최소값이 0 → 구조적 탭이 살아남아\n// `> \\t\\t…` prefix/탭 폭주가 된다(결함②). 또한 평면 비탐욕 정규식은 중첩 콜아웃을\n// 잘못 짝지어(바깥 열림 ↔ 안쪽 닫힘) 고아 태그를 남겼다.\n//\n// 해결: 타입 불문 \"가장 안쪽\" 컨테이너부터 한 루프에서 변환한다. body 패턴이 내부에\n// 어떤 컨테이너 시작 태그도 없음을 부정선읽기로 보장하므로(콜아웃 SPAN 과 동일 관용),\n// 매 패스의 매치는 항상 최내곽이다. 각 컨테이너의 선행 들여쓰기를 캡처해 본문 변환 후\n// 출력의 모든 줄에 **다시 입혀**, 변환 결과가 형제 줄과 같은 깊이에 머물게 한다. 그러면\n// 부모의 dedent 가 그 레벨을 통째로 균등 제거한다. 변환 결과엔 컨테이너 태그가 없으므로\n// 다음 패스에서 부모가 새 innermost 가 되어 임의 깊이·교차 중첩이 올바른 순서로 환원된다.\n\n// body: 내부에 어떤 컨테이너 시작 태그도 없는(=가장 안쪽) 구간. 부정선읽기가 START 태그만\n// 차단하므로 비탐욕 *? 가 자신의 닫는 태그에서 멈춘다(</callout> 등은 차단되지 않음).\nconst NO_CONTAINER_BODY = \"(?:(?!<details>|<callout|<columns>)[\\\\s\\\\S])*?\";\n\n// <summary> 제목: 첫 </summary> 에서 반드시 멈추고 중첩 컨테이너 시작 태그를 넘지 않는다.\n// 단순 `[\\s\\S]*?` 는 본문이 닫는 태그에 도달 못 할 때 첫 </summary> 너머로 백트랙해\n// 바깥 토글을 안쪽 </summary>/</details> 와 잘못 짝짓는다(중첩 토글 mis-pair, 결함②).\nconst SUMMARY_TITLE = \"((?:(?!<\\\\/summary>|<details>|<summary>)[\\\\s\\\\S])*?)\";\n\nconst INNERMOST_DETAILS_RE = new RegExp(\n `([\\\\t ]*)<details>\\\\s*<summary>${SUMMARY_TITLE}<\\\\/summary>(${NO_CONTAINER_BODY})<\\\\/details>`,\n \"g\",\n);\nconst INNERMOST_CALLOUT_RE = new RegExp(\n `([\\\\t ]*)<callout[^>]*>\\\\n?(${NO_CONTAINER_BODY})<\\\\/callout>`,\n \"g\",\n);\nconst INNERMOST_COLUMNS_RE = new RegExp(\n `([\\\\t ]*)<columns>\\\\n?(${NO_CONTAINER_BODY})<\\\\/columns>`,\n \"g\",\n);\nconst COLUMN_WRAP_RE = /[\\t ]*<column>\\n?([\\s\\S]*?)[\\t ]*<\\/column>\\n?/g;\n\n// 캡처한 선행 들여쓰기를 변환 결과의 비어있지-않은 모든 줄에 다시 입힌다.\nfunction reindentLines(text: string, indent: string): string {\n if (!indent) return text;\n return text\n .split(\"\\n\")\n .map((line) => (line === \"\" ? line : indent + line))\n .join(\"\\n\");\n}\n\n// <details> → > [!toggle]- (본문은 dedent 후 `> ` prefix). dedent 가 코드펜스를 열 0 으로\n// 정렬해 `> \\t``` ` cascade 를 차단하고(결함①), 부모 패스에서 다시 `> ` 가 입혀지면\n// `> > ` 형태의 올바른 Obsidian 중첩이 된다.\nfunction toggleToCallout(title: string, rawBody: string): string {\n const body = dedentContainerBody(rawBody);\n const calloutBody = body\n .split(\"\\n\")\n .map((line) => (line.trim() ? `> ${line}` : \">\"))\n .join(\"\\n\");\n return `> [!toggle]- ${title.trim()}\\n${calloutBody}`;\n}\n\n// <columns>/<column> → 평탄화. Obsidian 엔 칼럼 문법이 없어 각 칼럼 본문을 dedent 로\n// 구조적 탭까지 벗긴 뒤 빈 줄로 구분해 이어붙인다(결함②: 탭 하나만 벗기던 기존 동작 교체).\nfunction flattenColumns(body: string): string {\n const cols: string[] = [];\n const re = new RegExp(COLUMN_WRAP_RE.source, COLUMN_WRAP_RE.flags);\n let m: RegExpExecArray | null;\n let matched = false;\n while ((m = re.exec(body)) !== null) {\n matched = true;\n const col = dedentContainerBody(m[1]!);\n if (col.trim() !== \"\") cols.push(col);\n }\n // <column> 래퍼가 전혀 없을 때만 폴백 dedent. 래퍼가 있으나 모두 빈 칼럼이면 cols=[] →\n // \"\" 반환(태그 제거됨). 폴백을 cols.length===0 으로 걸면 빈 칼럼의 <column> 태그가 샌다.\n if (!matched) return dedentContainerBody(body);\n return cols.join(\"\\n\\n\");\n}\n\nfunction convertContainers(content: string): string {\n let result = content;\n let safety = 0;\n while (\n safety++ < 2000 &&\n (result.includes(\"<details>\") || result.includes(\"<callout\") || result.includes(\"<columns>\"))\n ) {\n const before = result;\n result = result.replace(\n INNERMOST_DETAILS_RE,\n (_m, indent: string, title: string, body: string) =>\n reindentLines(toggleToCallout(title, body), indent),\n );\n result = result.replace(INNERMOST_CALLOUT_RE, (_m, indent: string, body: string) =>\n reindentLines(calloutBodyToObsidian(body), indent),\n );\n result = result.replace(INNERMOST_COLUMNS_RE, (_m, indent: string, body: string) =>\n reindentLines(flattenColumns(body), indent),\n );\n if (result === before) break;\n }\n return result;\n}\n\nfunction calloutBodyToObsidian(body: string): string {\n // 콜아웃 본문도 토글과 동일한 코드펜스 cascade 위험이 있으므로 같은 dedent 를 적용한다.\n const lines = dedentContainerBody(body)\n .split(\"\\n\")\n .filter((l, i, arr) => !(i === 0 && l === \"\") && !(i === arr.length - 1 && l === \"\"));\n const firstLine = lines[0] ?? \"\";\n\n const emojiMatch = /^([\\p{Emoji}️‍]+)\\s*(.*)/u.exec(firstLine);\n const type = emojiMatch ? emojiToCalloutType(emojiMatch[1]!) : \"note\";\n const title = emojiMatch ? emojiMatch[2]! : firstLine;\n const rest = lines.slice(1).join(\"\\n\").trim();\n\n const calloutTitle = title ? `> [!${type}] ${title}` : `> [!${type}]`;\n const calloutBody = rest\n ? \"\\n\" +\n rest\n .split(\"\\n\")\n .map((line) => (line.trim() ? `> ${line}` : \">\"))\n .join(\"\\n\")\n : \"\";\n\n return calloutTitle + calloutBody;\n}\n\n// 푸시 측 내부 표현인 `::: callout` 펜스 폼만 처리한다(탭 중첩이 아니라 폭주 없음).\n// Notion 풀 API 의 <callout> 태그는 convertContainers 가 담당한다.\nfunction convertFencedCallouts(content: string): string {\n return content.replace(NOTION_CALLOUT_RE, (_match, body: string) => calloutBodyToObsidian(body));\n}\n\nfunction convertPageMentions(content: string): string {\n let result = content.replace(NOTION_PAGE_MENTION_RE, (_match, _id: string, text: string) => {\n const cleaned = text.trim();\n return `[[${cleaned}]]`;\n });\n // url 기반 page mention 은 두 형태로 온다:\n // - self-closing `<mention-page url=\"..32hex..\"/>`\n // - 라벨 동반(breadcrumb 등) `<mention-page url=\"..32hex..\">제목</mention-page>`\n // 둘 다 page id 로 환원해 `[[notion:id]]` 로 만들고, 후처리 resolveNotionLinks 가 정식\n // 제목으로 해소한다. mention 라벨은 항상 대상 페이지의 현재 제목이므로 id 해소가 SSOT —\n // 라벨을 버려도 무손실이며, 같은 줄의 다른 위키링크와 일관된 표현이 된다.\n // (`[^>]*?` 는 `>` 를 넘지 않는 lazy 매치, alternation 으로 self-closing/라벨형을 한 번에 처리)\n result = result.replace(\n /<mention-page\\s+url=\"https?:\\/\\/(?:www\\.)?notion\\.so\\/([a-f0-9]{32})\"[^>]*?(?:\\/>|>[\\s\\S]*?<\\/mention-page>)/g,\n (_match, id: string) => `[[notion:${id}]]`,\n );\n return result;\n}\n\nfunction convertUserMentions(content: string): string {\n return content.replace(NOTION_USER_MENTION_RE, (_match, name: string) => `@${name}`);\n}\n\nfunction convertDateMentions(content: string): string {\n return content.replace(NOTION_DATE_MENTION_RE, (_match, start: string, end?: string) => {\n return end ? `${start} → ${end}` : start;\n });\n}\n\n// 2D: <unknown> → 보존 마커 (삭제 대신 보존)\nfunction preserveUnknownBlocks(content: string): string {\n let result = content.replace(NOTION_UNKNOWN_RE, (_match, id: string, attrs: string) => {\n const typeMatch = /type=\"([^\"]*)\"/.exec(attrs);\n const altMatch = /alt=\"([^\"]*)\"/.exec(attrs);\n const blockType = altMatch?.[1] ?? typeMatch?.[1] ?? \"unknown\";\n return compactMarker(`unknown:id=${id}&type=${blockType}`);\n });\n result = result.replace(NOTION_UNKNOWN_URL_RE, (_match, url: string, attrs: string) => {\n const altMatch = /alt=\"([^\"]*)\"/.exec(attrs);\n const blockType = altMatch?.[1] ?? \"bookmark\";\n const marker = compactMarker(`unknown:id=${encodeURIComponent(url)}&type=${blockType}`);\n // URL 을 가진 임베드/북마크는 읽기뷰에서 보이지 않는 주석 마커만 남기면\n // 사용자가 \"왜 빈 줄이지?\" 하고 혼란스럽다. 클릭 가능한 링크를 앞에 붙이되,\n // round-trip 권위는 뒤따르는 마커(인코딩된 원본 URL)가 갖는다. 링크와 마커는\n // 공백 없이 즉시 인접시켜, 역변환 시 한 쌍으로 같이 제거 → Notion drift 방지.\n const label =\n blockType === \"embed\"\n ? \"🔗 Embed\"\n : blockType === \"bookmark\"\n ? \"🔖 Bookmark\"\n : `🔗 ${blockType}`;\n return `[${label}](${url})${marker}`;\n });\n return result;\n}\n\nfunction convertSyncedBlockRef(content: string): string {\n let result = content.replace(\n /<synced_block_reference[^>]*>[\\s\\S]*?<\\/synced_block_reference>/g,\n (match) => {\n const inner = match\n .replace(/<synced_block_reference[^>]*>\\n?/, \"\")\n .replace(/<\\/synced_block_reference>/, \"\")\n .split(\"\\n\")\n .map((l) => l.replace(/^\\t/, \"\"))\n .join(\"\\n\")\n .trim();\n return inner;\n },\n );\n result = result.replace(\n /<synced_block[^>]*>\\n?([\\s\\S]*?)<\\/synced_block>/g,\n (_match, inner: string) => inner.trim(),\n );\n return result;\n}\n\n// 2A: 미디어 태그 → Obsidian 마크다운\nfunction convertMediaTags(content: string): string {\n let result = content;\n\n result = result.replace(NOTION_AUDIO_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[🔊 ${cap}](${src})` : `[🔊 audio](${src})`;\n });\n\n result = result.replace(NOTION_VIDEO_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[🎬 ${cap}](${src})` : `[🎬 video](${src})`;\n });\n\n result = result.replace(NOTION_PDF_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[📄 ${cap}](${src})` : `[📄 pdf](${src})`;\n });\n\n result = result.replace(NOTION_FILE_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[📎 ${cap}](${src})` : `[📎 file](${src})`;\n });\n\n return result;\n}\n\n// 2B: <tab> → 보존 마커\nfunction convertTabBlocks(content: string): string {\n return content.replace(NOTION_TAB_RE, (_match, title: string, body: string) => {\n const trimmed = body.trim();\n const indented = trimmed\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n return `> [!tab] ${title}\\n${indented}`;\n });\n}\n\n// 2C: <span underline> / <span color> → 보존 마커 (균형 매칭, 중첩 안전)\n//\n// 비탐욕 단일 정규식(`<span ...>([\\s\\S]*?)</span>`)은 중첩 span 에서 첫 `</span>` 에\n// 멈춰 바깥 span 의 닫는 토큰 순서를 뒤집는다(rank6/I3 — 사용자가 보는 Obsidian 마커가\n// `%%/color%%%%/underline%%` 처럼 잘못 중첩됨). 대신 **안쪽(중첩 없는) span 부터** 마커로\n// 치환한다: 마커엔 `<span` 이 없으므로 다음 패스에서 바깥 span 이 다시 innermost 가 되어\n// 임의 깊이 중첩이 올바른 순서로 환원된다. body 패턴 `(?:(?!<span )[\\s\\S])*?` 가 내부에\n// 또 다른 span 시작이 없음을 보장해 \"가장 안쪽\"만 매칭한다.\nconst INNERMOST_SPAN_RE =\n /<span (?:underline=\"true\"|color=\"([^\"]+)\")>((?:(?!<span )[\\s\\S])*?)<\\/span>/g;\n\nfunction convertSpans(content: string): string {\n let result = content;\n let safety = 0;\n while (safety++ < 1000) {\n const next = result.replace(\n INNERMOST_SPAN_RE,\n (_match, color: string | undefined, inner: string) =>\n color !== undefined\n ? `${compactMarker(`color:${color}`)}${inner}%%/color%%`\n : `${compactMarker(\"underline\")}${inner}%%/underline%%`,\n );\n if (next === result) break;\n result = next;\n }\n return result;\n}\n\nfunction convertTogglesToHtml(content: string): string {\n const calloutToggleRe = /^> \\[!toggle\\]-\\s*(.+)\\n((?:>.*\\n?)*)/gm;\n\n let result = content;\n let prev = \"\";\n let safety = 0;\n while (result !== prev && safety++ < 100) {\n prev = result;\n result = result.replace(calloutToggleRe, (_match, title: string, body: string) => {\n const bodyText = body\n .split(\"\\n\")\n .map((line) => line.replace(/^>\\s?/, \"\"))\n .join(\"\\n\")\n .trim();\n return `<details>\\n<summary>${title.trim()}</summary>\\n\\n${bodyText}\\n\\n</details>`;\n });\n }\n\n const startRe = new RegExp(escapeRegex(TOGGLE_START), \"g\");\n const endRe = new RegExp(escapeRegex(TOGGLE_END), \"g\");\n\n safety = 0;\n while (result.includes(TOGGLE_START) && safety++ < 100) {\n const startIdx = result.indexOf(TOGGLE_START);\n const endIdx = findMatchingEnd(result, startIdx + TOGGLE_START.length);\n if (endIdx === -1) break;\n\n const inner = result.slice(startIdx + TOGGLE_START.length, endIdx).trim();\n const titleMatch = /^- (.+)$/m.exec(inner);\n const title = titleMatch ? titleMatch[1]! : \"\";\n const body = inner\n .split(\"\\n\")\n .slice(1)\n .map((line) => line.replace(/^ {2}/, \"\"))\n .join(\"\\n\")\n .trim();\n\n const html = `<details>\\n<summary>${title}</summary>\\n\\n${body}\\n\\n</details>`;\n result = result.slice(0, startIdx) + html + result.slice(endIdx + TOGGLE_END.length);\n }\n\n result = result.replace(startRe, \"\").replace(endRe, \"\");\n return result;\n}\n\nfunction findMatchingEnd(content: string, startFrom: number): number {\n let depth = 1;\n let pos = startFrom;\n\n while (pos < content.length && depth > 0) {\n const nextStart = content.indexOf(TOGGLE_START, pos);\n const nextEnd = content.indexOf(TOGGLE_END, pos);\n\n if (nextEnd === -1) return -1;\n\n if (nextStart !== -1 && nextStart < nextEnd) {\n depth++;\n pos = nextStart + TOGGLE_START.length;\n } else {\n depth--;\n if (depth === 0) return nextEnd;\n pos = nextEnd + TOGGLE_END.length;\n }\n }\n\n return -1;\n}\n\nfunction convertObsidianCallouts(content: string): string {\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n let i = 0;\n\n while (i < lines.length) {\n const headerMatch = /^> \\[!(\\w+)\\]([-+])?\\s*(.*)/.exec(lines[i]!);\n if (headerMatch) {\n const type = headerMatch[1]!;\n const title = headerMatch[3]!;\n const emoji = calloutTypeToEmoji(type) ?? \"💡\";\n const calloutTitle = title ? `${emoji} ${title}` : emoji;\n\n const bodyLines: string[] = [];\n i++;\n while (i < lines.length && lines[i]!.startsWith(\"> \")) {\n bodyLines.push(lines[i]!.slice(2));\n i++;\n }\n\n result.push(\"::: callout\");\n result.push(calloutTitle);\n if (bodyLines.length > 0) {\n result.push(...bodyLines);\n }\n result.push(\":::\");\n } else {\n result.push(lines[i]!);\n i++;\n }\n }\n\n return result.join(\"\\n\");\n}\n\nconst EMOJI_TYPE_MAP: Record<string, string> = {\n \"💡\": \"tip\",\n ℹ️: \"info\",\n \"⚠️\": \"warning\",\n \"🔥\": \"danger\",\n \"✅\": \"success\",\n \"❌\": \"failure\",\n \"❓\": \"question\",\n \"📝\": \"note\",\n \"📌\": \"abstract\",\n \"🐛\": \"bug\",\n \"💬\": \"quote\",\n \"📋\": \"example\",\n};\n\nconst TYPE_EMOJI_MAP: Record<string, string> = Object.fromEntries(\n Object.entries(EMOJI_TYPE_MAP).map(([k, v]) => [v, k]),\n);\n\nfunction emojiToCalloutType(emoji: string): string {\n return EMOJI_TYPE_MAP[emoji] ?? \"note\";\n}\n\nfunction calloutTypeToEmoji(type: string): string | undefined {\n return TYPE_EMOJI_MAP[type.toLowerCase()];\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst NOTION_PAGE_LINK_RE = /<page url=\"[^\"]*\">([\\s\\S]*?)<\\/page>/g;\nconst NOTION_EMPTY_BLOCK_RE = /^(?:>[\\t ]*)*[\\t ]*<empty-block\\/>\\n?/gm;\n\nfunction convertPageLinks(content: string): string {\n return content.replace(NOTION_PAGE_LINK_RE, (_match, text: string) => {\n const cleaned = text.replace(/\\*\\*/g, \"\").trim();\n return `[[${cleaned}]]`;\n });\n}\n\nfunction convertDatabaseBlocks(content: string): string {\n return content.replace(\n /<database[^>]*>([\\s\\S]*?)<\\/database>/g,\n (_match, title: string) => `**${title.trim()}** *(Notion DB)*`,\n );\n}\n\nfunction cleanInlineColorAttrs(content: string): string {\n return content.replace(/\\s*\\{color=\"[^\"]*\"\\}/g, \"\");\n}\n\nfunction removeEmptyBlocks(content: string): string {\n return content.replace(NOTION_EMPTY_BLOCK_RE, \"\\n\");\n}\n\nconst NOTION_INLINE_MATH_RE = /\\$`([^`]+)`\\$/g;\nconst NOTION_BLOCK_MATH_RE = /\\$\\$\\n```\\n([\\s\\S]*?)\\n```\\n\\$\\$/g;\n\nfunction convertNotionMath(content: string): string {\n let result = content.replace(NOTION_BLOCK_MATH_RE, (_match, eq: string) => {\n return `$$\\n${eq.trim()}\\n$$`;\n });\n result = result.replace(NOTION_INLINE_MATH_RE, (_match, eq: string) => `$${eq}$`);\n result = result.replace(/\\\\\\$([^$]+?)\\\\\\$/g, (_match, inner: string) => {\n const unescaped = inner.replace(/\\\\\\^/g, \"^\").replace(/\\\\~/g, \"~\");\n return `$${unescaped}$`;\n });\n return result;\n}\n\nfunction unescapeNotionChars(content: string): string {\n return content.replace(/\\\\~/g, \"~\").replace(/\\\\\\^/g, \"^\");\n}\n\nconst NOTION_TABLE_RE = /<table[^>]*>([\\s\\S]*?)<\\/table>/g;\nconst TABLE_ROW_RE = /<tr>([\\s\\S]*?)<\\/tr>/g;\nconst TABLE_CELL_RE = /<t[dh][^>]*>([\\s\\S]*?)<\\/t[dh]>/g;\n\nfunction isAlignmentRow(cells: string[]): boolean {\n return cells.every((c) => /^:?-{2,}:?$/.test(c.trim()));\n}\n\nfunction convertNotionTables(content: string): string {\n return content.replace(NOTION_TABLE_RE, (_match, tableBody: string) => {\n const rows: string[][] = [];\n let rowMatch: RegExpExecArray | null;\n const rowRe = new RegExp(TABLE_ROW_RE.source, TABLE_ROW_RE.flags);\n\n while ((rowMatch = rowRe.exec(tableBody)) !== null) {\n const cells: string[] = [];\n let cellMatch: RegExpExecArray | null;\n const cellRe = new RegExp(TABLE_CELL_RE.source, TABLE_CELL_RE.flags);\n while ((cellMatch = cellRe.exec(rowMatch[1]!)) !== null) {\n cells.push(cellMatch[1]!.trim());\n }\n if (!isAlignmentRow(cells)) {\n rows.push(cells);\n }\n }\n\n if (rows.length === 0) return _match;\n\n const colCount = Math.max(...rows.map((r) => r.length));\n const lines: string[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const padded = rows[i]!;\n while (padded.length < colCount) padded.push(\"\");\n lines.push(`| ${padded.join(\" | \")} |`);\n if (i === 0) {\n lines.push(`| ${padded.map(() => \"---\").join(\" | \")} |`);\n }\n }\n\n return lines.join(\"\\n\");\n });\n}\n\n// ─── Push 방향: 보존 마커 → Enhanced MD 복원 ───\n\nconst OBSIDIAN_MEDIA_AUDIO_RE = /\\[🔊\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst OBSIDIAN_MEDIA_VIDEO_RE = /\\[🎬\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst OBSIDIAN_MEDIA_PDF_RE = /\\[📄\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst OBSIDIAN_MEDIA_FILE_RE = /\\[📎\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\n\nfunction restoreMediaTags(content: string): string {\n let result = content;\n\n result = result.replace(OBSIDIAN_MEDIA_AUDIO_RE, (_match, caption: string, src: string) => {\n return `<audio src=\"${src}\">${caption}</audio>`;\n });\n\n result = result.replace(OBSIDIAN_MEDIA_VIDEO_RE, (_match, caption: string, src: string) => {\n return `<video src=\"${src}\">${caption}</video>`;\n });\n\n result = result.replace(OBSIDIAN_MEDIA_PDF_RE, (_match, caption: string, src: string) => {\n return `<pdf src=\"${src}\">${caption}</pdf>`;\n });\n\n result = result.replace(OBSIDIAN_MEDIA_FILE_RE, (_match, caption: string, src: string) => {\n return `<file src=\"${src}\">${caption}</file>`;\n });\n\n return result;\n}\n\nconst OBSIDIAN_TAB_RE = /^> \\[!tab\\]\\s*(.+)\\n((?:> .*\\n?)*)/gm;\n\nfunction restoreTabBlocks(content: string): string {\n return content.replace(OBSIDIAN_TAB_RE, (_match, title: string, body: string) => {\n const unquoted = body\n .split(\"\\n\")\n .map((line) => line.replace(/^> /, \"\"))\n .join(\"\\n\")\n .trim();\n return `<tab title=\"${title}\">${unquoted}</tab>`;\n });\n}\n\n// 앞에 즉시 인접(공백 없음)한 가시 링크 `[label](url)` 가 있으면 마커와 함께 소비한다.\n// 이는 forward 에서 URL 임베드/북마크를 \"[🔗 Embed](url)%%...%%\" 로 렌더한 쌍을 통째로\n// <unknown.../> 로 복원하기 위함이다. 공백 없는 인접만 매칭하므로 사용자 일반 링크는 영향 없음.\nconst OBSIDIAN_UNKNOWN_RE = new RegExp(\n `(?:\\\\[[^\\\\]]*\\\\]\\\\([^)]*\\\\))?%%${MARKER_BRAND_RE}:unknown:id=([^&]+)&type=([^%]+)%%`,\n \"g\",\n);\n\nfunction restoreUnknownBlocks(content: string): string {\n return content.replace(OBSIDIAN_UNKNOWN_RE, (_match, id: string, type: string) => {\n const decoded = decodeURIComponent(id);\n if (decoded.startsWith(\"http\")) {\n return `<unknown url=\"${decoded}\" alt=\"${type}\"/>`;\n }\n return `<unknown id=\"${id}\" type=\"${type}\"/>`;\n });\n}\n\nconst OBSIDIAN_COLOR_RE = new RegExp(\n `%%${MARKER_BRAND_RE}:color:([^%]+)%%([\\\\s\\\\S]*?)%%\\\\/color%%`,\n \"g\",\n);\n\nfunction restoreColorSpans(content: string): string {\n return content.replace(OBSIDIAN_COLOR_RE, (_match, color: string, text: string) => {\n return `<span color=\"${color}\">${text}</span>`;\n });\n}\n\nconst OBSIDIAN_UNDERLINE_RE = new RegExp(\n `%%${MARKER_BRAND_RE}:underline%%([\\\\s\\\\S]*?)%%\\\\/underline%%`,\n \"g\",\n);\n\nfunction restoreUnderlineSpans(content: string): string {\n return content.replace(OBSIDIAN_UNDERLINE_RE, (_match, text: string) => {\n return `<span underline=\"true\">${text}</span>`;\n });\n}\n\nfunction unescapePipes(content: string): string {\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n let inTable = false;\n\n for (const line of lines) {\n if (/^\\|.*\\|$/.test(line.trim()) || /^\\|[\\s-|]+\\|$/.test(line.trim())) {\n inTable = true;\n result.push(line);\n } else {\n if (inTable && line.trim() === \"\") {\n inTable = false;\n } else if (!/^\\|/.test(line.trim())) {\n inTable = false;\n }\n result.push(inTable ? line : line.replace(/\\\\\\|/g, \"|\"));\n }\n }\n\n return result.join(\"\\n\");\n}\n\nfunction ensureCalloutContinuity(content: string): string {\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n if (line.trim() === \"\" && i > 0 && i < lines.length - 1) {\n const prev = result[result.length - 1] ?? \"\";\n const next = lines[i + 1] ?? \"\";\n if (/^>/.test(prev) && /^>/.test(next) && !/^> \\[!/.test(next)) {\n result.push(\">\");\n continue;\n }\n }\n result.push(line);\n }\n return result.join(\"\\n\");\n}\n","import type { Config, DatabaseSyncConfig } from \"../types/config.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport type { VaultFS } from \"./vault-fs.js\";\nimport type { ConversionPipeline } from \"../converter/pipeline.js\";\nimport type { Conflict, FailedOperation, SyncRecord } from \"../types/sync.js\";\nimport type { DatabaseViewsConfig } from \"../types/view.js\";\nimport type { PageObjectResponse } from \"@notionhq/client/build/src/api-endpoints.js\";\nimport { PropertyMapper } from \"../notion/property-mapper.js\";\nimport type { ImageHandler } from \"./image-handler.js\";\nimport { resolvePullConflict } from \"./conflict-detector.js\";\nimport { computeHash } from \"../utils/hash.js\";\nimport { sanitizeFileName } from \"../utils/sanitize.js\";\nimport { resolveDbRowPath, selectDbRowFiles } from \"../utils/db-row-path.js\";\nimport { wikilinkTitleFromPath } from \"../utils/wikilink-title.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { BaseFileGenerator } from \"../view/base-file-generator.js\";\nimport { SidecarGenerator } from \"../view/sidecar-generator.js\";\nimport { selectStaleDbArtifacts } from \"./stale-db-artifacts.js\";\nimport { INTERNAL_DIR, DB_VIEWS_PATH } from \"../constants/paths.js\";\nimport {\n notionEnhancedToObsidian,\n obsidianToNotionEnhanced,\n} from \"../converter/enhanced-md-converter.js\";\nimport matter from \"gray-matter\";\n\nexport interface DatabaseSyncResult {\n created: number;\n updated: number;\n /** Pull 시 로컬·리모트 동시 수정으로 발생한 충돌 (push 는 항상 빈 배열). */\n conflicts: Conflict[];\n failed: FailedOperation[];\n /**\n * 이번 pull 에서 실제로 디스크에 기록한 db-row 파일 경로(SSOT).\n * 오케스트레이터의 링크 해소(resolveNotionLinks) 대상은 반드시 이 목록으로 정한다 —\n * 과거의 `getByStatus(\"synced\").slice(-N)` 휴리스틱은 ORDER BY 가 없어 증분 pull 에서\n * 엉뚱한 행을 골라 정작 바뀐 행의 relation UUID 를 영영 해소하지 못했다(M3). push 경로는 항상 빈 배열.\n */\n writtenPaths: string[];\n}\n\n/** {@link DatabaseSyncer.pullDatabasePage} 의 처리 결과. */\ntype PullPageOutcome =\n | { action: \"written\"; path: string }\n | { action: \"skipped\"; path: string }\n | { action: \"conflict\"; path: string; conflict: Conflict };\n\nexport class DatabaseSyncer {\n private readonly propertyMapper = new PropertyMapper();\n private readonly baseFileGenerator = new BaseFileGenerator();\n private readonly sidecarGenerator = new SidecarGenerator();\n\n constructor(\n private readonly config: Config,\n private readonly stateDb: IStateDB,\n private readonly notionClient: NotionClient,\n private readonly vaultFs: VaultFS,\n private readonly pipeline: ConversionPipeline,\n private readonly imageHandler: ImageHandler,\n ) {\n this.propertyMapper.setWikilinkResolver({\n resolve: (title: string) => stateDb.resolveWikilink(title)?.notionPageId ?? null,\n // M4: 후처리 패스(resolveNotionLinks)와 동일하게 파일 basename 으로 해소 — 원시 제목과\n // sanitize 된 파일명의 불일치로 인한 깨진/이중 위키링크 차단.\n resolvePageId: (pageId: string) => {\n const entry = stateDb.resolvePageId(pageId);\n return entry ? wikilinkTitleFromPath(entry.obsidianPath) : null;\n },\n });\n }\n\n async pullAll(): Promise<DatabaseSyncResult> {\n const databases = this.config.notion.databases;\n if (!databases || databases.length === 0) {\n return { created: 0, updated: 0, conflicts: [], failed: [], writtenPaths: [] };\n }\n\n let created = 0;\n let updated = 0;\n const conflicts: Conflict[] = [];\n const failed: FailedOperation[] = [];\n const writtenPaths: string[] = [];\n\n for (const dbConfig of databases) {\n try {\n const result = await this.pullDatabase(dbConfig);\n created += result.created;\n updated += result.updated;\n conflicts.push(...result.conflicts);\n failed.push(...result.failed);\n writtenPaths.push(...result.writtenPaths);\n } catch (error) {\n getLogger().warn(`[DB Sync] DB ${dbConfig.databaseId} pull 실패:`, error);\n failed.push({\n path: dbConfig.localFolder,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return { created, updated, conflicts, failed, writtenPaths };\n }\n\n async pushAll(): Promise<DatabaseSyncResult> {\n const databases = this.config.notion.databases;\n if (!databases || databases.length === 0) {\n return { created: 0, updated: 0, conflicts: [], failed: [], writtenPaths: [] };\n }\n\n let created = 0;\n let updated = 0;\n const failed: FailedOperation[] = [];\n\n for (const dbConfig of databases) {\n try {\n const result = await this.pushDatabase(dbConfig);\n created += result.created;\n updated += result.updated;\n failed.push(...result.failed);\n } catch (error) {\n getLogger().warn(`[DB Sync] DB ${dbConfig.databaseId} push 실패:`, error);\n failed.push({\n path: dbConfig.localFolder,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return { created, updated, conflicts: [], failed, writtenPaths: [] };\n }\n\n async pullDatabase(dbConfig: DatabaseSyncConfig): Promise<DatabaseSyncResult> {\n const schema = await this.notionClient.getDatabaseSchema(dbConfig.databaseId);\n this.propertyMapper.loadSchema(schema);\n\n await this.vaultFs.ensureFolder(dbConfig.localFolder);\n\n const viewsConfig = await this.pullDatabaseViews(dbConfig);\n await this.generateBaseFile(dbConfig, viewsConfig);\n\n const pages = await this.notionClient.queryAllDatabasePages(\n dbConfig.databaseId,\n dbConfig.pullFilter,\n );\n\n let created = 0;\n let updated = 0;\n const conflicts: Conflict[] = [];\n const failed: FailedOperation[] = [];\n // M3: 실제로 디스크에 기록된 DB 행 경로 — 후처리 링크 해소(resolveNotionLinks)가\n // 정확히 이 파일들만 재방문하도록 슬라이스 추정 대신 실측 수집한다.\n const writtenPaths: string[] = [];\n\n for (const page of pages) {\n try {\n const record = this.stateDb.getByNotionId(page.id);\n\n if (record) {\n // 리모트가 마지막 동기화 시점과 동일하면 건너뜀.\n if (page.last_edited_time === record.notionLastEdited) continue;\n const outcome = await this.pullDatabasePage(page, dbConfig);\n if (outcome.action === \"written\") {\n updated++;\n writtenPaths.push(outcome.path);\n } else if (outcome.action === \"conflict\") {\n conflicts.push(outcome.conflict);\n }\n // skipped(local-first): 카운트하지 않음\n } else {\n const outcome = await this.pullDatabasePage(page, dbConfig);\n created++;\n if (outcome.action === \"written\") {\n writtenPaths.push(outcome.path);\n }\n }\n } catch (error) {\n failed.push({\n path: `${dbConfig.localFolder}/${page.id}`,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n getLogger().debug(\n `[DB Sync] ${dbConfig.localFolder}: ${created} 생성, ${updated} 업데이트, ${conflicts.length} 충돌`,\n );\n return { created, updated, conflicts, failed, writtenPaths };\n }\n\n private async pullDatabaseViews(\n dbConfig: DatabaseSyncConfig,\n force = false,\n ): Promise<DatabaseViewsConfig | null> {\n try {\n const configPath = DB_VIEWS_PATH;\n\n if (!force) {\n try {\n const existing = await this.vaultFs.readFile(configPath);\n const parsed = JSON.parse(existing) as Record<string, DatabaseViewsConfig>;\n if (parsed[dbConfig.databaseId]) return parsed[dbConfig.databaseId]!;\n } catch {\n // 파일 없으면 계속 진행\n }\n }\n\n const viewsConfig = await this.notionClient.getDatabaseViewsConfig(dbConfig.databaseId);\n await this.vaultFs.ensureFolder(INTERNAL_DIR);\n\n let allViewsConfigs: Record<string, DatabaseViewsConfig> = {};\n try {\n const existing = await this.vaultFs.readFile(configPath);\n allViewsConfigs = JSON.parse(existing) as Record<string, DatabaseViewsConfig>;\n } catch {\n // 파일 없으면 빈 객체\n }\n\n allViewsConfigs[dbConfig.databaseId] = viewsConfig;\n await this.vaultFs.writeFile(configPath, JSON.stringify(allViewsConfigs, null, 2));\n getLogger().debug(\n `[DB Sync] 뷰 설정 ${viewsConfig.views.length}개 저장: ${dbConfig.databaseId}`,\n );\n return viewsConfig;\n } catch (error) {\n getLogger().warn(`[DB Sync] 뷰 설정 Pull 실패 (계속 진행):`, error);\n return null;\n }\n }\n\n private async generateBaseFile(\n dbConfig: DatabaseSyncConfig,\n viewsConfig: DatabaseViewsConfig | null,\n ): Promise<void> {\n try {\n const schemaFull = await this.notionClient.getDatabaseSchemaFull(dbConfig.databaseId);\n const dbName =\n viewsConfig?.databaseName ||\n (await this.notionClient.getDatabaseTitle(dbConfig.databaseId)) ||\n dbConfig.localFolder.split(\"/\").pop() ||\n \"Database\";\n\n const resolvedViews: DatabaseViewsConfig = viewsConfig ?? {\n databaseId: dbConfig.databaseId,\n databaseName: dbName,\n lastSynced: new Date().toISOString(),\n views: [{ id: \"default\", name: \"Table\", type: \"table\" }],\n };\n\n const baseContent = this.baseFileGenerator.generate({\n databaseId: dbConfig.databaseId,\n databaseName: dbName,\n schema: schemaFull,\n viewsConfig: resolvedViews,\n folderPath: dbConfig.localFolder,\n });\n\n const safeName = sanitizeFileName(dbName);\n const basePath = `${dbConfig.localFolder}/${safeName}.base`;\n await this.vaultFs.writeFile(basePath, baseContent);\n getLogger().debug(`[DB Sync] .base 파일 생성: ${basePath}`);\n\n await this.generateSidecar(dbConfig, dbName, safeName, schemaFull, resolvedViews);\n await this.cleanupStaleDbArtifacts(dbConfig.localFolder, safeName);\n } catch (error) {\n getLogger().warn(`[DB Sync] .base 파일 생성 실패 (계속 진행):`, error);\n }\n }\n\n /**\n * DB 제목이 바뀌면 `.base`/`.notion.json` 파일명(safeName)이 바뀌어 옛 이름의 산출물이\n * 같은 폴더에 고아로 잔존한다(drift·부활 원인). DB 폴더 **직속**의 산출물 중 현재 이름이\n * 아닌 것을 삭제해 멱등을 보장한다. 하위 폴더(중첩 DB)의 산출물은 보호한다.\n */\n private async cleanupStaleDbArtifacts(localFolder: string, safeName: string): Promise<void> {\n try {\n const keep = new Set([\n `${localFolder}/${safeName}.base`,\n `${localFolder}/${safeName}.notion.json`,\n ]);\n const files = await this.vaultFs.listNonMarkdownFiles();\n const stale = selectStaleDbArtifacts(files, localFolder, keep);\n for (const path of stale) {\n await this.vaultFs.deleteFile(path);\n getLogger().info(`[DB Sync] 고아 DB 산출물 삭제(rename): ${path}`);\n }\n } catch (error) {\n getLogger().warn(`[DB Sync] 고아 .base/.notion.json 정리 실패 (계속 진행):`, error);\n }\n }\n\n /**\n * `.base` 가 표현하지 못하는 Notion DB 메타데이터(미지원 뷰·필터식·커버크기 등)를\n * 사이드카 `<db>.notion.json` 으로 무손실 보존하고, degrade 된 항목을 정직하게 로그한다.\n * 결정적 직렬화라 동일 DB 상태 → 동일 바이트 → 멱등(drift/churn 0).\n */\n private async generateSidecar(\n dbConfig: DatabaseSyncConfig,\n dbName: string,\n safeName: string,\n schemaFull: Record<string, { id: string; type: string; options?: Array<{ name: string }> }>,\n resolvedViews: DatabaseViewsConfig,\n ): Promise<void> {\n try {\n const sidecar = this.sidecarGenerator.build({\n databaseId: dbConfig.databaseId,\n databaseName: dbName,\n schema: schemaFull,\n viewsConfig: resolvedViews,\n });\n const sidecarPath = `${dbConfig.localFolder}/${safeName}.notion.json`;\n await this.vaultFs.writeFile(sidecarPath, this.sidecarGenerator.serialize(sidecar));\n\n if (sidecar.degraded.length > 0) {\n const unrep = sidecar.degraded.filter((d) => d.kind === \"view-unrepresentable\").length;\n const dropped = sidecar.degraded.length - unrep;\n getLogger().info(\n `[DB Sync] '${dbName}' degrade ${sidecar.degraded.length}건` +\n ` (미표현 뷰 ${unrep} · 미표현 설정 ${dropped}) → ${safeName}.notion.json 보존`,\n );\n }\n } catch (error) {\n getLogger().warn(`[DB Sync] 사이드카 생성 실패 (계속 진행):`, error);\n }\n }\n\n private async pullDatabasePage(\n page: PageObjectResponse,\n dbConfig: DatabaseSyncConfig,\n ): Promise<PullPageOutcome> {\n const title = this.notionClient.extractTitle(page);\n const safeName = sanitizeFileName(title);\n\n const properties = this.propertyMapper.fromNotionProperties(\n (page as unknown as { properties: Record<string, unknown> }).properties,\n );\n properties.title = title;\n\n const cover = this.notionClient.extractCover(page);\n const icon = this.notionClient.extractIcon(page);\n\n if (cover) {\n try {\n const coverResult = await this.imageHandler.downloadAllImages(\n `![cover](${cover.url})`,\n `${safeName}-cover`,\n );\n // 이미지 핸들러가 실제 로컬 첨부 경로로 치환했을 때만 위키링크로 감싼다.\n // 다운로드 비활성/실패 시엔 원격 URL이 그대로 돌아오는데, 이를 `[[..]]` 로\n // 감싸면 존재하지 않는 `[[https://..]]` 파일을 가리키는 깨진 링크가 된다(cover-URL).\n const resolved = coverResult.content.match(/!\\[cover\\]\\((.+?)\\)/)?.[1];\n if (resolved && !/^https?:\\/\\//i.test(resolved)) {\n properties.cover = `[[${resolved}]]`;\n } else {\n properties.cover = cover.url;\n }\n } catch {\n properties.cover = cover.url;\n }\n }\n\n if (icon) {\n properties.icon = icon.value;\n }\n\n let markdown = \"\";\n try {\n const mdResult = await this.notionClient.getPageMarkdown(page.id);\n markdown = notionEnhancedToObsidian(mdResult.markdown);\n } catch {\n // Markdown API 실패 시 빈 내용\n }\n\n if (this.config.conversion.imageDownload === \"immediate\" && markdown) {\n try {\n const imageResult = await this.imageHandler.downloadAllImages(markdown, title);\n markdown = imageResult.content;\n } catch (error) {\n getLogger().warn(`[DB Sync] 이미지 다운로드 실패 (${title}):`, error);\n }\n }\n\n if (markdown) {\n try {\n const fileResult = await this.imageHandler.downloadAllFiles(markdown, title);\n markdown = fileResult.content;\n } catch (error) {\n getLogger().warn(`[DB Sync] 파일 다운로드 실패 (${title}):`, error);\n }\n }\n\n const existingRecord = this.stateDb.getByNotionId(page.id);\n let filePath: string;\n if (existingRecord?.obsidianPath) {\n filePath = existingRecord.obsidianPath;\n } else {\n filePath = resolveDbRowPath(dbConfig.localFolder, safeName, page.id, (p) =>\n this.stateDb.getByPath(p),\n );\n }\n\n const finalContent = this.pipeline.convertToMarkdown(\n markdown,\n {\n direction: \"pull\",\n path: \"markdown-api\",\n filePath,\n parentMode: \"database\",\n },\n { properties },\n );\n\n // 기존 추적 레코드가 있으면 무조건 덮어쓰기 전에 로컬 수정 여부를 검사한다.\n // (신규 페이지는 existingRecord 가 없으므로 충돌 검사 없이 바로 기록 — 로컬 파일 미존재)\n if (existingRecord) {\n let localContent = \"\";\n try {\n localContent = await this.vaultFs.readFile(filePath);\n } catch {\n localContent = \"\";\n }\n\n const resolution = resolvePullConflict({\n record: existingRecord,\n localContent,\n remoteContent: finalContent,\n remoteChange: {\n pageId: page.id,\n type: \"modified\",\n lastEdited: page.last_edited_time,\n previousEdited: existingRecord.notionLastEdited,\n },\n strategy: this.config.sync.conflictStrategy,\n });\n\n if (resolution.action === \"skip\") {\n // local-first: 로컬 보존, 리모트 변경 무시\n return { action: \"skipped\", path: filePath };\n }\n if (resolution.action === \"conflict\") {\n // 양쪽 모두 수정됨 → 충돌로 표시하고 로컬 보존 (사용자 해소 대기)\n this.stateDb.updateStatus(existingRecord.id, \"conflict\");\n return { action: \"conflict\", path: filePath, conflict: resolution.conflict! };\n }\n // resolution.action === \"write\" → 아래로 진행하여 덮어쓰기\n }\n\n await this.vaultFs.ensureFolder(dbConfig.localFolder);\n await this.vaultFs.writeFile(filePath, finalContent);\n\n const hash = computeHash(finalContent);\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: filePath,\n notionPageId: page.id,\n notionParentId: dbConfig.databaseId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: \"db-row\",\n status: \"synced\",\n baseSnapshot: Buffer.from(finalContent, \"utf-8\"),\n });\n\n this.stateDb.upsertWikilink({\n obsidianPath: filePath,\n notionPageId: page.id,\n title,\n aliases: extractAliases(properties),\n });\n });\n\n return { action: \"written\", path: filePath };\n }\n\n private async pushDatabase(dbConfig: DatabaseSyncConfig): Promise<DatabaseSyncResult> {\n const schema = await this.notionClient.getDatabaseSchema(dbConfig.databaseId);\n this.propertyMapper.loadSchema(schema);\n\n const allFiles = await this.vaultFs.listMarkdownFiles();\n // 직속 행 파일만 — 중첩 하위 폴더(별도 child_database)의 행은 각자의 DB push 가 관리하므로\n // 부모 DB 로 잘못 밀어 중복·오배치하지 않는다(오포함 차단).\n const dbFiles = selectDbRowFiles(allFiles, dbConfig.localFolder);\n\n // rename 감지용 고아 레코드(로컬 파일이 사라진 추적 레코드) 인덱스.\n // 새 경로의 파일이 어떤 고아의 내용 해시와 일치하면 신규 페이지 생성이 아니라 rename 으로 처리.\n const livePaths = new Set(dbFiles.map((f) => f.path));\n const orphanByHash = this.buildOrphanHashIndex(dbConfig.databaseId, livePaths);\n\n let created = 0;\n let updated = 0;\n const failed: FailedOperation[] = [];\n\n for (const file of dbFiles) {\n try {\n const content = await this.vaultFs.readFile(file.path);\n const hash = computeHash(content);\n\n const record = this.stateDb.getByPath(file.path);\n if (record?.contentHash === hash) continue;\n\n const parsed = matter(content);\n const frontmatter = parsed.data as Record<string, unknown>;\n const body = parsed.content;\n\n const title = (frontmatter.title as string) ?? extractTitleFromPath(file.path);\n delete frontmatter.title;\n\n const notionProps = this.propertyMapper.toNotionProperties(frontmatter, title);\n const enhanced = obsidianToNotionEnhanced(body.trim());\n\n if (record?.notionPageId) {\n try {\n await this.notionClient.updatePageProperties(record.notionPageId, notionProps);\n await this.notionClient.replacePageMarkdown(record.notionPageId, enhanced);\n } catch (error) {\n // push 실패: 본문/속성이 Notion 에 반영되지 않았으므로 해시를 전진시키거나\n // synced 로 표시하지 않는다. (과거: 본문 실패를 삼키고 synced 처리 → 거짓 동기화·\n // 본문 영구 유실. 해시 전진 탓에 다음 push 에서 스킵되어 변경이 영원히 전달 안 됨)\n this.stateDb.updateStatus(record.id, \"error\");\n failed.push({\n path: file.path,\n operation: \"update\",\n error: error instanceof Error ? error.message : String(error),\n });\n continue;\n }\n\n const updatedPage = await this.notionClient.getPage(record.notionPageId);\n this.stateDb.transaction(() => {\n this.stateDb.updateHash(record.id, hash, Buffer.from(content, \"utf-8\"));\n this.stateDb.updateStatus(record.id, \"synced\");\n this.stateDb.setNotionLastEdited(record.id, updatedPage.last_edited_time);\n // 제목/별칭이 바뀌었을 수 있으므로 wikilink 도 함께 갱신해 최신성을 보장한다.\n this.stateDb.upsertWikilink({\n obsidianPath: file.path,\n notionPageId: record.notionPageId!,\n title,\n aliases: extractAliases(frontmatter),\n });\n });\n updated++;\n } else {\n // rename 감지: 내용이 동일한 고아 레코드가 있으면 신규 페이지 생성 대신 경로만 재매핑.\n // (과거: getByPath(newPath)=null → 무조건 신규 생성 → Notion 중복 페이지 + 고아 레코드.\n // db-row 프론트매터엔 Notion page id 가 없어 내용 해시로 동일 행을 식별한다.)\n const renamed = orphanByHash.get(hash);\n if (renamed?.notionPageId) {\n const movedPageId = renamed.notionPageId;\n orphanByHash.delete(hash); // 같은 고아를 두 번 매칭하지 않도록 제거\n this.stateDb.transaction(() => {\n this.stateDb.updatePath(renamed.id, file.path);\n this.stateDb.updateHash(renamed.id, hash, Buffer.from(content, \"utf-8\"));\n this.stateDb.updateStatus(renamed.id, \"synced\");\n // 새 경로로 wikilink 갱신 — INSERT OR REPLACE 가 notion_page_id UNIQUE 충돌로\n // 이전 경로의 wikilink 행을 자동 정리한다.\n this.stateDb.upsertWikilink({\n obsidianPath: file.path,\n notionPageId: movedPageId,\n title,\n aliases: extractAliases(frontmatter),\n });\n });\n updated++;\n continue;\n }\n\n const page = await this.notionClient.createPageWithMarkdown({\n parentId: dbConfig.databaseId,\n parentType: \"database\",\n title,\n markdown: enhanced,\n properties: notionProps,\n });\n\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: file.path,\n notionPageId: page.id,\n notionParentId: dbConfig.databaseId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: \"db-row\",\n status: \"synced\",\n baseSnapshot: Buffer.from(content, \"utf-8\"),\n });\n\n this.stateDb.upsertWikilink({\n obsidianPath: file.path,\n notionPageId: page.id,\n title,\n aliases: extractAliases(frontmatter),\n });\n });\n created++;\n }\n } catch (error) {\n failed.push({\n path: file.path,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n getLogger().debug(`[DB Sync] ${dbConfig.localFolder}: ${created} 생성, ${updated} 업데이트`);\n return { created, updated, conflicts: [], failed, writtenPaths: [] };\n }\n\n /**\n * rename 감지를 위한 고아 레코드 인덱스(내용 해시 → 레코드)를 만든다.\n * 고아 = 해당 DB 소속 db-row 레코드 중 로컬 파일이 더 이상 존재하지 않는(livePaths 에 없는) 것.\n * 같은 해시가 여러 고아에 걸리면 첫 항목을 유지한다(희박한 케이스).\n */\n private buildOrphanHashIndex(\n databaseId: string,\n livePaths: Set<string>,\n ): Map<string, SyncRecord> {\n const index = new Map<string, SyncRecord>();\n for (const record of this.stateDb.getAll()) {\n if (\n record.fileType === \"db-row\" &&\n record.notionParentId === databaseId &&\n record.notionPageId &&\n !livePaths.has(record.obsidianPath) &&\n !index.has(record.contentHash)\n ) {\n index.set(record.contentHash, record);\n }\n }\n return index;\n }\n}\n\nfunction extractAliases(properties: Record<string, unknown>): string[] {\n const raw = properties.aliases ?? properties.alias;\n if (!raw) return [];\n if (Array.isArray(raw)) return raw.filter((a): a is string => typeof a === \"string\");\n if (typeof raw === \"string\")\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction extractTitleFromPath(filePath: string): string {\n const parts = filePath.split(\"/\");\n const filename = parts[parts.length - 1] ?? \"\";\n return filename.replace(/\\.md$/, \"\");\n}\n","export interface MergeResult {\n readonly success: boolean;\n readonly merged: string;\n readonly conflicts: MergeConflictRegion[];\n}\n\nexport interface MergeConflictRegion {\n readonly localLines: string[];\n readonly remoteLines: string[];\n}\n\n/** base 한 쪽(local 또는 remote)의 변경 조각. base[baseStart, baseEnd) 구간을 content 로 치환. */\ninterface Hunk {\n readonly baseStart: number;\n readonly baseEnd: number;\n readonly content: string[];\n /** 0 = local, 2 = remote (정렬 시 동률이면 local 우선). */\n readonly side: 0 | 2;\n}\n\n/**\n * 3-way 병합 (diff3). base 를 공통 조상으로 보고 local/remote 의 변경을 합친다.\n *\n * 표준 diff3 알고리즘:\n * 1. base↔local, base↔remote 각각의 LCS 로 \"변경 조각(hunk)\"을 추출한다.\n * (hunk = base 의 어떤 구간 [baseStart, baseEnd) 을 새 내용으로 치환·삭제·삽입)\n * 2. 모든 hunk 를 base 위치순으로 정렬하고, **base 구간이 겹치는** hunk 들을\n * 하나의 region 으로 묶는다. 겹치지 않는 hunk 사이의 base 줄은 양쪽 공통이므로 그대로 출력.\n * 3. 각 region 에서 local/remote 가 만들어낸 내용을 비교해 판정한다.\n * - local 결과 == base → local 미변경 → remote 채택\n * - remote 결과 == base → remote 미변경 → local 채택\n * - local 결과 == remote 결과 → 동일 변경 → 한쪽 채택\n * - 그 외 → 충돌 (양쪽이 같은 구간을 다르게 변경)\n *\n * 핵심은 hunk 의 base 구간이 **실제로 겹칠 때만** 충돌로 본다는 점이다. 서로 다른(인접\n * 포함) 줄을 고친 삽입·삭제·수정은 충돌 없이 합쳐진다. (이전 단순 라인-치환 구현은\n * 삽입/삭제를 오정렬해 거짓 충돌을 만들거나 무한 루프에 빠질 수 있었다.)\n */\nexport function threeWayMerge(base: string, local: string, remote: string): MergeResult {\n const baseLines = base.split(\"\\n\");\n const localLines = local.split(\"\\n\");\n const remoteLines = remote.split(\"\\n\");\n\n const hunks = [\n ...computeHunks(baseLines, localLines, 0),\n ...computeHunks(baseLines, remoteLines, 2),\n ];\n // base 시작 위치 오름차순, 동률이면 local(0) 먼저.\n hunks.sort((a, b) => a.baseStart - b.baseStart || a.side - b.side);\n\n const merged: string[] = [];\n const conflicts: MergeConflictRegion[] = [];\n let cursor = 0; // 다음에 출력할 base 인덱스.\n let i = 0;\n\n while (i < hunks.length) {\n const first = hunks[i]!;\n // region 앞쪽의 공통(안정) base 줄을 그대로 출력.\n if (first.baseStart > cursor) {\n merged.push(...baseLines.slice(cursor, first.baseStart));\n }\n\n const regionStart = first.baseStart;\n let regionEnd = first.baseEnd;\n const group: Hunk[] = [first];\n i++;\n\n // base 구간이 겹치는 hunk 들을 한 region 으로 흡수.\n // - 일반 겹침: 다음 hunk 의 시작이 regionEnd 보다 앞(strict).\n // - 같은 지점의 순수 삽입(regionEnd === regionStart): 시작 위치가 같으면 함께 묶는다\n // (양쪽이 같은 자리에 삽입 → 동일하면 1회, 다르면 충돌).\n while (i < hunks.length) {\n const next = hunks[i]!;\n const overlaps =\n next.baseStart < regionEnd || (regionEnd === regionStart && next.baseStart === regionStart);\n if (!overlaps) break;\n regionEnd = Math.max(regionEnd, next.baseEnd);\n group.push(next);\n i++;\n }\n\n const baseRegion = baseLines.slice(regionStart, regionEnd);\n const localRegion = applyHunks(baseLines, group, 0, regionStart, regionEnd);\n const remoteRegion = applyHunks(baseLines, group, 2, regionStart, regionEnd);\n\n if (arraysEqual(localRegion, baseRegion)) {\n merged.push(...remoteRegion); // local 미변경 → remote 채택\n } else if (arraysEqual(remoteRegion, baseRegion)) {\n merged.push(...localRegion); // remote 미변경 → local 채택\n } else if (arraysEqual(localRegion, remoteRegion)) {\n merged.push(...localRegion); // 동일 변경\n } else {\n conflicts.push({ localLines: localRegion, remoteLines: remoteRegion });\n merged.push(\"<<<<<<< LOCAL\");\n merged.push(...localRegion);\n merged.push(\"=======\");\n merged.push(...remoteRegion);\n merged.push(\">>>>>>> REMOTE\");\n }\n\n cursor = regionEnd;\n }\n\n // 마지막 region 이후의 공통 base 줄.\n if (cursor < baseLines.length) {\n merged.push(...baseLines.slice(cursor));\n }\n\n return {\n success: conflicts.length === 0,\n merged: merged.join(\"\\n\"),\n conflicts,\n };\n}\n\n/**\n * base 와 modified 의 LCS 매칭을 기준으로 변경 조각(hunk) 목록을 만든다.\n * 매칭되지 않은(=변경된) base 구간과 그에 대응하는 modified 구간을 한 hunk 로 묶는다.\n */\nfunction computeHunks(base: string[], modified: string[], side: 0 | 2): Hunk[] {\n const matches = lcsMatches(base, modified); // [baseIdx, modIdx] 오름차순\n const hunks: Hunk[] = [];\n\n let prevBase = -1;\n let prevMod = -1;\n const emitGap = (curBase: number, curMod: number): void => {\n const baseLen = curBase - (prevBase + 1);\n const modLen = curMod - (prevMod + 1);\n if (baseLen > 0 || modLen > 0) {\n hunks.push({\n baseStart: prevBase + 1,\n baseEnd: curBase,\n content: modified.slice(prevMod + 1, curMod),\n side,\n });\n }\n };\n\n for (const [b, m] of matches) {\n emitGap(b, m);\n prevBase = b;\n prevMod = m;\n }\n emitGap(base.length, modified.length); // 마지막 매칭 이후 꼬리.\n\n return hunks;\n}\n\n/**\n * region [regionStart, regionEnd) 에 대해 한 쪽(side)이 만들어낸 내용을 재구성한다.\n * 해당 side 의 hunk 는 base 를 치환하고, hunk 가 없는 base 줄은 그대로 복사한다.\n * region 경계는 항상 hunk 경계와 정렬되므로 hunk 가 region 을 가로지르지 않는다.\n */\nfunction applyHunks(\n baseLines: string[],\n group: Hunk[],\n side: 0 | 2,\n regionStart: number,\n regionEnd: number,\n): string[] {\n const out: string[] = [];\n let b = regionStart;\n for (const hunk of group) {\n if (hunk.side !== side) continue;\n if (hunk.baseStart > b) out.push(...baseLines.slice(b, hunk.baseStart));\n out.push(...hunk.content);\n b = hunk.baseEnd;\n }\n if (b < regionEnd) out.push(...baseLines.slice(b, regionEnd));\n return out;\n}\n\n/**\n * a 와 b 의 LCS 매칭 쌍 [aIndex, bIndex] 을 a 인덱스 오름차순으로 반환한다.\n * 라인 단위 비교(보통 수백~수천 줄)라 O(n·m) DP 로 충분하다.\n */\nfunction lcsMatches(a: string[], b: string[]): Array<[number, number]> {\n const n = a.length;\n const m = b.length;\n\n // dp[i][j] = a[i..], b[j..] 의 LCS 길이. 행마다 Uint32Array 로 메모리 절약.\n const dp: Uint32Array[] = new Array(n + 1);\n for (let i = 0; i <= n; i++) dp[i] = new Uint32Array(m + 1);\n\n for (let i = n - 1; i >= 0; i--) {\n const row = dp[i]!;\n const next = dp[i + 1]!;\n const ai = a[i];\n for (let j = m - 1; j >= 0; j--) {\n row[j] = ai === b[j] ? next[j + 1]! + 1 : Math.max(next[j]!, row[j + 1]!);\n }\n }\n\n const matches: Array<[number, number]> = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) {\n matches.push([i, j]);\n i++;\n j++;\n } else if (dp[i + 1]![j]! >= dp[i]![j + 1]!) {\n i++;\n } else {\n j++;\n }\n }\n\n return matches;\n}\n\nfunction arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((val, idx) => val === b[idx]);\n}\n","import type { Conflict, ConflictStrategy } from \"../types/sync.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { VaultFS } from \"../sync/vault-fs.js\";\nimport { threeWayMerge } from \"./merger.js\";\nimport { computeHash } from \"../utils/hash.js\";\n\nexport type ResolutionChoice = \"local\" | \"remote\" | \"merge\" | \"duplicate\";\n\nexport interface ResolutionResult {\n readonly path: string;\n readonly choice: ResolutionChoice;\n readonly success: boolean;\n readonly mergeHadConflicts?: boolean;\n}\n\nexport class ConflictResolver {\n constructor(\n private readonly stateDb: IStateDB,\n private readonly vaultFs: VaultFS,\n ) {}\n\n async resolve(conflict: Conflict, choice: ResolutionChoice): Promise<ResolutionResult> {\n switch (choice) {\n case \"local\":\n return this.resolveLocal(conflict);\n case \"remote\":\n return this.resolveRemote(conflict);\n case \"merge\":\n return this.resolveMerge(conflict);\n case \"duplicate\":\n return this.resolveDuplicate(conflict);\n }\n }\n\n async resolveByStrategy(\n conflict: Conflict,\n strategy: ConflictStrategy,\n ): Promise<ResolutionResult> {\n switch (strategy) {\n case \"local-first\":\n return this.resolve(conflict, \"local\");\n case \"remote-first\":\n return this.resolve(conflict, \"remote\");\n case \"duplicate\":\n return this.resolve(conflict, \"duplicate\");\n case \"manual\":\n return this.resolve(conflict, \"merge\");\n }\n }\n\n async resolveAll(conflicts: Conflict[], strategy: ConflictStrategy): Promise<ResolutionResult[]> {\n const results: ResolutionResult[] = [];\n for (const conflict of conflicts) {\n const result = await this.resolveByStrategy(conflict, strategy);\n results.push(result);\n }\n return results;\n }\n\n private async resolveLocal(conflict: Conflict): Promise<ResolutionResult> {\n const hash = computeHash(conflict.localContent);\n this.stateDb.updateHash(\n conflict.syncRecord.id,\n hash,\n Buffer.from(conflict.localContent, \"utf-8\"),\n );\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n\n return { path: conflict.syncRecord.obsidianPath, choice: \"local\", success: true };\n }\n\n private async resolveRemote(conflict: Conflict): Promise<ResolutionResult> {\n await this.vaultFs.writeFile(conflict.syncRecord.obsidianPath, conflict.remoteContent);\n\n const hash = computeHash(conflict.remoteContent);\n this.stateDb.updateHash(\n conflict.syncRecord.id,\n hash,\n Buffer.from(conflict.remoteContent, \"utf-8\"),\n );\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n\n return { path: conflict.syncRecord.obsidianPath, choice: \"remote\", success: true };\n }\n\n private async resolveMerge(conflict: Conflict): Promise<ResolutionResult> {\n const base = conflict.baseContent ?? \"\";\n const mergeResult = threeWayMerge(base, conflict.localContent, conflict.remoteContent);\n\n await this.vaultFs.writeFile(conflict.syncRecord.obsidianPath, mergeResult.merged);\n\n const hash = computeHash(mergeResult.merged);\n this.stateDb.updateHash(conflict.syncRecord.id, hash, Buffer.from(mergeResult.merged, \"utf-8\"));\n\n if (mergeResult.success) {\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n }\n\n return {\n path: conflict.syncRecord.obsidianPath,\n choice: \"merge\",\n success: mergeResult.success,\n mergeHadConflicts: !mergeResult.success,\n };\n }\n\n private async resolveDuplicate(conflict: Conflict): Promise<ResolutionResult> {\n const originalPath = conflict.syncRecord.obsidianPath;\n const ext = originalPath.endsWith(\".md\") ? \".md\" : \"\";\n const baseName = originalPath.replace(/\\.md$/, \"\");\n const conflictPath = `${baseName}.conflict${ext}`;\n\n await this.vaultFs.writeFile(conflictPath, conflict.remoteContent);\n\n const localHash = computeHash(conflict.localContent);\n this.stateDb.updateHash(\n conflict.syncRecord.id,\n localHash,\n Buffer.from(conflict.localContent, \"utf-8\"),\n );\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n\n return { path: originalPath, choice: \"duplicate\", success: true };\n }\n\n generateDiff(conflict: Conflict): string {\n const localLines = conflict.localContent.split(\"\\n\");\n const remoteLines = conflict.remoteContent.split(\"\\n\");\n const lines: string[] = [];\n\n lines.push(`--- local: ${conflict.syncRecord.obsidianPath}`);\n lines.push(`+++ remote: Notion (${conflict.remoteChange.pageId})`);\n lines.push(\"\");\n\n const maxLen = Math.max(localLines.length, remoteLines.length);\n for (let i = 0; i < maxLen; i++) {\n const localLine = localLines[i];\n const remoteLine = remoteLines[i];\n\n if (localLine === remoteLine) {\n lines.push(` ${localLine ?? \"\"}`);\n } else {\n if (localLine !== undefined) lines.push(`- ${localLine}`);\n if (remoteLine !== undefined) lines.push(`+ ${remoteLine}`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n}\n","/**\n * 취소 신호. `AbortSignal` 과 호환되며, 테스트에서 가벼운 목 객체로도 쓸 수 있다.\n */\nexport interface AbortLike {\n readonly aborted: boolean;\n}\n\nexport interface PoolOptions {\n /** 동시에 동작할 최대 worker 수. 1 미만이면 1로 보정한다. */\n readonly concurrency: number;\n /** 설정되면 `aborted === true` 인 순간부터 새 항목 처리를 멈춘다. */\n readonly signal?: AbortLike;\n}\n\n/**\n * 고정 크기 워커 풀로 항목들을 처리한다.\n *\n * `items.map((x) => doAsync(x))` 나 `Promise.all(tasks.map((t) => t()))` 방식은\n * 입력 개수(N)만큼의 Promise 를 한꺼번에 생성해 모두 메모리에 띄운다. 동시 실행은\n * 세마포어로 제한하더라도 \"대기 중인 N개의 Promise + 클로저\"가 그대로 상주하므로\n * 페이지 수가 많아질수록 메모리가 선형으로 늘어난다.\n *\n * `runPool` 은 정확히 `concurrency` 개의 worker 만 띄우고, 각 worker 가 공유 커서에서\n * 다음 인덱스를 꺼내 순차적으로 소비한다. 따라서 동시에 살아 있는 작업 Promise 가\n * 항상 `concurrency` 개로 일정하게 유지된다(백프레셔). 동시성 수준은 기존\n * 세마포어 방식과 동일하지만 메모리 사용이 입력 크기와 무관해진다.\n *\n * worker 가 throw 해도 해당 항목만 건너뛰고 풀은 계속 진행한다(한 건의 실패가\n * 전체를 중단시키지 않음). 실패 기록·재시도는 호출자(worker 내부)에서 담당한다.\n *\n * @param items 처리할 항목 (읽기 전용 — 풀이 변형하지 않는다).\n * @param worker 각 항목을 처리하는 비동기 함수. `index` 는 원본 배열에서의 위치.\n * @param options 동시성·취소 옵션.\n */\nexport async function runPool<T>(\n items: readonly T[],\n worker: (item: T, index: number) => Promise<void>,\n options: PoolOptions,\n): Promise<void> {\n const total = items.length;\n if (total === 0) return;\n\n const workerCount = Math.max(1, Math.min(Math.floor(options.concurrency) || 1, total));\n let cursor = 0;\n\n const runWorker = async (): Promise<void> => {\n // cursor 읽기→증가는 await 사이에서 원자적이므로(단일 스레드 이벤트 루프)\n // 두 worker 가 같은 인덱스를 가져가지 않는다.\n for (;;) {\n if (options.signal?.aborted) return;\n const index = cursor++;\n if (index >= total) return;\n try {\n await worker(items[index]!, index);\n } catch {\n // worker 내부에서 실패를 직접 기록한다. 풀은 다음 항목으로 계속 진행.\n }\n }\n };\n\n await Promise.all(Array.from({ length: workerCount }, () => runWorker()));\n}\n","import matter from \"gray-matter\";\nimport { stringifyFrontmatter } from \"../utils/frontmatter.js\";\n\n/** 대시 포함(8-4-4-4-12) 또는 대시 없는 32 hex Notion ID 전체 일치 패턴. */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$|^[0-9a-f]{32}$/i;\n\n/**\n * frontmatter 의 relation/people 속성에 박힌 원시 Notion UUID 를 `[[제목]]` 위키링크로 치환한다.\n *\n * 단일 패스 변환 시점에는 relation 대상 페이지가 아직 변환·등록되지 않아 propertyMapper 가\n * UUID 를 그대로 남긴다(예: `작가: 1c013b18-...`). pull 의 마지막 단계인 resolveNotionLinks 는\n * 인라인 DB 까지 모든 변환이 끝나 wikilink 맵이 **완성된 뒤** 실행되므로, 이 시점에 frontmatter\n * UUID 를 해소하면 단일 패스 순서 의존성을 부작용 없이 제거할 수 있다.\n *\n * 규칙:\n * - `idToTitle` 키는 대시 제거(clean) 와 대시 포함(raw) 양형식을 모두 담는다고 가정한다.\n * - 맵에 없는 UUID(미수집 타 DB 대상)는 무손실로 그대로 둔다.\n * - relation 은 스칼라·배열·중첩배열(rollup→relation) 모두 가능하므로 값을 재귀 순회한다.\n * - 해소된 항목이 0 이면 `content` 를 재직렬화하지 않고 원본을 그대로 반환해 churn 을 막는다.\n * - 직렬화는 sealed serializer(stringifyFrontmatter)만 거친다 — 변환 시점과 동일 직렬화기라\n * 미변경 키는 byte-identical 로 round-trip 되어 fixpoint 가 안정적이다.\n */\nexport function resolveFrontmatterRelations(\n content: string,\n idToTitle: Map<string, string>,\n): { content: string; count: number } {\n if (!content.startsWith(\"---\") || idToTitle.size === 0) {\n return { content, count: 0 };\n }\n\n let parsed: ReturnType<typeof matter>;\n try {\n parsed = matter(content);\n } catch {\n // frontmatter 파싱 실패(예: 본문 선행 `---` 오인) 시 무손실 패스\n return { content, count: 0 };\n }\n\n const data = parsed.data as Record<string, unknown>;\n if (!data || Object.keys(data).length === 0) {\n return { content, count: 0 };\n }\n\n let count = 0;\n const resolveValue = (value: unknown): unknown => {\n if (typeof value === \"string\") {\n if (!UUID_RE.test(value)) return value;\n const title = idToTitle.get(value.replace(/-/g, \"\"));\n if (!title) return value;\n count++;\n return `[[${title}]]`;\n }\n if (Array.isArray(value)) return value.map(resolveValue);\n return value;\n };\n\n // gray-matter 는 입력 문자열을 키로 파싱 결과를 캐시한다. `data` 를 in-place 로\n // 수정하면 동일 frontmatter 를 가진 다른 파일이 오염된 캐시 객체를 공유해\n // cross-file 오염이 발생한다. 반드시 새 객체에 결과를 담아 캐시를 건드리지 않는다.\n const resolved: Record<string, unknown> = {};\n for (const key of Object.keys(data)) {\n resolved[key] = resolveValue(data[key]);\n }\n\n if (count === 0) return { content, count: 0 };\n return { content: stringifyFrontmatter(parsed.content, resolved), count };\n}\n","import type {\n PushOptions,\n PushResult,\n PullOptions,\n PullResult,\n SyncOptions,\n SyncResult,\n StatusResult,\n SyncRecord,\n LocalChange,\n RemoteChange,\n Conflict,\n ConflictStrategy,\n FailedOperation,\n} from \"../types/sync.js\";\nimport type { Config } from \"../types/config.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport { isNotionObjectNotFound, DiscoveryTooLargeError } from \"../notion/client.js\";\nimport type { PageObjectResponse } from \"@notionhq/client/build/src/api-endpoints.js\";\nimport { Sema } from \"async-sema\";\nimport { ChangeDetector } from \"./change-detector.js\";\nimport type { ConversionPipeline } from \"../converter/pipeline.js\";\nimport { createDefaultPipeline } from \"../converter/pipeline-factory.js\";\nimport { BlockConverter } from \"../converter/block-converter.js\";\nimport { ImageHandler } from \"./image-handler.js\";\nimport { FileHandler } from \"./file-handler.js\";\nimport { DatabaseSyncer } from \"./database-syncer.js\";\nimport { resolvePullConflict } from \"./conflict-detector.js\";\nimport { ConflictResolver } from \"../conflict/resolver.js\";\nimport type { ResolutionChoice, ResolutionResult } from \"../conflict/resolver.js\";\nimport { PropertyMapper, type WikilinkResolver } from \"../notion/property-mapper.js\";\nimport { computeHash } from \"../utils/hash.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { sanitizeFileName } from \"../utils/sanitize.js\";\nimport { notionIdsEqual, normalizeNotionId } from \"../utils/id.js\";\nimport { runPool } from \"../utils/pool.js\";\nimport { wikilinkTitleFromPath } from \"../utils/wikilink-title.js\";\nimport { resolveFrontmatterRelations } from \"./frontmatter-link-resolver.js\";\nimport type { VaultFS } from \"./vault-fs.js\";\nimport {\n notionEnhancedToObsidian,\n obsidianToNotionEnhanced,\n} from \"../converter/enhanced-md-converter.js\";\n\n/** 자동 발견된 DB 설정 빌드 결과 — 동기화 가능/접근 불가/일시 오류를 명시적으로 구분한다. */\ntype DiscoveredDbOutcome =\n | { kind: \"ok\"; config: { databaseId: string; localFolder: string; titleProperty: string } }\n | { kind: \"inaccessible\" }\n | { kind: \"error\" };\n\n/** 접근 불가 DB denylist 를 보존하는 상태 메타 키. */\nconst INACCESSIBLE_DBS_META_KEY = \"inaccessible_dbs\";\n\n/** 전략 → 선택지 매핑. propagateResolution 이 push 방향을 정할 때 사용. */\nfunction strategyToChoice(strategy: ConflictStrategy): ResolutionChoice {\n switch (strategy) {\n case \"local-first\":\n return \"local\";\n case \"remote-first\":\n return \"remote\";\n case \"duplicate\":\n return \"duplicate\";\n case \"manual\":\n return \"merge\";\n }\n}\n\nexport class SyncOrchestrator {\n private readonly changeDetector: ChangeDetector;\n private readonly pipeline: ConversionPipeline;\n private readonly blockConverter: BlockConverter;\n private readonly imageHandler: ImageHandler;\n private readonly fileHandler: FileHandler;\n private readonly databaseSyncer: DatabaseSyncer;\n private readonly propertyMapper: PropertyMapper;\n private readonly conflictResolver: ConflictResolver;\n private dbSchemaLoaded = false;\n private _pullImageCount = 0;\n private _pullFileCount = 0;\n // pull 중 각 페이지 markdown(<database url=.../>)에서 추출한 인라인 DB 참조.\n // key: 하이픈 제거 databaseId, value: 그 DB가 박힌 부모 페이지 id.\n // 블록 트리 재귀 없이 markdown 신호만으로 컬럼/synced_block 등 깊이 중첩된\n // child_database 까지 발견해 폴더+.base 동기화 대상으로 등록한다.\n private _inlineDbRefs = new Map<string, string>();\n // pull 발견 단계에서 모든 페이지의 부모를 해소하며 채우는 \"자식을 가진 페이지\" 집합\n // (정규화된 page id). 폴더노트/폴더 판정의 단일 신뢰 원천 — 얕은 블록 검사로 callout·\n // column 등 컨테이너에 중첩된 자식 페이지를 놓쳐 폴더노트를 file 로 오분류하던 결함\n // (본문이 최상위로 밀려 ' (1).md' 로 분리)을 차단한다. detectRemoteChanges* 진입 시 재구성.\n private _childParentIds = new Set<string>();\n\n // 서브트리 직접 순회(getChildPagesRecursive) 시간 예산. 초과하면 search 기반 디스커버리로\n // 폴백한다. 분기점 근거: 워크스페이스 search 열거는 latency-bound 로 대략 이 수준(수천 페이지\n // 워크스페이스에서 ~100s)이므로, 순회가 이 시간을 넘기면 search 가 더 저렴해진다. 작은 볼트는\n // 이 예산 안에서 순회가 끝나 폴백 없이 빠르게 완료된다. (단위: ms)\n private static readonly DISCOVERY_RECURSIVE_BUDGET_MS = 90_000;\n\n constructor(\n private readonly config: Config,\n private readonly stateDb: IStateDB,\n private readonly notionClient: NotionClient,\n private readonly vaultFs: VaultFS,\n customFetch?: typeof globalThis.fetch,\n ) {\n this.changeDetector = new ChangeDetector(stateDb);\n this.pipeline = createDefaultPipeline({\n wikilinkResolver: (text) => stateDb.resolveWikilink(text),\n });\n this.blockConverter = new BlockConverter();\n this.imageHandler = new ImageHandler(\n vaultFs,\n config.paths.attachments,\n notionClient,\n customFetch,\n {\n concurrency: config.advanced.mediaConcurrency,\n maxRetries: config.advanced.mediaMaxRetries,\n retryBaseMs: config.advanced.mediaRetryBaseMs,\n maxFileSizeBytes: config.advanced.maxFileSizeBytes,\n },\n stateDb,\n );\n this.fileHandler = new FileHandler(\n vaultFs,\n notionClient,\n stateDb,\n config.advanced.fileConcurrency,\n );\n this.propertyMapper = new PropertyMapper();\n this.databaseSyncer = new DatabaseSyncer(\n config,\n stateDb,\n notionClient,\n vaultFs,\n this.pipeline,\n this.imageHandler,\n );\n // M4: 후처리 패스(resolveNotionLinks)와 동일하게 파일 basename 으로 위키링크\n // 텍스트를 만든다. 원시 제목(.title)을 쓰면 슬래시·콜론 등 파일명 금지문자\n // 때문에 단일 패스 링크가 실제 파일을 못 가리키는 불일치가 생겼다.\n // M1: 동일 resolver 를 페이지 모드 변환 경로(notionClient.extractProperties)에도\n // 주입한다. 주입하지 않으면 페이지 모드 relation 이 raw UUID 로 남아 매 pull 마다\n // 후처리로만 해소되는 2-write churn 이 생긴다(DB 모드는 this.propertyMapper 가 처리).\n const wikilinkResolver: WikilinkResolver = {\n resolve: (title: string) => stateDb.resolveWikilink(title)?.notionPageId ?? null,\n resolvePageId: (pageId: string) => {\n const entry = stateDb.resolvePageId(pageId);\n return entry ? wikilinkTitleFromPath(entry.obsidianPath) : null;\n },\n };\n this.propertyMapper.setWikilinkResolver(wikilinkResolver);\n this.notionClient.setWikilinkResolver(wikilinkResolver);\n\n this.blockConverter.initNotionToMd(this.notionClient.getInternalClient());\n this.conflictResolver = new ConflictResolver(stateDb, vaultFs);\n }\n\n async push(options?: PushOptions): Promise<PushResult> {\n const startTime = Date.now();\n\n if (this.config.sync.direction === \"pull\") {\n return { created: 0, updated: 0, deleted: 0, failed: [], duration: Date.now() - startTime };\n }\n\n this.cleanupInterruptedSync();\n this.repairFolderRecords();\n await this.recoverInterruptedPushOps();\n\n const stats = await this.vaultFs.listMarkdownFileStats();\n const changes = await this.changeDetector.detectLocalChangesFast(stats, (path) =>\n this.vaultFs.readFile(path),\n );\n\n const conflictPaths = new Set(this.stateDb.getByStatus(\"conflict\").map((r) => r.obsidianPath));\n const eligible = options?.force ? changes : changes.filter((c) => !conflictPaths.has(c.path));\n\n const dbFolders = (this.config.notion.databases ?? []).map((d) =>\n d.localFolder.endsWith(\"/\") ? d.localFolder : d.localFolder + \"/\",\n );\n const isDbPath = (path: string) => dbFolders.some((prefix) => path.startsWith(prefix));\n\n const excludeSet = options?.excludePaths ? new Set(options.excludePaths) : null;\n const filtered = (\n options?.paths\n ? eligible.filter((c) => options.paths!.some((p) => c.path.startsWith(p)))\n : eligible\n ).filter((c) => !isDbPath(c.path) && (!excludeSet || !excludeSet.has(c.path)));\n\n const hasDbConfigs = (this.config.notion.databases?.length ?? 0) > 0;\n if (filtered.length === 0 && !hasDbConfigs) {\n return { created: 0, updated: 0, deleted: 0, failed: [], duration: Date.now() - startTime };\n }\n\n if (options?.dryRun) {\n const dryCreated = filtered.filter((c) => c.type === \"created\").length;\n const dryUpdated = filtered.filter((c) => c.type === \"modified\" || c.type === \"moved\").length;\n const dryDeleted = filtered.filter((c) => c.type === \"deleted\").length;\n let dryProgress = 0;\n const dryTotal = filtered.length;\n for (const change of filtered) {\n const op =\n change.type === \"created\"\n ? (\"create\" as const)\n : change.type === \"deleted\"\n ? (\"delete\" as const)\n : (\"update\" as const);\n options?.onProgress?.(++dryProgress, dryTotal, { path: change.path, operation: op });\n }\n return {\n created: dryCreated,\n updated: dryUpdated,\n deleted: dryDeleted,\n failed: [],\n duration: Date.now() - startTime,\n };\n }\n\n this.stateDb.setMeta(\"push_in_progress\", \"true\");\n\n const folderPaths = new Set<string>();\n for (const change of filtered) {\n const parts = change.path.split(\"/\");\n if (parts.length > 1) {\n for (let i = 1; i < parts.length; i++) {\n folderPaths.add(parts.slice(0, i).join(\"/\"));\n }\n }\n }\n\n const sortedFolders = [...folderPaths].sort(\n (a, b) => a.split(\"/\").length - b.split(\"/\").length,\n );\n for (const folderPath of sortedFolders) {\n await this.ensureFolderPage(folderPath);\n }\n\n const counts = { created: 0, updated: 0, deleted: 0 };\n const failed: FailedOperation[] = [];\n\n let completed = 0;\n const total = filtered.length;\n\n const opOf = (change: LocalChange): \"create\" | \"update\" | \"delete\" =>\n change.type === \"created\" ? \"create\" : change.type === \"deleted\" ? \"delete\" : \"update\";\n\n // 단건 변경을 적용하고 카운트를 올린다. 실패는 throw 로 호출자에 위임.\n const applyPushChange = async (change: LocalChange): Promise<void> => {\n switch (change.type) {\n case \"created\":\n await this.pushCreate(change.path);\n counts.created++;\n break;\n case \"modified\":\n await this.pushUpdate(change.path);\n counts.updated++;\n break;\n case \"moved\":\n await this.pushMove(change.path);\n counts.updated++;\n break;\n case \"deleted\": {\n const propagated = await this.pushDelete(change.path);\n if (propagated) counts.deleted++;\n break;\n }\n }\n };\n\n // 1차 처리 — 고정 크기 워커 풀(백프레셔). 실패분은 변경 객체째 재시도 큐로.\n const retryQueue: LocalChange[] = [];\n await runPool(\n filtered,\n async (change) => {\n if (options?.signal?.aborted) return;\n options?.onProgress?.(++completed, total, { path: change.path, operation: opOf(change) });\n try {\n await applyPushChange(change);\n } catch {\n retryQueue.push(change);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n\n // 재시도 — 워커 풀 병렬(기존엔 순차). 변경 객체를 그대로 들고 있어 경로 역매칭\n // 취약함이 없다. pushCreate 는 멱등하므로 부분 성공분을 다시 만들지 않는다.\n if (retryQueue.length > 0) {\n const retryWaitMs = this.config.advanced.retryWaitMs;\n getLogger().info(\n `[Im-Nobsidian] Push ${retryQueue.length}건 재시도 (${retryWaitMs / 1000}초 후)`,\n );\n await new Promise((r) => setTimeout(r, retryWaitMs));\n\n await runPool(\n retryQueue,\n async (change) => {\n try {\n await applyPushChange(change);\n getLogger().info(`[Im-Nobsidian] 재시도 성공: ${change.path}`);\n } catch (error) {\n failed.push({\n path: change.path,\n operation: opOf(change),\n error: error instanceof Error ? error.message : String(error),\n });\n getLogger().warn(`[Im-Nobsidian] 재시도 실패: ${change.path}`);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n }\n\n if (this.config.sync.syncFiles !== false) {\n try {\n const fileResults = await this.fileHandler.pushAllFiles();\n if (fileResults.length > 0) {\n getLogger().info(`[Im-Nobsidian] ${fileResults.length}개 파일 업로드 완료`);\n }\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] 파일 업로드 중 오류:\", error);\n }\n }\n\n if ((this.config.notion.databases?.length ?? 0) > 0) {\n try {\n const dbResult = await this.databaseSyncer.pushAll();\n counts.created += dbResult.created;\n counts.updated += dbResult.updated;\n failed.push(...dbResult.failed);\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] DB Push 중 오류:\", error);\n }\n }\n\n this.stateDb.setMeta(\"last_push_at\", new Date().toISOString());\n this.stateDb.setMeta(\"last_sync_at\", new Date().toISOString());\n this.stateDb.setMeta(\"push_in_progress\", \"\");\n // 완료/실패한 WAL 항목 정리 — 테이블 무한 증가 방지(미완료 항목은 보존).\n this.stateDb.clearCompletedOperations();\n\n return {\n created: counts.created,\n updated: counts.updated,\n deleted: counts.deleted,\n failed,\n duration: Date.now() - startTime,\n };\n }\n\n async pull(options?: PullOptions): Promise<PullResult> {\n const startTime = Date.now();\n const emptyResult: PullResult = {\n created: 0,\n updated: 0,\n deleted: 0,\n conflicts: [],\n writtenPaths: [],\n failed: [],\n duration: Date.now() - startTime,\n imageCount: 0,\n fileCount: 0,\n linkCount: 0,\n };\n\n if (this.config.sync.direction === \"push\") {\n return emptyResult;\n }\n\n this.cleanupInterruptedSync();\n\n const counts = { created: 0, updated: 0, deleted: 0 };\n this._pullImageCount = 0;\n this._pullFileCount = 0;\n this._inlineDbRefs.clear();\n const conflicts: Conflict[] = [];\n const writtenPaths: string[] = [];\n const failed: FailedOperation[] = [];\n\n // M2: pull 의 모든 종료 경로가 동일하게 마감되도록 단일 헬퍼로 모은다 —\n // 기록된 파일(writtenPaths)의 본문 링크·frontmatter relation 후처리(resolveNotionLinks)와\n // 메타 마킹을 빠짐없이 거친다. 과거엔 디스커버리 DB 전용 조기 반환 경로가 이 후처리를\n // 건너뛰어, 그 행들의 위키링크/relation 이 UUID 그대로 남았다.\n const finalize = async (\n created: number,\n updated: number,\n deleted: number,\n ): Promise<PullResult> => {\n const linkCount = writtenPaths.length > 0 ? await this.resolveNotionLinks(writtenPaths) : 0;\n this.stateDb.setMeta(\"last_pull_at\", new Date().toISOString());\n this.stateDb.setMeta(\"last_sync_at\", new Date().toISOString());\n this.stateDb.setMeta(\"pull_in_progress\", \"\");\n return {\n created,\n updated,\n deleted,\n conflicts,\n writtenPaths,\n failed,\n duration: Date.now() - startTime,\n imageCount: this._pullImageCount,\n fileCount: this._pullFileCount,\n linkCount,\n };\n };\n\n const lastPull = this.stateDb.getMeta(\"last_pull_at\") ?? this.stateDb.getMeta(\"last_sync_at\");\n const trackedCount = this.stateDb.getAll().length;\n // 증분(searchRecentPages) 은 in_trash 페이지를 못 보므로 삭제를 감지하지 못한다(I10).\n // deleteSync 가 켜진 경우엔 삭제 전파가 필요하니 반드시 전체 스캔(detectRemoteChanges)을\n // 타게 해 사라진 추적 페이지를 잡는다. 꺼진 경우엔 어차피 삭제를 전파하지 않으므로 빠른\n // 증분 경로가 안전하다(누락해도 사용자 설정상 무동작).\n const canUseIncremental =\n !this.isDatabaseMode &&\n !!lastPull &&\n trackedCount > 0 &&\n !options?.force &&\n !this.config.sync.deleteSync;\n const remoteChanges = canUseIncremental\n ? await this.detectRemoteChangesIncremental(lastPull!)\n : await this.detectRemoteChanges();\n\n const filtered = options?.paths\n ? remoteChanges.filter((c) => {\n const record = this.stateDb.getByNotionId(c.pageId);\n return record && options.paths!.some((p) => record.obsidianPath.startsWith(p));\n })\n : remoteChanges;\n\n if (filtered.length === 0 && (this.config.notion.databases?.length ?? 0) === 0) {\n // 본문 페이지 변경이 없어도 디스커버리된 DB 행은 새로 기록될 수 있다. 그 행들의\n // 본문 링크·frontmatter relation 을 finalize() 의 resolveNotionLinks 가 해소한다(M2).\n // (기록이 0건이면 writtenPaths 가 비어 linkCount 0 으로 마감 — emptyResult 와 동일)\n const dbDiscovery = await this.pullDiscoveredDatabases(writtenPaths, failed, conflicts);\n return finalize(dbDiscovery.created, dbDiscovery.updated, 0);\n }\n if (filtered.length === 0) {\n return emptyResult;\n }\n\n if (options?.dryRun) {\n const dryCreated = filtered.filter((c) => c.type === \"created\").length;\n const dryUpdated = filtered.filter((c) => c.type === \"modified\").length;\n const dryDeleted = filtered.filter((c) => c.type === \"deleted\").length;\n let dryProgress = 0;\n const dryTotal = filtered.length;\n for (const change of filtered) {\n const op =\n change.type === \"created\"\n ? (\"create\" as const)\n : change.type === \"deleted\"\n ? (\"delete\" as const)\n : (\"update\" as const);\n const record = this.stateDb.getByNotionId(change.pageId);\n const displayPath = record?.obsidianPath ?? change.pageId;\n options?.onProgress?.(++dryProgress, dryTotal, { path: displayPath, operation: op });\n }\n return {\n created: dryCreated,\n updated: dryUpdated,\n deleted: dryDeleted,\n conflicts: [],\n writtenPaths: [],\n failed: [],\n duration: Date.now() - startTime,\n imageCount: 0,\n fileCount: 0,\n linkCount: 0,\n };\n }\n\n this.stateDb.setMeta(\"pull_in_progress\", \"true\");\n\n const pullTotal = filtered.length;\n let pullCompleted = 0;\n\n // 변경 메타를 FailedOperation 으로 변환(경로·작업종류·에러 메시지).\n const toFailure = (change: RemoteChange, error: unknown): FailedOperation => {\n const record = this.stateDb.getByNotionId(change.pageId);\n return {\n path: record?.obsidianPath ?? change.pageId,\n operation:\n change.type === \"created\" ? \"create\" : change.type === \"deleted\" ? \"delete\" : \"update\",\n error: error instanceof Error ? error.message : String(error),\n };\n };\n\n // 단일 변경을 적용하고 진행률 표시용 경로를 돌려준다. 실패는 throw 로 호출자에 위임.\n const applyChange = async (change: RemoteChange): Promise<string | undefined> => {\n switch (change.type) {\n case \"created\": {\n const path = await this.pullCreate(change.pageId);\n writtenPaths.push(path);\n counts.created++;\n return path;\n }\n case \"modified\": {\n const result = await this.pullUpdate(change);\n if (result.conflict) {\n conflicts.push(result.conflict);\n } else if (result.path && !result.unchanged) {\n // unchanged=true 는 content_hash 동일 no-op(가짜 수정) — 파일 재기록·churn 없음.\n // updated 카운트에 넣지 않아 보고가 정직해진다(I5).\n writtenPaths.push(result.path);\n counts.updated++;\n }\n return result.path;\n }\n case \"deleted\": {\n const record = this.stateDb.getByNotionId(change.pageId);\n const path = await this.pullDelete(change.pageId);\n if (path) {\n counts.deleted++;\n return path;\n }\n return record?.obsidianPath;\n }\n default:\n return undefined;\n }\n };\n\n // 1차 처리 — 고정 크기 워커 풀(백프레셔). 실패한 변경은 재시도 큐로 모은다.\n const retryQueue: RemoteChange[] = [];\n await runPool(\n filtered,\n async (change) => {\n if (options?.signal?.aborted) return;\n try {\n const resultPath = await applyChange(change);\n const record = this.stateDb.getByNotionId(change.pageId);\n const displayPath = resultPath ?? record?.obsidianPath ?? change.pageId;\n const op =\n change.type === \"created\"\n ? (\"create\" as const)\n : change.type === \"deleted\"\n ? (\"delete\" as const)\n : (\"update\" as const);\n options?.onProgress?.(++pullCompleted, pullTotal, { path: displayPath, operation: op });\n } catch {\n retryQueue.push(change);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n\n // 재시도 — 1차와 동일하게 워커 풀로 병렬 실행(기존엔 순차였다). 변경 객체를\n // 그대로 들고 있으므로 경로 문자열로 역매칭하던 취약함이 사라진다.\n if (retryQueue.length > 0) {\n const retryWaitMs = this.config.advanced.retryWaitMs;\n getLogger().info(\n `[Im-Nobsidian] Pull ${retryQueue.length}건 재시도 (${retryWaitMs / 1000}초 후)`,\n );\n await new Promise((r) => setTimeout(r, retryWaitMs));\n\n await runPool(\n retryQueue,\n async (change) => {\n try {\n await applyChange(change);\n const record = this.stateDb.getByNotionId(change.pageId);\n getLogger().info(\n `[Im-Nobsidian] 재시도 성공: ${record?.obsidianPath ?? change.pageId}`,\n );\n } catch (error) {\n const failure = toFailure(change, error);\n failed.push(failure);\n getLogger().warn(`[Im-Nobsidian] 재시도 실패: ${failure.path}`);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n }\n\n if ((this.config.notion.databases?.length ?? 0) > 0) {\n try {\n const dbResult = await this.databaseSyncer.pullAll();\n counts.created += dbResult.created;\n counts.updated += dbResult.updated;\n conflicts.push(...dbResult.conflicts);\n failed.push(...dbResult.failed);\n // M3: 후처리 대상은 실제 기록된 행 경로를 그대로 받는다. 과거엔 \"synced 상태의\n // db-row 중 마지막 N개\" 라는 슬라이스 추정을 썼는데, 정렬·기존행 혼입 때문에\n // 엉뚱한 파일을 후처리하거나 갓 쓴 행을 놓쳐 링크가 미해소로 남았다.\n writtenPaths.push(...dbResult.writtenPaths);\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] DB Pull 중 오류:\", error);\n }\n }\n\n {\n const dbDiscovery = await this.pullDiscoveredDatabases(writtenPaths, failed, conflicts);\n counts.created += dbDiscovery.created;\n counts.updated += dbDiscovery.updated;\n }\n\n return finalize(counts.created, counts.updated, counts.deleted);\n }\n\n async sync(options?: SyncOptions): Promise<SyncResult> {\n const startTime = Date.now();\n const pullResult = await this.pull(options);\n const pushResult = await this.push({\n ...options,\n paths: options?.paths,\n excludePaths: pullResult.writtenPaths,\n });\n\n return {\n pull: pullResult,\n push: pushResult,\n conflicts: pullResult.conflicts,\n duration: Date.now() - startTime,\n };\n }\n\n async status(): Promise<StatusResult> {\n const files = await this.vaultFs.listMarkdownFiles();\n const localChanges = this.changeDetector.detectLocalChanges(files);\n const lastSyncAt = this.stateDb.getMeta(\"last_sync_at\");\n // 증분은 삭제(in_trash)를 못 본다(I10). deleteSync 시 status 가 원격 삭제를 보고할 수\n // 있도록 전체 스캔으로 우회한다. 꺼진 경우엔 삭제를 행동에 옮기지 않으므로 증분으로 충분.\n const remoteChanges =\n lastSyncAt && !this.config.sync.deleteSync\n ? await this.detectRemoteChangesIncremental(lastSyncAt)\n : await this.detectRemoteChanges();\n const conflictRecords = this.stateDb.getByStatus(\"conflict\");\n\n const conflicts: Conflict[] = await this.buildConflictsFromRecords(\n conflictRecords,\n localChanges,\n remoteChanges,\n );\n\n return {\n localChanges,\n remoteChanges,\n conflicts,\n conflictRecords,\n pendingOperations: conflictRecords.length,\n lastSyncAt,\n };\n }\n\n async statusLocal(): Promise<StatusResult> {\n const stats = await this.vaultFs.listMarkdownFileStats();\n const localChanges = await this.changeDetector.detectLocalChangesFast(stats, (path) =>\n this.vaultFs.readFile(path),\n );\n const conflictRecords = this.stateDb.getByStatus(\"conflict\");\n const lastSyncAt = this.stateDb.getMeta(\"last_sync_at\");\n\n return {\n localChanges,\n remoteChanges: [],\n conflicts: [],\n conflictRecords,\n pendingOperations: conflictRecords.length,\n lastSyncAt,\n };\n }\n\n async fetch(): Promise<{\n newPages: number;\n deletedPages: number;\n modifiedPages: number;\n duration: number;\n }> {\n const startTime = Date.now();\n const changes = await this.detectRemoteChanges();\n this.stateDb.setMeta(\"last_fetch_at\", new Date().toISOString());\n return {\n newPages: changes.filter((c) => c.type === \"created\").length,\n modifiedPages: changes.filter((c) => c.type === \"modified\").length,\n deletedPages: changes.filter((c) => c.type === \"deleted\").length,\n duration: Date.now() - startTime,\n };\n }\n\n private async buildConflictsFromRecords(\n records: SyncRecord[],\n localChanges: LocalChange[],\n remoteChanges: RemoteChange[],\n ): Promise<Conflict[]> {\n const conflicts: Conflict[] = [];\n\n for (const record of records) {\n const localChange = localChanges.find((c) => c.path === record.obsidianPath) ?? {\n path: record.obsidianPath,\n type: \"modified\" as const,\n currentHash: record.contentHash,\n previousHash: record.contentHash,\n };\n\n const remoteChange = remoteChanges.find((c) => c.pageId === record.notionPageId) ?? {\n pageId: record.notionPageId ?? \"\",\n type: \"modified\" as const,\n lastEdited: record.notionLastEdited ?? \"\",\n previousEdited: null,\n };\n\n let localContent = \"\";\n try {\n localContent = await this.vaultFs.readFile(record.obsidianPath);\n } catch {\n // 파일이 삭제된 경우\n }\n\n let remoteContent = \"\";\n if (record.notionPageId) {\n try {\n remoteContent = await this.fetchPageMarkdown(record.notionPageId);\n } catch {\n // 페이지가 삭제된 경우\n }\n }\n\n conflicts.push({\n syncRecord: record,\n localChange,\n remoteChange,\n baseContent: record.baseSnapshot?.toString(\"utf-8\") ?? null,\n localContent,\n remoteContent,\n });\n }\n\n return conflicts;\n }\n\n private get isDatabaseMode(): boolean {\n return this.config.notion.parentMode === \"database\" && !!this.config.notion.databaseId;\n }\n\n private async discoverChildDatabases(): Promise<Array<{ dbId: string; parentPageId: string }>> {\n const allDbs: Array<{ dbId: string; parentPageId: string }> = [];\n const trackedPages = this.stateDb.getAll().filter((r) => r.notionPageId);\n const pageIds = [this.config.notion.rootPageId, ...trackedPages.map((r) => r.notionPageId!)];\n const seen = new Set<string>();\n\n for (const parentId of pageIds) {\n if (seen.has(parentId)) continue;\n seen.add(parentId);\n try {\n const dbIds = await this.notionClient.getChildDatabaseIds(parentId);\n for (const dbId of dbIds) {\n allDbs.push({ dbId, parentPageId: parentId });\n }\n } catch {\n // 접근 권한 없는 블록 무시\n }\n }\n\n return allDbs;\n }\n\n /**\n * 자동 발견된 child_database 1개를 DatabaseSyncer 설정으로 변환한다.\n * 블록 스캔/markdown 양쪽 발견 경로에서 공통으로 사용한다.\n * - localFolder: 부모 페이지의 obsidianPath 기준으로 폴더를 잡아 원본 중첩 구조를 보존\n * (예: 부모 \"AI Engineer (1).md\" + DB \"Minirecord Project\" → \"AI Engineer (1)/Minirecord-Project\")\n * - 제목 취득 실패 시 부모 폴더명 기반 안전 이름으로 폴백\n */\n private async buildDiscoveredDbConfig(\n dbId: string,\n parentPageId: string,\n ): Promise<DiscoveredDbOutcome> {\n let dbTitle: string;\n try {\n // 제목 + 접근 가능한 data source 유무를 1회 호출로 확인한다. data source 가 없으면\n // 행 조회가 404 로 실패하고 빈 폴더/.base 만 남기므로, 발견 단계에서 미리 제외한다.\n const info = await this.notionClient.getDatabaseSyncability(dbId);\n if (!info.queryable) {\n return { kind: \"inaccessible\" };\n }\n dbTitle = info.title;\n } catch (error) {\n // 삭제된 DB 도 404 → 접근 불가로 강등(재시도하지 않음). 그 외는 일시 오류로 본다.\n if (isNotionObjectNotFound(error)) return { kind: \"inaccessible\" };\n getLogger().warn(`[Im-Nobsidian] 자동 발견 DB ${dbId} 설정 생성 실패:`, error);\n return { kind: \"error\" };\n }\n\n const parentEntry = parentPageId ? this.stateDb.getByNotionId(parentPageId) : null;\n let parentFolder = \"\";\n if (parentEntry?.obsidianPath) {\n const obsPath = parentEntry.obsidianPath;\n if (obsPath.endsWith(\".md\")) {\n const parts = obsPath.split(\"/\");\n parts.pop();\n parentFolder = parts.length > 0 ? parts.join(\"/\") : obsPath.replace(/\\.md$/, \"\");\n } else {\n parentFolder = obsPath;\n }\n }\n let safeName: string;\n if (dbTitle) {\n safeName = dbTitle.replace(/[^a-zA-Z0-9가-힣\\s_-]/g, \"\").replace(/\\s+/g, \"-\");\n } else {\n const parentName = parentFolder.split(\"/\").pop() || \"\";\n safeName = parentName ? `${parentName}-DB` : `db-${dbId.replace(/-/g, \"\").slice(0, 8)}`;\n }\n if (!safeName) safeName = `db-${dbId.replace(/-/g, \"\").slice(0, 8)}`;\n if (!parentFolder) parentFolder = \"databases\";\n return {\n kind: \"ok\",\n config: {\n databaseId: dbId,\n localFolder: `${parentFolder}/${safeName}`,\n titleProperty: \"Name\",\n },\n };\n }\n\n /** 접근 불가 DB denylist 를 상태 메타에서 로드한다(하이픈 정규화). */\n private loadInaccessibleDbIds(): Set<string> {\n const raw = this.stateDb.getMeta(INACCESSIBLE_DBS_META_KEY);\n if (!raw) return new Set();\n try {\n const arr = JSON.parse(raw) as string[];\n return new Set(arr.map((id) => id.replace(/-/g, \"\")));\n } catch {\n return new Set();\n }\n }\n\n private async pullDiscoveredDatabases(\n writtenPaths: string[],\n failed: FailedOperation[],\n conflicts: Conflict[],\n ): Promise<{ created: number; updated: number }> {\n if (this.isDatabaseMode) return { created: 0, updated: 0 };\n\n let created = 0;\n let updated = 0;\n\n try {\n const cachedRaw = this.stateDb.getMeta(\"discovered_dbs\");\n let dbConfigs: Array<{ databaseId: string; localFolder: string; titleProperty: string }> = [];\n\n if (cachedRaw) {\n try {\n dbConfigs = JSON.parse(cachedRaw);\n } catch {\n dbConfigs = [];\n }\n }\n\n const configuredIds = new Set(\n (this.config.notion.databases ?? []).map((d) => d.databaseId.replace(/-/g, \"\")),\n );\n const knownIds = new Set<string>([\n ...configuredIds,\n ...dbConfigs.map((c) => c.databaseId.replace(/-/g, \"\")),\n ]);\n let changed = false;\n\n // 접근 불가(링크드/미공유/삭제) DB denylist — 매 pull 마다 doomed 404 재시도 +\n // 스택트레이스 노이즈를 차단한다. 발견 단계에서 걸러 빈 폴더/.base 오염도 막는다.\n const inaccessibleIds = this.loadInaccessibleDbIds();\n let inaccessibleChanged = false;\n const degrade = (rawId: string): void => {\n const nohyph = rawId.replace(/-/g, \"\");\n if (!inaccessibleIds.has(nohyph)) {\n inaccessibleIds.add(nohyph);\n inaccessibleChanged = true;\n }\n getLogger().info(\n `[Im-Nobsidian] DB ${rawId}: 접근 가능한 data source 없음(링크드/미공유/삭제 추정) — 동기화 대상에서 제외(제목은 부모 페이지에 보존)`,\n );\n };\n\n // (1) 블록 스캔 기반 발견 — 추적 페이지마다 직속 children 1회 조회로 비용이 크므로\n // 캐시가 비었을 때(최초 full pull)만 수행한다.\n if (dbConfigs.length === 0) {\n const discovered = await this.discoverChildDatabases();\n for (const { dbId, parentPageId } of discovered) {\n const nohyph = dbId.replace(/-/g, \"\");\n if (knownIds.has(nohyph) || inaccessibleIds.has(nohyph)) continue;\n const outcome = await this.buildDiscoveredDbConfig(dbId, parentPageId);\n knownIds.add(nohyph);\n if (outcome.kind === \"ok\") {\n dbConfigs.push(outcome.config);\n changed = true;\n } else if (outcome.kind === \"inaccessible\") {\n degrade(dbId);\n }\n }\n }\n\n // (2) markdown 기반 발견 — 추가 API 호출 없이 컬럼/synced_block 내부 깊이 중첩된\n // child_database 까지 포착한다. 이번 pull 에서 재취득된 페이지에 한해 채워지므로\n // 캐시 유무와 무관하게 항상 병합한다(증분 pull·업그레이드 시 신규 DB 흡수).\n for (const [nohyph, parentPageId] of this._inlineDbRefs) {\n if (knownIds.has(nohyph) || inaccessibleIds.has(nohyph)) continue;\n const dbId = normalizeNotionId(nohyph);\n const outcome = await this.buildDiscoveredDbConfig(dbId, parentPageId);\n knownIds.add(nohyph);\n if (outcome.kind === \"ok\") {\n dbConfigs.push(outcome.config);\n changed = true;\n } else if (outcome.kind === \"inaccessible\") {\n degrade(dbId);\n }\n }\n\n // 동기화 가능한 DB 만 처리하고, 캐시에 잔존하던 접근 불가 DB 는 건너뛴다.\n // 처리에 성공/일시실패한 DB 만 stillSyncable 로 모아 캐시의 권위적 스냅샷으로 삼는다.\n const stillSyncable: typeof dbConfigs = [];\n for (const dbConfig of dbConfigs) {\n if (inaccessibleIds.has(dbConfig.databaseId.replace(/-/g, \"\"))) continue;\n try {\n const dbResult = await this.databaseSyncer.pullDatabase(dbConfig);\n created += dbResult.created;\n updated += dbResult.updated;\n conflicts.push(...dbResult.conflicts);\n failed.push(...dbResult.failed);\n // M3: 슬라이스 추정 대신 실제 기록된 행 경로를 후처리 대상으로 받는다.\n writtenPaths.push(...dbResult.writtenPaths);\n stillSyncable.push(dbConfig);\n } catch (error) {\n if (isNotionObjectNotFound(error)) {\n // 캐시에 있었지만 이제 행 조회가 404 — 링크드/미공유/삭제로 강등(스택트레이스 억제).\n degrade(dbConfig.databaseId);\n } else {\n // 일시적/실제 오류 — 캐시에 유지해 다음 pull 에 재시도한다.\n getLogger().warn(`[Im-Nobsidian] DB ${dbConfig.databaseId} 동기화 실패:`, error);\n stillSyncable.push(dbConfig);\n }\n }\n }\n\n // 발견·강등·정리 결과를 캐시에 1회 반영(접근 불가 DB 는 stillSyncable 에서 빠져 제거됨).\n if (changed || inaccessibleChanged || stillSyncable.length !== dbConfigs.length) {\n this.stateDb.setMeta(\"discovered_dbs\", JSON.stringify(stillSyncable));\n }\n if (inaccessibleChanged) {\n this.stateDb.setMeta(INACCESSIBLE_DBS_META_KEY, JSON.stringify([...inaccessibleIds]));\n }\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] child_database 자동 발견 실패:\", error);\n }\n\n return { created, updated };\n }\n\n private async resolveNotionLinks(paths: string[]): Promise<number> {\n let totalResolved = 0;\n const allRecords = this.stateDb.getAll();\n const idToTitle = new Map<string, string>();\n for (const r of allRecords) {\n if (r.notionPageId && r.obsidianPath) {\n // M4: 단일 변환 패스(resolvePageId)와 동일한 규칙으로 위키링크 텍스트를 만든다.\n const title = wikilinkTitleFromPath(r.obsidianPath);\n const cleanId = r.notionPageId.replace(/-/g, \"\");\n idToTitle.set(cleanId, title);\n idToTitle.set(r.notionPageId, title);\n }\n }\n if (idToTitle.size === 0) return 0;\n\n for (const filePath of paths) {\n if (!filePath.endsWith(\".md\")) continue;\n try {\n let content = await this.vaultFs.readFile(filePath);\n let changed = false;\n\n const resolved = content.replace(/\\[\\[notion:([a-f0-9-]+)\\]\\]/g, (_match, id: string) => {\n const title = idToTitle.get(id.replace(/-/g, \"\"));\n if (title) {\n totalResolved++;\n changed = true;\n return `[[${title}]]`;\n }\n return _match;\n });\n content = resolved;\n\n // Notion 내부 페이지 링크는 `/<id>?pvs=N` 또는 `/p/<id>?...`(신형) 형태로 온다.\n // 선택적 `p/` 접두사와 임의 쿼리스트링(또는 쿼리 없음)을 모두 허용한다.\n const resolved2 = content.replace(\n /\\[([^\\]]+)\\]\\(\\/(?:p\\/)?([a-f0-9]{32})(?:\\?[^)]*)?\\)/g,\n (_match, text: string, id: string) => {\n const title = idToTitle.get(id);\n if (title) {\n totalResolved++;\n changed = true;\n return `[[${title}|${text}]]`;\n }\n return _match;\n },\n );\n content = resolved2;\n\n // frontmatter 의 relation/people 원시 UUID → `[[제목]]`. 변환 시점에는 대상\n // 페이지가 미등록이라 UUID 로 남지만, 이 post-pass 시점엔 맵이 완성돼 해소된다.\n const fm = resolveFrontmatterRelations(content, idToTitle);\n if (fm.count > 0) {\n content = fm.content;\n totalResolved += fm.count;\n changed = true;\n }\n\n if (changed) {\n await this.vaultFs.writeFile(filePath, content);\n // 링크 정규화로 디스크 내용이 바뀌었으므로 해당 sync record 의 해시·스냅샷·stat\n // 을 새 내용으로 재동기화한다. 이걸 빠뜨리면 디스크(위키링크 형태)와 저장 해시\n // (`/p/<id>` 형태)가 영구 불일치해 매 sync마다 \"modified\" 로 재감지되는\n // fixpoint 위반(I5)이 발생한다. push 가 가능한 파일은 다음 push 로 self-heal\n // 되지만, child page 를 가진 폴더노트는 push 가 실패해 영영 churn 한다.\n const record = this.stateDb.getByPath(filePath);\n if (record) {\n const stat = await this.vaultFs.getFileStat(filePath);\n this.stateDb.transaction(() => {\n this.stateDb.updateHash(\n record.id,\n computeHash(content),\n Buffer.from(content, \"utf-8\"),\n );\n if (stat) this.stateDb.updateStatCache(record.id, stat.mtime, stat.size);\n });\n }\n }\n } catch {\n // 파일 읽기/쓰기 실패 무시\n }\n }\n return totalResolved;\n }\n\n private async ensureDbSchema(): Promise<void> {\n if (this.dbSchemaLoaded || !this.isDatabaseMode) return;\n const schema = await this.notionClient.getDatabaseSchema(this.config.notion.databaseId!);\n this.propertyMapper.loadSchema(schema);\n this.dbSchemaLoaded = true;\n }\n\n private async pushCreate(path: string): Promise<void> {\n // 멱등성/원자성: 이전 시도가 페이지 생성까지는 성공해 notionPageId 가 이미\n // 매핑돼 있으면(이미지 업로드 실패·크래시·인-런 재시도 등) 새 페이지를 또\n // 만들지 않고 업데이트 경로로 위임한다 → 고아 페이지·중복 생성 방지.\n const existingRecord = this.stateDb.getByPath(path);\n if (existingRecord?.notionPageId) {\n await this.pushUpdate(path);\n return;\n }\n\n const content = await this.vaultFs.readFile(path);\n const title = extractTitle(path);\n const parentId = await this.resolveNotionParent(path);\n\n const selectedPath = this.pipeline.selectPath(content);\n if (selectedPath === \"block-api\") {\n getLogger().warn(\n `[Im-Nobsidian] \"${path}\" contains block-api features (inline-db/column/toggle) — converted with reduced fidelity in v0.1.0`,\n );\n }\n\n const conversionResult = this.pipeline.convertToNotion(content, {\n direction: \"push\",\n path: selectedPath,\n filePath: path,\n parentMode: this.config.notion.parentMode,\n });\n\n let effectiveParentId = parentId;\n let effectiveParentType: \"page\" | \"database\" = \"page\";\n let effectiveProperties = conversionResult.properties;\n\n if (this.isDatabaseMode) {\n await this.ensureDbSchema();\n effectiveParentId = this.config.notion.databaseId!;\n effectiveParentType = \"database\";\n effectiveProperties = this.propertyMapper.toNotionProperties(\n conversionResult.properties,\n title,\n );\n }\n\n // I12 WAL(쓰기-우선): 페이지를 만들기 전에 자리표시 state(notion_page_id=null) +\n // pending_operations(create) 를 먼저 기록한다. 생성 요청이 적용됐는데 응답이 유실되거나\n // (timeout) 프로세스가 죽어 매핑 기록 전에 중단되면, 다음 push 시작 시 recoverInterruptedPushOps\n // 가 부모에서 제목으로 고아 페이지를 찾아 입양하므로 중복 페이지 생성을 차단한다.\n const placeholder = this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: null,\n notionParentId: parentId,\n contentHash: \"\",\n notionLastEdited: null,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: this.isFolderNote(path) ? \"folder-note\" : \"file\",\n status: \"pending\",\n baseSnapshot: null,\n localMtime: null,\n localFileSize: null,\n });\n // 인-런 재시도 시 같은 state 에 대한 op 중복 기록을 막는다(기존 미완료 op 재사용).\n const existingOp = this.stateDb.getIncompleteOpByState(placeholder.id, \"create\");\n const walOpId =\n existingOp?.id ??\n this.stateDb.recordPendingOperation({\n syncStateId: placeholder.id,\n operation: \"create\",\n direction: \"push\",\n payload: JSON.stringify({ path, parentId, title }),\n });\n\n const page = await this.pushCreatePage(\n effectiveParentId,\n effectiveParentType,\n title,\n conversionResult.content,\n effectiveProperties,\n );\n\n // 페이지 생성 직후 매핑을 먼저 기록(전이 상태 pending). 이후 이미지 업로드 등이\n // 실패해도 이 레코드 덕에 다음 시도는 pushCreate(중복) 가 아니라 pushUpdate 로\n // 이어진다. contentHash 를 비워 변경감지가 \"미완료 → 재푸시 필요\"로 인식하게 한다.\n this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: page.id,\n notionParentId: parentId,\n contentHash: \"\",\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: this.isFolderNote(path) ? \"folder-note\" : \"file\",\n status: \"pending\",\n baseSnapshot: null,\n localMtime: null,\n localFileSize: null,\n });\n\n await this.imageHandler.uploadAndAppendImages(page.id, conversionResult.images);\n\n const hash = computeHash(content);\n const fileStat = await this.vaultFs.getFileStat(path);\n\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: page.id,\n notionParentId: parentId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: this.isFolderNote(path) ? \"folder-note\" : \"file\",\n status: \"synced\",\n baseSnapshot: Buffer.from(content, \"utf-8\"),\n localMtime: fileStat?.mtime ?? null,\n localFileSize: fileStat?.size ?? null,\n });\n\n const aliases = extractAliases(conversionResult.properties);\n this.stateDb.upsertWikilink({\n obsidianPath: path,\n notionPageId: page.id,\n title,\n aliases,\n });\n\n this.stateDb.storePreserveMarkers(path, conversionResult.preserveMarkers);\n });\n\n // 생성·매핑·이미지·최종 synced 까지 모두 끝났으므로 WAL 을 완료 처리한다.\n this.stateDb.markPendingCompleted(walOpId);\n }\n\n private async pushUpdate(path: string): Promise<void> {\n const content = await this.vaultFs.readFile(path);\n const record = this.stateDb.getByPath(path);\n if (!record?.notionPageId) return;\n\n const updatePath = this.pipeline.selectPath(content);\n if (updatePath === \"block-api\") {\n getLogger().warn(\n `[Im-Nobsidian] \"${path}\" contains block-api features (inline-db/column/toggle) — converted with reduced fidelity in v0.1.0`,\n );\n }\n\n const conversionResult = this.pipeline.convertToNotion(content, {\n direction: \"push\",\n path: updatePath,\n filePath: path,\n parentMode: this.config.notion.parentMode,\n });\n\n await this.pushUpdatePage(record.notionPageId, conversionResult.content, record.baseSnapshot);\n\n await this.imageHandler.uploadAndAppendImages(record.notionPageId, conversionResult.images);\n\n let propsToUpdate: Record<string, unknown> | undefined;\n if (\n this.isDatabaseMode &&\n conversionResult.properties &&\n Object.keys(conversionResult.properties).length > 0\n ) {\n await this.ensureDbSchema();\n const title = extractTitle(path);\n propsToUpdate = this.propertyMapper.toNotionProperties(conversionResult.properties, title);\n } else if (conversionResult.properties?.title) {\n const titleStr = String(conversionResult.properties.title);\n propsToUpdate = {\n title: { title: [{ text: { content: titleStr } }] },\n };\n }\n\n // notionLastEdited 는 반드시 Notion 서버가 돌려준 값으로 저장한다. 로컬 시각\n // (new Date())을 쓰면 서버 시각과 클록 스큐·네트워크 지연만큼 어긋나 다음 pull 이\n // 가짜 modified 로 오인 → 불필요 재조회·집계(false-churn). 속성 갱신이 있으면 그\n // 응답이 최종 mutation 이라 권위값이고, 없으면(블록/이미지만 변경) 1회 getPage 로\n // 권위값을 받아 진짜 fixpoint 를 만든다. (I5 — pull 측 content_hash 가드와 이중 차단)\n let lastEditedTime: string;\n if (propsToUpdate && Object.keys(propsToUpdate).length > 0) {\n const updatedPage = await this.notionClient.updatePageProperties(\n record.notionPageId,\n propsToUpdate,\n );\n lastEditedTime = updatedPage.last_edited_time;\n } else {\n const refreshed = await this.notionClient.getPage(record.notionPageId);\n lastEditedTime = refreshed.last_edited_time;\n }\n\n const hash = computeHash(content);\n const fileStat = await this.vaultFs.getFileStat(path);\n const title = extractTitle(path);\n const aliases = extractAliases(conversionResult.properties);\n this.stateDb.transaction(() => {\n this.stateDb.updateHash(record.id, hash, Buffer.from(content, \"utf-8\"));\n this.stateDb.updateStatus(record.id, \"synced\");\n this.stateDb.setNotionLastEdited(record.id, lastEditedTime);\n if (fileStat) {\n this.stateDb.updateStatCache(record.id, fileStat.mtime, fileStat.size);\n }\n this.stateDb.storePreserveMarkers(path, conversionResult.preserveMarkers);\n this.stateDb.upsertWikilink({\n obsidianPath: path,\n notionPageId: record.notionPageId!,\n title,\n aliases,\n });\n });\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // 충돌 해소 (I8) — 해소 결과를 로컬에만 쓰지 않고 Notion 으로 재push + notionLastEdited\n // 재조정까지 한 트랜잭션으로 묶는다. ConflictResolver 단독은 로컬 write + updateHash 만\n // 수행하므로(merge 결과가 Notion 에 반영되지 않음) 다음 pull 이 원격으로 덮어써 영구\n // 유실·충돌 루프가 발생한다. 해소 → 전파(propagate)를 오케스트레이터에서 봉합해 무손실\n // 보장. 변환 파이프라인이 필요한 push 는 기존 엔터프라이즈 경로(pushUpdate)를 재사용한다.\n // ──────────────────────────────────────────────────────────────────────────\n\n /** 단일 충돌을 사용자가 고른 선택지(local/remote/merge/duplicate)로 해소 + Notion 전파. */\n async resolveConflict(conflict: Conflict, choice: ResolutionChoice): Promise<ResolutionResult> {\n const result = await this.conflictResolver.resolve(conflict, choice);\n await this.propagateResolution(conflict, choice, result);\n return result;\n }\n\n /** 단일 충돌을 전략(manual/local-first/remote-first/duplicate)으로 해소 + Notion 전파. */\n async resolveConflictByStrategy(\n conflict: Conflict,\n strategy: ConflictStrategy,\n ): Promise<ResolutionResult> {\n const result = await this.conflictResolver.resolveByStrategy(conflict, strategy);\n await this.propagateResolution(conflict, strategyToChoice(strategy), result);\n return result;\n }\n\n /** 여러 충돌을 동일 전략으로 일괄 해소 + Notion 전파. */\n async resolveAllConflicts(\n conflicts: Conflict[],\n strategy: ConflictStrategy,\n ): Promise<ResolutionResult[]> {\n const results: ResolutionResult[] = [];\n for (const conflict of conflicts) {\n results.push(await this.resolveConflictByStrategy(conflict, strategy));\n }\n return results;\n }\n\n /** 충돌 미리보기용 통합 diff(원본 vs 로컬 vs 원격). 해소 없이 표시 전용. */\n generateConflictDiff(conflict: Conflict): string {\n return this.conflictResolver.generateDiff(conflict);\n }\n\n /**\n * 해소 결과를 Notion 으로 전파해 로컬↔원격 일관성을 봉합한다.\n * - remote 선택: 로컬이 원격으로 갱신됐을 뿐이므로 push 불필요. notionLastEdited 만\n * 원격 변경의 lastEdited 로 재조정 → 다음 pull 이 같은 변경을 재충돌로 보지 않음.\n * - merge 실패(충돌 마커 잔존): 사용자가 직접 풀어야 하므로 conflict 상태 유지·push 안 함.\n * - local / merge(성공) / duplicate: 해소된 로컬 내용을 Notion 에 재push(pushUpdate 가\n * 변환·이미지·속성·해시·notionLastEdited 를 한 트랜잭션으로 재조정) → 무손실 수렴.\n */\n private async propagateResolution(\n conflict: Conflict,\n choice: ResolutionChoice,\n result: ResolutionResult,\n ): Promise<void> {\n const record = conflict.syncRecord;\n if (!record.notionPageId) return;\n\n if (choice === \"remote\") {\n this.stateDb.setNotionLastEdited(record.id, conflict.remoteChange.lastEdited);\n return;\n }\n\n // merge 가 충돌 마커를 남긴 경우(자동 병합 실패) → push 하지 않고 conflict 상태 유지.\n if (!result.success) return;\n\n // local / merge(성공) / duplicate: 해소된 로컬 본문을 Notion 으로 재push.\n await this.pushUpdate(record.obsidianPath);\n }\n\n // 반환값: 실제로 원격(Notion) 삭제가 전파되었는지 여부.\n // deleteSync=false 면 로컬 삭제를 pending 으로만 기록하고 Notion 은 보존하므로\n // false 를 돌려준다 → 호출부가 deleted 카운트를 올리지 않아 보고가 정직해진다.\n private async pushDelete(path: string): Promise<boolean> {\n const record = this.stateDb.getByPath(path);\n if (!record?.notionPageId) return false;\n\n if (!this.config.sync.deleteSync) {\n this.stateDb.updateStatus(record.id, \"pending\");\n return false;\n }\n\n try {\n await this.notionClient.archivePage(record.notionPageId);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes(\"archived ancestor\")) {\n // 부모 페이지가 이미 아카이브됨 → 자식도 자동 아카이브 상태\n } else {\n throw error;\n }\n }\n this.stateDb.transaction(() => {\n this.stateDb.delete(record.id);\n this.stateDb.deleteWikilink(record.obsidianPath);\n });\n return true;\n }\n\n private async pushMove(path: string): Promise<void> {\n const record = this.stateDb.getByPath(path);\n if (!record?.notionPageId) return;\n\n const newParentId = await this.resolveNotionParent(path);\n const currentParentId = record.notionParentId;\n\n if (currentParentId && !notionIdsEqual(newParentId, currentParentId)) {\n try {\n const parentType = this.isDatabaseMode ? \"database\" : \"page\";\n await this.notionClient.movePage(record.notionPageId, newParentId, parentType);\n this.stateDb.setNotionParentId(record.id, newParentId);\n } catch {\n getLogger().warn(`[Im-Nobsidian] Move API 실패 — \"${path}\" 내용만 업데이트합니다`);\n }\n }\n\n await this.pushUpdate(path);\n }\n\n private async detectRemoteChanges(): Promise<RemoteChange[]> {\n const changes: RemoteChange[] = [];\n this._childParentIds.clear();\n const lastPull = this.stateDb.getMeta(\"last_pull_at\");\n const syncedRecords = this.stateDb.getAll();\n const trackedPageIds = new Set(\n syncedRecords.filter((r) => r.notionPageId).map((r) => r.notionPageId!),\n );\n\n let remotePages: Array<{ id: string; last_edited_time: string }>;\n if (this.isDatabaseMode) {\n const allPages: Array<{ id: string; last_edited_time: string }> = [];\n let cursor: string | undefined;\n do {\n const result = await this.notionClient.queryDatabase(this.config.notion.databaseId!, {\n startCursor: cursor,\n });\n allPages.push(\n ...result.results.map((p) => ({ id: p.id, last_edited_time: p.last_edited_time })),\n );\n cursor = result.nextCursor ?? undefined;\n } while (cursor);\n remotePages = allPages;\n } else {\n // 디스커버리 이중 전략(비용 상한 하이브리드):\n // 1) 기본 — root 서브트리 직접 BFS 순회(getChildPagesRecursive). 비용이 실제 동기화\n // 대상(서브트리)에 비례해, 작은 볼트가 수천 페이지 워크스페이스에 있어도 빠르다\n // (I10: 2-파일 볼트 pull ~12s). 단 비용은 서브트리 **전체 블록 수**에 비례하므로,\n // 2) 콘텐츠가 많은 대규모 서브트리에서는 시간 예산(DISCOVERY_RECURSIVE_BUDGET_MS)을\n // 초과할 수 있다. 그 경우 워크스페이스 search 기반 디스커버리로 폴백한다(비용이\n // 워크스페이스 페이지 수에 비례·예측가능·유한). 두 경로 모두 중첩 깊이와 무관하게\n // 모든 하위 페이지를 찾으므로 **무손실**이며, DB 행·archive/in_trash 를 동일하게\n // 제외해 orphan(삭제) 판정도 일관된다.\n let underRoot: PageObjectResponse[];\n try {\n underRoot = await this.notionClient.getChildPagesRecursive(this.config.notion.rootPageId, {\n deadlineMs: Date.now() + SyncOrchestrator.DISCOVERY_RECURSIVE_BUDGET_MS,\n });\n } catch (error) {\n if (!(error instanceof DiscoveryTooLargeError)) throw error;\n getLogger().info(\n `[Im-Nobsidian] 서브트리가 큼(${error.message}) → 워크스페이스 search 기반 디스커버리로 전환`,\n );\n underRoot = await this.notionClient.getPagesUnderRootViaSearch(\n this.config.notion.rootPageId,\n );\n }\n // 폴더 판정용 _childParentIds: 발견된 각 페이지의 부모(자식을 가진 페이지)를 수집한다.\n // 부모가 page_id 면 추가 API 호출 없이 즉시 해석(공통 경로), block 중첩만 1회 조회.\n this._childParentIds.add(normalizeNotionId(this.config.notion.rootPageId));\n for (const page of underRoot) {\n const parentId = await this.extractParentId(page);\n if (parentId) this._childParentIds.add(normalizeNotionId(parentId));\n }\n remotePages = underRoot.map((p) => ({ id: p.id, last_edited_time: p.last_edited_time }));\n }\n\n // 원격 페이지 목록을 page_id 로 디듀프한다. search API(페이지 모드)·queryDatabase(DB 모드)\n // 모두 페이지네이션 사이 재정렬로 같은 페이지를 중복 반환할 수 있고, 중복이 changes 로\n // 새면 같은 page_id 가 두 번 create 되어 동일 콘텐츠가 클린·`(1)` 두 경로에 기록(첫 파일\n // 고아화)된다. 여기가 페이지·DB 양 모드를 함께 막는 단일 차단점이다.\n const seenRemoteIds = new Set<string>();\n for (const page of remotePages) {\n const key = normalizeNotionId(page.id);\n if (seenRemoteIds.has(key)) continue;\n seenRemoteIds.add(key);\n\n const record = this.stateDb.getByNotionId(page.id);\n\n if (!record) {\n changes.push({\n pageId: page.id,\n type: \"created\",\n lastEdited: page.last_edited_time,\n previousEdited: null,\n });\n } else if (page.last_edited_time !== record.notionLastEdited) {\n changes.push({\n pageId: page.id,\n type: \"modified\",\n lastEdited: page.last_edited_time,\n previousEdited: record.notionLastEdited,\n });\n }\n\n trackedPageIds.delete(page.id);\n }\n\n if (this.config.sync.deleteSync && lastPull) {\n for (const orphanId of trackedPageIds) {\n const record = syncedRecords.find((r) => r.notionPageId === orphanId);\n if (record) {\n changes.push({\n pageId: orphanId,\n type: \"deleted\",\n lastEdited: new Date().toISOString(),\n previousEdited: record.notionLastEdited,\n });\n }\n }\n }\n\n return changes;\n }\n\n /**\n * 증분 원격 변경 감지 — `since` 이후 수정된 페이지만 search 로 받아 created/modified 만\n * 만든다. **삭제는 의도적으로 감지하지 않는다**: search API 는 in_trash/archived 페이지를\n * 반환하지 않아(=사라진 것을 증분만으로는 구분 불가) 삭제 판정에는 전체 enumeration 이\n * 필수다. 따라서 호출부는 `deleteSync` 가 켜진 경우 이 fast-path 를 쓰지 않고\n * `detectRemoteChanges`(전체 스캔, 삭제 diff 포함)로 우회한다. (I10)\n */\n private async detectRemoteChangesIncremental(since: string): Promise<RemoteChange[]> {\n const changes: RemoteChange[] = [];\n this._childParentIds.clear();\n const recentPages = await this.notionClient.searchRecentPages(since);\n\n for (const page of recentPages) {\n const record = this.stateDb.getByNotionId(page.id);\n if (!record) {\n try {\n const fullPage = await this.notionClient.getPage(page.id);\n const parentId = await this.extractParentId(fullPage);\n if (parentId) this._childParentIds.add(normalizeNotionId(parentId));\n if (parentId && this.isTrackedParent(parentId)) {\n changes.push({\n pageId: page.id,\n type: \"created\",\n lastEdited: page.last_edited_time,\n previousEdited: null,\n });\n }\n } catch {\n // inaccessible page\n }\n continue;\n }\n if (page.last_edited_time !== record.notionLastEdited) {\n changes.push({\n pageId: page.id,\n type: \"modified\",\n lastEdited: page.last_edited_time,\n previousEdited: record.notionLastEdited,\n });\n }\n }\n\n return changes;\n }\n\n private isTrackedParent(parentId: string): boolean {\n if (notionIdsEqual(parentId, this.config.notion.rootPageId)) return true;\n return !!this.stateDb.getByNotionId(parentId);\n }\n\n private async pullCreate(pageId: string): Promise<string> {\n const page = await this.notionClient.getPage(pageId);\n const title = this.notionClient.extractTitle(page);\n const safeName = sanitizeFileName(title);\n\n const parentPath = await this.resolveParentPath(page);\n\n const hasChildPages = await this.pageHasChildContainers(pageId);\n\n const markdown = await this.fetchPageMarkdown(pageId);\n const hasContent = markdown.trim().length > 0;\n\n let filePath: string;\n let fileType: \"file\" | \"folder-note\" | \"folder-only\";\n\n if (hasChildPages && hasContent) {\n const folderPath = parentPath ? `${parentPath}/${safeName}` : safeName;\n filePath = await this.resolveUniqueFilePath(`${folderPath}/${safeName}.md`);\n fileType = \"folder-note\";\n await this.vaultFs.ensureFolder(folderPath);\n } else if (hasChildPages && !hasContent) {\n const folderPath = parentPath ? `${parentPath}/${safeName}` : safeName;\n filePath = await this.resolveUniqueFilePath(`${folderPath}/${safeName}.md`);\n fileType = \"folder-only\";\n await this.vaultFs.ensureFolder(folderPath);\n } else {\n const basePath = parentPath ? `${parentPath}/${safeName}.md` : `${safeName}.md`;\n filePath = await this.resolveUniqueFilePath(basePath);\n fileType = \"file\";\n }\n\n let properties: Record<string, unknown>;\n if (this.isDatabaseMode) {\n await this.ensureDbSchema();\n properties = this.propertyMapper.fromNotionProperties(\n (page as unknown as { properties: Record<string, unknown> }).properties,\n );\n } else {\n properties = this.notionClient.extractProperties(page);\n }\n properties.title = title;\n\n let processedMarkdown = markdown;\n if (this.config.conversion.imageDownload === \"immediate\") {\n const imageResult = await this.imageHandler.downloadAllImages(markdown, title);\n processedMarkdown = imageResult.content;\n this._pullImageCount += imageResult.downloads.length;\n }\n\n const fileResult = await this.imageHandler.downloadAllFiles(processedMarkdown, title);\n processedMarkdown = fileResult.content;\n this._pullFileCount += fileResult.downloads.length;\n\n const finalContent = this.pipeline.convertToMarkdown(\n processedMarkdown,\n {\n direction: \"pull\",\n path: \"markdown-api\",\n filePath,\n parentMode: this.config.notion.parentMode,\n },\n { properties },\n );\n\n // 부모 해소는 파일 기록 전에 끝낸다. parent 가 block 일 때 resolveBlockToPageId 가\n // API 를 호출(429 가능)하는데, 이를 writeFile 뒤에 두면 기록만 되고 sync_state 등록 전에\n // throw → 재시도 시 같은 페이지가 `(1)` 로 재생성되며 첫 파일이 고아가 된다. 기록↔등록\n // 사이에는 throw 가능한 원격 호출을 두지 않는다(원자적 등록 보장).\n const resolvedParentId = await this.extractParentId(page);\n\n await this.vaultFs.writeFile(filePath, finalContent);\n\n const hash = computeHash(finalContent);\n const pullStat = await this.vaultFs.getFileStat(filePath);\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: filePath,\n notionPageId: pageId,\n notionParentId: resolvedParentId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType,\n status: \"synced\",\n baseSnapshot: Buffer.from(finalContent, \"utf-8\"),\n localMtime: pullStat?.mtime ?? null,\n localFileSize: pullStat?.size ?? null,\n });\n\n const aliases = extractAliases(properties);\n this.stateDb.upsertWikilink({\n obsidianPath: filePath,\n notionPageId: pageId,\n title,\n aliases,\n });\n });\n\n return filePath;\n }\n\n /**\n * 페이지가 폴더(자식 페이지·자식 DB 보유)인지 신뢰성 있게 판정한다.\n *\n * 결함(폴더노트 본문분리)의 근본 원인은 얕은 판정이었다 — 최상위 블록 첫 페이지에서\n * child_page 만 검사하면 callout·column·toggle 안에 중첩된 자식 페이지나 child_database 를\n * 놓쳐 폴더노트가 file 로 오분류되고, 본문이 폴더 밖 최상위로 밀려 resolveUniqueFilePath\n * 충돌(' (1).md')로 쪼개졌다.\n *\n * 1차: 발견 단계(서브트리 순회/증분)에서 전 페이지의 부모를 해소하며 만든\n * _childParentIds 집합으로 O(1) 판정(추가 API 호출 0, 처리 순서 무관) — 전체 pull 경로.\n * 폴백: 집합에 없을 때만(증분 pull 의 신규 폴더 등) fetchAllChildrenDeep 로 컨테이너를\n * 재귀 탐색해 child_page·child_database 를 직접 확인한다.\n */\n private async pageHasChildContainers(pageId: string): Promise<boolean> {\n if (this._childParentIds.has(normalizeNotionId(pageId))) return true;\n try {\n const deep = await this.notionClient.fetchAllChildrenDeep(pageId);\n return deep.some((b) => b.type === \"child_page\" || b.type === \"child_database\");\n } catch {\n return false;\n }\n }\n\n private async pullUpdate(\n change: RemoteChange,\n ): Promise<{ path?: string; conflict?: Conflict; unchanged?: boolean }> {\n const record = this.stateDb.getByNotionId(change.pageId);\n if (!record) return {};\n\n const page = await this.notionClient.getPage(change.pageId);\n let markdown = await this.fetchPageMarkdown(change.pageId);\n\n const title = this.notionClient.extractTitle(page);\n\n let properties: Record<string, unknown>;\n if (this.isDatabaseMode) {\n await this.ensureDbSchema();\n properties = this.propertyMapper.fromNotionProperties(\n (page as unknown as { properties: Record<string, unknown> }).properties,\n );\n } else {\n properties = this.notionClient.extractProperties(page);\n }\n properties.title = title;\n\n if (this.config.conversion.imageDownload === \"immediate\") {\n const imageResult = await this.imageHandler.downloadAllImages(markdown, title);\n markdown = imageResult.content;\n this._pullImageCount += imageResult.downloads.length;\n }\n\n const fileResult = await this.imageHandler.downloadAllFiles(markdown, title);\n markdown = fileResult.content;\n this._pullFileCount += fileResult.downloads.length;\n\n const savedMarkers = this.stateDb.getPreserveMarkers(record.obsidianPath);\n const remoteContent = this.pipeline.convertToMarkdown(\n markdown,\n {\n direction: \"pull\",\n path: \"markdown-api\",\n filePath: record.obsidianPath,\n parentMode: this.config.notion.parentMode,\n },\n { properties, preserveMarkers: savedMarkers.length > 0 ? savedMarkers : undefined },\n );\n\n let localContent: string;\n try {\n localContent = await this.vaultFs.readFile(record.obsidianPath);\n } catch {\n localContent = \"\";\n }\n\n const resolution = resolvePullConflict({\n record,\n localContent,\n remoteContent,\n remoteChange: change,\n strategy: this.config.sync.conflictStrategy,\n });\n\n if (resolution.action === \"skip\") {\n // local-first: 로컬 보존, 리모트 변경 무시\n return { path: record.obsidianPath };\n }\n if (resolution.action === \"conflict\") {\n this.stateDb.updateStatus(record.id, \"conflict\");\n return { conflict: resolution.conflict };\n }\n\n // I5 false-churn 차단: 리모트 변환 결과가 디스크 내용과 바이트 동일하면 Notion 이\n // last_edited 만 갱신한 '가짜 수정'이다. 파일을 재기록하면 mtime 이 바뀌어 다음 push 가\n // 로컬 수정으로 오인 → push↔pull 무한 churn. 파일은 건드리지 않고 추적 메타\n // (notionLastEdited)만 현재 원격값으로 정렬해 재감지를 멈춘다. content_hash 비교로\n // 진짜 변경과 가짜 변경을 구분하는 핵심 멱등 지점이다.\n if (remoteContent === localContent) {\n const stat = await this.vaultFs.getFileStat(record.obsidianPath);\n this.stateDb.upsert({\n obsidianPath: record.obsidianPath,\n notionPageId: change.pageId,\n notionParentId: record.notionParentId,\n contentHash: computeHash(remoteContent),\n notionLastEdited: page.last_edited_time,\n localLastModified: record.localLastModified,\n syncDirection: record.syncDirection,\n fileType: record.fileType,\n status: \"synced\",\n baseSnapshot: Buffer.from(remoteContent, \"utf-8\"),\n localMtime: stat?.mtime ?? record.localMtime ?? null,\n localFileSize: stat?.size ?? record.localFileSize ?? null,\n });\n return { path: record.obsidianPath, unchanged: true };\n }\n\n await this.vaultFs.writeFile(record.obsidianPath, remoteContent);\n\n const updateStat = await this.vaultFs.getFileStat(record.obsidianPath);\n const newHash = computeHash(remoteContent);\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: record.obsidianPath,\n notionPageId: change.pageId,\n notionParentId: record.notionParentId,\n contentHash: newHash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: record.syncDirection,\n fileType: record.fileType,\n status: \"synced\",\n baseSnapshot: Buffer.from(remoteContent, \"utf-8\"),\n localMtime: updateStat?.mtime ?? null,\n localFileSize: updateStat?.size ?? null,\n });\n\n const aliases = extractAliases(properties);\n this.stateDb.upsertWikilink({\n obsidianPath: record.obsidianPath,\n notionPageId: change.pageId,\n title,\n aliases,\n });\n });\n\n return { path: record.obsidianPath };\n }\n\n private async pullDelete(pageId: string): Promise<string | null> {\n const record = this.stateDb.getByNotionId(pageId);\n if (!record) return null;\n\n if (this.config.sync.deleteSync) {\n try {\n await this.vaultFs.deleteFile(record.obsidianPath);\n } catch {\n // 이미 삭제된 경우 무시\n }\n }\n\n this.stateDb.transaction(() => {\n this.stateDb.delete(record.id);\n this.stateDb.deleteWikilink(record.obsidianPath);\n });\n return record.obsidianPath;\n }\n\n private async ensureFolderPage(folderPath: string): Promise<void> {\n const folderNotePath = `${folderPath}/${folderPath.split(\"/\").pop()}.md`;\n const folderNoteRecord = this.stateDb.getByPath(folderNotePath);\n\n if (folderNoteRecord?.notionPageId) {\n const existing = this.stateDb.getByPath(folderPath);\n if (existing) {\n this.stateDb.transaction(() => {\n this.stateDb.delete(existing.id);\n this.stateDb.deleteWikilink(existing.obsidianPath);\n });\n }\n return;\n }\n\n const existing = this.stateDb.getByPath(folderPath);\n if (existing?.notionPageId) return;\n\n const parts = folderPath.split(\"/\");\n const folderName = parts[parts.length - 1]!;\n\n let parentId = this.config.notion.rootPageId;\n if (parts.length > 1) {\n const parentPath = parts.slice(0, -1).join(\"/\");\n await this.ensureFolderPage(parentPath);\n const parentNotePath = `${parentPath}/${parentPath.split(\"/\").pop()}.md`;\n const parentNote = this.stateDb.getByPath(parentNotePath);\n const parentRecord = this.stateDb.getByPath(parentPath);\n if (parentNote?.notionPageId) {\n parentId = parentNote.notionPageId;\n } else if (parentRecord?.notionPageId) {\n parentId = parentRecord.notionPageId;\n }\n }\n\n const folderPage = await this.notionClient.createPage({\n parentId,\n parentType: \"page\",\n title: folderName,\n });\n\n this.stateDb.upsert({\n obsidianPath: folderPath,\n notionPageId: folderPage.id,\n notionParentId: parentId,\n contentHash: \"\",\n notionLastEdited: folderPage.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: \"folder-note\",\n status: \"synced\",\n });\n }\n\n private async resolveNotionParent(filePath: string): Promise<string> {\n const parts = filePath.split(\"/\");\n if (parts.length <= 1) return this.config.notion.rootPageId;\n\n const folderPath = parts.slice(0, -1).join(\"/\");\n const folderRecord = this.stateDb.getByPath(folderPath);\n if (folderRecord?.notionPageId) return folderRecord.notionPageId;\n\n const folderName = parts[parts.length - 2]!;\n const folderNotePath = `${folderPath}/${folderName}.md`;\n const folderNoteRecord = this.stateDb.getByPath(folderNotePath);\n if (folderNoteRecord?.notionPageId) return folderNoteRecord.notionPageId;\n\n return this.config.notion.rootPageId;\n }\n\n private repairFolderRecords(): void {\n const allRecords = this.stateDb.getAll();\n const folderRecords = allRecords.filter(\n (r) => r.fileType === \"folder-note\" && !r.obsidianPath.endsWith(\".md\"),\n );\n for (const folder of folderRecords) {\n const folderName = folder.obsidianPath.split(\"/\").pop()!;\n const folderNotePath = `${folder.obsidianPath}/${folderName}.md`;\n const noteRecord = this.stateDb.getByPath(folderNotePath);\n if (noteRecord?.notionPageId) {\n this.stateDb.transaction(() => {\n this.stateDb.delete(folder.id);\n this.stateDb.deleteWikilink(folder.obsidianPath);\n });\n }\n }\n }\n\n private isFolderNote(filePath: string): boolean {\n const parts = filePath.split(\"/\");\n if (parts.length < 2) return false;\n const fileName = parts[parts.length - 1]!.replace(/\\.md$/, \"\");\n const folderName = parts[parts.length - 2]!;\n return fileName === folderName;\n }\n\n private async resolveParentPath(page: PageObjectResponse): Promise<string> {\n const parentId = await this.extractParentId(page);\n if (!parentId || notionIdsEqual(parentId, this.config.notion.rootPageId)) return \"\";\n\n const parentRecord = this.stateDb.getByNotionId(parentId);\n if (parentRecord) {\n if (parentRecord.fileType === \"folder-note\" || parentRecord.fileType === \"folder-only\") {\n const pathParts = parentRecord.obsidianPath.split(\"/\");\n pathParts.pop();\n return pathParts.join(\"/\");\n }\n const pathParts = parentRecord.obsidianPath.split(\"/\");\n pathParts.pop();\n const parentDir = pathParts.join(\"/\");\n return (\n parentDir ||\n sanitizeFileName(this.notionClient.extractTitle(await this.notionClient.getPage(parentId)))\n );\n }\n\n try {\n const parentPage = await this.notionClient.getPage(parentId);\n const parentTitle = this.notionClient.extractTitle(parentPage);\n const grandparentPath = await this.resolveParentPath(parentPage);\n const safeName = sanitizeFileName(parentTitle);\n return grandparentPath ? `${grandparentPath}/${safeName}` : safeName;\n } catch {\n return \"\";\n }\n }\n\n private async pushCreatePage(\n parentId: string,\n parentType: \"page\" | \"database\",\n title: string,\n markdownContent: string,\n properties?: Record<string, unknown>,\n ): Promise<PageObjectResponse> {\n if (this.config.conversion.preferMarkdownApi !== false) {\n const enhanced = obsidianToNotionEnhanced(markdownContent);\n return await this.notionClient.createPageWithMarkdown({\n parentId,\n parentType,\n title,\n markdown: enhanced,\n properties,\n });\n }\n\n const blocks = this.blockConverter.markdownToNotionBlocks(markdownContent);\n const page = await this.notionClient.createPage({\n parentId,\n parentType,\n title,\n properties,\n });\n if (blocks.length > 0) {\n await this.notionClient.appendChildren(page.id, blocks);\n }\n return page;\n }\n\n // 페이지에 살아있는(휴지통 아님) child page/database 가 직속 블록으로 존재하는가.\n // 휴지통(in_trash) 자식은 children.list 에 잡히지 않으므로 \"live\" 는 암묵적이다.\n private async pageHasLiveChildren(pageId: string): Promise<boolean> {\n try {\n const children = await this.notionClient.fetchAllChildren(pageId);\n return children.some((b) => b.type === \"child_page\" || b.type === \"child_database\");\n } catch (error) {\n // 조회 실패 시 안전측: 자식이 있을 수 있다고 보고 파괴적 replace 를 막는다.\n getLogger().warn(\n `[Im-Nobsidian] 자식 페이지 조회 실패 — 본문 push 보수적 생략(자식 보호): ${pageId} (${\n error instanceof Error ? error.message : String(error)\n })`,\n );\n return true;\n }\n }\n\n private async pushUpdatePage(\n pageId: string,\n markdownContent: string,\n _baseSnapshot?: Buffer | null,\n ): Promise<void> {\n // 데이터 손실 가드: 이 페이지가 살아있는 child page/database 를 가지면 두 push 경로\n // (replace_content[allow_deleting_content] · block 삭제-후-append)가 모두 자식을\n // 삭제한다. 실Notion probe 확인: replace_content 는 새 마크다운에 없는 child page 를\n // in_trash 로 삭제하고, child page 를 mention 으로 표현하려 하면 거부한다.\n // 자식 페이지는 각자 자기 sync record 로 독립 동기화되므로, 여기서는 본문 갱신을\n // 건너뛰고 자식을 보존한다(무손실). 폴더노트 본문 편집의 Notion 반영은 의도적 degrade.\n if (await this.pageHasLiveChildren(pageId)) {\n getLogger().warn(\n `[Im-Nobsidian] 자식 페이지 보유 — 본문 push 생략(자식 삭제 방지): ${pageId}. ` +\n `자식 페이지는 각자 동기화되며, 이 페이지 본문 편집은 Notion 에 반영되지 않습니다.`,\n );\n return;\n }\n\n if (this.config.conversion.preferMarkdownApi !== false) {\n const enhanced = obsidianToNotionEnhanced(markdownContent);\n await this.notionClient.replacePageMarkdown(pageId, enhanced);\n return;\n }\n\n const blocks = this.blockConverter.markdownToNotionBlocks(markdownContent);\n const existingBlocks = await this.notionClient.fetchAllChildren(pageId);\n\n if (blocks.length > 0) {\n await this.notionClient.appendChildren(pageId, blocks);\n }\n const deleteSema = new Sema(this.config.advanced.concurrency);\n await Promise.all(\n existingBlocks.map(async (block) => {\n await deleteSema.acquire();\n try {\n await this.notionClient.deleteBlock(block.id);\n } finally {\n deleteSema.release();\n }\n }),\n );\n }\n\n private async fetchPageMarkdown(pageId: string): Promise<string> {\n if (this.config.conversion.preferMarkdownApi !== false) {\n try {\n const result = await this.notionClient.getPageMarkdown(pageId);\n this.collectInlineDbRefs(pageId, result.markdown);\n return this.resolveNotionIdWikilinks(notionEnhancedToObsidian(result.markdown));\n } catch {\n // Markdown API 실패 시 blocks API fallback\n }\n }\n return this.blockConverter.notionBlocksToMarkdown(pageId);\n }\n\n // Markdown API는 인라인 데이터베이스를 다음처럼 렌더한다(컬럼/synced_block 내부 포함):\n // <database url=\"https://www.notion.so/<id-nohyph>\" inline=\"true\"\n // data-source-url=\"collection://<ds-id>\">Title</database>\n // url 안의 32자리 hex 가 databaseId 이므로, 별도 블록 트리 재귀 없이 이 태그만 파싱해\n // 깊이 중첩된 child_database 까지 폴더+.base 동기화 대상으로 등록한다.\n private collectInlineDbRefs(parentPageId: string, rawMarkdown: string): void {\n const re = /<database\\b[^>]*\\burl=\"https:\\/\\/www\\.notion\\.so\\/([a-f0-9]{32})\"[^>]*>/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(rawMarkdown)) !== null) {\n const dbId = m[1];\n if (dbId) this._inlineDbRefs.set(dbId, parentPageId);\n }\n }\n\n // pull 시 url 기반 page mention 은 `[[notion:<id>]]` 로 1차 변환된다(notionEnhancedToObsidian).\n // 이를 state DB 역조회로 원래 `[[제목]]` 위키링크로 복원해 push↔pull 라운드트립을 수렴시킨다.\n // 볼트 밖/미추적 페이지면 `[[notion:<id>]]` 를 그대로 두어 정보 손실을 막는다.\n private resolveNotionIdWikilinks(markdown: string): string {\n return markdown.replace(/\\[\\[notion:([a-f0-9]{32})\\]\\]/g, (match, id: string) => {\n const record = this.stateDb.getByNotionId(normalizeNotionId(id));\n if (!record?.obsidianPath) return match;\n const base = record.obsidianPath.split(\"/\").pop() ?? record.obsidianPath;\n const title = base.replace(/\\.md$/, \"\");\n return `[[${title}]]`;\n });\n }\n\n private async extractParentId(page: PageObjectResponse): Promise<string | null> {\n const parent = page.parent as {\n type: string;\n page_id?: string;\n database_id?: string;\n block_id?: string;\n };\n if (parent.type === \"page_id\") return parent.page_id ?? null;\n if (parent.type === \"database_id\") return parent.database_id ?? null;\n if (parent.type === \"block_id\" && parent.block_id) {\n return this.resolveBlockToPageId(parent.block_id);\n }\n return null;\n }\n\n private async resolveBlockToPageId(blockId: string): Promise<string | null> {\n for (let i = 0; i < 10; i++) {\n try {\n const block = await this.notionClient.getBlock(blockId);\n const bp = (\n block as unknown as { parent: { type: string; page_id?: string; block_id?: string } }\n ).parent;\n if (bp.type === \"page_id\") return bp.page_id ?? null;\n if (bp.type === \"block_id\" && bp.block_id) {\n blockId = bp.block_id;\n continue;\n }\n return null;\n } catch {\n return null;\n }\n }\n return null;\n }\n\n private cleanupInterruptedSync(): void {\n const pushInProgress = this.stateDb.getMeta(\"push_in_progress\");\n const pullInProgress = this.stateDb.getMeta(\"pull_in_progress\");\n\n if (pushInProgress === \"true\") {\n getLogger().warn(\"[Im-Nobsidian] 이전 push가 비정상 종료됨 — 플래그 정리\");\n this.stateDb.setMeta(\"push_in_progress\", \"\");\n }\n if (pullInProgress === \"true\") {\n getLogger().warn(\"[Im-Nobsidian] 이전 pull이 비정상 종료됨 — 플래그 정리\");\n this.stateDb.setMeta(\"pull_in_progress\", \"\");\n }\n }\n\n /**\n * I12 — 중단된 push create 작업 재개.\n *\n * pending_operations 에 미완료(create·push) 항목이 있으면:\n * - state 에 notion_page_id 가 이미 있으면 → 생성·매핑까지는 끝났고 markCompleted 직전에\n * 중단된 것 → 완료 처리(잔여 본문/이미지는 다음 변경감지가 pushUpdate 로 마무리).\n * - notion_page_id 가 비어 있으면(Window A: 생성 적용됐으나 매핑 기록 전 중단) → 부모에서\n * 제목으로 child_page 를 검색해 고아 페이지를 입양(중복 생성 차단). 없으면 자리표시\n * 레코드를 제거(FK CASCADE 로 op 도 삭제)해 다음 push 가 새로 생성하게 한다.\n *\n * 한계(문서화): Notion 은 idempotency key 가 없어 \"생성 요청 적용 직후 같은 호출 내 재시도\"\n * 로 인한 중복은 완전히 차단하지 못한다. 429 는 적용 전 거절이라 안전하고, 프로세스 재시작\n * 후 재개는 본 검색-입양으로 중복을 막는다. DB 모드(부모가 database)는 child_page 검색이\n * 불가하므로 자리표시 제거 후 재생성으로 폴백한다.\n */\n private async recoverInterruptedPushOps(): Promise<void> {\n const ops = this.stateDb.getIncompletePendingOperations();\n if (ops.length === 0) return;\n\n for (const op of ops) {\n if (op.direction !== \"push\" || op.operation !== \"create\") {\n // 현재 WAL 재개는 create·push 만 대상. 그 외는 정리만 한다.\n this.stateDb.markPendingFailed(op.id, \"unsupported resume op\");\n continue;\n }\n\n let payload: { path?: string; parentId?: string; title?: string } = {};\n try {\n payload = JSON.parse(op.payload ?? \"{}\") as typeof payload;\n } catch {\n this.stateDb.markPendingFailed(op.id, \"invalid payload json\");\n continue;\n }\n const path = payload.path;\n if (!path) {\n this.stateDb.markPendingFailed(op.id, \"missing payload.path\");\n continue;\n }\n\n const state = this.stateDb.getByPath(path);\n if (state?.notionPageId) {\n // 매핑 존재 → 안전. 완료 처리하고 잔여는 변경감지(contentHash=\"\")가 pushUpdate 로 마무리.\n this.stateDb.markPendingCompleted(op.id);\n continue;\n }\n\n const parentId = payload.parentId ?? state?.notionParentId ?? undefined;\n const title = payload.title;\n const adopted = parentId && title ? await this.findChildPageByTitle(parentId, title) : null;\n\n if (adopted) {\n // 고아 페이지 입양: 매핑만 채우고 pending 유지 → 다음 변경감지가 본문·이미지 마무리.\n this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: adopted,\n notionParentId: parentId ?? null,\n contentHash: \"\",\n notionLastEdited: state?.notionLastEdited ?? null,\n localLastModified: new Date().toISOString(),\n syncDirection: state?.syncDirection ?? \"both\",\n fileType: state?.fileType ?? (this.isFolderNote(path) ? \"folder-note\" : \"file\"),\n status: \"pending\",\n baseSnapshot: null,\n localMtime: null,\n localFileSize: null,\n });\n this.stateDb.markPendingCompleted(op.id);\n getLogger().info(`[Im-Nobsidian] 중단된 create 재개 — 고아 페이지 입양: ${path}`);\n } else if (state) {\n // 생성된 페이지를 못 찾음 → 자리표시 제거(CASCADE 로 op 삭제) → 다음 push 가 새로 생성.\n this.stateDb.delete(state.id);\n getLogger().info(`[Im-Nobsidian] 중단된 create 재개 — 미생성 확인, 자리표시 제거: ${path}`);\n } else {\n this.stateDb.markPendingCompleted(op.id);\n }\n }\n }\n\n /** 부모 페이지의 직속 자식 중 제목이 일치하는(보관/휴지통 제외) child_page id 를 찾는다. */\n private async findChildPageByTitle(parentId: string, title: string): Promise<string | null> {\n try {\n const children = await this.notionClient.fetchAllChildren(parentId);\n for (const b of children) {\n if (b.type !== \"child_page\") continue;\n const childTitle = (b as { child_page?: { title?: string } }).child_page?.title;\n if (childTitle !== title) continue;\n try {\n const page = await this.notionClient.getPage(b.id);\n const inTrash = (page as { in_trash?: boolean }).in_trash === true;\n if (inTrash || page.archived) continue;\n } catch {\n continue;\n }\n return b.id;\n }\n } catch (error) {\n getLogger().warn(\n `[Im-Nobsidian] 고아 페이지 검색 실패 (${parentId}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n return null;\n }\n\n private async resolveUniqueFilePath(basePath: string): Promise<string> {\n if (!(await this.vaultFs.exists(basePath))) return basePath;\n\n const dir = basePath.lastIndexOf(\"/\") >= 0 ? basePath.slice(0, basePath.lastIndexOf(\"/\")) : \"\";\n const ext = \".md\";\n const name = basePath.slice(dir ? dir.length + 1 : 0, -ext.length);\n\n for (let i = 1; i <= 99; i++) {\n const candidate = dir ? `${dir}/${name} (${i})${ext}` : `${name} (${i})${ext}`;\n if (!(await this.vaultFs.exists(candidate))) return candidate;\n }\n\n return basePath;\n }\n}\n\nfunction extractTitle(filePath: string): string {\n const parts = filePath.split(\"/\");\n const filename = parts[parts.length - 1] ?? \"\";\n return filename.replace(/\\.md$/, \"\");\n}\n\nfunction extractAliases(properties: Record<string, unknown>): string[] {\n const raw = properties.aliases ?? properties.alias;\n if (!raw) return [];\n if (Array.isArray(raw)) return raw.filter((a): a is string => typeof a === \"string\");\n if (typeof raw === \"string\")\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return [];\n}\n","import { readFile, writeFile, unlink, rename, mkdir, readdir, stat } from \"node:fs/promises\";\nimport { readFileSync } from \"node:fs\";\nimport { join, relative, dirname } from \"node:path\";\nimport type { VaultFS, NonMdFileInfo, FileStatInfo } from \"./vault-fs.js\";\nimport type { FileInfo } from \"./change-detector.js\";\nimport { IGNORE_FILE } from \"../constants/paths.js\";\n\nexport interface PathFilterConfig {\n readonly include?: string[];\n readonly exclude?: string[];\n}\n\nexport class NodeVaultFS implements VaultFS {\n private readonly includePatterns: string[];\n private readonly excludePatterns: string[];\n\n constructor(\n private readonly rootPath: string,\n pathConfig?: PathFilterConfig,\n ) {\n this.includePatterns = pathConfig?.include ?? [];\n const configExclude = pathConfig?.exclude ?? [];\n const ignorePatterns = this.loadImNobsidianIgnore();\n this.excludePatterns = [...configExclude, ...ignorePatterns];\n }\n\n private loadImNobsidianIgnore(): string[] {\n try {\n const ignorePath = join(this.rootPath, IGNORE_FILE);\n const content = readFileSync(ignorePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .map((line: string) => line.trim())\n .filter((line: string) => line && !line.startsWith(\"#\"));\n } catch {\n return [];\n }\n }\n\n async readFile(path: string): Promise<string> {\n const fullPath = join(this.rootPath, path);\n return readFile(fullPath, \"utf-8\");\n }\n\n async readBinary(path: string): Promise<Buffer> {\n const fullPath = join(this.rootPath, path);\n return readFile(fullPath);\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const fullPath = join(this.rootPath, path);\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, content, \"utf-8\");\n }\n\n async writeBinary(path: string, data: Buffer): Promise<void> {\n const fullPath = join(this.rootPath, path);\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, data);\n }\n\n async deleteFile(path: string): Promise<void> {\n const fullPath = join(this.rootPath, path);\n await unlink(fullPath);\n }\n\n async moveFile(from: string, to: string): Promise<void> {\n const fromPath = join(this.rootPath, from);\n const toPath = join(this.rootPath, to);\n await mkdir(dirname(toPath), { recursive: true });\n await rename(fromPath, toPath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await stat(join(this.rootPath, path));\n return true;\n } catch {\n return false;\n }\n }\n\n async ensureFolder(path: string): Promise<void> {\n await mkdir(join(this.rootPath, path), { recursive: true });\n }\n\n async listMarkdownFiles(): Promise<FileInfo[]> {\n const files: FileInfo[] = [];\n await this.walkDir(this.rootPath, files);\n return files;\n }\n\n async listMarkdownFileStats(): Promise<FileStatInfo[]> {\n const stats: FileStatInfo[] = [];\n await this.walkDirStats(this.rootPath, stats);\n return stats;\n }\n\n async getFileStat(path: string): Promise<FileStatInfo | null> {\n try {\n const fullPath = join(this.rootPath, path);\n const fileStat = await stat(fullPath);\n return { path, mtime: fileStat.mtime.toISOString(), size: fileStat.size };\n } catch {\n return null;\n }\n }\n\n async listNonMarkdownFiles(): Promise<NonMdFileInfo[]> {\n const files: NonMdFileInfo[] = [];\n await this.walkDirNonMd(this.rootPath, files);\n return files;\n }\n\n private matchesPattern(relativePath: string, pattern: string): boolean {\n if (pattern === \"**/*\" || pattern === \"**\") return true;\n\n if (pattern.endsWith(\"/**\")) {\n const dir = pattern.slice(0, -3);\n return relativePath.startsWith(dir + \"/\") || relativePath === dir;\n } else if (pattern.startsWith(\"*.\")) {\n const ext = pattern.slice(1);\n return relativePath.endsWith(ext);\n } else if (pattern.includes(\"*\")) {\n const regexStr = pattern\n .replace(/\\./g, \"\\\\.\")\n .replace(/\\*\\*/g, \"{{GLOBSTAR}}\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\{\\{GLOBSTAR\\}\\}/g, \".*\");\n return new RegExp(\"^\" + regexStr + \"$\").test(relativePath);\n } else {\n return relativePath === pattern || relativePath.startsWith(pattern + \"/\");\n }\n }\n\n private isExcluded(relativePath: string): boolean {\n if (this.includePatterns.length > 0) {\n const included = this.includePatterns.some((p) => this.matchesPattern(relativePath, p));\n if (!included) return true;\n }\n\n return this.excludePatterns.some((p) => this.matchesPattern(relativePath, p));\n }\n\n private async walkDirNonMd(dir: string, result: NonMdFileInfo[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.name.startsWith(\".\")) continue;\n\n const relativePath = relative(this.rootPath, fullPath);\n\n if (this.isExcluded(relativePath)) continue;\n\n if (entry.isDirectory()) {\n await this.walkDirNonMd(fullPath, result);\n } else if (entry.isFile() && !entry.name.endsWith(\".md\") && !entry.name.endsWith(\".base\")) {\n const fileStat = await stat(fullPath);\n result.push({\n path: relativePath,\n size: fileStat.size,\n mtime: fileStat.mtime.toISOString(),\n });\n }\n }\n }\n\n private async walkDirStats(dir: string, result: FileStatInfo[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.name.startsWith(\".\")) continue;\n\n const relativePath = relative(this.rootPath, fullPath);\n\n if (this.isExcluded(relativePath)) continue;\n\n if (entry.isDirectory()) {\n await this.walkDirStats(fullPath, result);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const fileStat = await stat(fullPath);\n result.push({\n path: relativePath,\n mtime: fileStat.mtime.toISOString(),\n size: fileStat.size,\n });\n }\n }\n }\n\n private async walkDir(dir: string, result: FileInfo[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.name.startsWith(\".\")) continue;\n\n const relativePath = relative(this.rootPath, fullPath);\n\n if (this.isExcluded(relativePath)) continue;\n\n if (entry.isDirectory()) {\n await this.walkDir(fullPath, result);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const content = await readFile(fullPath, \"utf-8\");\n const fileStat = await stat(fullPath);\n\n result.push({\n path: relativePath,\n content,\n mtime: fileStat.mtime.toISOString(),\n });\n }\n }\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst INLINE_DB_START = new RegExp(`%% ${MARKER_BRAND_RE}:inline-db:([^\\\\s]+) %%`, \"g\");\nconst INLINE_DB_END = new RegExp(`%% ${MARKER_BRAND_RE}:end %%`, \"g\");\n\nexport class InlineDBParser implements Processor {\n readonly name = \"InlineDBParser\";\n readonly order = 40;\n\n process(input: ProcessorInput): ProcessorOutput {\n const inlineDbBlocks: InlineDBBlock[] = [];\n const content = input.content;\n\n const startMatches = [...content.matchAll(INLINE_DB_START)];\n for (const match of startMatches) {\n const startIdx = match.index!;\n const params = parseParams(match[1]!);\n\n const afterStart = content.indexOf(\"\\n\", startIdx) + 1;\n const endMatch = INLINE_DB_END.exec(content.slice(afterStart));\n\n if (endMatch) {\n const tableContent = content.slice(afterStart, afterStart + endMatch.index!);\n inlineDbBlocks.push({\n id: params[\"id\"] ?? \"\",\n title: params[\"title\"] ?? \"\",\n tableMarkdown: tableContent.trim(),\n startIdx,\n endIdx: afterStart + endMatch.index! + endMatch[0].length,\n });\n }\n\n INLINE_DB_END.lastIndex = 0;\n }\n\n return {\n content,\n metadata: {\n ...input.metadata,\n inlineDbBlocks,\n },\n };\n }\n}\n\ninterface InlineDBBlock {\n readonly id: string;\n readonly title: string;\n readonly tableMarkdown: string;\n readonly startIdx: number;\n readonly endIdx: number;\n}\n\nfunction parseParams(paramString: string): Record<string, string> {\n const params: Record<string, string> = {};\n for (const pair of paramString.split(\"&\")) {\n const [key, value] = pair.split(\"=\");\n if (key && value) {\n params[key] = decodeURIComponent(value);\n }\n }\n return params;\n}\n","import { sanitizeFileName } from \"../utils/sanitize.js\";\n\nexport interface NotionPageNode {\n readonly id: string;\n readonly title: string;\n readonly hasContent: boolean;\n readonly hasChildren: boolean;\n readonly isDatabase: boolean;\n readonly parentId: string | null;\n readonly children: NotionPageNode[];\n}\n\nexport type MappingType = \"file\" | \"folder-note\" | \"folder-only\" | \"database-folder\";\n\nexport interface MappingResult {\n readonly type: MappingType;\n readonly obsidianPath: string;\n readonly folderPath?: string;\n readonly notePath?: string;\n readonly schemaPath?: string;\n}\n\nexport class TreeMapper {\n mapNotionToObsidian(root: NotionPageNode, basePath: string = \"\"): MappingResult[] {\n const results: MappingResult[] = [];\n this.mapRecursive(root, basePath, results);\n return results;\n }\n\n private mapRecursive(node: NotionPageNode, parentPath: string, results: MappingResult[]): void {\n const safeName = sanitizeFileName(node.title || \"_untitled\");\n const currentPath = parentPath ? `${parentPath}/${safeName}` : safeName;\n\n if (node.isDatabase) {\n results.push({\n type: \"database-folder\",\n obsidianPath: `${currentPath}/`,\n folderPath: `${currentPath}/`,\n schemaPath: `${currentPath}/_schema.yml`,\n });\n } else if (node.hasContent && node.hasChildren) {\n results.push({\n type: \"folder-note\",\n obsidianPath: `${currentPath}/${safeName}.md`,\n folderPath: `${currentPath}/`,\n notePath: `${currentPath}/${safeName}.md`,\n });\n } else if (!node.hasContent && node.hasChildren) {\n results.push({\n type: \"folder-only\",\n obsidianPath: `${currentPath}/`,\n folderPath: `${currentPath}/`,\n });\n } else {\n results.push({\n type: \"file\",\n obsidianPath: `${currentPath}.md`,\n });\n }\n\n for (const child of node.children) {\n this.mapRecursive(child, currentPath, results);\n }\n }\n\n mapObsidianToNotion(entries: FileSystemEntry[], parentPageId: string): PageCreationPlan[] {\n const plans: PageCreationPlan[] = [];\n this.planRecursive(entries, parentPageId, plans);\n return plans;\n }\n\n private planRecursive(\n entries: FileSystemEntry[],\n parentPageId: string,\n plans: PageCreationPlan[],\n ): void {\n for (const entry of entries) {\n if (entry.isDirectory) {\n const folderNote = this.findFolderNote(entry);\n\n if (folderNote) {\n plans.push({\n type: \"page-with-children\",\n title: entry.name,\n parentPageId,\n contentSource: folderNote.path,\n hasContent: true,\n });\n\n const childEntries = entry.children.filter((c) => c.path !== folderNote.path);\n this.planRecursive(childEntries, `placeholder:${entry.path}`, plans);\n } else {\n plans.push({\n type: \"empty-page-with-children\",\n title: entry.name,\n parentPageId,\n hasContent: false,\n });\n this.planRecursive(entry.children, `placeholder:${entry.path}`, plans);\n }\n } else if (entry.name.endsWith(\".md\") && !entry.name.startsWith(\"_\")) {\n plans.push({\n type: \"leaf-page\",\n title: entry.name.replace(/\\.md$/, \"\"),\n parentPageId,\n contentSource: entry.path,\n hasContent: true,\n });\n }\n }\n }\n\n private findFolderNote(dir: FileSystemEntry): FileSystemEntry | null {\n return dir.children.find((c) => c.name === `${dir.name}.md` || c.name === \"index.md\") ?? null;\n }\n\n determineFileType(page: {\n hasContent: boolean;\n hasChildren: boolean;\n isDatabase: boolean;\n }): MappingType {\n if (page.isDatabase) return \"database-folder\";\n if (page.hasContent && page.hasChildren) return \"folder-note\";\n if (!page.hasContent && page.hasChildren) return \"folder-only\";\n return \"file\";\n }\n}\n\nexport interface FileSystemEntry {\n readonly name: string;\n readonly path: string;\n readonly isDirectory: boolean;\n readonly children: FileSystemEntry[];\n}\n\nexport interface PageCreationPlan {\n readonly type: \"page-with-children\" | \"empty-page-with-children\" | \"leaf-page\";\n readonly title: string;\n readonly parentPageId: string;\n readonly contentSource?: string;\n readonly hasContent: boolean;\n}\n","import { watch } from \"chokidar\";\nimport type { FSWatcher } from \"chokidar\";\nimport { sep } from \"node:path\";\nimport { INTERNAL_DIR_GLOB } from \"../constants/paths.js\";\n\nexport type WatchEvent = \"add\" | \"change\" | \"unlink\";\n\nexport interface WatchCallback {\n (event: WatchEvent, path: string): void;\n}\n\nexport class FileWatcher {\n private watcher: FSWatcher | null = null;\n\n constructor(\n private readonly rootPath: string,\n private readonly callback: WatchCallback,\n ) {}\n\n start(): void {\n this.watcher = watch(this.rootPath, {\n // 이벤트 경로를 rootPath 기준 \"볼트 상대경로\"로 방출한다. 동기화 엔진의 변경\n // 감지·paths 필터는 모두 볼트 상대경로(listMarkdownFileStats 기준)를 쓰므로,\n // 절대경로를 그대로 넘기면 push 의 startsWith 스코프 필터에서 누락돼 변경 파일이\n // 실제로 동기화되지 않는다(증분 watch 의 핵심 버그).\n cwd: this.rootPath,\n ignored: [/(^|[/\\\\])\\./, \"**/node_modules/**\", INTERNAL_DIR_GLOB],\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 100,\n },\n });\n\n this.watcher.on(\"add\", (path) => this.callback(\"add\", this.toVaultPath(path)));\n this.watcher.on(\"change\", (path) => this.callback(\"change\", this.toVaultPath(path)));\n this.watcher.on(\"unlink\", (path) => this.callback(\"unlink\", this.toVaultPath(path)));\n }\n\n // 볼트 경로는 항상 \"/\" 구분자를 사용한다. Windows 백슬래시를 정규화.\n private toVaultPath(path: string): string {\n return sep === \"/\" ? path : path.split(sep).join(\"/\");\n }\n\n async stop(): Promise<void> {\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = null;\n }\n }\n}\n","import type { SyncOrchestrator } from \"../sync/orchestrator.js\";\nimport type { SyncResult } from \"../types/sync.js\";\nimport { FileWatcher } from \"./file-watcher.js\";\nimport type { WatchEvent } from \"./file-watcher.js\";\n\nexport interface WatchSyncOptions {\n readonly debounceMs?: number;\n readonly onSyncStart?: () => void;\n readonly onSyncComplete?: (result: SyncResult) => void;\n readonly onSyncError?: (error: Error) => void;\n readonly onFileChange?: (event: WatchEvent, path: string) => void;\n}\n\nconst DEFAULT_DEBOUNCE_MS = 2000;\n\nexport class WatchSyncService {\n private readonly debounceMs: number;\n private readonly options: WatchSyncOptions;\n private watcher: FileWatcher | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingChanges: Map<string, WatchEvent> = new Map();\n private syncing = false;\n private syncQueued = false;\n private running = false;\n\n constructor(\n private readonly rootPath: string,\n private readonly orchestrator: SyncOrchestrator,\n options: WatchSyncOptions = {},\n ) {\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n this.options = options;\n }\n\n start(): void {\n if (this.running) return;\n\n this.running = true;\n this.watcher = new FileWatcher(this.rootPath, (event, path) => {\n this.handleFileChange(event, path);\n });\n this.watcher.start();\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n this.running = false;\n this.clearDebounce();\n this.pendingChanges.clear();\n\n if (this.watcher) {\n await this.watcher.stop();\n this.watcher = null;\n }\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n isSyncing(): boolean {\n return this.syncing;\n }\n\n getPendingCount(): number {\n return this.pendingChanges.size;\n }\n\n private handleFileChange(event: WatchEvent, path: string): void {\n if (!path.endsWith(\".md\")) return;\n\n this.pendingChanges.set(path, event);\n this.options.onFileChange?.(event, path);\n this.scheduleSync();\n }\n\n private scheduleSync(): void {\n this.clearDebounce();\n\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n void this.executeSync();\n }, this.debounceMs);\n }\n\n private clearDebounce(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n\n private async executeSync(): Promise<void> {\n if (this.syncing) {\n this.syncQueued = true;\n return;\n }\n\n // 동기화를 시작하므로 대기 중인 debounce 타이머를 정리한다. 이 타이머가\n // pendingChanges 가 비워진 뒤 뒤늦게 발화하면 아래 가드에 걸려 무시되지만,\n // 미리 취소해 불필요한 재진입 자체를 없앤다.\n this.clearDebounce();\n\n // 누적된 변경이 없으면 아무것도 하지 않는다. 실제 파일 변경 기반 동기화는 항상\n // 경로를 동반하므로, 빈 상태로 진입했다는 것은 stale 타이머·중복 트리거라는 뜻이다.\n // 이때 sync() 를 경로 없이 호출하면 의도치 않은 전체 볼트 동기화가 된다.\n if (this.pendingChanges.size === 0) return;\n\n this.syncing = true;\n // 처리 대상을 스냅샷으로 떠 두고 큐를 비운다. 실패 시 되돌릴 수 있도록 이벤트까지 보존.\n const batch = new Map(this.pendingChanges);\n this.pendingChanges.clear();\n\n try {\n this.options.onSyncStart?.();\n\n const result = await this.orchestrator.sync({ paths: [...batch.keys()] });\n\n this.options.onSyncComplete?.(result);\n } catch (error) {\n // 동기화 실패 시 처리하던 경로를 큐로 되돌려 다음 트리거에서 재시도한다. 단,\n // 동기화 도중 같은 경로에 더 최신 이벤트가 들어왔다면 그것을 덮어쓰지 않는다.\n for (const [path, event] of batch) {\n if (!this.pendingChanges.has(path)) this.pendingChanges.set(path, event);\n }\n const err = error instanceof Error ? error : new Error(String(error));\n this.options.onSyncError?.(err);\n } finally {\n this.syncing = false;\n\n if (this.syncQueued) {\n this.syncQueued = false;\n void this.executeSync();\n } else if (this.pendingChanges.size > 0) {\n // 동기화 중 새로 들어왔거나 실패로 되돌린 경로가 있으면 재동기화를 예약한다.\n this.scheduleSync();\n }\n }\n }\n}\n","import type { ViewConfig } from \"../types/view.js\";\nimport type { DBEntry, PropertyValue, GroupedEntries, CalendarEntry } from \"./types.js\";\n\nexport function sortEntries(\n entries: DBEntry[],\n sorts: NonNullable<ViewConfig[\"sorts\"]>,\n): DBEntry[] {\n if (sorts.length === 0) return entries;\n\n return [...entries].sort((a, b) => {\n for (const sort of sorts) {\n const key = sort.property ?? sort.timestamp;\n if (!key) continue;\n\n const aVal = a.properties[key] ?? null;\n const bVal = b.properties[key] ?? null;\n const cmp = compareValues(aVal, bVal);\n if (cmp !== 0) return sort.direction === \"ascending\" ? cmp : -cmp;\n }\n return 0;\n });\n}\n\nexport function groupEntries(\n entries: DBEntry[],\n groupByProperty: string,\n options?: { sort?: \"ascending\" | \"descending\"; hideEmptyGroups?: boolean },\n): GroupedEntries[] {\n const groups = new Map<string, DBEntry[]>();\n const ungrouped: DBEntry[] = [];\n\n for (const entry of entries) {\n const val = entry.properties[groupByProperty] ?? null;\n const groupName = extractGroupName(val);\n\n if (groupName === null) {\n ungrouped.push(entry);\n } else {\n const existing = groups.get(groupName);\n if (existing) {\n existing.push(entry);\n } else {\n groups.set(groupName, [entry]);\n }\n }\n }\n\n let result: GroupedEntries[] = Array.from(groups.entries()).map(([name, items]) => ({\n groupName: name,\n entries: items,\n }));\n\n if (options?.sort === \"ascending\") {\n result.sort((a, b) => a.groupName.localeCompare(b.groupName));\n } else if (options?.sort === \"descending\") {\n result.sort((a, b) => b.groupName.localeCompare(a.groupName));\n }\n\n if (ungrouped.length > 0) {\n result.push({ groupName: \"그룹 없음\", entries: ungrouped });\n }\n\n if (options?.hideEmptyGroups) {\n result = result.filter((g) => g.entries.length > 0);\n }\n\n return result;\n}\n\nexport function extractCalendarEntries(entries: DBEntry[], dateProperty: string): CalendarEntry[] {\n const result: CalendarEntry[] = [];\n\n for (const entry of entries) {\n const val = entry.properties[dateProperty];\n if (!val) continue;\n\n if (typeof val === \"string\") {\n const date = parseDate(val);\n if (date) result.push({ entry, date });\n } else if (typeof val === \"object\" && val !== null && !Array.isArray(val) && \"start\" in val) {\n const date = parseDate(val.start);\n if (date) {\n result.push({\n entry,\n date,\n endDate: val.end ? (parseDate(val.end) ?? undefined) : undefined,\n });\n }\n }\n }\n\n return result;\n}\n\nexport function filterByMonth(\n calendarEntries: CalendarEntry[],\n year: number,\n month: number,\n): CalendarEntry[] {\n const monthStr = `${year}-${String(month).padStart(2, \"0\")}`;\n return calendarEntries.filter((ce) => ce.date.startsWith(monthStr));\n}\n\nexport function getVisibleProperties(\n viewConfig: ViewConfig,\n): Array<{ id: string; name: string; width?: number }> {\n if (!viewConfig.properties) return [];\n\n return viewConfig.properties\n .filter((p) => p.visible !== false)\n .map((p) => ({\n id: p.propertyId,\n name: p.propertyName ?? p.propertyId,\n width: p.width,\n }));\n}\n\nfunction compareValues(a: PropertyValue, b: PropertyValue): number {\n if (a === null && b === null) return 0;\n if (a === null) return 1;\n if (b === null) return -1;\n\n if (typeof a === \"string\" && typeof b === \"string\") return a.localeCompare(b);\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (typeof a === \"boolean\" && typeof b === \"boolean\") return (a ? 1 : 0) - (b ? 1 : 0);\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.join(\",\").localeCompare(b.join(\",\"));\n }\n\n if (typeof a === \"object\" && typeof b === \"object\" && a !== null && b !== null) {\n if (\"start\" in a && \"start\" in b) {\n return (a.start ?? \"\").localeCompare(b.start ?? \"\");\n }\n }\n\n return String(a).localeCompare(String(b));\n}\n\nfunction extractGroupName(val: PropertyValue): string | null {\n if (val === null || val === undefined) return null;\n if (typeof val === \"string\") return val || null;\n if (typeof val === \"boolean\") return val ? \"true\" : \"false\";\n if (typeof val === \"number\") return String(val);\n if (Array.isArray(val)) return val.length > 0 ? val.join(\", \") : null;\n if (typeof val === \"object\" && \"start\" in val) return val.start;\n return null;\n}\n\nexport interface FilterCondition {\n property: string;\n operator:\n | \"equals\"\n | \"contains\"\n | \"startsWith\"\n | \"isEmpty\"\n | \"isNotEmpty\"\n | \"gt\"\n | \"lt\"\n | \"between\";\n value?: string | number | boolean;\n valueTo?: string | number;\n}\n\nexport function filterEntries(\n entries: DBEntry[],\n searchQuery?: string,\n filters?: FilterCondition[],\n): DBEntry[] {\n let result = entries;\n\n if (searchQuery && searchQuery.trim()) {\n const q = searchQuery.trim().toLowerCase();\n result = result.filter((entry) => {\n if (entry.title.toLowerCase().includes(q)) return true;\n return Object.values(entry.properties).some((val) => {\n if (val === null || val === undefined) return false;\n if (typeof val === \"string\") return val.toLowerCase().includes(q);\n if (Array.isArray(val)) return val.some((v) => v.toLowerCase().includes(q));\n if (typeof val === \"object\" && \"start\" in val) return val.start.includes(q);\n return String(val).toLowerCase().includes(q);\n });\n });\n }\n\n if (filters && filters.length > 0) {\n for (const filter of filters) {\n result = result.filter((entry) => matchFilter(entry, filter));\n }\n }\n\n return result;\n}\n\nfunction matchFilter(entry: DBEntry, filter: FilterCondition): boolean {\n const val =\n filter.property === \"title\" ? entry.title : (entry.properties[filter.property] ?? null);\n\n switch (filter.operator) {\n case \"isEmpty\":\n return (\n val === null || val === undefined || val === \"\" || (Array.isArray(val) && val.length === 0)\n );\n case \"isNotEmpty\":\n return (\n val !== null && val !== undefined && val !== \"\" && !(Array.isArray(val) && val.length === 0)\n );\n case \"equals\":\n if (typeof val === \"boolean\") return val === filter.value;\n return String(val ?? \"\") === String(filter.value ?? \"\");\n case \"contains\": {\n const needle = String(filter.value ?? \"\").toLowerCase();\n if (typeof val === \"string\") return val.toLowerCase().includes(needle);\n if (Array.isArray(val)) return val.some((v) => v.toLowerCase().includes(needle));\n return String(val ?? \"\")\n .toLowerCase()\n .includes(needle);\n }\n case \"startsWith\":\n return String(val ?? \"\").startsWith(String(filter.value ?? \"\"));\n case \"gt\":\n return typeof val === \"number\" && typeof filter.value === \"number\" && val > filter.value;\n case \"lt\":\n return typeof val === \"number\" && typeof filter.value === \"number\" && val < filter.value;\n case \"between\": {\n if (\n typeof val !== \"number\" ||\n typeof filter.value !== \"number\" ||\n typeof filter.valueTo !== \"number\"\n )\n return false;\n return val >= filter.value && val <= filter.valueTo;\n }\n default:\n return true;\n }\n}\n\nfunction parseDate(value: string): string | null {\n const match = /^(\\d{4}-\\d{2}-\\d{2})/.exec(value);\n return match?.[1] ?? null;\n}\n","import type { VaultFS } from \"../sync/vault-fs.js\";\nimport type { DatabaseViewsConfig, ViewConfig } from \"../types/view.js\";\nimport type { DBEntry, PropertyValue, ViewRenderData, PropertySchema } from \"./types.js\";\nimport { sortEntries, groupEntries, extractCalendarEntries } from \"./filter-engine.js\";\nimport { getVisibleProperties } from \"./filter-engine.js\";\nimport matter from \"gray-matter\";\nimport { DB_VIEWS_PATH } from \"../constants/paths.js\";\nimport { selectDbRowFiles } from \"../utils/db-row-path.js\";\n\nexport class ViewDataProvider {\n constructor(private readonly vaultFs: VaultFS) {}\n\n async loadAllViewConfigs(): Promise<Record<string, DatabaseViewsConfig>> {\n try {\n const raw = await this.vaultFs.readFile(DB_VIEWS_PATH);\n return JSON.parse(raw) as Record<string, DatabaseViewsConfig>;\n } catch {\n return {};\n }\n }\n\n async getViewConfigs(databaseId: string): Promise<DatabaseViewsConfig | null> {\n const all = await this.loadAllViewConfigs();\n return all[databaseId] ?? null;\n }\n\n async collectEntries(folderPath: string): Promise<DBEntry[]> {\n const allFiles = await this.vaultFs.listMarkdownFiles();\n // 직속 행 파일만 — 중첩 하위 폴더(별도 child_database·자식 페이지 본문)는 부모 DB 의\n // 행이 아니므로 카드로 새어 들지 않게 제외한다(I9 오포함 차단).\n const dbFiles = selectDbRowFiles(allFiles, folderPath);\n\n const entries: DBEntry[] = [];\n\n for (const file of dbFiles) {\n try {\n const content = await this.vaultFs.readFile(file.path);\n const entry = parseEntry(file.path, content);\n if (entry) entries.push(entry);\n } catch {\n // 파일 읽기 실패 시 스킵\n }\n }\n\n return entries;\n }\n\n async buildViewData(\n databaseId: string,\n viewId: string,\n folderPath: string,\n schema?: Record<string, PropertySchema>,\n ): Promise<ViewRenderData | null> {\n const dbConfig = await this.getViewConfigs(databaseId);\n if (!dbConfig) return null;\n\n const viewConfig = dbConfig.views.find((v) => v.id === viewId);\n if (!viewConfig) return null;\n\n const entries = await this.collectEntries(folderPath);\n\n return this.processViewData(entries, viewConfig, databaseId, dbConfig.databaseName, schema);\n }\n\n async buildDefaultViewData(\n databaseId: string,\n folderPath: string,\n schema?: Record<string, PropertySchema>,\n ): Promise<ViewRenderData | null> {\n const dbConfig = await this.getViewConfigs(databaseId);\n if (!dbConfig || dbConfig.views.length === 0) return null;\n\n const viewConfig = dbConfig.views[0]!;\n const entries = await this.collectEntries(folderPath);\n\n return this.processViewData(entries, viewConfig, databaseId, dbConfig.databaseName, schema);\n }\n\n processViewData(\n entries: DBEntry[],\n viewConfig: ViewConfig,\n databaseId: string,\n databaseName?: string,\n schema?: Record<string, PropertySchema>,\n ): ViewRenderData {\n let processed = entries;\n\n if (viewConfig.sorts && viewConfig.sorts.length > 0) {\n processed = sortEntries(processed, viewConfig.sorts);\n }\n\n const visibleProps = getVisibleProperties(viewConfig);\n const propertyNames =\n visibleProps.length > 0 ? visibleProps.map((p) => p.name) : collectPropertyNames(processed);\n\n const data: ViewRenderData = {\n databaseId,\n databaseName,\n viewConfig,\n entries: processed,\n propertyNames,\n schema,\n };\n\n if (viewConfig.type === \"board\" && viewConfig.groupBy) {\n const grouped = groupEntries(\n processed,\n viewConfig.groupBy.propertyName ?? viewConfig.groupBy.propertyId,\n {\n sort: viewConfig.groupBy.sort === \"manual\" ? undefined : viewConfig.groupBy.sort,\n hideEmptyGroups: viewConfig.groupBy.hideEmptyGroups,\n },\n );\n return { ...data, grouped };\n }\n\n if (viewConfig.type === \"calendar\" && viewConfig.datePropertyName) {\n const calendarEntries = extractCalendarEntries(processed, viewConfig.datePropertyName);\n return { ...data, calendarEntries };\n }\n\n return data;\n }\n}\n\nfunction parseEntry(path: string, content: string): DBEntry | null {\n try {\n const parsed = matter(content);\n const fm = parsed.data as Record<string, unknown>;\n\n const title = coerceString(fm.title) ?? extractTitleFromPath(path);\n const icon = coerceString(fm.icon);\n const cover = coerceCover(fm.cover);\n\n const properties: Record<string, PropertyValue> = {};\n for (const [key, value] of Object.entries(fm)) {\n if (key === \"title\" || key === \"icon\" || key === \"cover\") continue;\n properties[key] = normalizePropertyValue(value);\n }\n\n return { path, title, icon, cover, properties };\n } catch {\n return null;\n }\n}\n\n/**\n * 갤러리 커버 값을 **렌더 가능한 단일 URL 스칼라**로 강제 변환한다(없으면 undefined).\n *\n * Notion `files` 속성을 갤러리 커버로 쓰면 행마다 파일 수가 달라, property-mapper 는 단일\n * 파일은 스칼라 문자열로·복수 파일은 **URL 배열**로 직렬화한다(데이터 보존). 그러나 카드\n * 커버 `<img src>` 는 스칼라만 받으므로, 배열이 그대로 흘러들면 `src=\"url1,url2\"` 로\n * 합쳐져 **깨진 이미지**가 된다. Notion 도 다중 파일 커버는 **첫 파일**을 쓰므로 동일하게\n * 첫 렌더 가능한 URL 로 degrade 한다. 파일 객체(`{url}`/`{external:{url}}`)도 방어적으로 처리.\n *\n * `DBEntry.cover: string` 타입을 런타임에서 보증한다(과거: `as string` 캐스팅이 배열을\n * 문자열로 단언해 타입이 거짓이었다).\n */\nfunction coerceCover(raw: unknown): string | undefined {\n const firstUrl = (v: unknown): string | undefined => {\n if (typeof v === \"string\") return v.trim() || undefined;\n if (v && typeof v === \"object\") {\n const o = v as { url?: unknown; external?: { url?: unknown } };\n const url = o.url ?? o.external?.url;\n if (typeof url === \"string\") return url.trim() || undefined;\n }\n return undefined;\n };\n\n if (Array.isArray(raw)) {\n for (const item of raw) {\n const url = firstUrl(item);\n if (url) return url; // 다중값 → 첫 렌더 가능한 URL 로 degrade\n }\n return undefined;\n }\n return firstUrl(raw);\n}\n\n/**\n * `DBEntry` 의 스칼라 문자열 필드(`title`/`icon`)를 **렌더·검색 안전한 단일 문자열**로\n * 강제 변환한다(없으면 undefined → 호출처에서 파일명 등으로 폴백).\n *\n * 프론트매터는 다형값을 흘려보낼 수 있다:\n * - `title: 2026` → js-yaml 이 **number** 로 파싱(따옴표 없는 숫자 제목은 흔함).\n * - `title: [a, b]` / 수동 오편집 → **배열**.\n * 과거 `fm.title as string` 캐스팅은 이를 string 으로 **거짓 단언**했고, 뒤따르는\n * `filter-engine` 의 `entry.title.toLowerCase()` 가 `X.toLowerCase is not a function` 으로\n * **뷰 검색 전체를 크래시**시켰다(I9 위반 — rank22 의 커버 배열 깨짐과 동일 계열).\n * number/boolean 은 문자열화, 배열은 첫 비공백 문자열로 degrade 하여 타입을 런타임 보증한다.\n */\nfunction coerceString(raw: unknown): string | undefined {\n if (typeof raw === \"string\") return raw.trim() || undefined;\n if (typeof raw === \"number\" || typeof raw === \"boolean\") return String(raw);\n if (Array.isArray(raw)) {\n for (const item of raw) {\n const s = coerceString(item);\n if (s) return s; // 다중값 → 첫 렌더 가능한 문자열로 degrade\n }\n }\n return undefined;\n}\n\nfunction normalizePropertyValue(value: unknown): PropertyValue {\n if (value === null || value === undefined) return null;\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return value;\n if (typeof value === \"boolean\") return value;\n\n if (value instanceof Date) {\n return value.toISOString().split(\"T\")[0]!;\n }\n\n if (Array.isArray(value)) {\n return value.map((v) => String(v));\n }\n\n if (typeof value === \"object\" && value !== null) {\n const obj = value as Record<string, unknown>;\n if (\"start\" in obj) {\n return {\n start: String(obj.start),\n end: obj.end ? String(obj.end) : undefined,\n };\n }\n }\n\n return String(value);\n}\n\nfunction extractTitleFromPath(filePath: string): string {\n const parts = filePath.split(\"/\");\n const filename = parts[parts.length - 1] ?? \"\";\n return filename.replace(/\\.md$/, \"\");\n}\n\nfunction collectPropertyNames(entries: DBEntry[]): string[] {\n const names = new Set<string>();\n for (const entry of entries) {\n for (const key of Object.keys(entry.properties)) {\n names.add(key);\n }\n }\n return Array.from(names);\n}\n","import type { VaultFS } from \"../sync/vault-fs.js\";\nimport type { DBEntry, PropertyValue } from \"./types.js\";\nimport matter from \"gray-matter\";\nimport { stringifyFrontmatter } from \"../utils/frontmatter.js\";\n\nexport class EntryEditor {\n constructor(private readonly vaultFs: VaultFS) {}\n\n async updateProperty(\n entryPath: string,\n propertyName: string,\n newValue: PropertyValue,\n ): Promise<void> {\n const content = await this.vaultFs.readFile(entryPath);\n const parsed = matter(content);\n\n parsed.data[propertyName] = newValue;\n\n const updated = stringifyFrontmatter(parsed.content, parsed.data);\n await this.vaultFs.writeFile(entryPath, updated);\n }\n\n async createEntry(\n folderPath: string,\n title: string,\n properties: Record<string, PropertyValue>,\n ): Promise<string> {\n const safeName = title.replace(/[\\\\/:*?\"<>|]/g, \"_\").trim() || \"Untitled\";\n const filePath = `${folderPath}/${safeName}.md`;\n\n const frontmatter = { title, ...properties };\n const content = stringifyFrontmatter(\"\", frontmatter);\n\n await this.vaultFs.ensureFolder(folderPath);\n await this.vaultFs.writeFile(filePath, content);\n\n return filePath;\n }\n\n async moveEntryToGroup(\n entry: DBEntry,\n groupProperty: string,\n newGroupValue: string,\n ): Promise<void> {\n await this.updateProperty(entry.path, groupProperty, newGroupValue);\n }\n\n async updateDate(entryPath: string, dateProperty: string, newDate: string): Promise<void> {\n await this.updateProperty(entryPath, dateProperty, newDate);\n }\n}\n","import type { NotionColor } from \"./types.js\";\n\nconst NOTION_COLORS: Record<NotionColor, string> = {\n default: \"#37352F\",\n gray: \"#787774\",\n brown: \"#9F6B53\",\n orange: \"#D9730D\",\n yellow: \"#CB912F\",\n green: \"#448361\",\n blue: \"#337EA9\",\n purple: \"#9065B0\",\n pink: \"#C14C8A\",\n red: \"#D44C47\",\n};\n\nconst NOTION_BG_COLORS: Record<NotionColor, string> = {\n default: \"#F1F1EF\",\n gray: \"#F1F1EF\",\n brown: \"#F4EEEE\",\n orange: \"#FBECDD\",\n yellow: \"#FBF3DB\",\n green: \"#EDF3EC\",\n blue: \"#E7F3F8\",\n purple: \"#F4F0F7\",\n pink: \"#F9F0F5\",\n red: \"#FDEBEC\",\n};\n\nexport function getNotionColor(color: NotionColor | string): string {\n return NOTION_COLORS[color as NotionColor] ?? NOTION_COLORS.default;\n}\n\nexport function getNotionBgColor(color: NotionColor | string): string {\n return NOTION_BG_COLORS[color as NotionColor] ?? NOTION_BG_COLORS.default;\n}\n\nexport function generateColorCSS(): string {\n const lines: string[] = [];\n for (const [name, hex] of Object.entries(NOTION_COLORS)) {\n lines.push(` --notion-color-${name}: ${hex};`);\n }\n for (const [name, hex] of Object.entries(NOTION_BG_COLORS)) {\n lines.push(` --notion-bg-${name}: ${hex};`);\n }\n return `:root {\\n${lines.join(\"\\n\")}\\n}`;\n}\n","/**\n * 본문 링크 충실도(fidelity) 분류기 — 회귀 상시 잠금용 측정 인프라.\n *\n * pull 결과물(.md 본문)에 남은 notion 링크/멘션을 네 부류로 분류한다:\n *\n * 1. preservedMarkers — `[text](url)%%im-nobsidian:...%%` 형태의 의도된 무손실\n * 보존 마커(copy_indicator 등). push 라운드트립 복원용으로 *일부러* 남긴 것이라\n * 결함이 아니다.\n * 2. externalLinks — 동기화 코퍼스에 없는 외부 notion.so 링크. 위키링크로 환원할\n * 대상이 없으므로 맨 링크로 두는 게 정당하다.\n * 3. selfReferences — 자기 자신 페이지를 가리키는 링크/멘션(블록 앵커 등). 정당.\n * 4. defects — 동기화된 *다른* 페이지로의 미해소 링크/멘션. 이것만이 진짜\n * 충실도 결함이다(M2/M3/M4/M6 가 봉합한 대상).\n *\n * 변환 파이프라인이 완전하면 `defects.length === 0` 이어야 한다. 이 분류기를 픽스처로\n * 잠가(unit test) 두면 변환기 회귀가 즉시 드러나고, 실제 vault 에 대고 돌리면(아래\n * scripts/audit-vault.mjs) 코퍼스 전체의 충실도를 정량 측정할 수 있다.\n *\n * 마커/ID 판별은 SSOT 를 재사용한다 — 마커 브랜드는 {@link MARKER_BRAND},\n * 정규 id 는 {@link compactNotionId}. 별도 헬퍼를 만들지 않는다.\n */\n\nimport { MARKER_BRAND } from \"../constants/markers.js\";\nimport { compactNotionId } from \"../utils/id.js\";\n\n/** 미해소로 남은 링크/멘션의 형태. */\nexport type FidelityDefectForm = \"md-link\" | \"mention-page\";\n\n/** 진짜 충실도 결함 — 동기화된 다른 페이지로의 미해소 링크/멘션. */\nexport interface FidelityDefect {\n /** 미해소 형태(맨 마크다운 링크 / 미변환 mention-page 태그). */\n form: FidelityDefectForm;\n /** 대상 페이지의 정규(compact) id. */\n targetPageId: string;\n /** 대상 페이지 제목(맵에 있으면). */\n targetTitle: string | null;\n /** 결함 원문 조각(진단용). */\n raw: string;\n}\n\n/** {@link classifyBodyFidelity} 분류 결과. */\nexport interface FidelityClassification {\n /** `[text](url)%%im-nobsidian:...%%` — 의도된 무손실 보존 마커(결함 아님). */\n preservedMarkers: number;\n /** 코퍼스에 없는 외부 notion.so 링크(정당). */\n externalLinks: number;\n /** 자기 자신 페이지를 가리키는 링크/멘션(정당). */\n selfReferences: number;\n /** 동기화된 다른 페이지로의 미해소 링크/멘션 — 진짜 결함. */\n defects: FidelityDefect[];\n}\n\n/** 분류에 필요한 코퍼스 컨텍스트. */\nexport interface FidelityContext {\n /** 동기화된 전체 페이지의 정규(compact) id 집합. */\n knownPageIds: ReadonlySet<string>;\n /** 정규 id → 제목. 선택(결함 진단용). */\n titleById?: ReadonlyMap<string, string>;\n /** 이 본문이 속한 페이지의 정규 id. 자기참조 판별용. 선택. */\n ownPageId?: string;\n}\n\n/**\n * notion id 추출 정규식 — 하이픈 포함 UUID 와 32연속 hex 를 모두 인식한다.\n * `-?` 가 모두 선택이므로 단일 패턴이 두 형태를 포괄한다.\n */\nconst NOTION_ID_RE = /[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}/gi;\n\n/** notion.so 마크다운 링크 + 직후 보존 마커 동반 여부. group1=url, group2=마커. */\nconst MD_LINK_RE = new RegExp(\n `\\\\[[^\\\\]]*\\\\]\\\\((https?://[^)\\\\s]*notion\\\\.so/[^)\\\\s]*)\\\\)(\\\\s*%%\\\\s*${MARKER_BRAND}\\\\b)?`,\n \"gi\",\n);\n\n/** mention-page 태그 — self-closing `/>` 와 라벨 동반 `>..</mention-page>` 모두 포괄. */\nconst MENTION_PAGE_RE = /<mention-page\\b[\\s\\S]*?(?:\\/>|>[\\s\\S]*?<\\/mention-page>)/gi;\n\n/** 문자열에서 마지막 notion id 를 정규(compact) 형태로 추출. 없으면 null. */\nfunction lastNotionId(text: string): string | null {\n const matches = text.match(NOTION_ID_RE);\n if (!matches || matches.length === 0) return null;\n return compactNotionId(matches[matches.length - 1]!);\n}\n\n/**\n * 본문 문자열의 notion 링크/멘션 충실도를 분류한다. 순수 함수 — I/O 없음.\n *\n * @param body 분석할 마크다운 본문(프론트매터 포함 가능; 보존 마커·위키링크는 무시됨).\n * @param ctx 코퍼스 컨텍스트(알려진 페이지 id 집합 등).\n */\nexport function classifyBodyFidelity(body: string, ctx: FidelityContext): FidelityClassification {\n const result: FidelityClassification = {\n preservedMarkers: 0,\n externalLinks: 0,\n selfReferences: 0,\n defects: [],\n };\n\n const own = ctx.ownPageId ? compactNotionId(ctx.ownPageId) : null;\n const titleOf = (id: string): string | null => ctx.titleById?.get(id) ?? null;\n\n const classifyId = (id: string | null, form: FidelityDefectForm, raw: string): void => {\n if (id === null) {\n // id 를 못 뽑은 링크/멘션은 외부로 간주(코퍼스 매칭 불가).\n result.externalLinks += 1;\n return;\n }\n if (own !== null && id === own) {\n result.selfReferences += 1;\n return;\n }\n if (ctx.knownPageIds.has(id)) {\n result.defects.push({ form, targetPageId: id, targetTitle: titleOf(id), raw: raw.trim() });\n return;\n }\n result.externalLinks += 1;\n };\n\n // 1) notion.so 마크다운 링크\n for (const m of body.matchAll(MD_LINK_RE)) {\n const url = m[1] ?? \"\";\n const hasMarker = Boolean(m[2]);\n if (hasMarker) {\n result.preservedMarkers += 1;\n continue;\n }\n classifyId(lastNotionId(url), \"md-link\", m[0]);\n }\n\n // 2) mention-page 태그(변환됐어야 할 잔류물)\n for (const m of body.matchAll(MENTION_PAGE_RE)) {\n classifyId(lastNotionId(m[0]), \"mention-page\", m[0]);\n }\n\n return result;\n}\n\n/** 여러 본문의 분류 결과를 합산한 코퍼스 단위 요약. */\nexport interface FidelitySummary {\n files: number;\n preservedMarkers: number;\n externalLinks: number;\n selfReferences: number;\n defects: number;\n /** 결함이 1건 이상인 파일 경로 → 결함 목록. */\n defectsByFile: Record<string, FidelityDefect[]>;\n}\n\n/** 파일별 분류 결과(경로 + 분류)를 코퍼스 요약으로 합산한다. */\nexport function summarizeFidelity(\n perFile: ReadonlyArray<{ path: string; classification: FidelityClassification }>,\n): FidelitySummary {\n const summary: FidelitySummary = {\n files: perFile.length,\n preservedMarkers: 0,\n externalLinks: 0,\n selfReferences: 0,\n defects: 0,\n defectsByFile: {},\n };\n for (const { path, classification } of perFile) {\n summary.preservedMarkers += classification.preservedMarkers;\n summary.externalLinks += classification.externalLinks;\n summary.selfReferences += classification.selfReferences;\n summary.defects += classification.defects.length;\n if (classification.defects.length > 0) {\n summary.defectsByFile[path] = classification.defects;\n }\n }\n return summary;\n}\n"]}
1
+ {"version":3,"sources":["../src/types/config.ts","../src/constants/paths.ts","../src/config/manager.ts","../src/utils/id.ts","../src/state/migrations/001-initial.ts","../src/state/migrations/002-file-registry.ts","../src/state/migrations/003-stat-cache.ts","../src/state/state-db.ts","../src/notion/property-mapper.ts","../src/utils/logger.ts","../src/notion/client.ts","../src/notion/block-builder.ts","../src/utils/hash.ts","../src/sync/change-detector.ts","../src/constants/markers.ts","../src/converter/pipeline.ts","../src/converter/pre-processors/frontmatter.ts","../src/utils/md-regions.ts","../src/converter/pre-processors/wikilink.ts","../src/converter/pre-processors/callout.ts","../src/converter/pre-processors/math.ts","../src/converter/pre-processors/embed.ts","../src/converter/pre-processors/preserve-marker.ts","../src/converter/pre-processors/unsupported-block-stripper.ts","../src/utils/frontmatter.ts","../src/converter/pre-processors/properties-table.ts","../src/converter/pre-processors/html-annotation.ts","../src/converter/pre-processors/comment-stripper.ts","../src/converter/pre-processors/footnote-guard.ts","../src/converter/pre-processors/table-alignment.ts","../src/converter/link-restore.ts","../src/converter/post-processors/mention-to-wikilink.ts","../src/converter/post-processors/escape-normalizer.ts","../src/converter/post-processors/highlight-restorer.ts","../src/converter/post-processors/table-alignment-restorer.ts","../src/converter/post-processors/preserve-marker-injector.ts","../src/converter/post-processors/callout-restorer.ts","../src/converter/post-processors/color-annotator.ts","../src/converter/post-processors/frontmatter-generator.ts","../src/converter/post-processors/local-image-restorer.ts","../src/converter/post-processors/properties-table-restorer.ts","../src/converter/post-processors/block-spacer.ts","../src/converter/pipeline-factory.ts","../src/converter/rich-text-converter.ts","../src/converter/block-converter.ts","../src/sync/image-handler.ts","../src/sync/file-handler.ts","../src/sync/conflict-detector.ts","../src/utils/sanitize.ts","../src/utils/db-row-path.ts","../src/utils/wikilink-title.ts","../src/view/base-file-generator.ts","../src/view/sidecar-generator.ts","../src/sync/stale-db-artifacts.ts","../src/converter/enhanced-md-converter.ts","../src/sync/database-syncer.ts","../src/conflict/merger.ts","../src/conflict/resolver.ts","../src/utils/pool.ts","../src/sync/frontmatter-link-resolver.ts","../src/sync/orchestrator.ts","../src/sync/node-vault-fs.ts","../src/converter/pre-processors/inline-db.ts","../src/structure/tree-mapper.ts","../src/watcher/file-watcher.ts","../src/watcher/watch-sync-service.ts","../src/view/filter-engine.ts","../src/view/view-data-provider.ts","../src/view/entry-editor.ts","../src/view/color-map.ts","../src/audit/fidelity.ts"],"names":["stat","url","fetch","readFile","content","WIKILINK_REGEX","matter","at","escapeRegex","createHash","Sema","EXTENSION_TO_MIME","EMOJI_TYPE_MAP","TABLE_ROW_RE","i","j","baseName","extractAliases","title","existing","pathParts","join","mkdir","writeFile","extractTitleFromPath"],"mappings":"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","file":"index.js","sourcesContent":["import { z } from \"zod\";\n\nconst DatabaseSyncSchema = z.object({\n databaseId: z.string(),\n localFolder: z.string(),\n propertyMapping: z.record(z.string()).optional(),\n pullFilter: z.unknown().optional(),\n titleProperty: z.string().default(\"Name\"),\n});\n\nexport type DatabaseSyncConfig = z.infer<typeof DatabaseSyncSchema>;\n\nexport const ConfigSchema = z.object({\n version: z.literal(1),\n notion: z.object({\n token: z.string().startsWith(\"ntn_\"),\n rootPageId: z.string(),\n workspaceId: z.string().optional(),\n parentMode: z.enum([\"page\", \"database\"]).default(\"page\"),\n databaseId: z.string().optional(),\n databases: z.array(DatabaseSyncSchema).default([]),\n }),\n sync: z.object({\n direction: z.enum([\"push\", \"pull\", \"both\"]).default(\"both\"),\n conflictStrategy: z\n .enum([\"local-first\", \"remote-first\", \"manual\", \"duplicate\"])\n .default(\"manual\"),\n autoSync: z.boolean().default(false),\n autoSyncInterval: z.number().min(30).max(3600).default(300),\n deleteSync: z.boolean().default(false),\n syncFiles: z.boolean().default(true),\n }),\n paths: z.object({\n include: z.array(z.string()).default([\"**/*\"]),\n exclude: z.array(z.string()).default([]),\n attachments: z.string().default(\"attachments\"),\n }),\n conversion: z.object({\n preferMarkdownApi: z.boolean().default(true),\n preserveMarkers: z.boolean().default(true),\n frontmatterMapping: z.boolean().default(true),\n imageDownload: z.enum([\"immediate\", \"lazy\", \"skip\"]).default(\"immediate\"),\n }),\n advanced: z.object({\n // Notion API 클라이언트 동시성/타임아웃\n concurrency: z.number().min(1).max(10).default(3),\n timeoutMs: z.number().min(5000).max(60000).default(30000),\n // 페이지네이션/블록 배치 (Notion API children append 상한 = 100)\n pageSize: z.number().min(1).max(100).default(100),\n batchSize: z.number().min(1).max(100).default(100),\n // Rate limit 게이트 (요청 간 최소 간격, ms)\n rateLimitIntervalMs: z.number().min(0).max(5000).default(350),\n // API 재시도 (지수 백오프: retryBaseDelayMs * retryBackoffFactor^attempt)\n maxRetries: z.number().min(0).max(10).default(5),\n retryBaseDelayMs: z.number().min(100).max(10000).default(1000),\n retryBackoffFactor: z.number().min(1).max(10).default(2),\n // 오케스트레이터 단계 간 재시도 대기 (ms)\n retryWaitMs: z.number().min(0).max(30000).default(2000),\n // 미디어(이미지/파일) 다운로드 동시성/재시도\n mediaConcurrency: z.number().min(1).max(10).default(3),\n mediaMaxRetries: z.number().min(0).max(10).default(3),\n mediaRetryBaseMs: z.number().min(100).max(10000).default(1000),\n // 비마크다운 파일(첨부) 업로드/다운로드 동시성\n fileConcurrency: z.number().min(1).max(10).default(2),\n // 다운로드 파일 크기 상한 (bytes, 기본 100MB)\n maxFileSizeBytes: z\n .number()\n .min(1024)\n .default(100 * 1024 * 1024),\n }),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\nexport const DEFAULT_CONFIG: Config = {\n version: 1,\n notion: {\n token: \"\",\n rootPageId: \"\",\n parentMode: \"page\",\n databases: [],\n },\n sync: {\n direction: \"both\",\n conflictStrategy: \"manual\",\n autoSync: false,\n autoSyncInterval: 300,\n deleteSync: false,\n syncFiles: true,\n },\n paths: {\n include: [\"**/*\"],\n exclude: [],\n attachments: \"attachments\",\n },\n conversion: {\n preferMarkdownApi: true,\n preserveMarkers: true,\n frontmatterMapping: true,\n imageDownload: \"immediate\",\n },\n advanced: {\n concurrency: 3,\n timeoutMs: 30000,\n pageSize: 100,\n batchSize: 100,\n rateLimitIntervalMs: 350,\n maxRetries: 5,\n retryBaseDelayMs: 1000,\n retryBackoffFactor: 2,\n retryWaitMs: 2000,\n mediaConcurrency: 3,\n mediaMaxRetries: 3,\n mediaRetryBaseMs: 1000,\n fileConcurrency: 2,\n maxFileSizeBytes: 100 * 1024 * 1024,\n },\n};\n","/**\n * 내부 메타데이터 경로 단일 진실원(SSOT).\n *\n * `.im-nobsidian` 디렉터리·하위 파일명·ignore 파일·gitignore 항목을 한곳에서 정의한다.\n * 디렉터리/파일명을 바꾸거나 리브랜딩할 때 이 파일만 수정하면 전 패키지에 반영된다.\n */\n\n/** 내부 메타데이터 디렉터리명 (vault 루트 기준). */\nexport const INTERNAL_DIR = \".im-nobsidian\";\n\n/** 동기화 설정 파일명. */\nexport const CONFIG_FILE = \"config.json\";\n\n/** SQLite 상태 DB 파일명. */\nexport const STATE_DB_FILE = \"sync.db\";\n\n/** DB 뷰 메타데이터 파일명. */\nexport const DB_VIEWS_FILE = \"db-views.json\";\n\n/** 동기화 제외 패턴 파일명 (디렉터리 외부, vault 루트 직속). */\nexport const IGNORE_FILE = \".im-nobsidian-ignore\";\n\n/** `.gitignore`에 추가하는 항목. */\nexport const GITIGNORE_ENTRY = `${INTERNAL_DIR}/`;\n\n/** vault 상대 POSIX 경로 — DB 뷰 메타데이터. */\nexport const DB_VIEWS_PATH = `${INTERNAL_DIR}/${DB_VIEWS_FILE}`;\n\n/** vault 상대 POSIX 경로 — 상태 DB. */\nexport const STATE_DB_PATH = `${INTERNAL_DIR}/${STATE_DB_FILE}`;\n\n/** 파일 감시에서 제외할 내부 디렉터리 glob. */\nexport const INTERNAL_DIR_GLOB = `**/${INTERNAL_DIR}/**`;\n\n/**\n * 주어진 vault 상대 경로(POSIX)가 내부 메타데이터 디렉터리에 속하는지 판별한다.\n */\nexport function isInternalPath(path: string): boolean {\n return path === INTERNAL_DIR || path.startsWith(`${INTERNAL_DIR}/`);\n}\n","import { readFile, writeFile, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { ConfigSchema, DEFAULT_CONFIG } from \"../types/config.js\";\nimport type { Config } from \"../types/config.js\";\nimport { INTERNAL_DIR, CONFIG_FILE, STATE_DB_FILE, GITIGNORE_ENTRY } from \"../constants/paths.js\";\n\nexport class ConfigManager {\n private config: Config | null = null;\n\n constructor(private readonly vaultRoot: string) {}\n\n get configDir(): string {\n return join(this.vaultRoot, INTERNAL_DIR);\n }\n\n get configPath(): string {\n return join(this.configDir, CONFIG_FILE);\n }\n\n get dbPath(): string {\n return join(this.configDir, STATE_DB_FILE);\n }\n\n async load(): Promise<Config> {\n try {\n const raw = await readFile(this.configPath, \"utf-8\");\n const parsed = JSON.parse(raw);\n this.config = ConfigSchema.parse(parsed);\n return this.config;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`설정 파일의 JSON 형식이 올바르지 않습니다: ${this.configPath}`);\n }\n if (error instanceof Error && error.name === \"ZodError\") {\n throw new Error(`설정 파일 검증 실패: ${error.message}`);\n }\n throw new Error(\n `설정 파일을 찾을 수 없습니다: ${this.configPath}\\n'im-nobsidian init'을 먼저 실행하세요.`,\n );\n }\n }\n\n async save(config: Config): Promise<void> {\n await mkdir(this.configDir, { recursive: true });\n const content = JSON.stringify(config, null, 2);\n await writeFile(this.configPath, content, \"utf-8\");\n this.config = config;\n }\n\n async init(params: { token: string; rootPageId: string }): Promise<Config> {\n const config: Config = {\n ...DEFAULT_CONFIG,\n notion: {\n ...DEFAULT_CONFIG.notion,\n token: params.token,\n rootPageId: params.rootPageId,\n },\n };\n\n await this.save(config);\n await this.ensureGitignore();\n return config;\n }\n\n getConfig(): Config {\n if (!this.config) {\n throw new Error(\"설정이 로드되지 않았습니다. load()를 먼저 호출하세요.\");\n }\n return this.config;\n }\n\n private async ensureGitignore(): Promise<void> {\n const gitignorePath = join(this.vaultRoot, \".gitignore\");\n const entry = GITIGNORE_ENTRY;\n\n try {\n const content = await readFile(gitignorePath, \"utf-8\");\n if (!content.includes(entry)) {\n await writeFile(gitignorePath, `${content.trimEnd()}\\n${entry}\\n`, \"utf-8\");\n }\n } catch {\n await writeFile(gitignorePath, `${entry}\\n`, \"utf-8\");\n }\n }\n\n async isInitialized(): Promise<boolean> {\n try {\n const { stat } = await import(\"node:fs/promises\");\n await stat(this.configPath);\n return true;\n } catch {\n return false;\n }\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport function generateId(): string {\n return randomUUID();\n}\n\nexport function normalizeNotionId(id: string): string {\n const raw = id.replace(/-/g, \"\");\n if (raw.length !== 32) return id;\n return `${raw.slice(0, 8)}-${raw.slice(8, 12)}-${raw.slice(12, 16)}-${raw.slice(16, 20)}-${raw.slice(20)}`;\n}\n\nexport function notionIdsEqual(a: string, b: string): boolean {\n return a.replace(/-/g, \"\") === b.replace(/-/g, \"\");\n}\n\n/**\n * 멘션 위키링크용 정규 id — 하이픈 제거 + 소문자. 오케스트레이터의 멘션 해소 정규식\n * (`[[notion:<32hex>]]`)이 인식하는 유일한 형태다. 블록 폴백 경로(formatMention)와\n * markdown-api 경로(convertPageMentions)가 동일 형태로 수렴하도록 한다(rank20/I3).\n */\nexport function compactNotionId(id: string): string {\n return id.replace(/-/g, \"\").toLowerCase();\n}\n","export const INITIAL_MIGRATION = `\nCREATE TABLE IF NOT EXISTS sync_state (\n id TEXT PRIMARY KEY,\n obsidian_path TEXT NOT NULL,\n notion_page_id TEXT,\n notion_parent_id TEXT,\n content_hash TEXT NOT NULL,\n notion_last_edited TEXT,\n local_last_modified TEXT NOT NULL,\n sync_direction TEXT NOT NULL DEFAULT 'both',\n file_type TEXT NOT NULL DEFAULT 'file',\n status TEXT NOT NULL DEFAULT 'pending',\n base_snapshot BLOB,\n version INTEGER NOT NULL DEFAULT 1,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\n CONSTRAINT chk_sync_direction CHECK (sync_direction IN ('push', 'pull', 'both')),\n CONSTRAINT chk_file_type CHECK (file_type IN ('file', 'folder-note', 'folder-only', 'db-row')),\n CONSTRAINT chk_status CHECK (status IN ('synced', 'pending', 'conflict', 'error'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_sync_state_path ON sync_state(obsidian_path);\nCREATE UNIQUE INDEX IF NOT EXISTS idx_sync_state_notion ON sync_state(notion_page_id) WHERE notion_page_id IS NOT NULL;\nCREATE INDEX IF NOT EXISTS idx_sync_state_status ON sync_state(status);\nCREATE INDEX IF NOT EXISTS idx_sync_state_parent ON sync_state(notion_parent_id);\n\nCREATE TABLE IF NOT EXISTS wikilink_map (\n obsidian_path TEXT PRIMARY KEY,\n notion_page_id TEXT NOT NULL UNIQUE,\n title TEXT NOT NULL,\n aliases TEXT DEFAULT '[]',\n updated_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_wikilink_title ON wikilink_map(title);\nCREATE INDEX IF NOT EXISTS idx_wikilink_notion ON wikilink_map(notion_page_id);\n\nCREATE TABLE IF NOT EXISTS pending_operations (\n id TEXT PRIMARY KEY,\n sync_state_id TEXT NOT NULL REFERENCES sync_state(id) ON DELETE CASCADE,\n operation TEXT NOT NULL,\n direction TEXT NOT NULL,\n payload TEXT,\n retry_count INTEGER NOT NULL DEFAULT 0,\n error_message TEXT,\n status TEXT NOT NULL DEFAULT 'pending',\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n completed_at TEXT,\n\n CONSTRAINT chk_operation CHECK (operation IN ('create', 'update', 'delete', 'move')),\n CONSTRAINT chk_direction CHECK (direction IN ('push', 'pull')),\n CONSTRAINT chk_op_status CHECK (status IN ('pending', 'processing', 'completed', 'failed'))\n);\n\nCREATE INDEX IF NOT EXISTS idx_pending_status ON pending_operations(status, created_at);\n\nCREATE TABLE IF NOT EXISTS image_registry (\n id TEXT PRIMARY KEY,\n sync_state_id TEXT NOT NULL REFERENCES sync_state(id) ON DELETE CASCADE,\n notion_file_url TEXT NOT NULL,\n local_path TEXT NOT NULL,\n content_hash TEXT NOT NULL,\n file_size INTEGER NOT NULL,\n mime_type TEXT NOT NULL,\n expires_at TEXT,\n downloaded_at TEXT NOT NULL DEFAULT (datetime('now'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_image_hash ON image_registry(content_hash);\nCREATE INDEX IF NOT EXISTS idx_image_sync ON image_registry(sync_state_id);\n\nCREATE TABLE IF NOT EXISTS sync_metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n\nINSERT OR IGNORE INTO sync_metadata (key, value) VALUES ('schema_version', '1');\n`;\n","export const FILE_REGISTRY_MIGRATION = `\nCREATE TABLE IF NOT EXISTS file_registry (\n id TEXT PRIMARY KEY,\n local_path TEXT NOT NULL,\n notion_page_id TEXT NOT NULL,\n file_upload_id TEXT NOT NULL,\n file_type TEXT NOT NULL DEFAULT 'file',\n file_hash TEXT NOT NULL,\n file_size INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL DEFAULT (datetime('now')),\n updated_at TEXT NOT NULL DEFAULT (datetime('now')),\n\n CONSTRAINT chk_file_type CHECK (file_type IN ('image', 'pdf', 'video', 'audio', 'file'))\n);\n\nCREATE UNIQUE INDEX IF NOT EXISTS idx_file_registry_path ON file_registry(local_path);\nCREATE INDEX IF NOT EXISTS idx_file_registry_page ON file_registry(notion_page_id);\n\nUPDATE sync_metadata SET value = '2' WHERE key = 'schema_version';\n`;\n","export const STAT_CACHE_MIGRATION = `\nALTER TABLE sync_state ADD COLUMN local_mtime TEXT;\nALTER TABLE sync_state ADD COLUMN local_file_size INTEGER;\n\nUPDATE sync_metadata SET value = '3' WHERE key = 'schema_version';\n`;\n","import Database from \"better-sqlite3\";\nimport type { SyncRecord, SyncStatus, WikilinkEntry, PreserveMarker } from \"../types/index.js\";\nimport { generateId } from \"../utils/id.js\";\nimport { INITIAL_MIGRATION } from \"./migrations/001-initial.js\";\nimport { FILE_REGISTRY_MIGRATION } from \"./migrations/002-file-registry.js\";\nimport { STAT_CACHE_MIGRATION } from \"./migrations/003-stat-cache.js\";\nimport type { IStateDB } from \"./state-db-interface.js\";\n\nexport class StateDB implements IStateDB {\n private readonly db: Database.Database;\n\n private constructor(db: Database.Database) {\n this.db = db;\n this.db.pragma(\"journal_mode = WAL\");\n this.db.pragma(\"foreign_keys = ON\");\n }\n\n static open(dbPath: string): StateDB {\n const db = new Database(dbPath);\n const stateDb = new StateDB(db);\n stateDb.migrate();\n return stateDb;\n }\n\n private migrate(): void {\n const version = this.getSchemaVersion();\n if (version < 1) {\n this.db.exec(INITIAL_MIGRATION);\n }\n if (version < 2) {\n this.db.exec(FILE_REGISTRY_MIGRATION);\n }\n if (version < 3) {\n this.db.exec(STAT_CACHE_MIGRATION);\n }\n }\n\n private getSchemaVersion(): number {\n try {\n const row = this.db\n .prepare(\"SELECT value FROM sync_metadata WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined;\n return row ? Number(row.value) : 0;\n } catch {\n return 0;\n }\n }\n\n close(): void {\n this.db.close();\n }\n\n // --- sync_state ---\n\n getByPath(path: string): SyncRecord | null {\n const row = this.db.prepare(\"SELECT * FROM sync_state WHERE obsidian_path = ?\").get(path) as\n | RawSyncRow\n | undefined;\n return row ? this.mapRow(row) : null;\n }\n\n getByNotionId(pageId: string): SyncRecord | null {\n const row = this.db.prepare(\"SELECT * FROM sync_state WHERE notion_page_id = ?\").get(pageId) as\n | RawSyncRow\n | undefined;\n return row ? this.mapRow(row) : null;\n }\n\n getByStatus(status: SyncStatus): SyncRecord[] {\n const rows = this.db\n .prepare(\"SELECT * FROM sync_state WHERE status = ?\")\n .all(status) as RawSyncRow[];\n return rows.map((r) => this.mapRow(r));\n }\n\n getAll(): SyncRecord[] {\n const rows = this.db.prepare(\"SELECT * FROM sync_state\").all() as RawSyncRow[];\n return rows.map((r) => this.mapRow(r));\n }\n\n upsert(record: UpsertSyncRecord): SyncRecord {\n const existing = this.getByPath(record.obsidianPath);\n\n if (existing) {\n this.db\n .prepare(\n `UPDATE sync_state SET\n notion_page_id = ?, notion_parent_id = ?, content_hash = ?,\n notion_last_edited = ?, local_last_modified = ?,\n sync_direction = ?, file_type = ?, status = ?,\n base_snapshot = ?, local_mtime = ?, local_file_size = ?,\n version = version + 1, updated_at = datetime('now')\n WHERE id = ?`,\n )\n .run(\n record.notionPageId ?? null,\n record.notionParentId ?? null,\n record.contentHash,\n record.notionLastEdited ?? null,\n record.localLastModified,\n record.syncDirection,\n record.fileType,\n record.status,\n record.baseSnapshot ?? null,\n record.localMtime ?? null,\n record.localFileSize ?? null,\n existing.id,\n );\n return this.getByPath(record.obsidianPath)!;\n }\n\n const id = generateId();\n this.db\n .prepare(\n `INSERT INTO sync_state\n (id, obsidian_path, notion_page_id, notion_parent_id, content_hash,\n notion_last_edited, local_last_modified, sync_direction, file_type,\n status, base_snapshot, local_mtime, local_file_size, version)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)`,\n )\n .run(\n id,\n record.obsidianPath,\n record.notionPageId ?? null,\n record.notionParentId ?? null,\n record.contentHash,\n record.notionLastEdited ?? null,\n record.localLastModified,\n record.syncDirection,\n record.fileType,\n record.status,\n record.baseSnapshot ?? null,\n record.localMtime ?? null,\n record.localFileSize ?? null,\n );\n return this.getByPath(record.obsidianPath)!;\n }\n\n updateStatus(id: string, status: SyncStatus): void {\n this.db\n .prepare(\"UPDATE sync_state SET status = ?, updated_at = datetime('now') WHERE id = ?\")\n .run(status, id);\n }\n\n updateHash(id: string, hash: string, snapshot?: Buffer | null): void {\n if (snapshot !== undefined) {\n this.db\n .prepare(\n \"UPDATE sync_state SET content_hash = ?, base_snapshot = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(hash, snapshot, id);\n } else {\n this.db\n .prepare(\n \"UPDATE sync_state SET content_hash = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(hash, id);\n }\n }\n\n setNotionLastEdited(id: string, lastEdited: string): void {\n this.db\n .prepare(\n \"UPDATE sync_state SET notion_last_edited = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(lastEdited, id);\n }\n\n updateStatCache(id: string, mtime: string, fileSize: number): void {\n this.db\n .prepare(\n \"UPDATE sync_state SET local_mtime = ?, local_file_size = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(mtime, fileSize, id);\n }\n\n setNotionParentId(id: string, parentId: string): void {\n this.db\n .prepare(\n \"UPDATE sync_state SET notion_parent_id = ?, updated_at = datetime('now') WHERE id = ?\",\n )\n .run(parentId, id);\n }\n\n updatePath(id: string, newPath: string): void {\n this.db\n .prepare(\"UPDATE sync_state SET obsidian_path = ?, updated_at = datetime('now') WHERE id = ?\")\n .run(newPath, id);\n }\n\n delete(id: string): void {\n this.db.prepare(\"DELETE FROM sync_state WHERE id = ?\").run(id);\n }\n\n // --- wikilink_map ---\n\n resolveWikilink(text: string): WikilinkEntry | null {\n const byTitle = this.db.prepare(\"SELECT * FROM wikilink_map WHERE title = ?\").get(text) as\n | RawWikilinkRow\n | undefined;\n\n if (byTitle) return this.mapWikilinkRow(byTitle);\n\n const byAlias = this.db\n .prepare(\"SELECT * FROM wikilink_map WHERE aliases LIKE ?\")\n .get(`%\"${text}\"%`) as RawWikilinkRow | undefined;\n\n if (byAlias) return this.mapWikilinkRow(byAlias);\n\n const byFilename = this.db\n .prepare(\"SELECT * FROM wikilink_map WHERE obsidian_path LIKE ?\")\n .get(`%/${text}.md`) as RawWikilinkRow | undefined;\n\n return byFilename ? this.mapWikilinkRow(byFilename) : null;\n }\n\n resolvePageId(pageId: string): WikilinkEntry | null {\n const row = this.db\n .prepare(\"SELECT * FROM wikilink_map WHERE notion_page_id = ?\")\n .get(pageId) as RawWikilinkRow | undefined;\n return row ? this.mapWikilinkRow(row) : null;\n }\n\n upsertWikilink(entry: WikilinkEntry): void {\n this.db\n .prepare(\n `INSERT OR REPLACE INTO wikilink_map (obsidian_path, notion_page_id, title, aliases, updated_at)\n VALUES (?, ?, ?, ?, datetime('now'))`,\n )\n .run(entry.obsidianPath, entry.notionPageId, entry.title, JSON.stringify(entry.aliases));\n }\n\n deleteWikilink(obsidianPath: string): void {\n this.db.prepare(\"DELETE FROM wikilink_map WHERE obsidian_path = ?\").run(obsidianPath);\n }\n\n // --- sync_metadata ---\n\n getMeta(key: string): string | null {\n const row = this.db.prepare(\"SELECT value FROM sync_metadata WHERE key = ?\").get(key) as\n | { value: string }\n | undefined;\n return row?.value ?? null;\n }\n\n setMeta(key: string, value: string): void {\n this.db\n .prepare(\"INSERT OR REPLACE INTO sync_metadata (key, value) VALUES (?, ?)\")\n .run(key, value);\n }\n\n // --- file_registry ---\n\n isFileRegistered(localPath: string): boolean {\n const row = this.db.prepare(\"SELECT 1 FROM file_registry WHERE local_path = ?\").get(localPath);\n return !!row;\n }\n\n getFileRegistry(localPath: string): FileRegistryEntry | null {\n const row = this.db\n .prepare(\"SELECT * FROM file_registry WHERE local_path = ?\")\n .get(localPath) as RawFileRegistryRow | undefined;\n return row ? this.mapFileRegistryRow(row) : null;\n }\n\n getFilesByPageId(notionPageId: string): FileRegistryEntry[] {\n const rows = this.db\n .prepare(\"SELECT * FROM file_registry WHERE notion_page_id = ?\")\n .all(notionPageId) as RawFileRegistryRow[];\n return rows.map((r) => this.mapFileRegistryRow(r));\n }\n\n registerFile(entry: RegisterFileInput): void {\n const id = generateId();\n this.db\n .prepare(\n `INSERT OR REPLACE INTO file_registry\n (id, local_path, notion_page_id, file_upload_id, file_type, file_hash, file_size)\n VALUES (?, ?, ?, ?, ?, ?, ?)`,\n )\n .run(\n id,\n entry.localPath,\n entry.notionPageId,\n entry.fileUploadId,\n entry.fileType,\n entry.fileHash,\n entry.fileSize,\n );\n }\n\n deleteFileRegistry(localPath: string): void {\n this.db.prepare(\"DELETE FROM file_registry WHERE local_path = ?\").run(localPath);\n }\n\n private mapFileRegistryRow(row: RawFileRegistryRow): FileRegistryEntry {\n return {\n id: row.id,\n localPath: row.local_path,\n notionPageId: row.notion_page_id,\n fileUploadId: row.file_upload_id,\n fileType: row.file_type,\n fileHash: row.file_hash,\n fileSize: row.file_size,\n };\n }\n\n // --- pending_operations (I12 크래시 복구 WAL) ---\n\n recordPendingOperation(input: RecordPendingInput): string {\n const id = generateId();\n this.db\n .prepare(\n `INSERT INTO pending_operations\n (id, sync_state_id, operation, direction, payload, status)\n VALUES (?, ?, ?, ?, ?, 'pending')`,\n )\n .run(id, input.syncStateId, input.operation, input.direction, input.payload ?? null);\n return id;\n }\n\n getIncompletePendingOperations(): PendingOperation[] {\n const rows = this.db\n .prepare(\n \"SELECT * FROM pending_operations WHERE status IN ('pending', 'processing') ORDER BY created_at ASC\",\n )\n .all() as RawPendingRow[];\n return rows.map((r) => this.mapPendingRow(r));\n }\n\n getIncompleteOpByState(\n syncStateId: string,\n operation: PendingOperation[\"operation\"],\n ): PendingOperation | null {\n const row = this.db\n .prepare(\n `SELECT * FROM pending_operations\n WHERE sync_state_id = ? AND operation = ? AND status IN ('pending', 'processing')\n ORDER BY created_at ASC LIMIT 1`,\n )\n .get(syncStateId, operation) as RawPendingRow | undefined;\n return row ? this.mapPendingRow(row) : null;\n }\n\n markPendingCompleted(id: string): void {\n this.db\n .prepare(\n \"UPDATE pending_operations SET status = 'completed', completed_at = datetime('now') WHERE id = ?\",\n )\n .run(id);\n }\n\n markPendingFailed(id: string, errorMessage: string): void {\n this.db\n .prepare(\n \"UPDATE pending_operations SET status = 'failed', retry_count = retry_count + 1, error_message = ?, completed_at = datetime('now') WHERE id = ?\",\n )\n .run(errorMessage, id);\n }\n\n clearCompletedOperations(): void {\n this.db.prepare(\"DELETE FROM pending_operations WHERE status IN ('completed', 'failed')\").run();\n }\n\n private mapPendingRow(row: RawPendingRow): PendingOperation {\n return {\n id: row.id,\n syncStateId: row.sync_state_id,\n operation: row.operation as PendingOperation[\"operation\"],\n direction: row.direction as PendingOperation[\"direction\"],\n payload: row.payload,\n retryCount: row.retry_count,\n errorMessage: row.error_message,\n status: row.status as PendingOperation[\"status\"],\n createdAt: row.created_at,\n completedAt: row.completed_at,\n };\n }\n\n // --- preserve markers ---\n\n storePreserveMarkers(path: string, markers: PreserveMarker[]): void {\n if (markers.length === 0) {\n this.db.prepare(\"DELETE FROM sync_metadata WHERE key = ?\").run(`preserve_markers:${path}`);\n return;\n }\n this.setMeta(`preserve_markers:${path}`, JSON.stringify(markers));\n }\n\n getPreserveMarkers(path: string): PreserveMarker[] {\n const value = this.getMeta(`preserve_markers:${path}`);\n if (!value) return [];\n try {\n return JSON.parse(value) as PreserveMarker[];\n } catch {\n return [];\n }\n }\n\n // --- transaction ---\n\n transaction<T>(fn: () => T): T {\n return this.db.transaction(fn)();\n }\n\n // --- private ---\n\n private mapRow(row: RawSyncRow): SyncRecord {\n return {\n id: row.id,\n obsidianPath: row.obsidian_path,\n notionPageId: row.notion_page_id,\n notionParentId: row.notion_parent_id,\n contentHash: row.content_hash,\n notionLastEdited: row.notion_last_edited,\n localLastModified: row.local_last_modified,\n syncDirection: row.sync_direction as SyncRecord[\"syncDirection\"],\n fileType: row.file_type as SyncRecord[\"fileType\"],\n status: row.status as SyncRecord[\"status\"],\n baseSnapshot: row.base_snapshot,\n localMtime: row.local_mtime,\n localFileSize: row.local_file_size,\n version: row.version,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n }\n\n private mapWikilinkRow(row: RawWikilinkRow): WikilinkEntry {\n return {\n obsidianPath: row.obsidian_path,\n notionPageId: row.notion_page_id,\n title: row.title,\n aliases: JSON.parse(row.aliases || \"[]\") as string[],\n };\n }\n}\n\nexport interface UpsertSyncRecord {\n readonly obsidianPath: string;\n readonly notionPageId?: string | null;\n readonly notionParentId?: string | null;\n readonly contentHash: string;\n readonly notionLastEdited?: string | null;\n readonly localLastModified: string;\n readonly syncDirection: SyncRecord[\"syncDirection\"];\n readonly fileType: SyncRecord[\"fileType\"];\n readonly status: SyncRecord[\"status\"];\n readonly baseSnapshot?: Buffer | null;\n readonly localMtime?: string | null;\n readonly localFileSize?: number | null;\n}\n\ninterface RawSyncRow {\n id: string;\n obsidian_path: string;\n notion_page_id: string | null;\n notion_parent_id: string | null;\n content_hash: string;\n notion_last_edited: string | null;\n local_last_modified: string;\n sync_direction: string;\n file_type: string;\n status: string;\n base_snapshot: Buffer | null;\n local_mtime: string | null;\n local_file_size: number | null;\n version: number;\n created_at: string;\n updated_at: string;\n}\n\ninterface RawWikilinkRow {\n obsidian_path: string;\n notion_page_id: string;\n title: string;\n aliases: string;\n updated_at: string;\n}\n\ninterface RawFileRegistryRow {\n id: string;\n local_path: string;\n notion_page_id: string;\n file_upload_id: string;\n file_type: string;\n file_hash: string;\n file_size: number;\n}\n\nexport interface FileRegistryEntry {\n readonly id: string;\n readonly localPath: string;\n readonly notionPageId: string;\n readonly fileUploadId: string;\n readonly fileType: string;\n readonly fileHash: string;\n readonly fileSize: number;\n}\n\nexport interface RegisterFileInput {\n readonly localPath: string;\n readonly notionPageId: string;\n readonly fileUploadId: string;\n readonly fileType: string;\n readonly fileHash: string;\n readonly fileSize: number;\n}\n\ninterface RawPendingRow {\n id: string;\n sync_state_id: string;\n operation: string;\n direction: string;\n payload: string | null;\n retry_count: number;\n error_message: string | null;\n status: string;\n created_at: string;\n completed_at: string | null;\n}\n\n/** I12 크래시 복구 WAL 항목. push/pull 적용 전 기록되고, 적용 완료 시 completed 로 마감된다. */\nexport interface PendingOperation {\n readonly id: string;\n readonly syncStateId: string;\n readonly operation: \"create\" | \"update\" | \"delete\" | \"move\";\n readonly direction: \"push\" | \"pull\";\n readonly payload: string | null;\n readonly retryCount: number;\n readonly errorMessage: string | null;\n readonly status: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n readonly createdAt: string;\n readonly completedAt: string | null;\n}\n\nexport interface RecordPendingInput {\n readonly syncStateId: string;\n readonly operation: PendingOperation[\"operation\"];\n readonly direction: PendingOperation[\"direction\"];\n readonly payload?: string | null;\n}\n","type NotionPropertySchema = {\n id: string;\n type: string;\n name: string;\n};\n\ntype NotionPropertyValue = Record<string, unknown>;\n\n// ISO-8601 date / datetime. **양끝 앵커 필수** — 앵커가 없으면 \"2026-05-29 마감\" 처럼\n// 날짜로 시작하는 일반 텍스트가 date 로 오분류되어 본문이 유실되고 Notion 에 잘못된\n// 날짜가 전송된다. 초/밀리초/타임존(Z, ±HH:MM)까지 허용해 read→write 라운드트립을 보존.\nconst DATE_REGEX =\n /^\\d{4}-\\d{2}-\\d{2}(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,3})?)?(?:Z|[+-]\\d{2}:?\\d{2})?)?$/;\nconst WIKILINK_REGEX = /^\\[\\[(.+?)(?:\\|.+?)?\\]\\]$/;\n\n/**\n * Notion 은 비어 있는 배열형 속성값을 문서화된 `[]` 가 아니라 빈 객체 `{}` 로\n * 돌려주는 경우가 있다(특히 data source 분리 모델의 일부 행). `as Array<…>` 캐스트는\n * 이 불일치를 숨기고, 뒤따르는 `.map` 호출이 \"X.map is not a function\" 으로 그 행\n * 전체를 pull 실패시켜 **영구 데이터 손실 + 멱등성(churn) 위반**을 만든다.\n * 모든 배열 추출은 이 가드를 통과시켜, 배열이 아니면 안전하게 빈 배열로 강등한다.\n */\nfunction asArray<T>(value: unknown): T[] {\n return Array.isArray(value) ? (value as T[]) : [];\n}\n\nexport interface WikilinkResolver {\n resolve(title: string): string | null;\n resolvePageId(pageId: string): string | null;\n}\n\nexport class PropertyMapper {\n private schema: Map<string, NotionPropertySchema> = new Map();\n private wikilinkResolver: WikilinkResolver | null = null;\n\n setWikilinkResolver(resolver: WikilinkResolver): void {\n this.wikilinkResolver = resolver;\n }\n\n loadSchema(properties: Record<string, { id: string; type: string }>): void {\n this.schema.clear();\n for (const [name, prop] of Object.entries(properties)) {\n this.schema.set(name, { id: prop.id, type: prop.type, name });\n }\n }\n\n toNotionProperties(\n frontmatter: Record<string, unknown>,\n title: string,\n ): Record<string, NotionPropertyValue> {\n const result: Record<string, NotionPropertyValue> = {\n title: { title: [{ text: { content: title } }] },\n };\n\n for (const [key, value] of Object.entries(frontmatter)) {\n if (key === \"title\") continue;\n if (value === null || value === undefined) continue;\n\n const schemaProp = this.schema.get(key);\n if (schemaProp) {\n const converted = this.convertBySchema(schemaProp.type, value);\n if (converted) result[key] = converted;\n } else {\n const inferred = this.inferAndConvert(value);\n if (inferred) result[key] = inferred;\n }\n }\n\n return result;\n }\n\n fromNotionProperties(notionProps: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, rawProp] of Object.entries(notionProps)) {\n const prop = rawProp as { type: string; [k: string]: unknown };\n if (prop.type === \"title\") continue;\n const value = this.extractValue(prop);\n if (value !== undefined) {\n result[key] = value;\n }\n }\n\n return result;\n }\n\n private convertBySchema(type: string, value: unknown): NotionPropertyValue | null {\n switch (type) {\n case \"rich_text\":\n return { rich_text: [{ text: { content: String(value) } }] };\n\n case \"number\": {\n // 숫자로 변환 불가한 값(NaN/Infinity)은 전송하지 않는다. {number: NaN} 은\n // JSON 직렬화 시 null 로 바뀌어 기존 값을 소리 없이 비워버린다.\n const num = typeof value === \"number\" ? value : Number(value);\n return Number.isFinite(num) ? { number: num } : null;\n }\n\n case \"select\": {\n // 빈 이름은 Notion API 가 거부한다. 공백뿐이면 스킵(기존 값 보존).\n const name = String(value);\n return name.trim() ? { select: { name } } : null;\n }\n\n case \"multi_select\": {\n const items = Array.isArray(value)\n ? value\n : String(value)\n .split(\",\")\n .map((s) => s.trim());\n // 빈 옵션 이름 제거 — \"a,,b\" 나 후행 콤마로 생긴 빈 항목은 Notion 이 거부한다.\n const names = items.map((name: unknown) => String(name)).filter((name) => name.trim());\n return { multi_select: names.map((name) => ({ name })) };\n }\n\n case \"checkbox\":\n return { checkbox: Boolean(value) };\n\n case \"date\": {\n if (typeof value === \"object\" && value !== null && \"start\" in value) {\n const obj = value as { start: string; end?: string | null };\n return { date: { start: obj.start, end: obj.end ?? null } };\n }\n const dateStr = String(value);\n if (DATE_REGEX.test(dateStr)) {\n return { date: { start: dateStr, end: null } };\n }\n return null;\n }\n\n case \"url\":\n return { url: String(value) };\n\n case \"email\":\n return { email: String(value) };\n\n case \"phone_number\":\n return { phone_number: String(value) };\n\n case \"status\": {\n // select 와 동일 — 빈 상태 이름은 Notion 이 거부한다.\n const name = String(value);\n return name.trim() ? { status: { name } } : null;\n }\n\n case \"relation\": {\n const items = Array.isArray(value) ? value : [value];\n const ids: Array<{ id: string }> = [];\n for (const item of items) {\n const str = String(item);\n const match = str.match(WIKILINK_REGEX);\n if (match?.[1] && this.wikilinkResolver) {\n const pageId = this.wikilinkResolver.resolve(match[1]);\n if (pageId) ids.push({ id: pageId });\n } else if (str.match(/^[0-9a-f-]{32,36}$/)) {\n ids.push({ id: str });\n }\n }\n return ids.length > 0 ? { relation: ids } : null;\n }\n\n case \"people\": {\n const users = Array.isArray(value) ? value : [value];\n const peopleArr = users\n .map((u) => {\n const s = String(u);\n if (s.match(/^[0-9a-f-]{32,36}$/)) return { object: \"user\" as const, id: s };\n return null;\n })\n .filter(Boolean);\n return peopleArr.length > 0 ? { people: peopleArr } : null;\n }\n\n case \"files\": {\n const fileList = Array.isArray(value) ? value : [value];\n // 빈 URL 파일 항목은 Notion 이 거부하므로 제거한다(잘못된 첨부 전송 방지).\n const filesArr = fileList\n .map((f) => {\n if (typeof f === \"object\" && f !== null && \"url\" in f) {\n const obj = f as { name?: string; url: string };\n const url = String(obj.url ?? \"\");\n if (!url) return null;\n return { type: \"external\", name: obj.name ?? \"file\", external: { url } };\n }\n const url = String(f);\n if (!url) return null;\n return { type: \"external\", name: url, external: { url } };\n })\n .filter(Boolean);\n return { files: filesArr };\n }\n\n case \"created_time\":\n case \"last_edited_time\":\n case \"created_by\":\n case \"last_edited_by\":\n case \"formula\":\n case \"rollup\":\n case \"unique_id\":\n case \"verification\":\n return null;\n\n default:\n return { rich_text: [{ text: { content: String(value) } }] };\n }\n }\n\n private inferAndConvert(value: unknown): NotionPropertyValue | null {\n if (typeof value === \"boolean\") {\n return { checkbox: value };\n }\n if (typeof value === \"number\") {\n return { number: value };\n }\n if (Array.isArray(value)) {\n return {\n multi_select: value.map((v) => ({ name: String(v) })),\n };\n }\n if (typeof value === \"string\") {\n if (DATE_REGEX.test(value)) {\n return { date: { start: value, end: null } };\n }\n if (value.startsWith(\"http://\") || value.startsWith(\"https://\")) {\n return { url: value };\n }\n return { rich_text: [{ text: { content: value } }] };\n }\n return null;\n }\n\n private extractValue(prop: { type: string; [k: string]: unknown }): unknown {\n switch (prop.type) {\n case \"rich_text\": {\n const arr = asArray<{ plain_text: string }>(prop.rich_text);\n return arr.map((t) => t.plain_text).join(\"\") || null;\n }\n case \"number\":\n return prop.number;\n case \"select\": {\n const sel = prop.select as { name: string } | null;\n return sel?.name ?? null;\n }\n case \"multi_select\": {\n return asArray<{ name: string }>(prop.multi_select).map((s) => s.name);\n }\n case \"checkbox\":\n return prop.checkbox;\n case \"date\": {\n const dateObj = prop.date as { start: string; end?: string | null } | null;\n if (!dateObj) return null;\n if (dateObj.end) return { start: dateObj.start, end: dateObj.end };\n return dateObj.start;\n }\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 \"status\": {\n const status = prop.status as { name: string } | null;\n return status?.name ?? null;\n }\n case \"created_time\":\n return prop.created_time;\n case \"last_edited_time\":\n return prop.last_edited_time;\n case \"people\": {\n return asArray<{ name?: string; id: string }>(prop.people).map((p) => p.name ?? p.id);\n }\n case \"files\": {\n const files = asArray<{\n name: string;\n type: string;\n file?: { url: string };\n external?: { url: string };\n }>(prop.files);\n // Obsidian Bases 의 카드 `image:` 는 스칼라 문자열(외부 URL 또는 [[wikilink]])만\n // 렌더한다 — [{name,url}] 객체 배열은 표시되지 않는다. 따라서 URL 문자열로 직렬화한다.\n // 단일 파일 → 스칼라(갤러리 커버 렌더), 복수 → URL 배열(데이터 보존).\n // toNotionProperties 의 files 케이스가 문자열/문자열배열을 모두 받으므로 라운드트립 안전.\n const urls = files\n .map((f) => (f.type === \"file\" ? f.file?.url : f.external?.url))\n .filter((u): u is string => typeof u === \"string\" && u.length > 0);\n if (urls.length === 0) return [];\n return urls.length === 1 ? urls[0] : urls;\n }\n case \"formula\": {\n const formula = prop.formula as { type: string; [k: string]: unknown } | undefined;\n if (!formula) return null;\n return formula[formula.type];\n }\n case \"relation\": {\n const rel = asArray<{ id: string }>(prop.relation);\n if (rel.length === 0) return [];\n return rel.map((r) => {\n if (this.wikilinkResolver) {\n const title = this.wikilinkResolver.resolvePageId(r.id);\n if (title) return `[[${title}]]`;\n }\n return r.id;\n });\n }\n case \"rollup\": {\n const rollup = prop.rollup as { type: string; [k: string]: unknown } | undefined;\n if (!rollup) return null;\n if (rollup.type === \"array\") {\n const arr = asArray<{ type: string; [k: string]: unknown }>(rollup.array);\n return arr.map((item) => this.extractValue(item));\n }\n return rollup[rollup.type] ?? null;\n }\n case \"unique_id\": {\n const uid = prop.unique_id as { prefix?: string; number?: number } | undefined;\n // number 가 없으면(빈 객체 등) \"undefined\" 문자열이 새는 것을 막는다.\n if (!uid || typeof uid.number !== \"number\") return null;\n return uid.prefix ? `${uid.prefix}-${uid.number}` : String(uid.number);\n }\n case \"created_by\":\n case \"last_edited_by\": {\n const user = prop[prop.type] as { name?: string; id: string } | undefined;\n return user?.name ?? user?.id ?? null;\n }\n case \"verification\": {\n const v = prop.verification as { state: string } | undefined;\n return v?.state ?? null;\n }\n default:\n return null;\n }\n }\n}\n","export interface Logger {\n warn(message: string, ...args: unknown[]): void;\n error(message: string, ...args: unknown[]): void;\n info(message: string, ...args: unknown[]): void;\n debug(message: string, ...args: unknown[]): void;\n}\n\nconst consoleLogger: Logger = {\n warn: (msg, ...args) => console.warn(msg, ...args),\n error: (msg, ...args) => console.error(msg, ...args),\n info: (msg, ...args) => console.info(msg, ...args),\n debug: () => {},\n};\n\nlet currentLogger: Logger = consoleLogger;\n\nexport function setLogger(logger: Logger): void {\n currentLogger = logger;\n}\n\nexport function getLogger(): Logger {\n return currentLogger;\n}\n","import { Client, LogLevel } from \"@notionhq/client\";\nimport { Sema } from \"async-sema\";\nimport type {\n BlockObjectResponse,\n PageObjectResponse,\n PartialBlockObjectResponse,\n PageMarkdownResponse,\n} from \"@notionhq/client/build/src/api-endpoints.js\";\nimport type {\n DataSourceViewObjectResponse,\n ListDatabaseViewsResponse,\n} from \"@notionhq/client/build/src/api-endpoints/views.js\";\nimport { PropertyMapper, type WikilinkResolver } from \"./property-mapper.js\";\nimport type { ViewConfig, DatabaseViewsConfig, PageCover, PageIcon } from \"../types/view.js\";\nimport type { Config } from \"../types/config.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { normalizeNotionId } from \"../utils/id.js\";\n\n/**\n * Notion SDK 의 404(`object_not_found`) 판별 — 링크드 DB·미공유 데이터 소스·삭제된\n * 페이지/DB 의 **권위적 신호**다. 그래야 일시적/실제 오류(검증·rate limit·5xx)와 구분해\n * 행 동기화 불가를 정직히 강등(스택트레이스 대신 1줄 + denylist)할 수 있다.\n * SDK 의 `APIResponseError` 는 `code`/`status` 를 노출한다.\n */\nexport function isNotionObjectNotFound(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n const e = error as { code?: unknown; status?: unknown };\n return e.code === \"object_not_found\" || e.status === 404;\n}\n\n/**\n * 서브트리 직접 순회(getChildPagesRecursive) 비용이 시간 예산을 초과했을 때 던지는 신호.\n * 순회 비용은 **서브트리 전체 블록 수**에 비례(중첩 페이지 무손실 탐색을 위해 모든 블록을\n * 깊이 순회)하므로, 콘텐츠가 많은 대규모 서브트리에서는 워크스페이스 search 기반 디스커버리\n * (비용이 워크스페이스 페이지 수에 비례·예측가능)가 더 저렴하다. 이 오류를 받은 호출측은\n * search 기반 폴백(getPagesUnderRootViaSearch)으로 전환한다. 작은 볼트는 예산 안에서\n * 순회가 끝나 폴백 없이 빠르게 완료된다(이중 전략의 분기점).\n */\nexport class DiscoveryTooLargeError extends Error {\n constructor(elapsedMs: number) {\n super(`subtree discovery exceeded time budget (${elapsedMs}ms)`);\n this.name = \"DiscoveryTooLargeError\";\n }\n}\n\nexport interface NotionClientOptions {\n readonly token: string;\n readonly concurrency?: number;\n readonly timeoutMs?: number;\n readonly rateLimitIntervalMs?: number;\n readonly maxRetries?: number;\n readonly retryBaseDelayMs?: number;\n readonly retryBackoffFactor?: number;\n readonly pageSize?: number;\n readonly batchSize?: number;\n readonly fetch?: typeof globalThis.fetch;\n}\n\nexport class NotionClient {\n private readonly client: Client;\n private readonly sema: Sema;\n private readonly propertyMapper = new PropertyMapper();\n\n private readonly minRequestInterval: number;\n private readonly maxRetries: number;\n private readonly retryBaseDelayMs: number;\n private readonly retryBackoffFactor: number;\n private readonly defaultPageSize: number;\n private readonly batchSize: number;\n\n constructor(options: NotionClientOptions) {\n this.client = new Client({\n auth: options.token,\n timeoutMs: options.timeoutMs ?? 30000,\n logLevel: LogLevel.ERROR,\n ...(options.fetch ? { fetch: options.fetch } : {}),\n });\n this.sema = new Sema(options.concurrency ?? 3);\n this.minRequestInterval = options.rateLimitIntervalMs ?? 350;\n this.maxRetries = options.maxRetries ?? 5;\n this.retryBaseDelayMs = options.retryBaseDelayMs ?? 1000;\n this.retryBackoffFactor = options.retryBackoffFactor ?? 2;\n this.defaultPageSize = options.pageSize ?? 100;\n this.batchSize = options.batchSize ?? 100;\n }\n\n /** config.advanced 의 운영 튜닝값으로 클라이언트를 생성한다 (매직넘버 단일 진실원). */\n static fromConfig(config: Config, fetch?: typeof globalThis.fetch): NotionClient {\n const a = config.advanced;\n return new NotionClient({\n token: config.notion.token,\n concurrency: a.concurrency,\n timeoutMs: a.timeoutMs,\n rateLimitIntervalMs: a.rateLimitIntervalMs,\n maxRetries: a.maxRetries,\n retryBaseDelayMs: a.retryBaseDelayMs,\n retryBackoffFactor: a.retryBackoffFactor,\n pageSize: a.pageSize,\n batchSize: a.batchSize,\n ...(fetch ? { fetch } : {}),\n });\n }\n\n getInternalClient(): Client {\n return this.client;\n }\n\n // ─── Page CRUD ───\n\n async getPage(pageId: string): Promise<PageObjectResponse> {\n return this.withRateLimit(\n () => this.client.pages.retrieve({ page_id: pageId }) as Promise<PageObjectResponse>,\n );\n }\n\n async createPage(params: {\n parentId: string;\n parentType: \"page\" | \"database\";\n title: string;\n properties?: Record<string, unknown>;\n children?: BlockObjectResponse[];\n }): Promise<PageObjectResponse> {\n const parent =\n params.parentType === \"database\"\n ? { database_id: params.parentId }\n : { page_id: params.parentId };\n\n const properties =\n params.parentType === \"page\"\n ? { title: { title: [{ text: { content: params.title } }] } }\n : ((params.properties as never) ?? {\n title: { title: [{ text: { content: params.title } }] },\n });\n\n return this.withRateLimit(\n () =>\n this.client.pages.create({\n parent,\n properties: properties as never,\n children: params.children as never,\n }) as Promise<PageObjectResponse>,\n );\n }\n\n async createPageWithMarkdown(params: {\n parentId: string;\n parentType: \"page\" | \"database\";\n title: string;\n markdown: string;\n properties?: Record<string, unknown>;\n }): Promise<PageObjectResponse> {\n const parent =\n params.parentType === \"database\"\n ? { database_id: params.parentId }\n : { page_id: params.parentId };\n\n const properties =\n params.parentType === \"page\"\n ? { title: { title: [{ text: { content: params.title } }] } }\n : ((params.properties as never) ?? {\n title: { title: [{ text: { content: params.title } }] },\n });\n\n return this.withRateLimit(\n () =>\n this.client.pages.create({\n parent,\n properties: properties as never,\n markdown: params.markdown,\n }) as Promise<PageObjectResponse>,\n );\n }\n\n async updatePageProperties(\n pageId: string,\n properties: Record<string, unknown>,\n ): Promise<PageObjectResponse> {\n return this.withRateLimit(\n () =>\n this.client.pages.update({\n page_id: pageId,\n properties: properties as never,\n }) as Promise<PageObjectResponse>,\n );\n }\n\n // ─── Markdown API ───\n\n async getPageMarkdown(pageId: string): Promise<PageMarkdownResponse> {\n return this.withRateLimit(() => this.client.pages.retrieveMarkdown({ page_id: pageId }));\n }\n\n async replacePageMarkdown(pageId: string, markdown: string): Promise<PageMarkdownResponse> {\n return this.withRateLimit(() =>\n this.client.pages.updateMarkdown({\n page_id: pageId,\n type: \"replace_content\",\n replace_content: {\n new_str: markdown,\n allow_deleting_content: true,\n },\n }),\n );\n }\n\n async updatePageMarkdownPartial(\n pageId: string,\n patches: Array<{ oldStr: string; newStr: string; replaceAll?: boolean }>,\n ): Promise<PageMarkdownResponse> {\n return this.withRateLimit(() =>\n this.client.pages.updateMarkdown({\n page_id: pageId,\n type: \"update_content\",\n update_content: {\n content_updates: patches.map((p) => ({\n old_str: p.oldStr,\n new_str: p.newStr,\n replace_all_matches: p.replaceAll ?? false,\n })),\n allow_deleting_content: true,\n },\n }),\n );\n }\n\n // ─── Page Move ───\n\n async movePage(\n pageId: string,\n newParentId: string,\n newParentType: \"page\" | \"database\",\n ): Promise<PageObjectResponse> {\n const parent =\n newParentType === \"database\" ? { database_id: newParentId } : { page_id: newParentId };\n return this.withRateLimit(\n () =>\n this.client.pages.update({\n page_id: pageId,\n parent,\n } as never) as Promise<PageObjectResponse>,\n );\n }\n\n // ─── Database / DataSource ───\n\n /**\n * 데이터베이스 1개를 신 모델(2025-09-03 data source 분리)로 조회한다.\n * - title: database 객체에 그대로 존재한다.\n * - properties(스키마): 신 모델에선 data source 에 있으므로 1차 data source 를 조회해 채운다.\n * data source 접근 불가(링크드 DB 등)면 database 객체의 properties 로 폴백한다(제목은 보존).\n *\n * 폐기한 레거시 raw fetch(`GET /v1/databases/{id}`, Notion-Version 2022-06-28)는 신 모델로\n * 업그레이드된 다수 DB에 400 을 반환해 자동 발견 DB 가 통째 드롭(내용 손실)되던 원인이었다.\n * SDK(`databases.retrieve`/`dataSources.retrieve`)는 동일 토큰으로 정상 동작한다.\n */\n private async fetchDatabaseModern(databaseId: string): Promise<Record<string, unknown>> {\n const db = (await this.withRateLimit(() =>\n this.client.databases.retrieve({ database_id: databaseId }),\n )) as unknown as {\n title?: unknown;\n properties?: Record<string, unknown>;\n data_sources?: Array<{ id: string; name?: string }>;\n };\n\n // 신 모델(2025-09-03): 한 database 가 2개 이상의 data source 를 가질 수 있고, 각 data\n // source 가 자체 스키마(properties)를 갖는다. 1차 data source 만 읽으면 2번째+ 의 컬럼이\n // 침묵 유실되므로 접근 가능한 전 data source 의 properties 를 union 병합한다(이름 충돌은\n // 첫 정의 우선 — 동일 컬럼이 여러 소스에 중복돼도 안정적). 어떤 data source 도 접근\n // 불가하면 database 객체의 properties 로 폴백(제목은 이미 확보).\n const dataSources = db.data_sources ?? [];\n const merged: Record<string, unknown> = {};\n let anyAccessible = false;\n for (const ds of dataSources) {\n try {\n const dsObj = (await this.withRateLimit(() =>\n this.client.dataSources.retrieve({ data_source_id: ds.id }),\n )) as unknown as { properties?: Record<string, unknown> };\n if (dsObj.properties && Object.keys(dsObj.properties).length > 0) {\n anyAccessible = true;\n for (const [name, prop] of Object.entries(dsObj.properties)) {\n if (!(name in merged)) merged[name] = prop;\n }\n }\n } catch {\n // 접근 불가 data source 건너뜀 — 나머지 소스로 계속.\n }\n }\n\n const properties: Record<string, unknown> = anyAccessible ? merged : (db.properties ?? {});\n return { title: db.title, properties };\n }\n\n async getDatabaseTitle(databaseId: string): Promise<string> {\n const db = await this.fetchDatabaseModern(databaseId);\n const titleArr = db.title as Array<{ plain_text: string }> | undefined;\n return titleArr?.[0]?.plain_text ?? \"\";\n }\n\n /**\n * 발견된 DB 가 **동기화 가능한지**(접근 가능한 data source 가 있는지) 1회 호출로 판별한다.\n * 신 모델(2025-09-03)에서 링크드 DB·미공유 데이터 소스·삭제 DB 는 `data_sources` 가\n * 비어, 행 조회(`dataSources.query`)가 404 로 실패하고 그 전에 생성된 빈 폴더/`.base` 만\n * 남긴다. 발견 단계에서 미리 걸러 **빈 폴더/.base 오염 + 매 pull 의 404 노이즈**를 차단한다.\n * 제목은 함께 반환해 호출처가 추가 조회 없이 폴더명을 잡게 한다.\n */\n async getDatabaseSyncability(databaseId: string): Promise<{ title: string; queryable: boolean }> {\n const db = (await this.withRateLimit(() =>\n this.client.databases.retrieve({ database_id: databaseId }),\n )) as unknown as {\n title?: Array<{ plain_text: string }>;\n data_sources?: Array<{ id: string }>;\n };\n const title = Array.isArray(db.title) ? (db.title[0]?.plain_text ?? \"\") : \"\";\n return { title, queryable: (db.data_sources?.length ?? 0) > 0 };\n }\n\n async getDatabaseSchema(\n databaseId: string,\n ): Promise<Record<string, { id: string; type: string }>> {\n const db = await this.fetchDatabaseModern(databaseId);\n const properties = db.properties as Record<string, { id: string; type: string }> | undefined;\n if (!properties) return {};\n const schema: Record<string, { id: string; type: string }> = {};\n for (const [name, prop] of Object.entries(properties)) {\n schema[name] = { id: prop.id, type: prop.type };\n }\n return schema;\n }\n\n async getDatabaseSchemaFull(databaseId: string): Promise<\n Record<\n string,\n {\n id: string;\n type: string;\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n }\n >\n > {\n const db = await this.fetchDatabaseModern(databaseId);\n const properties = db.properties as Record<string, Record<string, unknown>> | undefined;\n if (!properties) return {};\n\n const schema: Record<\n string,\n {\n id: string;\n type: string;\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n }\n > = {};\n\n for (const [name, prop] of Object.entries(properties)) {\n const entry: {\n id: string;\n type: string;\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n } = {\n id: prop.id as string,\n type: prop.type as string,\n };\n\n if (prop.type === \"select\" || prop.type === \"multi_select\") {\n const typeData = prop[prop.type as string] as\n | {\n options?: Array<{ name: string; color?: string }>;\n }\n | undefined;\n if (typeData?.options) {\n entry.options = typeData.options.map((o) => ({ name: o.name, color: o.color }));\n }\n }\n\n if (prop.type === \"status\") {\n const statusData = prop.status as\n | {\n options?: Array<{ name: string; color?: string }>;\n groups?: Array<{ name: string; color?: string; option_ids?: string[] }>;\n }\n | undefined;\n if (statusData?.options) {\n entry.options = statusData.options.map((o) => ({ name: o.name, color: o.color }));\n }\n if (statusData?.groups) {\n entry.groups = statusData.groups.map((g) => ({\n name: g.name,\n color: g.color,\n optionIds: g.option_ids,\n }));\n }\n }\n\n schema[name] = entry;\n }\n\n return schema;\n }\n\n /** 특정 data source 1개를 직접 쿼리한다(저수준). 다중 data source 순회의 빌딩블록. */\n private async queryDataSource(\n dataSourceId: string,\n options?: { startCursor?: string; pageSize?: number; filter?: unknown },\n ): Promise<{ results: PageObjectResponse[]; nextCursor: string | null }> {\n const response = await this.withRateLimit(() =>\n this.client.dataSources.query({\n data_source_id: dataSourceId,\n start_cursor: options?.startCursor,\n page_size: options?.pageSize ?? this.defaultPageSize,\n filter: options?.filter as never,\n }),\n );\n return {\n results: response.results as PageObjectResponse[],\n nextCursor: response.next_cursor,\n };\n }\n\n /**\n * database 의 1차 data source 1페이지를 쿼리한다(증분 detect 등 단일 소스 경로용).\n * 전 행을 빠짐없이 받으려면 {@link queryAllDatabasePages} 를 쓴다(전 data source 순회).\n */\n async queryDatabase(\n databaseId: string,\n options?: { startCursor?: string; pageSize?: number; filter?: unknown },\n ): Promise<{ results: PageObjectResponse[]; nextCursor: string | null }> {\n const dsId = await this.getDataSourceId(databaseId);\n return this.queryDataSource(dsId, options);\n }\n\n /**\n * database 의 **모든 data source** 행을 빠짐없이 조회한다(2025-09-03 신 모델).\n * 한 database 가 2개 이상의 data source(각자 행 집합)를 가질 수 있어, 1차 data source 만\n * 페이지네이션하면 2번째+ 의 행이 통째 침묵 유실된다. 전 data source 를 순회·페이지네이션\n * 하고 page_id 로 디듀프(소스 간 동일 페이지 방어)한 뒤 합친다. 다중 소스면 1회 경고해\n * \"소스별 탭 구분이 한 폴더로 병합\"되는 점을 비침묵으로 알린다.\n */\n async queryAllDatabasePages(databaseId: string, filter?: unknown): Promise<PageObjectResponse[]> {\n const metas = await this.getDataSourceMetas(databaseId);\n if (metas.length > 1) {\n const label = metas.map((m) => m.name || m.id).join(\", \");\n getLogger().warn(\n `[Notion] DB ${databaseId} 에 data source ${metas.length}개 발견 — 전 소스 행을 한 폴더로 병합 동기화합니다 (${label}). 소스별 탭 구분은 .base 뷰에 보존되지 않습니다.`,\n );\n }\n\n const all: PageObjectResponse[] = [];\n const seen = new Set<string>();\n for (const meta of metas) {\n let cursor: string | undefined;\n do {\n const response = await this.queryDataSource(meta.id, {\n startCursor: cursor,\n pageSize: this.defaultPageSize,\n filter,\n });\n for (const page of response.results) {\n const key = normalizeNotionId(page.id);\n if (seen.has(key)) continue;\n seen.add(key);\n all.push(page);\n }\n cursor = response.nextCursor ?? undefined;\n } while (cursor);\n }\n\n return all;\n }\n\n /** database 의 1차 data source id(없으면 databaseId 폴백). 단일 소스 경로 호환용. */\n async getDataSourceId(databaseId: string): Promise<string> {\n const metas = await this.getDataSourceMetas(databaseId);\n return metas[0]?.id ?? databaseId;\n }\n\n /**\n * database 의 전 data source 메타(id + 이름)를 반환한다. data source 가 없으면(레거시/단일)\n * databaseId 자체를 단일 소스로 폴백해 호출처가 항상 ≥1 개를 받게 한다.\n */\n async getDataSourceMetas(databaseId: string): Promise<Array<{ id: string; name: string }>> {\n const db = (await this.withRateLimit(() =>\n this.client.databases.retrieve({ database_id: databaseId }),\n )) as unknown as { data_sources?: Array<{ id: string; name?: string }> };\n const list = db.data_sources ?? [];\n if (list.length === 0) return [{ id: databaseId, name: \"\" }];\n return list.map((ds) => ({ id: ds.id, name: ds.name ?? \"\" }));\n }\n\n async archivePage(pageId: string): Promise<void> {\n await this.withRateLimit(() => this.client.pages.update({ page_id: pageId, archived: true }));\n }\n\n async getFileBlockUrl(blockId: string): Promise<string | null> {\n try {\n const block = await this.withRateLimit(() =>\n this.client.blocks.retrieve({ block_id: blockId }),\n );\n const b = block as unknown as {\n type: string;\n file?: { file?: { url: string }; external?: { url: string } };\n pdf?: { file?: { url: string }; external?: { url: string } };\n video?: { file?: { url: string }; external?: { url: string } };\n audio?: { file?: { url: string }; external?: { url: string } };\n image?: { file?: { url: string }; external?: { url: string } };\n };\n const media = b.file ?? b.pdf ?? b.video ?? b.audio ?? b.image;\n return media?.file?.url ?? media?.external?.url ?? null;\n } catch {\n return null;\n }\n }\n\n async getBlock(blockId: string): Promise<BlockObjectResponse> {\n return this.withRateLimit(() =>\n this.client.blocks.retrieve({ block_id: blockId }),\n ) as Promise<BlockObjectResponse>;\n }\n\n // ─── Block CRUD ───\n\n async listChildren(\n blockId: string,\n options?: { startCursor?: string; pageSize?: number },\n ): Promise<{\n results: (BlockObjectResponse | PartialBlockObjectResponse)[];\n nextCursor: string | null;\n }> {\n const response = await this.withRateLimit(() =>\n this.client.blocks.children.list({\n block_id: blockId,\n start_cursor: options?.startCursor,\n page_size: options?.pageSize ?? this.defaultPageSize,\n }),\n );\n return {\n results: response.results,\n nextCursor: response.next_cursor,\n };\n }\n\n async fetchAllChildren(blockId: string): Promise<BlockObjectResponse[]> {\n const blocks: BlockObjectResponse[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await this.listChildren(blockId, { startCursor: cursor });\n blocks.push(...response.results.filter((b): b is BlockObjectResponse => \"type\" in b));\n cursor = response.nextCursor ?? undefined;\n } while (cursor);\n\n return blocks;\n }\n\n private static readonly CONTAINER_BLOCK_TYPES = new Set([\n \"column_list\",\n \"column\",\n \"callout\",\n \"toggle\",\n \"quote\",\n ]);\n\n async fetchAllChildrenDeep(blockId: string): Promise<BlockObjectResponse[]> {\n const directChildren = await this.fetchAllChildren(blockId);\n const allBlocks: BlockObjectResponse[] = [...directChildren];\n\n const toExpand = directChildren.filter((b) => {\n if (!b.has_children) return false;\n if (b.type === \"child_page\" || b.type === \"child_database\") return false;\n if (NotionClient.CONTAINER_BLOCK_TYPES.has(b.type)) return true;\n if (b.type === \"synced_block\") {\n const sb = b as unknown as { synced_block: { synced_from: { block_id: string } | null } };\n return sb.synced_block?.synced_from === null;\n }\n return true;\n });\n\n for (const container of toExpand) {\n try {\n const nested = await this.fetchAllChildrenDeep(container.id);\n allBlocks.push(...nested);\n } catch {\n // 접근 권한 없는 블록 무시\n }\n }\n\n return allBlocks;\n }\n\n async appendChildren(blockId: string, children: unknown[]): Promise<void> {\n const batchSize = this.batchSize;\n for (let i = 0; i < children.length; i += batchSize) {\n const batch = children.slice(i, i + batchSize);\n await this.withRateLimit(() =>\n this.client.blocks.children.append({\n block_id: blockId,\n children: batch as never,\n }),\n );\n }\n }\n\n async deleteBlock(blockId: string): Promise<void> {\n await this.withRateLimit(() => this.client.blocks.delete({ block_id: blockId }));\n }\n\n // ─── File Upload ───\n\n async uploadFile(fileData: Blob, filename: string, contentType: string): Promise<string> {\n const upload = await this.withRateLimit(() =>\n this.client.fileUploads.create({ filename, content_type: contentType }),\n );\n\n const fileUploadId = (upload as unknown as { id: string }).id;\n\n const sendResult = await this.withRateLimit(() =>\n this.client.fileUploads.send({\n file_upload_id: fileUploadId,\n file: { data: fileData, filename },\n }),\n );\n\n const status = (sendResult as unknown as { status: string }).status;\n if (status === \"pending\") {\n await this.withRateLimit(() =>\n this.client.fileUploads.complete({ file_upload_id: fileUploadId }),\n );\n }\n\n return fileUploadId;\n }\n\n // ─── Search & Navigation ───\n\n async search(params: {\n query?: string;\n filter?: { property: \"object\"; value: \"page\" | \"data_source\" };\n startCursor?: string;\n pageSize?: number;\n }): Promise<{ results: PageObjectResponse[]; nextCursor: string | null }> {\n const response = await this.withRateLimit(() =>\n this.client.search({\n query: params.query,\n filter: params.filter,\n start_cursor: params.startCursor,\n page_size: params.pageSize ?? this.defaultPageSize,\n }),\n );\n return {\n results: response.results as PageObjectResponse[],\n nextCursor: response.next_cursor,\n };\n }\n\n async searchRecentPages(since: string): Promise<Array<{ id: string; last_edited_time: string }>> {\n const results: Array<{ id: string; last_edited_time: string }> = [];\n let cursor: string | undefined;\n const sinceDate = new Date(since);\n\n outer: do {\n const response = await this.withRateLimit(() =>\n this.client.search({\n filter: { property: \"object\", value: \"page\" },\n sort: { direction: \"descending\", timestamp: \"last_edited_time\" },\n start_cursor: cursor,\n page_size: this.defaultPageSize,\n }),\n );\n\n for (const page of response.results) {\n const p = page as PageObjectResponse;\n if (new Date(p.last_edited_time) <= sinceDate) {\n break outer;\n }\n results.push({ id: p.id, last_edited_time: p.last_edited_time });\n }\n\n cursor = response.next_cursor ?? undefined;\n } while (cursor);\n\n return results;\n }\n\n async getChildPages(parentId: string): Promise<PageObjectResponse[]> {\n const blocks = await this.fetchAllChildrenDeep(parentId);\n const childPageBlocks = blocks.filter((b) => b.type === \"child_page\");\n\n if (childPageBlocks.length === 0) return [];\n\n const pages = await Promise.all(childPageBlocks.map((b) => this.getPage(b.id)));\n // 휴지통/아카이브된 페이지 제외: 부모 블록에는 child_page 참조가 남아 있어도\n // 대상 페이지가 삭제(in_trash)·보관(archived)된 경우 블록 조회 시 object_not_found가\n // 발생하므로 동기화 대상에서 사전 제거한다. (재귀 스캔의 무한·실패 전파 차단)\n return pages.filter((p) => !NotionClient.isTrashedOrArchived(p));\n }\n\n /** 페이지가 휴지통(in_trash)이거나 보관(archived) 상태인지 판정한다. */\n private static isTrashedOrArchived(page: PageObjectResponse): boolean {\n // in_trash는 런타임 응답에는 존재하나 SDK 타입에 미선언 → 안전 캐스트로 접근\n const inTrash = (page as { in_trash?: boolean }).in_trash === true;\n return inTrash || page.archived === true;\n }\n\n async getChildDatabaseIds(parentId: string): Promise<string[]> {\n const children = await this.fetchAllChildren(parentId);\n return children.filter((b) => b.type === \"child_database\").map((b) => b.id);\n }\n\n /**\n * root 서브트리를 직접 BFS 순회해 하위 페이지를 모두 수집한다(중첩 깊이 무관·무손실).\n * 비용은 서브트리 전체 블록 수에 비례한다.\n *\n * @param opts.deadlineMs `Date.now()` 기준 마감 시각. 각 페이지 처리 전 초과를 검사해\n * 초과 시 {@link DiscoveryTooLargeError}를 던진다(대규모 서브트리 → search 폴백 유도).\n * 미지정 시 무제한(기존 동작 유지 — 테스트 mock 경로는 영향 없음).\n */\n async getChildPagesRecursive(\n parentId: string,\n opts?: { deadlineMs?: number },\n ): Promise<PageObjectResponse[]> {\n const all: PageObjectResponse[] = [];\n let currentLevel: string[] = [parentId];\n const start = Date.now();\n\n while (currentLevel.length > 0) {\n const nextLevel: string[] = [];\n\n for (const id of currentLevel) {\n if (opts?.deadlineMs !== undefined && Date.now() > opts.deadlineMs) {\n throw new DiscoveryTooLargeError(Date.now() - start);\n }\n let children: PageObjectResponse[];\n try {\n children = await this.getChildPages(id);\n } catch (error) {\n // 한 서브트리가 접근 불가(공유 해제·삭제 등)여도 전체 스캔이 중단되지 않도록\n // 해당 노드만 건너뛴다. 형제·다른 가지의 페이지 손실을 방지한다.\n getLogger().warn(\n `[Im-Nobsidian] 하위 페이지 스캔 건너뜀 (${id}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n continue;\n }\n for (const child of children) {\n all.push(child);\n nextLevel.push(child.id);\n }\n }\n\n currentLevel = nextLevel;\n }\n\n return all;\n }\n\n /** 워크스페이스에서 통합에 공유된 모든 페이지를 bulk search 로 열거한다(100/요청). */\n async searchAllPages(): Promise<PageObjectResponse[]> {\n const pages: PageObjectResponse[] = [];\n let cursor: string | undefined;\n do {\n const r = await this.search({\n filter: { property: \"object\", value: \"page\" },\n startCursor: cursor,\n });\n pages.push(...r.results);\n cursor = r.nextCursor ?? undefined;\n } while (cursor);\n return pages;\n }\n\n /**\n * root 하위 페이지를 **search 기반**으로 디스커버리한다(대규모 서브트리용 폴백).\n *\n * 전략: 워크스페이스 전체 페이지를 1회 bulk search 로 열거(비용 ∝ 워크스페이스 페이지 수,\n * 예측가능·유한)한 뒤, 각 페이지의 부모 체인을 따라 root 도달 여부를 판정한다. page_id\n * 부모는 메모리 맵으로 추가 호출 없이 즉시 해석하고, block_id 부모(컬럼·토글 등 레이아웃에\n * 중첩된 페이지)만 getBlock 으로 소유 페이지를 해석(memo)한다. search 는 중첩 깊이와 무관하게\n * 모든 페이지를 반환하므로 직접 순회와 동일하게 **무손실**이다.\n *\n * getChildPagesRecursive 와 동일 집합을 보장하기 위해:\n * - DB 행(parent=data_source_id/database_id)은 child_page 로 도달 불가 → 제외\n * - 휴지통/보관(in_trash/archived) 페이지 제외\n * - root 자신은 제외(직접 순회도 root 의 *자식*부터 수집)\n */\n async getPagesUnderRootViaSearch(rootId: string): Promise<PageObjectResponse[]> {\n const all = await this.searchAllPages();\n const rootN = normalizeNotionId(rootId);\n const byId = new Map<string, PageObjectResponse>();\n for (const p of all) byId.set(normalizeNotionId(p.id), p);\n\n type Parent = {\n type: string;\n page_id?: string;\n block_id?: string;\n data_source_id?: string;\n database_id?: string;\n };\n\n // block_id → 소유 페이지 id(없으면 null). 같은 블록 재해석을 막는 memo.\n const blockOwner = new Map<string, string | null>();\n const resolveBlockOwner = async (blockId: string): Promise<string | null> => {\n let bid = blockId;\n const seen = new Set<string>();\n for (let i = 0; i < 20 && bid && !seen.has(bid); i++) {\n seen.add(bid);\n const cached = blockOwner.get(bid);\n if (cached !== undefined) return cached;\n let bp: Parent;\n try {\n bp = ((await this.getBlock(bid)) as unknown as { parent: Parent }).parent;\n } catch {\n blockOwner.set(bid, null);\n return null;\n }\n if (bp.type === \"page_id\" && bp.page_id) {\n const owner = bp.page_id;\n blockOwner.set(blockId, owner);\n return owner;\n }\n if (bp.type === \"block_id\" && bp.block_id) {\n bid = bp.block_id;\n continue;\n }\n blockOwner.set(blockId, null);\n return null; // data_source_id/database_id/workspace → 페이지 소유자 아님\n }\n return null;\n };\n\n // pageId(normalized) → root 하위 여부. 체인 전체를 한 번에 memo 한다.\n const memo = new Map<string, boolean>();\n const isUnderRoot = async (startId: string): Promise<boolean> => {\n const chain: string[] = [];\n let cur: string | null = normalizeNotionId(startId);\n const seen = new Set<string>();\n let result = false;\n while (cur && !seen.has(cur)) {\n if (cur === rootN) {\n result = true;\n break;\n }\n const cached = memo.get(cur);\n if (cached !== undefined) {\n result = cached;\n break;\n }\n seen.add(cur);\n chain.push(cur);\n const pg = byId.get(cur);\n if (!pg) break; // 부모가 열거 집합 밖(root 위/미공유) → root 하위 아님\n const parent = pg.parent as Parent;\n if (parent.type === \"page_id\" && parent.page_id) {\n cur = normalizeNotionId(parent.page_id);\n } else if (parent.type === \"block_id\" && parent.block_id) {\n const owner = await resolveBlockOwner(parent.block_id);\n cur = owner ? normalizeNotionId(owner) : null;\n } else {\n cur = null; // workspace/data_source_id/database_id → 체인 종료\n }\n }\n for (const c of chain) memo.set(c, result);\n return result;\n };\n\n const out: PageObjectResponse[] = [];\n for (const p of all) {\n const pid = normalizeNotionId(p.id);\n if (pid === rootN) continue; // root 자신 제외\n const ptype = (p.parent as Parent).type;\n if (ptype === \"data_source_id\" || ptype === \"database_id\") continue; // DB 행 제외\n if (NotionClient.isTrashedOrArchived(p)) continue;\n if (await isUnderRoot(p.id)) out.push(p);\n }\n return out;\n }\n\n // ─── Views API ───\n\n async listDatabaseViews(databaseId: string): Promise<ViewConfig[]> {\n const allViews: ViewConfig[] = [];\n let cursor: string | undefined;\n\n do {\n const response = await this.withRateLimit(() =>\n this.client.views.list({\n database_id: databaseId,\n start_cursor: cursor,\n page_size: this.defaultPageSize,\n }),\n );\n\n const viewRefs = (response as ListDatabaseViewsResponse).results;\n for (const ref of viewRefs) {\n try {\n const detail = await this.getView(ref.id as string);\n if (detail) allViews.push(detail);\n } catch {\n // 뷰 상세 조회 실패 시 스킵\n }\n }\n\n cursor = (response as ListDatabaseViewsResponse).next_cursor as string | undefined;\n } while (cursor);\n\n return allViews;\n }\n\n async getView(viewId: string): Promise<ViewConfig | null> {\n const view = await this.withRateLimit(() => this.client.views.retrieve({ view_id: viewId }));\n\n const v = view as DataSourceViewObjectResponse;\n if (!v.type) return null;\n\n return parseViewResponse(v);\n }\n\n async getDatabaseViewsConfig(databaseId: string): Promise<DatabaseViewsConfig> {\n const views = await this.listDatabaseViews(databaseId);\n return {\n databaseId,\n lastSynced: new Date().toISOString(),\n views,\n };\n }\n\n // ─── Cover / Icon Extraction ───\n\n extractCover(page: PageObjectResponse): PageCover | null {\n const raw = page as unknown as {\n cover?: {\n type: string;\n file?: { url: string; expiry_time?: string };\n external?: { url: string };\n };\n };\n if (!raw.cover) return null;\n\n if (raw.cover.type === \"file\" && raw.cover.file) {\n return {\n type: \"file\",\n url: raw.cover.file.url,\n expiryTime: raw.cover.file.expiry_time,\n };\n }\n if (raw.cover.type === \"external\" && raw.cover.external) {\n return { type: \"external\", url: raw.cover.external.url };\n }\n return null;\n }\n\n extractIcon(page: PageObjectResponse): PageIcon | null {\n const raw = page as unknown as {\n icon?: {\n type: string;\n emoji?: string;\n external?: { url: string };\n file?: { url: string; expiry_time?: string };\n icon?: { name: string; color?: string };\n };\n };\n if (!raw.icon) return null;\n\n switch (raw.icon.type) {\n case \"emoji\":\n return { type: \"emoji\", value: raw.icon.emoji! };\n case \"external\":\n return { type: \"external\", value: raw.icon.external!.url };\n case \"file\":\n return { type: \"file\", value: raw.icon.file!.url };\n case \"icon\":\n return { type: \"icon\", value: raw.icon.icon!.name, color: raw.icon.icon!.color };\n default:\n return null;\n }\n }\n\n // ─── Property Extraction ───\n\n extractTitle(page: PageObjectResponse): string {\n const props = page.properties as Record<\n string,\n { type: string; title?: Array<{ plain_text?: string }> }\n >;\n for (const prop of Object.values(props)) {\n // 빈 제목 행은 Notion 이 title 을 배열이 아닌 빈 객체({})로 돌려주기도 한다.\n // Array.isArray 가드 없이 .map 을 호출하면 \"title.map is not a function\" 으로\n // 그 행 전체가 pull 실패→손실되고 매 pull 마다 churn 이 남는다(멱등성 위반).\n if (prop.type === \"title\" && Array.isArray(prop.title)) {\n const joined = prop.title.map((t) => t.plain_text ?? \"\").join(\"\");\n if (joined) return joined;\n }\n }\n return \"제목 없음\";\n }\n\n /**\n * 페이지 모드 pull(extractProperties)의 relation/people 속성을 raw Notion UUID 가\n * 아니라 [[제목]] 위키링크로 해소하도록 resolver 를 주입한다. 주입하지 않으면 매\n * pull 마다 relation 이 raw UUID 로 재생성돼, 후처리(resolveNotionLinks)에만 의존하는\n * 2-write churn 이 남는다(M1). DB 모드는 orchestrator/DatabaseSyncer 의 자체 mapper 가\n * 이미 resolver 를 주입받아 면역이다.\n */\n setWikilinkResolver(resolver: WikilinkResolver): void {\n this.propertyMapper.setWikilinkResolver(resolver);\n }\n\n extractProperties(page: PageObjectResponse): Record<string, unknown> {\n return this.propertyMapper.fromNotionProperties(page.properties as Record<string, unknown>);\n }\n\n // ─── Internal ───\n\n private lastRequestTime = 0;\n\n private async withRateLimit<T>(fn: () => Promise<T>): Promise<T> {\n await this.sema.acquire();\n try {\n const now = Date.now();\n const elapsed = now - this.lastRequestTime;\n if (elapsed < this.minRequestInterval) {\n await sleep(this.minRequestInterval - elapsed);\n }\n this.lastRequestTime = Date.now();\n return await this.executeWithRetry(fn);\n } finally {\n this.sema.release();\n }\n }\n\n private async executeWithRetry<T>(fn: () => Promise<T>, attempt: number = 0): Promise<T> {\n try {\n return await fn();\n } catch (error: unknown) {\n if (isRetryable(error) && attempt < this.maxRetries) {\n const baseDelay =\n extractRetryAfter(error) ??\n this.retryBaseDelayMs * Math.pow(this.retryBackoffFactor, attempt);\n const jitter = baseDelay * (0.5 + Math.random() * 0.5);\n await sleep(jitter);\n return this.executeWithRetry(fn, attempt + 1);\n }\n throw error;\n }\n }\n}\n\nfunction isRetryable(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n const code = (error as { code?: string }).code;\n if (code === \"notionhq_client_request_timeout\" || code === \"ECONNRESET\" || code === \"ETIMEDOUT\") {\n return true;\n }\n if (!(\"status\" in error)) return false;\n const status = (error as { status: number }).status;\n return status === 429 || status === 502 || status === 503 || status === 504;\n}\n\nfunction extractRetryAfter(error: unknown): number | null {\n if (typeof error === \"object\" && error !== null && \"headers\" in error) {\n const headers = (error as { headers: Record<string, string> }).headers;\n const retryAfter = headers?.[\"retry-after\"];\n if (retryAfter) return Number(retryAfter) * 1000;\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction parseViewResponse(v: DataSourceViewObjectResponse): ViewConfig {\n const config: ViewConfig = {\n id: v.id as string,\n name: v.name,\n type: v.type,\n dataSourceId: v.data_source_id,\n filter: v.filter,\n sorts: v.sorts?.map((s) => {\n if (\"property\" in s) {\n return { property: s.property, direction: s.direction };\n }\n return { timestamp: s.timestamp, direction: s.direction };\n }),\n ...extractViewTypeConfig(v.configuration),\n };\n return config;\n}\n\ntype MutableViewConfig = {\n -readonly [K in keyof ViewConfig]: ViewConfig[K];\n};\n\nfunction extractViewTypeConfig(\n cfg: DataSourceViewObjectResponse[\"configuration\"],\n): Partial<MutableViewConfig> {\n if (!cfg) return {};\n\n const result: Partial<MutableViewConfig> = {};\n\n if (\"properties\" in cfg && cfg.properties) {\n result.properties = cfg.properties.map((p) => ({\n propertyId: p.property_id,\n propertyName: p.property_name,\n visible: p.visible,\n width: p.width,\n wrap: p.wrap,\n }));\n }\n\n if (\"group_by\" in cfg && cfg.group_by) {\n const gb = cfg.group_by;\n result.groupBy = {\n type: gb.type,\n propertyId: gb.property_id,\n propertyName: \"property_name\" in gb ? (gb.property_name as string) : undefined,\n sort:\n \"sort\" in gb && gb.sort\n ? ((gb.sort as { type: string }).type as \"manual\" | \"ascending\" | \"descending\")\n : undefined,\n hideEmptyGroups: \"hide_empty_groups\" in gb ? (gb.hide_empty_groups as boolean) : undefined,\n };\n }\n\n if (\"cover\" in cfg && cfg.cover) {\n result.cover = {\n type: cfg.cover.type,\n propertyId: cfg.cover.property_id,\n };\n }\n\n if (\"cover_size\" in cfg) result.coverSize = cfg.cover_size;\n if (\"cover_aspect\" in cfg) result.coverAspect = cfg.cover_aspect;\n\n if (\"date_property_id\" in cfg) {\n result.datePropertyId = cfg.date_property_id;\n result.datePropertyName = cfg.date_property_name;\n }\n\n if (\"view_range\" in cfg) result.viewRange = cfg.view_range;\n\n return result;\n}\n","const VALID_COLORS = new Set([\n \"default\",\n \"gray\",\n \"brown\",\n \"orange\",\n \"yellow\",\n \"green\",\n \"blue\",\n \"purple\",\n \"pink\",\n \"red\",\n \"gray_background\",\n \"brown_background\",\n \"orange_background\",\n \"yellow_background\",\n \"green_background\",\n \"blue_background\",\n \"purple_background\",\n \"pink_background\",\n \"red_background\",\n]);\n\ntype NotionColor = string;\n\nfunction safeColor(color: string): NotionColor {\n return VALID_COLORS.has(color) ? color : \"default\";\n}\n\nexport interface RichTextSegment {\n content: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n code?: boolean;\n color?: string;\n link?: string;\n}\n\nexport interface NotionRichText {\n type: \"text\";\n text: { content: string; link?: { url: string } | null };\n annotations: {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n code: boolean;\n color: string;\n };\n}\n\nexport interface NotionEquationRichText {\n type: \"equation\";\n equation: { expression: string };\n}\n\nexport interface NotionMentionRichText {\n type: \"mention\";\n mention:\n | { type: \"page\"; page: { id: string } }\n | { type: \"date\"; date: { start: string; end?: string } }\n | { type: \"user\"; user: { id: string } }\n | { type: \"database\"; database: { id: string } };\n}\n\nexport type RichTextItem = NotionRichText | NotionEquationRichText | NotionMentionRichText;\n\nexport interface NotionBlock {\n object?: \"block\";\n type: string;\n [key: string]: unknown;\n}\n\nexport class NotionBlockBuilder {\n // ─── Rich Text ──────────────────────────────────────────\n\n static richText(content: string, options?: Partial<RichTextSegment>): NotionRichText[] {\n const textObj: { content: string; link?: { url: string } | null } = { content };\n if (options?.link) {\n textObj.link = { url: options.link };\n }\n return [\n {\n type: \"text\",\n text: textObj,\n annotations: {\n bold: options?.bold ?? false,\n italic: options?.italic ?? false,\n underline: options?.underline ?? false,\n strikethrough: options?.strikethrough ?? false,\n code: options?.code ?? false,\n color: safeColor(options?.color ?? \"default\"),\n },\n },\n ];\n }\n\n static richTextArray(segments: RichTextSegment[]): NotionRichText[] {\n return segments.map((seg) => {\n const textObj: { content: string; link?: { url: string } | null } = {\n content: seg.content,\n };\n if (seg.link) {\n textObj.link = { url: seg.link };\n }\n return {\n type: \"text\" as const,\n text: textObj,\n annotations: {\n bold: seg.bold ?? false,\n italic: seg.italic ?? false,\n underline: seg.underline ?? false,\n strikethrough: seg.strikethrough ?? false,\n code: seg.code ?? false,\n color: safeColor(seg.color ?? \"default\"),\n },\n };\n });\n }\n\n static richTextEquation(expression: string): NotionEquationRichText[] {\n return [{ type: \"equation\", equation: { expression } }];\n }\n\n static richTextMentionPage(pageId: string): NotionMentionRichText[] {\n return [{ type: \"mention\", mention: { type: \"page\", page: { id: pageId } } }];\n }\n\n static richTextMentionDate(start: string, end?: string): NotionMentionRichText[] {\n const date: { start: string; end?: string } = { start };\n if (end) date.end = end;\n return [{ type: \"mention\", mention: { type: \"date\", date } }];\n }\n\n // ─── Basic Blocks ───────────────────────────────────────\n\n static paragraph(richText: RichTextItem[], color?: string): NotionBlock {\n return {\n object: \"block\",\n type: \"paragraph\",\n paragraph: { rich_text: richText, color: safeColor(color ?? \"default\") },\n };\n }\n\n static heading(\n level: 1 | 2 | 3,\n richText: RichTextItem[],\n options?: { color?: string; isToggleable?: boolean; children?: NotionBlock[] },\n ): NotionBlock {\n const key = `heading_${level}`;\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(options?.color ?? \"default\"),\n is_toggleable: options?.isToggleable ?? false,\n };\n if (options?.isToggleable && options?.children) {\n data.children = options.children;\n }\n return { object: \"block\", type: key, [key]: data };\n }\n\n static callout(\n richText: RichTextItem[],\n icon?: string,\n options?: { color?: string; children?: NotionBlock[] },\n ): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n icon: { type: \"emoji\", emoji: icon ?? \"\\u{1F4CC}\" },\n color: safeColor(options?.color ?? \"default\"),\n };\n if (options?.children) {\n data.children = options.children;\n }\n return { object: \"block\", type: \"callout\", callout: data };\n }\n\n static toggle(richText: RichTextItem[], children?: NotionBlock[], color?: string): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return { object: \"block\", type: \"toggle\", toggle: data };\n }\n\n static bulletedListItem(\n richText: RichTextItem[],\n children?: NotionBlock[],\n color?: string,\n ): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return {\n object: \"block\",\n type: \"bulleted_list_item\",\n bulleted_list_item: data,\n };\n }\n\n static numberedListItem(\n richText: RichTextItem[],\n children?: NotionBlock[],\n color?: string,\n ): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return {\n object: \"block\",\n type: \"numbered_list_item\",\n numbered_list_item: data,\n };\n }\n\n static toDo(richText: RichTextItem[], checked?: boolean, color?: string): NotionBlock {\n return {\n object: \"block\",\n type: \"to_do\",\n to_do: {\n rich_text: richText,\n checked: checked ?? false,\n color: safeColor(color ?? \"default\"),\n },\n };\n }\n\n static quote(richText: RichTextItem[], children?: NotionBlock[], color?: string): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: richText,\n color: safeColor(color ?? \"default\"),\n };\n if (children) {\n data.children = children;\n }\n return { object: \"block\", type: \"quote\", quote: data };\n }\n\n static divider(): NotionBlock {\n return { object: \"block\", type: \"divider\", divider: {} };\n }\n\n static code(code: string, language?: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n rich_text: NotionBlockBuilder.richText(code),\n language: language ?? \"plain text\",\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"code\", code: data };\n }\n\n static equationBlock(expression: string): NotionBlock {\n return {\n object: \"block\",\n type: \"equation\",\n equation: { expression },\n };\n }\n\n // ─── Media Blocks ───────────────────────────────────────\n\n static image(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"image\", image: data };\n }\n\n static bookmark(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = { url };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"bookmark\", bookmark: data };\n }\n\n static video(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"video\", video: data };\n }\n\n static audio(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"audio\", audio: data };\n }\n\n static fileBlock(url: string, name?: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (name) data.name = name;\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"file\", file: data };\n }\n\n static pdf(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = {\n type: \"external\",\n external: { url },\n };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"pdf\", pdf: data };\n }\n\n static embed(url: string, caption?: string): NotionBlock {\n const data: Record<string, unknown> = { url };\n if (caption) {\n data.caption = NotionBlockBuilder.richText(caption);\n }\n return { object: \"block\", type: \"embed\", embed: data };\n }\n\n // ─── Advanced Blocks ────────────────────────────────────\n\n static tableOfContents(color?: string): NotionBlock {\n return {\n object: \"block\",\n type: \"table_of_contents\",\n table_of_contents: { color: safeColor(color ?? \"default\") },\n };\n }\n\n static breadcrumb(): NotionBlock {\n return { object: \"block\", type: \"breadcrumb\", breadcrumb: {} };\n }\n\n static columnList(columns: NotionBlock[][]): NotionBlock {\n const children = columns.map((colBlocks) => ({\n object: \"block\" as const,\n type: \"column\" as const,\n column: { children: colBlocks },\n }));\n return {\n object: \"block\",\n type: \"column_list\",\n column_list: { children },\n };\n }\n\n static syncedBlockOriginal(children: NotionBlock[]): NotionBlock {\n return {\n object: \"block\",\n type: \"synced_block\",\n synced_block: { synced_from: null, children },\n };\n }\n\n static syncedBlockDuplicate(originalBlockId: string): NotionBlock {\n return {\n object: \"block\",\n type: \"synced_block\",\n synced_block: { synced_from: { block_id: originalBlockId } },\n };\n }\n\n static linkToPage(pageId: string): NotionBlock {\n return {\n object: \"block\",\n type: \"link_to_page\",\n link_to_page: { type: \"page_id\", page_id: pageId },\n };\n }\n\n static table(rows: string[][], hasColumnHeader?: boolean, hasRowHeader?: boolean): NotionBlock {\n if (rows.length === 0) rows = [[\"\", \"\"]];\n const width = rows[0]!.length;\n const tableRows = rows.map((row) => {\n const cells = row.map((cell) => NotionBlockBuilder.richText(cell));\n while (cells.length < width) {\n cells.push(NotionBlockBuilder.richText(\"\"));\n }\n return {\n object: \"block\" as const,\n type: \"table_row\" as const,\n table_row: { cells },\n };\n });\n return {\n object: \"block\",\n type: \"table\",\n table: {\n table_width: width,\n has_column_header: hasColumnHeader ?? true,\n has_row_header: hasRowHeader ?? false,\n children: tableRows,\n },\n };\n }\n}\n","import { createHash } from \"node:crypto\";\n\nexport function computeHash(content: string): string {\n return createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n}\n\nexport function computeBufferHash(buffer: Buffer): string {\n return createHash(\"sha256\").update(buffer).digest(\"hex\");\n}\n","import type { LocalChange } from \"../types/sync.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { FileStatInfo } from \"./vault-fs.js\";\nimport { computeHash } from \"../utils/hash.js\";\n\nexport interface FileInfo {\n readonly path: string;\n readonly content: string;\n readonly mtime: string;\n}\n\nexport class ChangeDetector {\n constructor(private readonly stateDb: IStateDB) {}\n\n async detectLocalChangesFast(\n stats: FileStatInfo[],\n readFile: (path: string) => Promise<string>,\n ): Promise<LocalChange[]> {\n const changes: LocalChange[] = [];\n const existingPaths = new Set<string>();\n\n for (const file of stats) {\n existingPaths.add(file.path);\n const record = this.stateDb.getByPath(file.path);\n\n if (!record) {\n const content = await readFile(file.path);\n changes.push({\n path: file.path,\n type: \"created\",\n currentHash: computeHash(content),\n previousHash: null,\n });\n continue;\n }\n\n if (record.localMtime === file.mtime && record.localFileSize === file.size) {\n continue;\n }\n\n const content = await readFile(file.path);\n const currentHash = computeHash(content);\n if (record.contentHash !== currentHash) {\n changes.push({\n path: file.path,\n type: \"modified\",\n currentHash,\n previousHash: record.contentHash,\n });\n }\n }\n\n const syncedRecords = this.stateDb.getByStatus(\"synced\");\n for (const record of syncedRecords) {\n if (!existingPaths.has(record.obsidianPath)) {\n if (record.fileType === \"folder-note\" || record.fileType === \"folder-only\") {\n if (!record.obsidianPath.endsWith(\".md\")) continue;\n }\n changes.push({\n path: record.obsidianPath,\n type: \"deleted\",\n currentHash: \"\",\n previousHash: record.contentHash,\n });\n }\n }\n\n return this.detectMoves(changes);\n }\n\n detectLocalChanges(currentFiles: FileInfo[]): LocalChange[] {\n const changes: LocalChange[] = [];\n const existingPaths = new Set<string>();\n\n for (const file of currentFiles) {\n existingPaths.add(file.path);\n const record = this.stateDb.getByPath(file.path);\n\n if (!record) {\n changes.push({\n path: file.path,\n type: \"created\",\n currentHash: computeHash(file.content),\n previousHash: null,\n });\n continue;\n }\n\n if (record.localMtime && record.localMtime === file.mtime) {\n continue;\n }\n\n const currentHash = computeHash(file.content);\n if (record.contentHash !== currentHash) {\n changes.push({\n path: file.path,\n type: \"modified\",\n currentHash,\n previousHash: record.contentHash,\n });\n }\n }\n\n const syncedRecords = this.stateDb.getByStatus(\"synced\");\n for (const record of syncedRecords) {\n if (!existingPaths.has(record.obsidianPath)) {\n if (record.fileType === \"folder-note\" || record.fileType === \"folder-only\") {\n if (!record.obsidianPath.endsWith(\".md\")) continue;\n }\n changes.push({\n path: record.obsidianPath,\n type: \"deleted\",\n currentHash: \"\",\n previousHash: record.contentHash,\n });\n }\n }\n\n return this.detectMoves(changes);\n }\n\n private detectMoves(changes: LocalChange[]): LocalChange[] {\n const result: LocalChange[] = [];\n const created = changes.filter((c) => c.type === \"created\");\n const deleted = changes.filter((c) => c.type === \"deleted\");\n const others = changes.filter((c) => c.type !== \"created\" && c.type !== \"deleted\");\n\n const matchedCreated = new Set<string>();\n const matchedDeleted = new Set<string>();\n\n for (const del of deleted) {\n const match = created.find(\n (c) => c.currentHash === del.previousHash && !matchedCreated.has(c.path),\n );\n if (match) {\n matchedCreated.add(match.path);\n matchedDeleted.add(del.path);\n result.push({\n path: match.path,\n type: \"moved\",\n currentHash: match.currentHash,\n previousHash: del.previousHash,\n movedFrom: del.path,\n });\n }\n }\n\n for (const c of created) {\n if (!matchedCreated.has(c.path)) result.push(c);\n }\n for (const d of deleted) {\n if (!matchedDeleted.has(d.path)) result.push(d);\n }\n result.push(...others);\n\n return result;\n }\n}\n","/**\n * 보존 마커(preserve marker) 단일 진실원(SSOT).\n *\n * 변환 불가 요소를 라운드트립 보존하기 위해 본문에 삽입하는 마커가 공유하는\n * 브랜드 토큰을 한곳에서 정의한다. 리브랜딩 시 {@link MARKER_BRAND}만 바꾸면\n * 모든 빌더·정규식에 반영된다.\n *\n * 주의: 마커 포맷(공백 유무)은 기존 vault·Notion에 이미 기록된 데이터와의 호환을\n * 위해 변경하지 않는다. 두 포맷이 공존한다 — 공백형(`%% brand:... %%`)과\n * 압축형(`%%brand:...%%`).\n */\n\n/** 모든 보존 마커가 공유하는 브랜드 토큰. */\nexport const MARKER_BRAND = \"im-nobsidian\";\n\n// ─── 의사 프로토콜 (링크 보존) ───\n\n/** 위키링크 보존용 의사 프로토콜 prefix: `im-nobsidian://wikilink/`. */\nexport const WIKILINK_PROTOCOL = `${MARKER_BRAND}://wikilink/`;\n\n/** 임베드 보존용 의사 프로토콜 prefix: `im-nobsidian://embed/`. */\nexport const EMBED_PROTOCOL = `${MARKER_BRAND}://embed/`;\n\n// ─── 공백형 마커 `%% im-nobsidian:BODY %%` ───\n\n/** 공백형 HTML 주석 마커 생성: `%% im-nobsidian:BODY %%`. */\nexport function spacedMarker(body: string): string {\n return `%% ${MARKER_BRAND}:${body} %%`;\n}\n\n/** 공백형 마커 종료 토큰: `%% im-nobsidian:end %%`. */\nexport const SPACED_END = spacedMarker(\"end\");\n\n// ─── 압축형 마커 `%%im-nobsidian:BODY%%` ───\n\n/** 압축형 마커 생성: `%%im-nobsidian:BODY%%`. */\nexport function compactMarker(body: string): string {\n return `%%${MARKER_BRAND}:${body}%%`;\n}\n\n/** 토글 블록 보존 마커 (enhanced-md-converter / block-converter 공유). */\nexport const TOGGLE_START = compactMarker(\"toggle:start\");\nexport const TOGGLE_END = compactMarker(\"toggle:end\");\n\n/** 컬럼 레이아웃 보존 마커 (block-converter). */\nexport const COLUMN_LIST_START = compactMarker(\"column-list:start\");\nexport const COLUMN_LIST_END = compactMarker(\"column-list:end\");\nexport const COLUMN_SEP = compactMarker(\"column\");\n\n/** 목차(table of contents) 블록 보존 마커. */\nexport const TOC_MARKER = compactMarker(\"toc\");\n\n/**\n * breadcrumb 블록 보존 마커. Notion breadcrumb 은 마크다운 표현이 없어 pull 시\n * 빈 문자열로 소실됐다 — 이 마커로 자리를 남겨 push 시 breadcrumb 블록으로 복원한다.\n */\nexport const BREADCRUMB_MARKER = compactMarker(\"breadcrumb\");\n\n/** YAML 프로퍼티 테이블 보존 태그 (yaml 코드블록 내 주석): `# im-nobsidian:properties`. */\nexport const PROPERTIES_TAG = `# ${MARKER_BRAND}:properties`;\n\n// ─── 정규식 헬퍼 ───\n\n/**\n * 정규식 패턴에 직접 삽입할 수 있는 브랜드 토큰.\n * 브랜드에 정규식 특수문자가 없어(하이픈은 문자클래스 밖에서 리터럴) 이스케이프 없이 사용 가능.\n * 사용 예: `new RegExp(`%% ${MARKER_BRAND_RE}:end %%`, \"g\")`\n */\nexport const MARKER_BRAND_RE = MARKER_BRAND;\n","import type {\n ConversionContext,\n ConversionPath,\n ConversionResult,\n Processor,\n ProcessorInput,\n ProcessorMetadata,\n} from \"../types/convert.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { MARKER_BRAND_RE } from \"../constants/markers.js\";\n\nconst INLINE_DB_PROBE = new RegExp(`%% ${MARKER_BRAND_RE}:inline-db`);\nconst TOGGLE_HEADING_PROBE = new RegExp(`%% ${MARKER_BRAND_RE}:toggle-heading`);\n\nexport class ConversionPipeline {\n private readonly preProcessors: Processor[] = [];\n private readonly postProcessors: Processor[] = [];\n\n registerPreProcessor(processor: Processor): void {\n this.preProcessors.push(processor);\n this.preProcessors.sort((a, b) => a.order - b.order);\n }\n\n registerPostProcessor(processor: Processor): void {\n this.postProcessors.push(processor);\n this.postProcessors.sort((a, b) => a.order - b.order);\n }\n\n selectPath(content: string): ConversionPath {\n const hasInlineDb = INLINE_DB_PROBE.test(content);\n const hasColumnLayout = />\\s*\\[!col\\]/.test(content);\n const hasToggleHeading = TOGGLE_HEADING_PROBE.test(content);\n\n if (hasInlineDb || hasColumnLayout || hasToggleHeading) {\n return \"block-api\";\n }\n\n return \"markdown-api\";\n }\n\n convertToNotion(markdown: string, context: ConversionContext): ConversionResult {\n let input: ProcessorInput = {\n content: markdown,\n metadata: {},\n context,\n };\n\n for (const processor of this.preProcessors) {\n try {\n const output = processor.process(input);\n input = {\n content: output.content,\n metadata: output.metadata,\n context,\n };\n } catch (error) {\n getLogger().warn(`[${processor.name}] Pre-processor failed:`, error);\n }\n }\n\n return {\n content: input.content,\n properties: (input.metadata.properties as Record<string, unknown>) ?? {},\n images: input.metadata.images ?? [],\n preserveMarkers: input.metadata.preserveMarkers ?? [],\n };\n }\n\n convertToMarkdown(\n content: string,\n context: ConversionContext,\n metadata?: ProcessorMetadata,\n ): string {\n let input: ProcessorInput = {\n content,\n metadata: metadata ?? {},\n context,\n };\n\n for (const processor of this.postProcessors) {\n try {\n const output = processor.process(input);\n input = {\n content: output.content,\n metadata: output.metadata,\n context,\n };\n } catch (error) {\n getLogger().warn(`[${processor.name}] Post-processor failed:`, error);\n }\n }\n\n return input.content;\n }\n}\n","import matter from \"gray-matter\";\nimport type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\n\nexport class FrontmatterExtractor implements Processor {\n readonly name = \"FrontmatterExtractor\";\n readonly order = 10;\n\n process(input: ProcessorInput): ProcessorOutput {\n const { data, content } = matter(input.content);\n\n return {\n content: content.trim(),\n metadata: {\n ...input.metadata,\n properties: data,\n },\n };\n }\n}\n","/**\n * 펜스 코드블록(``` / ~~~) 바깥 영역에만 변환 함수를 적용한다.\n *\n * 주석 제거·각주 이스케이프·이스케이프 정규화 같은 텍스트 치환이 코드블록\n * 내부 리터럴을 오염시키지 않도록 하는 공용 가드. 인라인 코드(백틱 1개)는\n * 세그먼트 경계 판정 비용 대비 실익이 작아 다루지 않는다.\n */\n/**\n * 마커 재삽입용 앵커 — idx 직전의 같은 줄 접두(최대 32자)를, 줄 첫머리면 직전\n * 비어있지 않은 줄(최대 48자)을 돌려준다. push 시점 절대 offset 은 pull 산출물에서\n * 무의미하므로, 텍스트 앵커가 위치 복원의 1차 수단이 된다.\n */\nexport function computeAnchor(content: string, idx: number): string {\n const before = content.slice(Math.max(0, idx - 32), idx);\n const sameLine = before.split(\"\\n\").pop() ?? \"\";\n if (sameLine.trim().length >= 4) return sameLine;\n const prevLines = content.slice(0, idx).split(\"\\n\");\n for (let i = prevLines.length - 2; i >= 0; i--) {\n const line = prevLines[i]!.trim();\n if (line.length > 0) return line.slice(0, 48);\n }\n return \"\";\n}\n\nexport function mapOutsideCodeFences(content: string, fn: (segment: string) => string): string {\n const lines = content.split(\"\\n\");\n const out: string[] = [];\n let buffer: string[] = [];\n let fence: string | null = null;\n\n const flush = () => {\n if (buffer.length > 0) {\n out.push(fn(buffer.join(\"\\n\")));\n buffer = [];\n }\n };\n\n for (const line of lines) {\n const fenceMatch = line.match(/^\\s*(```+|~~~+)/);\n if (fence === null && fenceMatch) {\n flush();\n fence = fenceMatch[1]![0]!.repeat(3);\n out.push(line);\n continue;\n }\n if (fence !== null) {\n out.push(line);\n if (fenceMatch && fenceMatch[1]!.startsWith(fence)) {\n fence = null;\n }\n continue;\n }\n buffer.push(line);\n }\n flush();\n return out.join(\"\\n\");\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n WikilinkEntry,\n PreserveMarker,\n} from \"../../types/convert.js\";\nimport { WIKILINK_PROTOCOL } from \"../../constants/markers.js\";\nimport { computeAnchor } from \"../../utils/md-regions.js\";\n\nconst WIKILINK_REGEX = /(?<!!)\\[\\[([^\\]|]+)(?:\\|([^\\]]+))?\\]\\]/g;\n\nexport type WikilinkResolverFn = (text: string) => WikilinkEntry | null;\n\nexport class WikilinkResolver implements Processor {\n readonly name = \"WikilinkResolver\";\n readonly order = 20;\n\n constructor(private readonly resolve?: WikilinkResolverFn) {}\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const preserveMarkers: PreserveMarker[] = input.metadata.preserveMarkers\n ? [...input.metadata.preserveMarkers]\n : [];\n\n const resolved = input.content.replace(\n WIKILINK_REGEX,\n (_match: string, target: string, display: string | undefined, offset: number) => {\n const label = display ?? target;\n\n if (this.resolve) {\n const entry = this.resolve(target);\n if (entry) {\n return `<mention-page id=\"${entry.notionPageId}\">${label}</mention-page>`;\n }\n }\n\n // F28 교훈: startIndex 0 하드코딩은 pull 재삽입 시 프론트매터 앞 오염을\n // 낳았다. 실제 오프셋 + 텍스트 앵커를 남겨 위치 복원이 가능하게 한다.\n const params: Record<string, string> = display\n ? { text: target, display }\n : { text: target };\n params.__anchor = computeAnchor(input.content, offset);\n preserveMarkers.push({\n type: \"wikilink\",\n params,\n startIndex: offset,\n });\n\n const encodedTarget = encodeURIComponent(target);\n return `[${label}](${WIKILINK_PROTOCOL}${encodedTarget})`;\n },\n );\n\n return {\n content: resolved,\n metadata: { ...input.metadata, preserveMarkers },\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { spacedMarker } from \"../../constants/markers.js\";\n\nconst CALLOUT_REGEX = /^> \\[!(\\w+)\\]([+-])?\\s*(.*)?$/gm;\n\nconst CALLOUT_EMOJI_MAP: Record<string, string> = {\n note: \"\\u{1F4DD}\",\n abstract: \"\\u{1F4CB}\",\n summary: \"\\u{1F4CB}\",\n info: \"\\u{2139}\\u{FE0F}\",\n tip: \"\\u{1F4A1}\",\n hint: \"\\u{1F4A1}\",\n success: \"\\u{2705}\",\n check: \"\\u{2705}\",\n question: \"\\u{2753}\",\n faq: \"\\u{2753}\",\n warning: \"\\u{26A0}\\u{FE0F}\",\n caution: \"\\u{26A0}\\u{FE0F}\",\n failure: \"\\u{274C}\",\n fail: \"\\u{274C}\",\n danger: \"\\u{1F525}\",\n error: \"\\u{1F525}\",\n bug: \"\\u{1F41B}\",\n example: \"\\u{1F4CC}\",\n quote: \"\\u{1F4AC}\",\n cite: \"\\u{1F4AC}\",\n};\n\nexport class CalloutTransformer implements Processor {\n readonly name = \"CalloutTransformer\";\n readonly order = 30;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.path === \"markdown-api\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content.replace(\n CALLOUT_REGEX,\n (_match, type: string, foldable: string | undefined, title: string | undefined) => {\n const emoji = CALLOUT_EMOJI_MAP[type.toLowerCase()] ?? \"\\u{1F4DD}\";\n const titleText = title?.trim() || type;\n const foldMeta = foldable\n ? `\\n${spacedMarker(`callout:type=${type}&foldable=${foldable === \"+\" ? \"open\" : \"closed\"}`)}`\n : `\\n${spacedMarker(`callout:type=${type}`)}`;\n\n return `> ${emoji} **${titleText}**${foldMeta}`;\n },\n );\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\n\nconst BLOCK_MATH_REGEX = /\\$\\$([\\s\\S]+?)\\$\\$/g;\nconst INLINE_MATH_REGEX = /(?<![\\\\$])\\$([^\\n$]+?)\\$(?!\\$)/g;\n\nexport class MathNormalizer implements Processor {\n readonly name = \"MathNormalizer\";\n readonly order = 50;\n\n process(input: ProcessorInput): ProcessorOutput {\n let content = input.content;\n\n content = content.replace(BLOCK_MATH_REGEX, (_match, equation: string) => {\n return `$$\\n${equation.trim()}\\n$$`;\n });\n\n content = content.replace(INLINE_MATH_REGEX, (_match, equation: string) => {\n return `$${equation.trim()}$`;\n });\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport type { ImageReference } from \"../../types/convert.js\";\nimport { EMBED_PROTOCOL, spacedMarker } from \"../../constants/markers.js\";\n\nconst OBSIDIAN_EMBED_REGEX = /!\\[\\[([^\\]]+)\\]\\]/g;\nconst MARKDOWN_IMAGE_REGEX = /!\\[([^\\]]*)\\]\\(([^)]+)\\)/g;\n\nconst VIDEO_HOSTS = [\"youtube.com\", \"youtu.be\", \"vimeo.com\"];\n\nexport class EmbedResolver implements Processor {\n readonly name = \"EmbedResolver\";\n readonly order = 60;\n\n process(input: ProcessorInput): ProcessorOutput {\n const images: ImageReference[] = input.metadata.images ? [...input.metadata.images] : [];\n const isPush = input.context.direction === \"push\";\n\n let content = input.content.replace(OBSIDIAN_EMBED_REGEX, (_match, target: string) => {\n if (isImageFile(target)) {\n images.push({ url: target, localPath: target, isExternal: false });\n if (isPush && !isExternalUrl(target)) {\n const fileName = target.split(\"/\").pop() ?? target;\n return `> 📎 ${fileName}\\n> ${spacedMarker(`local-image:${target}`)}`;\n }\n return `![${target}](${encodeURI(target)})`;\n }\n // 비이미지 로컬 첨부 파일(pdf/mov 등): EMBED_PROTOCOL href 는 Notion 이 스킴을\n // 버려 평문으로 강등된다 — 이미지와 동일한 quote+마커 쌍으로 왕복을 보존한다(D5).\n // 노트 임베드(확장자 없음·.md·.canvas)는 위키링크/멘션 계열이므로 기존 경로 유지.\n if (isPush && !isExternalUrl(target) && isAttachmentFile(target)) {\n const fileName = target.split(\"/\").pop() ?? target;\n return `> 📎 ${fileName}\\n> ${spacedMarker(`local-file:${target}`)}`;\n }\n const encoded = encodeURIComponent(target);\n return `[${target}](${EMBED_PROTOCOL}${encoded})`;\n });\n\n content = content.replace(MARKDOWN_IMAGE_REGEX, (_match, alt: string, url: string) => {\n if (isVideoUrl(url)) {\n return `${spacedMarker(`embed:type=video&url=${encodeURIComponent(url)}`)}\\n[${alt || \"Video\"}](${url})`;\n }\n if (isExternalUrl(url)) {\n images.push({ url, isExternal: true });\n }\n return `![${alt}](${url})`;\n });\n\n return {\n content,\n metadata: { ...input.metadata, images },\n };\n }\n}\n\nfunction isImageFile(path: string): boolean {\n return /\\.(png|jpg|jpeg|gif|svg|webp|bmp|ico)$/i.test(path);\n}\n\n/** 노트(.md/.canvas)·확장자 없는 위키 대상이 아닌, 실물 첨부 파일 임베드인지(D5). */\nfunction isAttachmentFile(target: string): boolean {\n const path = target.split(\"|\")[0]!;\n const ext = /\\.([a-z0-9]+)$/i.exec(path)?.[1]?.toLowerCase();\n return ext !== undefined && ext !== \"md\" && ext !== \"canvas\";\n}\n\nfunction isVideoUrl(url: string): boolean {\n return VIDEO_HOSTS.some((host) => url.includes(host));\n}\n\nfunction isExternalUrl(url: string): boolean {\n return url.startsWith(\"http://\") || url.startsWith(\"https://\");\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport type { PreserveMarker } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\nimport { computeAnchor } from \"../../utils/md-regions.js\";\n\nconst MARKER_REGEX = new RegExp(`%% ${MARKER_BRAND_RE}:(\\\\w[\\\\w-]*):([^\\\\s]+?) %%`, \"g\");\n\nexport class PreserveMarkerCollector implements Processor {\n readonly name = \"PreserveMarkerCollector\";\n readonly order = 70;\n\n process(input: ProcessorInput): ProcessorOutput {\n const markers: PreserveMarker[] = input.metadata.preserveMarkers\n ? [...input.metadata.preserveMarkers]\n : [];\n\n const matches = [...input.content.matchAll(MARKER_REGEX)];\n for (const match of matches) {\n markers.push({\n type: match[1]!,\n params: parseMarkerParams(match[2]!, input.content, match.index!),\n startIndex: match.index!,\n });\n }\n\n return {\n content: input.content,\n metadata: { ...input.metadata, preserveMarkers: markers },\n };\n }\n}\n\n/**\n * 파라미터 파싱. `k=v&k2=v2` 형식이 아닌 원시 페이로드(`local-image:경로` 류)는\n * `__raw` 로 원문 보존한다 — 과거엔 빈 객체로 저장돼 재삽입 시\n * `%% brand:local-image: %%` 껍데기 마커가 생성됐다(F29).\n * `__anchor` 는 push 시점 오프셋이 무의미해진 pull 산출물에서의 위치 복원 수단.\n */\nfunction parseMarkerParams(\n paramString: string,\n content: string,\n index: number,\n): Record<string, string> {\n const params: Record<string, string> = {};\n if (paramString.includes(\"=\")) {\n for (const pair of paramString.split(\"&\")) {\n const eqIdx = pair.indexOf(\"=\");\n if (eqIdx > 0) {\n params[pair.slice(0, eqIdx)] = decodeURIComponent(pair.slice(eqIdx + 1));\n }\n }\n } else {\n params.__raw = paramString;\n }\n params.__anchor = computeAnchor(content, index);\n return params;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\n\nconst UNSUPPORTED_CALLOUT_REGEX = /> \\[!im-nobsidian-unsupported\\][^\\n]*\\n(?:>[^\\n]*\\n)*/g;\n\nexport class UnsupportedBlockStripper implements Processor {\n readonly name = \"UnsupportedBlockStripper\";\n readonly order = 5;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content.replace(UNSUPPORTED_CALLOUT_REGEX, \"\");\n\n return {\n content: content.replace(/\\n{3,}/g, \"\\n\\n\"),\n metadata: input.metadata,\n };\n }\n}\n","import matter from \"gray-matter\";\n\n/**\n * gray-matter 의 `matter.stringify(file, data)` 는 `file` 이 **문자열**이면 내부에서\n * `matter(file)` 로 본문을 먼저 파싱한다. 본문이 `---` 로 시작하면(Notion divider,\n * 수평선, `---` 로 여는 구획 등) 그 `---…---` 블록을 frontmatter 로 오인해 YAML 로\n * 파싱하다 throw 하고, 결과적으로 frontmatter 생성이 통째로 스킵되어 **속성이 유실**된다.\n *\n * 객체 형태(`{ content }`)로 넘기면 이 재파싱을 건너뛰므로 본문이 무엇으로 시작하든\n * 안전하다. 모든 frontmatter 직렬화는 반드시 이 함수를 거쳐 footgun 을 한 곳에 봉인한다.\n */\nexport function stringifyFrontmatter(content: string, data: Record<string, unknown>): string {\n const out = matter.stringify(\n { content } as unknown as Parameters<typeof matter.stringify>[0],\n data,\n );\n return unquoteFrontmatterDates(out);\n}\n\nconst QUOTED_DATE_LINE_RE = /^([ \\t]*[^:\\n]+:[ \\t]*)'(\\d{4}-\\d{2}-\\d{2})'([ \\t]*)$/gm;\n\n/**\n * js-yaml 은 `2026-07-14` 평문이 YAML timestamp 로 재해석되는 것을 막으려 작은따옴표로\n * 감싸지만, Obsidian 저작 관행(그리고 Obsidian 의 해석)은 따옴표 없는 날짜다 — 왕복 시\n * `created: 2026-07-14` 가 `created: '2026-07-14'` 로 변해 가짜 diff 를 만든다(D3).\n * 의미가 동일하므로 프론트매터 영역에 한해 원 표기로 되돌린다.\n */\nfunction unquoteFrontmatterDates(out: string): string {\n if (!out.startsWith(\"---\\n\")) return out;\n const close = out.indexOf(\"\\n---\\n\", 3);\n if (close === -1) return out;\n const fmEnd = close + \"\\n---\\n\".length;\n const fm = out.slice(0, fmEnd).replace(QUOTED_DATE_LINE_RE, \"$1$2$3\");\n return fm + out.slice(fmEnd);\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { PROPERTIES_TAG } from \"../../constants/markers.js\";\nimport { stringifyFrontmatter } from \"../../utils/frontmatter.js\";\n\nexport class PropertiesTableInjector implements Processor {\n readonly name = \"PropertiesTableInjector\";\n readonly order = 15;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n if (input.context.parentMode === \"database\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const properties = input.metadata.properties as Record<string, unknown> | undefined;\n if (!properties || Object.keys(properties).length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n const filteredProps: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(properties)) {\n filteredProps[key] = value;\n }\n\n if (Object.keys(filteredProps).length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n const yamlStr = stringifyFrontmatter(\"\", filteredProps).trim();\n const yamlBody = yamlStr.slice(4, -3).trim();\n const codeBlock = \"```yaml\\n\" + PROPERTIES_TAG + \"\\n\" + yamlBody + \"\\n```\";\n\n const content = codeBlock + \"\\n\\n---\\n\\n\" + input.content;\n\n return { content, metadata: input.metadata };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE, compactMarker } from \"../../constants/markers.js\";\nimport { mapOutsideCodeFences } from \"../../utils/md-regions.js\";\n\n/** `<u>밑줄</u>` (Obsidian·HTML 관용) — push 시 underline 마커로 승격. */\nconst UNDERLINE_REGEX = /<u>([\\s\\S]*?)<\\/u>/g;\n\n/** `==하이라이트==` — 같은 줄 내, `===`(3연속)와 구분. */\nconst HIGHLIGHT_REGEX = /(?<!=)==([^=\\n]+?)==(?!=)/g;\n\n/**\n * 색상 span(`<span class=\"notion-red\">` / `notion-yellow-bg`) — pull(notion-to-md) 경로가 만든\n * 레거시 표현. 1번 그룹=베이스 색, 2번 그룹=배경(`-bg`) 여부.\n */\nconst COLOR_SPAN_REGEX = /<span class=\"notion-(\\w+)(-bg)?\">([\\s\\S]*?)<\\/span>/g;\n\n/** 공백형 색상 보존마커 `%% im-nobsidian:color:X %%...%% im-nobsidian:end %%` (block 경로 산출물). */\nconst SPACED_COLOR_REGEX = new RegExp(\n `%% ${MARKER_BRAND_RE}:color:(\\\\w+(?:_background)?) %%([\\\\s\\\\S]*?)%% ${MARKER_BRAND_RE}:end %%`,\n \"g\",\n);\n\n/**\n * 인라인 annotation(underline·color) 무손실 보존기 — push 전처리(order 5).\n *\n * 과거에는 underline/color 표기를 **제거**(strip)했으나, 그러면 Notion 으로 push 할 때\n * 서식이 영구 소실됐다(I3 손실점). Notion 의 Enhanced Markdown 은 underline/color 를\n * `<span underline=\"true\">` / `<span color=\"X\">` 로 **무손실 표현**하므로, 여기서는 제거 대신\n * 프로젝트 정본인 **compact 보존마커**(`%%im-nobsidian:underline%%…%%/underline%%`,\n * `%%im-nobsidian:color:C%%…%%/color%%`)로 **승격**만 한다. 실제 Notion span 복원은\n * push 직전 단일 SSOT 인 {@link obsidianToNotionEnhanced} 가 담당한다.\n *\n * 입력 표기는 pull 경로별로 다르다.\n * - Markdown API 경로: 이미 compact 마커 → 무변경 통과(여기 정규식에 걸리지 않음).\n * - notion-to-md(block) 경로: `<u>` + 공백형 색상 마커 → compact 마커로 정규화.\n * - 사용자가 직접 작성한 `<u>` / 레거시 `<span class=\"notion-*\">` → compact 마커로 승격.\n *\n * compact 마커는 공백이 없어 PreserveMarkerCollector(공백형만 수집)·기타 전처리기를\n * 무손상 통과한다(기존 underline/color 왕복이 이를 실증).\n */\nexport class InlineAnnotationPreserver implements Processor {\n readonly name = \"InlineAnnotationPreserver\";\n readonly order = 5;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n let content = input.content;\n\n // 공백형 색상 마커 → compact 색상 마커 (색상값은 그대로 보존)\n content = content.replace(\n SPACED_COLOR_REGEX,\n (_m, color: string, text: string) => `${compactMarker(`color:${color}`)}${text}%%/color%%`,\n );\n\n // <u>…</u> → underline 마커\n content = content.replace(\n UNDERLINE_REGEX,\n (_m, text: string) => `${compactMarker(\"underline\")}${text}%%/underline%%`,\n );\n\n // <span class=\"notion-X[-bg]\"> → compact 색상 마커 (-bg → _background)\n content = content.replace(\n COLOR_SPAN_REGEX,\n (_m, base: string, bg: string | undefined, text: string) => {\n const color = bg ? `${base}_background` : base;\n return `${compactMarker(`color:${color}`)}${text}%%/color%%`;\n },\n );\n\n // ==하이라이트== → 노랑 배경 (F24). Obsidian 하이라이트의 유일한 자연 대응이\n // Notion yellow 배경이다. 색상명은 pull 경로(Notion md export)가 쓰는\n // `yellow_bg` 로 맞춰 HighlightRestorer 와 왕복 대칭을 이룬다.\n content = mapOutsideCodeFences(content, (segment) =>\n segment.replace(\n HIGHLIGHT_REGEX,\n (_m, text: string) => `${compactMarker(\"color:yellow_bg\")}${text}%%/color%%`,\n ),\n );\n\n return { content, metadata: input.metadata };\n }\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n PreserveMarker,\n} from \"../../types/convert.js\";\nimport { MARKER_BRAND } from \"../../constants/markers.js\";\nimport { mapOutsideCodeFences, computeAnchor } from \"../../utils/md-regions.js\";\n\nconst COMMENT_REGEX = /%%([\\s\\S]*?)%%/g;\n\n/**\n * Obsidian 주석(`%%...%%`)은 로컬 전용 표기다 — Notion 에 평문으로 노출되면\n * 사적 메모가 유출된다(F26). push 시 본문에서 제거하되, preserve marker(DB)로\n * 남겨 pull 재작성 시 앵커 위치에 복원한다.\n *\n * im-nobsidian 브랜드 마커(`%%im-nobsidian:...%%`·`%% im-nobsidian:... %%`)와\n * 닫는 토큰(`%%/color%%` 류)은 동기화 자체의 운반체이므로 건드리지 않는다.\n */\nexport class CommentStripper implements Processor {\n readonly name = \"CommentStripper\";\n // FrontmatterExtractor(10) 뒤 — YAML 값 속 `%%` 를 본문 주석으로 오인하지 않는다.\n readonly order = 11;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const markers: PreserveMarker[] = input.metadata.preserveMarkers\n ? [...input.metadata.preserveMarkers]\n : [];\n\n const content = mapOutsideCodeFences(input.content, (segment) =>\n segment.replace(COMMENT_REGEX, (match, body: string, offset: number) => {\n const trimmed = body.trimStart();\n if (trimmed.startsWith(`${MARKER_BRAND}:`) || trimmed.startsWith(\"/\")) {\n return match;\n }\n markers.push({\n type: \"comment\",\n params: { text: body, __anchor: computeAnchor(segment, offset) },\n startIndex: offset,\n });\n return \"\";\n }),\n );\n\n return {\n content,\n metadata: { ...input.metadata, preserveMarkers: markers },\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { mapOutsideCodeFences } from \"../../utils/md-regions.js\";\n\nconst FOOTNOTE_TOKEN_REGEX = /(?<!\\\\)\\[\\^([^\\]\\s]+)\\]/g;\n\n/**\n * 각주(`[^1]` 참조 + `[^1]: 내용` 정의)는 remark(각주 확장 없음)가 참조 링크로\n * 오파싱해 `[\\[1\\]](1)` 형태로 영구 파손된다(F25). push 전에 여는 대괄호를\n * 이스케이프(`\\[^1]`)해 링크 파싱을 차단한다 — Notion 에는 `[^1]` 평문으로\n * 보이고(가시적 degrade), pull 시 EscapeNormalizer 가 원형으로 복원해\n * 왕복은 무손실이다.\n */\nexport class FootnoteGuard implements Processor {\n readonly name = \"FootnoteGuard\";\n readonly order = 12;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = mapOutsideCodeFences(input.content, (segment) =>\n segment.replace(FOOTNOTE_TOKEN_REGEX, \"\\\\[^$1]\"),\n );\n\n return { content, metadata: input.metadata };\n }\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n PreserveMarker,\n} from \"../../types/convert.js\";\n\nconst DELIMITER_CELL_RE = /^:?-{1,}:?$/;\n\n/** 구분행 한 줄을 셀 배열로 파싱한다. 구분행이 아니면 null. */\nexport function parseDelimiterRow(line: string): string[] | null {\n const trimmed = line.trim();\n if (!trimmed.includes(\"-\") || !trimmed.includes(\"|\")) return null;\n const inner = trimmed.replace(/^\\|/, \"\").replace(/\\|$/, \"\");\n const cells = inner.split(\"|\").map((c) => c.trim());\n if (cells.length === 0) return null;\n return cells.every((c) => DELIMITER_CELL_RE.test(c)) ? cells : null;\n}\n\nexport function cellAlignment(cell: string): \"left\" | \"center\" | \"right\" | \"none\" {\n const l = cell.startsWith(\":\");\n const r = cell.endsWith(\":\");\n if (l && r) return \"center\";\n if (r) return \"right\";\n if (l) return \"left\";\n return \"none\";\n}\n\nexport function alignmentsToDelimiter(alignments: string[]): string {\n const cells = alignments.map((a) => {\n switch (a) {\n case \"center\":\n return \":---:\";\n case \"right\":\n return \"---:\";\n case \"left\":\n return \":---\";\n default:\n return \"---\";\n }\n });\n return `| ${cells.join(\" | \")} |`;\n}\n\n/**\n * GFM 표의 정렬 구분행(`| :--- | :---: | ---: |`)을 Notion markdown 임포터가\n * 구분행으로 인식하지 못해 **데이터 행으로 강등**시킨다(F30, 실측). push 전에\n * 콜론 없는 표준 구분행으로 정규화하고, 정렬 정보는 preserve marker 로 남겨\n * pull 시 TableAlignmentRestorer 가 원형을 복원한다.\n */\nexport class TableAlignmentGuard implements Processor {\n readonly name = \"TableAlignmentGuard\";\n readonly order = 45;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"push\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const markers: PreserveMarker[] = input.metadata.preserveMarkers\n ? [...input.metadata.preserveMarkers]\n : [];\n\n const lines = input.content.split(\"\\n\");\n let changed = false;\n\n for (let i = 1; i < lines.length; i++) {\n const cells = parseDelimiterRow(lines[i]!);\n if (!cells || !lines[i]!.includes(\":\")) continue;\n const prev = lines[i - 1]!;\n if (!prev.includes(\"|\")) continue;\n\n markers.push({\n type: \"table-align\",\n params: {\n align: cells.map(cellAlignment).join(\",\"),\n __anchor: prev.trim().slice(0, 64),\n // 원본 구분행 원문. 복원 시 정렬뿐 아니라 셀 폭 패딩까지 그대로 되살려\n // 라운드트립 delta-0 을 만족시킨다(__ 접두라 마커 렌더링에서 제외).\n __line: lines[i]!,\n },\n startIndex: 0,\n });\n lines[i] = alignmentsToDelimiter(cells.map(() => \"none\"));\n changed = true;\n }\n\n return {\n content: changed ? lines.join(\"\\n\") : input.content,\n metadata: { ...input.metadata, preserveMarkers: markers },\n };\n }\n}\n","import { WIKILINK_PROTOCOL, EMBED_PROTOCOL } from \"../constants/markers.js\";\n\n/**\n * Pull 시 Notion 측 링크 표현을 Obsidian 위키링크/임베드로 복원하는 공유 로직.\n *\n * 본문(MentionToWikilink)과 프론트매터 속성 값(FrontmatterGenerator) 양쪽이\n * 동일한 규칙을 써야 하므로 한곳에서 정의한다. 마커가 없는 문자열에는 무영향(no-op).\n */\n\n/** Notion 페이지 링크 → `[[display]]`. */\nconst NOTION_LINK_REGEX =\n /\\[([^\\]]+)\\]\\((?:https:\\/\\/(?:www\\.)?notion\\.so\\/|notion:\\/\\/)([a-f0-9-]+)\\)/g;\n\n/** 위키링크 보존 마커 → `[[target]]` 또는 `[[target|display]]`. */\nconst WIKILINK_PRESERVE_REGEX = new RegExp(`\\\\[([^\\\\]]+)\\\\]\\\\(${WIKILINK_PROTOCOL}([^)]+)\\\\)`, \"g\");\n\n/** 임베드 보존 마커 → `![[target]]`. */\nconst EMBED_PRESERVE_REGEX = new RegExp(`\\\\[([^\\\\]]+)\\\\]\\\\(${EMBED_PROTOCOL}([^)]+)\\\\)`, \"g\");\n\n/** 문자열에서 링크 보존 마커를 위키링크/임베드로 복원한다. */\nexport function restoreLinkMarkers(text: string): string {\n let out = text.replace(NOTION_LINK_REGEX, (_match, display: string) => `[[${display}]]`);\n\n out = out.replace(WIKILINK_PRESERVE_REGEX, (_match, display: string, encodedTarget: string) => {\n const target = decodeURIComponent(encodedTarget);\n return target === display ? `[[${target}]]` : `[[${target}|${display}]]`;\n });\n\n out = out.replace(EMBED_PRESERVE_REGEX, (_match, _display: string, encodedTarget: string) => {\n const target = decodeURIComponent(encodedTarget);\n return `![[${target}]]`;\n });\n\n return out;\n}\n\n/**\n * 프론트매터 속성 값(문자열/배열) 안의 링크 보존 마커를 재귀적으로 복원한다.\n * 숫자·불리언·날짜 등 비문자열 값은 그대로 둔다.\n */\nexport function restoreLinkMarkersInValue(value: unknown): unknown {\n if (typeof value === \"string\") return restoreLinkMarkers(value);\n if (Array.isArray(value)) return value.map((v) => restoreLinkMarkersInValue(v));\n return value;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { restoreLinkMarkers } from \"../link-restore.js\";\n\nexport class MentionToWikilink implements Processor {\n readonly name = \"MentionToWikilink\";\n readonly order = 10;\n\n process(input: ProcessorInput): ProcessorOutput {\n return { content: restoreLinkMarkers(input.content), metadata: input.metadata };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { mapOutsideCodeFences } from \"../../utils/md-regions.js\";\n\n/**\n * Notion → md 산출물의 과잉 이스케이프를 정규화한다(F27·F30 계열).\n *\n * - `\\:` → `:` — 콜론은 마크다운에서 이스케이프가 불필요하고(CommonMark 상\n * `\\:` 는 `:` 와 동일 의미), 이 이스케이프가 보존 마커\n * (`%% im-nobsidian\\:local-image\\:... %%`)와 표 셀(`\\:---\\:`)을 깨뜨린다.\n * - `\\[^1\\]`/`\\[^` → `[^1]`/`[^` — FootnoteGuard 가 push 때 이스케이프한\n * 각주 토큰을 원형으로 되돌린다(F25 왕복 복원).\n *\n * 다른 복원기(LocalImageRestorer 등)의 정규식이 원형 마커를 전제하므로\n * 가장 먼저(order 3) 실행한다.\n */\nexport class EscapeNormalizer implements Processor {\n readonly name = \"EscapeNormalizer\";\n readonly order = 3;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = mapOutsideCodeFences(input.content, (segment) =>\n segment\n .replace(/\\\\\\[\\^([^\\]\\\\\\n]+)\\\\\\]/g, \"[^$1]\")\n .replace(/\\\\\\[\\^/g, \"[^\")\n .replace(/\\\\:/g, \":\"),\n );\n\n return { content, metadata: input.metadata };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\n/** compact 노랑배경 마커 — pull 경로(Notion md export)는 `yellow_bg` 를 쓴다. */\nconst COMPACT_YELLOW_RE = new RegExp(\n `%%${MARKER_BRAND_RE}:color:yellow(?:_background|_bg)%%([^\\\\n]*?)%%\\\\/color%%`,\n \"g\",\n);\n\n/** 공백형 노랑배경 마커 (block 경로 산출물). */\nconst SPACED_YELLOW_RE = new RegExp(\n `%% ${MARKER_BRAND_RE}:color:yellow(?:_background|_bg) %%([^\\\\n]*?)%% ${MARKER_BRAND_RE}:end %%`,\n \"g\",\n);\n\n/**\n * Notion 노랑 배경(yellow_bg)을 Obsidian 하이라이트 `==...==` 로 복원한다(F24).\n * push 쪽 대응(InlineAnnotationPreserver 의 `==` 승격)과 쌍을 이뤄\n * `==x==` ↔ yellow_bg 왕복을 무손실로 만든다. 여러 줄에 걸친 색상은\n * `==` 문법이 표현하지 못하므로 마커 형태를 유지한다(줄 단위만 매칭).\n */\nexport class HighlightRestorer implements Processor {\n readonly name = \"HighlightRestorer\";\n readonly order = 25;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content\n .replace(COMPACT_YELLOW_RE, (_m, text: string) => (text ? `==${text}==` : \"\"))\n .replace(SPACED_YELLOW_RE, (_m, text: string) => (text ? `==${text}==` : \"\"));\n\n return { content, metadata: input.metadata };\n }\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n PreserveMarker,\n} from \"../../types/convert.js\";\nimport {\n parseDelimiterRow,\n cellAlignment,\n alignmentsToDelimiter,\n} from \"../pre-processors/table-alignment.js\";\n\n/**\n * 표 정렬 왕복 복원(F30)의 pull 쪽 절반.\n *\n * 1) 팬텀 행 치유 — TableAlignmentGuard 이전에 push 된 페이지는 Notion 표에\n * 정렬행이 데이터 행으로 박혀 있다. 표준 구분행 바로 아래에 콜론 정렬\n * 패턴 행이 오면 구분행에 병합하고 데이터 행을 제거한다.\n * 2) 마커 복원 — Guard 가 남긴 table-align 마커의 앵커(헤더 행)를 찾아\n * 표준 구분행을 원래 정렬 구분행으로 되돌린다. 소비한 마커는 metadata 에서\n * 제거해 PreserveMarkerInjector 의 재삽입 대상에서 뺀다.\n */\nexport class TableAlignmentRestorer implements Processor {\n readonly name = \"TableAlignmentRestorer\";\n readonly order = 35;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const lines = input.content.split(\"\\n\");\n\n // 1) 팬텀 정렬행 치유\n for (let i = 1; i < lines.length - 1; i++) {\n const delim = parseDelimiterRow(lines[i]!);\n if (!delim || lines[i]!.includes(\":\")) continue;\n const phantom = parseDelimiterRow(lines[i + 1]!);\n if (!phantom || !lines[i + 1]!.includes(\":\") || phantom.length !== delim.length) continue;\n if (!lines[i - 1]!.includes(\"|\")) continue;\n lines[i] = alignmentsToDelimiter(phantom.map(cellAlignment));\n lines.splice(i + 1, 1);\n }\n\n // 2) table-align 마커 복원 (+소비)\n const markers = input.metadata.preserveMarkers ?? [];\n const remaining: PreserveMarker[] = [];\n for (const marker of markers) {\n if (marker.type !== \"table-align\" || !marker.params.align || !marker.params.__anchor) {\n remaining.push(marker);\n continue;\n }\n const anchor = marker.params.__anchor;\n const idx = lines.findIndex(\n (line, i) =>\n i < lines.length - 1 &&\n line.trim().startsWith(anchor) &&\n parseDelimiterRow(lines[i + 1]!) !== null,\n );\n if (idx === -1) continue; // 앵커 유실 — 정렬만 소실시키고 마커는 폐기(재삽입 노이즈 방지)\n const delimCells = parseDelimiterRow(lines[idx + 1]!)!;\n if (lines[idx + 1]!.includes(\":\")) continue; // 이미 정렬 구분행(팬텀 치유 경로가 처리)\n // 원본 구분행 원문(__line)이 있고 셀 수가 일치하면 그대로 복원(폭 패딩까지 delta-0).\n // 없거나 표 구조가 달라졌으면 정렬 정보만으로 표준형을 합성한다.\n const originalLine = marker.params.__line;\n if (originalLine && parseDelimiterRow(originalLine)?.length === delimCells.length) {\n lines[idx + 1] = originalLine;\n continue;\n }\n const alignments = marker.params.align.split(\",\");\n while (alignments.length < delimCells.length) alignments.push(\"none\");\n lines[idx + 1] = alignmentsToDelimiter(alignments.slice(0, delimCells.length));\n }\n\n return {\n content: lines.join(\"\\n\"),\n metadata: { ...input.metadata, preserveMarkers: remaining },\n };\n }\n}\n","import type {\n Processor,\n ProcessorInput,\n ProcessorOutput,\n PreserveMarker,\n} from \"../../types/convert.js\";\nimport { spacedMarker } from \"../../constants/markers.js\";\n\n/**\n * 다른 복원기가 소비하지 못하고 실제로 유실된 보존 마커를 재삽입하는 최후 보루.\n *\n * 핵심 전제(F28 교훈): DB 에 저장된 startIndex 는 **push 시점 문자열**의 절대\n * 오프셋이라 pull 산출물에서는 무의미하다 — 프론트매터 앞·단어 한가운데에\n * 마커를 박아 파일을 파손시켰다. 재삽입은 반드시\n * 1) 이미 의미적으로 복원된 마커는 건너뛰고(위키링크 → `[[...]]` 존재 등),\n * 2) 텍스트 앵커(__anchor)를 1차 위치 수단으로 쓰며,\n * 3) 프론트매터 뒤·줄 경계에만, 마커 단독 줄로 삽입한다.\n *\n * 이중 모드: `__anchor` 키가 없는 마커는 구버전 DB blob(수집기가 앵커를 안 남기던\n * 시절)이다. 이들은 구계약 — \"변환이 마커만 제거했다면 startIndex 오프셋 원문 삽입이\n * 원본을 정확히 재구성한다\" — 을 유지하되 프론트매터 앞 삽입만 금지한다. 위해한\n * 레거시 사례(빈 params 껍데기, 이미 복원된 위키링크)는 render-null 폐기와 의미\n * 복원 검사가 이미 걸러낸다.\n */\nexport class PreserveMarkerInjector implements Processor {\n readonly name = \"PreserveMarkerInjector\";\n readonly order = 100;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const markers = input.metadata.preserveMarkers;\n if (!markers || markers.length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n let content = input.content;\n\n const missing = markers.filter((m) => {\n const rendered = this.renderMarker(m);\n if (rendered === null) return false;\n if (content.includes(rendered)) return false;\n return !this.isSemanticallyRestored(m, content);\n });\n\n if (missing.length === 0) {\n return { content, metadata: input.metadata };\n }\n\n const sorted = [...missing].sort((a, b) => a.startIndex - b.startIndex);\n for (const marker of sorted) {\n const rendered = this.renderMarker(marker)!;\n\n if (marker.params?.__anchor === undefined) {\n // 레거시 마커: startIndex 오프셋에 원문 그대로 삽입(구계약). 프론트매터 앞만 금지.\n const at = Math.max(frontmatterEnd(content), Math.min(marker.startIndex, content.length));\n content = content.slice(0, at) + rendered + content.slice(at);\n continue;\n }\n\n const at = this.findInsertionPoint(marker, content);\n const before = content.slice(0, at);\n const needsNewline = before.length > 0 && !before.endsWith(\"\\n\");\n content = before + (needsNewline ? \"\\n\" : \"\") + rendered + \"\\n\" + content.slice(at);\n }\n\n return { content, metadata: input.metadata };\n }\n\n /** 마커의 본문 표현. 복원 불가능한(빈) 마커는 null — 삽입하지 않고 폐기한다. */\n private renderMarker(marker: PreserveMarker): string | null {\n const params = marker.params ?? {};\n\n if (marker.type === \"comment\") {\n return params.text ? `%%${params.text}%%` : null;\n }\n\n if (params.__raw !== undefined) {\n return spacedMarker(`${marker.type}:${params.__raw}`);\n }\n\n const entries = Object.entries(params).filter(([key]) => !key.startsWith(\"__\"));\n if (entries.length === 0) return null;\n const body = entries.map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join(\"&\");\n return spacedMarker(`${marker.type}:${body}`);\n }\n\n /** 마커가 이미 원래 문법으로 복원돼 있으면 재삽입은 중복·오염이다. */\n private isSemanticallyRestored(marker: PreserveMarker, content: string): boolean {\n const params = marker.params ?? {};\n switch (marker.type) {\n case \"wikilink\": {\n const text = params.text;\n if (!text) return false;\n return content.includes(`[[${text}]]`) || content.includes(`[[${text}|`);\n }\n case \"local-image\":\n case \"local-file\": {\n const target = params.__raw ?? params.path;\n return target ? content.includes(`![[${target}]]`) : false;\n }\n case \"table-align\":\n // 전용 복원기(TableAlignmentRestorer)가 소비/폐기한다 — 본문 재삽입은 노이즈.\n return true;\n default:\n return false;\n }\n }\n\n /** 삽입 위치: 앵커 → startIndex(줄 경계 보정) 순. 항상 프론트매터 뒤. */\n private findInsertionPoint(marker: PreserveMarker, content: string): number {\n const fmEnd = frontmatterEnd(content);\n const anchor = marker.params?.__anchor;\n\n if (anchor && anchor.trim().length >= 4) {\n const idx = content.indexOf(anchor, fmEnd);\n if (idx !== -1) {\n return nextLineStart(content, idx + anchor.length);\n }\n }\n\n const clamped = Math.max(fmEnd, Math.min(marker.startIndex, content.length));\n return nextLineStart(content, clamped);\n }\n}\n\n/** 선두 YAML 프론트매터 블록의 끝(다음 본문 시작) 오프셋. 없으면 0. */\nfunction frontmatterEnd(content: string): number {\n if (!content.startsWith(\"---\\n\")) return 0;\n const close = content.indexOf(\"\\n---\", 3);\n if (close === -1) return 0;\n const lineEnd = content.indexOf(\"\\n\", close + 4);\n return lineEnd === -1 ? content.length : lineEnd + 1;\n}\n\n/** pos 가 속한 줄의 다음 줄 시작 오프셋(마지막 줄이면 문서 끝). */\nfunction nextLineStart(content: string, pos: number): number {\n const nl = content.indexOf(\"\\n\", pos);\n return nl === -1 ? content.length : nl + 1;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst EMOJI_TYPE_MAP: Record<string, string> = {\n \"\\u{1F4DD}\": \"note\",\n \"\\u{1F4CB}\": \"abstract\",\n \"\\u{2139}\\u{FE0F}\": \"info\",\n \"\\u{1F4A1}\": \"tip\",\n \"\\u{2705}\": \"success\",\n \"\\u{2753}\": \"question\",\n \"\\u{26A0}\\u{FE0F}\": \"warning\",\n \"\\u{274C}\": \"failure\",\n \"\\u{1F525}\": \"danger\",\n \"\\u{1F41B}\": \"bug\",\n \"\\u{1F4CC}\": \"example\",\n \"\\u{1F4AC}\": \"quote\",\n};\n\nconst CALLOUT_PRESERVE_REGEX = new RegExp(\n `%% ${MARKER_BRAND_RE}:callout:type=(\\\\w+)(?:&foldable=(open|closed))? %%`,\n \"g\",\n);\n\nexport class CalloutRestorer implements Processor {\n readonly name = \"CalloutRestorer\";\n readonly order = 20;\n\n process(input: ProcessorInput): ProcessorOutput {\n let content = input.content;\n\n content = content.replace(CALLOUT_PRESERVE_REGEX, (_match, type: string, foldable?: string) => {\n if (foldable) {\n const foldChar = foldable === \"open\" ? \"+\" : \"-\";\n return `[!${type}]${foldChar}`;\n }\n return `[!${type}]`;\n });\n\n for (const [emoji, type] of Object.entries(EMOJI_TYPE_MAP)) {\n const pattern = new RegExp(`> ${escapeRegex(emoji)} \\\\*\\\\*(.+?)\\\\*\\\\*`, \"g\");\n content = content.replace(pattern, (_match, title: string) => {\n if (title.toLowerCase() === type) {\n return `> [!${type}]`;\n }\n return `> [!${type}] ${title}`;\n });\n }\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst COLOR_MARKER_REGEX = new RegExp(\n `%% ${MARKER_BRAND_RE}:color:(\\\\w+(?:_background)?) %%([\\\\s\\\\S]*?)%% ${MARKER_BRAND_RE}:end %%`,\n \"g\",\n);\n\nexport class ColorAnnotator implements Processor {\n readonly name = \"ColorAnnotator\";\n readonly order = 30;\n\n process(input: ProcessorInput): ProcessorOutput {\n const content = input.content.replace(\n COLOR_MARKER_REGEX,\n (_match, color: string, text: string) => {\n const cssClass = color.endsWith(\"_background\")\n ? `notion-${color.replace(\"_background\", \"-bg\")}`\n : `notion-${color}`;\n return `<span class=\"${cssClass}\">${text}</span>`;\n },\n );\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { restoreLinkMarkersInValue } from \"../link-restore.js\";\nimport { stringifyFrontmatter } from \"../../utils/frontmatter.js\";\n\nexport class FrontmatterGenerator implements Processor {\n readonly name = \"FrontmatterGenerator\";\n readonly order = 90;\n\n process(input: ProcessorInput): ProcessorOutput {\n const properties = input.metadata.properties as Record<string, unknown> | undefined;\n\n if (!properties || Object.keys(properties).length === 0) {\n return { content: input.content, metadata: input.metadata };\n }\n\n // Pull 시 속성 값에 박힌 위키링크/임베드 보존 마커를 [[...]] 로 복원한다.\n const restoreMarkers = input.context.direction === \"pull\";\n const normalized = normalizeProperties(properties, restoreMarkers);\n const content = stringifyFrontmatter(input.content, normalized);\n\n return {\n content,\n metadata: input.metadata,\n };\n }\n}\n\nfunction normalizeProperties(\n props: Record<string, unknown>,\n restoreMarkers: boolean,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(props)) {\n const restored = restoreMarkers ? restoreLinkMarkersInValue(value) : value;\n const normalized = normalizeValue(restored);\n if (normalized !== undefined) {\n result[key] = normalized;\n }\n }\n\n return result;\n}\n\nfunction normalizeValue(value: unknown): unknown {\n if (value instanceof Date) {\n return normalizeDate(value.toISOString());\n }\n\n if (typeof value === \"string\") {\n return normalizeDate(value);\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) return undefined;\n return value;\n }\n\n if (typeof value === \"object\" && value !== null && \"start\" in value) {\n const dateObj = value as { start: string; end?: string | null };\n const normalized = {\n start: normalizeDate(dateObj.start),\n ...(dateObj.end ? { end: normalizeDate(dateObj.end) } : {}),\n };\n return normalized;\n }\n\n return value;\n}\n\nconst MIDNIGHT_RE = /T00:00:00(?:\\.\\d{3})?(?:Z|[+-]\\d{2}:\\d{2})/;\n\nfunction normalizeDate(dateStr: string): string {\n if (typeof dateStr !== \"string\") return dateStr;\n if (MIDNIGHT_RE.test(dateStr)) {\n return dateStr.split(\"T\")[0] ?? dateStr;\n }\n return dateStr;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst LOCAL_IMAGE_MARKER_REGEX = new RegExp(\n `>\\\\s*📎\\\\s*[^\\\\n]*\\\\n>\\\\s*%%\\\\s*${MARKER_BRAND_RE}:local-(?:image|file):([^\\\\s]+)\\\\s*%%`,\n \"g\",\n);\n\nexport class LocalImageRestorer implements Processor {\n readonly name = \"LocalImageRestorer\";\n readonly order = 15;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const content = input.content.replace(LOCAL_IMAGE_MARKER_REGEX, (_match, target: string) => {\n return `![[${target}]]`;\n });\n\n return { content, metadata: input.metadata };\n }\n}\n","import matter from \"gray-matter\";\nimport type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst YAML_PROPERTIES_REGEX = new RegExp(\n \"```yaml\\\\n# \" + MARKER_BRAND_RE + \":properties\\\\n([\\\\s\\\\S]*?)```\\\\n*(?:---\\\\n*)?\",\n);\n\nconst LEGACY_TABLE_REGEX =\n /^\\s*\\| Property\\s*\\| Value\\s*\\|\\n\\s*\\|\\s*-{3,}\\s*\\|\\s*-{3,}\\s*\\|\\n((?:\\|[^\\n]+\\|\\n?)+)\\n*---\\n*/;\n\nexport class PropertiesTableRestorer implements Processor {\n readonly name = \"PropertiesTableRestorer\";\n readonly order = 5;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n\n const yamlMatch = input.content.match(YAML_PROPERTIES_REGEX);\n if (yamlMatch) {\n return this.restoreFromYaml(input, yamlMatch);\n }\n\n const tableMatch = input.content.match(LEGACY_TABLE_REGEX);\n if (tableMatch) {\n return this.restoreFromTable(input, tableMatch);\n }\n\n return { content: input.content, metadata: input.metadata };\n }\n\n private restoreFromYaml(input: ProcessorInput, match: RegExpMatchArray): ProcessorOutput {\n const yamlContent = match[1]!;\n const fakeDocument = `---\\n${yamlContent}---\\n`;\n\n let parsed: Record<string, unknown>;\n try {\n const result = matter(fakeDocument);\n parsed = result.data;\n } catch {\n return { content: input.content, metadata: input.metadata };\n }\n\n const properties: Record<string, unknown> = {\n ...(input.metadata.properties as Record<string, unknown> | undefined),\n ...parsed,\n };\n\n const content = input.content.replace(YAML_PROPERTIES_REGEX, \"\").trimStart();\n\n return {\n content,\n metadata: { ...input.metadata, properties },\n };\n }\n\n private restoreFromTable(input: ProcessorInput, match: RegExpMatchArray): ProcessorOutput {\n const rows = match[1]!.trim().split(\"\\n\");\n const properties: Record<string, unknown> = {\n ...(input.metadata.properties as Record<string, unknown> | undefined),\n };\n\n for (const row of rows) {\n const cells = row\n .split(\"|\")\n .map((c) => c.trim())\n .filter(Boolean);\n if (cells.length >= 2) {\n const key = cells[0]!;\n const rawValue = cells[1]!;\n properties[key] = parseLegacyValue(rawValue);\n }\n }\n\n const content = input.content.replace(LEGACY_TABLE_REGEX, \"\").trimStart();\n\n return {\n content,\n metadata: { ...input.metadata, properties },\n };\n }\n}\n\nfunction parseLegacyValue(raw: string): unknown {\n if (raw === \"\" || raw === \"null\") return null;\n if (raw === \"true\") return true;\n if (raw === \"false\") return false;\n\n const unquoted = stripQuotes(raw);\n const num = Number(unquoted);\n if (!isNaN(num) && unquoted.trim() !== \"\") return num;\n\n if (unquoted.includes(\", \")) {\n const parts = unquoted.split(\", \");\n const looksLikeArray = parts.every((p) => p.split(/\\s+/).length <= 3);\n if (looksLikeArray) {\n return parts.map((v) => {\n const n = Number(v);\n return !isNaN(n) && v.trim() !== \"\" ? n : v;\n });\n }\n }\n\n if (unquoted.startsWith(\"{\") || unquoted.startsWith(\"[\")) {\n try {\n return JSON.parse(unquoted);\n } catch {\n return unquoted;\n }\n }\n\n return unquoted;\n}\n\nfunction stripQuotes(s: string): string {\n if ((s.startsWith('\"') && s.endsWith('\"')) || (s.startsWith(\"'\") && s.endsWith(\"'\"))) {\n return s.slice(1, -1);\n }\n return s;\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND } from \"../../constants/markers.js\";\n\n/**\n * 블록 간격 정규화(D1) — Notion markdown export 는 블록 사이 빈 줄이 없는 압축형이라\n * 그대로 저장하면 (1) 인접 문단이 CommonMark lazy continuation 으로 한 문단으로 병합되고\n * (2) 인접 콜아웃이 하나의 콜아웃으로 합쳐진다. 재push 시 실제 병합이 일어나는\n * ping-pong 손상이므로 표준 마크다운 간격(블록 사이 빈 줄 1개)으로 되살린다.\n *\n * 묶음 유지(내부 빈 줄 없음): 리스트 연속(중첩·들여쓴 하위 내용 포함), 인용 연속\n * (단 `> [!type]` 콜아웃 시작은 새 블록), 표 행 연속, 각주 정의(`[^n]:`) 연속,\n * 펜스(``` ~~~ $$) 내부, 브랜드 보존 마커 줄(직전 블록에 부착 — 앵커 인접성 유지).\n *\n * 들여쓰기 정규화(D4): export 는 리스트 중첩에 탭을 쓴다. Obsidian/작성 관행의\n * 4-space 로 통일한다(펜스 내부 제외).\n *\n * 압축형 감지: 1차 신호는 `metadata.notionExportCompact` — orchestrator 가 **원시**\n * export(enhanced 변환 전)에서 `isCompactExport` 로 판정해 전달한다. 원시 export 는\n * 펜스 밖 빈 줄이 0 개지만(실측: v2 torture 89줄·f14 239줄), 노션의 명시적 빈 문단\n * 블록 `<empty-block/>` 이 enhanced 변환(removeEmptyBlocks)에서 빈 줄로 바뀌므로\n * 파이프라인 도착 시점의 내용만으로는 압축형을 오판한다(f14 실측: 빈 줄 6개로 스킵).\n * 플래그 미지정(오프라인 왕복, 테스트, blocks-API 폴백) 시에만 내용 기반 휴리스틱\n * — 펜스 밖 빈 줄이 하나라도 있으면 저작형으로 보고 무동작 — 으로 폴백한다.\n * 저작형 문서의 hard-wrap 문단·마커 주변 간격을 재그룹핑으로 파손하지 않기 위함.\n *\n * 한계: Notion 문단 내부 soft break(shift+enter)로 생긴 다중 행은 문단 경계와\n * 구분 불가능해 별개 문단으로 분리된다.\n *\n * pull 전용, order 110 — PreserveMarkerInjector(100)가 앵커 기준으로 삽입을 끝낸\n * 뒤에 간격만 손대야 앵커 오프셋 계산과 충돌하지 않는다.\n */\nexport class BlockSpacer implements Processor {\n readonly name = \"BlockSpacer\";\n readonly order = 110;\n\n process(input: ProcessorInput): ProcessorOutput {\n if (input.context.direction !== \"pull\") {\n return { content: input.content, metadata: input.metadata };\n }\n return {\n content: respace(input.content, input.metadata.notionExportCompact),\n metadata: input.metadata,\n };\n }\n}\n\ntype BlockKind = \"list\" | \"quote\" | \"table\" | \"footnote\" | \"fence\" | \"math\" | \"other\";\n\nconst LIST_ITEM_RE = /^[ \\t]*(?:[-*+]|\\d+[.)])\\s/;\nconst QUOTE_RE = /^[ \\t]*>/;\nconst CALLOUT_START_RE = /^[ \\t]*>\\s*\\[![^\\]]*\\]/;\nconst TABLE_ROW_RE = /^[ \\t]*\\|/;\nconst FOOTNOTE_DEF_RE = /^\\[\\^[^\\]]+\\]:/;\nconst FENCE_RE = /^[ \\t]*(```+|~~~+)/;\nconst MATH_FENCE_RE = /^[ \\t]*\\$\\$\\s*$/;\nconst BRAND_MARKER_LINE_RE = new RegExp(`^[ \\\\t]*%%\\\\s*${MARKER_BRAND}:`);\n\n/** 리스트 항목 아래 들여쓴 연속 내용(자식 문단 등)인지 — 리스트 블록에 묶는다. */\nconst INDENTED_CONTINUATION_RE = /^(?:\\t| {2,})\\S/;\n\nexport function respace(content: string, sourceCompact?: boolean): string {\n // 원시 export 가 간격 있는 문서였다면(blocks-API 폴백 등) 무동작\n if (sourceCompact === false) return content;\n\n const lines = content.split(\"\\n\");\n\n // 선두 프론트매터는 원형 보존\n const head: string[] = [];\n let start = 0;\n if (lines[0]?.trim() === \"---\") {\n for (let i = 1; i < lines.length; i++) {\n if (lines[i]!.trim() === \"---\") {\n for (let j = 0; j <= i; j++) head.push(lines[j]!);\n start = i + 1;\n break;\n }\n }\n }\n\n // 압축형 감지 휴리스틱(플래그 미지정 시 폴백) — 간격이 이미 있는 문서는 손대지 않는다.\n // sourceCompact === true 면 orchestrator 가 원시 export 로 이미 판정했으므로 건너뛴다\n // (enhanced 변환의 <empty-block/>→빈 줄 치환이 휴리스틱을 오판시키는 것을 차단, D1).\n if (sourceCompact === undefined && hasBlankOutsideFences(lines, start)) return content;\n\n // 블록 그룹핑\n const blocks: { kind: BlockKind; lines: string[] }[] = [];\n let fence: \"code\" | \"math\" | null = null;\n let fenceToken = \"\";\n // 압축 export 의 빈 줄은 <empty-block/>(명시적 빈 문단) 유래 — 사용자가 의도한\n // 블록 경계다. 다음 줄이 같은 종류라도 직전 블록에 붙이지 않는다(리스트/인용 재병합 방지).\n let boundary = false;\n\n const push = (kind: BlockKind, line: string) => {\n blocks.push({ kind, lines: [line] });\n };\n const appendToLast = (line: string) => {\n blocks[blocks.length - 1]!.lines.push(line);\n };\n const last = () => blocks[blocks.length - 1];\n\n for (let i = start; i < lines.length; i++) {\n const raw = lines[i]!;\n\n if (fence !== null) {\n appendToLast(raw);\n const closed =\n fence === \"code\"\n ? FENCE_RE.test(raw) && raw.trim().startsWith(fenceToken)\n : MATH_FENCE_RE.test(raw);\n if (closed) fence = null;\n continue;\n }\n\n if (raw.trim() === \"\") {\n boundary = true; // 경계 신호만 남기고 간격은 재계산한다\n continue;\n }\n const atBoundary = boundary;\n boundary = false;\n\n const fenceMatch = raw.match(FENCE_RE);\n if (fenceMatch) {\n push(\"fence\", raw);\n fence = \"code\";\n fenceToken = fenceMatch[1]![0]!.repeat(3);\n continue;\n }\n if (MATH_FENCE_RE.test(raw)) {\n push(\"math\", raw);\n fence = \"math\";\n continue;\n }\n\n // 리스트 들여쓰기 탭 → 4-space (펜스 밖 리스트/연속 줄만)\n const line =\n LIST_ITEM_RE.test(raw) || INDENTED_CONTINUATION_RE.test(raw)\n ? raw.replace(/^\\t+/, (t) => \" \".repeat(t.length))\n : raw;\n\n if (BRAND_MARKER_LINE_RE.test(line) && blocks.length > 0) {\n appendToLast(line); // 보존 마커는 앵커(직전 블록)에 부착 — 경계보다 앵커 인접성 우선\n continue;\n }\n if (LIST_ITEM_RE.test(line)) {\n if (last()?.kind === \"list\" && !atBoundary) appendToLast(line);\n else push(\"list\", line);\n continue;\n }\n if (last()?.kind === \"list\" && INDENTED_CONTINUATION_RE.test(line)) {\n // 경계 무시하고 리스트에 부착 — 분리하면 4-space 들여쓴 줄이 코드 블록으로 오파싱된다\n appendToLast(line);\n continue;\n }\n if (QUOTE_RE.test(line)) {\n if (last()?.kind === \"quote\" && !CALLOUT_START_RE.test(line) && !atBoundary) {\n appendToLast(line);\n } else {\n push(\"quote\", line);\n }\n continue;\n }\n if (TABLE_ROW_RE.test(line)) {\n if (last()?.kind === \"table\" && !atBoundary) appendToLast(line);\n else push(\"table\", line);\n continue;\n }\n if (FOOTNOTE_DEF_RE.test(line)) {\n if (last()?.kind === \"footnote\" && !atBoundary) appendToLast(line);\n else push(\"footnote\", line);\n continue;\n }\n push(\"other\", line);\n }\n\n const body = blocks.map((b) => b.lines.join(\"\\n\")).join(\"\\n\\n\");\n const tail = content.endsWith(\"\\n\") ? \"\\n\" : \"\";\n if (head.length === 0) return body + tail;\n return `${head.join(\"\\n\")}\\n\\n${body}${tail}`;\n}\n\n/**\n * 원시 Notion markdown export 의 압축형 판정 — orchestrator 가 `notionEnhancedToObsidian`\n * **호출 전**(즉 `<empty-block/>` 이 아직 토큰인 시점)에 사용해 `metadata.notionExportCompact`\n * 로 전달한다. 압축 export 는 펜스 밖 빈 줄이 0 개다(빈 문단은 `<empty-block/>` 토큰이라\n * 빈 줄로 계수되지 않음). 프론트매터는 export 에 존재하지 않으므로 고려하지 않는다.\n */\nexport function isCompactExport(rawMarkdown: string): boolean {\n return !hasBlankOutsideFences(rawMarkdown.split(\"\\n\"), 0);\n}\n\n/** 프론트매터 뒤~말미 빈 줄 앞 구간에서 펜스 밖 빈 줄 존재 여부(압축형 판정). */\nfunction hasBlankOutsideFences(lines: string[], start: number): boolean {\n let end = lines.length - 1;\n while (end >= start && lines[end]!.trim() === \"\") end--;\n\n let fence: \"code\" | \"math\" | null = null;\n let fenceToken = \"\";\n for (let i = start; i <= end; i++) {\n const raw = lines[i]!;\n if (fence !== null) {\n const closed =\n fence === \"code\"\n ? FENCE_RE.test(raw) && raw.trim().startsWith(fenceToken)\n : MATH_FENCE_RE.test(raw);\n if (closed) fence = null;\n continue;\n }\n const fenceMatch = raw.match(FENCE_RE);\n if (fenceMatch) {\n fence = \"code\";\n fenceToken = fenceMatch[1]![0]!.repeat(3);\n continue;\n }\n if (MATH_FENCE_RE.test(raw)) {\n fence = \"math\";\n continue;\n }\n if (raw.trim() === \"\") return true;\n }\n return false;\n}\n","import { ConversionPipeline } from \"./pipeline.js\";\nimport { FrontmatterExtractor } from \"./pre-processors/frontmatter.js\";\nimport { WikilinkResolver, type WikilinkResolverFn } from \"./pre-processors/wikilink.js\";\nimport { CalloutTransformer } from \"./pre-processors/callout.js\";\nimport { MathNormalizer } from \"./pre-processors/math.js\";\nimport { EmbedResolver } from \"./pre-processors/embed.js\";\nimport { PreserveMarkerCollector } from \"./pre-processors/preserve-marker.js\";\nimport { UnsupportedBlockStripper } from \"./pre-processors/unsupported-block-stripper.js\";\nimport { PropertiesTableInjector } from \"./pre-processors/properties-table.js\";\nimport { InlineAnnotationPreserver } from \"./pre-processors/html-annotation.js\";\nimport { CommentStripper } from \"./pre-processors/comment-stripper.js\";\nimport { FootnoteGuard } from \"./pre-processors/footnote-guard.js\";\nimport { TableAlignmentGuard } from \"./pre-processors/table-alignment.js\";\nimport { MentionToWikilink } from \"./post-processors/mention-to-wikilink.js\";\nimport { EscapeNormalizer } from \"./post-processors/escape-normalizer.js\";\nimport { HighlightRestorer } from \"./post-processors/highlight-restorer.js\";\nimport { TableAlignmentRestorer } from \"./post-processors/table-alignment-restorer.js\";\nimport { PreserveMarkerInjector } from \"./post-processors/preserve-marker-injector.js\";\nimport { CalloutRestorer } from \"./post-processors/callout-restorer.js\";\nimport { ColorAnnotator } from \"./post-processors/color-annotator.js\";\nimport { FrontmatterGenerator } from \"./post-processors/frontmatter-generator.js\";\nimport { LocalImageRestorer } from \"./post-processors/local-image-restorer.js\";\nimport { PropertiesTableRestorer } from \"./post-processors/properties-table-restorer.js\";\nimport { BlockSpacer } from \"./post-processors/block-spacer.js\";\n\nexport interface PipelineOptions {\n readonly wikilinkResolver?: WikilinkResolverFn;\n}\n\nexport function createDefaultPipeline(options?: PipelineOptions): ConversionPipeline {\n const pipeline = new ConversionPipeline();\n\n pipeline.registerPreProcessor(new InlineAnnotationPreserver());\n pipeline.registerPreProcessor(new UnsupportedBlockStripper());\n pipeline.registerPreProcessor(new CommentStripper());\n pipeline.registerPreProcessor(new FrontmatterExtractor());\n pipeline.registerPreProcessor(new FootnoteGuard());\n pipeline.registerPreProcessor(new PropertiesTableInjector());\n pipeline.registerPreProcessor(new WikilinkResolver(options?.wikilinkResolver));\n pipeline.registerPreProcessor(new CalloutTransformer());\n pipeline.registerPreProcessor(new TableAlignmentGuard());\n pipeline.registerPreProcessor(new MathNormalizer());\n pipeline.registerPreProcessor(new EmbedResolver());\n pipeline.registerPreProcessor(new PreserveMarkerCollector());\n\n pipeline.registerPostProcessor(new EscapeNormalizer());\n pipeline.registerPostProcessor(new PropertiesTableRestorer());\n pipeline.registerPostProcessor(new LocalImageRestorer());\n pipeline.registerPostProcessor(new HighlightRestorer());\n pipeline.registerPostProcessor(new TableAlignmentRestorer());\n pipeline.registerPostProcessor(new PreserveMarkerInjector());\n pipeline.registerPostProcessor(new MentionToWikilink());\n pipeline.registerPostProcessor(new CalloutRestorer());\n pipeline.registerPostProcessor(new ColorAnnotator());\n pipeline.registerPostProcessor(new FrontmatterGenerator());\n pipeline.registerPostProcessor(new BlockSpacer());\n\n return pipeline;\n}\n","/**\n * Notion rich_text → Markdown 인라인 변환 (순수 함수).\n *\n * 블록 변환(block-converter)에서 분리해 단위 테스트 가능하게 한다. 인라인 서식,\n * 수식, 멘션, 색상 보존 마커 등 rich_text 한 배열을 마크다운 문자열로 환원하는\n * 책임만 가진다(SRP). Notion API·notion-to-md 에 의존하지 않는다.\n */\nimport { compactMarker } from \"../constants/markers.js\";\nimport { compactNotionId } from \"../utils/id.js\";\n\n/** caption 등 서식 없는 rich_text 의 최소 형태. */\nexport type RichTextItem = { plain_text: string; href?: string | null };\n\n/** annotations·equation·mention 까지 담은 완전한 rich_text 형태. */\nexport interface RichTextAnnotated extends RichTextItem {\n annotations?: Record<string, unknown>;\n type?: string;\n equation?: { expression: string };\n mention?: {\n type: string;\n page?: { id: string };\n date?: { start: string; end?: string | null };\n user?: { id: string; name?: string };\n database?: { id: string };\n };\n}\n\n/** rich_text 배열을 서식 없는 평문으로 환원한다(caption 등에 사용). */\nexport function richTextToPlain(richText: RichTextItem[] | undefined): string {\n if (!richText) return \"\";\n return richText.map((t) => t.plain_text).join(\"\");\n}\n\n/**\n * rich_text 배열을 마크다운으로 환원한다. 인라인 코드/굵게/기울임/취소선/밑줄/링크/\n * 색상(보존 마커)/수식/멘션을 모두 처리한다.\n */\nexport function richTextToMarkdown(richText: RichTextAnnotated[] | undefined): string {\n if (!richText) return \"\";\n return richText\n .map((t) => {\n if (t.type === \"equation\" && t.equation) {\n return `$${t.equation.expression}$`;\n }\n\n if (t.type === \"mention\" && t.mention) {\n return formatMention(t.mention, t.plain_text);\n }\n\n let text = t.plain_text;\n const a = t.annotations;\n if (a?.code) text = `\\`${text}\\``;\n if (a?.bold) text = `**${text}**`;\n if (a?.italic) text = `*${text}*`;\n if (a?.strikethrough) text = `~~${text}~~`;\n if (a?.underline) text = `<u>${text}</u>`;\n if (t.href) text = `[${text}](${t.href})`;\n\n const color = a?.color as string | undefined;\n if (color && color !== \"default\") {\n // 압축형 정본(`%%im-nobsidian:color:X%%text%%/color%%`)으로 통일한다.\n // enhanced-md-converter 의 restoreColorSpans 가 이 형태만 인식하므로, 공백형을\n // 내보내면 블록 폴백 경로의 색상이 push 시 silent 손실된다(rank15/I3).\n text = `${compactMarker(`color:${color}`)}${text}%%/color%%`;\n }\n\n return text;\n })\n .join(\"\");\n}\n\n/**\n * 멘션을 마크다운으로 환원한다. page·database 는 위키링크, date 는 날짜 문자열,\n * user 는 `@이름`. 그 외(link_preview·template_mention·custom_emoji 등)는 빈 문자열로\n * 버리면 본문이 소실되므로 Notion 이 채워주는 plain_text(예: URL, \"@오늘\")로 보존한다.\n */\nexport function formatMention(\n mention: NonNullable<RichTextAnnotated[\"mention\"]>,\n plainText: string,\n): string {\n switch (mention.type) {\n case \"page\":\n // 블록 폴백 경로도 markdown-api 경로(convertPageMentions)와 동일한 정규형\n // `[[notion:<32hex>]]` 로 내보낸다. 과거의 `[[<하이픈 id>]]` 는 오케스트레이터의\n // 멘션 해소 정규식과 맞지 않아 제목으로 복원되지 못하고 고아 위키링크로 남았다(rank20/I3).\n return mention.page ? `[[notion:${compactNotionId(mention.page.id)}]]` : plainText;\n case \"date\": {\n if (!mention.date) return plainText;\n const start = mention.date.start;\n return mention.date.end ? `${start} → ${mention.date.end}` : start;\n }\n case \"user\":\n return mention.user?.name ? `@${mention.user.name}` : plainText || \"@user\";\n case \"database\":\n return mention.database ? `[[notion:${compactNotionId(mention.database.id)}]]` : plainText;\n default:\n return plainText;\n }\n}\n","import { markdownToBlocks } from \"@tryfabric/martian\";\nimport { NotionToMarkdown } from \"notion-to-md\";\nimport type { Client } from \"@notionhq/client\";\nimport type { BlockObjectResponse } from \"@notionhq/client/build/src/api-endpoints.js\";\nimport { NotionBlockBuilder } from \"../notion/block-builder.js\";\nimport type { NotionBlock } from \"../notion/block-builder.js\";\nimport { richTextToPlain, richTextToMarkdown } from \"./rich-text-converter.js\";\nimport type { RichTextItem } from \"./rich-text-converter.js\";\nimport {\n MARKER_BRAND,\n compactMarker,\n TOGGLE_START,\n TOGGLE_END,\n COLUMN_LIST_START,\n COLUMN_SEP,\n COLUMN_LIST_END,\n TOC_MARKER,\n BREADCRUMB_MARKER,\n} from \"../constants/markers.js\";\n\nconst TRULY_UNSUPPORTED_BLOCK_TYPES = [\"unsupported\", \"template\"] as const;\n\nconst DIVIDER_PLACEHOLDER = \"​%%IM-NOBSIDIAN_DIVIDER%%​\";\n\nconst VIDEO_URL_PATTERNS = [\n /^https?:\\/\\/(www\\.)?youtube\\.com\\/watch/,\n /^https?:\\/\\/youtu\\.be\\//,\n /^https?:\\/\\/(www\\.)?vimeo\\.com\\//,\n /^https?:\\/\\/(www\\.)?dailymotion\\.com\\//,\n /^https?:\\/\\/(www\\.)?loom\\.com\\/share\\//,\n];\n\nconst EMBED_URL_PATTERNS = [\n /^https?:\\/\\/(www\\.)?figma\\.com\\//,\n /^https?:\\/\\/docs\\.google\\.com\\//,\n /^https?:\\/\\/drive\\.google\\.com\\//,\n /^https?:\\/\\/(www\\.)?miro\\.com\\//,\n /^https?:\\/\\/(www\\.)?twitter\\.com\\//,\n /^https?:\\/\\/(www\\.)?x\\.com\\//,\n /^https?:\\/\\/codepen\\.io\\//,\n /^https?:\\/\\/gist\\.github\\.com\\//,\n /^https?:\\/\\/(www\\.)?spotify\\.com\\//,\n /^https?:\\/\\/(www\\.)?soundcloud\\.com\\//,\n];\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nexport class BlockConverter {\n private n2m: NotionToMarkdown | null = null;\n private client: Client | null = null;\n\n initNotionToMd(client: Client): void {\n this.client = client;\n this.n2m = new NotionToMarkdown({ notionClient: client });\n this.registerCustomTransformers();\n }\n\n private registerCustomTransformers(): void {\n if (!this.n2m) return;\n\n for (const blockType of TRULY_UNSUPPORTED_BLOCK_TYPES) {\n this.n2m.setCustomTransformer(blockType, (block) => {\n const id = block.id ?? \"unknown\";\n return Promise.resolve(\n `> [!${MARKER_BRAND}-unsupported] Notion 전용 블록\\n> type: ${blockType}, id: ${id}\\n> ${compactMarker(`unsupported:type=${blockType}&id=${id}`)}`,\n );\n });\n }\n\n this.registerToggleTransformer();\n this.registerColumnTransformer();\n this.registerSyncedBlockTransformer();\n this.registerBookmarkTransformer();\n this.registerVideoTransformer();\n this.registerAudioTransformer();\n this.registerFileTransformer();\n this.registerChildPageTransformer();\n this.registerChildDatabaseTransformer();\n this.registerLinkToPageTransformer();\n this.registerTocTransformer();\n this.registerBreadcrumbTransformer();\n this.registerLinkPreviewTransformer();\n this.registerPdfTransformer();\n this.registerEmbedTransformer();\n this.registerCalloutTransformer();\n this.registerToggleHeadingTransformers();\n this.registerNumberedListTransformer();\n }\n\n /**\n * `numbered_list_item` 을 `1.` 마크다운으로 내보내 **번호 목록 타입을 보존**한다(I2 블록 라운드트립).\n *\n * notion-to-md 기본 렌더는 `md.bullet(text, block.numbered_list_item.number)` 를 쓰는데\n * Notion API 는 list item 에 `.number` 를 채워주지 않아 `undefined` → 불릿(`- `)으로 **강등**된다.\n * 그러면 블록 폴백 경로(notionBlocksToMarkdown)로 pull 한 뒤 다시 push 하면 numbered_list_item 이\n * bulleted_list_item 으로 **타입 유실**된다(기본 markdown-api 경로는 영향 없음).\n *\n * 항상 `1.` 로 내보내면 마크다운이 시각적으로 자동 재번호하므로 표시는 동일하고, martian 이 다시\n * numbered_list_item 으로 파싱해 타입이 보존된다. 커스텀 트랜스포머 등록은 notion-to-md 의 기본\n * 자식 처리를 끄므로(라이브러리 설계), 자식은 toggle/callout 과 동일하게 직접 fetch·들여쓰기한다.\n */\n private registerNumberedListTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n this.n2m.setCustomTransformer(\"numbered_list_item\", async (block) => {\n const b = block as unknown as {\n numbered_list_item: { rich_text: RichTextItem[] };\n } & BlockObjectResponse;\n const text = richTextToMarkdown(b.numbered_list_item?.rich_text as never);\n let result = `1. ${text}`;\n if (b.has_children) {\n const children = await n2m.pageToMarkdown(b.id);\n const childMd =\n (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n if (childMd.trim()) {\n const indented = childMd\n .split(\"\\n\")\n .map((l: string) => (l.trim() ? ` ${l}` : \"\"))\n .join(\"\\n\")\n .trimEnd();\n result += \"\\n\" + indented;\n }\n }\n return result;\n });\n }\n\n private registerToggleTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n this.n2m.setCustomTransformer(\"toggle\", async (block) => {\n const b = block as unknown as { toggle: { rich_text: RichTextItem[] } } & BlockObjectResponse;\n const title = richTextToMarkdown(b.toggle?.rich_text as never);\n const children = b.has_children ? await n2m.pageToMarkdown(b.id) : [];\n const childMd = (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n const indented = childMd\n .split(\"\\n\")\n .map((line: string) => (line.trim() ? ` ${line}` : \" \"))\n .join(\"\\n\")\n .trimEnd();\n return `${TOGGLE_START}\\n- ${title}\\n${indented}\\n${TOGGLE_END}`;\n });\n }\n\n private registerToggleHeadingTransformers(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n\n for (const level of [1, 2, 3] as const) {\n const headingKey = `heading_${level}` as const;\n this.n2m.setCustomTransformer(headingKey, async (block) => {\n const b = block as unknown as {\n [K in typeof headingKey]: { rich_text: RichTextItem[]; is_toggleable?: boolean };\n } & BlockObjectResponse;\n const headingData = b[headingKey];\n const text = richTextToMarkdown(headingData?.rich_text as never);\n const prefix = \"#\".repeat(level);\n\n if (headingData?.is_toggleable && b.has_children) {\n const children = await n2m.pageToMarkdown(b.id);\n const childMd =\n (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n return `${prefix} ${text}\\n\\n${childMd.trimEnd()}`;\n }\n\n return `${prefix} ${text}`;\n });\n }\n }\n\n private registerColumnTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n const client = this.client!;\n\n this.n2m.setCustomTransformer(\"column_list\", async (block) => {\n const b = block as BlockObjectResponse;\n const response = await client.blocks.children.list({ block_id: b.id });\n const columns = response.results as BlockObjectResponse[];\n const parts: string[] = [];\n\n for (let i = 0; i < columns.length; i++) {\n const col = columns[i]!;\n const children = await n2m.pageToMarkdown(col.id);\n const childMd =\n (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n parts.push(`${COLUMN_SEP}\\n${childMd.trimEnd()}`);\n }\n\n return `${COLUMN_LIST_START}\\n${parts.join(\"\\n\")}\\n${COLUMN_LIST_END}`;\n });\n\n this.n2m.setCustomTransformer(\"column\", async () => \"\");\n }\n\n private registerSyncedBlockTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n const client = this.client!;\n\n this.n2m.setCustomTransformer(\"synced_block\", async (block) => {\n const b = block as unknown as {\n synced_block: { synced_from: { block_id: string } | null };\n } & BlockObjectResponse;\n\n const sourceId = b.synced_block?.synced_from?.block_id ?? b.id;\n\n const response = await client.blocks.children.list({ block_id: sourceId });\n const mdBlocks: unknown[] = [];\n for (const child of response.results as BlockObjectResponse[]) {\n const result = await n2m.blockToMarkdown(child as never);\n if (result) mdBlocks.push(result);\n }\n const childMd = n2m.toMarkdownString(mdBlocks as never).parent ?? \"\";\n return childMd.trimEnd();\n });\n }\n\n private registerBookmarkTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"bookmark\", async (block) => {\n const b = block as unknown as {\n bookmark: { url: string; caption?: RichTextItem[] };\n };\n const url = b.bookmark?.url ?? \"\";\n const caption = richTextToPlain(b.bookmark?.caption);\n if (caption) {\n return `[${caption}](${url})`;\n }\n return `[${url}](${url})`;\n });\n }\n\n private registerVideoTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"video\", async (block) => {\n const b = block as unknown as {\n video: {\n type: string;\n external?: { url: string };\n file?: { url: string };\n caption?: RichTextItem[];\n };\n };\n const url = b.video?.type === \"external\" ? b.video.external?.url : b.video?.file?.url;\n const caption = richTextToPlain(b.video?.caption);\n return `![${caption || \"video\"}](${url ?? \"\"})`;\n });\n }\n\n private registerAudioTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"audio\", async (block) => {\n const b = block as unknown as {\n audio: {\n type: string;\n external?: { url: string };\n file?: { url: string };\n caption?: RichTextItem[];\n };\n };\n const url = b.audio?.type === \"external\" ? b.audio.external?.url : b.audio?.file?.url;\n const caption = richTextToPlain(b.audio?.caption);\n return `![${caption || \"audio\"}](${url ?? \"\"})`;\n });\n }\n\n private registerFileTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"file\", async (block) => {\n const b = block as unknown as {\n file: {\n type: string;\n external?: { url: string };\n file?: { url: string };\n caption?: RichTextItem[];\n name?: string;\n };\n };\n const url = b.file?.type === \"external\" ? b.file.external?.url : b.file?.file?.url;\n const name = b.file?.name ?? richTextToPlain(b.file?.caption) ?? \"file\";\n return `[${name}](${url ?? \"\"})`;\n });\n }\n\n private registerChildPageTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"child_page\", async (block) => {\n const b = block as unknown as { child_page: { title: string } };\n const title = b.child_page?.title ?? \"Untitled\";\n return `[[${title}]]`;\n });\n }\n\n private registerChildDatabaseTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"child_database\", async (block) => {\n const b = block as unknown as {\n child_database: { title: string };\n } & BlockObjectResponse;\n const title = b.child_database?.title ?? \"Database\";\n return `> [!database] ${title}\\n> ${compactMarker(`child-database:id=${b.id}&title=${encodeURIComponent(title)}`)}`;\n });\n }\n\n private registerLinkToPageTransformer(): void {\n if (!this.n2m) return;\n const client = this.client!;\n this.n2m.setCustomTransformer(\"link_to_page\", async (block) => {\n const b = block as unknown as {\n link_to_page: { type: string; page_id?: string; database_id?: string };\n };\n const pageId = b.link_to_page?.page_id ?? b.link_to_page?.database_id;\n if (!pageId) return \"\";\n try {\n const page = await client.pages.retrieve({ page_id: pageId });\n const p = page as {\n properties: Record<string, { type: string; title?: Array<{ plain_text: string }> }>;\n };\n for (const prop of Object.values(p.properties)) {\n if (prop.type === \"title\" && prop.title?.[0]?.plain_text) {\n return `[[${prop.title[0].plain_text}]]`;\n }\n }\n } catch {\n // fallback\n }\n return `[[${pageId}]]`;\n });\n }\n\n private registerTocTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"table_of_contents\", async () => {\n return TOC_MARKER;\n });\n }\n\n private registerBreadcrumbTransformer(): void {\n if (!this.n2m) return;\n // breadcrumb 은 마크다운 표현이 없다. 빈 문자열로 버리면 라운드트립에서 소실되므로\n // 보존 마커를 남겨 push 시 breadcrumb 블록으로 복원한다(convertSingleLineMarker).\n this.n2m.setCustomTransformer(\"breadcrumb\", async () => BREADCRUMB_MARKER);\n }\n\n private registerLinkPreviewTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"link_preview\", async (block) => {\n const b = block as unknown as { link_preview: { url: string } };\n const url = b.link_preview?.url ?? \"\";\n return `[${url}](${url})`;\n });\n }\n\n private registerPdfTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"pdf\", async (block) => {\n const b = block as unknown as {\n pdf: {\n type: string;\n file?: { url: string };\n external?: { url: string };\n caption?: RichTextItem[];\n };\n };\n const url = b.pdf?.type === \"file\" ? (b.pdf.file?.url ?? \"\") : (b.pdf?.external?.url ?? \"\");\n const caption = b.pdf?.caption ? richTextToMarkdown(b.pdf.caption as never) : \"\";\n return `[📄 ${caption || \"PDF\"}](${url})`;\n });\n }\n\n private registerEmbedTransformer(): void {\n if (!this.n2m) return;\n this.n2m.setCustomTransformer(\"embed\", async (block) => {\n const b = block as unknown as {\n embed: { url: string; caption?: RichTextItem[] };\n };\n const url = b.embed?.url ?? \"\";\n const caption = b.embed?.caption ? richTextToMarkdown(b.embed.caption as never) : \"\";\n return `[${caption || url}](${url})`;\n });\n }\n\n private registerCalloutTransformer(): void {\n if (!this.n2m) return;\n const n2m = this.n2m;\n this.n2m.setCustomTransformer(\"callout\", async (block) => {\n const b = block as unknown as {\n callout: { rich_text: RichTextItem[]; icon?: { type: string; emoji?: string } };\n } & BlockObjectResponse;\n const text = richTextToMarkdown(b.callout?.rich_text as never);\n const emoji = b.callout?.icon?.emoji ?? \"\";\n\n const children = b.has_children ? await n2m.pageToMarkdown(b.id) : [];\n const childMd = (Array.isArray(children) ? n2m.toMarkdownString(children).parent : \"\") ?? \"\";\n\n const EMOJI_TO_TYPE: Record<string, string> = {\n \"\\u{1F4DD}\": \"note\",\n \"\\u{1F4CB}\": \"abstract\",\n \"\\u{2139}\\u{FE0F}\": \"info\",\n \"\\u{1F4A1}\": \"tip\",\n \"\\u{2705}\": \"success\",\n \"\\u{2753}\": \"question\",\n \"\\u{26A0}\\u{FE0F}\": \"warning\",\n \"\\u{274C}\": \"failure\",\n \"\\u{1F525}\": \"danger\",\n \"\\u{1F41B}\": \"bug\",\n \"\\u{1F4CC}\": \"example\",\n \"\\u{1F4AC}\": \"quote\",\n };\n const calloutType = EMOJI_TO_TYPE[emoji] ?? \"note\";\n\n let result = `> [!${calloutType}] ${text}`;\n if (childMd?.trim()) {\n const lines = childMd\n .trim()\n .split(\"\\n\")\n .map((l: string) => (l.trim() ? `> ${l}` : \">\"));\n result += \"\\n\" + lines.join(\"\\n\");\n }\n return result;\n });\n }\n\n markdownToNotionBlocks(markdown: string): unknown[] {\n const preprocessed = this.preProcessMarkdown(markdown);\n const blocks = markdownToBlocks(preprocessed) as Array<Record<string, unknown>>;\n const processed = this.postProcessBlocks(blocks);\n return normalizeBlocksForNotion(processed as Array<Record<string, unknown>>);\n }\n\n private toggleContents: Map<number, string> = new Map();\n private columnContents: Map<number, string[]> = new Map();\n private toggleCounter = 0;\n private columnCounter = 0;\n\n private preProcessMarkdown(markdown: string): string {\n this.toggleContents.clear();\n this.columnContents.clear();\n this.toggleCounter = 0;\n this.columnCounter = 0;\n\n let processed = this.extractToggleBlocks(markdown);\n processed = this.extractColumnBlocks(processed);\n processed = this.replaceDividers(processed);\n processed = processed.replace(/<unknown[^>]*\\/>/g, \"\");\n processed = this.stripInlineAnnotationMarkers(processed);\n return processed;\n }\n\n /**\n * compact underline/color 보존마커를 평문으로 강등 — block(martian) 폴백 경로 전용.\n *\n * 무손실 underline/color 복원은 기본 경로인 Markdown API({@link obsidianToNotionEnhanced})가\n * 전담한다. martian 은 이 서식을 표현할 수 없으므로, Markdown API 가 실패해 이 폴백을 탈 때는\n * 마커 텍스트가 본문에 리터럴로 새지 않도록 텍스트만 남기고 마커를 제거한다(서식 degrade).\n */\n private stripInlineAnnotationMarkers(markdown: string): string {\n return markdown\n .replace(new RegExp(`%%${MARKER_BRAND}:underline%%([\\\\s\\\\S]*?)%%\\\\/underline%%`, \"g\"), \"$1\")\n .replace(new RegExp(`%%${MARKER_BRAND}:color:[^%]+%%([\\\\s\\\\S]*?)%%\\\\/color%%`, \"g\"), \"$1\");\n }\n\n private replaceDividers(markdown: string): string {\n const lines = markdown.split(\"\\n\");\n const result: string[] = [];\n let inCodeBlock = false;\n\n for (const line of lines) {\n if (line.trimStart().startsWith(\"```\")) {\n inCodeBlock = !inCodeBlock;\n }\n\n if (!inCodeBlock && /^---\\s*$/.test(line.trim())) {\n result.push(DIVIDER_PLACEHOLDER);\n } else {\n result.push(line);\n }\n }\n\n return result.join(\"\\n\");\n }\n\n private extractToggleBlocks(markdown: string): string {\n const startRe = new RegExp(`^${escapeRegex(TOGGLE_START)}$`, \"gm\");\n const endRe = new RegExp(`^${escapeRegex(TOGGLE_END)}$`, \"gm\");\n let result = markdown;\n let match: RegExpExecArray | null;\n\n while ((match = startRe.exec(result)) !== null) {\n endRe.lastIndex = match.index;\n const endMatch = endRe.exec(result);\n if (!endMatch) break;\n\n const content = result.slice(match.index + match[0].length + 1, endMatch.index).trimEnd();\n const id = this.toggleCounter++;\n this.toggleContents.set(id, content);\n\n const placeholder = `%%IM-NOBSIDIAN_TOGGLE_${id}%%`;\n result =\n result.slice(0, match.index) +\n placeholder +\n result.slice(endMatch.index + endMatch[0].length);\n\n startRe.lastIndex = match.index + placeholder.length;\n }\n\n return result;\n }\n\n private extractColumnBlocks(markdown: string): string {\n const startRe = new RegExp(`^${escapeRegex(COLUMN_LIST_START)}$`, \"gm\");\n const endRe = new RegExp(`^${escapeRegex(COLUMN_LIST_END)}$`, \"gm\");\n let result = markdown;\n let match: RegExpExecArray | null;\n\n while ((match = startRe.exec(result)) !== null) {\n endRe.lastIndex = match.index;\n const endMatch = endRe.exec(result);\n if (!endMatch) break;\n\n const inner = result.slice(match.index + match[0].length + 1, endMatch.index);\n const columns = inner\n .split(new RegExp(`^${escapeRegex(COLUMN_SEP)}$`, \"m\"))\n .map((c) => c.trim())\n .filter(Boolean);\n\n const id = this.columnCounter++;\n this.columnContents.set(id, columns);\n\n const placeholder = `%%IM-NOBSIDIAN_COLLIST_${id}%%`;\n result =\n result.slice(0, match.index) +\n placeholder +\n result.slice(endMatch.index + endMatch[0].length);\n\n startRe.lastIndex = match.index + placeholder.length;\n }\n\n return result;\n }\n\n private postProcessBlocks(blocks: Array<Record<string, unknown>>): unknown[] {\n const result: unknown[] = [];\n\n for (const block of blocks) {\n const toggleConverted = this.convertTogglePlaceholder(block);\n if (toggleConverted) {\n result.push(toggleConverted);\n continue;\n }\n\n const columnConverted = this.convertColumnPlaceholder(block);\n if (columnConverted) {\n result.push(columnConverted);\n continue;\n }\n\n const dividerConverted = this.convertDividerPlaceholder(block);\n if (dividerConverted) {\n result.push(dividerConverted);\n continue;\n }\n\n const markerConverted = this.convertSingleLineMarker(block);\n if (markerConverted) {\n result.push(markerConverted);\n continue;\n }\n\n const videoConverted = this.convertImageToVideoOrEmbed(block);\n if (videoConverted) {\n result.push(videoConverted);\n continue;\n }\n\n // martian 의 blockquote 자식-중첩을 평탄화해 본문을 quote.rich_text 로 복원한 뒤,\n // 이모지 접두사 quote 의 callout 변환을 적용한다(평탄화 전에는 rich_text 가 비어 no-op).\n const flattened = this.flattenMartianBlockquote(block);\n const calloutConverted = this.convertQuoteToCallout(flattened);\n result.push(calloutConverted);\n }\n\n return result;\n }\n\n private convertTogglePlaceholder(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const text = para?.rich_text?.[0]?.text?.content ?? \"\";\n\n const toggleMatch = text.match(/%%IM-NOBSIDIAN_TOGGLE_(\\d+)%%/);\n if (!toggleMatch) return null;\n\n const id = parseInt(toggleMatch[1]!, 10);\n const content = this.toggleContents.get(id);\n if (content === undefined) return null;\n\n const titleMatch = content.match(/^- (.+)$/m);\n const title = titleMatch?.[1] ?? \"Toggle\";\n\n const childLines = content.split(\"\\n\").slice(1);\n const childMd = childLines\n .map((l) => (l.startsWith(\" \") ? l.slice(2) : l))\n .join(\"\\n\")\n .trim();\n\n const children = childMd ? (markdownToBlocks(childMd) as Array<Record<string, unknown>>) : [];\n\n return NotionBlockBuilder.toggle(\n NotionBlockBuilder.richText(title),\n children.length > 0 ? (children as unknown as NotionBlock[]) : undefined,\n );\n }\n\n private convertColumnPlaceholder(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const text = para?.rich_text?.[0]?.text?.content ?? \"\";\n\n const colMatch = text.match(/%%IM-NOBSIDIAN_COLLIST_(\\d+)%%/);\n if (!colMatch) return null;\n\n const id = parseInt(colMatch[1]!, 10);\n const columns = this.columnContents.get(id);\n if (!columns) return null;\n\n const columnBlocks = columns.map((colMd) => {\n const blocks = markdownToBlocks(colMd) as Array<Record<string, unknown>>;\n return this.postProcessBlocks(blocks) as unknown as NotionBlock[];\n });\n\n return NotionBlockBuilder.columnList(columnBlocks);\n }\n\n private convertDividerPlaceholder(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const text = para?.rich_text?.[0]?.text?.content ?? \"\";\n\n if (text.includes(\"%%IM-NOBSIDIAN_DIVIDER%%\")) {\n return NotionBlockBuilder.divider();\n }\n return null;\n }\n\n /**\n * 단일 라인 보존 마커(목차·breadcrumb)를 원래 블록으로 복원한다.\n * pull 시 마크다운 표현이 없는 블록을 `%%im-nobsidian:toc%%` /\n * `%%im-nobsidian:breadcrumb%%` 마커 문단으로 남겨두므로, push 시 이 문단을\n * 감지해 table_of_contents / breadcrumb 블록으로 되돌린다. 그러지 않으면\n * 마커 텍스트가 일반 문단으로 Notion 에 기록되는 잠재 손실이 된다.\n */\n private convertSingleLineMarker(block: Record<string, unknown>): unknown | null {\n if (block.type !== \"paragraph\") return null;\n\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const texts = para?.rich_text ?? [];\n if (texts.length !== 1) return null;\n\n const text = (texts[0]?.text?.content ?? \"\").trim();\n if (text === TOC_MARKER) {\n return NotionBlockBuilder.tableOfContents();\n }\n if (text === BREADCRUMB_MARKER) {\n return NotionBlockBuilder.breadcrumb();\n }\n return null;\n }\n\n private convertImageToVideoOrEmbed(block: Record<string, unknown>): unknown | null {\n let url = \"\";\n let caption: string | undefined;\n\n if (block.type === \"image\") {\n const img = block.image as\n | {\n external?: { url: string };\n file?: { url: string };\n caption?: Array<{ text?: { content: string } }>;\n }\n | undefined;\n // video/audio/file/pdf 핸들러와 동일하게 external·file(업로드) 양쪽 URL 을 수용한다.\n // file 만 있는 업로드 이미지의 video/embed 승격이 누락되던 비대칭 결함을 봉합(rank17/I3).\n url = img?.external?.url ?? img?.file?.url ?? \"\";\n caption = img?.caption?.[0]?.text?.content;\n } else if (block.type === \"paragraph\") {\n const para = block.paragraph as\n | { rich_text?: Array<{ text?: { content: string } }> }\n | undefined;\n const texts = para?.rich_text ?? [];\n if (texts.length === 1) {\n const content = texts[0]?.text?.content ?? \"\";\n if (/^https?:\\/\\//.test(content)) {\n url = content;\n }\n }\n }\n\n if (!url) return null;\n\n if (VIDEO_URL_PATTERNS.some((p) => p.test(url))) {\n return NotionBlockBuilder.video(url, caption);\n }\n\n if (EMBED_URL_PATTERNS.some((p) => p.test(url))) {\n return NotionBlockBuilder.embed(url, caption);\n }\n\n return null;\n }\n\n /**\n * `@tryfabric/martian` 의 blockquote 표현을 **평탄화**한다(I2/I3 무손실 push).\n *\n * martian 의 parseBlockquote 는 `notion.blockquote([], children)` 로 본문을 quote 의\n * **자식 paragraph** 로 내려보내고 quote.rich_text 를 비운다(라이브러리 설계). 그 결과\n * `> 인용문` 을 push 하면 Notion 에 \"빈 인용 줄 + 들여쓴 자식 문단\"이 만들어지고, 다시\n * pull 하면 `> `(빈 줄) 아래에 자식 문단이 매달려 **원문과 구조가 갈라진다**(라운드트립 손실).\n * 또한 quote.rich_text[0] 이 항상 비어 callout 이모지 감지({@link convertQuoteToCallout})도\n * 무력화됐다.\n *\n * 선두의 연속된 paragraph 자식을 quote.rich_text 로 끌어올리고(문단 사이는 줄바꿈 rich_text\n * 로 연결 — Notion 네이티브 멀티라인 인용 표현), paragraph 가 아닌 자식(중첩 리스트 등)은\n * children 으로 남겨 구조를 보존한다. 이미 rich_text 에 본문이 있거나 끌어올릴 paragraph 가\n * 없으면 원본을 그대로 반환한다(안전 no-op).\n */\n private flattenMartianBlockquote(block: Record<string, unknown>): Record<string, unknown> {\n if (block.type !== \"quote\") return block;\n const quote = block.quote as\n | {\n rich_text?: Array<Record<string, unknown>>;\n children?: Array<Record<string, unknown>>;\n }\n | undefined;\n if (!quote) return block;\n\n const richText = quote.rich_text ?? [];\n const hasText = richText.some((r) => {\n const t = r as { text?: { content?: string }; plain_text?: string };\n return (t.text?.content ?? t.plain_text ?? \"\") !== \"\";\n });\n const children = quote.children ?? [];\n // 본문이 이미 rich_text 에 있거나 끌어올릴 자식이 없으면 변형하지 않는다.\n if (hasText || children.length === 0) return block;\n\n const hoisted: Array<Record<string, unknown>> = [];\n let consumed = 0;\n for (; consumed < children.length; consumed++) {\n const child = children[consumed] as Record<string, unknown>;\n if (child.type !== \"paragraph\") break;\n const para = child.paragraph as { rich_text?: Array<Record<string, unknown>> } | undefined;\n const paraRt = para?.rich_text ?? [];\n if (hoisted.length > 0) {\n // 문단 사이 줄바꿈을 Notion 네이티브 인용처럼 rich_text 줄바꿈으로 보존.\n hoisted.push(\n ...(NotionBlockBuilder.richText(\"\\n\") as unknown as Array<Record<string, unknown>>),\n );\n }\n hoisted.push(...paraRt);\n }\n // 끌어올릴 선두 paragraph 가 하나도 없으면(리스트 등만 존재) 원본 유지.\n if (hoisted.length === 0) return block;\n\n const remaining = children.slice(consumed);\n const newQuote: Record<string, unknown> = { ...quote, rich_text: hoisted };\n if (remaining.length > 0) newQuote.children = remaining;\n else delete newQuote.children;\n return { ...block, quote: newQuote };\n }\n\n private convertQuoteToCallout(block: Record<string, unknown>): unknown {\n if (block.type !== \"quote\") return block;\n\n const quote = block.quote as\n | {\n rich_text: Array<{\n type: string;\n text?: { content: string; link?: unknown };\n annotations?: Record<string, boolean>;\n }>;\n children?: Array<Record<string, unknown>>;\n }\n | undefined;\n if (!quote?.rich_text?.[0]) return block;\n\n const firstText = quote.rich_text[0]?.text?.content ?? \"\";\n\n const KNOWN_CALLOUT_EMOJIS = [\n \"\\u{1F4DD}\",\n \"\\u{1F4CB}\",\n \"\\u{2139}\\u{FE0F}\",\n \"\\u{1F4A1}\",\n \"\\u{2705}\",\n \"\\u{2753}\",\n \"\\u{26A0}\\u{FE0F}\",\n \"\\u{274C}\",\n \"\\u{1F525}\",\n \"\\u{1F41B}\",\n \"\\u{1F4CC}\",\n \"\\u{1F4AC}\",\n ];\n const matchedEmoji = KNOWN_CALLOUT_EMOJIS.find((e) => firstText.startsWith(e));\n if (!matchedEmoji) return block;\n\n const emoji = matchedEmoji;\n const remainingText = firstText.slice(emoji.length).replace(/^\\s+/, \"\");\n\n const newRichText = [...quote.rich_text];\n if (remainingText) {\n newRichText[0] = {\n ...newRichText[0]!,\n text: { content: remainingText, link: null },\n };\n } else {\n newRichText.shift();\n }\n\n return {\n type: \"callout\",\n callout: {\n rich_text: newRichText,\n icon: { type: \"emoji\", emoji },\n children: quote.children ?? [],\n },\n };\n }\n\n async notionBlocksToMarkdown(pageId: string): Promise<string> {\n if (!this.n2m) {\n throw new Error(\n \"NotionToMarkdown이 초기화되지 않았습니다. initNotionToMd()를 먼저 호출하세요.\",\n );\n }\n\n const mdBlocks = await this.n2m.pageToMarkdown(pageId);\n const result = this.n2m.toMarkdownString(mdBlocks);\n return result.parent ?? \"\";\n }\n\n /**\n * **in-memory** 블록 배열을 마크다운으로 변환한다(페이지 fetch 없음). notion-to-md 의\n * blocksToMarkdown 을 직접 호출하므로, `has_children:false` 인 평면 블록은 Notion 클라이언트를\n * 전혀 건드리지 않는다 → 고정 픽스처로 **오프라인 결정론** 블록 라운드트립(I2)을 잠글 수 있는\n * 정식 테스트 시임. children 이 있는 블록(table 행·callout 자식 등)은 클라이언트를 호출하므로\n * 호출 측이 평면 블록만 넣어야 오프라인이 보장된다.\n */\n async notionBlockArrayToMarkdown(blocks: Array<Record<string, unknown>>): Promise<string> {\n if (!this.n2m) {\n throw new Error(\n \"NotionToMarkdown이 초기화되지 않았습니다. initNotionToMd()를 먼저 호출하세요.\",\n );\n }\n const mdBlocks = await this.n2m.blocksToMarkdown(blocks as never);\n return this.n2m.toMarkdownString(mdBlocks).parent ?? \"\";\n }\n}\n\nconst NOTION_MAX_TABLE_ROWS = 100;\nconst NOTION_MAX_LIST_DEPTH = 3;\n\nfunction normalizeBlocksForNotion(\n blocks: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n const result: Array<Record<string, unknown>> = [];\n\n for (const block of blocks) {\n if (block.type === \"table\") {\n result.push(...normalizeTable(block));\n } else if (isListBlock(block)) {\n result.push(flattenListDepth(block, 0));\n } else {\n result.push(block);\n }\n }\n\n return result;\n}\n\nfunction normalizeTable(block: Record<string, unknown>): Array<Record<string, unknown>> {\n const table = block.table as\n | {\n table_width: number;\n has_column_header: boolean;\n has_row_header: boolean;\n children: Array<Record<string, unknown>>;\n }\n | undefined;\n if (!table?.children) return [block];\n\n const rows = table.children;\n if (rows.length === 0) return [block];\n\n let maxCells = table.table_width;\n for (const row of rows) {\n const tr = row.table_row as { cells: unknown[][] } | undefined;\n if (tr?.cells && tr.cells.length > maxCells) {\n maxCells = tr.cells.length;\n }\n }\n\n const normalizedRows = rows.map((row) => {\n const tr = row.table_row as { cells: unknown[][] } | undefined;\n if (!tr?.cells) return row;\n\n const cells = [...tr.cells];\n while (cells.length < maxCells) {\n cells.push([{ type: \"text\", text: { content: \"\" } }]);\n }\n if (cells.length > maxCells) {\n cells.length = maxCells;\n }\n\n return { ...row, table_row: { ...tr, cells } };\n });\n\n if (normalizedRows.length <= NOTION_MAX_TABLE_ROWS) {\n return [\n {\n ...block,\n table: { ...table, table_width: maxCells, children: normalizedRows },\n },\n ];\n }\n\n const tables: Array<Record<string, unknown>> = [];\n const headerRow = table.has_column_header ? normalizedRows[0] : null;\n const dataRows = table.has_column_header ? normalizedRows.slice(1) : normalizedRows;\n const chunkSize = headerRow ? NOTION_MAX_TABLE_ROWS - 1 : NOTION_MAX_TABLE_ROWS;\n\n for (let i = 0; i < dataRows.length; i += chunkSize) {\n const chunk = dataRows.slice(i, i + chunkSize);\n const children = headerRow ? [headerRow, ...chunk] : chunk;\n tables.push({\n type: \"table\",\n table: {\n table_width: maxCells,\n has_column_header: !!headerRow,\n has_row_header: table.has_row_header,\n children,\n },\n });\n }\n\n return tables;\n}\n\nfunction isListBlock(block: Record<string, unknown>): boolean {\n return (\n block.type === \"bulleted_list_item\" ||\n block.type === \"numbered_list_item\" ||\n block.type === \"to_do\"\n );\n}\n\nfunction flattenListDepth(block: Record<string, unknown>, depth: number): Record<string, unknown> {\n const blockType = block.type as string;\n const blockData = block[blockType] as\n | { children?: Array<Record<string, unknown>>; [key: string]: unknown }\n | undefined;\n if (!blockData?.children || blockData.children.length === 0) return block;\n\n if (depth >= NOTION_MAX_LIST_DEPTH - 1) {\n const flattened = collectAllDescendants(blockData.children);\n return {\n ...block,\n [blockType]: { ...blockData, children: flattened },\n };\n }\n\n const normalizedChildren = blockData.children.map((child) => {\n if (isListBlock(child)) {\n return flattenListDepth(child, depth + 1);\n }\n return child;\n });\n\n return {\n ...block,\n [blockType]: { ...blockData, children: normalizedChildren },\n };\n}\n\nfunction collectAllDescendants(\n blocks: Array<Record<string, unknown>>,\n): Array<Record<string, unknown>> {\n const result: Array<Record<string, unknown>> = [];\n for (const block of blocks) {\n const blockType = block.type as string;\n const blockData = block[blockType] as\n | { children?: Array<Record<string, unknown>>; [key: string]: unknown }\n | undefined;\n const children = blockData?.children;\n const blockWithoutChildren = children\n ? { ...block, [blockType]: { ...blockData, children: undefined } }\n : block;\n result.push(blockWithoutChildren);\n if (children && children.length > 0) {\n result.push(...collectAllDescendants(children));\n }\n }\n return result;\n}\n","import { createHash } from \"node:crypto\";\nimport { Sema } from \"async-sema\";\nimport type { VaultFS } from \"./vault-fs.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { ImageReference } from \"../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../constants/markers.js\";\nimport { getLogger } from \"../utils/logger.js\";\n\n/** 미디어(이미지/파일) 다운로드 운영 튜닝값. 미지정 시 기존 동작과 동일한 기본값 사용. */\nexport interface MediaOptions {\n readonly concurrency?: number;\n readonly maxRetries?: number;\n readonly retryBaseMs?: number;\n readonly maxFileSizeBytes?: number;\n}\n\nexport interface ImageDownloadResult {\n readonly originalUrl: string;\n readonly localPath: string;\n readonly hash: string;\n readonly size: number;\n}\n\n/** 다운로드는 됐지만 아직 디스크에 쓰지 않은 이미지 — D6 dedup 판정 후 persist 한다. */\ninterface FetchedImage {\n readonly originalUrl: string;\n readonly localPath: string;\n readonly hash: string;\n /** 전체 sha256 — file_registry.fileHash 와 동일 산식의 비교 키. */\n readonly fullHash: string;\n readonly buffer: Buffer;\n}\n\nexport interface ImageUploadResult {\n readonly localPath: string;\n readonly fileUploadId: string;\n /** 업로드한 이미지의 전체 sha256 — file_registry 비교 키(FileHandler 와 동일 산식). */\n readonly fileHash: string;\n readonly fileSize: number;\n}\n\nconst IMAGE_EXTENSIONS: Record<string, string> = {\n \"image/png\": \".png\",\n \"image/jpeg\": \".jpg\",\n \"image/gif\": \".gif\",\n \"image/webp\": \".webp\",\n \"image/svg+xml\": \".svg\",\n \"image/bmp\": \".bmp\",\n \"image/tiff\": \".tiff\",\n};\n\nconst EXTENSION_TO_MIME: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".bmp\": \"image/bmp\",\n \".ico\": \"image/x-icon\",\n \".tiff\": \"image/tiff\",\n};\n\n/** 괄호 균형 스캔으로 찾은 마크다운 링크/임베드 한 건. */\nexport interface MarkdownLinkSpan {\n readonly full: string;\n readonly label: string;\n readonly url: string;\n readonly isEmbed: boolean;\n}\n\n/**\n * `![label](url)` / `[label](url)` 을 괄호 균형 스캔으로 추출한다.\n * Notion 캡션은 내부에 `[텍스트](url)` 링크를 허용하므로, `[^\\]]*` 류 정규식은\n * 캡션 속 첫 `]` 에서 라벨을 끊고 캡션 내부 URL 을 이미지 URL 로 오인한다.\n */\nexport function scanMarkdownLinks(markdown: string): MarkdownLinkSpan[] {\n const spans: MarkdownLinkSpan[] = [];\n let i = 0;\n while (i < markdown.length) {\n const open = markdown.indexOf(\"[\", i);\n if (open === -1) break;\n if (markdown[open - 1] === \"\\\\\") {\n i = open + 1;\n continue;\n }\n const isEmbed = markdown[open - 1] === \"!\" && markdown[open - 2] !== \"\\\\\";\n // 라벨: 대괄호 깊이 균형(이스케이프 스킵). 빈 줄을 만나면 링크가 아니다.\n let depth = 1;\n let j = open + 1;\n let broken = false;\n while (j < markdown.length && depth > 0) {\n const ch = markdown[j];\n if (ch === \"\\\\\") {\n j += 2;\n continue;\n }\n if (ch === \"\\n\" && markdown[j + 1] === \"\\n\") {\n broken = true;\n break;\n }\n if (ch === \"[\") depth++;\n else if (ch === \"]\") depth--;\n j++;\n }\n if (broken || depth !== 0 || markdown[j] !== \"(\") {\n i = open + 1;\n continue;\n }\n const label = markdown.slice(open + 1, j - 1);\n let parenDepth = 1;\n let k = j + 1;\n while (k < markdown.length && parenDepth > 0) {\n const ch = markdown[k];\n if (ch === \"\\\\\") {\n k += 2;\n continue;\n }\n if (ch === \"\\n\") {\n broken = true;\n break;\n }\n if (ch === \"(\") parenDepth++;\n else if (ch === \")\") parenDepth--;\n k++;\n }\n if (broken || parenDepth !== 0) {\n i = open + 1;\n continue;\n }\n const start = isEmbed ? open - 1 : open;\n spans.push({\n full: markdown.slice(start, k),\n label,\n url: markdown.slice(j + 1, k - 1),\n isEmbed,\n });\n i = k;\n }\n return spans;\n}\n\n/** 라벨을 `![[경로|별칭]]` 별칭으로 안전하게 쓸 수 있는 평문으로 변환한다. */\nexport function toWikilinkAlias(label: string): string {\n return label\n .replace(/!?\\[([^\\]]*)\\]\\(([^)]*)\\)/g, \"$1\")\n .replace(/\\[\\[([^\\]|]+)(?:\\|([^\\]]+))?\\]\\]/g, (_m, t: string, d?: string) => d ?? t)\n .replace(/[\\r\\n]+/g, \" \")\n .replace(/\\]\\]/g, \")\")\n .replace(/\\|/g, \"-\")\n .trim();\n}\n\nconst INTERNAL_FILE_URL_RE = /^file:\\/\\/%7B.*%7D%7D$/;\nconst FILE_LABEL_PREFIX_RE = /^(?:📎|🎬|🎞|📄|🔊)\\s*/u;\n\nconst LOCAL_MARKER_RE = new RegExp(`${MARKER_BRAND_RE}:local-(?:image|file):([^\\\\s%]+)`, \"g\");\n\n/** pull 원문(이스케이프 포함 가능)에서 제자리 보존 마커의 대상 파일명 집합을 뽑는다(D6). */\nfunction collectLocalMarkerBasenames(markdown: string): Set<string> {\n const names = new Set<string>();\n const unescaped = markdown.replace(/\\\\/g, \"\");\n for (const m of unescaped.matchAll(LOCAL_MARKER_RE)) {\n names.add(baseName(m[1]!));\n }\n return names;\n}\n\nfunction baseName(path: string): string {\n return path.split(\"/\").pop() ?? path;\n}\n\nexport class ImageHandler {\n private readonly customFetch?: typeof globalThis.fetch;\n private readonly concurrency: number;\n private readonly maxRetries: number;\n private readonly retryBaseMs: number;\n private readonly maxFileSizeBytes: number;\n\n constructor(\n private readonly vaultFs: VaultFS,\n private readonly attachmentFolder: string = \"attachments\",\n private readonly notionClient?: NotionClient,\n customFetch?: typeof globalThis.fetch,\n options?: MediaOptions,\n private readonly stateDb?: IStateDB,\n ) {\n this.customFetch = customFetch;\n this.concurrency = options?.concurrency ?? 3;\n this.maxRetries = options?.maxRetries ?? 3;\n this.retryBaseMs = options?.retryBaseMs ?? 1000;\n this.maxFileSizeBytes = options?.maxFileSizeBytes ?? 100 * 1024 * 1024;\n }\n\n private get fetchFn(): typeof globalThis.fetch {\n return this.customFetch ?? globalThis.fetch;\n }\n\n async downloadImage(url: string, pageTitle: string): Promise<ImageDownloadResult> {\n return this.persistImage(await this.fetchImage(url, pageTitle));\n }\n\n private async fetchImage(url: string, pageTitle: string): Promise<FetchedImage> {\n const maxRetries = this.maxRetries;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n if (attempt > 0) {\n await new Promise((r) => setTimeout(r, this.retryBaseMs * attempt));\n getLogger().info(\n `[Im-Nobsidian] 이미지 다운로드 재시도 (${attempt + 1}/${maxRetries}): ${pageTitle}`,\n );\n }\n const response = await this.fetchFn(url);\n if (!response.ok) {\n throw new Error(`이미지 다운로드 실패: ${response.status} ${response.statusText}`);\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"image/png\";\n const extension = IMAGE_EXTENSIONS[contentType] ?? this.guessExtension(url) ?? \".png\";\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const fullHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n const hash = fullHash.slice(0, 12);\n const safeName = pageTitle\n .replace(/[^a-zA-Z0-9가-힣\\s-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .slice(0, 50);\n\n const fileName = `${safeName}-${hash}${extension}`;\n const localPath = `${this.attachmentFolder}/${fileName}`;\n\n return { originalUrl: url, localPath, hash, fullHash, buffer };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError!;\n }\n\n private async persistImage(fetched: FetchedImage): Promise<ImageDownloadResult> {\n await this.vaultFs.ensureFolder(this.attachmentFolder);\n await this.vaultFs.writeBinary(fetched.localPath, fetched.buffer);\n return {\n originalUrl: fetched.originalUrl,\n localPath: fetched.localPath,\n hash: fetched.hash,\n size: fetched.buffer.length,\n };\n }\n\n async downloadAllImages(\n markdown: string,\n pageTitle: string,\n pageId?: string,\n ): Promise<{ content: string; downloads: ImageDownloadResult[] }> {\n // F14: 캡션에 중첩 링크가 있으면 정규식이 URL 을 오인하므로 괄호 균형 스캔을 쓴다.\n const embeds = scanMarkdownLinks(markdown).filter((s) => s.isEmbed);\n const notionMatches = embeds.filter(\n (s) => /^https?:\\/\\//.test(s.url) && this.isNotionImageUrl(s.url),\n );\n const internalMatches = embeds.filter((s) => INTERNAL_FILE_URL_RE.test(s.url));\n\n if (notionMatches.length === 0 && internalMatches.length === 0) {\n return { content: markdown, downloads: [] };\n }\n\n // D6: push 는 본문 임베드 이미지를 quote+마커 쌍(제자리) + 페이지 끝 이미지 블록\n // (append)의 이중 표현으로 올린다. pull 에서 그 끝 블록을 그대로 받으면 노트 꼬리에\n // 중복 `![[attachments/...]]` 가 유입되므로, file_registry 해시(전체 sha256)와\n // 본문 마커의 파일명이 모두 일치하는 다운로드는 사본으로 판정해 라인째 버린다.\n const registryByHash = new Map<string, string[]>();\n if (pageId && this.stateDb) {\n for (const entry of this.stateDb.getFilesByPageId(pageId)) {\n const list = registryByHash.get(entry.fileHash) ?? [];\n list.push(entry.localPath);\n registryByHash.set(entry.fileHash, list);\n }\n }\n const markerBasenames = collectLocalMarkerBasenames(markdown);\n const isAppendedCopy = (fetched: FetchedImage): boolean => {\n const paths = registryByHash.get(fetched.fullHash);\n return paths !== undefined && paths.some((p) => markerBasenames.has(baseName(p)));\n };\n\n const sema = new Sema(this.concurrency);\n const downloads: ImageDownloadResult[] = [];\n let result = markdown;\n\n const httpResults = await Promise.allSettled(\n notionMatches.map(async (span) => {\n await sema.acquire();\n try {\n return {\n span,\n fetched: await this.fetchImage(span.url, pageTitle),\n };\n } finally {\n sema.release();\n }\n }),\n );\n\n for (const settled of httpResults) {\n if (settled.status !== \"fulfilled\") continue;\n const { span, fetched } = settled.value;\n if (isAppendedCopy(fetched)) {\n result = result.replace(span.full, \"\");\n continue;\n }\n const download = await this.persistImage(fetched);\n downloads.push(download);\n const alias = toWikilinkAlias(span.label);\n const obsidianEmbed = `![[${download.localPath}${alias ? `|${alias}` : \"\"}]]`;\n result = result.replace(span.full, obsidianEmbed);\n }\n\n for (const span of internalMatches) {\n await sema.acquire();\n try {\n const parsed = this.parseNotionFileUrl(span.url);\n if (!parsed || !this.notionClient) continue;\n\n const realUrl = await this.notionClient.getFileBlockUrl(parsed.blockId);\n if (!realUrl) {\n getLogger().warn(`[Im-Nobsidian] 이미지 Block URL 조회 실패: ${parsed.fileName}`);\n continue;\n }\n\n const fetched = await this.fetchImage(realUrl, pageTitle);\n if (isAppendedCopy(fetched)) {\n result = result.replace(span.full, \"\");\n continue;\n }\n const download = await this.persistImage(fetched);\n downloads.push(download);\n const alias = toWikilinkAlias(span.label);\n const obsidianEmbed = `![[${download.localPath}${alias ? `|${alias}` : \"\"}]]`;\n result = result.replace(span.full, obsidianEmbed);\n } catch (error) {\n getLogger().warn(`내부 이미지 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n return { content: result, downloads };\n }\n\n async uploadLocalImage(localPath: string, noteFolder?: string): Promise<ImageUploadResult> {\n if (!this.notionClient) {\n throw new Error(\"NotionClient required for image upload\");\n }\n\n const { buffer, resolvedPath } = await this.readImageFromVault(localPath, noteFolder);\n const filename = localPath.split(\"/\").pop() ?? \"image.png\";\n const contentType = this.getContentTypeFromPath(filename);\n const blob = new Blob([buffer], { type: contentType });\n const fileUploadId = await this.notionClient.uploadFile(blob, filename, contentType);\n // FileHandler.pushAllFiles 의 dedup 비교(전체 sha256)와 동일 산식으로 계산해 두 경로가\n // 같은 첨부를 동일 키로 인식하게 한다. localPath 도 해석된 실제 볼트 경로로 돌려줘야\n // 레지스트리 키가 폴더 스캔(pushAllFiles)의 file.path 와 일치해 중복 업로드가 차단된다.\n const fileHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n\n return { localPath: resolvedPath, fileUploadId, fileHash, fileSize: buffer.length };\n }\n\n async uploadAndAppendImages(\n pageId: string,\n images: ImageReference[],\n notePath?: string,\n ): Promise<ImageUploadResult[]> {\n if (!this.notionClient) return [];\n\n const localImages = images.filter((img) => !img.isExternal && img.localPath);\n if (localImages.length === 0) return [];\n\n const noteFolder = notePath?.includes(\"/\")\n ? notePath.slice(0, notePath.lastIndexOf(\"/\"))\n : undefined;\n const results: ImageUploadResult[] = [];\n const imageBlocks: unknown[] = [];\n\n for (const img of localImages) {\n try {\n const result = await this.uploadLocalImage(img.localPath!, noteFolder);\n results.push(result);\n imageBlocks.push({\n type: \"image\",\n image: {\n type: \"file_upload\",\n file_upload: { id: result.fileUploadId },\n },\n });\n } catch (error) {\n // 경로 미해석(ENOENT)은 예상 가능한 상황(폴더 스캔 업로드가 후속 처리) —\n // 스택트레이스 대신 한 줄 경고로 낮춘다(F23). 그 외 오류는 원본을 남긴다.\n if ((error as NodeJS.ErrnoException)?.code === \"ENOENT\") {\n getLogger().warn(`이미지 업로드 건너뜀 — 볼트에서 파일을 찾지 못함: ${img.localPath}`);\n } else {\n getLogger().warn(`이미지 업로드 실패 (${img.localPath}):`, error);\n }\n }\n }\n\n if (imageBlocks.length > 0) {\n await this.notionClient.appendChildren(pageId, imageBlocks);\n // 업로드 성공분을 file_registry 에 등록한다. 노트 임베드 이미지는 여기서(노트 페이지에)\n // 처리되므로, 이후 FileHandler.pushAllFiles 가 같은 첨부를 폴더 페이지에 standalone\n // 으로 재업로드하는 중복(I6 \"중복 업로드 0\" 위반)을 공유 레지스트리로 차단한다.\n // 단, replace_content(기본 push)는 노트 블록을 매번 wipe 하므로 임베드 이미지 블록은\n // 노트 본문이 바뀔 때마다 재업로드+재append 가 불가피하다(file_upload 1회용 + atomic\n // replace). 이는 블록 더블링/데이터 손실이 아니며, 무변경 재sync 는 변경감지가 스킵해\n // 재업로드 0 을 보장한다.\n if (this.stateDb) {\n for (const r of results) {\n try {\n this.stateDb.registerFile({\n localPath: r.localPath,\n notionPageId: pageId,\n fileUploadId: r.fileUploadId,\n fileType: \"image\",\n fileHash: r.fileHash,\n fileSize: r.fileSize,\n });\n } catch (error) {\n getLogger().warn(`이미지 레지스트리 등록 실패 (${r.localPath}):`, error);\n }\n }\n }\n }\n\n return results;\n }\n\n /**\n * 임베드 경로를 볼트 실제 파일로 해석한다(F23). Obsidian 위키링크 임베드는 노트 옆\n * 파일을 파일명만으로 참조하는 게 관례라, 노트 폴더 → 볼트 루트 → attachments/ 순으로\n * 시도한다. 폴백은 조용히 진행하고, 전부 실패했을 때만 마지막 오류를 던진다.\n */\n private async readImageFromVault(\n localPath: string,\n noteFolder?: string,\n ): Promise<{ buffer: Buffer; resolvedPath: string }> {\n const candidates: string[] = [];\n if (noteFolder && !localPath.includes(\"/\")) {\n candidates.push(`${noteFolder}/${localPath}`);\n }\n candidates.push(localPath, `${this.attachmentFolder}/${localPath}`);\n\n let lastError: unknown;\n for (const candidate of candidates) {\n try {\n return { buffer: await this.vaultFs.readBinary(candidate), resolvedPath: candidate };\n } catch (error) {\n lastError = error;\n }\n }\n throw lastError;\n }\n\n private getContentTypeFromPath(filename: string): string {\n const ext = filename.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n return (ext && EXTENSION_TO_MIME[ext]) ?? \"application/octet-stream\";\n }\n\n async downloadAllFiles(\n markdown: string,\n pageTitle: string,\n ): Promise<{ content: string; downloads: ImageDownloadResult[] }> {\n // F14: 캡션 중첩 링크 대응 — 괄호 균형 스캔 후 파일 라벨(이모지 프리픽스)만 취한다.\n const fileLinks = scanMarkdownLinks(markdown).filter(\n (s) => !s.isEmbed && FILE_LABEL_PREFIX_RE.test(s.label),\n );\n const notionHttpMatches = fileLinks.filter(\n (s) => /^https?:\\/\\//.test(s.url) && this.isNotionFileUrl(s.url),\n );\n const mdInternalMatches = fileLinks.filter((s) => INTERNAL_FILE_URL_RE.test(s.url));\n\n const xmlHttpRegex =\n /<(?:file|video|audio|pdf)\\s+src=\"(https?:\\/\\/[^\"]+)\">([\\s\\S]*?)<\\/(?:file|video|audio|pdf)>/g;\n const xmlHttpMatches = [...markdown.matchAll(xmlHttpRegex)];\n const notionXmlHttpMatches = xmlHttpMatches.filter((m) => m[1] && this.isNotionFileUrl(m[1]));\n\n const xmlInternalRegex =\n /<(?:file|video|audio|pdf)\\s+src=\"(file:\\/\\/%7B.*?%7D%7D)\">([\\s\\S]*?)<\\/(?:file|video|audio|pdf)>/g;\n const xmlInternalMatches = [...markdown.matchAll(xmlInternalRegex)];\n\n const totalMatches =\n notionHttpMatches.length +\n mdInternalMatches.length +\n notionXmlHttpMatches.length +\n xmlInternalMatches.length;\n\n if (totalMatches === 0) {\n return { content: markdown, downloads: [] };\n }\n\n const sema = new Sema(this.concurrency);\n const downloads: ImageDownloadResult[] = [];\n let result = markdown;\n\n for (const span of notionHttpMatches) {\n await sema.acquire();\n try {\n const caption = toWikilinkAlias(span.label.replace(FILE_LABEL_PREFIX_RE, \"\")) || \"file\";\n const download = await this.downloadFile(span.url, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n // F19: 다운로드한 미디어는 링크가 아니라 임베드(![[..]])로 복원해야 인라인 렌더된다.\n const obsidianLink = `![[${download.localPath}|${caption}]]`;\n result = result.replace(span.full, obsidianLink);\n } catch (error) {\n getLogger().warn(`파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n for (const span of mdInternalMatches) {\n await sema.acquire();\n try {\n const parsed = this.parseNotionFileUrl(span.url);\n if (!parsed || !this.notionClient) continue;\n\n const blockId = parsed.blockId;\n const fileName = parsed.fileName;\n const realUrl = await this.notionClient.getFileBlockUrl(blockId);\n if (!realUrl) continue;\n\n const caption =\n fileName || toWikilinkAlias(span.label.replace(FILE_LABEL_PREFIX_RE, \"\")) || \"file\";\n const download = await this.downloadFile(realUrl, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `![[${download.localPath}|${caption}]]`;\n result = result.replace(span.full, obsidianLink);\n } catch (error) {\n getLogger().warn(`내부 파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n for (const match of notionXmlHttpMatches) {\n await sema.acquire();\n try {\n const url = match[1]!;\n const caption = toWikilinkAlias(match[2] ?? \"\") || \"file\";\n const download = await this.downloadFile(url, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `![[${download.localPath}|${caption}]]`;\n result = result.replace(match[0]!, obsidianLink);\n } catch (error) {\n getLogger().warn(`파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n for (const match of xmlInternalMatches) {\n await sema.acquire();\n try {\n const fileUrl = match[1]!;\n const parsed = this.parseNotionFileUrl(fileUrl);\n if (!parsed || !this.notionClient) continue;\n\n const blockId = parsed.blockId;\n const fileName = parsed.fileName;\n const realUrl = await this.notionClient.getFileBlockUrl(blockId);\n if (!realUrl) continue;\n\n const caption = fileName || toWikilinkAlias(match[2] ?? \"\") || \"file\";\n const download = await this.downloadFile(realUrl, pageTitle, caption);\n if (!download.localPath) continue;\n downloads.push(download);\n const obsidianLink = `![[${download.localPath}|${caption}]]`;\n result = result.replace(match[0]!, obsidianLink);\n } catch (error) {\n getLogger().warn(`내부 파일 다운로드 실패: ${error}`);\n } finally {\n sema.release();\n }\n }\n\n return { content: result, downloads };\n }\n\n private parseNotionFileUrl(fileUrl: string): { blockId: string; fileName: string } | null {\n try {\n const decoded = decodeURIComponent(fileUrl.replace(\"file://\", \"\"));\n const json = JSON.parse(decoded) as {\n source?: string;\n permissionRecord?: { id?: string };\n };\n const blockId = json.permissionRecord?.id ?? \"\";\n const source = json.source ?? \"\";\n const fileNameMatch = source.match(/attachment:[^:]+:(.+)$/);\n const fileName = fileNameMatch ? decodeURIComponent(fileNameMatch[1]!) : \"\";\n return blockId ? { blockId, fileName } : null;\n } catch {\n return null;\n }\n }\n\n private async downloadFile(\n url: string,\n _pageTitle: string,\n caption: string,\n ): Promise<ImageDownloadResult> {\n const maxRetries = this.maxRetries;\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n try {\n if (attempt > 0) {\n await new Promise((r) => setTimeout(r, this.retryBaseMs * attempt));\n getLogger().info(\n `[Im-Nobsidian] 파일 다운로드 재시도 (${attempt + 1}/${maxRetries}): ${caption}`,\n );\n }\n const response = await this.fetchFn(url);\n if (!response.ok) {\n throw new Error(`파일 다운로드 실패: ${response.status} ${response.statusText}`);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n const MAX_FILE_SIZE = this.maxFileSizeBytes;\n if (contentLength && parseInt(contentLength, 10) > MAX_FILE_SIZE) {\n const sizeMB = Math.round(parseInt(contentLength, 10) / 1024 / 1024);\n getLogger().debug(`[Im-Nobsidian] 파일 스킵 — 너무 큼 (${sizeMB}MB): ${caption}`);\n return { originalUrl: url, localPath: \"\", hash: \"\", size: 0 };\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\").slice(0, 12);\n\n const extension = this.guessFileExtension(url, response.headers.get(\"content-type\"));\n const safeName = caption\n .replace(/[^a-zA-Z0-9가-힣\\s._-]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .slice(0, 80);\n const fileName = `${safeName}-${hash}${extension}`;\n const localPath = `${this.attachmentFolder}/${fileName}`;\n\n await this.vaultFs.ensureFolder(this.attachmentFolder);\n await this.vaultFs.writeBinary(localPath, buffer);\n\n return { originalUrl: url, localPath, hash, size: buffer.length };\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n }\n }\n throw lastError!;\n }\n\n private isNotionImageUrl(url: string): boolean {\n return this.isNotionFileUrl(url);\n }\n\n private isNotionFileUrl(url: string): boolean {\n return (\n url.includes(\"secure.notion-static.com\") ||\n url.includes(\"prod-files-secure\") ||\n url.includes(\"s3.us-west-2.amazonaws.com/secure.notion-static.com\")\n );\n }\n\n private guessExtension(url: string): string | null {\n const pathname = new URL(url).pathname;\n const ext = pathname.match(/\\.(png|jpg|jpeg|gif|webp|svg|bmp|tiff)(\\?|$)/i);\n return ext ? `.${ext[1]!.toLowerCase()}` : null;\n }\n\n private guessFileExtension(url: string, contentType: string | null): string {\n try {\n const pathname = new URL(url).pathname;\n const extMatch = pathname.match(/\\.([a-zA-Z0-9]{1,10})(?:\\?|$)/);\n if (extMatch) return `.${extMatch[1]!.toLowerCase()}`;\n } catch {\n // URL 파싱 실패 시 MIME 타입으로 폴백\n }\n\n const mimeMap: Record<string, string> = {\n \"application/pdf\": \".pdf\",\n \"application/zip\": \".zip\",\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\": \".xlsx\",\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\": \".pptx\",\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\": \".docx\",\n \"application/x-hwp\": \".hwp\",\n \"application/gzip\": \".gz\",\n };\n if (contentType && mimeMap[contentType]) return mimeMap[contentType]!;\n return \"\";\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { Sema } from \"async-sema\";\nimport type { VaultFS, NonMdFileInfo } from \"./vault-fs.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport { getLogger } from \"../utils/logger.js\";\n\nexport type NotionBlockType = \"image\" | \"pdf\" | \"video\" | \"audio\" | \"file\";\n\nexport interface FileUploadResult {\n readonly localPath: string;\n readonly fileUploadId: string;\n readonly blockType: NotionBlockType;\n}\n\nexport interface FileDownloadResult {\n readonly url: string;\n readonly localPath: string;\n readonly hash: string;\n readonly size: number;\n}\n\nconst EXTENSION_TO_BLOCK_TYPE: Record<string, NotionBlockType> = {\n \".png\": \"image\",\n \".jpg\": \"image\",\n \".jpeg\": \"image\",\n \".gif\": \"image\",\n \".svg\": \"image\",\n \".webp\": \"image\",\n \".ico\": \"image\",\n \".bmp\": \"image\",\n \".tiff\": \"image\",\n \".tif\": \"image\",\n \".avif\": \"image\",\n \".apng\": \"image\",\n \".heic\": \"image\",\n\n \".pdf\": \"pdf\",\n\n \".mp4\": \"video\",\n \".mov\": \"video\",\n \".webm\": \"video\",\n \".avi\": \"video\",\n \".mkv\": \"video\",\n \".flv\": \"video\",\n \".wmv\": \"video\",\n \".m4v\": \"video\",\n \".mpeg\": \"video\",\n \".ogv\": \"video\",\n \".3gp\": \"video\",\n\n \".mp3\": \"audio\",\n \".wav\": \"audio\",\n \".ogg\": \"audio\",\n \".m4a\": \"audio\",\n \".flac\": \"audio\",\n \".aac\": \"audio\",\n \".wma\": \"audio\",\n \".opus\": \"audio\",\n \".weba\": \"audio\",\n};\n\nconst EXTENSION_TO_MIME: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".svg\": \"image/svg+xml\",\n \".bmp\": \"image/bmp\",\n \".ico\": \"image/x-icon\",\n \".tiff\": \"image/tiff\",\n \".tif\": \"image/tiff\",\n \".avif\": \"image/avif\",\n \".heic\": \"image/heic\",\n \".pdf\": \"application/pdf\",\n \".mp4\": \"video/mp4\",\n \".mov\": \"video/quicktime\",\n \".webm\": \"video/webm\",\n \".avi\": \"video/x-msvideo\",\n \".mkv\": \"video/x-matroska\",\n \".mp3\": \"audio/mpeg\",\n \".wav\": \"audio/wav\",\n \".ogg\": \"audio/ogg\",\n \".m4a\": \"audio/mp4\",\n \".flac\": \"audio/flac\",\n \".aac\": \"audio/aac\",\n \".docx\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n \".xlsx\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n \".pptx\": \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n \".zip\": \"application/zip\",\n \".gz\": \"application/gzip\",\n \".tar\": \"application/x-tar\",\n \".rar\": \"application/vnd.rar\",\n \".7z\": \"application/x-7z-compressed\",\n \".py\": \"text/x-python\",\n \".js\": \"text/javascript\",\n \".ts\": \"text/typescript\",\n \".json\": \"application/json\",\n \".csv\": \"text/csv\",\n \".txt\": \"text/plain\",\n \".html\": \"text/html\",\n \".xml\": \"application/xml\",\n \".hwp\": \"application/x-hwp\",\n \".xls\": \"application/vnd.ms-excel\",\n \".doc\": \"application/msword\",\n \".ppt\": \"application/vnd.ms-powerpoint\",\n};\n\nexport function getBlockType(filename: string): NotionBlockType {\n const ext = filename.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n if (!ext) return \"file\";\n return EXTENSION_TO_BLOCK_TYPE[ext] ?? \"file\";\n}\n\nexport function getMimeType(filename: string): string {\n const ext = filename.match(/\\.[^.]+$/)?.[0]?.toLowerCase();\n if (!ext) return \"application/octet-stream\";\n return EXTENSION_TO_MIME[ext] ?? \"application/octet-stream\";\n}\n\nfunction getFolderPath(filePath: string): string {\n const parts = filePath.split(\"/\");\n return parts.length > 1 ? parts.slice(0, -1).join(\"/\") : \"\";\n}\n\nexport class FileHandler {\n private readonly sema: Sema;\n\n constructor(\n private readonly vaultFs: VaultFS,\n private readonly notionClient: NotionClient,\n private readonly stateDb: IStateDB,\n concurrency: number = 2,\n ) {\n this.sema = new Sema(concurrency);\n }\n\n async pushFilesForFolder(folderPageId: string, folderPath: string): Promise<FileUploadResult[]> {\n const allFiles = await this.vaultFs.listNonMarkdownFiles();\n const folderFiles = allFiles.filter((f) => getFolderPath(f.path) === folderPath);\n\n if (folderFiles.length === 0) return [];\n\n const results: FileUploadResult[] = [];\n\n for (const file of folderFiles) {\n const existing = this.stateDb.getFileRegistry(file.path);\n if (existing) {\n if (existing.fileSize === file.size) continue;\n const buffer = await this.vaultFs.readBinary(file.path);\n const currentHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n if (existing.fileHash === currentHash) continue;\n }\n\n await this.sema.acquire();\n try {\n const result = await this.uploadFile(file, folderPageId);\n if (result) results.push(result);\n } catch (error) {\n getLogger().warn(`파일 업로드 실패 (${file.path}):`, error);\n } finally {\n this.sema.release();\n }\n }\n\n return results;\n }\n\n async pushAllFiles(): Promise<FileUploadResult[]> {\n const allFiles = await this.vaultFs.listNonMarkdownFiles();\n if (allFiles.length === 0) return [];\n\n const filesByFolder = new Map<string, NonMdFileInfo[]>();\n for (const file of allFiles) {\n const folder = getFolderPath(file.path);\n const list = filesByFolder.get(folder) ?? [];\n list.push(file);\n filesByFolder.set(folder, list);\n }\n\n const results: FileUploadResult[] = [];\n\n for (const [folderPath, files] of filesByFolder) {\n const folderRecord = folderPath\n ? this.stateDb.getByPath(folderPath)\n : this.stateDb.getByPath(\"__root__\");\n\n const folderPageId = folderRecord?.notionPageId;\n if (!folderPageId) {\n if (files.length > 0) {\n getLogger().debug(\n `폴더 페이지 없음, 파일 스킵: ${folderPath || \"(루트)\"} (${files.length}개)`,\n );\n }\n continue;\n }\n\n for (const file of files) {\n const existing = this.stateDb.getFileRegistry(file.path);\n if (existing) {\n if (existing.fileSize === file.size) continue;\n const buffer = await this.vaultFs.readBinary(file.path);\n const currentHash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n if (existing.fileHash === currentHash) continue;\n }\n\n await this.sema.acquire();\n try {\n const result = await this.uploadFile(file, folderPageId);\n if (result) results.push(result);\n } catch (error) {\n getLogger().warn(`파일 업로드 실패 (${file.path}):`, error);\n } finally {\n this.sema.release();\n }\n }\n }\n\n return results;\n }\n\n async downloadFileBlock(\n url: string,\n filename: string,\n targetFolder: string,\n ): Promise<FileDownloadResult> {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`파일 다운로드 실패: ${response.status} ${response.statusText}`);\n }\n\n const buffer = Buffer.from(await response.arrayBuffer());\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n const localPath = targetFolder ? `${targetFolder}/${filename}` : filename;\n\n await this.vaultFs.ensureFolder(targetFolder || \".\");\n await this.vaultFs.writeBinary(localPath, buffer);\n\n return { url, localPath, hash, size: buffer.length };\n }\n\n async downloadFileBlocks(\n blocks: Array<{ type: string; url: string; caption?: string }>,\n targetFolder: string,\n ): Promise<FileDownloadResult[]> {\n const results: FileDownloadResult[] = [];\n\n for (const block of blocks) {\n const filename = this.extractFilename(block.url, block.caption);\n if (this.stateDb.isFileRegistered(`${targetFolder}/${filename}`)) continue;\n\n await this.sema.acquire();\n try {\n const result = await this.downloadFileBlock(block.url, filename, targetFolder);\n results.push(result);\n } catch (error) {\n getLogger().warn(`파일 다운로드 실패 (${block.url}):`, error);\n } finally {\n this.sema.release();\n }\n }\n\n return results;\n }\n\n private async uploadFile(\n file: NonMdFileInfo,\n parentPageId: string,\n ): Promise<FileUploadResult | null> {\n const buffer = await this.vaultFs.readBinary(file.path);\n const filename = file.path.split(\"/\").pop() ?? \"file\";\n const contentType = getMimeType(filename);\n const blockType = getBlockType(filename);\n const hash = createHash(\"sha256\").update(buffer).digest(\"hex\");\n\n const blob = new Blob([buffer], { type: contentType });\n const fileUploadId = await this.notionClient.uploadFile(blob, filename, contentType);\n\n const block = this.createFileBlock(blockType, fileUploadId);\n await this.notionClient.appendChildren(parentPageId, [block]);\n\n this.stateDb.registerFile({\n localPath: file.path,\n notionPageId: parentPageId,\n fileUploadId,\n fileType: blockType,\n fileHash: hash,\n fileSize: file.size,\n });\n\n getLogger().info(`파일 업로드 완료: ${file.path} → ${blockType} 블록`);\n\n return { localPath: file.path, fileUploadId, blockType };\n }\n\n private createFileBlock(blockType: NotionBlockType, fileUploadId: string): unknown {\n const fileRef = {\n type: \"file_upload\" as const,\n file_upload: { id: fileUploadId },\n };\n\n switch (blockType) {\n case \"image\":\n return { type: \"image\", image: fileRef };\n case \"pdf\":\n return { type: \"pdf\", pdf: fileRef };\n case \"video\":\n return { type: \"video\", video: fileRef };\n case \"audio\":\n return { type: \"audio\", audio: fileRef };\n case \"file\":\n default:\n return { type: \"file\", file: fileRef };\n }\n }\n\n private extractFilename(url: string, caption?: string): string {\n if (caption) {\n const safe = caption.replace(/[^a-zA-Z0-9가-힣._\\s-]/g, \"\").trim();\n if (safe) return safe;\n }\n\n try {\n const pathname = new URL(url).pathname;\n const segments = pathname.split(\"/\");\n const last = segments[segments.length - 1];\n if (last && last.includes(\".\")) return decodeURIComponent(last);\n } catch {\n // fallback\n }\n\n const ext = url.match(/\\.(png|jpg|jpeg|gif|pdf|mp4|mp3|docx|xlsx|zip|webp)(\\?|$)/i);\n return `file-${Date.now()}${ext ? `.${ext[1]}` : \"\"}`;\n }\n}\n","import type { Conflict, ConflictStrategy, RemoteChange, SyncRecord } from \"../types/sync.js\";\nimport { computeHash } from \"../utils/hash.js\";\n\n/**\n * Pull 충돌 해소 시 취할 동작.\n * - `write`: 로컬을 리모트 내용으로 덮어쓴다 (로컬 미수정 또는 remote-first).\n * - `skip`: 로컬을 보존하고 리모트 내용을 버린다 (local-first).\n * - `conflict`: 양쪽 모두 수정됨 → 사용자 해소 대기 (manual/duplicate).\n */\nexport type PullConflictAction = \"write\" | \"skip\" | \"conflict\";\n\nexport interface PullConflictInput {\n /** 동기화 상태 레코드 (마지막 동기화 시점 해시·스냅샷 포함). */\n readonly record: SyncRecord;\n /** 디스크의 현재 로컬 내용 (파일 없으면 \"\"). */\n readonly localContent: string;\n /** Notion에서 가져와 변환한 리모트 내용. */\n readonly remoteContent: string;\n /** 충돌 객체 구성용 리모트 변경 메타. */\n readonly remoteChange: RemoteChange;\n /** 설정된 충돌 해소 전략. */\n readonly strategy: ConflictStrategy;\n}\n\nexport interface PullConflictResult {\n readonly action: PullConflictAction;\n /** action === \"conflict\" 일 때만 채워진다. */\n readonly conflict?: Conflict;\n /** 호출자가 재계산하지 않도록 제공하는 로컬 내용 해시. */\n readonly localHash: string;\n}\n\n/**\n * Pull 시 로컬 수정 여부를 판정하고 충돌 전략에 따라 동작을 결정하는 순수 함수.\n *\n * 마지막 동기화 이후 로컬이 수정되었는지(`localHash !== record.contentHash`)를 기준으로,\n * 수정되지 않았으면 안전하게 덮어쓰고, 수정되었으면 전략에 따라 보존/덮어쓰기/충돌을 반환한다.\n * 이 함수는 어떤 I/O도 수행하지 않으므로 orchestrator(일반 페이지)와 database-syncer(DB 행)가\n * 동일한 충돌 판정 로직을 공유한다.\n */\nexport function resolvePullConflict(input: PullConflictInput): PullConflictResult {\n const { record, localContent, remoteContent, remoteChange, strategy } = input;\n\n const localHash = computeHash(localContent);\n const localModified = localHash !== record.contentHash;\n\n // 로컬이 마지막 동기화 이후 변경되지 않았다면 충돌 없이 덮어쓰기 안전.\n if (!localModified) {\n return { action: \"write\", localHash };\n }\n\n // 로컬이 수정됨 → 전략에 따라 분기.\n if (strategy === \"remote-first\") {\n return { action: \"write\", localHash };\n }\n if (strategy === \"local-first\") {\n return { action: \"skip\", localHash };\n }\n\n // --- manual / duplicate: 충돌로 넘기기 전에 \"거짓 충돌\"부터 걸러낸다 ---\n\n // 양쪽 내용이 이미 동일하면 충돌이 아니다(동일 편집으로 수렴). 덮어써도 무손실이고\n // 상태를 synced 로 정리하므로 write 로 처리한다.\n if (localContent === remoteContent) {\n return { action: \"write\", localHash };\n }\n\n // 리모트 내용이 base(마지막 동기화 스냅샷)와 같으면 리모트는 실제로 변하지 않은 것이다.\n // (notion last_edited 만 갱신된 가짜 변경.) 로컬만 바뀌었으므로 로컬을 보존(skip)한다.\n // 이때 write 로 덮어쓰면 로컬의 새 편집이 옛 내용으로 사라진다 — 반드시 skip.\n const baseContent = record.baseSnapshot?.toString(\"utf-8\") ?? null;\n if (baseContent !== null && remoteContent === baseContent) {\n return { action: \"skip\", localHash };\n }\n\n // manual / duplicate → 충돌로 보존, 사용자 해소 대기.\n const conflict: Conflict = {\n syncRecord: record,\n localChange: {\n path: record.obsidianPath,\n type: \"modified\",\n currentHash: localHash,\n previousHash: record.contentHash,\n },\n remoteChange,\n baseContent,\n localContent,\n remoteContent,\n };\n\n return { action: \"conflict\", conflict, localHash };\n}\n","// eslint-disable-next-line no-control-regex\nconst INVALID_CHARS = /[<>:\"/\\\\|?*\\x00-\\x1f]/g;\n// 파일시스템상으로는 유효하지만 Obsidian 위키링크 문법(`[[제목]]`)을 깨는 문자(대괄호).\n// basename 에 `[`/`]` 가 남으면 그 basename 으로 만든 `[[..]]` 가 첫 `]]` 에서 조기 종료돼\n// 링크가 깨진다(예: 제목 \"Attention [2017]\" → `[[Attention [2017]]]`). 파일명 SSOT 인 이\n// 함수에서 한 번 봉합하면 단일 변환·후처리·relation 경로가 모두 안전해진다(M5). 파일시스템\n// 무효 문자(INVALID_CHARS)와는 관심사가 다르므로 상수를 분리한다. 별칭 구분자 `|` 는 이미\n// INVALID_CHARS 가 처리한다.\nconst WIKILINK_UNSAFE_CHARS = /[[\\]]/g;\nconst TRAILING_DOTS = /\\.+$/;\nconst RESERVED_NAMES = new Set([\n \"CON\",\n \"PRN\",\n \"AUX\",\n \"NUL\",\n \"COM1\",\n \"COM2\",\n \"COM3\",\n \"COM4\",\n \"COM5\",\n \"COM6\",\n \"COM7\",\n \"COM8\",\n \"COM9\",\n \"LPT1\",\n \"LPT2\",\n \"LPT3\",\n \"LPT4\",\n \"LPT5\",\n \"LPT6\",\n \"LPT7\",\n \"LPT8\",\n \"LPT9\",\n]);\n\nexport function sanitizeFileName(name: string): string {\n let sanitized = name\n .replace(INVALID_CHARS, \"_\")\n .replace(WIKILINK_UNSAFE_CHARS, \"_\")\n .replace(TRAILING_DOTS, \"\")\n .trim()\n .slice(0, 200);\n\n if (RESERVED_NAMES.has(sanitized.toUpperCase())) {\n sanitized = `_${sanitized}`;\n }\n\n if (sanitized.length === 0) {\n sanitized = \"_untitled\";\n }\n\n return sanitized;\n}\n","import { notionIdsEqual } from \"./id.js\";\n\n/** {@link resolveDbRowPath} 가 경로 점유 여부를 조회하기 위한 최소 레코드 형태. */\nexport interface PathOwner {\n notionPageId: string | null;\n}\n\n/** {@link selectDbRowFiles} 입력의 최소 형태(경로만 필요). */\nexport interface VaultPathRef {\n readonly path: string;\n}\n\n/**\n * DB 폴더의 **직속(depth 1)** 행 파일만 고른다 — 중첩 하위 폴더는 제외한다.\n *\n * DB 행은 항상 `localFolder/<name>.md` 로 **평탄하게** 기록된다({@link resolveDbRowPath}).\n * 하위 폴더(`localFolder/SubDB/...`)는 **별도 child_database** 이거나 자식 페이지 본문이라\n * 부모 DB 의 행이 아니다. `path.startsWith(prefix)` 단순 매칭은 이 중첩 파일까지 부모 행으로\n * **오포함(over-inclusion)** 한다:\n * - 뷰(I9): 하위 DB 의 행이 부모 갤러리/테이블/보드에 카드로 새어 든다.\n * - push: 하위 DB 행을 부모 DB 로 잘못 밀어 중복 생성·오배치를 낸다.\n * `selectStaleDbArtifacts` 와 동일한 \"직속만 — 중첩 DB 보호\" 규칙(`rel` 에 `/` 없음)을 적용한다.\n * 폴더 경계도 정확히 본다: `localFolder` 가 `databases/tasks` 면 형제 폴더\n * `databases/tasks2/x.md` 는 `databases/tasks/` prefix 에 걸리지 않아 자연히 제외된다.\n *\n * 입력은 이미 마크다운으로 필터된 목록을 가정한다(확장자 재검증 안 함). 결정적: 입력 순서\n * 보존, 부수효과 없음.\n *\n * @param files 볼트의 마크다운 파일 참조 목록(경로 기준)\n * @param localFolder DB 폴더 경로(확장자·후행 슬래시 무관)\n */\nexport function selectDbRowFiles<T extends VaultPathRef>(\n files: ReadonlyArray<T>,\n localFolder: string,\n): T[] {\n const prefix = localFolder.endsWith(\"/\") ? localFolder : `${localFolder}/`;\n return files.filter((file) => {\n if (!file.path.startsWith(prefix)) return false;\n const rel = file.path.slice(prefix.length);\n return rel.length > 0 && !rel.includes(\"/\");\n });\n}\n\n/**\n * DB 행 파일 경로를 충돌 없이 결정한다.\n *\n * 같은 DB 에 동명 페이지(예: 제목이 비어 \"제목 없음\" 으로 수렴하는 행들)가 여럿\n * 있으면 Notion 페이지 ID 조각으로 디스앰비규에이션한다. 단 ID 앞 8 글자는 같은\n * DB 안에서 **유일하지 않다** — 노션 페이지 ID 는 생성 시각 기반이라 앞자리가\n * 비랜덤이어서, 같은 DB 의 두 동명 페이지가 같은 8 글자 prefix 를 갖는 일이 흔하다.\n * 단일 8 글자 접미사만 쓰면 두 페이지가 **동일 경로**로 귀결되어\n * ① 한 페이지가 다른 페이지의 파일을 덮어써 데이터가 유실되고\n * ② 매 pull 마다 두 페이지가 같은 파일을 두고 핑퐁하여 멱등성(churn 0)이 깨진다.\n *\n * 따라서 후보 경로가 *다른* 페이지에 이미 점유되어 있으면 ID 조각을 8→16→32 로\n * 넓혀 유일 경로를 찾는다. 두 페이지의 ID 는 불변이므로 항상 같은 경로로 수렴 →\n * 한 번 배정된 뒤에는 sync_state 에 경로가 고정되어(다음 pull 은 기존 레코드 경로\n * 재사용) churn 이 발생하지 않는다.\n *\n * @param localFolder DB 폴더 경로 (확장자·슬래시 없는 디렉터리)\n * @param safeName sanitize 된 파일명(확장자 제외)\n * @param pageId 대상 Notion 페이지 ID (하이픈 유무 무관)\n * @param lookupByPath 후보 경로의 현재 소유 레코드를 돌려주는 조회 함수(없으면 null)\n */\nexport function resolveDbRowPath(\n localFolder: string,\n safeName: string,\n pageId: string,\n lookupByPath: (path: string) => PathOwner | null,\n): string {\n const ownedBySelf = (candidate: string): boolean => {\n const owner = lookupByPath(candidate);\n // 점유자가 없으면 비어 있는 경로 → 사용 가능.\n // 점유자의 ID 가 비어 있으면(레코드 손상 등) 자기 소유로 단정하지 않고 회피한다.\n if (!owner) return true;\n return owner.notionPageId != null && notionIdsEqual(owner.notionPageId, pageId);\n };\n\n const natural = `${localFolder}/${safeName}.md`;\n if (ownedBySelf(natural)) return natural;\n\n const raw = pageId.replace(/-/g, \"\");\n for (const len of [8, 16, 32]) {\n const candidate = `${localFolder}/${safeName} (${raw.slice(0, len)}).md`;\n if (ownedBySelf(candidate)) return candidate;\n }\n\n // 전체 ID(32 글자)는 전역 유일하므로 위 루프에서 반드시 반환된다.\n // 도달 불가 경로이나 방어적으로 전체 ID 접미사를 반환한다.\n return `${localFolder}/${safeName} (${raw}).md`;\n}\n","/**\n * Obsidian 위키링크가 실제로 해소하는 대상 이름(파일 basename, `.md` 제거)을 경로에서 도출한다.\n *\n * 변환 단일 패스(`resolvePageId` 로 페이지 멘션→`[[제목]]`)와 후처리 패스\n * (`resolveNotionLinks` 의 본문 링크·frontmatter relation 해소)가 **동일한 규칙**으로\n * 위키링크 텍스트를 만들도록 강제하는 SSOT.\n *\n * 과거엔 단일 패스가 StateDB 의 원시 제목(`.title`)을, 후처리 패스가 sanitize 된\n * basename 을 써서 같은 페이지가 서로 다른 `[[..]]` 텍스트로 해소됐다 — 원시 제목에\n * 슬래시·콜론 등 파일명 금지문자가 있으면 단일 패스 링크가 실제 파일을 못 가리키는\n * 깨진/이중 위키링크가 됐다(M4). 두 경로 모두 이 함수를 통과시켜 불일치를 차단한다.\n */\nexport function wikilinkTitleFromPath(obsidianPath: string): string {\n return obsidianPath.replace(/\\.md$/i, \"\").split(\"/\").pop() ?? \"\";\n}\n","import type { DatabaseViewsConfig, ViewConfig } from \"../types/view.js\";\n\nexport interface BasePropertySchema {\n readonly id: string;\n readonly type: string;\n readonly options?: Array<{ name: string; color?: string }>;\n readonly groups?: Array<{ name: string; color?: string; optionIds?: string[] }>;\n}\n\nexport interface BaseFileOptions {\n readonly databaseId: string;\n readonly databaseName: string;\n readonly schema: Record<string, BasePropertySchema>;\n readonly viewsConfig: DatabaseViewsConfig;\n readonly folderPath: string;\n}\n\nexport type BasesViewType = \"table\" | \"cards\" | \"list\";\n\n/**\n * Notion 뷰 타입 → Obsidian Bases 뷰 타입 매핑(SSOT).\n *\n * `null` = Bases 에 대응 뷰가 없어 `.base` 로 표현 불가. 이 경우 해당 뷰는 `.base` 에서\n * 누락되므로, 사이드카(`<db>.notion.json`)가 원본 뷰 설정을 무손실 보존한다.\n * 뷰는 현재 pull-authoritative — Notion API 가 2026-03-19 뷰 생성/수정/삭제를 열었지만\n * 본 프로젝트는 아직 뷰 write-back 을 구현하지 않았다(로드맵 항목). push 로 되돌릴 수\n * 없는 동안 \"조용한 유실 금지\"는 곧 \"보존 + 정직한 degrade 리포트\"를 의미한다.\n */\nexport const NOTION_TO_BASES_VIEW: Record<string, BasesViewType | null> = {\n table: \"table\",\n gallery: \"cards\",\n list: \"list\",\n board: \"cards\",\n calendar: null,\n timeline: null,\n form: null,\n chart: null,\n map: null,\n dashboard: null,\n};\n\n/** Notion 뷰 타입의 Bases 대응 타입을 돌려준다. 미지원/미상 타입은 `null`. */\nexport function basesViewTypeOf(notionType: string): BasesViewType | null {\n return NOTION_TO_BASES_VIEW[notionType] ?? null;\n}\n\nexport class BaseFileGenerator {\n generate(options: BaseFileOptions): string {\n const lines: string[] = [];\n\n lines.push(`# Auto-generated by Im-Nobsidian from Notion DB: ${options.databaseName}`);\n lines.push(`# Database ID: ${options.databaseId}`);\n lines.push(\"\");\n\n this.writeFilters(lines, options.folderPath);\n this.writeFormulas(lines, options.viewsConfig.views);\n this.writePropertyDisplayNames(lines, options.schema);\n this.writeViews(lines, options.viewsConfig.views, options.schema);\n\n // YAML 파일은 말미 개행으로 끝낸다(POSIX 텍스트 관례·diff 안정성).\n return lines.join(\"\\n\") + \"\\n\";\n }\n\n private writeFilters(lines: string[], folderPath: string): void {\n lines.push(\"filters:\");\n lines.push(\" and:\");\n lines.push(` - file.inFolder(\"${folderPath}\")`);\n // `.base` 파일 자신도 폴더에 있어 카드로 잡히므로(빈 카드) markdown 노트만 남긴다.\n lines.push(` - file.ext == \"md\"`);\n lines.push(\"\");\n }\n\n private needsContentCoverFormula(views: ViewConfig[]): boolean {\n return views.some(\n (v) =>\n v.type === \"gallery\" &&\n v.cover &&\n (v.cover.type === \"page_content\" || v.cover.type === \"page_content_first\"),\n );\n }\n\n private writeFormulas(lines: string[], views: ViewConfig[]): void {\n if (!this.needsContentCoverFormula(views)) return;\n\n lines.push(\"formulas:\");\n lines.push(\" coverImage: file.embeds[0]\");\n lines.push(\"\");\n }\n\n private writePropertyDisplayNames(\n lines: string[],\n schema: Record<string, BasePropertySchema>,\n ): void {\n const entries = Object.entries(schema).filter(([, prop]) => prop.type !== \"title\");\n if (entries.length === 0) return;\n\n lines.push(\"properties:\");\n for (const [name] of entries) {\n lines.push(` ${this.yamlKey(name)}:`);\n lines.push(` displayName: ${this.yamlValue(name)}`);\n }\n lines.push(\"\");\n }\n\n private writeViews(\n lines: string[],\n views: ViewConfig[],\n schema: Record<string, BasePropertySchema>,\n ): void {\n const basesViews = views\n .map((v) => this.convertView(v, schema))\n .filter((v): v is NonNullable<typeof v> => v !== null);\n\n if (basesViews.length === 0) {\n lines.push(\"views:\");\n lines.push(\" - type: table\");\n lines.push(\" name: Table\");\n return;\n }\n\n // Obsidian Bases 는 뷰 이름 유일성을 요구한다. Notion 은 이름 없는 뷰를 'Untitled'로\n // 반환하므로(동명 다수 발생) 중복 시 ' 2','3'… 접미사로 유일화한다. 미적용 시 Bases 가\n // 동명 뷰를 하나로 합치거나 무시해 갤러리·표 뷰가 사라진다.\n this.dedupeViewNames(basesViews);\n\n lines.push(\"views:\");\n for (const view of basesViews) {\n lines.push(` - type: ${view.type}`);\n lines.push(` name: ${this.yamlValue(view.name)}`);\n\n if (view.order && view.order.length > 0) {\n lines.push(\" order:\");\n for (const col of view.order) {\n lines.push(` - ${this.propRef(col)}`);\n }\n }\n\n if (view.sort && view.sort.length > 0) {\n lines.push(\" sort:\");\n for (const s of view.sort) {\n // Bases 정렬 항목의 키는 `property`다(`column` 아님 — Obsidian이 무시함).\n lines.push(` - property: ${this.propRef(s.property)}`);\n lines.push(` direction: ${s.direction}`);\n }\n }\n\n if (view.groupBy) {\n lines.push(\" groupBy:\");\n lines.push(` property: ${this.propRef(view.groupBy.property)}`);\n if (view.groupBy.direction) {\n lines.push(` direction: ${view.groupBy.direction}`);\n }\n }\n\n if (view.image) {\n lines.push(` image: ${this.propRef(view.image)}`);\n }\n }\n }\n\n /**\n * 뷰 이름을 Bases 요구사항대로 유일화한다(in-place). 동명 충돌 시 ' 2',' 3'… 를 붙이되\n * 이미 존재하는 이름과 다시 충돌하지 않을 때까지 증가시킨다.\n */\n private dedupeViewNames(views: Array<{ name: string }>): void {\n const used = new Set<string>();\n for (const v of views) {\n let name = v.name;\n if (used.has(name)) {\n let n = 2;\n while (used.has(`${v.name} ${n}`)) n++;\n name = `${v.name} ${n}`;\n }\n used.add(name);\n v.name = name;\n }\n }\n\n private convertView(\n view: ViewConfig,\n schema: Record<string, BasePropertySchema>,\n ): {\n type: BasesViewType;\n name: string;\n order?: string[];\n sort?: Array<{ property: string; direction: string }>;\n groupBy?: { property: string; direction?: string };\n image?: string;\n } | null {\n const basesType = NOTION_TO_BASES_VIEW[view.type];\n if (!basesType) return null;\n\n const result: {\n type: BasesViewType;\n name: string;\n order?: string[];\n sort?: Array<{ property: string; direction: string }>;\n groupBy?: { property: string; direction?: string };\n image?: string;\n } = {\n type: basesType,\n name: view.name || view.type,\n };\n\n if (view.properties && view.properties.length > 0) {\n const visible = view.properties\n .filter((p) => p.visible !== false)\n .map((p) => {\n const name = p.propertyName ?? this.resolvePropertyName(p.propertyId, schema);\n if (!name) return null;\n // title 타입 속성은 카드/표 제목(file.name)과 중복되고, 프론트매터엔\n // title 키가 없어(본문 H1·파일명으로 보존) 빈 컬럼으로 표시되므로 제외한다.\n if (schema[name]?.type === \"title\") return null;\n return this.toNoteRef(name);\n })\n .filter((name): name is string => !!name);\n\n if (visible.length > 0) {\n result.order = [\"file.name\", ...visible];\n }\n }\n\n if (view.sorts && view.sorts.length > 0) {\n result.sort = view.sorts\n .map((s) => {\n let property: string;\n if (s.property) {\n const propName = this.resolvePropertyName(s.property, schema) ?? s.property;\n property = this.toNoteRef(propName);\n } else if (s.timestamp) {\n property = s.timestamp === \"created_time\" ? \"file.ctime\" : \"file.mtime\";\n } else {\n return null;\n }\n return {\n property,\n direction: s.direction === \"ascending\" ? \"ASC\" : \"DESC\",\n };\n })\n .filter((s): s is NonNullable<typeof s> => s !== null);\n }\n\n if (view.groupBy) {\n const propName =\n view.groupBy.propertyName ?? this.resolvePropertyName(view.groupBy.propertyId, schema);\n if (propName) {\n result.groupBy = {\n property: this.toNoteRef(propName),\n direction:\n view.groupBy.sort === \"ascending\"\n ? \"ASC\"\n : view.groupBy.sort === \"descending\"\n ? \"DESC\"\n : undefined,\n };\n }\n }\n\n if (view.type === \"gallery\" && view.cover) {\n if (view.cover.type === \"property\" && view.cover.propertyId) {\n const propName = this.resolvePropertyName(view.cover.propertyId, schema);\n if (propName) result.image = this.toNoteRef(propName);\n } else if (view.cover.type === \"page_cover\") {\n result.image = \"note.cover\";\n } else if (view.cover.type === \"page_content\" || view.cover.type === \"page_content_first\") {\n result.image = \"formula.coverImage\";\n }\n }\n\n return result;\n }\n\n private toNoteRef(propertyName: string): string {\n return propertyName;\n }\n\n /**\n * 속성 참조(order/sort/groupBy/image)를 YAML로 안전하게 출력한다.\n * `file.name`·`formula.coverImage`·`note.cover` 같은 접두사 식별자와 공백 포함 일반 속성명은\n * 평문 스칼라로 안전하므로 그대로 두고, 콜론·해시·따옴표 등 YAML 메타문자가 있을 때만 인용한다.\n */\n private propRef(ref: string): string {\n if (/^[A-Za-z0-9_][A-Za-z0-9_. ]*$/.test(ref) && !ref.endsWith(\" \")) return ref;\n return `\"${ref.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n }\n\n private resolvePropertyName(\n propertyId: string,\n schema: Record<string, BasePropertySchema>,\n ): string | undefined {\n // Notion `views.retrieve` 는 RAW 속성 id(예: `[jiM`)를 주지만\n // `databases.retrieve` 스키마는 URL-인코딩된 id(예: `%5BjiM`)를 준다.\n // 디코드 후 비교하지 않으면 \"title\" 외 모든 속성(cover/order/sort/groupBy)이\n // 매칭에 실패해 갤러리 커버·표시 컬럼이 통째로 사라진다.\n const target = this.decodeId(propertyId);\n for (const [name, prop] of Object.entries(schema)) {\n if (this.decodeId(prop.id) === target) return name;\n }\n return undefined;\n }\n\n private decodeId(id: string): string {\n try {\n return decodeURIComponent(id);\n } catch {\n return id;\n }\n }\n\n private yamlKey(key: string): string {\n if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) return key;\n return `\"${key.replace(/\"/g, '\\\\\"')}\"`;\n }\n\n private yamlValue(value: string): string {\n if (/^[a-zA-Z0-9_-]+$/.test(value)) return value;\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n }\n}\n","import type { DatabaseViewsConfig, ViewConfig } from \"../types/view.js\";\nimport {\n basesViewTypeOf,\n type BasePropertySchema,\n type BasesViewType,\n} from \"./base-file-generator.js\";\n\n/**\n * DB 사이드카(`<db>.notion.json`) — `.base` 로 표현할 수 없는 Notion DB 메타데이터를\n * 무손실 보존하는 단일 파일.\n *\n * ## 왜 필요한가 (I4·I7 \"조용한 유실 금지\")\n *\n * Obsidian Bases(`.base`)는 Notion DB 뷰의 일부만 표현한다:\n * · 미지원 뷰(calendar/timeline/form/chart/map/dashboard)는 `.base` 에서 통째 누락.\n * · 표현되는 뷰도 Notion **필터식·커버 크기/비율·컬럼 width/wrap·빈그룹 숨김** 등은\n * Bases 문법에 대응이 없어 손실된다.\n *\n * Notion API 는 뷰 생성/수정을 지원하지 않으므로(뷰는 pull-authoritative) 이 메타데이터는\n * push 로 Notion 에 되돌릴 수 없다. 따라서 \"무손실\"의 의미는 **로컬에 완전·정직하게\n * 보존하고, 무엇이 degrade 됐는지 명시 리포트**하는 것이다. 사이드카는 이를 `.base` 와\n * 같은 폴더에 co-locate 해 사람이 발견 가능하고 도구가 재사용 가능하게 만든다.\n *\n * ## 멱등성\n *\n * 매 pull 마다 재생성되므로 **결정적**이어야 한다(타임스탬프·실행시각 금지, 키 정렬).\n * 동일 DB 상태 → 동일 바이트 → drift 0 / churn 0.\n */\nexport interface NotionSidecar {\n readonly generator: \"im-nobsidian\";\n readonly schemaVersion: 1;\n readonly databaseId: string;\n readonly databaseName: string;\n /** 속성 스키마 — 이름 정렬. `.base` displayName 만으로는 잃는 타입/옵션을 보존. */\n readonly properties: SidecarProperty[];\n /** 모든 뷰(표현/미표현 공통) — Notion 순서 유지. */\n readonly views: SidecarView[];\n /** 정직한 손실 리포트 — 무엇이 `.base` 에서 누락/degrade 됐는가. */\n readonly degraded: DegradeNote[];\n}\n\nexport interface SidecarProperty {\n readonly name: string;\n readonly id: string;\n readonly type: string;\n /** select/multi_select/status 옵션명(있으면). */\n readonly options?: string[];\n}\n\nexport interface SidecarView {\n readonly id: string;\n readonly name: string;\n readonly notionType: string;\n /** Bases 대응 타입. `null` = `.base` 미표현(사이드카가 유일 보존처). */\n readonly basesType: BasesViewType | null;\n /** 원본 뷰 설정 중 의미 있는 항목(키 정렬). 빈 값은 생략. */\n readonly config: Record<string, unknown>;\n}\n\nexport interface DegradeNote {\n readonly view: string;\n readonly kind: \"view-unrepresentable\" | \"setting-dropped\";\n readonly detail: string;\n}\n\n/** `.base` 가 표현하지 못해 사이드카로만 보존되는 뷰 설정 키 → 사람용 사유. */\nconst DROPPED_SETTING_REASONS: Record<string, string> = {\n filter: \"Notion 필터식은 .base 로 표현되지 않음(폴더 필터만 적용)\",\n coverSize: \"갤러리 커버 크기는 Bases 미지원\",\n coverAspect: \"갤러리 커버 비율은 Bases 미지원\",\n viewRange: \"캘린더 표시 범위(week/month)는 Bases 미지원\",\n columnWidths: \"컬럼 너비(width)는 Bases 미지원\",\n columnWraps: \"컬럼 줄바꿈(wrap)은 Bases 미지원\",\n hideEmptyGroups: \"빈 그룹 숨김은 Bases 미지원\",\n};\n\nexport class SidecarGenerator {\n /**\n * 사이드카 객체를 빌드한다(순수 — I/O 없음). 직렬화는 {@link serialize} 가 담당.\n */\n build(options: {\n databaseId: string;\n databaseName: string;\n schema: Record<string, BasePropertySchema>;\n viewsConfig: DatabaseViewsConfig;\n }): NotionSidecar {\n const degraded: DegradeNote[] = [];\n\n const properties = this.buildProperties(options.schema);\n const views = options.viewsConfig.views.map((v) => this.buildView(v, degraded));\n\n // 정직성·안정성: 리포트를 (뷰명, kind, detail) 로 정렬해 결정적 순서 보장.\n degraded.sort(\n (a, b) =>\n a.view.localeCompare(b.view) ||\n a.kind.localeCompare(b.kind) ||\n a.detail.localeCompare(b.detail),\n );\n\n return {\n generator: \"im-nobsidian\",\n schemaVersion: 1,\n databaseId: options.databaseId,\n databaseName: options.databaseName,\n properties,\n views,\n degraded,\n };\n }\n\n /**\n * 사이드카를 결정적 JSON 문자열로 직렬화한다(키 재귀 정렬 + 말미 개행).\n * 동일 입력 → 동일 바이트 → 멱등(drift/churn 0).\n */\n serialize(sidecar: NotionSidecar): string {\n return stableStringify(sidecar) + \"\\n\";\n }\n\n private buildProperties(schema: Record<string, BasePropertySchema>): SidecarProperty[] {\n return Object.entries(schema)\n .map(([name, prop]): SidecarProperty => {\n const options = prop.options?.map((o) => o.name).filter((n) => n.length > 0);\n return {\n name,\n id: prop.id,\n type: prop.type,\n ...(options && options.length > 0 ? { options } : {}),\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n }\n\n private buildView(view: ViewConfig, degraded: DegradeNote[]): SidecarView {\n const basesType = basesViewTypeOf(view.type);\n const viewName = view.name || view.type;\n\n if (basesType === null) {\n degraded.push({\n view: viewName,\n kind: \"view-unrepresentable\",\n detail: `'${view.type}' 뷰는 Obsidian Bases 대응이 없어 .base 에서 누락 — 사이드카로만 보존`,\n });\n }\n\n const config = this.extractConfig(view, basesType, viewName, degraded);\n\n return {\n id: view.id,\n name: viewName,\n notionType: view.type,\n basesType,\n config,\n };\n }\n\n /**\n * 뷰 설정 중 의미 있는 항목을 추출한다. `.base` 가 표현 못하는 항목(필터·커버크기 등)은\n * config 에 보존하면서 동시에 degrade 리포트에 1줄씩 기록한다(표현되는 뷰에 한해 —\n * 미표현 뷰는 이미 view-unrepresentable 로 통째 보고됨).\n */\n private extractConfig(\n view: ViewConfig,\n basesType: BasesViewType | null,\n viewName: string,\n degraded: DegradeNote[],\n ): Record<string, unknown> {\n const config: Record<string, unknown> = {};\n const noteDrop = (key: string): void => {\n if (basesType !== null && DROPPED_SETTING_REASONS[key]) {\n degraded.push({\n view: viewName,\n kind: \"setting-dropped\",\n detail: DROPPED_SETTING_REASONS[key]!,\n });\n }\n };\n\n if (view.filter !== undefined && view.filter !== null) {\n config[\"filter\"] = view.filter;\n noteDrop(\"filter\");\n }\n if (view.sorts && view.sorts.length > 0) config[\"sorts\"] = view.sorts;\n if (view.groupBy) {\n config[\"groupBy\"] = view.groupBy;\n if (view.groupBy.hideEmptyGroups) noteDrop(\"hideEmptyGroups\");\n }\n if (view.cover) config[\"cover\"] = view.cover;\n if (view.coverSize) {\n config[\"coverSize\"] = view.coverSize;\n noteDrop(\"coverSize\");\n }\n if (view.coverAspect) {\n config[\"coverAspect\"] = view.coverAspect;\n noteDrop(\"coverAspect\");\n }\n if (view.datePropertyId) config[\"datePropertyId\"] = view.datePropertyId;\n if (view.datePropertyName) config[\"datePropertyName\"] = view.datePropertyName;\n if (view.viewRange) {\n config[\"viewRange\"] = view.viewRange;\n noteDrop(\"viewRange\");\n }\n\n if (view.properties && view.properties.length > 0) {\n config[\"properties\"] = view.properties;\n if (view.properties.some((p) => p.width !== undefined)) noteDrop(\"columnWidths\");\n if (view.properties.some((p) => p.wrap !== undefined)) noteDrop(\"columnWraps\");\n }\n\n return config;\n }\n}\n\n/**\n * 키를 재귀 정렬한 결정적 JSON 직렬화기. 배열 순서는 보존(뷰/속성의 원본 순서가 유의미),\n * 객체 키만 사전순 정렬해 동일 입력에 동일 바이트를 보장한다.\n */\nfunction stableStringify(value: unknown): string {\n return JSON.stringify(sortKeys(value), null, 2);\n}\n\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value !== null && typeof value === \"object\") {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>).sort()) {\n sorted[key] = sortKeys((value as Record<string, unknown>)[key]);\n }\n return sorted;\n }\n return value;\n}\n","/**\n * DB 산출물(`.base`/사이드카 `.notion.json`) rename 고아 정리 — 순수 선택 로직.\n *\n * Notion DB 제목이 바뀌면 산출물 파일명(`sanitizeFileName(title)`)이 바뀌어 옛 이름의\n * `.base`·`.notion.json` 이 **같은 폴더에 고아로 잔존**한다. 이는 pull 멱등을 깨고\n * (drift) 삭제 검증에서 부활(resurrection)로 잡히는 결함이다. 본 모듈은 어떤 파일을\n * 삭제 대상으로 고를지를 **부수효과 없이 결정**한다(테스트·재사용 용이).\n */\n\n/** 볼트 파일 참조의 최소 형태(경로만 필요). */\nexport interface VaultFileRef {\n readonly path: string;\n}\n\n/** DB 폴더 직속에서 정리 대상이 되는 산출물 확장자. */\nconst ARTIFACT_SUFFIXES = [\".base\", \".notion.json\"] as const;\n\n/**\n * `localFolder` **직속**의 고아 `.base`/`.notion.json` 경로를 고른다.\n *\n * 규칙:\n * - `localFolder/` 로 시작하고 그 뒤에 `/` 가 없는 **직속 파일만** 대상 — 하위 폴더(중첩 DB)의\n * 산출물은 각자의 DB 동기화가 관리하므로 절대 건드리지 않는다.\n * - 확장자가 `.base` 또는 `.notion.json` 인 것만.\n * - `keepPaths` 에 포함된 **현재 산출물**은 제외.\n *\n * 결정적: 입력 순서를 보존해 반환(멱등·테스트 안정). 부수효과 없음.\n */\nexport function selectStaleDbArtifacts(\n files: ReadonlyArray<VaultFileRef>,\n localFolder: string,\n keepPaths: ReadonlySet<string>,\n): string[] {\n const prefix = `${localFolder}/`;\n const stale: string[] = [];\n for (const file of files) {\n const path = file.path;\n if (!path.startsWith(prefix)) continue;\n const rel = path.slice(prefix.length);\n if (rel.includes(\"/\")) continue; // 폴더 직속만 — 중첩 DB 산출물 보호\n if (!ARTIFACT_SUFFIXES.some((suffix) => rel.endsWith(suffix))) continue;\n if (keepPaths.has(path)) continue;\n stale.push(path);\n }\n return stale;\n}\n","import {\n MARKER_BRAND_RE,\n compactMarker,\n TOGGLE_START,\n TOGGLE_END,\n WIKILINK_PROTOCOL,\n} from \"../constants/markers.js\";\n\nconst NOTION_CALLOUT_RE = /^::: callout\\n([\\s\\S]*?)\\n:::/gm;\nconst NOTION_PAGE_MENTION_RE = /<mention-page id=\"([^\"]+)\">([\\s\\S]*?)<\\/mention-page>/g;\nconst NOTION_USER_MENTION_RE = /<mention-user id=\"[^\"]*\">([^<]*)<\\/mention-user>/g;\nconst NOTION_DATE_MENTION_RE = /<mention-date start=\"([^\"]*)\"(?: end=\"([^\"]*)\")?[^>]*\\/>/g;\nconst NOTION_UNKNOWN_RE = /<unknown id=\"([^\"]*)\"([^>]*)\\/>/g;\nconst NOTION_UNKNOWN_URL_RE = /<unknown url=\"([^\"]*)\"([^>]*)\\/>/g;\n\nconst NOTION_AUDIO_RE = /[\\t ]*<audio src=\"([^\"]*)\">([\\s\\S]*?)<\\/audio>/g;\nconst NOTION_VIDEO_RE = /[\\t ]*<video src=\"([^\"]*)\">([\\s\\S]*?)<\\/video>/g;\nconst NOTION_PDF_RE = /[\\t ]*<pdf src=\"([^\"]*)\">([\\s\\S]*?)<\\/pdf>/g;\nconst NOTION_FILE_RE = /[\\t ]*<file src=\"([^\"]*)\">([\\s\\S]*?)<\\/file>/g;\nconst NOTION_TAB_RE = /<tab title=\"([^\"]*)\">([\\s\\S]*?)<\\/tab>/g;\n\nexport function notionEnhancedToObsidian(enhanced: string): string {\n let result = enhanced;\n\n result = convertSyncedBlockRef(result);\n result = normalizeCodeBlockToggles(result);\n result = convertContainers(result);\n result = convertFencedCallouts(result);\n result = convertPageMentions(result);\n result = convertPageLinks(result);\n result = convertUserMentions(result);\n result = convertDateMentions(result);\n result = convertMediaTags(result);\n result = convertTabBlocks(result);\n result = preserveUnknownBlocks(result);\n result = convertNotionMath(result);\n result = convertNotionTables(result);\n result = convertSpans(result);\n result = convertDatabaseBlocks(result);\n result = cleanInlineColorAttrs(result);\n result = removeEmptyBlocks(result);\n result = unescapePipes(result);\n result = unescapeNotionChars(result);\n result = unescapeWikilinkBrackets(result);\n result = ensureCalloutContinuity(result);\n\n return result;\n}\n\n// Notion markdown API 는 평문 위키링크 `[[..]]` 를 `\\[\\[..\\]\\]` 로 escape 저장한다.\n// (resolved 위키링크는 mention 이 되어 이 경로를 타지 않고, unresolved 만 평문으로 보존됨)\n// pull 시 escape 를 해제해 Obsidian 위키링크 기능과 push↔pull 수렴을 보장한다.\nfunction unescapeWikilinkBrackets(content: string): string {\n return content.replace(/\\\\\\[\\\\\\[([\\s\\S]*?)\\\\\\]\\\\\\]/g, \"[[$1]]\");\n}\n\nexport function obsidianToNotionEnhanced(obsidian: string): string {\n let result = obsidian;\n\n result = convertTogglesToHtml(result);\n result = restoreTabBlocks(result);\n result = convertObsidianCallouts(result);\n result = restoreMediaTags(result);\n result = restoreUnknownBlocks(result);\n result = restoreColorSpans(result);\n result = restoreUnderlineSpans(result);\n result = convertMentionPageIdToUrl(result);\n result = restoreWikilinkPreserveLinks(result);\n\n return result;\n}\n\n// ─── Push 방향: 위키링크 → Notion markdown API 호환 표현 ───\n//\n// 배경: Notion 공식 markdown API(`pages.create({markdown})`, `updateMarkdown`)는\n// - `<mention-page id=\"X\">label</mention-page>` 를 **통째로 삭제**한다(레이블까지 소실).\n// - `<mention-page url=\"https://www.notion.so/<id>\"/>` 만 진짜 page mention 으로 인식한다.\n// - 커스텀 스킴 링크(`[label](im-nobsidian://wikilink/..)`)는 링크를 버리고 텍스트만 남긴다.\n// - 평문 `[[target]]` 는 텍스트로 escape 보존되어 round-trip 시 정확히 복원된다.\n// 따라서 파이프라인(WikilinkResolver)이 만든 표현을 위 규칙에 맞게 한 번 더 변환한다.\n\nconst MENTION_PAGE_ID_RE = /<mention-page id=\"([^\"]+)\">[\\s\\S]*?<\\/mention-page>/g;\nconst WIKILINK_PRESERVE_LINK_RE = new RegExp(\n `\\\\[([^\\\\]]+)\\\\]\\\\(${WIKILINK_PROTOCOL}([^)]+)\\\\)`,\n \"g\",\n);\n\n// resolved 위키링크: id 기반 mention → Notion 이 수용하는 url 기반 mention 으로 변환\nfunction convertMentionPageIdToUrl(content: string): string {\n return content.replace(MENTION_PAGE_ID_RE, (_match, id: string) => {\n const nohyph = id.replace(/-/g, \"\");\n return `<mention-page url=\"https://www.notion.so/${nohyph}\"/>`;\n });\n}\n\n// unresolved 위키링크: preserve-link → 평문 위키링크 (Notion 이 텍스트로 보존, round-trip 수렴)\nfunction restoreWikilinkPreserveLinks(content: string): string {\n return content.replace(WIKILINK_PRESERVE_LINK_RE, (_match, label: string, enc: string) => {\n let target = enc;\n try {\n target = decodeURIComponent(enc);\n } catch {\n // 잘못 인코딩된 경우 원문 유지\n }\n return target === label ? `[[${target}]]` : `[[${target}|${label}]]`;\n });\n}\n\n/**\n * 코드펜스 본문에 나타나는 가장 긴 백틱 런보다 1 이상 긴 펜스를 만든다(최소 3).\n *\n * CommonMark fenced-code 규칙: 본문에 펜스와 같은 길이의 백틱 런이 있으면 그 지점에서\n * 코드블록이 조기 종료된다. 토글/콜아웃 본문에 마크다운 예제(펜스 포함)가 들어가는 경우\n * 3-백틱 고정 펜스는 깨지므로, 본문을 스캔해 안전한 펜스 길이를 동적으로 결정한다.\n */\nfunction fenceFor(body: string): string {\n let longest = 0;\n const re = /`+/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body)) !== null) longest = Math.max(longest, m[0].length);\n return \"`\".repeat(Math.max(3, longest + 1));\n}\n\n/**\n * 컨테이너(토글/콜아웃) 본문을 blockquote(`> `)로 감싸기 전에 적용하는 dedent.\n *\n * Notion Markdown API 는 `<details>`/callout 의 직계 자식을 중첩 깊이만큼 탭으로\n * 들여쓴다. 특히 **코드블록은 펜스 줄만 탭으로 들여쓰고 내부 코드 텍스트는 열 0 에\n * 그대로 둔다(비대칭 들여쓰기)** — 실제 Notion 출력에서 확인된 구조다:\n *\n * ```\n * <details>\n * <summary>제목</summary>\n * \\t```javascript ← 펜스만 탭 들여쓰기\n * 코드 본문 (열 0) ← 내부 텍스트는 들여쓰기 없음\n * \\t```\n * </details>\n * ```\n *\n * 이 들여쓰기를 둔 채 `> ` 를 붙이면 펜스가 `> \\t``` ` 가 되어 CommonMark 펜스 규칙\n * (들여쓰기 ≤3칸, 탭=4칸)을 위반한다. 그러면 코드블록이 열리거나 닫히지 않아 렌더링이\n * 깨지고, 닫는 펜스가 무시되면 이후 본문 전체를 코드로 삼키는 cascade 가 된다(결함①).\n *\n * 공통 선행 들여쓰기만 제거하는 단순 dedent 는 이 비대칭 구조를 고치지 못한다(코드\n * 본문이 열 0 이라 공통 최소값이 0 → 무변경). **테이블도 동일한 비대칭**을 보인다:\n * `<table>` 태그만 깊게 들여쓰고 내부 `<tr>/<td>` 행은 열 0 에 둔다. 이 열 0 행이 공통\n * 최소값을 0 으로 끌어내려, 같은 본문의 형제 줄(리스트·문단)까지 구조적 탭을 못 벗는\n * prefix/탭 폭주가 된다(결함②). 따라서 코드블록·테이블 블록을 인식해 다르게 처리한다:\n * - **경계 줄(코드펜스 / <table>·</table>)**: 선행 들여쓰기를 모두 제거해 열 0 으로 정렬.\n * - **블록 내부(코드 본문 / 테이블 행)**: 의미·열정렬을 위해 원문 그대로 보존.\n * - **그 외(산문)**: 공통 선행 들여쓰기만 제거(중첩 리스트 등 상대 들여쓰기는 보존).\n * 공통 최소값은 **산문 줄만**으로 계산하므로 열 0 의 코드·테이블 행에 오염되지 않는다.\n * 앞뒤 빈 줄은 정리하고, 공백만 있는 줄은 비운다.\n */\nfunction dedentContainerBody(text: string): string {\n const lines = text.split(\"\\n\");\n while (lines.length && lines[0]!.trim() === \"\") lines.shift();\n while (lines.length && lines[lines.length - 1]!.trim() === \"\") lines.pop();\n\n // 1패스: 코드블록·테이블 경계를 추적해 각 줄을 분류한다.\n type LineKind = \"fence\" | \"code\" | \"prose\";\n const kinds: LineKind[] = [];\n let inCode = false;\n let fenceChar = \"\";\n let fenceLen = 0;\n let inTable = false;\n for (const line of lines) {\n const fence = /^[\\t ]*(`{3,}|~{3,})(.*)$/.exec(line);\n if (inCode) {\n if (\n fence &&\n fence[1]![0] === fenceChar &&\n fence[1]!.length >= fenceLen &&\n fence[2]!.trim() === \"\"\n ) {\n inCode = false;\n kinds.push(\"fence\");\n } else {\n kinds.push(\"code\");\n }\n } else if (inTable) {\n const closes = /<\\/table>/.test(line);\n kinds.push(closes ? \"fence\" : \"code\");\n if (closes) inTable = false;\n } else if (fence) {\n inCode = true;\n fenceChar = fence[1]![0]!;\n fenceLen = fence[1]!.length;\n kinds.push(\"fence\");\n } else if (/^[\\t ]*<table[^>]*>/.test(line)) {\n // <table> 태그만 깊게 들여쓰고 내부 행은 열 0 인 비대칭 구조. 한 줄에서 닫히지\n // 않으면 테이블 모드로 진입해 행을 보존, 닫는 </table> 도 경계로 열 0 정렬한다.\n if (!/<\\/table>/.test(line)) inTable = true;\n kinds.push(\"fence\");\n } else {\n kinds.push(\"prose\");\n }\n }\n\n // 2패스: 산문 줄의 공통 선행 들여쓰기 계산(상대 들여쓰기 보존 — textwrap.dedent 의미론).\n let min = Infinity;\n lines.forEach((l, i) => {\n if (kinds[i] !== \"prose\" || l.trim() === \"\") return;\n min = Math.min(min, /^[\\t ]*/.exec(l)![0].length);\n });\n if (!Number.isFinite(min)) min = 0;\n\n // 3패스: 경계(fence)→열0 정렬, 내부(code)→원문 보존, 산문(prose)→공통 들여쓰기 제거.\n return lines\n .map((l, i) => {\n if (l.trim() === \"\") return \"\";\n if (kinds[i] === \"code\") return l;\n if (kinds[i] === \"fence\") return l.replace(/^[\\t ]+/, \"\");\n return l.slice(min);\n })\n .join(\"\\n\");\n}\n\nfunction normalizeCodeBlockToggles(content: string): string {\n // 여는/닫는 펜스의 들여쓰기를 가변(`[\\t ]*`)으로 일반화하고, 펜스 길이(`{3,}`)를\n // 백레퍼런스로 대칭 매칭한다. 중첩 토글(두 탭 들여쓰기)·긴 펜스 케이스도 변환된다.\n return content.replace(\n /^[\\t ]*- (.+)\\n[\\t ]*(`{3,})(\\w*)\\n([\\s\\S]*?)\\n[\\t ]*\\2[\\t ]*$/gm,\n (_match, title: string, _open: string, lang: string, rawBody: string) => {\n const body = dedentContainerBody(rawBody);\n const fence = fenceFor(body);\n return `<details>\\n<summary>${title.trim()}</summary>\\n${fence}${lang}\\n${body}\\n${fence}\\n</details>`;\n },\n );\n}\n\n// ── 컨테이너(토글/콜아웃/칼럼) 통합 변환 ──────────────────────────────────────\n//\n// Notion Markdown API 는 <details>/<callout>/<columns> 를 중첩 깊이만큼 탭으로 들여쓴\n// 직계 자식으로 표현한다. 타입별로 분리된 순차 패스로 처리하면 두 문제가 생긴다:\n// (1) 교차 중첩(콜아웃-in-칼럼-in-토글)을 한 패스가 다룰 수 없다.\n// (2) 안쪽 컨테이너를 먼저 풀며 그 선행 들여쓰기를 열 0 으로 당기면, 부모 본문의\n// 들여쓰기가 불균등해져 dedent 공통최소값이 0 → 구조적 탭이 살아남아\n// `> \\t\\t…` prefix/탭 폭주가 된다(결함②). 또한 평면 비탐욕 정규식은 중첩 콜아웃을\n// 잘못 짝지어(바깥 열림 ↔ 안쪽 닫힘) 고아 태그를 남겼다.\n//\n// 해결: 타입 불문 \"가장 안쪽\" 컨테이너부터 한 루프에서 변환한다. body 패턴이 내부에\n// 어떤 컨테이너 시작 태그도 없음을 부정선읽기로 보장하므로(콜아웃 SPAN 과 동일 관용),\n// 매 패스의 매치는 항상 최내곽이다. 각 컨테이너의 선행 들여쓰기를 캡처해 본문 변환 후\n// 출력의 모든 줄에 **다시 입혀**, 변환 결과가 형제 줄과 같은 깊이에 머물게 한다. 그러면\n// 부모의 dedent 가 그 레벨을 통째로 균등 제거한다. 변환 결과엔 컨테이너 태그가 없으므로\n// 다음 패스에서 부모가 새 innermost 가 되어 임의 깊이·교차 중첩이 올바른 순서로 환원된다.\n\n// body: 내부에 어떤 컨테이너 시작 태그도 없는(=가장 안쪽) 구간. 부정선읽기가 START 태그만\n// 차단하므로 비탐욕 *? 가 자신의 닫는 태그에서 멈춘다(</callout> 등은 차단되지 않음).\nconst NO_CONTAINER_BODY = \"(?:(?!<details>|<callout|<columns>)[\\\\s\\\\S])*?\";\n\n// <summary> 제목: 첫 </summary> 에서 반드시 멈추고 중첩 컨테이너 시작 태그를 넘지 않는다.\n// 단순 `[\\s\\S]*?` 는 본문이 닫는 태그에 도달 못 할 때 첫 </summary> 너머로 백트랙해\n// 바깥 토글을 안쪽 </summary>/</details> 와 잘못 짝짓는다(중첩 토글 mis-pair, 결함②).\nconst SUMMARY_TITLE = \"((?:(?!<\\\\/summary>|<details>|<summary>)[\\\\s\\\\S])*?)\";\n\nconst INNERMOST_DETAILS_RE = new RegExp(\n `([\\\\t ]*)<details>\\\\s*<summary>${SUMMARY_TITLE}<\\\\/summary>(${NO_CONTAINER_BODY})<\\\\/details>`,\n \"g\",\n);\nconst INNERMOST_CALLOUT_RE = new RegExp(\n `([\\\\t ]*)<callout[^>]*>\\\\n?(${NO_CONTAINER_BODY})<\\\\/callout>`,\n \"g\",\n);\nconst INNERMOST_COLUMNS_RE = new RegExp(\n `([\\\\t ]*)<columns>\\\\n?(${NO_CONTAINER_BODY})<\\\\/columns>`,\n \"g\",\n);\nconst COLUMN_WRAP_RE = /[\\t ]*<column>\\n?([\\s\\S]*?)[\\t ]*<\\/column>\\n?/g;\n\n// 캡처한 선행 들여쓰기를 변환 결과의 비어있지-않은 모든 줄에 다시 입힌다.\nfunction reindentLines(text: string, indent: string): string {\n if (!indent) return text;\n return text\n .split(\"\\n\")\n .map((line) => (line === \"\" ? line : indent + line))\n .join(\"\\n\");\n}\n\n// <details> → > [!toggle]- (본문은 dedent 후 `> ` prefix). dedent 가 코드펜스를 열 0 으로\n// 정렬해 `> \\t``` ` cascade 를 차단하고(결함①), 부모 패스에서 다시 `> ` 가 입혀지면\n// `> > ` 형태의 올바른 Obsidian 중첩이 된다.\nfunction toggleToCallout(title: string, rawBody: string): string {\n const body = dedentContainerBody(rawBody);\n const calloutBody = body\n .split(\"\\n\")\n .map((line) => (line.trim() ? `> ${line}` : \">\"))\n .join(\"\\n\");\n return `> [!toggle]- ${title.trim()}\\n${calloutBody}`;\n}\n\n// <columns>/<column> → 평탄화. Obsidian 엔 칼럼 문법이 없어 각 칼럼 본문을 dedent 로\n// 구조적 탭까지 벗긴 뒤 빈 줄로 구분해 이어붙인다(결함②: 탭 하나만 벗기던 기존 동작 교체).\nfunction flattenColumns(body: string): string {\n const cols: string[] = [];\n const re = new RegExp(COLUMN_WRAP_RE.source, COLUMN_WRAP_RE.flags);\n let m: RegExpExecArray | null;\n let matched = false;\n while ((m = re.exec(body)) !== null) {\n matched = true;\n const col = dedentContainerBody(m[1]!);\n if (col.trim() !== \"\") cols.push(col);\n }\n // <column> 래퍼가 전혀 없을 때만 폴백 dedent. 래퍼가 있으나 모두 빈 칼럼이면 cols=[] →\n // \"\" 반환(태그 제거됨). 폴백을 cols.length===0 으로 걸면 빈 칼럼의 <column> 태그가 샌다.\n if (!matched) return dedentContainerBody(body);\n return cols.join(\"\\n\\n\");\n}\n\nfunction convertContainers(content: string): string {\n let result = content;\n let safety = 0;\n while (\n safety++ < 2000 &&\n (result.includes(\"<details>\") || result.includes(\"<callout\") || result.includes(\"<columns>\"))\n ) {\n const before = result;\n result = result.replace(\n INNERMOST_DETAILS_RE,\n (_m, indent: string, title: string, body: string) =>\n reindentLines(toggleToCallout(title, body), indent),\n );\n result = result.replace(INNERMOST_CALLOUT_RE, (_m, indent: string, body: string) =>\n reindentLines(calloutBodyToObsidian(body), indent),\n );\n result = result.replace(INNERMOST_COLUMNS_RE, (_m, indent: string, body: string) =>\n reindentLines(flattenColumns(body), indent),\n );\n if (result === before) break;\n }\n return result;\n}\n\nfunction calloutBodyToObsidian(body: string): string {\n // 콜아웃 본문도 토글과 동일한 코드펜스 cascade 위험이 있으므로 같은 dedent 를 적용한다.\n const lines = dedentContainerBody(body)\n .split(\"\\n\")\n .filter((l, i, arr) => !(i === 0 && l === \"\") && !(i === arr.length - 1 && l === \"\"));\n const firstLine = lines[0] ?? \"\";\n\n const emojiMatch = /^([\\p{Emoji}️‍]+)\\s*(.*)/u.exec(firstLine);\n const type = emojiMatch ? emojiToCalloutType(emojiMatch[1]!) : \"note\";\n const title = emojiMatch ? emojiMatch[2]! : firstLine;\n const rest = lines.slice(1).join(\"\\n\").trim();\n\n const calloutTitle = title ? `> [!${type}] ${title}` : `> [!${type}]`;\n const calloutBody = rest\n ? \"\\n\" +\n rest\n .split(\"\\n\")\n .map((line) => (line.trim() ? `> ${line}` : \">\"))\n .join(\"\\n\")\n : \"\";\n\n return calloutTitle + calloutBody;\n}\n\n// 푸시 측 내부 표현인 `::: callout` 펜스 폼만 처리한다(탭 중첩이 아니라 폭주 없음).\n// Notion 풀 API 의 <callout> 태그는 convertContainers 가 담당한다.\nfunction convertFencedCallouts(content: string): string {\n return content.replace(NOTION_CALLOUT_RE, (_match, body: string) => calloutBodyToObsidian(body));\n}\n\nfunction convertPageMentions(content: string): string {\n let result = content.replace(NOTION_PAGE_MENTION_RE, (_match, _id: string, text: string) => {\n const cleaned = text.trim();\n return `[[${cleaned}]]`;\n });\n // url 기반 page mention 은 두 형태로 온다:\n // - self-closing `<mention-page url=\"..32hex..\"/>`\n // - 라벨 동반(breadcrumb 등) `<mention-page url=\"..32hex..\">제목</mention-page>`\n // 둘 다 page id 로 환원해 `[[notion:id]]` 로 만들고, 후처리 resolveNotionLinks 가 정식\n // 제목으로 해소한다. mention 라벨은 항상 대상 페이지의 현재 제목이므로 id 해소가 SSOT —\n // 라벨을 버려도 무손실이며, 같은 줄의 다른 위키링크와 일관된 표현이 된다.\n // (`[^>]*?` 는 `>` 를 넘지 않는 lazy 매치, alternation 으로 self-closing/라벨형을 한 번에 처리)\n result = result.replace(\n /<mention-page\\s+url=\"https?:\\/\\/(?:www\\.)?notion\\.so\\/([a-f0-9]{32})\"[^>]*?(?:\\/>|>[\\s\\S]*?<\\/mention-page>)/g,\n (_match, id: string) => `[[notion:${id}]]`,\n );\n return result;\n}\n\nfunction convertUserMentions(content: string): string {\n return content.replace(NOTION_USER_MENTION_RE, (_match, name: string) => `@${name}`);\n}\n\nfunction convertDateMentions(content: string): string {\n return content.replace(NOTION_DATE_MENTION_RE, (_match, start: string, end?: string) => {\n return end ? `${start} → ${end}` : start;\n });\n}\n\n// 2D: <unknown> → 보존 마커 (삭제 대신 보존)\nfunction preserveUnknownBlocks(content: string): string {\n let result = content.replace(NOTION_UNKNOWN_RE, (_match, id: string, attrs: string) => {\n const typeMatch = /type=\"([^\"]*)\"/.exec(attrs);\n const altMatch = /alt=\"([^\"]*)\"/.exec(attrs);\n const blockType = altMatch?.[1] ?? typeMatch?.[1] ?? \"unknown\";\n return compactMarker(`unknown:id=${id}&type=${blockType}`);\n });\n result = result.replace(NOTION_UNKNOWN_URL_RE, (_match, url: string, attrs: string) => {\n const altMatch = /alt=\"([^\"]*)\"/.exec(attrs);\n const blockType = altMatch?.[1] ?? \"bookmark\";\n const marker = compactMarker(`unknown:id=${encodeURIComponent(url)}&type=${blockType}`);\n // URL 을 가진 임베드/북마크는 읽기뷰에서 보이지 않는 주석 마커만 남기면\n // 사용자가 \"왜 빈 줄이지?\" 하고 혼란스럽다. 클릭 가능한 링크를 앞에 붙이되,\n // round-trip 권위는 뒤따르는 마커(인코딩된 원본 URL)가 갖는다. 링크와 마커는\n // 공백 없이 즉시 인접시켜, 역변환 시 한 쌍으로 같이 제거 → Notion drift 방지.\n const label =\n blockType === \"embed\"\n ? \"🔗 Embed\"\n : blockType === \"bookmark\"\n ? \"🔖 Bookmark\"\n : `🔗 ${blockType}`;\n return `[${label}](${url})${marker}`;\n });\n return result;\n}\n\nfunction convertSyncedBlockRef(content: string): string {\n let result = content.replace(\n /<synced_block_reference[^>]*>[\\s\\S]*?<\\/synced_block_reference>/g,\n (match) => {\n const inner = match\n .replace(/<synced_block_reference[^>]*>\\n?/, \"\")\n .replace(/<\\/synced_block_reference>/, \"\")\n .split(\"\\n\")\n .map((l) => l.replace(/^\\t/, \"\"))\n .join(\"\\n\")\n .trim();\n return inner;\n },\n );\n result = result.replace(\n /<synced_block[^>]*>\\n?([\\s\\S]*?)<\\/synced_block>/g,\n (_match, inner: string) => inner.trim(),\n );\n return result;\n}\n\n// 2A: 미디어 태그 → Obsidian 마크다운\nfunction convertMediaTags(content: string): string {\n let result = content;\n\n result = result.replace(NOTION_AUDIO_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[🔊 ${cap}](${src})` : `[🔊 audio](${src})`;\n });\n\n result = result.replace(NOTION_VIDEO_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[🎬 ${cap}](${src})` : `[🎬 video](${src})`;\n });\n\n result = result.replace(NOTION_PDF_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[📄 ${cap}](${src})` : `[📄 pdf](${src})`;\n });\n\n result = result.replace(NOTION_FILE_RE, (_match, src: string, caption: string) => {\n const cap = caption.trim();\n return cap ? `[📎 ${cap}](${src})` : `[📎 file](${src})`;\n });\n\n return result;\n}\n\n// 2B: <tab> → 보존 마커\nfunction convertTabBlocks(content: string): string {\n return content.replace(NOTION_TAB_RE, (_match, title: string, body: string) => {\n const trimmed = body.trim();\n const indented = trimmed\n .split(\"\\n\")\n .map((line) => `> ${line}`)\n .join(\"\\n\");\n return `> [!tab] ${title}\\n${indented}`;\n });\n}\n\n// 2C: <span underline> / <span color> → 보존 마커 (균형 매칭, 중첩 안전)\n//\n// 비탐욕 단일 정규식(`<span ...>([\\s\\S]*?)</span>`)은 중첩 span 에서 첫 `</span>` 에\n// 멈춰 바깥 span 의 닫는 토큰 순서를 뒤집는다(rank6/I3 — 사용자가 보는 Obsidian 마커가\n// `%%/color%%%%/underline%%` 처럼 잘못 중첩됨). 대신 **안쪽(중첩 없는) span 부터** 마커로\n// 치환한다: 마커엔 `<span` 이 없으므로 다음 패스에서 바깥 span 이 다시 innermost 가 되어\n// 임의 깊이 중첩이 올바른 순서로 환원된다. body 패턴 `(?:(?!<span )[\\s\\S])*?` 가 내부에\n// 또 다른 span 시작이 없음을 보장해 \"가장 안쪽\"만 매칭한다.\nconst INNERMOST_SPAN_RE =\n /<span (?:underline=\"true\"|color=\"([^\"]+)\")>((?:(?!<span )[\\s\\S])*?)<\\/span>/g;\n\nfunction convertSpans(content: string): string {\n let result = content;\n let safety = 0;\n while (safety++ < 1000) {\n const next = result.replace(\n INNERMOST_SPAN_RE,\n (_match, color: string | undefined, inner: string) =>\n color !== undefined\n ? `${compactMarker(`color:${color}`)}${inner}%%/color%%`\n : `${compactMarker(\"underline\")}${inner}%%/underline%%`,\n );\n if (next === result) break;\n result = next;\n }\n return result;\n}\n\nfunction convertTogglesToHtml(content: string): string {\n const calloutToggleRe = /^> \\[!toggle\\]-\\s*(.+)\\n((?:>.*\\n?)*)/gm;\n\n let result = content;\n let prev = \"\";\n let safety = 0;\n while (result !== prev && safety++ < 100) {\n prev = result;\n result = result.replace(calloutToggleRe, (_match, title: string, body: string) => {\n const bodyText = body\n .split(\"\\n\")\n .map((line) => line.replace(/^>\\s?/, \"\"))\n .join(\"\\n\")\n .trim();\n return `<details>\\n<summary>${title.trim()}</summary>\\n\\n${bodyText}\\n\\n</details>`;\n });\n }\n\n const startRe = new RegExp(escapeRegex(TOGGLE_START), \"g\");\n const endRe = new RegExp(escapeRegex(TOGGLE_END), \"g\");\n\n safety = 0;\n while (result.includes(TOGGLE_START) && safety++ < 100) {\n const startIdx = result.indexOf(TOGGLE_START);\n const endIdx = findMatchingEnd(result, startIdx + TOGGLE_START.length);\n if (endIdx === -1) break;\n\n const inner = result.slice(startIdx + TOGGLE_START.length, endIdx).trim();\n const titleMatch = /^- (.+)$/m.exec(inner);\n const title = titleMatch ? titleMatch[1]! : \"\";\n const body = inner\n .split(\"\\n\")\n .slice(1)\n .map((line) => line.replace(/^ {2}/, \"\"))\n .join(\"\\n\")\n .trim();\n\n const html = `<details>\\n<summary>${title}</summary>\\n\\n${body}\\n\\n</details>`;\n result = result.slice(0, startIdx) + html + result.slice(endIdx + TOGGLE_END.length);\n }\n\n result = result.replace(startRe, \"\").replace(endRe, \"\");\n return result;\n}\n\nfunction findMatchingEnd(content: string, startFrom: number): number {\n let depth = 1;\n let pos = startFrom;\n\n while (pos < content.length && depth > 0) {\n const nextStart = content.indexOf(TOGGLE_START, pos);\n const nextEnd = content.indexOf(TOGGLE_END, pos);\n\n if (nextEnd === -1) return -1;\n\n if (nextStart !== -1 && nextStart < nextEnd) {\n depth++;\n pos = nextStart + TOGGLE_START.length;\n } else {\n depth--;\n if (depth === 0) return nextEnd;\n pos = nextEnd + TOGGLE_END.length;\n }\n }\n\n return -1;\n}\n\nfunction convertObsidianCallouts(content: string): string {\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n let i = 0;\n\n while (i < lines.length) {\n const headerMatch = /^> \\[!(\\w+)\\]([-+])?\\s*(.*)/.exec(lines[i]!);\n if (headerMatch) {\n const type = headerMatch[1]!;\n const title = headerMatch[3]!;\n const emoji = calloutTypeToEmoji(type) ?? \"💡\";\n const calloutTitle = title ? `${emoji} ${title}` : emoji;\n\n const bodyLines: string[] = [];\n i++;\n while (i < lines.length && lines[i]!.startsWith(\"> \")) {\n bodyLines.push(lines[i]!.slice(2));\n i++;\n }\n\n result.push(\"::: callout\");\n result.push(calloutTitle);\n if (bodyLines.length > 0) {\n result.push(...bodyLines);\n }\n result.push(\":::\");\n } else {\n result.push(lines[i]!);\n i++;\n }\n }\n\n return result.join(\"\\n\");\n}\n\nconst EMOJI_TYPE_MAP: Record<string, string> = {\n \"💡\": \"tip\",\n ℹ️: \"info\",\n \"⚠️\": \"warning\",\n \"🔥\": \"danger\",\n \"✅\": \"success\",\n \"❌\": \"failure\",\n \"❓\": \"question\",\n \"📝\": \"note\",\n \"📌\": \"abstract\",\n \"🐛\": \"bug\",\n \"💬\": \"quote\",\n \"📋\": \"example\",\n};\n\nconst TYPE_EMOJI_MAP: Record<string, string> = Object.fromEntries(\n Object.entries(EMOJI_TYPE_MAP).map(([k, v]) => [v, k]),\n);\n\nfunction emojiToCalloutType(emoji: string): string {\n return EMOJI_TYPE_MAP[emoji] ?? \"note\";\n}\n\nfunction calloutTypeToEmoji(type: string): string | undefined {\n return TYPE_EMOJI_MAP[type.toLowerCase()];\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nconst NOTION_PAGE_LINK_RE = /<page url=\"[^\"]*\">([\\s\\S]*?)<\\/page>/g;\nconst NOTION_EMPTY_BLOCK_RE = /^(?:>[\\t ]*)*[\\t ]*<empty-block\\/>\\n?/gm;\n\nfunction convertPageLinks(content: string): string {\n return content.replace(NOTION_PAGE_LINK_RE, (_match, text: string) => {\n const cleaned = text.replace(/\\*\\*/g, \"\").trim();\n return `[[${cleaned}]]`;\n });\n}\n\nfunction convertDatabaseBlocks(content: string): string {\n return content.replace(\n /<database[^>]*>([\\s\\S]*?)<\\/database>/g,\n (_match, title: string) => `**${title.trim()}** *(Notion DB)*`,\n );\n}\n\nfunction cleanInlineColorAttrs(content: string): string {\n return content.replace(/\\s*\\{color=\"[^\"]*\"\\}/g, \"\");\n}\n\nfunction removeEmptyBlocks(content: string): string {\n return content.replace(NOTION_EMPTY_BLOCK_RE, \"\\n\");\n}\n\nconst NOTION_INLINE_MATH_RE = /\\$`([^`]+)`\\$/g;\nconst NOTION_BLOCK_MATH_RE = /\\$\\$\\n```\\n([\\s\\S]*?)\\n```\\n\\$\\$/g;\n\nfunction convertNotionMath(content: string): string {\n let result = content.replace(NOTION_BLOCK_MATH_RE, (_match, eq: string) => {\n return `$$\\n${eq.trim()}\\n$$`;\n });\n result = result.replace(NOTION_INLINE_MATH_RE, (_match, eq: string) => `$${eq}$`);\n result = result.replace(/\\\\\\$([^$]+?)\\\\\\$/g, (_match, inner: string) => {\n const unescaped = inner.replace(/\\\\\\^/g, \"^\").replace(/\\\\~/g, \"~\");\n return `$${unescaped}$`;\n });\n return result;\n}\n\nfunction unescapeNotionChars(content: string): string {\n return content.replace(/\\\\~/g, \"~\").replace(/\\\\\\^/g, \"^\");\n}\n\nconst NOTION_TABLE_RE = /<table[^>]*>([\\s\\S]*?)<\\/table>/g;\nconst TABLE_ROW_RE = /<tr>([\\s\\S]*?)<\\/tr>/g;\nconst TABLE_CELL_RE = /<t[dh][^>]*>([\\s\\S]*?)<\\/t[dh]>/g;\n\nfunction isAlignmentRow(cells: string[]): boolean {\n return cells.every((c) => /^:?-{2,}:?$/.test(c.trim()));\n}\n\nfunction convertNotionTables(content: string): string {\n return content.replace(NOTION_TABLE_RE, (_match, tableBody: string) => {\n const rows: string[][] = [];\n let rowMatch: RegExpExecArray | null;\n const rowRe = new RegExp(TABLE_ROW_RE.source, TABLE_ROW_RE.flags);\n\n while ((rowMatch = rowRe.exec(tableBody)) !== null) {\n const cells: string[] = [];\n let cellMatch: RegExpExecArray | null;\n const cellRe = new RegExp(TABLE_CELL_RE.source, TABLE_CELL_RE.flags);\n while ((cellMatch = cellRe.exec(rowMatch[1]!)) !== null) {\n cells.push(cellMatch[1]!.trim());\n }\n if (!isAlignmentRow(cells)) {\n rows.push(cells);\n }\n }\n\n if (rows.length === 0) return _match;\n\n const colCount = Math.max(...rows.map((r) => r.length));\n const lines: string[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const padded = rows[i]!;\n while (padded.length < colCount) padded.push(\"\");\n lines.push(`| ${padded.join(\" | \")} |`);\n if (i === 0) {\n lines.push(`| ${padded.map(() => \"---\").join(\" | \")} |`);\n }\n }\n\n return lines.join(\"\\n\");\n });\n}\n\n// ─── Push 방향: 보존 마커 → Enhanced MD 복원 ───\n\nconst OBSIDIAN_MEDIA_AUDIO_RE = /\\[🔊\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst OBSIDIAN_MEDIA_VIDEO_RE = /\\[🎬\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst OBSIDIAN_MEDIA_PDF_RE = /\\[📄\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\nconst OBSIDIAN_MEDIA_FILE_RE = /\\[📎\\s*([^\\]]*)\\]\\(([^)]+)\\)/g;\n\nfunction restoreMediaTags(content: string): string {\n let result = content;\n\n result = result.replace(OBSIDIAN_MEDIA_AUDIO_RE, (_match, caption: string, src: string) => {\n return `<audio src=\"${src}\">${caption}</audio>`;\n });\n\n result = result.replace(OBSIDIAN_MEDIA_VIDEO_RE, (_match, caption: string, src: string) => {\n return `<video src=\"${src}\">${caption}</video>`;\n });\n\n result = result.replace(OBSIDIAN_MEDIA_PDF_RE, (_match, caption: string, src: string) => {\n return `<pdf src=\"${src}\">${caption}</pdf>`;\n });\n\n result = result.replace(OBSIDIAN_MEDIA_FILE_RE, (_match, caption: string, src: string) => {\n return `<file src=\"${src}\">${caption}</file>`;\n });\n\n return result;\n}\n\nconst OBSIDIAN_TAB_RE = /^> \\[!tab\\]\\s*(.+)\\n((?:> .*\\n?)*)/gm;\n\nfunction restoreTabBlocks(content: string): string {\n return content.replace(OBSIDIAN_TAB_RE, (_match, title: string, body: string) => {\n const unquoted = body\n .split(\"\\n\")\n .map((line) => line.replace(/^> /, \"\"))\n .join(\"\\n\")\n .trim();\n return `<tab title=\"${title}\">${unquoted}</tab>`;\n });\n}\n\n// 앞에 즉시 인접(공백 없음)한 가시 링크 `[label](url)` 가 있으면 마커와 함께 소비한다.\n// 이는 forward 에서 URL 임베드/북마크를 \"[🔗 Embed](url)%%...%%\" 로 렌더한 쌍을 통째로\n// <unknown.../> 로 복원하기 위함이다. 공백 없는 인접만 매칭하므로 사용자 일반 링크는 영향 없음.\nconst OBSIDIAN_UNKNOWN_RE = new RegExp(\n `(?:\\\\[[^\\\\]]*\\\\]\\\\([^)]*\\\\))?%%${MARKER_BRAND_RE}:unknown:id=([^&]+)&type=([^%]+)%%`,\n \"g\",\n);\n\nfunction restoreUnknownBlocks(content: string): string {\n return content.replace(OBSIDIAN_UNKNOWN_RE, (_match, id: string, type: string) => {\n const decoded = decodeURIComponent(id);\n if (decoded.startsWith(\"http\")) {\n return `<unknown url=\"${decoded}\" alt=\"${type}\"/>`;\n }\n return `<unknown id=\"${id}\" type=\"${type}\"/>`;\n });\n}\n\nconst OBSIDIAN_COLOR_RE = new RegExp(\n `%%${MARKER_BRAND_RE}:color:([^%]+)%%([\\\\s\\\\S]*?)%%\\\\/color%%`,\n \"g\",\n);\n\nfunction restoreColorSpans(content: string): string {\n return content.replace(OBSIDIAN_COLOR_RE, (_match, color: string, text: string) => {\n return `<span color=\"${color}\">${text}</span>`;\n });\n}\n\nconst OBSIDIAN_UNDERLINE_RE = new RegExp(\n `%%${MARKER_BRAND_RE}:underline%%([\\\\s\\\\S]*?)%%\\\\/underline%%`,\n \"g\",\n);\n\nfunction restoreUnderlineSpans(content: string): string {\n return content.replace(OBSIDIAN_UNDERLINE_RE, (_match, text: string) => {\n return `<span underline=\"true\">${text}</span>`;\n });\n}\n\nfunction unescapePipes(content: string): string {\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n let inTable = false;\n\n for (const line of lines) {\n if (/^\\|.*\\|$/.test(line.trim()) || /^\\|[\\s-|]+\\|$/.test(line.trim())) {\n inTable = true;\n result.push(line);\n } else {\n if (inTable && line.trim() === \"\") {\n inTable = false;\n } else if (!/^\\|/.test(line.trim())) {\n inTable = false;\n }\n result.push(inTable ? line : line.replace(/\\\\\\|/g, \"|\"));\n }\n }\n\n return result.join(\"\\n\");\n}\n\nfunction ensureCalloutContinuity(content: string): string {\n const lines = content.split(\"\\n\");\n const result: string[] = [];\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i]!;\n if (line.trim() === \"\" && i > 0 && i < lines.length - 1) {\n const prev = result[result.length - 1] ?? \"\";\n const next = lines[i + 1] ?? \"\";\n if (/^>/.test(prev) && /^>/.test(next) && !/^> \\[!/.test(next)) {\n result.push(\">\");\n continue;\n }\n }\n result.push(line);\n }\n return result.join(\"\\n\");\n}\n","import type { Config, DatabaseSyncConfig } from \"../types/config.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport type { VaultFS } from \"./vault-fs.js\";\nimport type { ConversionPipeline } from \"../converter/pipeline.js\";\nimport type { Conflict, FailedOperation, SyncRecord } from \"../types/sync.js\";\nimport type { DatabaseViewsConfig } from \"../types/view.js\";\nimport type { PageObjectResponse } from \"@notionhq/client/build/src/api-endpoints.js\";\nimport { PropertyMapper } from \"../notion/property-mapper.js\";\nimport type { ImageHandler } from \"./image-handler.js\";\nimport { resolvePullConflict } from \"./conflict-detector.js\";\nimport { computeHash } from \"../utils/hash.js\";\nimport { sanitizeFileName } from \"../utils/sanitize.js\";\nimport { resolveDbRowPath, selectDbRowFiles } from \"../utils/db-row-path.js\";\nimport { wikilinkTitleFromPath } from \"../utils/wikilink-title.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { BaseFileGenerator } from \"../view/base-file-generator.js\";\nimport { SidecarGenerator } from \"../view/sidecar-generator.js\";\nimport { selectStaleDbArtifacts } from \"./stale-db-artifacts.js\";\nimport { INTERNAL_DIR, DB_VIEWS_PATH } from \"../constants/paths.js\";\nimport {\n notionEnhancedToObsidian,\n obsidianToNotionEnhanced,\n} from \"../converter/enhanced-md-converter.js\";\nimport { isCompactExport } from \"../converter/post-processors/block-spacer.js\";\nimport matter from \"gray-matter\";\n\nexport interface DatabaseSyncResult {\n created: number;\n updated: number;\n /** Pull 시 로컬·리모트 동시 수정으로 발생한 충돌 (push 는 항상 빈 배열). */\n conflicts: Conflict[];\n failed: FailedOperation[];\n /**\n * 이번 pull 에서 실제로 디스크에 기록한 db-row 파일 경로(SSOT).\n * 오케스트레이터의 링크 해소(resolveNotionLinks) 대상은 반드시 이 목록으로 정한다 —\n * 과거의 `getByStatus(\"synced\").slice(-N)` 휴리스틱은 ORDER BY 가 없어 증분 pull 에서\n * 엉뚱한 행을 골라 정작 바뀐 행의 relation UUID 를 영영 해소하지 못했다(M3). push 경로는 항상 빈 배열.\n */\n writtenPaths: string[];\n}\n\n/** {@link DatabaseSyncer.pullDatabasePage} 의 처리 결과. */\ntype PullPageOutcome =\n | { action: \"written\"; path: string }\n | { action: \"skipped\"; path: string }\n | { action: \"conflict\"; path: string; conflict: Conflict };\n\nexport class DatabaseSyncer {\n private readonly propertyMapper = new PropertyMapper();\n private readonly baseFileGenerator = new BaseFileGenerator();\n private readonly sidecarGenerator = new SidecarGenerator();\n\n constructor(\n private readonly config: Config,\n private readonly stateDb: IStateDB,\n private readonly notionClient: NotionClient,\n private readonly vaultFs: VaultFS,\n private readonly pipeline: ConversionPipeline,\n private readonly imageHandler: ImageHandler,\n ) {\n this.propertyMapper.setWikilinkResolver({\n resolve: (title: string) => stateDb.resolveWikilink(title)?.notionPageId ?? null,\n // M4: 후처리 패스(resolveNotionLinks)와 동일하게 파일 basename 으로 해소 — 원시 제목과\n // sanitize 된 파일명의 불일치로 인한 깨진/이중 위키링크 차단.\n resolvePageId: (pageId: string) => {\n const entry = stateDb.resolvePageId(pageId);\n return entry ? wikilinkTitleFromPath(entry.obsidianPath) : null;\n },\n });\n }\n\n async pullAll(): Promise<DatabaseSyncResult> {\n const databases = this.config.notion.databases;\n if (!databases || databases.length === 0) {\n return { created: 0, updated: 0, conflicts: [], failed: [], writtenPaths: [] };\n }\n\n let created = 0;\n let updated = 0;\n const conflicts: Conflict[] = [];\n const failed: FailedOperation[] = [];\n const writtenPaths: string[] = [];\n\n for (const dbConfig of databases) {\n try {\n const result = await this.pullDatabase(dbConfig);\n created += result.created;\n updated += result.updated;\n conflicts.push(...result.conflicts);\n failed.push(...result.failed);\n writtenPaths.push(...result.writtenPaths);\n } catch (error) {\n getLogger().warn(`[DB Sync] DB ${dbConfig.databaseId} pull 실패:`, error);\n failed.push({\n path: dbConfig.localFolder,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return { created, updated, conflicts, failed, writtenPaths };\n }\n\n async pushAll(): Promise<DatabaseSyncResult> {\n const databases = this.config.notion.databases;\n if (!databases || databases.length === 0) {\n return { created: 0, updated: 0, conflicts: [], failed: [], writtenPaths: [] };\n }\n\n let created = 0;\n let updated = 0;\n const failed: FailedOperation[] = [];\n\n for (const dbConfig of databases) {\n try {\n const result = await this.pushDatabase(dbConfig);\n created += result.created;\n updated += result.updated;\n failed.push(...result.failed);\n } catch (error) {\n getLogger().warn(`[DB Sync] DB ${dbConfig.databaseId} push 실패:`, error);\n failed.push({\n path: dbConfig.localFolder,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return { created, updated, conflicts: [], failed, writtenPaths: [] };\n }\n\n async pullDatabase(dbConfig: DatabaseSyncConfig): Promise<DatabaseSyncResult> {\n const schema = await this.notionClient.getDatabaseSchema(dbConfig.databaseId);\n this.propertyMapper.loadSchema(schema);\n\n await this.vaultFs.ensureFolder(dbConfig.localFolder);\n\n const viewsConfig = await this.pullDatabaseViews(dbConfig);\n await this.generateBaseFile(dbConfig, viewsConfig);\n\n const pages = await this.notionClient.queryAllDatabasePages(\n dbConfig.databaseId,\n dbConfig.pullFilter,\n );\n\n let created = 0;\n let updated = 0;\n const conflicts: Conflict[] = [];\n const failed: FailedOperation[] = [];\n // M3: 실제로 디스크에 기록된 DB 행 경로 — 후처리 링크 해소(resolveNotionLinks)가\n // 정확히 이 파일들만 재방문하도록 슬라이스 추정 대신 실측 수집한다.\n const writtenPaths: string[] = [];\n\n for (const page of pages) {\n try {\n const record = this.stateDb.getByNotionId(page.id);\n\n if (record) {\n // 리모트가 마지막 동기화 시점과 동일하면 건너뜀.\n if (page.last_edited_time === record.notionLastEdited) continue;\n const outcome = await this.pullDatabasePage(page, dbConfig);\n if (outcome.action === \"written\") {\n updated++;\n writtenPaths.push(outcome.path);\n } else if (outcome.action === \"conflict\") {\n conflicts.push(outcome.conflict);\n }\n // skipped(local-first): 카운트하지 않음\n } else {\n const outcome = await this.pullDatabasePage(page, dbConfig);\n created++;\n if (outcome.action === \"written\") {\n writtenPaths.push(outcome.path);\n }\n }\n } catch (error) {\n failed.push({\n path: `${dbConfig.localFolder}/${page.id}`,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n getLogger().debug(\n `[DB Sync] ${dbConfig.localFolder}: ${created} 생성, ${updated} 업데이트, ${conflicts.length} 충돌`,\n );\n return { created, updated, conflicts, failed, writtenPaths };\n }\n\n private async pullDatabaseViews(\n dbConfig: DatabaseSyncConfig,\n force = false,\n ): Promise<DatabaseViewsConfig | null> {\n try {\n const configPath = DB_VIEWS_PATH;\n\n if (!force) {\n try {\n const existing = await this.vaultFs.readFile(configPath);\n const parsed = JSON.parse(existing) as Record<string, DatabaseViewsConfig>;\n if (parsed[dbConfig.databaseId]) return parsed[dbConfig.databaseId]!;\n } catch {\n // 파일 없으면 계속 진행\n }\n }\n\n const viewsConfig = await this.notionClient.getDatabaseViewsConfig(dbConfig.databaseId);\n await this.vaultFs.ensureFolder(INTERNAL_DIR);\n\n let allViewsConfigs: Record<string, DatabaseViewsConfig> = {};\n try {\n const existing = await this.vaultFs.readFile(configPath);\n allViewsConfigs = JSON.parse(existing) as Record<string, DatabaseViewsConfig>;\n } catch {\n // 파일 없으면 빈 객체\n }\n\n allViewsConfigs[dbConfig.databaseId] = viewsConfig;\n await this.vaultFs.writeFile(configPath, JSON.stringify(allViewsConfigs, null, 2));\n getLogger().debug(\n `[DB Sync] 뷰 설정 ${viewsConfig.views.length}개 저장: ${dbConfig.databaseId}`,\n );\n return viewsConfig;\n } catch (error) {\n getLogger().warn(`[DB Sync] 뷰 설정 Pull 실패 (계속 진행):`, error);\n return null;\n }\n }\n\n private async generateBaseFile(\n dbConfig: DatabaseSyncConfig,\n viewsConfig: DatabaseViewsConfig | null,\n ): Promise<void> {\n try {\n const schemaFull = await this.notionClient.getDatabaseSchemaFull(dbConfig.databaseId);\n const dbName =\n viewsConfig?.databaseName ||\n (await this.notionClient.getDatabaseTitle(dbConfig.databaseId)) ||\n dbConfig.localFolder.split(\"/\").pop() ||\n \"Database\";\n\n const resolvedViews: DatabaseViewsConfig = viewsConfig ?? {\n databaseId: dbConfig.databaseId,\n databaseName: dbName,\n lastSynced: new Date().toISOString(),\n views: [{ id: \"default\", name: \"Table\", type: \"table\" }],\n };\n\n const baseContent = this.baseFileGenerator.generate({\n databaseId: dbConfig.databaseId,\n databaseName: dbName,\n schema: schemaFull,\n viewsConfig: resolvedViews,\n folderPath: dbConfig.localFolder,\n });\n\n const safeName = sanitizeFileName(dbName);\n const basePath = `${dbConfig.localFolder}/${safeName}.base`;\n await this.vaultFs.writeFile(basePath, baseContent);\n getLogger().debug(`[DB Sync] .base 파일 생성: ${basePath}`);\n\n await this.generateSidecar(dbConfig, dbName, safeName, schemaFull, resolvedViews);\n await this.cleanupStaleDbArtifacts(dbConfig.localFolder, safeName);\n } catch (error) {\n getLogger().warn(`[DB Sync] .base 파일 생성 실패 (계속 진행):`, error);\n }\n }\n\n /**\n * DB 제목이 바뀌면 `.base`/`.notion.json` 파일명(safeName)이 바뀌어 옛 이름의 산출물이\n * 같은 폴더에 고아로 잔존한다(drift·부활 원인). DB 폴더 **직속**의 산출물 중 현재 이름이\n * 아닌 것을 삭제해 멱등을 보장한다. 하위 폴더(중첩 DB)의 산출물은 보호한다.\n */\n private async cleanupStaleDbArtifacts(localFolder: string, safeName: string): Promise<void> {\n try {\n const keep = new Set([\n `${localFolder}/${safeName}.base`,\n `${localFolder}/${safeName}.notion.json`,\n ]);\n const files = await this.vaultFs.listNonMarkdownFiles();\n const stale = selectStaleDbArtifacts(files, localFolder, keep);\n for (const path of stale) {\n await this.vaultFs.deleteFile(path);\n getLogger().info(`[DB Sync] 고아 DB 산출물 삭제(rename): ${path}`);\n }\n } catch (error) {\n getLogger().warn(`[DB Sync] 고아 .base/.notion.json 정리 실패 (계속 진행):`, error);\n }\n }\n\n /**\n * `.base` 가 표현하지 못하는 Notion DB 메타데이터(미지원 뷰·필터식·커버크기 등)를\n * 사이드카 `<db>.notion.json` 으로 무손실 보존하고, degrade 된 항목을 정직하게 로그한다.\n * 결정적 직렬화라 동일 DB 상태 → 동일 바이트 → 멱등(drift/churn 0).\n */\n private async generateSidecar(\n dbConfig: DatabaseSyncConfig,\n dbName: string,\n safeName: string,\n schemaFull: Record<string, { id: string; type: string; options?: Array<{ name: string }> }>,\n resolvedViews: DatabaseViewsConfig,\n ): Promise<void> {\n try {\n const sidecar = this.sidecarGenerator.build({\n databaseId: dbConfig.databaseId,\n databaseName: dbName,\n schema: schemaFull,\n viewsConfig: resolvedViews,\n });\n const sidecarPath = `${dbConfig.localFolder}/${safeName}.notion.json`;\n await this.vaultFs.writeFile(sidecarPath, this.sidecarGenerator.serialize(sidecar));\n\n if (sidecar.degraded.length > 0) {\n const unrep = sidecar.degraded.filter((d) => d.kind === \"view-unrepresentable\").length;\n const dropped = sidecar.degraded.length - unrep;\n getLogger().info(\n `[DB Sync] '${dbName}' degrade ${sidecar.degraded.length}건` +\n ` (미표현 뷰 ${unrep} · 미표현 설정 ${dropped}) → ${safeName}.notion.json 보존`,\n );\n }\n } catch (error) {\n getLogger().warn(`[DB Sync] 사이드카 생성 실패 (계속 진행):`, error);\n }\n }\n\n private async pullDatabasePage(\n page: PageObjectResponse,\n dbConfig: DatabaseSyncConfig,\n ): Promise<PullPageOutcome> {\n const title = this.notionClient.extractTitle(page);\n const safeName = sanitizeFileName(title);\n\n const properties = this.propertyMapper.fromNotionProperties(\n (page as unknown as { properties: Record<string, unknown> }).properties,\n );\n properties.title = title;\n\n const cover = this.notionClient.extractCover(page);\n const icon = this.notionClient.extractIcon(page);\n\n if (cover) {\n try {\n const coverResult = await this.imageHandler.downloadAllImages(\n `![cover](${cover.url})`,\n `${safeName}-cover`,\n );\n // 이미지 핸들러가 실제 로컬 첨부 경로로 치환했을 때만 위키링크로 감싼다.\n // 다운로드 비활성/실패 시엔 원격 URL이 그대로 돌아오는데, 이를 `[[..]]` 로\n // 감싸면 존재하지 않는 `[[https://..]]` 파일을 가리키는 깨진 링크가 된다(cover-URL).\n const resolved = coverResult.content.match(/!\\[cover\\]\\((.+?)\\)/)?.[1];\n if (resolved && !/^https?:\\/\\//i.test(resolved)) {\n properties.cover = `[[${resolved}]]`;\n } else {\n properties.cover = cover.url;\n }\n } catch {\n properties.cover = cover.url;\n }\n }\n\n if (icon) {\n properties.icon = icon.value;\n }\n\n let markdown = \"\";\n let exportCompact = false;\n try {\n const mdResult = await this.notionClient.getPageMarkdown(page.id);\n // 압축형 판정은 원시 export 기준(D1) — enhanced 변환 후에는 판정 불가\n exportCompact = isCompactExport(mdResult.markdown);\n markdown = notionEnhancedToObsidian(mdResult.markdown);\n } catch {\n // Markdown API 실패 시 빈 내용\n }\n\n if (this.config.conversion.imageDownload === \"immediate\" && markdown) {\n try {\n const imageResult = await this.imageHandler.downloadAllImages(markdown, title);\n markdown = imageResult.content;\n } catch (error) {\n getLogger().warn(`[DB Sync] 이미지 다운로드 실패 (${title}):`, error);\n }\n }\n\n if (markdown) {\n try {\n const fileResult = await this.imageHandler.downloadAllFiles(markdown, title);\n markdown = fileResult.content;\n } catch (error) {\n getLogger().warn(`[DB Sync] 파일 다운로드 실패 (${title}):`, error);\n }\n }\n\n const existingRecord = this.stateDb.getByNotionId(page.id);\n let filePath: string;\n if (existingRecord?.obsidianPath) {\n filePath = existingRecord.obsidianPath;\n } else {\n filePath = resolveDbRowPath(dbConfig.localFolder, safeName, page.id, (p) =>\n this.stateDb.getByPath(p),\n );\n }\n\n const finalContent = this.pipeline.convertToMarkdown(\n markdown,\n {\n direction: \"pull\",\n path: \"markdown-api\",\n filePath,\n parentMode: \"database\",\n },\n { properties, notionExportCompact: exportCompact },\n );\n\n // 기존 추적 레코드가 있으면 무조건 덮어쓰기 전에 로컬 수정 여부를 검사한다.\n // (신규 페이지는 existingRecord 가 없으므로 충돌 검사 없이 바로 기록 — 로컬 파일 미존재)\n if (existingRecord) {\n let localContent = \"\";\n try {\n localContent = await this.vaultFs.readFile(filePath);\n } catch {\n localContent = \"\";\n }\n\n const resolution = resolvePullConflict({\n record: existingRecord,\n localContent,\n remoteContent: finalContent,\n remoteChange: {\n pageId: page.id,\n type: \"modified\",\n lastEdited: page.last_edited_time,\n previousEdited: existingRecord.notionLastEdited,\n },\n strategy: this.config.sync.conflictStrategy,\n });\n\n if (resolution.action === \"skip\") {\n // local-first: 로컬 보존, 리모트 변경 무시\n return { action: \"skipped\", path: filePath };\n }\n if (resolution.action === \"conflict\") {\n // 양쪽 모두 수정됨 → 충돌로 표시하고 로컬 보존 (사용자 해소 대기)\n this.stateDb.updateStatus(existingRecord.id, \"conflict\");\n return { action: \"conflict\", path: filePath, conflict: resolution.conflict! };\n }\n // resolution.action === \"write\" → 아래로 진행하여 덮어쓰기\n }\n\n await this.vaultFs.ensureFolder(dbConfig.localFolder);\n await this.vaultFs.writeFile(filePath, finalContent);\n\n const hash = computeHash(finalContent);\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: filePath,\n notionPageId: page.id,\n notionParentId: dbConfig.databaseId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: \"db-row\",\n status: \"synced\",\n baseSnapshot: Buffer.from(finalContent, \"utf-8\"),\n });\n\n this.stateDb.upsertWikilink({\n obsidianPath: filePath,\n notionPageId: page.id,\n title,\n aliases: extractAliases(properties),\n });\n });\n\n return { action: \"written\", path: filePath };\n }\n\n private async pushDatabase(dbConfig: DatabaseSyncConfig): Promise<DatabaseSyncResult> {\n const schema = await this.notionClient.getDatabaseSchema(dbConfig.databaseId);\n this.propertyMapper.loadSchema(schema);\n\n const allFiles = await this.vaultFs.listMarkdownFiles();\n // 직속 행 파일만 — 중첩 하위 폴더(별도 child_database)의 행은 각자의 DB push 가 관리하므로\n // 부모 DB 로 잘못 밀어 중복·오배치하지 않는다(오포함 차단).\n const dbFiles = selectDbRowFiles(allFiles, dbConfig.localFolder);\n\n // rename 감지용 고아 레코드(로컬 파일이 사라진 추적 레코드) 인덱스.\n // 새 경로의 파일이 어떤 고아의 내용 해시와 일치하면 신규 페이지 생성이 아니라 rename 으로 처리.\n const livePaths = new Set(dbFiles.map((f) => f.path));\n const orphanByHash = this.buildOrphanHashIndex(dbConfig.databaseId, livePaths);\n\n let created = 0;\n let updated = 0;\n const failed: FailedOperation[] = [];\n\n for (const file of dbFiles) {\n try {\n const content = await this.vaultFs.readFile(file.path);\n const hash = computeHash(content);\n\n const record = this.stateDb.getByPath(file.path);\n if (record?.contentHash === hash) continue;\n\n const parsed = matter(content);\n const frontmatter = parsed.data as Record<string, unknown>;\n const body = parsed.content;\n\n const title = (frontmatter.title as string) ?? extractTitleFromPath(file.path);\n delete frontmatter.title;\n\n const notionProps = this.propertyMapper.toNotionProperties(frontmatter, title);\n const enhanced = obsidianToNotionEnhanced(body.trim());\n\n if (record?.notionPageId) {\n try {\n await this.notionClient.updatePageProperties(record.notionPageId, notionProps);\n await this.notionClient.replacePageMarkdown(record.notionPageId, enhanced);\n } catch (error) {\n // push 실패: 본문/속성이 Notion 에 반영되지 않았으므로 해시를 전진시키거나\n // synced 로 표시하지 않는다. (과거: 본문 실패를 삼키고 synced 처리 → 거짓 동기화·\n // 본문 영구 유실. 해시 전진 탓에 다음 push 에서 스킵되어 변경이 영원히 전달 안 됨)\n this.stateDb.updateStatus(record.id, \"error\");\n failed.push({\n path: file.path,\n operation: \"update\",\n error: error instanceof Error ? error.message : String(error),\n });\n continue;\n }\n\n const updatedPage = await this.notionClient.getPage(record.notionPageId);\n this.stateDb.transaction(() => {\n this.stateDb.updateHash(record.id, hash, Buffer.from(content, \"utf-8\"));\n this.stateDb.updateStatus(record.id, \"synced\");\n this.stateDb.setNotionLastEdited(record.id, updatedPage.last_edited_time);\n // 제목/별칭이 바뀌었을 수 있으므로 wikilink 도 함께 갱신해 최신성을 보장한다.\n this.stateDb.upsertWikilink({\n obsidianPath: file.path,\n notionPageId: record.notionPageId!,\n title,\n aliases: extractAliases(frontmatter),\n });\n });\n updated++;\n } else {\n // rename 감지: 내용이 동일한 고아 레코드가 있으면 신규 페이지 생성 대신 경로만 재매핑.\n // (과거: getByPath(newPath)=null → 무조건 신규 생성 → Notion 중복 페이지 + 고아 레코드.\n // db-row 프론트매터엔 Notion page id 가 없어 내용 해시로 동일 행을 식별한다.)\n const renamed = orphanByHash.get(hash);\n if (renamed?.notionPageId) {\n const movedPageId = renamed.notionPageId;\n orphanByHash.delete(hash); // 같은 고아를 두 번 매칭하지 않도록 제거\n this.stateDb.transaction(() => {\n this.stateDb.updatePath(renamed.id, file.path);\n this.stateDb.updateHash(renamed.id, hash, Buffer.from(content, \"utf-8\"));\n this.stateDb.updateStatus(renamed.id, \"synced\");\n // 새 경로로 wikilink 갱신 — INSERT OR REPLACE 가 notion_page_id UNIQUE 충돌로\n // 이전 경로의 wikilink 행을 자동 정리한다.\n this.stateDb.upsertWikilink({\n obsidianPath: file.path,\n notionPageId: movedPageId,\n title,\n aliases: extractAliases(frontmatter),\n });\n });\n updated++;\n continue;\n }\n\n const page = await this.notionClient.createPageWithMarkdown({\n parentId: dbConfig.databaseId,\n parentType: \"database\",\n title,\n markdown: enhanced,\n properties: notionProps,\n });\n\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: file.path,\n notionPageId: page.id,\n notionParentId: dbConfig.databaseId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: \"db-row\",\n status: \"synced\",\n baseSnapshot: Buffer.from(content, \"utf-8\"),\n });\n\n this.stateDb.upsertWikilink({\n obsidianPath: file.path,\n notionPageId: page.id,\n title,\n aliases: extractAliases(frontmatter),\n });\n });\n created++;\n }\n } catch (error) {\n failed.push({\n path: file.path,\n operation: \"create\",\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n getLogger().debug(`[DB Sync] ${dbConfig.localFolder}: ${created} 생성, ${updated} 업데이트`);\n return { created, updated, conflicts: [], failed, writtenPaths: [] };\n }\n\n /**\n * rename 감지를 위한 고아 레코드 인덱스(내용 해시 → 레코드)를 만든다.\n * 고아 = 해당 DB 소속 db-row 레코드 중 로컬 파일이 더 이상 존재하지 않는(livePaths 에 없는) 것.\n * 같은 해시가 여러 고아에 걸리면 첫 항목을 유지한다(희박한 케이스).\n */\n private buildOrphanHashIndex(\n databaseId: string,\n livePaths: Set<string>,\n ): Map<string, SyncRecord> {\n const index = new Map<string, SyncRecord>();\n for (const record of this.stateDb.getAll()) {\n if (\n record.fileType === \"db-row\" &&\n record.notionParentId === databaseId &&\n record.notionPageId &&\n !livePaths.has(record.obsidianPath) &&\n !index.has(record.contentHash)\n ) {\n index.set(record.contentHash, record);\n }\n }\n return index;\n }\n}\n\nfunction extractAliases(properties: Record<string, unknown>): string[] {\n const raw = properties.aliases ?? properties.alias;\n if (!raw) return [];\n if (Array.isArray(raw)) return raw.filter((a): a is string => typeof a === \"string\");\n if (typeof raw === \"string\")\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return [];\n}\n\nfunction extractTitleFromPath(filePath: string): string {\n const parts = filePath.split(\"/\");\n const filename = parts[parts.length - 1] ?? \"\";\n return filename.replace(/\\.md$/, \"\");\n}\n","export interface MergeResult {\n readonly success: boolean;\n readonly merged: string;\n readonly conflicts: MergeConflictRegion[];\n}\n\nexport interface MergeConflictRegion {\n readonly localLines: string[];\n readonly remoteLines: string[];\n}\n\n/** base 한 쪽(local 또는 remote)의 변경 조각. base[baseStart, baseEnd) 구간을 content 로 치환. */\ninterface Hunk {\n readonly baseStart: number;\n readonly baseEnd: number;\n readonly content: string[];\n /** 0 = local, 2 = remote (정렬 시 동률이면 local 우선). */\n readonly side: 0 | 2;\n}\n\n/**\n * 3-way 병합 (diff3). base 를 공통 조상으로 보고 local/remote 의 변경을 합친다.\n *\n * 표준 diff3 알고리즘:\n * 1. base↔local, base↔remote 각각의 LCS 로 \"변경 조각(hunk)\"을 추출한다.\n * (hunk = base 의 어떤 구간 [baseStart, baseEnd) 을 새 내용으로 치환·삭제·삽입)\n * 2. 모든 hunk 를 base 위치순으로 정렬하고, **base 구간이 겹치는** hunk 들을\n * 하나의 region 으로 묶는다. 겹치지 않는 hunk 사이의 base 줄은 양쪽 공통이므로 그대로 출력.\n * 3. 각 region 에서 local/remote 가 만들어낸 내용을 비교해 판정한다.\n * - local 결과 == base → local 미변경 → remote 채택\n * - remote 결과 == base → remote 미변경 → local 채택\n * - local 결과 == remote 결과 → 동일 변경 → 한쪽 채택\n * - 그 외 → 충돌 (양쪽이 같은 구간을 다르게 변경)\n *\n * 핵심은 hunk 의 base 구간이 **실제로 겹칠 때만** 충돌로 본다는 점이다. 서로 다른(인접\n * 포함) 줄을 고친 삽입·삭제·수정은 충돌 없이 합쳐진다. (이전 단순 라인-치환 구현은\n * 삽입/삭제를 오정렬해 거짓 충돌을 만들거나 무한 루프에 빠질 수 있었다.)\n */\nexport function threeWayMerge(base: string, local: string, remote: string): MergeResult {\n const baseLines = base.split(\"\\n\");\n const localLines = local.split(\"\\n\");\n const remoteLines = remote.split(\"\\n\");\n\n const hunks = [\n ...computeHunks(baseLines, localLines, 0),\n ...computeHunks(baseLines, remoteLines, 2),\n ];\n // base 시작 위치 오름차순, 동률이면 local(0) 먼저.\n hunks.sort((a, b) => a.baseStart - b.baseStart || a.side - b.side);\n\n const merged: string[] = [];\n const conflicts: MergeConflictRegion[] = [];\n let cursor = 0; // 다음에 출력할 base 인덱스.\n let i = 0;\n\n while (i < hunks.length) {\n const first = hunks[i]!;\n // region 앞쪽의 공통(안정) base 줄을 그대로 출력.\n if (first.baseStart > cursor) {\n merged.push(...baseLines.slice(cursor, first.baseStart));\n }\n\n const regionStart = first.baseStart;\n let regionEnd = first.baseEnd;\n const group: Hunk[] = [first];\n i++;\n\n // base 구간이 겹치는 hunk 들을 한 region 으로 흡수.\n // - 일반 겹침: 다음 hunk 의 시작이 regionEnd 보다 앞(strict).\n // - 같은 지점의 순수 삽입(regionEnd === regionStart): 시작 위치가 같으면 함께 묶는다\n // (양쪽이 같은 자리에 삽입 → 동일하면 1회, 다르면 충돌).\n while (i < hunks.length) {\n const next = hunks[i]!;\n const overlaps =\n next.baseStart < regionEnd || (regionEnd === regionStart && next.baseStart === regionStart);\n if (!overlaps) break;\n regionEnd = Math.max(regionEnd, next.baseEnd);\n group.push(next);\n i++;\n }\n\n const baseRegion = baseLines.slice(regionStart, regionEnd);\n const localRegion = applyHunks(baseLines, group, 0, regionStart, regionEnd);\n const remoteRegion = applyHunks(baseLines, group, 2, regionStart, regionEnd);\n\n if (arraysEqual(localRegion, baseRegion)) {\n merged.push(...remoteRegion); // local 미변경 → remote 채택\n } else if (arraysEqual(remoteRegion, baseRegion)) {\n merged.push(...localRegion); // remote 미변경 → local 채택\n } else if (arraysEqual(localRegion, remoteRegion)) {\n merged.push(...localRegion); // 동일 변경\n } else {\n conflicts.push({ localLines: localRegion, remoteLines: remoteRegion });\n merged.push(\"<<<<<<< LOCAL\");\n merged.push(...localRegion);\n merged.push(\"=======\");\n merged.push(...remoteRegion);\n merged.push(\">>>>>>> REMOTE\");\n }\n\n cursor = regionEnd;\n }\n\n // 마지막 region 이후의 공통 base 줄.\n if (cursor < baseLines.length) {\n merged.push(...baseLines.slice(cursor));\n }\n\n return {\n success: conflicts.length === 0,\n merged: merged.join(\"\\n\"),\n conflicts,\n };\n}\n\n/**\n * base 와 modified 의 LCS 매칭을 기준으로 변경 조각(hunk) 목록을 만든다.\n * 매칭되지 않은(=변경된) base 구간과 그에 대응하는 modified 구간을 한 hunk 로 묶는다.\n */\nfunction computeHunks(base: string[], modified: string[], side: 0 | 2): Hunk[] {\n const matches = lcsMatches(base, modified); // [baseIdx, modIdx] 오름차순\n const hunks: Hunk[] = [];\n\n let prevBase = -1;\n let prevMod = -1;\n const emitGap = (curBase: number, curMod: number): void => {\n const baseLen = curBase - (prevBase + 1);\n const modLen = curMod - (prevMod + 1);\n if (baseLen > 0 || modLen > 0) {\n hunks.push({\n baseStart: prevBase + 1,\n baseEnd: curBase,\n content: modified.slice(prevMod + 1, curMod),\n side,\n });\n }\n };\n\n for (const [b, m] of matches) {\n emitGap(b, m);\n prevBase = b;\n prevMod = m;\n }\n emitGap(base.length, modified.length); // 마지막 매칭 이후 꼬리.\n\n return hunks;\n}\n\n/**\n * region [regionStart, regionEnd) 에 대해 한 쪽(side)이 만들어낸 내용을 재구성한다.\n * 해당 side 의 hunk 는 base 를 치환하고, hunk 가 없는 base 줄은 그대로 복사한다.\n * region 경계는 항상 hunk 경계와 정렬되므로 hunk 가 region 을 가로지르지 않는다.\n */\nfunction applyHunks(\n baseLines: string[],\n group: Hunk[],\n side: 0 | 2,\n regionStart: number,\n regionEnd: number,\n): string[] {\n const out: string[] = [];\n let b = regionStart;\n for (const hunk of group) {\n if (hunk.side !== side) continue;\n if (hunk.baseStart > b) out.push(...baseLines.slice(b, hunk.baseStart));\n out.push(...hunk.content);\n b = hunk.baseEnd;\n }\n if (b < regionEnd) out.push(...baseLines.slice(b, regionEnd));\n return out;\n}\n\n/**\n * a 와 b 의 LCS 매칭 쌍 [aIndex, bIndex] 을 a 인덱스 오름차순으로 반환한다.\n * 라인 단위 비교(보통 수백~수천 줄)라 O(n·m) DP 로 충분하다.\n */\nfunction lcsMatches(a: string[], b: string[]): Array<[number, number]> {\n const n = a.length;\n const m = b.length;\n\n // dp[i][j] = a[i..], b[j..] 의 LCS 길이. 행마다 Uint32Array 로 메모리 절약.\n const dp: Uint32Array[] = new Array(n + 1);\n for (let i = 0; i <= n; i++) dp[i] = new Uint32Array(m + 1);\n\n for (let i = n - 1; i >= 0; i--) {\n const row = dp[i]!;\n const next = dp[i + 1]!;\n const ai = a[i];\n for (let j = m - 1; j >= 0; j--) {\n row[j] = ai === b[j] ? next[j + 1]! + 1 : Math.max(next[j]!, row[j + 1]!);\n }\n }\n\n const matches: Array<[number, number]> = [];\n let i = 0;\n let j = 0;\n while (i < n && j < m) {\n if (a[i] === b[j]) {\n matches.push([i, j]);\n i++;\n j++;\n } else if (dp[i + 1]![j]! >= dp[i]![j + 1]!) {\n i++;\n } else {\n j++;\n }\n }\n\n return matches;\n}\n\nfunction arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((val, idx) => val === b[idx]);\n}\n","import type { Conflict, ConflictStrategy } from \"../types/sync.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { VaultFS } from \"../sync/vault-fs.js\";\nimport { threeWayMerge } from \"./merger.js\";\nimport { computeHash } from \"../utils/hash.js\";\n\nexport type ResolutionChoice = \"local\" | \"remote\" | \"merge\" | \"duplicate\";\n\nexport interface ResolutionResult {\n readonly path: string;\n readonly choice: ResolutionChoice;\n readonly success: boolean;\n readonly mergeHadConflicts?: boolean;\n}\n\nexport class ConflictResolver {\n constructor(\n private readonly stateDb: IStateDB,\n private readonly vaultFs: VaultFS,\n ) {}\n\n async resolve(conflict: Conflict, choice: ResolutionChoice): Promise<ResolutionResult> {\n switch (choice) {\n case \"local\":\n return this.resolveLocal(conflict);\n case \"remote\":\n return this.resolveRemote(conflict);\n case \"merge\":\n return this.resolveMerge(conflict);\n case \"duplicate\":\n return this.resolveDuplicate(conflict);\n }\n }\n\n async resolveByStrategy(\n conflict: Conflict,\n strategy: ConflictStrategy,\n ): Promise<ResolutionResult> {\n switch (strategy) {\n case \"local-first\":\n return this.resolve(conflict, \"local\");\n case \"remote-first\":\n return this.resolve(conflict, \"remote\");\n case \"duplicate\":\n return this.resolve(conflict, \"duplicate\");\n case \"manual\":\n return this.resolve(conflict, \"merge\");\n }\n }\n\n async resolveAll(conflicts: Conflict[], strategy: ConflictStrategy): Promise<ResolutionResult[]> {\n const results: ResolutionResult[] = [];\n for (const conflict of conflicts) {\n const result = await this.resolveByStrategy(conflict, strategy);\n results.push(result);\n }\n return results;\n }\n\n private async resolveLocal(conflict: Conflict): Promise<ResolutionResult> {\n const hash = computeHash(conflict.localContent);\n this.stateDb.updateHash(\n conflict.syncRecord.id,\n hash,\n Buffer.from(conflict.localContent, \"utf-8\"),\n );\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n\n return { path: conflict.syncRecord.obsidianPath, choice: \"local\", success: true };\n }\n\n private async resolveRemote(conflict: Conflict): Promise<ResolutionResult> {\n await this.vaultFs.writeFile(conflict.syncRecord.obsidianPath, conflict.remoteContent);\n\n const hash = computeHash(conflict.remoteContent);\n this.stateDb.updateHash(\n conflict.syncRecord.id,\n hash,\n Buffer.from(conflict.remoteContent, \"utf-8\"),\n );\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n\n return { path: conflict.syncRecord.obsidianPath, choice: \"remote\", success: true };\n }\n\n private async resolveMerge(conflict: Conflict): Promise<ResolutionResult> {\n const base = conflict.baseContent ?? \"\";\n const mergeResult = threeWayMerge(base, conflict.localContent, conflict.remoteContent);\n\n await this.vaultFs.writeFile(conflict.syncRecord.obsidianPath, mergeResult.merged);\n\n const hash = computeHash(mergeResult.merged);\n this.stateDb.updateHash(conflict.syncRecord.id, hash, Buffer.from(mergeResult.merged, \"utf-8\"));\n\n if (mergeResult.success) {\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n }\n\n return {\n path: conflict.syncRecord.obsidianPath,\n choice: \"merge\",\n success: mergeResult.success,\n mergeHadConflicts: !mergeResult.success,\n };\n }\n\n private async resolveDuplicate(conflict: Conflict): Promise<ResolutionResult> {\n const originalPath = conflict.syncRecord.obsidianPath;\n const ext = originalPath.endsWith(\".md\") ? \".md\" : \"\";\n const baseName = originalPath.replace(/\\.md$/, \"\");\n const conflictPath = `${baseName}.conflict${ext}`;\n\n await this.vaultFs.writeFile(conflictPath, conflict.remoteContent);\n\n const localHash = computeHash(conflict.localContent);\n this.stateDb.updateHash(\n conflict.syncRecord.id,\n localHash,\n Buffer.from(conflict.localContent, \"utf-8\"),\n );\n this.stateDb.updateStatus(conflict.syncRecord.id, \"synced\");\n\n return { path: originalPath, choice: \"duplicate\", success: true };\n }\n\n generateDiff(conflict: Conflict): string {\n const localLines = conflict.localContent.split(\"\\n\");\n const remoteLines = conflict.remoteContent.split(\"\\n\");\n const lines: string[] = [];\n\n lines.push(`--- local: ${conflict.syncRecord.obsidianPath}`);\n lines.push(`+++ remote: Notion (${conflict.remoteChange.pageId})`);\n lines.push(\"\");\n\n const maxLen = Math.max(localLines.length, remoteLines.length);\n for (let i = 0; i < maxLen; i++) {\n const localLine = localLines[i];\n const remoteLine = remoteLines[i];\n\n if (localLine === remoteLine) {\n lines.push(` ${localLine ?? \"\"}`);\n } else {\n if (localLine !== undefined) lines.push(`- ${localLine}`);\n if (remoteLine !== undefined) lines.push(`+ ${remoteLine}`);\n }\n }\n\n return lines.join(\"\\n\");\n }\n}\n","/**\n * 취소 신호. `AbortSignal` 과 호환되며, 테스트에서 가벼운 목 객체로도 쓸 수 있다.\n */\nexport interface AbortLike {\n readonly aborted: boolean;\n}\n\nexport interface PoolOptions {\n /** 동시에 동작할 최대 worker 수. 1 미만이면 1로 보정한다. */\n readonly concurrency: number;\n /** 설정되면 `aborted === true` 인 순간부터 새 항목 처리를 멈춘다. */\n readonly signal?: AbortLike;\n}\n\n/**\n * 고정 크기 워커 풀로 항목들을 처리한다.\n *\n * `items.map((x) => doAsync(x))` 나 `Promise.all(tasks.map((t) => t()))` 방식은\n * 입력 개수(N)만큼의 Promise 를 한꺼번에 생성해 모두 메모리에 띄운다. 동시 실행은\n * 세마포어로 제한하더라도 \"대기 중인 N개의 Promise + 클로저\"가 그대로 상주하므로\n * 페이지 수가 많아질수록 메모리가 선형으로 늘어난다.\n *\n * `runPool` 은 정확히 `concurrency` 개의 worker 만 띄우고, 각 worker 가 공유 커서에서\n * 다음 인덱스를 꺼내 순차적으로 소비한다. 따라서 동시에 살아 있는 작업 Promise 가\n * 항상 `concurrency` 개로 일정하게 유지된다(백프레셔). 동시성 수준은 기존\n * 세마포어 방식과 동일하지만 메모리 사용이 입력 크기와 무관해진다.\n *\n * worker 가 throw 해도 해당 항목만 건너뛰고 풀은 계속 진행한다(한 건의 실패가\n * 전체를 중단시키지 않음). 실패 기록·재시도는 호출자(worker 내부)에서 담당한다.\n *\n * @param items 처리할 항목 (읽기 전용 — 풀이 변형하지 않는다).\n * @param worker 각 항목을 처리하는 비동기 함수. `index` 는 원본 배열에서의 위치.\n * @param options 동시성·취소 옵션.\n */\nexport async function runPool<T>(\n items: readonly T[],\n worker: (item: T, index: number) => Promise<void>,\n options: PoolOptions,\n): Promise<void> {\n const total = items.length;\n if (total === 0) return;\n\n const workerCount = Math.max(1, Math.min(Math.floor(options.concurrency) || 1, total));\n let cursor = 0;\n\n const runWorker = async (): Promise<void> => {\n // cursor 읽기→증가는 await 사이에서 원자적이므로(단일 스레드 이벤트 루프)\n // 두 worker 가 같은 인덱스를 가져가지 않는다.\n for (;;) {\n if (options.signal?.aborted) return;\n const index = cursor++;\n if (index >= total) return;\n try {\n await worker(items[index]!, index);\n } catch {\n // worker 내부에서 실패를 직접 기록한다. 풀은 다음 항목으로 계속 진행.\n }\n }\n };\n\n await Promise.all(Array.from({ length: workerCount }, () => runWorker()));\n}\n","import matter from \"gray-matter\";\nimport { stringifyFrontmatter } from \"../utils/frontmatter.js\";\n\n/** 대시 포함(8-4-4-4-12) 또는 대시 없는 32 hex Notion ID 전체 일치 패턴. */\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$|^[0-9a-f]{32}$/i;\n\n/**\n * frontmatter 의 relation/people 속성에 박힌 원시 Notion UUID 를 `[[제목]]` 위키링크로 치환한다.\n *\n * 단일 패스 변환 시점에는 relation 대상 페이지가 아직 변환·등록되지 않아 propertyMapper 가\n * UUID 를 그대로 남긴다(예: `작가: 1c013b18-...`). pull 의 마지막 단계인 resolveNotionLinks 는\n * 인라인 DB 까지 모든 변환이 끝나 wikilink 맵이 **완성된 뒤** 실행되므로, 이 시점에 frontmatter\n * UUID 를 해소하면 단일 패스 순서 의존성을 부작용 없이 제거할 수 있다.\n *\n * 규칙:\n * - `idToTitle` 키는 대시 제거(clean) 와 대시 포함(raw) 양형식을 모두 담는다고 가정한다.\n * - 맵에 없는 UUID(미수집 타 DB 대상)는 무손실로 그대로 둔다.\n * - relation 은 스칼라·배열·중첩배열(rollup→relation) 모두 가능하므로 값을 재귀 순회한다.\n * - 해소된 항목이 0 이면 `content` 를 재직렬화하지 않고 원본을 그대로 반환해 churn 을 막는다.\n * - 직렬화는 sealed serializer(stringifyFrontmatter)만 거친다 — 변환 시점과 동일 직렬화기라\n * 미변경 키는 byte-identical 로 round-trip 되어 fixpoint 가 안정적이다.\n */\nexport function resolveFrontmatterRelations(\n content: string,\n idToTitle: Map<string, string>,\n): { content: string; count: number } {\n if (!content.startsWith(\"---\") || idToTitle.size === 0) {\n return { content, count: 0 };\n }\n\n let parsed: ReturnType<typeof matter>;\n try {\n parsed = matter(content);\n } catch {\n // frontmatter 파싱 실패(예: 본문 선행 `---` 오인) 시 무손실 패스\n return { content, count: 0 };\n }\n\n const data = parsed.data as Record<string, unknown>;\n if (!data || Object.keys(data).length === 0) {\n return { content, count: 0 };\n }\n\n let count = 0;\n const resolveValue = (value: unknown): unknown => {\n if (typeof value === \"string\") {\n if (!UUID_RE.test(value)) return value;\n const title = idToTitle.get(value.replace(/-/g, \"\"));\n if (!title) return value;\n count++;\n return `[[${title}]]`;\n }\n if (Array.isArray(value)) return value.map(resolveValue);\n return value;\n };\n\n // gray-matter 는 입력 문자열을 키로 파싱 결과를 캐시한다. `data` 를 in-place 로\n // 수정하면 동일 frontmatter 를 가진 다른 파일이 오염된 캐시 객체를 공유해\n // cross-file 오염이 발생한다. 반드시 새 객체에 결과를 담아 캐시를 건드리지 않는다.\n const resolved: Record<string, unknown> = {};\n for (const key of Object.keys(data)) {\n resolved[key] = resolveValue(data[key]);\n }\n\n if (count === 0) return { content, count: 0 };\n return { content: stringifyFrontmatter(parsed.content, resolved), count };\n}\n","import type {\n PushOptions,\n PushResult,\n PullOptions,\n PullResult,\n SyncOptions,\n SyncResult,\n StatusResult,\n SyncRecord,\n LocalChange,\n RemoteChange,\n Conflict,\n ConflictStrategy,\n FailedOperation,\n} from \"../types/sync.js\";\nimport type { Config } from \"../types/config.js\";\nimport type { IStateDB } from \"../state/state-db-interface.js\";\nimport type { NotionClient } from \"../notion/client.js\";\nimport { isNotionObjectNotFound, DiscoveryTooLargeError } from \"../notion/client.js\";\nimport type { PageObjectResponse } from \"@notionhq/client/build/src/api-endpoints.js\";\nimport { Sema } from \"async-sema\";\nimport { ChangeDetector } from \"./change-detector.js\";\nimport type { ConversionPipeline } from \"../converter/pipeline.js\";\nimport { createDefaultPipeline } from \"../converter/pipeline-factory.js\";\nimport { BlockConverter } from \"../converter/block-converter.js\";\nimport { ImageHandler } from \"./image-handler.js\";\nimport { FileHandler } from \"./file-handler.js\";\nimport { DatabaseSyncer } from \"./database-syncer.js\";\nimport { resolvePullConflict } from \"./conflict-detector.js\";\nimport { ConflictResolver } from \"../conflict/resolver.js\";\nimport type { ResolutionChoice, ResolutionResult } from \"../conflict/resolver.js\";\nimport { PropertyMapper, type WikilinkResolver } from \"../notion/property-mapper.js\";\nimport { computeHash } from \"../utils/hash.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { sanitizeFileName } from \"../utils/sanitize.js\";\nimport { notionIdsEqual, normalizeNotionId } from \"../utils/id.js\";\nimport { runPool } from \"../utils/pool.js\";\nimport { wikilinkTitleFromPath } from \"../utils/wikilink-title.js\";\nimport { resolveFrontmatterRelations } from \"./frontmatter-link-resolver.js\";\nimport type { VaultFS } from \"./vault-fs.js\";\nimport {\n notionEnhancedToObsidian,\n obsidianToNotionEnhanced,\n} from \"../converter/enhanced-md-converter.js\";\nimport { isCompactExport } from \"../converter/post-processors/block-spacer.js\";\n\n/** 자동 발견된 DB 설정 빌드 결과 — 동기화 가능/접근 불가/일시 오류를 명시적으로 구분한다. */\ntype DiscoveredDbOutcome =\n | { kind: \"ok\"; config: { databaseId: string; localFolder: string; titleProperty: string } }\n | { kind: \"inaccessible\" }\n | { kind: \"error\" };\n\n/** 접근 불가 DB denylist 를 보존하는 상태 메타 키. */\nconst INACCESSIBLE_DBS_META_KEY = \"inaccessible_dbs\";\n\n/**\n * 증분 pull 워터마크 안전창(F20). Notion search 는 인덱싱 지연이 있어 생성 직후 페이지가\n * 결과에 안 잡히는데, 워터마크를 그대로 쓰면 다음 pull 부터 last_edited < since 로\n * 영원히 제외된다(실측 재현: 신규 하위 페이지가 편집 전까지 3회 연속 미발견).\n * 이 창만큼 되돌려 조회하면 지연 인덱싱분을 다음 pull 이 회수한다.\n */\nconst INCREMENTAL_SAFETY_WINDOW_MS = 15 * 60_000;\n\n/** 전략 → 선택지 매핑. propagateResolution 이 push 방향을 정할 때 사용. */\nfunction strategyToChoice(strategy: ConflictStrategy): ResolutionChoice {\n switch (strategy) {\n case \"local-first\":\n return \"local\";\n case \"remote-first\":\n return \"remote\";\n case \"duplicate\":\n return \"duplicate\";\n case \"manual\":\n return \"merge\";\n }\n}\n\nexport class SyncOrchestrator {\n private readonly changeDetector: ChangeDetector;\n private readonly pipeline: ConversionPipeline;\n private readonly blockConverter: BlockConverter;\n private readonly imageHandler: ImageHandler;\n private readonly fileHandler: FileHandler;\n private readonly databaseSyncer: DatabaseSyncer;\n private readonly propertyMapper: PropertyMapper;\n private readonly conflictResolver: ConflictResolver;\n private dbSchemaLoaded = false;\n private _pullImageCount = 0;\n private _pullFileCount = 0;\n // pull 중 각 페이지 markdown(<database url=.../>)에서 추출한 인라인 DB 참조.\n // key: 하이픈 제거 databaseId, value: 그 DB가 박힌 부모 페이지 id.\n // 블록 트리 재귀 없이 markdown 신호만으로 컬럼/synced_block 등 깊이 중첩된\n // child_database 까지 발견해 폴더+.base 동기화 대상으로 등록한다.\n private _inlineDbRefs = new Map<string, string>();\n // pull 발견 단계에서 모든 페이지의 부모를 해소하며 채우는 \"자식을 가진 페이지\" 집합\n // (정규화된 page id). 폴더노트/폴더 판정의 단일 신뢰 원천 — 얕은 블록 검사로 callout·\n // column 등 컨테이너에 중첩된 자식 페이지를 놓쳐 폴더노트를 file 로 오분류하던 결함\n // (본문이 최상위로 밀려 ' (1).md' 로 분리)을 차단한다. detectRemoteChanges* 진입 시 재구성.\n private _childParentIds = new Set<string>();\n\n // 서브트리 직접 순회(getChildPagesRecursive) 시간 예산. 초과하면 search 기반 디스커버리로\n // 폴백한다. 분기점 근거: 워크스페이스 search 열거는 latency-bound 로 대략 이 수준(수천 페이지\n // 워크스페이스에서 ~100s)이므로, 순회가 이 시간을 넘기면 search 가 더 저렴해진다. 작은 볼트는\n // 이 예산 안에서 순회가 끝나 폴백 없이 빠르게 완료된다. (단위: ms)\n private static readonly DISCOVERY_RECURSIVE_BUDGET_MS = 90_000;\n\n constructor(\n private readonly config: Config,\n private readonly stateDb: IStateDB,\n private readonly notionClient: NotionClient,\n private readonly vaultFs: VaultFS,\n customFetch?: typeof globalThis.fetch,\n ) {\n this.changeDetector = new ChangeDetector(stateDb);\n this.pipeline = createDefaultPipeline({\n wikilinkResolver: (text) => stateDb.resolveWikilink(text),\n });\n this.blockConverter = new BlockConverter();\n this.imageHandler = new ImageHandler(\n vaultFs,\n config.paths.attachments,\n notionClient,\n customFetch,\n {\n concurrency: config.advanced.mediaConcurrency,\n maxRetries: config.advanced.mediaMaxRetries,\n retryBaseMs: config.advanced.mediaRetryBaseMs,\n maxFileSizeBytes: config.advanced.maxFileSizeBytes,\n },\n stateDb,\n );\n this.fileHandler = new FileHandler(\n vaultFs,\n notionClient,\n stateDb,\n config.advanced.fileConcurrency,\n );\n this.propertyMapper = new PropertyMapper();\n this.databaseSyncer = new DatabaseSyncer(\n config,\n stateDb,\n notionClient,\n vaultFs,\n this.pipeline,\n this.imageHandler,\n );\n // M4: 후처리 패스(resolveNotionLinks)와 동일하게 파일 basename 으로 위키링크\n // 텍스트를 만든다. 원시 제목(.title)을 쓰면 슬래시·콜론 등 파일명 금지문자\n // 때문에 단일 패스 링크가 실제 파일을 못 가리키는 불일치가 생겼다.\n // M1: 동일 resolver 를 페이지 모드 변환 경로(notionClient.extractProperties)에도\n // 주입한다. 주입하지 않으면 페이지 모드 relation 이 raw UUID 로 남아 매 pull 마다\n // 후처리로만 해소되는 2-write churn 이 생긴다(DB 모드는 this.propertyMapper 가 처리).\n const wikilinkResolver: WikilinkResolver = {\n resolve: (title: string) => stateDb.resolveWikilink(title)?.notionPageId ?? null,\n resolvePageId: (pageId: string) => {\n const entry = stateDb.resolvePageId(pageId);\n return entry ? wikilinkTitleFromPath(entry.obsidianPath) : null;\n },\n };\n this.propertyMapper.setWikilinkResolver(wikilinkResolver);\n this.notionClient.setWikilinkResolver(wikilinkResolver);\n\n this.blockConverter.initNotionToMd(this.notionClient.getInternalClient());\n this.conflictResolver = new ConflictResolver(stateDb, vaultFs);\n }\n\n async push(options?: PushOptions): Promise<PushResult> {\n const startTime = Date.now();\n\n if (this.config.sync.direction === \"pull\") {\n return { created: 0, updated: 0, deleted: 0, failed: [], duration: Date.now() - startTime };\n }\n\n this.cleanupInterruptedSync();\n this.repairFolderRecords();\n await this.recoverInterruptedPushOps();\n\n const stats = await this.vaultFs.listMarkdownFileStats();\n const changes = await this.changeDetector.detectLocalChangesFast(stats, (path) =>\n this.vaultFs.readFile(path),\n );\n\n const conflictPaths = new Set(this.stateDb.getByStatus(\"conflict\").map((r) => r.obsidianPath));\n const eligible = options?.force ? changes : changes.filter((c) => !conflictPaths.has(c.path));\n\n const dbFolders = (this.config.notion.databases ?? []).map((d) =>\n d.localFolder.endsWith(\"/\") ? d.localFolder : d.localFolder + \"/\",\n );\n const isDbPath = (path: string) => dbFolders.some((prefix) => path.startsWith(prefix));\n\n const excludeSet = options?.excludePaths ? new Set(options.excludePaths) : null;\n const filtered = (\n options?.paths\n ? eligible.filter((c) => options.paths!.some((p) => c.path.startsWith(p)))\n : eligible\n ).filter((c) => !isDbPath(c.path) && (!excludeSet || !excludeSet.has(c.path)));\n\n const hasDbConfigs = (this.config.notion.databases?.length ?? 0) > 0;\n if (filtered.length === 0 && !hasDbConfigs) {\n return { created: 0, updated: 0, deleted: 0, failed: [], duration: Date.now() - startTime };\n }\n\n if (options?.dryRun) {\n const dryCreated = filtered.filter((c) => c.type === \"created\").length;\n const dryUpdated = filtered.filter((c) => c.type === \"modified\" || c.type === \"moved\").length;\n const dryDeleted = filtered.filter((c) => c.type === \"deleted\").length;\n let dryProgress = 0;\n const dryTotal = filtered.length;\n for (const change of filtered) {\n const op =\n change.type === \"created\"\n ? (\"create\" as const)\n : change.type === \"deleted\"\n ? (\"delete\" as const)\n : (\"update\" as const);\n options?.onProgress?.(++dryProgress, dryTotal, { path: change.path, operation: op });\n }\n return {\n created: dryCreated,\n updated: dryUpdated,\n deleted: dryDeleted,\n failed: [],\n duration: Date.now() - startTime,\n };\n }\n\n this.stateDb.setMeta(\"push_in_progress\", \"true\");\n\n const folderPaths = new Set<string>();\n for (const change of filtered) {\n const parts = change.path.split(\"/\");\n if (parts.length > 1) {\n for (let i = 1; i < parts.length; i++) {\n folderPaths.add(parts.slice(0, i).join(\"/\"));\n }\n }\n }\n\n const sortedFolders = [...folderPaths].sort(\n (a, b) => a.split(\"/\").length - b.split(\"/\").length,\n );\n for (const folderPath of sortedFolders) {\n await this.ensureFolderPage(folderPath);\n }\n\n const counts = { created: 0, updated: 0, deleted: 0 };\n const failed: FailedOperation[] = [];\n\n let completed = 0;\n const total = filtered.length;\n\n const opOf = (change: LocalChange): \"create\" | \"update\" | \"delete\" =>\n change.type === \"created\" ? \"create\" : change.type === \"deleted\" ? \"delete\" : \"update\";\n\n // 단건 변경을 적용하고 카운트를 올린다. 실패는 throw 로 호출자에 위임.\n const applyPushChange = async (change: LocalChange): Promise<void> => {\n switch (change.type) {\n case \"created\":\n await this.pushCreate(change.path);\n counts.created++;\n break;\n case \"modified\":\n await this.pushUpdate(change.path);\n counts.updated++;\n break;\n case \"moved\":\n await this.pushMove(change.path);\n counts.updated++;\n break;\n case \"deleted\": {\n const propagated = await this.pushDelete(change.path);\n if (propagated) counts.deleted++;\n break;\n }\n }\n };\n\n // 1차 처리 — 고정 크기 워커 풀(백프레셔). 실패분은 변경 객체째 재시도 큐로.\n const retryQueue: LocalChange[] = [];\n await runPool(\n filtered,\n async (change) => {\n if (options?.signal?.aborted) return;\n options?.onProgress?.(++completed, total, { path: change.path, operation: opOf(change) });\n try {\n await applyPushChange(change);\n } catch {\n retryQueue.push(change);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n\n // 재시도 — 워커 풀 병렬(기존엔 순차). 변경 객체를 그대로 들고 있어 경로 역매칭\n // 취약함이 없다. pushCreate 는 멱등하므로 부분 성공분을 다시 만들지 않는다.\n if (retryQueue.length > 0) {\n const retryWaitMs = this.config.advanced.retryWaitMs;\n getLogger().info(\n `[Im-Nobsidian] Push ${retryQueue.length}건 재시도 (${retryWaitMs / 1000}초 후)`,\n );\n await new Promise((r) => setTimeout(r, retryWaitMs));\n\n await runPool(\n retryQueue,\n async (change) => {\n try {\n await applyPushChange(change);\n getLogger().info(`[Im-Nobsidian] 재시도 성공: ${change.path}`);\n } catch (error) {\n failed.push({\n path: change.path,\n operation: opOf(change),\n error: error instanceof Error ? error.message : String(error),\n });\n getLogger().warn(`[Im-Nobsidian] 재시도 실패: ${change.path}`);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n }\n\n if (this.config.sync.syncFiles !== false) {\n try {\n const fileResults = await this.fileHandler.pushAllFiles();\n if (fileResults.length > 0) {\n getLogger().info(`[Im-Nobsidian] ${fileResults.length}개 파일 업로드 완료`);\n }\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] 파일 업로드 중 오류:\", error);\n }\n }\n\n if ((this.config.notion.databases?.length ?? 0) > 0) {\n try {\n const dbResult = await this.databaseSyncer.pushAll();\n counts.created += dbResult.created;\n counts.updated += dbResult.updated;\n failed.push(...dbResult.failed);\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] DB Push 중 오류:\", error);\n }\n }\n\n this.stateDb.setMeta(\"last_push_at\", new Date().toISOString());\n this.stateDb.setMeta(\"last_sync_at\", new Date().toISOString());\n this.stateDb.setMeta(\"push_in_progress\", \"\");\n // 완료/실패한 WAL 항목 정리 — 테이블 무한 증가 방지(미완료 항목은 보존).\n this.stateDb.clearCompletedOperations();\n\n return {\n created: counts.created,\n updated: counts.updated,\n deleted: counts.deleted,\n failed,\n duration: Date.now() - startTime,\n };\n }\n\n async pull(options?: PullOptions): Promise<PullResult> {\n const startTime = Date.now();\n const emptyResult: PullResult = {\n created: 0,\n updated: 0,\n deleted: 0,\n conflicts: [],\n writtenPaths: [],\n failed: [],\n duration: Date.now() - startTime,\n imageCount: 0,\n fileCount: 0,\n linkCount: 0,\n };\n\n if (this.config.sync.direction === \"push\") {\n return emptyResult;\n }\n\n this.cleanupInterruptedSync();\n\n const counts = { created: 0, updated: 0, deleted: 0 };\n this._pullImageCount = 0;\n this._pullFileCount = 0;\n this._inlineDbRefs.clear();\n const conflicts: Conflict[] = [];\n const writtenPaths: string[] = [];\n const failed: FailedOperation[] = [];\n\n // M2: pull 의 모든 종료 경로가 동일하게 마감되도록 단일 헬퍼로 모은다 —\n // 기록된 파일(writtenPaths)의 본문 링크·frontmatter relation 후처리(resolveNotionLinks)와\n // 메타 마킹을 빠짐없이 거친다. 과거엔 디스커버리 DB 전용 조기 반환 경로가 이 후처리를\n // 건너뛰어, 그 행들의 위키링크/relation 이 UUID 그대로 남았다.\n const finalize = async (\n created: number,\n updated: number,\n deleted: number,\n ): Promise<PullResult> => {\n const linkCount = writtenPaths.length > 0 ? await this.resolveNotionLinks(writtenPaths) : 0;\n this.stateDb.setMeta(\"last_pull_at\", new Date().toISOString());\n this.stateDb.setMeta(\"last_sync_at\", new Date().toISOString());\n this.stateDb.setMeta(\"pull_in_progress\", \"\");\n return {\n created,\n updated,\n deleted,\n conflicts,\n writtenPaths,\n failed,\n duration: Date.now() - startTime,\n imageCount: this._pullImageCount,\n fileCount: this._pullFileCount,\n linkCount,\n };\n };\n\n const lastPull = this.stateDb.getMeta(\"last_pull_at\") ?? this.stateDb.getMeta(\"last_sync_at\");\n const trackedCount = this.stateDb.getAll().length;\n // 증분(searchRecentPages) 은 in_trash 페이지를 못 보므로 삭제를 감지하지 못한다(I10).\n // deleteSync 가 켜진 경우엔 삭제 전파가 필요하니 반드시 전체 스캔(detectRemoteChanges)을\n // 타게 해 사라진 추적 페이지를 잡는다. 꺼진 경우엔 어차피 삭제를 전파하지 않으므로 빠른\n // 증분 경로가 안전하다(누락해도 사용자 설정상 무동작).\n const canUseIncremental =\n !this.isDatabaseMode &&\n !!lastPull &&\n trackedCount > 0 &&\n !options?.force &&\n !this.config.sync.deleteSync;\n const remoteChanges = canUseIncremental\n ? await this.detectRemoteChangesIncremental(lastPull!)\n : await this.detectRemoteChanges();\n\n const filtered = options?.paths\n ? remoteChanges.filter((c) => {\n const record = this.stateDb.getByNotionId(c.pageId);\n return record && options.paths!.some((p) => record.obsidianPath.startsWith(p));\n })\n : remoteChanges;\n\n if (filtered.length === 0 && (this.config.notion.databases?.length ?? 0) === 0) {\n // 본문 페이지 변경이 없어도 디스커버리된 DB 행은 새로 기록될 수 있다. 그 행들의\n // 본문 링크·frontmatter relation 을 finalize() 의 resolveNotionLinks 가 해소한다(M2).\n // (기록이 0건이면 writtenPaths 가 비어 linkCount 0 으로 마감 — emptyResult 와 동일)\n const dbDiscovery = await this.pullDiscoveredDatabases(\n writtenPaths,\n failed,\n conflicts,\n options?.force === true,\n );\n return finalize(dbDiscovery.created, dbDiscovery.updated, 0);\n }\n if (filtered.length === 0) {\n return emptyResult;\n }\n\n if (options?.dryRun) {\n const dryCreated = filtered.filter((c) => c.type === \"created\").length;\n const dryUpdated = filtered.filter((c) => c.type === \"modified\").length;\n const dryDeleted = filtered.filter((c) => c.type === \"deleted\").length;\n let dryProgress = 0;\n const dryTotal = filtered.length;\n for (const change of filtered) {\n const op =\n change.type === \"created\"\n ? (\"create\" as const)\n : change.type === \"deleted\"\n ? (\"delete\" as const)\n : (\"update\" as const);\n const record = this.stateDb.getByNotionId(change.pageId);\n const displayPath = record?.obsidianPath ?? change.pageId;\n options?.onProgress?.(++dryProgress, dryTotal, { path: displayPath, operation: op });\n }\n return {\n created: dryCreated,\n updated: dryUpdated,\n deleted: dryDeleted,\n conflicts: [],\n writtenPaths: [],\n failed: [],\n duration: Date.now() - startTime,\n imageCount: 0,\n fileCount: 0,\n linkCount: 0,\n };\n }\n\n this.stateDb.setMeta(\"pull_in_progress\", \"true\");\n\n const pullTotal = filtered.length;\n let pullCompleted = 0;\n\n // 변경 메타를 FailedOperation 으로 변환(경로·작업종류·에러 메시지).\n const toFailure = (change: RemoteChange, error: unknown): FailedOperation => {\n const record = this.stateDb.getByNotionId(change.pageId);\n return {\n path: record?.obsidianPath ?? change.pageId,\n operation:\n change.type === \"created\" ? \"create\" : change.type === \"deleted\" ? \"delete\" : \"update\",\n error: error instanceof Error ? error.message : String(error),\n };\n };\n\n // 단일 변경을 적용하고 진행률 표시용 경로를 돌려준다. 실패는 throw 로 호출자에 위임.\n const applyChange = async (change: RemoteChange): Promise<string | undefined> => {\n switch (change.type) {\n case \"created\": {\n const path = await this.pullCreate(change.pageId);\n writtenPaths.push(path);\n counts.created++;\n return path;\n }\n case \"modified\": {\n const result = await this.pullUpdate(change);\n if (result.conflict) {\n conflicts.push(result.conflict);\n } else if (result.path && !result.unchanged) {\n // unchanged=true 는 content_hash 동일 no-op(가짜 수정) — 파일 재기록·churn 없음.\n // updated 카운트에 넣지 않아 보고가 정직해진다(I5).\n writtenPaths.push(result.path);\n counts.updated++;\n }\n return result.path;\n }\n case \"deleted\": {\n const record = this.stateDb.getByNotionId(change.pageId);\n const path = await this.pullDelete(change.pageId);\n if (path) {\n counts.deleted++;\n return path;\n }\n return record?.obsidianPath;\n }\n default:\n return undefined;\n }\n };\n\n // 1차 처리 — 고정 크기 워커 풀(백프레셔). 실패한 변경은 재시도 큐로 모은다.\n const retryQueue: RemoteChange[] = [];\n await runPool(\n filtered,\n async (change) => {\n if (options?.signal?.aborted) return;\n try {\n const resultPath = await applyChange(change);\n const record = this.stateDb.getByNotionId(change.pageId);\n const displayPath = resultPath ?? record?.obsidianPath ?? change.pageId;\n const op =\n change.type === \"created\"\n ? (\"create\" as const)\n : change.type === \"deleted\"\n ? (\"delete\" as const)\n : (\"update\" as const);\n options?.onProgress?.(++pullCompleted, pullTotal, { path: displayPath, operation: op });\n } catch {\n retryQueue.push(change);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n\n // 재시도 — 1차와 동일하게 워커 풀로 병렬 실행(기존엔 순차였다). 변경 객체를\n // 그대로 들고 있으므로 경로 문자열로 역매칭하던 취약함이 사라진다.\n if (retryQueue.length > 0) {\n const retryWaitMs = this.config.advanced.retryWaitMs;\n getLogger().info(\n `[Im-Nobsidian] Pull ${retryQueue.length}건 재시도 (${retryWaitMs / 1000}초 후)`,\n );\n await new Promise((r) => setTimeout(r, retryWaitMs));\n\n await runPool(\n retryQueue,\n async (change) => {\n try {\n await applyChange(change);\n const record = this.stateDb.getByNotionId(change.pageId);\n getLogger().info(\n `[Im-Nobsidian] 재시도 성공: ${record?.obsidianPath ?? change.pageId}`,\n );\n } catch (error) {\n const failure = toFailure(change, error);\n failed.push(failure);\n getLogger().warn(`[Im-Nobsidian] 재시도 실패: ${failure.path}`);\n }\n },\n { concurrency: this.config.advanced.concurrency, signal: options?.signal },\n );\n }\n\n if ((this.config.notion.databases?.length ?? 0) > 0) {\n try {\n const dbResult = await this.databaseSyncer.pullAll();\n counts.created += dbResult.created;\n counts.updated += dbResult.updated;\n conflicts.push(...dbResult.conflicts);\n failed.push(...dbResult.failed);\n // M3: 후처리 대상은 실제 기록된 행 경로를 그대로 받는다. 과거엔 \"synced 상태의\n // db-row 중 마지막 N개\" 라는 슬라이스 추정을 썼는데, 정렬·기존행 혼입 때문에\n // 엉뚱한 파일을 후처리하거나 갓 쓴 행을 놓쳐 링크가 미해소로 남았다.\n writtenPaths.push(...dbResult.writtenPaths);\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] DB Pull 중 오류:\", error);\n }\n }\n\n {\n const dbDiscovery = await this.pullDiscoveredDatabases(\n writtenPaths,\n failed,\n conflicts,\n options?.force === true,\n );\n counts.created += dbDiscovery.created;\n counts.updated += dbDiscovery.updated;\n }\n\n return finalize(counts.created, counts.updated, counts.deleted);\n }\n\n async sync(options?: SyncOptions): Promise<SyncResult> {\n const startTime = Date.now();\n const pullResult = await this.pull(options);\n const pushResult = await this.push({\n ...options,\n paths: options?.paths,\n excludePaths: pullResult.writtenPaths,\n });\n\n return {\n pull: pullResult,\n push: pushResult,\n conflicts: pullResult.conflicts,\n duration: Date.now() - startTime,\n };\n }\n\n async status(): Promise<StatusResult> {\n const files = await this.vaultFs.listMarkdownFiles();\n const localChanges = this.changeDetector.detectLocalChanges(files);\n const lastSyncAt = this.stateDb.getMeta(\"last_sync_at\");\n // 증분은 삭제(in_trash)를 못 본다(I10). deleteSync 시 status 가 원격 삭제를 보고할 수\n // 있도록 전체 스캔으로 우회한다. 꺼진 경우엔 삭제를 행동에 옮기지 않으므로 증분으로 충분.\n const remoteChanges =\n lastSyncAt && !this.config.sync.deleteSync\n ? await this.detectRemoteChangesIncremental(lastSyncAt)\n : await this.detectRemoteChanges();\n const conflictRecords = this.stateDb.getByStatus(\"conflict\");\n\n const conflicts: Conflict[] = await this.buildConflictsFromRecords(\n conflictRecords,\n localChanges,\n remoteChanges,\n );\n\n return {\n localChanges,\n remoteChanges,\n conflicts,\n conflictRecords,\n pendingOperations: conflictRecords.length,\n lastSyncAt,\n };\n }\n\n async statusLocal(): Promise<StatusResult> {\n const stats = await this.vaultFs.listMarkdownFileStats();\n const localChanges = await this.changeDetector.detectLocalChangesFast(stats, (path) =>\n this.vaultFs.readFile(path),\n );\n const conflictRecords = this.stateDb.getByStatus(\"conflict\");\n const lastSyncAt = this.stateDb.getMeta(\"last_sync_at\");\n\n return {\n localChanges,\n remoteChanges: [],\n conflicts: [],\n conflictRecords,\n pendingOperations: conflictRecords.length,\n lastSyncAt,\n };\n }\n\n async fetch(): Promise<{\n newPages: number;\n deletedPages: number;\n modifiedPages: number;\n duration: number;\n }> {\n const startTime = Date.now();\n const changes = await this.detectRemoteChanges();\n this.stateDb.setMeta(\"last_fetch_at\", new Date().toISOString());\n return {\n newPages: changes.filter((c) => c.type === \"created\").length,\n modifiedPages: changes.filter((c) => c.type === \"modified\").length,\n deletedPages: changes.filter((c) => c.type === \"deleted\").length,\n duration: Date.now() - startTime,\n };\n }\n\n private async buildConflictsFromRecords(\n records: SyncRecord[],\n localChanges: LocalChange[],\n remoteChanges: RemoteChange[],\n ): Promise<Conflict[]> {\n const conflicts: Conflict[] = [];\n\n for (const record of records) {\n const localChange = localChanges.find((c) => c.path === record.obsidianPath) ?? {\n path: record.obsidianPath,\n type: \"modified\" as const,\n currentHash: record.contentHash,\n previousHash: record.contentHash,\n };\n\n const remoteChange = remoteChanges.find((c) => c.pageId === record.notionPageId) ?? {\n pageId: record.notionPageId ?? \"\",\n type: \"modified\" as const,\n lastEdited: record.notionLastEdited ?? \"\",\n previousEdited: null,\n };\n\n let localContent = \"\";\n try {\n localContent = await this.vaultFs.readFile(record.obsidianPath);\n } catch {\n // 파일이 삭제된 경우\n }\n\n let remoteContent = \"\";\n if (record.notionPageId) {\n try {\n remoteContent = (await this.fetchPageMarkdown(record.notionPageId)).content;\n } catch {\n // 페이지가 삭제된 경우\n }\n }\n\n conflicts.push({\n syncRecord: record,\n localChange,\n remoteChange,\n baseContent: record.baseSnapshot?.toString(\"utf-8\") ?? null,\n localContent,\n remoteContent,\n });\n }\n\n return conflicts;\n }\n\n private get isDatabaseMode(): boolean {\n return this.config.notion.parentMode === \"database\" && !!this.config.notion.databaseId;\n }\n\n private async discoverChildDatabases(): Promise<Array<{ dbId: string; parentPageId: string }>> {\n const allDbs: Array<{ dbId: string; parentPageId: string }> = [];\n const trackedPages = this.stateDb.getAll().filter((r) => r.notionPageId);\n const pageIds = [this.config.notion.rootPageId, ...trackedPages.map((r) => r.notionPageId!)];\n const seen = new Set<string>();\n\n for (const parentId of pageIds) {\n if (seen.has(parentId)) continue;\n seen.add(parentId);\n try {\n const dbIds = await this.notionClient.getChildDatabaseIds(parentId);\n for (const dbId of dbIds) {\n allDbs.push({ dbId, parentPageId: parentId });\n }\n } catch {\n // 접근 권한 없는 블록 무시\n }\n }\n\n return allDbs;\n }\n\n /**\n * 자동 발견된 child_database 1개를 DatabaseSyncer 설정으로 변환한다.\n * 블록 스캔/markdown 양쪽 발견 경로에서 공통으로 사용한다.\n * - localFolder: 부모 페이지의 obsidianPath 기준으로 폴더를 잡아 원본 중첩 구조를 보존\n * (예: 부모 \"AI Engineer (1).md\" + DB \"Minirecord Project\" → \"AI Engineer (1)/Minirecord-Project\")\n * - 제목 취득 실패 시 부모 폴더명 기반 안전 이름으로 폴백\n */\n private async buildDiscoveredDbConfig(\n dbId: string,\n parentPageId: string,\n ): Promise<DiscoveredDbOutcome> {\n let dbTitle: string;\n try {\n // 제목 + 접근 가능한 data source 유무를 1회 호출로 확인한다. data source 가 없으면\n // 행 조회가 404 로 실패하고 빈 폴더/.base 만 남기므로, 발견 단계에서 미리 제외한다.\n const info = await this.notionClient.getDatabaseSyncability(dbId);\n if (!info.queryable) {\n return { kind: \"inaccessible\" };\n }\n dbTitle = info.title;\n } catch (error) {\n // 삭제된 DB 도 404 → 접근 불가로 강등(재시도하지 않음). 그 외는 일시 오류로 본다.\n if (isNotionObjectNotFound(error)) return { kind: \"inaccessible\" };\n getLogger().warn(`[Im-Nobsidian] 자동 발견 DB ${dbId} 설정 생성 실패:`, error);\n return { kind: \"error\" };\n }\n\n const parentEntry = parentPageId ? this.stateDb.getByNotionId(parentPageId) : null;\n let parentFolder = \"\";\n if (parentEntry?.obsidianPath) {\n const obsPath = parentEntry.obsidianPath;\n if (obsPath.endsWith(\".md\")) {\n const parts = obsPath.split(\"/\");\n parts.pop();\n parentFolder = parts.length > 0 ? parts.join(\"/\") : obsPath.replace(/\\.md$/, \"\");\n } else {\n parentFolder = obsPath;\n }\n }\n let safeName: string;\n if (dbTitle) {\n safeName = dbTitle.replace(/[^a-zA-Z0-9가-힣\\s_-]/g, \"\").replace(/\\s+/g, \"-\");\n } else {\n const parentName = parentFolder.split(\"/\").pop() || \"\";\n safeName = parentName ? `${parentName}-DB` : `db-${dbId.replace(/-/g, \"\").slice(0, 8)}`;\n }\n if (!safeName) safeName = `db-${dbId.replace(/-/g, \"\").slice(0, 8)}`;\n if (!parentFolder) parentFolder = \"databases\";\n return {\n kind: \"ok\",\n config: {\n databaseId: dbId,\n localFolder: `${parentFolder}/${safeName}`,\n titleProperty: \"Name\",\n },\n };\n }\n\n /** 접근 불가 DB denylist 를 상태 메타에서 로드한다(하이픈 정규화). */\n private loadInaccessibleDbIds(): Set<string> {\n const raw = this.stateDb.getMeta(INACCESSIBLE_DBS_META_KEY);\n if (!raw) return new Set();\n try {\n const arr = JSON.parse(raw) as string[];\n return new Set(arr.map((id) => id.replace(/-/g, \"\")));\n } catch {\n return new Set();\n }\n }\n\n private async pullDiscoveredDatabases(\n writtenPaths: string[],\n failed: FailedOperation[],\n conflicts: Conflict[],\n forceRediscovery = false,\n ): Promise<{ created: number; updated: number }> {\n if (this.isDatabaseMode) return { created: 0, updated: 0 };\n\n let created = 0;\n let updated = 0;\n\n try {\n const cachedRaw = this.stateDb.getMeta(\"discovered_dbs\");\n let dbConfigs: Array<{ databaseId: string; localFolder: string; titleProperty: string }> = [];\n\n if (cachedRaw) {\n try {\n dbConfigs = JSON.parse(cachedRaw);\n } catch {\n dbConfigs = [];\n }\n }\n\n const configuredIds = new Set(\n (this.config.notion.databases ?? []).map((d) => d.databaseId.replace(/-/g, \"\")),\n );\n const knownIds = new Set<string>([\n ...configuredIds,\n ...dbConfigs.map((c) => c.databaseId.replace(/-/g, \"\")),\n ]);\n let changed = false;\n\n // 접근 불가(링크드/미공유/삭제) DB denylist — 매 pull 마다 doomed 404 재시도 +\n // 스택트레이스 노이즈를 차단한다. 발견 단계에서 걸러 빈 폴더/.base 오염도 막는다.\n const inaccessibleIds = this.loadInaccessibleDbIds();\n let inaccessibleChanged = false;\n const degrade = (rawId: string): void => {\n const nohyph = rawId.replace(/-/g, \"\");\n if (!inaccessibleIds.has(nohyph)) {\n inaccessibleIds.add(nohyph);\n inaccessibleChanged = true;\n }\n getLogger().info(\n `[Im-Nobsidian] DB ${rawId}: 접근 가능한 data source 없음(링크드/미공유/삭제 추정) — 동기화 대상에서 제외(제목은 부모 페이지에 보존)`,\n );\n };\n\n // (1) 블록 스캔 기반 발견 — 추적 페이지마다 직속 children 1회 조회로 비용이 크므로\n // 캐시가 비었을 때(최초 full pull)만 수행한다. 이후 생긴 신규 child DB 는 이\n // 게이트 탓에 복구 경로가 없었으므로(F21), --force 시에는 재스캔을 허용한다.\n if (dbConfigs.length === 0 || forceRediscovery) {\n const discovered = await this.discoverChildDatabases();\n for (const { dbId, parentPageId } of discovered) {\n const nohyph = dbId.replace(/-/g, \"\");\n if (knownIds.has(nohyph) || inaccessibleIds.has(nohyph)) continue;\n const outcome = await this.buildDiscoveredDbConfig(dbId, parentPageId);\n knownIds.add(nohyph);\n if (outcome.kind === \"ok\") {\n dbConfigs.push(outcome.config);\n changed = true;\n } else if (outcome.kind === \"inaccessible\") {\n degrade(dbId);\n }\n }\n }\n\n // (2) markdown 기반 발견 — 추가 API 호출 없이 컬럼/synced_block 내부 깊이 중첩된\n // child_database 까지 포착한다. 이번 pull 에서 재취득된 페이지에 한해 채워지므로\n // 캐시 유무와 무관하게 항상 병합한다(증분 pull·업그레이드 시 신규 DB 흡수).\n for (const [nohyph, parentPageId] of this._inlineDbRefs) {\n if (knownIds.has(nohyph) || inaccessibleIds.has(nohyph)) continue;\n const dbId = normalizeNotionId(nohyph);\n const outcome = await this.buildDiscoveredDbConfig(dbId, parentPageId);\n knownIds.add(nohyph);\n if (outcome.kind === \"ok\") {\n dbConfigs.push(outcome.config);\n changed = true;\n } else if (outcome.kind === \"inaccessible\") {\n degrade(dbId);\n }\n }\n\n // 동기화 가능한 DB 만 처리하고, 캐시에 잔존하던 접근 불가 DB 는 건너뛴다.\n // 처리에 성공/일시실패한 DB 만 stillSyncable 로 모아 캐시의 권위적 스냅샷으로 삼는다.\n const stillSyncable: typeof dbConfigs = [];\n for (const dbConfig of dbConfigs) {\n if (inaccessibleIds.has(dbConfig.databaseId.replace(/-/g, \"\"))) continue;\n try {\n const dbResult = await this.databaseSyncer.pullDatabase(dbConfig);\n created += dbResult.created;\n updated += dbResult.updated;\n conflicts.push(...dbResult.conflicts);\n failed.push(...dbResult.failed);\n // M3: 슬라이스 추정 대신 실제 기록된 행 경로를 후처리 대상으로 받는다.\n writtenPaths.push(...dbResult.writtenPaths);\n stillSyncable.push(dbConfig);\n } catch (error) {\n if (isNotionObjectNotFound(error)) {\n // 캐시에 있었지만 이제 행 조회가 404 — 링크드/미공유/삭제로 강등(스택트레이스 억제).\n degrade(dbConfig.databaseId);\n } else {\n // 일시적/실제 오류 — 캐시에 유지해 다음 pull 에 재시도한다.\n getLogger().warn(`[Im-Nobsidian] DB ${dbConfig.databaseId} 동기화 실패:`, error);\n stillSyncable.push(dbConfig);\n }\n }\n }\n\n // 발견·강등·정리 결과를 캐시에 1회 반영(접근 불가 DB 는 stillSyncable 에서 빠져 제거됨).\n if (changed || inaccessibleChanged || stillSyncable.length !== dbConfigs.length) {\n this.stateDb.setMeta(\"discovered_dbs\", JSON.stringify(stillSyncable));\n }\n if (inaccessibleChanged) {\n this.stateDb.setMeta(INACCESSIBLE_DBS_META_KEY, JSON.stringify([...inaccessibleIds]));\n }\n } catch (error) {\n getLogger().warn(\"[Im-Nobsidian] child_database 자동 발견 실패:\", error);\n }\n\n return { created, updated };\n }\n\n private async resolveNotionLinks(paths: string[]): Promise<number> {\n let totalResolved = 0;\n const allRecords = this.stateDb.getAll();\n const idToTitle = new Map<string, string>();\n for (const r of allRecords) {\n if (r.notionPageId && r.obsidianPath) {\n // M4: 단일 변환 패스(resolvePageId)와 동일한 규칙으로 위키링크 텍스트를 만든다.\n const title = wikilinkTitleFromPath(r.obsidianPath);\n const cleanId = r.notionPageId.replace(/-/g, \"\");\n idToTitle.set(cleanId, title);\n idToTitle.set(r.notionPageId, title);\n }\n }\n if (idToTitle.size === 0) return 0;\n\n for (const filePath of paths) {\n if (!filePath.endsWith(\".md\")) continue;\n try {\n let content = await this.vaultFs.readFile(filePath);\n let changed = false;\n\n const resolved = content.replace(/\\[\\[notion:([a-f0-9-]+)\\]\\]/g, (_match, id: string) => {\n const title = idToTitle.get(id.replace(/-/g, \"\"));\n if (title) {\n totalResolved++;\n changed = true;\n return `[[${title}]]`;\n }\n return _match;\n });\n content = resolved;\n\n // Notion 내부 페이지 링크는 `/<id>?pvs=N` 또는 `/p/<id>?...`(신형) 형태로 온다.\n // 선택적 `p/` 접두사와 임의 쿼리스트링(또는 쿼리 없음)을 모두 허용한다.\n const resolved2 = content.replace(\n /\\[([^\\]]+)\\]\\(\\/(?:p\\/)?([a-f0-9]{32})(?:\\?[^)]*)?\\)/g,\n (_match, text: string, id: string) => {\n const title = idToTitle.get(id);\n if (title) {\n totalResolved++;\n changed = true;\n return `[[${title}|${text}]]`;\n }\n return _match;\n },\n );\n content = resolved2;\n\n // frontmatter 의 relation/people 원시 UUID → `[[제목]]`. 변환 시점에는 대상\n // 페이지가 미등록이라 UUID 로 남지만, 이 post-pass 시점엔 맵이 완성돼 해소된다.\n const fm = resolveFrontmatterRelations(content, idToTitle);\n if (fm.count > 0) {\n content = fm.content;\n totalResolved += fm.count;\n changed = true;\n }\n\n if (changed) {\n await this.vaultFs.writeFile(filePath, content);\n // 링크 정규화로 디스크 내용이 바뀌었으므로 해당 sync record 의 해시·스냅샷·stat\n // 을 새 내용으로 재동기화한다. 이걸 빠뜨리면 디스크(위키링크 형태)와 저장 해시\n // (`/p/<id>` 형태)가 영구 불일치해 매 sync마다 \"modified\" 로 재감지되는\n // fixpoint 위반(I5)이 발생한다. push 가 가능한 파일은 다음 push 로 self-heal\n // 되지만, child page 를 가진 폴더노트는 push 가 실패해 영영 churn 한다.\n const record = this.stateDb.getByPath(filePath);\n if (record) {\n const stat = await this.vaultFs.getFileStat(filePath);\n this.stateDb.transaction(() => {\n this.stateDb.updateHash(\n record.id,\n computeHash(content),\n Buffer.from(content, \"utf-8\"),\n );\n if (stat) this.stateDb.updateStatCache(record.id, stat.mtime, stat.size);\n });\n }\n }\n } catch {\n // 파일 읽기/쓰기 실패 무시\n }\n }\n return totalResolved;\n }\n\n private async ensureDbSchema(): Promise<void> {\n if (this.dbSchemaLoaded || !this.isDatabaseMode) return;\n const schema = await this.notionClient.getDatabaseSchema(this.config.notion.databaseId!);\n this.propertyMapper.loadSchema(schema);\n this.dbSchemaLoaded = true;\n }\n\n private async pushCreate(path: string): Promise<void> {\n // 멱등성/원자성: 이전 시도가 페이지 생성까지는 성공해 notionPageId 가 이미\n // 매핑돼 있으면(이미지 업로드 실패·크래시·인-런 재시도 등) 새 페이지를 또\n // 만들지 않고 업데이트 경로로 위임한다 → 고아 페이지·중복 생성 방지.\n const existingRecord = this.stateDb.getByPath(path);\n if (existingRecord?.notionPageId) {\n await this.pushUpdate(path);\n return;\n }\n\n const content = await this.vaultFs.readFile(path);\n const title = extractTitle(path);\n const parentId = await this.resolveNotionParent(path);\n\n const selectedPath = this.pipeline.selectPath(content);\n if (selectedPath === \"block-api\") {\n getLogger().warn(\n `[Im-Nobsidian] \"${path}\" contains block-api features (inline-db/column/toggle) — converted with reduced fidelity in v0.1.0`,\n );\n }\n\n const conversionResult = this.pipeline.convertToNotion(content, {\n direction: \"push\",\n path: selectedPath,\n filePath: path,\n parentMode: this.config.notion.parentMode,\n });\n\n let effectiveParentId = parentId;\n let effectiveParentType: \"page\" | \"database\" = \"page\";\n let effectiveProperties = conversionResult.properties;\n\n if (this.isDatabaseMode) {\n await this.ensureDbSchema();\n effectiveParentId = this.config.notion.databaseId!;\n effectiveParentType = \"database\";\n effectiveProperties = this.propertyMapper.toNotionProperties(\n conversionResult.properties,\n title,\n );\n }\n\n // I12 WAL(쓰기-우선): 페이지를 만들기 전에 자리표시 state(notion_page_id=null) +\n // pending_operations(create) 를 먼저 기록한다. 생성 요청이 적용됐는데 응답이 유실되거나\n // (timeout) 프로세스가 죽어 매핑 기록 전에 중단되면, 다음 push 시작 시 recoverInterruptedPushOps\n // 가 부모에서 제목으로 고아 페이지를 찾아 입양하므로 중복 페이지 생성을 차단한다.\n const placeholder = this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: null,\n notionParentId: parentId,\n contentHash: \"\",\n notionLastEdited: null,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: this.isFolderNote(path) ? \"folder-note\" : \"file\",\n status: \"pending\",\n baseSnapshot: null,\n localMtime: null,\n localFileSize: null,\n });\n // 인-런 재시도 시 같은 state 에 대한 op 중복 기록을 막는다(기존 미완료 op 재사용).\n const existingOp = this.stateDb.getIncompleteOpByState(placeholder.id, \"create\");\n const walOpId =\n existingOp?.id ??\n this.stateDb.recordPendingOperation({\n syncStateId: placeholder.id,\n operation: \"create\",\n direction: \"push\",\n payload: JSON.stringify({ path, parentId, title }),\n });\n\n const page = await this.pushCreatePage(\n effectiveParentId,\n effectiveParentType,\n title,\n conversionResult.content,\n effectiveProperties,\n );\n\n // 페이지 생성 직후 매핑을 먼저 기록(전이 상태 pending). 이후 이미지 업로드 등이\n // 실패해도 이 레코드 덕에 다음 시도는 pushCreate(중복) 가 아니라 pushUpdate 로\n // 이어진다. contentHash 를 비워 변경감지가 \"미완료 → 재푸시 필요\"로 인식하게 한다.\n this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: page.id,\n notionParentId: parentId,\n contentHash: \"\",\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: this.isFolderNote(path) ? \"folder-note\" : \"file\",\n status: \"pending\",\n baseSnapshot: null,\n localMtime: null,\n localFileSize: null,\n });\n\n await this.imageHandler.uploadAndAppendImages(page.id, conversionResult.images, path);\n\n const hash = computeHash(content);\n const fileStat = await this.vaultFs.getFileStat(path);\n\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: page.id,\n notionParentId: parentId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: this.isFolderNote(path) ? \"folder-note\" : \"file\",\n status: \"synced\",\n baseSnapshot: Buffer.from(content, \"utf-8\"),\n localMtime: fileStat?.mtime ?? null,\n localFileSize: fileStat?.size ?? null,\n });\n\n const aliases = extractAliases(conversionResult.properties);\n this.stateDb.upsertWikilink({\n obsidianPath: path,\n notionPageId: page.id,\n title,\n aliases,\n });\n\n this.stateDb.storePreserveMarkers(path, conversionResult.preserveMarkers);\n });\n\n // 생성·매핑·이미지·최종 synced 까지 모두 끝났으므로 WAL 을 완료 처리한다.\n this.stateDb.markPendingCompleted(walOpId);\n }\n\n private async pushUpdate(path: string): Promise<void> {\n const content = await this.vaultFs.readFile(path);\n const record = this.stateDb.getByPath(path);\n if (!record?.notionPageId) return;\n\n const updatePath = this.pipeline.selectPath(content);\n if (updatePath === \"block-api\") {\n getLogger().warn(\n `[Im-Nobsidian] \"${path}\" contains block-api features (inline-db/column/toggle) — converted with reduced fidelity in v0.1.0`,\n );\n }\n\n const conversionResult = this.pipeline.convertToNotion(content, {\n direction: \"push\",\n path: updatePath,\n filePath: path,\n parentMode: this.config.notion.parentMode,\n });\n\n await this.pushUpdatePage(record.notionPageId, conversionResult.content, record.baseSnapshot);\n\n await this.imageHandler.uploadAndAppendImages(\n record.notionPageId,\n conversionResult.images,\n path,\n );\n\n let propsToUpdate: Record<string, unknown> | undefined;\n if (\n this.isDatabaseMode &&\n conversionResult.properties &&\n Object.keys(conversionResult.properties).length > 0\n ) {\n await this.ensureDbSchema();\n const title = extractTitle(path);\n propsToUpdate = this.propertyMapper.toNotionProperties(conversionResult.properties, title);\n } else if (conversionResult.properties?.title) {\n const titleStr = String(conversionResult.properties.title);\n propsToUpdate = {\n title: { title: [{ text: { content: titleStr } }] },\n };\n }\n\n // notionLastEdited 는 반드시 Notion 서버가 돌려준 값으로 저장한다. 로컬 시각\n // (new Date())을 쓰면 서버 시각과 클록 스큐·네트워크 지연만큼 어긋나 다음 pull 이\n // 가짜 modified 로 오인 → 불필요 재조회·집계(false-churn). 속성 갱신이 있으면 그\n // 응답이 최종 mutation 이라 권위값이고, 없으면(블록/이미지만 변경) 1회 getPage 로\n // 권위값을 받아 진짜 fixpoint 를 만든다. (I5 — pull 측 content_hash 가드와 이중 차단)\n let lastEditedTime: string;\n if (propsToUpdate && Object.keys(propsToUpdate).length > 0) {\n const updatedPage = await this.notionClient.updatePageProperties(\n record.notionPageId,\n propsToUpdate,\n );\n lastEditedTime = updatedPage.last_edited_time;\n } else {\n const refreshed = await this.notionClient.getPage(record.notionPageId);\n lastEditedTime = refreshed.last_edited_time;\n }\n\n const hash = computeHash(content);\n const fileStat = await this.vaultFs.getFileStat(path);\n const title = extractTitle(path);\n const aliases = extractAliases(conversionResult.properties);\n this.stateDb.transaction(() => {\n this.stateDb.updateHash(record.id, hash, Buffer.from(content, \"utf-8\"));\n this.stateDb.updateStatus(record.id, \"synced\");\n this.stateDb.setNotionLastEdited(record.id, lastEditedTime);\n if (fileStat) {\n this.stateDb.updateStatCache(record.id, fileStat.mtime, fileStat.size);\n }\n this.stateDb.storePreserveMarkers(path, conversionResult.preserveMarkers);\n this.stateDb.upsertWikilink({\n obsidianPath: path,\n notionPageId: record.notionPageId!,\n title,\n aliases,\n });\n });\n }\n\n // ──────────────────────────────────────────────────────────────────────────\n // 충돌 해소 (I8) — 해소 결과를 로컬에만 쓰지 않고 Notion 으로 재push + notionLastEdited\n // 재조정까지 한 트랜잭션으로 묶는다. ConflictResolver 단독은 로컬 write + updateHash 만\n // 수행하므로(merge 결과가 Notion 에 반영되지 않음) 다음 pull 이 원격으로 덮어써 영구\n // 유실·충돌 루프가 발생한다. 해소 → 전파(propagate)를 오케스트레이터에서 봉합해 무손실\n // 보장. 변환 파이프라인이 필요한 push 는 기존 엔터프라이즈 경로(pushUpdate)를 재사용한다.\n // ──────────────────────────────────────────────────────────────────────────\n\n /** 단일 충돌을 사용자가 고른 선택지(local/remote/merge/duplicate)로 해소 + Notion 전파. */\n async resolveConflict(conflict: Conflict, choice: ResolutionChoice): Promise<ResolutionResult> {\n const result = await this.conflictResolver.resolve(conflict, choice);\n await this.propagateResolution(conflict, choice, result);\n return result;\n }\n\n /** 단일 충돌을 전략(manual/local-first/remote-first/duplicate)으로 해소 + Notion 전파. */\n async resolveConflictByStrategy(\n conflict: Conflict,\n strategy: ConflictStrategy,\n ): Promise<ResolutionResult> {\n const result = await this.conflictResolver.resolveByStrategy(conflict, strategy);\n await this.propagateResolution(conflict, strategyToChoice(strategy), result);\n return result;\n }\n\n /** 여러 충돌을 동일 전략으로 일괄 해소 + Notion 전파. */\n async resolveAllConflicts(\n conflicts: Conflict[],\n strategy: ConflictStrategy,\n ): Promise<ResolutionResult[]> {\n const results: ResolutionResult[] = [];\n for (const conflict of conflicts) {\n results.push(await this.resolveConflictByStrategy(conflict, strategy));\n }\n return results;\n }\n\n /** 충돌 미리보기용 통합 diff(원본 vs 로컬 vs 원격). 해소 없이 표시 전용. */\n generateConflictDiff(conflict: Conflict): string {\n return this.conflictResolver.generateDiff(conflict);\n }\n\n /**\n * 해소 결과를 Notion 으로 전파해 로컬↔원격 일관성을 봉합한다.\n * - remote 선택: 로컬이 원격으로 갱신됐을 뿐이므로 push 불필요. notionLastEdited 만\n * 원격 변경의 lastEdited 로 재조정 → 다음 pull 이 같은 변경을 재충돌로 보지 않음.\n * - merge 실패(충돌 마커 잔존): 사용자가 직접 풀어야 하므로 conflict 상태 유지·push 안 함.\n * - local / merge(성공) / duplicate: 해소된 로컬 내용을 Notion 에 재push(pushUpdate 가\n * 변환·이미지·속성·해시·notionLastEdited 를 한 트랜잭션으로 재조정) → 무손실 수렴.\n */\n private async propagateResolution(\n conflict: Conflict,\n choice: ResolutionChoice,\n result: ResolutionResult,\n ): Promise<void> {\n const record = conflict.syncRecord;\n if (!record.notionPageId) return;\n\n if (choice === \"remote\") {\n this.stateDb.setNotionLastEdited(record.id, conflict.remoteChange.lastEdited);\n return;\n }\n\n // merge 가 충돌 마커를 남긴 경우(자동 병합 실패) → push 하지 않고 conflict 상태 유지.\n if (!result.success) return;\n\n // local / merge(성공) / duplicate: 해소된 로컬 본문을 Notion 으로 재push.\n await this.pushUpdate(record.obsidianPath);\n }\n\n // 반환값: 실제로 원격(Notion) 삭제가 전파되었는지 여부.\n // deleteSync=false 면 로컬 삭제를 pending 으로만 기록하고 Notion 은 보존하므로\n // false 를 돌려준다 → 호출부가 deleted 카운트를 올리지 않아 보고가 정직해진다.\n private async pushDelete(path: string): Promise<boolean> {\n const record = this.stateDb.getByPath(path);\n if (!record?.notionPageId) return false;\n\n if (!this.config.sync.deleteSync) {\n this.stateDb.updateStatus(record.id, \"pending\");\n return false;\n }\n\n try {\n await this.notionClient.archivePage(record.notionPageId);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes(\"archived ancestor\")) {\n // 부모 페이지가 이미 아카이브됨 → 자식도 자동 아카이브 상태\n } else {\n throw error;\n }\n }\n this.stateDb.transaction(() => {\n this.stateDb.delete(record.id);\n this.stateDb.deleteWikilink(record.obsidianPath);\n });\n return true;\n }\n\n private async pushMove(path: string): Promise<void> {\n const record = this.stateDb.getByPath(path);\n if (!record?.notionPageId) return;\n\n const newParentId = await this.resolveNotionParent(path);\n const currentParentId = record.notionParentId;\n\n if (currentParentId && !notionIdsEqual(newParentId, currentParentId)) {\n try {\n const parentType = this.isDatabaseMode ? \"database\" : \"page\";\n await this.notionClient.movePage(record.notionPageId, newParentId, parentType);\n this.stateDb.setNotionParentId(record.id, newParentId);\n } catch {\n getLogger().warn(`[Im-Nobsidian] Move API 실패 — \"${path}\" 내용만 업데이트합니다`);\n }\n }\n\n await this.pushUpdate(path);\n }\n\n private async detectRemoteChanges(): Promise<RemoteChange[]> {\n const changes: RemoteChange[] = [];\n this._childParentIds.clear();\n const lastPull = this.stateDb.getMeta(\"last_pull_at\");\n const syncedRecords = this.stateDb.getAll();\n const trackedPageIds = new Set(\n syncedRecords.filter((r) => r.notionPageId).map((r) => r.notionPageId!),\n );\n\n let remotePages: Array<{ id: string; last_edited_time: string }>;\n if (this.isDatabaseMode) {\n const allPages: Array<{ id: string; last_edited_time: string }> = [];\n let cursor: string | undefined;\n do {\n const result = await this.notionClient.queryDatabase(this.config.notion.databaseId!, {\n startCursor: cursor,\n });\n allPages.push(\n ...result.results.map((p) => ({ id: p.id, last_edited_time: p.last_edited_time })),\n );\n cursor = result.nextCursor ?? undefined;\n } while (cursor);\n remotePages = allPages;\n } else {\n // 디스커버리 이중 전략(비용 상한 하이브리드):\n // 1) 기본 — root 서브트리 직접 BFS 순회(getChildPagesRecursive). 비용이 실제 동기화\n // 대상(서브트리)에 비례해, 작은 볼트가 수천 페이지 워크스페이스에 있어도 빠르다\n // (I10: 2-파일 볼트 pull ~12s). 단 비용은 서브트리 **전체 블록 수**에 비례하므로,\n // 2) 콘텐츠가 많은 대규모 서브트리에서는 시간 예산(DISCOVERY_RECURSIVE_BUDGET_MS)을\n // 초과할 수 있다. 그 경우 워크스페이스 search 기반 디스커버리로 폴백한다(비용이\n // 워크스페이스 페이지 수에 비례·예측가능·유한). 두 경로 모두 중첩 깊이와 무관하게\n // 모든 하위 페이지를 찾으므로 **무손실**이며, DB 행·archive/in_trash 를 동일하게\n // 제외해 orphan(삭제) 판정도 일관된다.\n let underRoot: PageObjectResponse[];\n try {\n underRoot = await this.notionClient.getChildPagesRecursive(this.config.notion.rootPageId, {\n deadlineMs: Date.now() + SyncOrchestrator.DISCOVERY_RECURSIVE_BUDGET_MS,\n });\n } catch (error) {\n if (!(error instanceof DiscoveryTooLargeError)) throw error;\n getLogger().info(\n `[Im-Nobsidian] 서브트리가 큼(${error.message}) → 워크스페이스 search 기반 디스커버리로 전환`,\n );\n underRoot = await this.notionClient.getPagesUnderRootViaSearch(\n this.config.notion.rootPageId,\n );\n }\n // 폴더 판정용 _childParentIds: 발견된 각 페이지의 부모(자식을 가진 페이지)를 수집한다.\n // 부모가 page_id 면 추가 API 호출 없이 즉시 해석(공통 경로), block 중첩만 1회 조회.\n this._childParentIds.add(normalizeNotionId(this.config.notion.rootPageId));\n for (const page of underRoot) {\n const parentId = await this.extractParentId(page);\n if (parentId) this._childParentIds.add(normalizeNotionId(parentId));\n }\n remotePages = underRoot.map((p) => ({ id: p.id, last_edited_time: p.last_edited_time }));\n }\n\n // 원격 페이지 목록을 page_id 로 디듀프한다. search API(페이지 모드)·queryDatabase(DB 모드)\n // 모두 페이지네이션 사이 재정렬로 같은 페이지를 중복 반환할 수 있고, 중복이 changes 로\n // 새면 같은 page_id 가 두 번 create 되어 동일 콘텐츠가 클린·`(1)` 두 경로에 기록(첫 파일\n // 고아화)된다. 여기가 페이지·DB 양 모드를 함께 막는 단일 차단점이다.\n const seenRemoteIds = new Set<string>();\n for (const page of remotePages) {\n const key = normalizeNotionId(page.id);\n if (seenRemoteIds.has(key)) continue;\n seenRemoteIds.add(key);\n\n const record = this.stateDb.getByNotionId(page.id);\n\n if (!record) {\n changes.push({\n pageId: page.id,\n type: \"created\",\n lastEdited: page.last_edited_time,\n previousEdited: null,\n });\n } else if (page.last_edited_time !== record.notionLastEdited) {\n changes.push({\n pageId: page.id,\n type: \"modified\",\n lastEdited: page.last_edited_time,\n previousEdited: record.notionLastEdited,\n });\n }\n\n trackedPageIds.delete(page.id);\n }\n\n if (this.config.sync.deleteSync && lastPull) {\n for (const orphanId of trackedPageIds) {\n const record = syncedRecords.find((r) => r.notionPageId === orphanId);\n if (record) {\n changes.push({\n pageId: orphanId,\n type: \"deleted\",\n lastEdited: new Date().toISOString(),\n previousEdited: record.notionLastEdited,\n });\n }\n }\n }\n\n return changes;\n }\n\n /**\n * 증분 원격 변경 감지 — `since` 이후 수정된 페이지만 search 로 받아 created/modified 만\n * 만든다. **삭제는 의도적으로 감지하지 않는다**: search API 는 in_trash/archived 페이지를\n * 반환하지 않아(=사라진 것을 증분만으로는 구분 불가) 삭제 판정에는 전체 enumeration 이\n * 필수다. 따라서 호출부는 `deleteSync` 가 켜진 경우 이 fast-path 를 쓰지 않고\n * `detectRemoteChanges`(전체 스캔, 삭제 diff 포함)로 우회한다. (I10)\n */\n private async detectRemoteChangesIncremental(since: string): Promise<RemoteChange[]> {\n const changes: RemoteChange[] = [];\n this._childParentIds.clear();\n // 안전창만큼 과거로 되돌려 조회(F20). 넓어진 창에 들어온 무변경 페이지는 아래\n // last_edited 비교가 걸러내므로 재처리 비용 없이 멱등하다.\n const sinceMs = Date.parse(since);\n const safeSince = Number.isFinite(sinceMs)\n ? new Date(sinceMs - INCREMENTAL_SAFETY_WINDOW_MS).toISOString()\n : since;\n const recentPages = await this.notionClient.searchRecentPages(safeSince);\n\n for (const page of recentPages) {\n const record = this.stateDb.getByNotionId(page.id);\n if (!record) {\n try {\n const fullPage = await this.notionClient.getPage(page.id);\n const parentId = await this.extractParentId(fullPage);\n if (parentId) this._childParentIds.add(normalizeNotionId(parentId));\n if (parentId && this.isTrackedParent(parentId)) {\n changes.push({\n pageId: page.id,\n type: \"created\",\n lastEdited: page.last_edited_time,\n previousEdited: null,\n });\n }\n } catch {\n // inaccessible page\n }\n continue;\n }\n if (page.last_edited_time !== record.notionLastEdited) {\n changes.push({\n pageId: page.id,\n type: \"modified\",\n lastEdited: page.last_edited_time,\n previousEdited: record.notionLastEdited,\n });\n }\n }\n\n return changes;\n }\n\n private isTrackedParent(parentId: string): boolean {\n if (notionIdsEqual(parentId, this.config.notion.rootPageId)) return true;\n return !!this.stateDb.getByNotionId(parentId);\n }\n\n private async pullCreate(pageId: string): Promise<string> {\n const page = await this.notionClient.getPage(pageId);\n const title = this.notionClient.extractTitle(page);\n const safeName = sanitizeFileName(title);\n\n const parentPath = await this.resolveParentPath(page);\n\n const hasChildPages = await this.pageHasChildContainers(pageId);\n\n const { content: markdown, compact: exportCompact } = await this.fetchPageMarkdown(pageId);\n const hasContent = markdown.trim().length > 0;\n\n let filePath: string;\n let fileType: \"file\" | \"folder-note\" | \"folder-only\";\n\n if (hasChildPages && hasContent) {\n const folderPath = parentPath ? `${parentPath}/${safeName}` : safeName;\n filePath = await this.resolveUniqueFilePath(`${folderPath}/${safeName}.md`);\n fileType = \"folder-note\";\n await this.vaultFs.ensureFolder(folderPath);\n } else if (hasChildPages && !hasContent) {\n const folderPath = parentPath ? `${parentPath}/${safeName}` : safeName;\n filePath = await this.resolveUniqueFilePath(`${folderPath}/${safeName}.md`);\n fileType = \"folder-only\";\n await this.vaultFs.ensureFolder(folderPath);\n } else {\n const basePath = parentPath ? `${parentPath}/${safeName}.md` : `${safeName}.md`;\n filePath = await this.resolveUniqueFilePath(basePath);\n fileType = \"file\";\n }\n\n let properties: Record<string, unknown>;\n if (this.isDatabaseMode) {\n await this.ensureDbSchema();\n properties = this.propertyMapper.fromNotionProperties(\n (page as unknown as { properties: Record<string, unknown> }).properties,\n );\n } else {\n properties = this.notionClient.extractProperties(page);\n }\n // D2(page 모드): 파일명 stem 으로 복원 가능한 제목은 프론트매터에 주입하지 않는다 —\n // 원본에 없던 `title:` 키가 pull 마다 생기는 가짜 diff 의 원인. sanitize·`(1)` 접미사로\n // 파일명이 제목과 달라진 경우만 보존한다(DB 모드 title 은 Name 컬럼 데이터라 항상 유지).\n if (this.isDatabaseMode || extractTitle(filePath) !== title) {\n properties.title = title;\n }\n\n let processedMarkdown = markdown;\n if (this.config.conversion.imageDownload === \"immediate\") {\n const imageResult = await this.imageHandler.downloadAllImages(markdown, title, pageId);\n processedMarkdown = imageResult.content;\n this._pullImageCount += imageResult.downloads.length;\n }\n\n const fileResult = await this.imageHandler.downloadAllFiles(processedMarkdown, title);\n processedMarkdown = fileResult.content;\n this._pullFileCount += fileResult.downloads.length;\n\n const finalContent = this.pipeline.convertToMarkdown(\n processedMarkdown,\n {\n direction: \"pull\",\n path: \"markdown-api\",\n filePath,\n parentMode: this.config.notion.parentMode,\n },\n { properties, notionExportCompact: exportCompact },\n );\n\n // 부모 해소는 파일 기록 전에 끝낸다. parent 가 block 일 때 resolveBlockToPageId 가\n // API 를 호출(429 가능)하는데, 이를 writeFile 뒤에 두면 기록만 되고 sync_state 등록 전에\n // throw → 재시도 시 같은 페이지가 `(1)` 로 재생성되며 첫 파일이 고아가 된다. 기록↔등록\n // 사이에는 throw 가능한 원격 호출을 두지 않는다(원자적 등록 보장).\n const resolvedParentId = await this.extractParentId(page);\n\n await this.vaultFs.writeFile(filePath, finalContent);\n\n const hash = computeHash(finalContent);\n const pullStat = await this.vaultFs.getFileStat(filePath);\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: filePath,\n notionPageId: pageId,\n notionParentId: resolvedParentId,\n contentHash: hash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType,\n status: \"synced\",\n baseSnapshot: Buffer.from(finalContent, \"utf-8\"),\n localMtime: pullStat?.mtime ?? null,\n localFileSize: pullStat?.size ?? null,\n });\n\n const aliases = extractAliases(properties);\n this.stateDb.upsertWikilink({\n obsidianPath: filePath,\n notionPageId: pageId,\n title,\n aliases,\n });\n });\n\n return filePath;\n }\n\n /**\n * 페이지가 폴더(자식 페이지·자식 DB 보유)인지 신뢰성 있게 판정한다.\n *\n * 결함(폴더노트 본문분리)의 근본 원인은 얕은 판정이었다 — 최상위 블록 첫 페이지에서\n * child_page 만 검사하면 callout·column·toggle 안에 중첩된 자식 페이지나 child_database 를\n * 놓쳐 폴더노트가 file 로 오분류되고, 본문이 폴더 밖 최상위로 밀려 resolveUniqueFilePath\n * 충돌(' (1).md')로 쪼개졌다.\n *\n * 1차: 발견 단계(서브트리 순회/증분)에서 전 페이지의 부모를 해소하며 만든\n * _childParentIds 집합으로 O(1) 판정(추가 API 호출 0, 처리 순서 무관) — 전체 pull 경로.\n * 폴백: 집합에 없을 때만(증분 pull 의 신규 폴더 등) fetchAllChildrenDeep 로 컨테이너를\n * 재귀 탐색해 child_page·child_database 를 직접 확인한다.\n */\n private async pageHasChildContainers(pageId: string): Promise<boolean> {\n if (this._childParentIds.has(normalizeNotionId(pageId))) return true;\n try {\n const deep = await this.notionClient.fetchAllChildrenDeep(pageId);\n return deep.some((b) => b.type === \"child_page\" || b.type === \"child_database\");\n } catch {\n return false;\n }\n }\n\n private async pullUpdate(\n change: RemoteChange,\n ): Promise<{ path?: string; conflict?: Conflict; unchanged?: boolean }> {\n const record = this.stateDb.getByNotionId(change.pageId);\n if (!record) return {};\n\n const page = await this.notionClient.getPage(change.pageId);\n const fetched = await this.fetchPageMarkdown(change.pageId);\n let markdown = fetched.content;\n\n const title = this.notionClient.extractTitle(page);\n\n let properties: Record<string, unknown>;\n if (this.isDatabaseMode) {\n await this.ensureDbSchema();\n properties = this.propertyMapper.fromNotionProperties(\n (page as unknown as { properties: Record<string, unknown> }).properties,\n );\n } else {\n properties = this.notionClient.extractProperties(page);\n }\n // D2: pullCreate 와 동일 — 파일명으로 복원 가능한 제목은 주입하지 않는다.\n if (this.isDatabaseMode || extractTitle(record.obsidianPath) !== title) {\n properties.title = title;\n }\n\n if (this.config.conversion.imageDownload === \"immediate\") {\n const imageResult = await this.imageHandler.downloadAllImages(markdown, title, change.pageId);\n markdown = imageResult.content;\n this._pullImageCount += imageResult.downloads.length;\n }\n\n const fileResult = await this.imageHandler.downloadAllFiles(markdown, title);\n markdown = fileResult.content;\n this._pullFileCount += fileResult.downloads.length;\n\n const savedMarkers = this.stateDb.getPreserveMarkers(record.obsidianPath);\n const remoteContent = this.pipeline.convertToMarkdown(\n markdown,\n {\n direction: \"pull\",\n path: \"markdown-api\",\n filePath: record.obsidianPath,\n parentMode: this.config.notion.parentMode,\n },\n {\n properties,\n preserveMarkers: savedMarkers.length > 0 ? savedMarkers : undefined,\n notionExportCompact: fetched.compact,\n },\n );\n\n let localContent: string;\n try {\n localContent = await this.vaultFs.readFile(record.obsidianPath);\n } catch {\n localContent = \"\";\n }\n\n const resolution = resolvePullConflict({\n record,\n localContent,\n remoteContent,\n remoteChange: change,\n strategy: this.config.sync.conflictStrategy,\n });\n\n if (resolution.action === \"skip\") {\n // local-first: 로컬 보존, 리모트 변경 무시\n return { path: record.obsidianPath };\n }\n if (resolution.action === \"conflict\") {\n this.stateDb.updateStatus(record.id, \"conflict\");\n return { conflict: resolution.conflict };\n }\n\n // I5 false-churn 차단: 리모트 변환 결과가 디스크 내용과 바이트 동일하면 Notion 이\n // last_edited 만 갱신한 '가짜 수정'이다. 파일을 재기록하면 mtime 이 바뀌어 다음 push 가\n // 로컬 수정으로 오인 → push↔pull 무한 churn. 파일은 건드리지 않고 추적 메타\n // (notionLastEdited)만 현재 원격값으로 정렬해 재감지를 멈춘다. content_hash 비교로\n // 진짜 변경과 가짜 변경을 구분하는 핵심 멱등 지점이다.\n if (remoteContent === localContent) {\n const stat = await this.vaultFs.getFileStat(record.obsidianPath);\n this.stateDb.upsert({\n obsidianPath: record.obsidianPath,\n notionPageId: change.pageId,\n notionParentId: record.notionParentId,\n contentHash: computeHash(remoteContent),\n notionLastEdited: page.last_edited_time,\n localLastModified: record.localLastModified,\n syncDirection: record.syncDirection,\n fileType: record.fileType,\n status: \"synced\",\n baseSnapshot: Buffer.from(remoteContent, \"utf-8\"),\n localMtime: stat?.mtime ?? record.localMtime ?? null,\n localFileSize: stat?.size ?? record.localFileSize ?? null,\n });\n return { path: record.obsidianPath, unchanged: true };\n }\n\n await this.vaultFs.writeFile(record.obsidianPath, remoteContent);\n\n const updateStat = await this.vaultFs.getFileStat(record.obsidianPath);\n const newHash = computeHash(remoteContent);\n this.stateDb.transaction(() => {\n this.stateDb.upsert({\n obsidianPath: record.obsidianPath,\n notionPageId: change.pageId,\n notionParentId: record.notionParentId,\n contentHash: newHash,\n notionLastEdited: page.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: record.syncDirection,\n fileType: record.fileType,\n status: \"synced\",\n baseSnapshot: Buffer.from(remoteContent, \"utf-8\"),\n localMtime: updateStat?.mtime ?? null,\n localFileSize: updateStat?.size ?? null,\n });\n\n const aliases = extractAliases(properties);\n this.stateDb.upsertWikilink({\n obsidianPath: record.obsidianPath,\n notionPageId: change.pageId,\n title,\n aliases,\n });\n });\n\n return { path: record.obsidianPath };\n }\n\n private async pullDelete(pageId: string): Promise<string | null> {\n const record = this.stateDb.getByNotionId(pageId);\n if (!record) return null;\n\n if (this.config.sync.deleteSync) {\n try {\n await this.vaultFs.deleteFile(record.obsidianPath);\n } catch {\n // 이미 삭제된 경우 무시\n }\n }\n\n this.stateDb.transaction(() => {\n this.stateDb.delete(record.id);\n this.stateDb.deleteWikilink(record.obsidianPath);\n });\n return record.obsidianPath;\n }\n\n private async ensureFolderPage(folderPath: string): Promise<void> {\n const folderNotePath = `${folderPath}/${folderPath.split(\"/\").pop()}.md`;\n const folderNoteRecord = this.stateDb.getByPath(folderNotePath);\n\n if (folderNoteRecord?.notionPageId) {\n const existing = this.stateDb.getByPath(folderPath);\n if (existing) {\n this.stateDb.transaction(() => {\n this.stateDb.delete(existing.id);\n this.stateDb.deleteWikilink(existing.obsidianPath);\n });\n }\n return;\n }\n\n const existing = this.stateDb.getByPath(folderPath);\n if (existing?.notionPageId) return;\n\n const parts = folderPath.split(\"/\");\n const folderName = parts[parts.length - 1]!;\n\n let parentId = this.config.notion.rootPageId;\n if (parts.length > 1) {\n const parentPath = parts.slice(0, -1).join(\"/\");\n await this.ensureFolderPage(parentPath);\n const parentNotePath = `${parentPath}/${parentPath.split(\"/\").pop()}.md`;\n const parentNote = this.stateDb.getByPath(parentNotePath);\n const parentRecord = this.stateDb.getByPath(parentPath);\n if (parentNote?.notionPageId) {\n parentId = parentNote.notionPageId;\n } else if (parentRecord?.notionPageId) {\n parentId = parentRecord.notionPageId;\n }\n }\n\n const folderPage = await this.notionClient.createPage({\n parentId,\n parentType: \"page\",\n title: folderName,\n });\n\n this.stateDb.upsert({\n obsidianPath: folderPath,\n notionPageId: folderPage.id,\n notionParentId: parentId,\n contentHash: \"\",\n notionLastEdited: folderPage.last_edited_time,\n localLastModified: new Date().toISOString(),\n syncDirection: \"both\",\n fileType: \"folder-note\",\n status: \"synced\",\n });\n }\n\n private async resolveNotionParent(filePath: string): Promise<string> {\n const parts = filePath.split(\"/\");\n if (parts.length <= 1) return this.config.notion.rootPageId;\n\n const folderPath = parts.slice(0, -1).join(\"/\");\n const folderRecord = this.stateDb.getByPath(folderPath);\n if (folderRecord?.notionPageId) return folderRecord.notionPageId;\n\n const folderName = parts[parts.length - 2]!;\n const folderNotePath = `${folderPath}/${folderName}.md`;\n const folderNoteRecord = this.stateDb.getByPath(folderNotePath);\n if (folderNoteRecord?.notionPageId) return folderNoteRecord.notionPageId;\n\n return this.config.notion.rootPageId;\n }\n\n private repairFolderRecords(): void {\n const allRecords = this.stateDb.getAll();\n const folderRecords = allRecords.filter(\n (r) => r.fileType === \"folder-note\" && !r.obsidianPath.endsWith(\".md\"),\n );\n for (const folder of folderRecords) {\n const folderName = folder.obsidianPath.split(\"/\").pop()!;\n const folderNotePath = `${folder.obsidianPath}/${folderName}.md`;\n const noteRecord = this.stateDb.getByPath(folderNotePath);\n if (noteRecord?.notionPageId) {\n this.stateDb.transaction(() => {\n this.stateDb.delete(folder.id);\n this.stateDb.deleteWikilink(folder.obsidianPath);\n });\n }\n }\n }\n\n private isFolderNote(filePath: string): boolean {\n const parts = filePath.split(\"/\");\n if (parts.length < 2) return false;\n const fileName = parts[parts.length - 1]!.replace(/\\.md$/, \"\");\n const folderName = parts[parts.length - 2]!;\n return fileName === folderName;\n }\n\n private async resolveParentPath(page: PageObjectResponse): Promise<string> {\n const parentId = await this.extractParentId(page);\n if (!parentId || notionIdsEqual(parentId, this.config.notion.rootPageId)) return \"\";\n\n const parentRecord = this.stateDb.getByNotionId(parentId);\n if (parentRecord) {\n if (parentRecord.fileType === \"folder-note\" || parentRecord.fileType === \"folder-only\") {\n const pathParts = parentRecord.obsidianPath.split(\"/\");\n pathParts.pop();\n return pathParts.join(\"/\");\n }\n const pathParts = parentRecord.obsidianPath.split(\"/\");\n pathParts.pop();\n const parentDir = pathParts.join(\"/\");\n return (\n parentDir ||\n sanitizeFileName(this.notionClient.extractTitle(await this.notionClient.getPage(parentId)))\n );\n }\n\n try {\n const parentPage = await this.notionClient.getPage(parentId);\n const parentTitle = this.notionClient.extractTitle(parentPage);\n const grandparentPath = await this.resolveParentPath(parentPage);\n const safeName = sanitizeFileName(parentTitle);\n return grandparentPath ? `${grandparentPath}/${safeName}` : safeName;\n } catch {\n return \"\";\n }\n }\n\n private async pushCreatePage(\n parentId: string,\n parentType: \"page\" | \"database\",\n title: string,\n markdownContent: string,\n properties?: Record<string, unknown>,\n ): Promise<PageObjectResponse> {\n if (this.config.conversion.preferMarkdownApi !== false) {\n const enhanced = obsidianToNotionEnhanced(markdownContent);\n return await this.notionClient.createPageWithMarkdown({\n parentId,\n parentType,\n title,\n markdown: enhanced,\n properties,\n });\n }\n\n const blocks = this.blockConverter.markdownToNotionBlocks(markdownContent);\n const page = await this.notionClient.createPage({\n parentId,\n parentType,\n title,\n properties,\n });\n if (blocks.length > 0) {\n await this.notionClient.appendChildren(page.id, blocks);\n }\n return page;\n }\n\n // 페이지에 살아있는(휴지통 아님) child page/database 가 직속 블록으로 존재하는가.\n // 휴지통(in_trash) 자식은 children.list 에 잡히지 않으므로 \"live\" 는 암묵적이다.\n private async pageHasLiveChildren(pageId: string): Promise<boolean> {\n try {\n const children = await this.notionClient.fetchAllChildren(pageId);\n return children.some((b) => b.type === \"child_page\" || b.type === \"child_database\");\n } catch (error) {\n // 조회 실패 시 안전측: 자식이 있을 수 있다고 보고 파괴적 replace 를 막는다.\n getLogger().warn(\n `[Im-Nobsidian] 자식 페이지 조회 실패 — 본문 push 보수적 생략(자식 보호): ${pageId} (${\n error instanceof Error ? error.message : String(error)\n })`,\n );\n return true;\n }\n }\n\n private async pushUpdatePage(\n pageId: string,\n markdownContent: string,\n _baseSnapshot?: Buffer | null,\n ): Promise<void> {\n // 데이터 손실 가드: 이 페이지가 살아있는 child page/database 를 가지면 두 push 경로\n // (replace_content[allow_deleting_content] · block 삭제-후-append)가 모두 자식을\n // 삭제한다. 실Notion probe 확인: replace_content 는 새 마크다운에 없는 child page 를\n // in_trash 로 삭제하고, child page 를 mention 으로 표현하려 하면 거부한다.\n // 자식 페이지는 각자 자기 sync record 로 독립 동기화되므로, 여기서는 본문 갱신을\n // 건너뛰고 자식을 보존한다(무손실). 폴더노트 본문 편집의 Notion 반영은 의도적 degrade.\n if (await this.pageHasLiveChildren(pageId)) {\n getLogger().warn(\n `[Im-Nobsidian] 자식 페이지 보유 — 본문 push 생략(자식 삭제 방지): ${pageId}. ` +\n `자식 페이지는 각자 동기화되며, 이 페이지 본문 편집은 Notion 에 반영되지 않습니다.`,\n );\n return;\n }\n\n if (this.config.conversion.preferMarkdownApi !== false) {\n const enhanced = obsidianToNotionEnhanced(markdownContent);\n await this.notionClient.replacePageMarkdown(pageId, enhanced);\n return;\n }\n\n const blocks = this.blockConverter.markdownToNotionBlocks(markdownContent);\n const existingBlocks = await this.notionClient.fetchAllChildren(pageId);\n\n if (blocks.length > 0) {\n await this.notionClient.appendChildren(pageId, blocks);\n }\n const deleteSema = new Sema(this.config.advanced.concurrency);\n await Promise.all(\n existingBlocks.map(async (block) => {\n await deleteSema.acquire();\n try {\n await this.notionClient.deleteBlock(block.id);\n } finally {\n deleteSema.release();\n }\n }),\n );\n }\n\n private async fetchPageMarkdown(pageId: string): Promise<{ content: string; compact: boolean }> {\n if (this.config.conversion.preferMarkdownApi !== false) {\n try {\n const result = await this.notionClient.getPageMarkdown(pageId);\n this.collectInlineDbRefs(pageId, result.markdown);\n return {\n content: this.resolveNotionIdWikilinks(notionEnhancedToObsidian(result.markdown)),\n // 압축형 판정은 반드시 원시 export 기준 — enhanced 변환이 <empty-block/> 을\n // 빈 줄로 바꾼 뒤에는 BlockSpacer 가 저작형과 구분할 수 없다(D1).\n compact: isCompactExport(result.markdown),\n };\n } catch {\n // Markdown API 실패 시 blocks API fallback\n }\n }\n // blocks-API 폴백 산출물은 이미 표준 간격 — 재간격 불필요\n return { content: await this.blockConverter.notionBlocksToMarkdown(pageId), compact: false };\n }\n\n // Markdown API는 인라인 데이터베이스를 다음처럼 렌더한다(컬럼/synced_block 내부 포함):\n // <database url=\"https://www.notion.so/<id-nohyph>\" inline=\"true\"\n // data-source-url=\"collection://<ds-id>\">Title</database>\n // url 안의 32자리 hex 가 databaseId 이므로, 별도 블록 트리 재귀 없이 이 태그만 파싱해\n // 깊이 중첩된 child_database 까지 폴더+.base 동기화 대상으로 등록한다.\n private collectInlineDbRefs(parentPageId: string, rawMarkdown: string): void {\n const re = /<database\\b[^>]*\\burl=\"https:\\/\\/www\\.notion\\.so\\/([a-f0-9]{32})\"[^>]*>/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(rawMarkdown)) !== null) {\n const dbId = m[1];\n if (dbId) this._inlineDbRefs.set(dbId, parentPageId);\n }\n }\n\n // pull 시 url 기반 page mention 은 `[[notion:<id>]]` 로 1차 변환된다(notionEnhancedToObsidian).\n // 이를 state DB 역조회로 원래 `[[제목]]` 위키링크로 복원해 push↔pull 라운드트립을 수렴시킨다.\n // 볼트 밖/미추적 페이지면 `[[notion:<id>]]` 를 그대로 두어 정보 손실을 막는다.\n private resolveNotionIdWikilinks(markdown: string): string {\n return markdown.replace(/\\[\\[notion:([a-f0-9]{32})\\]\\]/g, (match, id: string) => {\n const record = this.stateDb.getByNotionId(normalizeNotionId(id));\n if (!record?.obsidianPath) return match;\n const base = record.obsidianPath.split(\"/\").pop() ?? record.obsidianPath;\n const title = base.replace(/\\.md$/, \"\");\n return `[[${title}]]`;\n });\n }\n\n private async extractParentId(page: PageObjectResponse): Promise<string | null> {\n const parent = page.parent as {\n type: string;\n page_id?: string;\n database_id?: string;\n block_id?: string;\n };\n if (parent.type === \"page_id\") return parent.page_id ?? null;\n if (parent.type === \"database_id\") return parent.database_id ?? null;\n if (parent.type === \"block_id\" && parent.block_id) {\n return this.resolveBlockToPageId(parent.block_id);\n }\n return null;\n }\n\n private async resolveBlockToPageId(blockId: string): Promise<string | null> {\n for (let i = 0; i < 10; i++) {\n try {\n const block = await this.notionClient.getBlock(blockId);\n const bp = (\n block as unknown as { parent: { type: string; page_id?: string; block_id?: string } }\n ).parent;\n if (bp.type === \"page_id\") return bp.page_id ?? null;\n if (bp.type === \"block_id\" && bp.block_id) {\n blockId = bp.block_id;\n continue;\n }\n return null;\n } catch {\n return null;\n }\n }\n return null;\n }\n\n private cleanupInterruptedSync(): void {\n const pushInProgress = this.stateDb.getMeta(\"push_in_progress\");\n const pullInProgress = this.stateDb.getMeta(\"pull_in_progress\");\n\n if (pushInProgress === \"true\") {\n getLogger().warn(\"[Im-Nobsidian] 이전 push가 비정상 종료됨 — 플래그 정리\");\n this.stateDb.setMeta(\"push_in_progress\", \"\");\n }\n if (pullInProgress === \"true\") {\n getLogger().warn(\"[Im-Nobsidian] 이전 pull이 비정상 종료됨 — 플래그 정리\");\n this.stateDb.setMeta(\"pull_in_progress\", \"\");\n }\n }\n\n /**\n * I12 — 중단된 push create 작업 재개.\n *\n * pending_operations 에 미완료(create·push) 항목이 있으면:\n * - state 에 notion_page_id 가 이미 있으면 → 생성·매핑까지는 끝났고 markCompleted 직전에\n * 중단된 것 → 완료 처리(잔여 본문/이미지는 다음 변경감지가 pushUpdate 로 마무리).\n * - notion_page_id 가 비어 있으면(Window A: 생성 적용됐으나 매핑 기록 전 중단) → 부모에서\n * 제목으로 child_page 를 검색해 고아 페이지를 입양(중복 생성 차단). 없으면 자리표시\n * 레코드를 제거(FK CASCADE 로 op 도 삭제)해 다음 push 가 새로 생성하게 한다.\n *\n * 한계(문서화): Notion 은 idempotency key 가 없어 \"생성 요청 적용 직후 같은 호출 내 재시도\"\n * 로 인한 중복은 완전히 차단하지 못한다. 429 는 적용 전 거절이라 안전하고, 프로세스 재시작\n * 후 재개는 본 검색-입양으로 중복을 막는다. DB 모드(부모가 database)는 child_page 검색이\n * 불가하므로 자리표시 제거 후 재생성으로 폴백한다.\n */\n private async recoverInterruptedPushOps(): Promise<void> {\n const ops = this.stateDb.getIncompletePendingOperations();\n if (ops.length === 0) return;\n\n for (const op of ops) {\n if (op.direction !== \"push\" || op.operation !== \"create\") {\n // 현재 WAL 재개는 create·push 만 대상. 그 외는 정리만 한다.\n this.stateDb.markPendingFailed(op.id, \"unsupported resume op\");\n continue;\n }\n\n let payload: { path?: string; parentId?: string; title?: string } = {};\n try {\n payload = JSON.parse(op.payload ?? \"{}\") as typeof payload;\n } catch {\n this.stateDb.markPendingFailed(op.id, \"invalid payload json\");\n continue;\n }\n const path = payload.path;\n if (!path) {\n this.stateDb.markPendingFailed(op.id, \"missing payload.path\");\n continue;\n }\n\n const state = this.stateDb.getByPath(path);\n if (state?.notionPageId) {\n // 매핑 존재 → 안전. 완료 처리하고 잔여는 변경감지(contentHash=\"\")가 pushUpdate 로 마무리.\n this.stateDb.markPendingCompleted(op.id);\n continue;\n }\n\n const parentId = payload.parentId ?? state?.notionParentId ?? undefined;\n const title = payload.title;\n const adopted = parentId && title ? await this.findChildPageByTitle(parentId, title) : null;\n\n if (adopted) {\n // 고아 페이지 입양: 매핑만 채우고 pending 유지 → 다음 변경감지가 본문·이미지 마무리.\n this.stateDb.upsert({\n obsidianPath: path,\n notionPageId: adopted,\n notionParentId: parentId ?? null,\n contentHash: \"\",\n notionLastEdited: state?.notionLastEdited ?? null,\n localLastModified: new Date().toISOString(),\n syncDirection: state?.syncDirection ?? \"both\",\n fileType: state?.fileType ?? (this.isFolderNote(path) ? \"folder-note\" : \"file\"),\n status: \"pending\",\n baseSnapshot: null,\n localMtime: null,\n localFileSize: null,\n });\n this.stateDb.markPendingCompleted(op.id);\n getLogger().info(`[Im-Nobsidian] 중단된 create 재개 — 고아 페이지 입양: ${path}`);\n } else if (state) {\n // 생성된 페이지를 못 찾음 → 자리표시 제거(CASCADE 로 op 삭제) → 다음 push 가 새로 생성.\n this.stateDb.delete(state.id);\n getLogger().info(`[Im-Nobsidian] 중단된 create 재개 — 미생성 확인, 자리표시 제거: ${path}`);\n } else {\n this.stateDb.markPendingCompleted(op.id);\n }\n }\n }\n\n /** 부모 페이지의 직속 자식 중 제목이 일치하는(보관/휴지통 제외) child_page id 를 찾는다. */\n private async findChildPageByTitle(parentId: string, title: string): Promise<string | null> {\n try {\n const children = await this.notionClient.fetchAllChildren(parentId);\n for (const b of children) {\n if (b.type !== \"child_page\") continue;\n const childTitle = (b as { child_page?: { title?: string } }).child_page?.title;\n if (childTitle !== title) continue;\n try {\n const page = await this.notionClient.getPage(b.id);\n const inTrash = (page as { in_trash?: boolean }).in_trash === true;\n if (inTrash || page.archived) continue;\n } catch {\n continue;\n }\n return b.id;\n }\n } catch (error) {\n getLogger().warn(\n `[Im-Nobsidian] 고아 페이지 검색 실패 (${parentId}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n return null;\n }\n\n private async resolveUniqueFilePath(basePath: string): Promise<string> {\n if (!(await this.vaultFs.exists(basePath))) return basePath;\n\n const dir = basePath.lastIndexOf(\"/\") >= 0 ? basePath.slice(0, basePath.lastIndexOf(\"/\")) : \"\";\n const ext = \".md\";\n const name = basePath.slice(dir ? dir.length + 1 : 0, -ext.length);\n\n for (let i = 1; i <= 99; i++) {\n const candidate = dir ? `${dir}/${name} (${i})${ext}` : `${name} (${i})${ext}`;\n if (!(await this.vaultFs.exists(candidate))) return candidate;\n }\n\n return basePath;\n }\n}\n\nfunction extractTitle(filePath: string): string {\n const parts = filePath.split(\"/\");\n const filename = parts[parts.length - 1] ?? \"\";\n return filename.replace(/\\.md$/, \"\");\n}\n\nfunction extractAliases(properties: Record<string, unknown>): string[] {\n const raw = properties.aliases ?? properties.alias;\n if (!raw) return [];\n if (Array.isArray(raw)) return raw.filter((a): a is string => typeof a === \"string\");\n if (typeof raw === \"string\")\n return raw\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n return [];\n}\n","import { readFile, writeFile, unlink, rename, mkdir, readdir, stat } from \"node:fs/promises\";\nimport { readFileSync } from \"node:fs\";\nimport { join, relative, dirname } from \"node:path\";\nimport type { VaultFS, NonMdFileInfo, FileStatInfo } from \"./vault-fs.js\";\nimport type { FileInfo } from \"./change-detector.js\";\nimport { IGNORE_FILE } from \"../constants/paths.js\";\n\nexport interface PathFilterConfig {\n readonly include?: string[];\n readonly exclude?: string[];\n}\n\nexport class NodeVaultFS implements VaultFS {\n private readonly includePatterns: string[];\n private readonly excludePatterns: string[];\n\n constructor(\n private readonly rootPath: string,\n pathConfig?: PathFilterConfig,\n ) {\n this.includePatterns = pathConfig?.include ?? [];\n const configExclude = pathConfig?.exclude ?? [];\n const ignorePatterns = this.loadImNobsidianIgnore();\n this.excludePatterns = [...configExclude, ...ignorePatterns];\n }\n\n private loadImNobsidianIgnore(): string[] {\n try {\n const ignorePath = join(this.rootPath, IGNORE_FILE);\n const content = readFileSync(ignorePath, \"utf-8\");\n return content\n .split(\"\\n\")\n .map((line: string) => line.trim())\n .filter((line: string) => line && !line.startsWith(\"#\"));\n } catch {\n return [];\n }\n }\n\n async readFile(path: string): Promise<string> {\n const fullPath = join(this.rootPath, path);\n return readFile(fullPath, \"utf-8\");\n }\n\n async readBinary(path: string): Promise<Buffer> {\n const fullPath = join(this.rootPath, path);\n return readFile(fullPath);\n }\n\n async writeFile(path: string, content: string): Promise<void> {\n const fullPath = join(this.rootPath, path);\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, content, \"utf-8\");\n }\n\n async writeBinary(path: string, data: Buffer): Promise<void> {\n const fullPath = join(this.rootPath, path);\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFile(fullPath, data);\n }\n\n async deleteFile(path: string): Promise<void> {\n const fullPath = join(this.rootPath, path);\n await unlink(fullPath);\n }\n\n async moveFile(from: string, to: string): Promise<void> {\n const fromPath = join(this.rootPath, from);\n const toPath = join(this.rootPath, to);\n await mkdir(dirname(toPath), { recursive: true });\n await rename(fromPath, toPath);\n }\n\n async exists(path: string): Promise<boolean> {\n try {\n await stat(join(this.rootPath, path));\n return true;\n } catch {\n return false;\n }\n }\n\n async ensureFolder(path: string): Promise<void> {\n await mkdir(join(this.rootPath, path), { recursive: true });\n }\n\n async listMarkdownFiles(): Promise<FileInfo[]> {\n const files: FileInfo[] = [];\n await this.walkDir(this.rootPath, files);\n return files;\n }\n\n async listMarkdownFileStats(): Promise<FileStatInfo[]> {\n const stats: FileStatInfo[] = [];\n await this.walkDirStats(this.rootPath, stats);\n return stats;\n }\n\n async getFileStat(path: string): Promise<FileStatInfo | null> {\n try {\n const fullPath = join(this.rootPath, path);\n const fileStat = await stat(fullPath);\n return { path, mtime: fileStat.mtime.toISOString(), size: fileStat.size };\n } catch {\n return null;\n }\n }\n\n async listNonMarkdownFiles(): Promise<NonMdFileInfo[]> {\n const files: NonMdFileInfo[] = [];\n await this.walkDirNonMd(this.rootPath, files);\n return files;\n }\n\n private matchesPattern(relativePath: string, pattern: string): boolean {\n if (pattern === \"**/*\" || pattern === \"**\") return true;\n\n if (pattern.endsWith(\"/**\")) {\n const dir = pattern.slice(0, -3);\n return relativePath.startsWith(dir + \"/\") || relativePath === dir;\n } else if (pattern.startsWith(\"*.\")) {\n const ext = pattern.slice(1);\n return relativePath.endsWith(ext);\n } else if (pattern.includes(\"*\")) {\n const regexStr = pattern\n .replace(/\\./g, \"\\\\.\")\n .replace(/\\*\\*/g, \"{{GLOBSTAR}}\")\n .replace(/\\*/g, \"[^/]*\")\n .replace(/\\{\\{GLOBSTAR\\}\\}/g, \".*\");\n return new RegExp(\"^\" + regexStr + \"$\").test(relativePath);\n } else {\n return relativePath === pattern || relativePath.startsWith(pattern + \"/\");\n }\n }\n\n private isExcluded(relativePath: string): boolean {\n if (this.includePatterns.length > 0) {\n const included = this.includePatterns.some((p) => this.matchesPattern(relativePath, p));\n if (!included) return true;\n }\n\n return this.excludePatterns.some((p) => this.matchesPattern(relativePath, p));\n }\n\n private async walkDirNonMd(dir: string, result: NonMdFileInfo[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.name.startsWith(\".\")) continue;\n\n const relativePath = relative(this.rootPath, fullPath);\n\n if (this.isExcluded(relativePath)) continue;\n\n if (entry.isDirectory()) {\n await this.walkDirNonMd(fullPath, result);\n } else if (entry.isFile() && !entry.name.endsWith(\".md\") && !entry.name.endsWith(\".base\")) {\n const fileStat = await stat(fullPath);\n result.push({\n path: relativePath,\n size: fileStat.size,\n mtime: fileStat.mtime.toISOString(),\n });\n }\n }\n }\n\n private async walkDirStats(dir: string, result: FileStatInfo[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.name.startsWith(\".\")) continue;\n\n const relativePath = relative(this.rootPath, fullPath);\n\n if (this.isExcluded(relativePath)) continue;\n\n if (entry.isDirectory()) {\n await this.walkDirStats(fullPath, result);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const fileStat = await stat(fullPath);\n result.push({\n path: relativePath,\n mtime: fileStat.mtime.toISOString(),\n size: fileStat.size,\n });\n }\n }\n }\n\n private async walkDir(dir: string, result: FileInfo[]): Promise<void> {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name);\n\n if (entry.name.startsWith(\".\")) continue;\n\n const relativePath = relative(this.rootPath, fullPath);\n\n if (this.isExcluded(relativePath)) continue;\n\n if (entry.isDirectory()) {\n await this.walkDir(fullPath, result);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const content = await readFile(fullPath, \"utf-8\");\n const fileStat = await stat(fullPath);\n\n result.push({\n path: relativePath,\n content,\n mtime: fileStat.mtime.toISOString(),\n });\n }\n }\n }\n}\n","import type { Processor, ProcessorInput, ProcessorOutput } from \"../../types/convert.js\";\nimport { MARKER_BRAND_RE } from \"../../constants/markers.js\";\n\nconst INLINE_DB_START = new RegExp(`%% ${MARKER_BRAND_RE}:inline-db:([^\\\\s]+) %%`, \"g\");\nconst INLINE_DB_END = new RegExp(`%% ${MARKER_BRAND_RE}:end %%`, \"g\");\n\nexport class InlineDBParser implements Processor {\n readonly name = \"InlineDBParser\";\n readonly order = 40;\n\n process(input: ProcessorInput): ProcessorOutput {\n const inlineDbBlocks: InlineDBBlock[] = [];\n const content = input.content;\n\n const startMatches = [...content.matchAll(INLINE_DB_START)];\n for (const match of startMatches) {\n const startIdx = match.index!;\n const params = parseParams(match[1]!);\n\n const afterStart = content.indexOf(\"\\n\", startIdx) + 1;\n const endMatch = INLINE_DB_END.exec(content.slice(afterStart));\n\n if (endMatch) {\n const tableContent = content.slice(afterStart, afterStart + endMatch.index!);\n inlineDbBlocks.push({\n id: params[\"id\"] ?? \"\",\n title: params[\"title\"] ?? \"\",\n tableMarkdown: tableContent.trim(),\n startIdx,\n endIdx: afterStart + endMatch.index! + endMatch[0].length,\n });\n }\n\n INLINE_DB_END.lastIndex = 0;\n }\n\n return {\n content,\n metadata: {\n ...input.metadata,\n inlineDbBlocks,\n },\n };\n }\n}\n\ninterface InlineDBBlock {\n readonly id: string;\n readonly title: string;\n readonly tableMarkdown: string;\n readonly startIdx: number;\n readonly endIdx: number;\n}\n\nfunction parseParams(paramString: string): Record<string, string> {\n const params: Record<string, string> = {};\n for (const pair of paramString.split(\"&\")) {\n const [key, value] = pair.split(\"=\");\n if (key && value) {\n params[key] = decodeURIComponent(value);\n }\n }\n return params;\n}\n","import { sanitizeFileName } from \"../utils/sanitize.js\";\n\nexport interface NotionPageNode {\n readonly id: string;\n readonly title: string;\n readonly hasContent: boolean;\n readonly hasChildren: boolean;\n readonly isDatabase: boolean;\n readonly parentId: string | null;\n readonly children: NotionPageNode[];\n}\n\nexport type MappingType = \"file\" | \"folder-note\" | \"folder-only\" | \"database-folder\";\n\nexport interface MappingResult {\n readonly type: MappingType;\n readonly obsidianPath: string;\n readonly folderPath?: string;\n readonly notePath?: string;\n readonly schemaPath?: string;\n}\n\nexport class TreeMapper {\n mapNotionToObsidian(root: NotionPageNode, basePath: string = \"\"): MappingResult[] {\n const results: MappingResult[] = [];\n this.mapRecursive(root, basePath, results);\n return results;\n }\n\n private mapRecursive(node: NotionPageNode, parentPath: string, results: MappingResult[]): void {\n const safeName = sanitizeFileName(node.title || \"_untitled\");\n const currentPath = parentPath ? `${parentPath}/${safeName}` : safeName;\n\n if (node.isDatabase) {\n results.push({\n type: \"database-folder\",\n obsidianPath: `${currentPath}/`,\n folderPath: `${currentPath}/`,\n schemaPath: `${currentPath}/_schema.yml`,\n });\n } else if (node.hasContent && node.hasChildren) {\n results.push({\n type: \"folder-note\",\n obsidianPath: `${currentPath}/${safeName}.md`,\n folderPath: `${currentPath}/`,\n notePath: `${currentPath}/${safeName}.md`,\n });\n } else if (!node.hasContent && node.hasChildren) {\n results.push({\n type: \"folder-only\",\n obsidianPath: `${currentPath}/`,\n folderPath: `${currentPath}/`,\n });\n } else {\n results.push({\n type: \"file\",\n obsidianPath: `${currentPath}.md`,\n });\n }\n\n for (const child of node.children) {\n this.mapRecursive(child, currentPath, results);\n }\n }\n\n mapObsidianToNotion(entries: FileSystemEntry[], parentPageId: string): PageCreationPlan[] {\n const plans: PageCreationPlan[] = [];\n this.planRecursive(entries, parentPageId, plans);\n return plans;\n }\n\n private planRecursive(\n entries: FileSystemEntry[],\n parentPageId: string,\n plans: PageCreationPlan[],\n ): void {\n for (const entry of entries) {\n if (entry.isDirectory) {\n const folderNote = this.findFolderNote(entry);\n\n if (folderNote) {\n plans.push({\n type: \"page-with-children\",\n title: entry.name,\n parentPageId,\n contentSource: folderNote.path,\n hasContent: true,\n });\n\n const childEntries = entry.children.filter((c) => c.path !== folderNote.path);\n this.planRecursive(childEntries, `placeholder:${entry.path}`, plans);\n } else {\n plans.push({\n type: \"empty-page-with-children\",\n title: entry.name,\n parentPageId,\n hasContent: false,\n });\n this.planRecursive(entry.children, `placeholder:${entry.path}`, plans);\n }\n } else if (entry.name.endsWith(\".md\") && !entry.name.startsWith(\"_\")) {\n plans.push({\n type: \"leaf-page\",\n title: entry.name.replace(/\\.md$/, \"\"),\n parentPageId,\n contentSource: entry.path,\n hasContent: true,\n });\n }\n }\n }\n\n private findFolderNote(dir: FileSystemEntry): FileSystemEntry | null {\n return dir.children.find((c) => c.name === `${dir.name}.md` || c.name === \"index.md\") ?? null;\n }\n\n determineFileType(page: {\n hasContent: boolean;\n hasChildren: boolean;\n isDatabase: boolean;\n }): MappingType {\n if (page.isDatabase) return \"database-folder\";\n if (page.hasContent && page.hasChildren) return \"folder-note\";\n if (!page.hasContent && page.hasChildren) return \"folder-only\";\n return \"file\";\n }\n}\n\nexport interface FileSystemEntry {\n readonly name: string;\n readonly path: string;\n readonly isDirectory: boolean;\n readonly children: FileSystemEntry[];\n}\n\nexport interface PageCreationPlan {\n readonly type: \"page-with-children\" | \"empty-page-with-children\" | \"leaf-page\";\n readonly title: string;\n readonly parentPageId: string;\n readonly contentSource?: string;\n readonly hasContent: boolean;\n}\n","import { watch } from \"chokidar\";\nimport type { FSWatcher } from \"chokidar\";\nimport { sep } from \"node:path\";\nimport { INTERNAL_DIR_GLOB } from \"../constants/paths.js\";\n\nexport type WatchEvent = \"add\" | \"change\" | \"unlink\";\n\nexport interface WatchCallback {\n (event: WatchEvent, path: string): void;\n}\n\nexport class FileWatcher {\n private watcher: FSWatcher | null = null;\n\n constructor(\n private readonly rootPath: string,\n private readonly callback: WatchCallback,\n ) {}\n\n start(): void {\n this.watcher = watch(this.rootPath, {\n // 이벤트 경로를 rootPath 기준 \"볼트 상대경로\"로 방출한다. 동기화 엔진의 변경\n // 감지·paths 필터는 모두 볼트 상대경로(listMarkdownFileStats 기준)를 쓰므로,\n // 절대경로를 그대로 넘기면 push 의 startsWith 스코프 필터에서 누락돼 변경 파일이\n // 실제로 동기화되지 않는다(증분 watch 의 핵심 버그).\n cwd: this.rootPath,\n ignored: [/(^|[/\\\\])\\./, \"**/node_modules/**\", INTERNAL_DIR_GLOB],\n persistent: true,\n ignoreInitial: true,\n awaitWriteFinish: {\n stabilityThreshold: 500,\n pollInterval: 100,\n },\n });\n\n this.watcher.on(\"add\", (path) => this.callback(\"add\", this.toVaultPath(path)));\n this.watcher.on(\"change\", (path) => this.callback(\"change\", this.toVaultPath(path)));\n this.watcher.on(\"unlink\", (path) => this.callback(\"unlink\", this.toVaultPath(path)));\n }\n\n // 볼트 경로는 항상 \"/\" 구분자를 사용한다. Windows 백슬래시를 정규화.\n private toVaultPath(path: string): string {\n return sep === \"/\" ? path : path.split(sep).join(\"/\");\n }\n\n async stop(): Promise<void> {\n if (this.watcher) {\n await this.watcher.close();\n this.watcher = null;\n }\n }\n}\n","import type { SyncOrchestrator } from \"../sync/orchestrator.js\";\nimport type { SyncResult } from \"../types/sync.js\";\nimport { FileWatcher } from \"./file-watcher.js\";\nimport type { WatchEvent } from \"./file-watcher.js\";\n\nexport interface WatchSyncOptions {\n readonly debounceMs?: number;\n readonly onSyncStart?: () => void;\n readonly onSyncComplete?: (result: SyncResult) => void;\n readonly onSyncError?: (error: Error) => void;\n readonly onFileChange?: (event: WatchEvent, path: string) => void;\n}\n\nconst DEFAULT_DEBOUNCE_MS = 2000;\n\nexport class WatchSyncService {\n private readonly debounceMs: number;\n private readonly options: WatchSyncOptions;\n private watcher: FileWatcher | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private pendingChanges: Map<string, WatchEvent> = new Map();\n private syncing = false;\n private syncQueued = false;\n private running = false;\n\n constructor(\n private readonly rootPath: string,\n private readonly orchestrator: SyncOrchestrator,\n options: WatchSyncOptions = {},\n ) {\n this.debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n this.options = options;\n }\n\n start(): void {\n if (this.running) return;\n\n this.running = true;\n this.watcher = new FileWatcher(this.rootPath, (event, path) => {\n this.handleFileChange(event, path);\n });\n this.watcher.start();\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n this.running = false;\n this.clearDebounce();\n this.pendingChanges.clear();\n\n if (this.watcher) {\n await this.watcher.stop();\n this.watcher = null;\n }\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n isSyncing(): boolean {\n return this.syncing;\n }\n\n getPendingCount(): number {\n return this.pendingChanges.size;\n }\n\n private handleFileChange(event: WatchEvent, path: string): void {\n if (!path.endsWith(\".md\")) return;\n\n this.pendingChanges.set(path, event);\n this.options.onFileChange?.(event, path);\n this.scheduleSync();\n }\n\n private scheduleSync(): void {\n this.clearDebounce();\n\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n void this.executeSync();\n }, this.debounceMs);\n }\n\n private clearDebounce(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n\n private async executeSync(): Promise<void> {\n if (this.syncing) {\n this.syncQueued = true;\n return;\n }\n\n // 동기화를 시작하므로 대기 중인 debounce 타이머를 정리한다. 이 타이머가\n // pendingChanges 가 비워진 뒤 뒤늦게 발화하면 아래 가드에 걸려 무시되지만,\n // 미리 취소해 불필요한 재진입 자체를 없앤다.\n this.clearDebounce();\n\n // 누적된 변경이 없으면 아무것도 하지 않는다. 실제 파일 변경 기반 동기화는 항상\n // 경로를 동반하므로, 빈 상태로 진입했다는 것은 stale 타이머·중복 트리거라는 뜻이다.\n // 이때 sync() 를 경로 없이 호출하면 의도치 않은 전체 볼트 동기화가 된다.\n if (this.pendingChanges.size === 0) return;\n\n this.syncing = true;\n // 처리 대상을 스냅샷으로 떠 두고 큐를 비운다. 실패 시 되돌릴 수 있도록 이벤트까지 보존.\n const batch = new Map(this.pendingChanges);\n this.pendingChanges.clear();\n\n try {\n this.options.onSyncStart?.();\n\n const result = await this.orchestrator.sync({ paths: [...batch.keys()] });\n\n this.options.onSyncComplete?.(result);\n } catch (error) {\n // 동기화 실패 시 처리하던 경로를 큐로 되돌려 다음 트리거에서 재시도한다. 단,\n // 동기화 도중 같은 경로에 더 최신 이벤트가 들어왔다면 그것을 덮어쓰지 않는다.\n for (const [path, event] of batch) {\n if (!this.pendingChanges.has(path)) this.pendingChanges.set(path, event);\n }\n const err = error instanceof Error ? error : new Error(String(error));\n this.options.onSyncError?.(err);\n } finally {\n this.syncing = false;\n\n if (this.syncQueued) {\n this.syncQueued = false;\n void this.executeSync();\n } else if (this.pendingChanges.size > 0) {\n // 동기화 중 새로 들어왔거나 실패로 되돌린 경로가 있으면 재동기화를 예약한다.\n this.scheduleSync();\n }\n }\n }\n}\n","import type { ViewConfig } from \"../types/view.js\";\nimport type { DBEntry, PropertyValue, GroupedEntries, CalendarEntry } from \"./types.js\";\n\nexport function sortEntries(\n entries: DBEntry[],\n sorts: NonNullable<ViewConfig[\"sorts\"]>,\n): DBEntry[] {\n if (sorts.length === 0) return entries;\n\n return [...entries].sort((a, b) => {\n for (const sort of sorts) {\n const key = sort.property ?? sort.timestamp;\n if (!key) continue;\n\n const aVal = a.properties[key] ?? null;\n const bVal = b.properties[key] ?? null;\n const cmp = compareValues(aVal, bVal);\n if (cmp !== 0) return sort.direction === \"ascending\" ? cmp : -cmp;\n }\n return 0;\n });\n}\n\nexport function groupEntries(\n entries: DBEntry[],\n groupByProperty: string,\n options?: { sort?: \"ascending\" | \"descending\"; hideEmptyGroups?: boolean },\n): GroupedEntries[] {\n const groups = new Map<string, DBEntry[]>();\n const ungrouped: DBEntry[] = [];\n\n for (const entry of entries) {\n const val = entry.properties[groupByProperty] ?? null;\n const groupName = extractGroupName(val);\n\n if (groupName === null) {\n ungrouped.push(entry);\n } else {\n const existing = groups.get(groupName);\n if (existing) {\n existing.push(entry);\n } else {\n groups.set(groupName, [entry]);\n }\n }\n }\n\n let result: GroupedEntries[] = Array.from(groups.entries()).map(([name, items]) => ({\n groupName: name,\n entries: items,\n }));\n\n if (options?.sort === \"ascending\") {\n result.sort((a, b) => a.groupName.localeCompare(b.groupName));\n } else if (options?.sort === \"descending\") {\n result.sort((a, b) => b.groupName.localeCompare(a.groupName));\n }\n\n if (ungrouped.length > 0) {\n result.push({ groupName: \"그룹 없음\", entries: ungrouped });\n }\n\n if (options?.hideEmptyGroups) {\n result = result.filter((g) => g.entries.length > 0);\n }\n\n return result;\n}\n\nexport function extractCalendarEntries(entries: DBEntry[], dateProperty: string): CalendarEntry[] {\n const result: CalendarEntry[] = [];\n\n for (const entry of entries) {\n const val = entry.properties[dateProperty];\n if (!val) continue;\n\n if (typeof val === \"string\") {\n const date = parseDate(val);\n if (date) result.push({ entry, date });\n } else if (typeof val === \"object\" && val !== null && !Array.isArray(val) && \"start\" in val) {\n const date = parseDate(val.start);\n if (date) {\n result.push({\n entry,\n date,\n endDate: val.end ? (parseDate(val.end) ?? undefined) : undefined,\n });\n }\n }\n }\n\n return result;\n}\n\nexport function filterByMonth(\n calendarEntries: CalendarEntry[],\n year: number,\n month: number,\n): CalendarEntry[] {\n const monthStr = `${year}-${String(month).padStart(2, \"0\")}`;\n return calendarEntries.filter((ce) => ce.date.startsWith(monthStr));\n}\n\nexport function getVisibleProperties(\n viewConfig: ViewConfig,\n): Array<{ id: string; name: string; width?: number }> {\n if (!viewConfig.properties) return [];\n\n return viewConfig.properties\n .filter((p) => p.visible !== false)\n .map((p) => ({\n id: p.propertyId,\n name: p.propertyName ?? p.propertyId,\n width: p.width,\n }));\n}\n\nfunction compareValues(a: PropertyValue, b: PropertyValue): number {\n if (a === null && b === null) return 0;\n if (a === null) return 1;\n if (b === null) return -1;\n\n if (typeof a === \"string\" && typeof b === \"string\") return a.localeCompare(b);\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n if (typeof a === \"boolean\" && typeof b === \"boolean\") return (a ? 1 : 0) - (b ? 1 : 0);\n\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.join(\",\").localeCompare(b.join(\",\"));\n }\n\n if (typeof a === \"object\" && typeof b === \"object\" && a !== null && b !== null) {\n if (\"start\" in a && \"start\" in b) {\n return (a.start ?? \"\").localeCompare(b.start ?? \"\");\n }\n }\n\n return String(a).localeCompare(String(b));\n}\n\nfunction extractGroupName(val: PropertyValue): string | null {\n if (val === null || val === undefined) return null;\n if (typeof val === \"string\") return val || null;\n if (typeof val === \"boolean\") return val ? \"true\" : \"false\";\n if (typeof val === \"number\") return String(val);\n if (Array.isArray(val)) return val.length > 0 ? val.join(\", \") : null;\n if (typeof val === \"object\" && \"start\" in val) return val.start;\n return null;\n}\n\nexport interface FilterCondition {\n property: string;\n operator:\n | \"equals\"\n | \"contains\"\n | \"startsWith\"\n | \"isEmpty\"\n | \"isNotEmpty\"\n | \"gt\"\n | \"lt\"\n | \"between\";\n value?: string | number | boolean;\n valueTo?: string | number;\n}\n\nexport function filterEntries(\n entries: DBEntry[],\n searchQuery?: string,\n filters?: FilterCondition[],\n): DBEntry[] {\n let result = entries;\n\n if (searchQuery && searchQuery.trim()) {\n const q = searchQuery.trim().toLowerCase();\n result = result.filter((entry) => {\n if (entry.title.toLowerCase().includes(q)) return true;\n return Object.values(entry.properties).some((val) => {\n if (val === null || val === undefined) return false;\n if (typeof val === \"string\") return val.toLowerCase().includes(q);\n if (Array.isArray(val)) return val.some((v) => v.toLowerCase().includes(q));\n if (typeof val === \"object\" && \"start\" in val) return val.start.includes(q);\n return String(val).toLowerCase().includes(q);\n });\n });\n }\n\n if (filters && filters.length > 0) {\n for (const filter of filters) {\n result = result.filter((entry) => matchFilter(entry, filter));\n }\n }\n\n return result;\n}\n\nfunction matchFilter(entry: DBEntry, filter: FilterCondition): boolean {\n const val =\n filter.property === \"title\" ? entry.title : (entry.properties[filter.property] ?? null);\n\n switch (filter.operator) {\n case \"isEmpty\":\n return (\n val === null || val === undefined || val === \"\" || (Array.isArray(val) && val.length === 0)\n );\n case \"isNotEmpty\":\n return (\n val !== null && val !== undefined && val !== \"\" && !(Array.isArray(val) && val.length === 0)\n );\n case \"equals\":\n if (typeof val === \"boolean\") return val === filter.value;\n return String(val ?? \"\") === String(filter.value ?? \"\");\n case \"contains\": {\n const needle = String(filter.value ?? \"\").toLowerCase();\n if (typeof val === \"string\") return val.toLowerCase().includes(needle);\n if (Array.isArray(val)) return val.some((v) => v.toLowerCase().includes(needle));\n return String(val ?? \"\")\n .toLowerCase()\n .includes(needle);\n }\n case \"startsWith\":\n return String(val ?? \"\").startsWith(String(filter.value ?? \"\"));\n case \"gt\":\n return typeof val === \"number\" && typeof filter.value === \"number\" && val > filter.value;\n case \"lt\":\n return typeof val === \"number\" && typeof filter.value === \"number\" && val < filter.value;\n case \"between\": {\n if (\n typeof val !== \"number\" ||\n typeof filter.value !== \"number\" ||\n typeof filter.valueTo !== \"number\"\n )\n return false;\n return val >= filter.value && val <= filter.valueTo;\n }\n default:\n return true;\n }\n}\n\nfunction parseDate(value: string): string | null {\n const match = /^(\\d{4}-\\d{2}-\\d{2})/.exec(value);\n return match?.[1] ?? null;\n}\n","import type { VaultFS } from \"../sync/vault-fs.js\";\nimport type { DatabaseViewsConfig, ViewConfig } from \"../types/view.js\";\nimport type { DBEntry, PropertyValue, ViewRenderData, PropertySchema } from \"./types.js\";\nimport { sortEntries, groupEntries, extractCalendarEntries } from \"./filter-engine.js\";\nimport { getVisibleProperties } from \"./filter-engine.js\";\nimport matter from \"gray-matter\";\nimport { DB_VIEWS_PATH } from \"../constants/paths.js\";\nimport { selectDbRowFiles } from \"../utils/db-row-path.js\";\n\nexport class ViewDataProvider {\n constructor(private readonly vaultFs: VaultFS) {}\n\n async loadAllViewConfigs(): Promise<Record<string, DatabaseViewsConfig>> {\n try {\n const raw = await this.vaultFs.readFile(DB_VIEWS_PATH);\n return JSON.parse(raw) as Record<string, DatabaseViewsConfig>;\n } catch {\n return {};\n }\n }\n\n async getViewConfigs(databaseId: string): Promise<DatabaseViewsConfig | null> {\n const all = await this.loadAllViewConfigs();\n return all[databaseId] ?? null;\n }\n\n async collectEntries(folderPath: string): Promise<DBEntry[]> {\n const allFiles = await this.vaultFs.listMarkdownFiles();\n // 직속 행 파일만 — 중첩 하위 폴더(별도 child_database·자식 페이지 본문)는 부모 DB 의\n // 행이 아니므로 카드로 새어 들지 않게 제외한다(I9 오포함 차단).\n const dbFiles = selectDbRowFiles(allFiles, folderPath);\n\n const entries: DBEntry[] = [];\n\n for (const file of dbFiles) {\n try {\n const content = await this.vaultFs.readFile(file.path);\n const entry = parseEntry(file.path, content);\n if (entry) entries.push(entry);\n } catch {\n // 파일 읽기 실패 시 스킵\n }\n }\n\n return entries;\n }\n\n async buildViewData(\n databaseId: string,\n viewId: string,\n folderPath: string,\n schema?: Record<string, PropertySchema>,\n ): Promise<ViewRenderData | null> {\n const dbConfig = await this.getViewConfigs(databaseId);\n if (!dbConfig) return null;\n\n const viewConfig = dbConfig.views.find((v) => v.id === viewId);\n if (!viewConfig) return null;\n\n const entries = await this.collectEntries(folderPath);\n\n return this.processViewData(entries, viewConfig, databaseId, dbConfig.databaseName, schema);\n }\n\n async buildDefaultViewData(\n databaseId: string,\n folderPath: string,\n schema?: Record<string, PropertySchema>,\n ): Promise<ViewRenderData | null> {\n const dbConfig = await this.getViewConfigs(databaseId);\n if (!dbConfig || dbConfig.views.length === 0) return null;\n\n const viewConfig = dbConfig.views[0]!;\n const entries = await this.collectEntries(folderPath);\n\n return this.processViewData(entries, viewConfig, databaseId, dbConfig.databaseName, schema);\n }\n\n processViewData(\n entries: DBEntry[],\n viewConfig: ViewConfig,\n databaseId: string,\n databaseName?: string,\n schema?: Record<string, PropertySchema>,\n ): ViewRenderData {\n let processed = entries;\n\n if (viewConfig.sorts && viewConfig.sorts.length > 0) {\n processed = sortEntries(processed, viewConfig.sorts);\n }\n\n const visibleProps = getVisibleProperties(viewConfig);\n const propertyNames =\n visibleProps.length > 0 ? visibleProps.map((p) => p.name) : collectPropertyNames(processed);\n\n const data: ViewRenderData = {\n databaseId,\n databaseName,\n viewConfig,\n entries: processed,\n propertyNames,\n schema,\n };\n\n if (viewConfig.type === \"board\" && viewConfig.groupBy) {\n const grouped = groupEntries(\n processed,\n viewConfig.groupBy.propertyName ?? viewConfig.groupBy.propertyId,\n {\n sort: viewConfig.groupBy.sort === \"manual\" ? undefined : viewConfig.groupBy.sort,\n hideEmptyGroups: viewConfig.groupBy.hideEmptyGroups,\n },\n );\n return { ...data, grouped };\n }\n\n if (viewConfig.type === \"calendar\" && viewConfig.datePropertyName) {\n const calendarEntries = extractCalendarEntries(processed, viewConfig.datePropertyName);\n return { ...data, calendarEntries };\n }\n\n return data;\n }\n}\n\nfunction parseEntry(path: string, content: string): DBEntry | null {\n try {\n const parsed = matter(content);\n const fm = parsed.data as Record<string, unknown>;\n\n const title = coerceString(fm.title) ?? extractTitleFromPath(path);\n const icon = coerceString(fm.icon);\n const cover = coerceCover(fm.cover);\n\n const properties: Record<string, PropertyValue> = {};\n for (const [key, value] of Object.entries(fm)) {\n if (key === \"title\" || key === \"icon\" || key === \"cover\") continue;\n properties[key] = normalizePropertyValue(value);\n }\n\n return { path, title, icon, cover, properties };\n } catch {\n return null;\n }\n}\n\n/**\n * 갤러리 커버 값을 **렌더 가능한 단일 URL 스칼라**로 강제 변환한다(없으면 undefined).\n *\n * Notion `files` 속성을 갤러리 커버로 쓰면 행마다 파일 수가 달라, property-mapper 는 단일\n * 파일은 스칼라 문자열로·복수 파일은 **URL 배열**로 직렬화한다(데이터 보존). 그러나 카드\n * 커버 `<img src>` 는 스칼라만 받으므로, 배열이 그대로 흘러들면 `src=\"url1,url2\"` 로\n * 합쳐져 **깨진 이미지**가 된다. Notion 도 다중 파일 커버는 **첫 파일**을 쓰므로 동일하게\n * 첫 렌더 가능한 URL 로 degrade 한다. 파일 객체(`{url}`/`{external:{url}}`)도 방어적으로 처리.\n *\n * `DBEntry.cover: string` 타입을 런타임에서 보증한다(과거: `as string` 캐스팅이 배열을\n * 문자열로 단언해 타입이 거짓이었다).\n */\nfunction coerceCover(raw: unknown): string | undefined {\n const firstUrl = (v: unknown): string | undefined => {\n if (typeof v === \"string\") return v.trim() || undefined;\n if (v && typeof v === \"object\") {\n const o = v as { url?: unknown; external?: { url?: unknown } };\n const url = o.url ?? o.external?.url;\n if (typeof url === \"string\") return url.trim() || undefined;\n }\n return undefined;\n };\n\n if (Array.isArray(raw)) {\n for (const item of raw) {\n const url = firstUrl(item);\n if (url) return url; // 다중값 → 첫 렌더 가능한 URL 로 degrade\n }\n return undefined;\n }\n return firstUrl(raw);\n}\n\n/**\n * `DBEntry` 의 스칼라 문자열 필드(`title`/`icon`)를 **렌더·검색 안전한 단일 문자열**로\n * 강제 변환한다(없으면 undefined → 호출처에서 파일명 등으로 폴백).\n *\n * 프론트매터는 다형값을 흘려보낼 수 있다:\n * - `title: 2026` → js-yaml 이 **number** 로 파싱(따옴표 없는 숫자 제목은 흔함).\n * - `title: [a, b]` / 수동 오편집 → **배열**.\n * 과거 `fm.title as string` 캐스팅은 이를 string 으로 **거짓 단언**했고, 뒤따르는\n * `filter-engine` 의 `entry.title.toLowerCase()` 가 `X.toLowerCase is not a function` 으로\n * **뷰 검색 전체를 크래시**시켰다(I9 위반 — rank22 의 커버 배열 깨짐과 동일 계열).\n * number/boolean 은 문자열화, 배열은 첫 비공백 문자열로 degrade 하여 타입을 런타임 보증한다.\n */\nfunction coerceString(raw: unknown): string | undefined {\n if (typeof raw === \"string\") return raw.trim() || undefined;\n if (typeof raw === \"number\" || typeof raw === \"boolean\") return String(raw);\n if (Array.isArray(raw)) {\n for (const item of raw) {\n const s = coerceString(item);\n if (s) return s; // 다중값 → 첫 렌더 가능한 문자열로 degrade\n }\n }\n return undefined;\n}\n\nfunction normalizePropertyValue(value: unknown): PropertyValue {\n if (value === null || value === undefined) return null;\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\") return value;\n if (typeof value === \"boolean\") return value;\n\n if (value instanceof Date) {\n return value.toISOString().split(\"T\")[0]!;\n }\n\n if (Array.isArray(value)) {\n return value.map((v) => String(v));\n }\n\n if (typeof value === \"object\" && value !== null) {\n const obj = value as Record<string, unknown>;\n if (\"start\" in obj) {\n return {\n start: String(obj.start),\n end: obj.end ? String(obj.end) : undefined,\n };\n }\n }\n\n return String(value);\n}\n\nfunction extractTitleFromPath(filePath: string): string {\n const parts = filePath.split(\"/\");\n const filename = parts[parts.length - 1] ?? \"\";\n return filename.replace(/\\.md$/, \"\");\n}\n\nfunction collectPropertyNames(entries: DBEntry[]): string[] {\n const names = new Set<string>();\n for (const entry of entries) {\n for (const key of Object.keys(entry.properties)) {\n names.add(key);\n }\n }\n return Array.from(names);\n}\n","import type { VaultFS } from \"../sync/vault-fs.js\";\nimport type { DBEntry, PropertyValue } from \"./types.js\";\nimport matter from \"gray-matter\";\nimport { stringifyFrontmatter } from \"../utils/frontmatter.js\";\n\nexport class EntryEditor {\n constructor(private readonly vaultFs: VaultFS) {}\n\n async updateProperty(\n entryPath: string,\n propertyName: string,\n newValue: PropertyValue,\n ): Promise<void> {\n const content = await this.vaultFs.readFile(entryPath);\n const parsed = matter(content);\n\n parsed.data[propertyName] = newValue;\n\n const updated = stringifyFrontmatter(parsed.content, parsed.data);\n await this.vaultFs.writeFile(entryPath, updated);\n }\n\n async createEntry(\n folderPath: string,\n title: string,\n properties: Record<string, PropertyValue>,\n ): Promise<string> {\n const safeName = title.replace(/[\\\\/:*?\"<>|]/g, \"_\").trim() || \"Untitled\";\n const filePath = `${folderPath}/${safeName}.md`;\n\n const frontmatter = { title, ...properties };\n const content = stringifyFrontmatter(\"\", frontmatter);\n\n await this.vaultFs.ensureFolder(folderPath);\n await this.vaultFs.writeFile(filePath, content);\n\n return filePath;\n }\n\n async moveEntryToGroup(\n entry: DBEntry,\n groupProperty: string,\n newGroupValue: string,\n ): Promise<void> {\n await this.updateProperty(entry.path, groupProperty, newGroupValue);\n }\n\n async updateDate(entryPath: string, dateProperty: string, newDate: string): Promise<void> {\n await this.updateProperty(entryPath, dateProperty, newDate);\n }\n}\n","import type { NotionColor } from \"./types.js\";\n\nconst NOTION_COLORS: Record<NotionColor, string> = {\n default: \"#37352F\",\n gray: \"#787774\",\n brown: \"#9F6B53\",\n orange: \"#D9730D\",\n yellow: \"#CB912F\",\n green: \"#448361\",\n blue: \"#337EA9\",\n purple: \"#9065B0\",\n pink: \"#C14C8A\",\n red: \"#D44C47\",\n};\n\nconst NOTION_BG_COLORS: Record<NotionColor, string> = {\n default: \"#F1F1EF\",\n gray: \"#F1F1EF\",\n brown: \"#F4EEEE\",\n orange: \"#FBECDD\",\n yellow: \"#FBF3DB\",\n green: \"#EDF3EC\",\n blue: \"#E7F3F8\",\n purple: \"#F4F0F7\",\n pink: \"#F9F0F5\",\n red: \"#FDEBEC\",\n};\n\nexport function getNotionColor(color: NotionColor | string): string {\n return NOTION_COLORS[color as NotionColor] ?? NOTION_COLORS.default;\n}\n\nexport function getNotionBgColor(color: NotionColor | string): string {\n return NOTION_BG_COLORS[color as NotionColor] ?? NOTION_BG_COLORS.default;\n}\n\nexport function generateColorCSS(): string {\n const lines: string[] = [];\n for (const [name, hex] of Object.entries(NOTION_COLORS)) {\n lines.push(` --notion-color-${name}: ${hex};`);\n }\n for (const [name, hex] of Object.entries(NOTION_BG_COLORS)) {\n lines.push(` --notion-bg-${name}: ${hex};`);\n }\n return `:root {\\n${lines.join(\"\\n\")}\\n}`;\n}\n","/**\n * 본문 링크 충실도(fidelity) 분류기 — 회귀 상시 잠금용 측정 인프라.\n *\n * pull 결과물(.md 본문)에 남은 notion 링크/멘션을 네 부류로 분류한다:\n *\n * 1. preservedMarkers — `[text](url)%%im-nobsidian:...%%` 형태의 의도된 무손실\n * 보존 마커(copy_indicator 등). push 라운드트립 복원용으로 *일부러* 남긴 것이라\n * 결함이 아니다.\n * 2. externalLinks — 동기화 코퍼스에 없는 외부 notion.so 링크. 위키링크로 환원할\n * 대상이 없으므로 맨 링크로 두는 게 정당하다.\n * 3. selfReferences — 자기 자신 페이지를 가리키는 링크/멘션(블록 앵커 등). 정당.\n * 4. defects — 동기화된 *다른* 페이지로의 미해소 링크/멘션. 이것만이 진짜\n * 충실도 결함이다(M2/M3/M4/M6 가 봉합한 대상).\n *\n * 변환 파이프라인이 완전하면 `defects.length === 0` 이어야 한다. 이 분류기를 픽스처로\n * 잠가(unit test) 두면 변환기 회귀가 즉시 드러나고, 실제 vault 에 대고 돌리면(아래\n * scripts/audit-vault.mjs) 코퍼스 전체의 충실도를 정량 측정할 수 있다.\n *\n * 마커/ID 판별은 SSOT 를 재사용한다 — 마커 브랜드는 {@link MARKER_BRAND},\n * 정규 id 는 {@link compactNotionId}. 별도 헬퍼를 만들지 않는다.\n */\n\nimport { MARKER_BRAND } from \"../constants/markers.js\";\nimport { compactNotionId } from \"../utils/id.js\";\n\n/** 미해소로 남은 링크/멘션의 형태. */\nexport type FidelityDefectForm = \"md-link\" | \"mention-page\";\n\n/** 진짜 충실도 결함 — 동기화된 다른 페이지로의 미해소 링크/멘션. */\nexport interface FidelityDefect {\n /** 미해소 형태(맨 마크다운 링크 / 미변환 mention-page 태그). */\n form: FidelityDefectForm;\n /** 대상 페이지의 정규(compact) id. */\n targetPageId: string;\n /** 대상 페이지 제목(맵에 있으면). */\n targetTitle: string | null;\n /** 결함 원문 조각(진단용). */\n raw: string;\n}\n\n/** {@link classifyBodyFidelity} 분류 결과. */\nexport interface FidelityClassification {\n /** `[text](url)%%im-nobsidian:...%%` — 의도된 무손실 보존 마커(결함 아님). */\n preservedMarkers: number;\n /** 코퍼스에 없는 외부 notion.so 링크(정당). */\n externalLinks: number;\n /** 자기 자신 페이지를 가리키는 링크/멘션(정당). */\n selfReferences: number;\n /** 동기화된 다른 페이지로의 미해소 링크/멘션 — 진짜 결함. */\n defects: FidelityDefect[];\n}\n\n/** 분류에 필요한 코퍼스 컨텍스트. */\nexport interface FidelityContext {\n /** 동기화된 전체 페이지의 정규(compact) id 집합. */\n knownPageIds: ReadonlySet<string>;\n /** 정규 id → 제목. 선택(결함 진단용). */\n titleById?: ReadonlyMap<string, string>;\n /** 이 본문이 속한 페이지의 정규 id. 자기참조 판별용. 선택. */\n ownPageId?: string;\n}\n\n/**\n * notion id 추출 정규식 — 하이픈 포함 UUID 와 32연속 hex 를 모두 인식한다.\n * `-?` 가 모두 선택이므로 단일 패턴이 두 형태를 포괄한다.\n */\nconst NOTION_ID_RE = /[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}/gi;\n\n/** notion.so 마크다운 링크 + 직후 보존 마커 동반 여부. group1=url, group2=마커. */\nconst MD_LINK_RE = new RegExp(\n `\\\\[[^\\\\]]*\\\\]\\\\((https?://[^)\\\\s]*notion\\\\.so/[^)\\\\s]*)\\\\)(\\\\s*%%\\\\s*${MARKER_BRAND}\\\\b)?`,\n \"gi\",\n);\n\n/** mention-page 태그 — self-closing `/>` 와 라벨 동반 `>..</mention-page>` 모두 포괄. */\nconst MENTION_PAGE_RE = /<mention-page\\b[\\s\\S]*?(?:\\/>|>[\\s\\S]*?<\\/mention-page>)/gi;\n\n/** 문자열에서 마지막 notion id 를 정규(compact) 형태로 추출. 없으면 null. */\nfunction lastNotionId(text: string): string | null {\n const matches = text.match(NOTION_ID_RE);\n if (!matches || matches.length === 0) return null;\n return compactNotionId(matches[matches.length - 1]!);\n}\n\n/**\n * 본문 문자열의 notion 링크/멘션 충실도를 분류한다. 순수 함수 — I/O 없음.\n *\n * @param body 분석할 마크다운 본문(프론트매터 포함 가능; 보존 마커·위키링크는 무시됨).\n * @param ctx 코퍼스 컨텍스트(알려진 페이지 id 집합 등).\n */\nexport function classifyBodyFidelity(body: string, ctx: FidelityContext): FidelityClassification {\n const result: FidelityClassification = {\n preservedMarkers: 0,\n externalLinks: 0,\n selfReferences: 0,\n defects: [],\n };\n\n const own = ctx.ownPageId ? compactNotionId(ctx.ownPageId) : null;\n const titleOf = (id: string): string | null => ctx.titleById?.get(id) ?? null;\n\n const classifyId = (id: string | null, form: FidelityDefectForm, raw: string): void => {\n if (id === null) {\n // id 를 못 뽑은 링크/멘션은 외부로 간주(코퍼스 매칭 불가).\n result.externalLinks += 1;\n return;\n }\n if (own !== null && id === own) {\n result.selfReferences += 1;\n return;\n }\n if (ctx.knownPageIds.has(id)) {\n result.defects.push({ form, targetPageId: id, targetTitle: titleOf(id), raw: raw.trim() });\n return;\n }\n result.externalLinks += 1;\n };\n\n // 1) notion.so 마크다운 링크\n for (const m of body.matchAll(MD_LINK_RE)) {\n const url = m[1] ?? \"\";\n const hasMarker = Boolean(m[2]);\n if (hasMarker) {\n result.preservedMarkers += 1;\n continue;\n }\n classifyId(lastNotionId(url), \"md-link\", m[0]);\n }\n\n // 2) mention-page 태그(변환됐어야 할 잔류물)\n for (const m of body.matchAll(MENTION_PAGE_RE)) {\n classifyId(lastNotionId(m[0]), \"mention-page\", m[0]);\n }\n\n return result;\n}\n\n/** 여러 본문의 분류 결과를 합산한 코퍼스 단위 요약. */\nexport interface FidelitySummary {\n files: number;\n preservedMarkers: number;\n externalLinks: number;\n selfReferences: number;\n defects: number;\n /** 결함이 1건 이상인 파일 경로 → 결함 목록. */\n defectsByFile: Record<string, FidelityDefect[]>;\n}\n\n/** 파일별 분류 결과(경로 + 분류)를 코퍼스 요약으로 합산한다. */\nexport function summarizeFidelity(\n perFile: ReadonlyArray<{ path: string; classification: FidelityClassification }>,\n): FidelitySummary {\n const summary: FidelitySummary = {\n files: perFile.length,\n preservedMarkers: 0,\n externalLinks: 0,\n selfReferences: 0,\n defects: 0,\n defectsByFile: {},\n };\n for (const { path, classification } of perFile) {\n summary.preservedMarkers += classification.preservedMarkers;\n summary.externalLinks += classification.externalLinks;\n summary.selfReferences += classification.selfReferences;\n summary.defects += classification.defects.length;\n if (classification.defects.length > 0) {\n summary.defectsByFile[path] = classification.defects;\n }\n }\n return summary;\n}\n"]}