im-nobsidian 0.1.11 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -0
- package/dist/index.js +14 -47
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# im-nobsidian
|
|
2
|
+
|
|
3
|
+
> `nobsi` — the CLI for [Im-Nobsidian](https://github.com/JaylenAI/Im-Nobsidian), the only true bidirectional sync between Obsidian and Notion.
|
|
4
|
+
|
|
5
|
+
<p>
|
|
6
|
+
<a href="https://www.npmjs.com/package/im-nobsidian"><img src="https://img.shields.io/npm/v/im-nobsidian" alt="npm version" /></a>
|
|
7
|
+
<a href="https://github.com/JaylenAI/Im-Nobsidian/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT" /></a>
|
|
8
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-20%2B-green" alt="Node.js" /></a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
Edit in Obsidian, see it in Notion — and back. Run `nobsi sync` and both sides stay in sync: formatting, properties, folder structure, attachments. Conflict resolution and round-trip preservation built in.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g nobsi
|
|
17
|
+
# or run without installing
|
|
18
|
+
npx nobsi --help
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The binary is available as both `nobsi` and `im-nobsidian`.
|
|
22
|
+
|
|
23
|
+
## Quick start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
nobsi init # configure Notion token + root page + vault path
|
|
27
|
+
nobsi pull # Notion → Obsidian
|
|
28
|
+
nobsi push # Obsidian → Notion
|
|
29
|
+
nobsi sync # bidirectional (pull → push)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Commands
|
|
33
|
+
|
|
34
|
+
| Command | Description |
|
|
35
|
+
| --------------- | --------------------------------------------------- |
|
|
36
|
+
| `nobsi init` | First-time setup — Notion token, root page, vault |
|
|
37
|
+
| `nobsi pull` | Pull Notion changes into the local vault |
|
|
38
|
+
| `nobsi push` | Push local changes to Notion |
|
|
39
|
+
| `nobsi sync` | Bidirectional sync (pull → push) |
|
|
40
|
+
| `nobsi status` | Show sync state (`--full` includes remote changes) |
|
|
41
|
+
| `nobsi resolve` | Resolve conflicts |
|
|
42
|
+
| `nobsi watch` | Watch files + auto-sync on change |
|
|
43
|
+
| `nobsi diff` | Show differences between local and Notion |
|
|
44
|
+
| `nobsi fetch` | Scan Notion remote state (incl. deletion detection) |
|
|
45
|
+
|
|
46
|
+
Config and sync state live in `.im-nobsidian/` inside your vault. Your Notion token is stored locally and never committed.
|
|
47
|
+
|
|
48
|
+
## Documentation
|
|
49
|
+
|
|
50
|
+
[Repo](https://github.com/JaylenAI/Im-Nobsidian#readme) · [Changelog](https://github.com/JaylenAI/Im-Nobsidian/blob/main/docs/06-devlog/CHANGELOG.md)
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT © hanseungheon
|
package/dist/index.js
CHANGED
|
@@ -183,11 +183,7 @@ var pushCommand = new Command2("push").description("\uB85C\uCEEC \uBCC0\uACBD\uC
|
|
|
183
183
|
const config = await configManager.load();
|
|
184
184
|
const stateDb = StateDB.open(configManager.dbPath);
|
|
185
185
|
try {
|
|
186
|
-
const client =
|
|
187
|
-
token: config.notion.token,
|
|
188
|
-
concurrency: config.advanced.concurrency,
|
|
189
|
-
timeoutMs: config.advanced.timeoutMs
|
|
190
|
-
});
|
|
186
|
+
const client = NotionClient2.fromConfig(config);
|
|
191
187
|
const vaultFs = new NodeVaultFS(cwd, config.paths);
|
|
192
188
|
const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);
|
|
193
189
|
console.log(`
|
|
@@ -237,11 +233,7 @@ var pullCommand = new Command3("pull").description("Notion \uBCC0\uACBD\uC0AC\uD
|
|
|
237
233
|
const config = await configManager.load();
|
|
238
234
|
const stateDb = StateDB2.open(configManager.dbPath);
|
|
239
235
|
try {
|
|
240
|
-
const client =
|
|
241
|
-
token: config.notion.token,
|
|
242
|
-
concurrency: config.advanced.concurrency,
|
|
243
|
-
timeoutMs: config.advanced.timeoutMs
|
|
244
|
-
});
|
|
236
|
+
const client = NotionClient3.fromConfig(config);
|
|
245
237
|
const vaultFs = new NodeVaultFS2(cwd, config.paths);
|
|
246
238
|
const orchestrator = new SyncOrchestrator2(config, stateDb, client, vaultFs);
|
|
247
239
|
console.log(`
|
|
@@ -309,11 +301,7 @@ var syncCommand = new Command4("sync").description("\uC591\uBC29\uD5A5 \uB3D9\uA
|
|
|
309
301
|
const config = await configManager.load();
|
|
310
302
|
const stateDb = StateDB3.open(configManager.dbPath);
|
|
311
303
|
try {
|
|
312
|
-
const client =
|
|
313
|
-
token: config.notion.token,
|
|
314
|
-
concurrency: config.advanced.concurrency,
|
|
315
|
-
timeoutMs: config.advanced.timeoutMs
|
|
316
|
-
});
|
|
304
|
+
const client = NotionClient4.fromConfig(config);
|
|
317
305
|
const vaultFs = new NodeVaultFS3(cwd, config.paths);
|
|
318
306
|
const orchestrator = new SyncOrchestrator3(config, stateDb, client, vaultFs);
|
|
319
307
|
console.log(`
|
|
@@ -383,10 +371,7 @@ var statusCommand = new Command5("status").description("\uB3D9\uAE30\uD654 \uC0C
|
|
|
383
371
|
const config = await configManager.load();
|
|
384
372
|
const stateDb = StateDB4.open(configManager.dbPath);
|
|
385
373
|
try {
|
|
386
|
-
const client =
|
|
387
|
-
token: config.notion.token,
|
|
388
|
-
concurrency: config.advanced.concurrency
|
|
389
|
-
});
|
|
374
|
+
const client = NotionClient5.fromConfig(config);
|
|
390
375
|
const vaultFs = new NodeVaultFS4(cwd, config.paths);
|
|
391
376
|
const orchestrator = new SyncOrchestrator4(config, stateDb, client, vaultFs);
|
|
392
377
|
const status = opts.full ? await orchestrator.status() : await orchestrator.statusLocal();
|
|
@@ -520,11 +505,7 @@ var diffCommand = new Command6("diff").description("\uB85C\uCEEC\uACFC Notion \u
|
|
|
520
505
|
const config = await configManager.load();
|
|
521
506
|
const stateDb = StateDB5.open(configManager.dbPath);
|
|
522
507
|
try {
|
|
523
|
-
const client =
|
|
524
|
-
token: config.notion.token,
|
|
525
|
-
concurrency: config.advanced.concurrency,
|
|
526
|
-
timeoutMs: config.advanced.timeoutMs
|
|
527
|
-
});
|
|
508
|
+
const client = NotionClient6.fromConfig(config);
|
|
528
509
|
const vaultFs = new NodeVaultFS5(cwd, config.paths);
|
|
529
510
|
const orchestrator = new SyncOrchestrator5(config, stateDb, client, vaultFs);
|
|
530
511
|
const status = await orchestrator.statusLocal();
|
|
@@ -610,11 +591,7 @@ var fetchCommand = new Command7("fetch").description("Notion \uB9AC\uBAA8\uD2B8
|
|
|
610
591
|
const config = await configManager.load();
|
|
611
592
|
const stateDb = StateDB6.open(configManager.dbPath);
|
|
612
593
|
try {
|
|
613
|
-
const client =
|
|
614
|
-
token: config.notion.token,
|
|
615
|
-
concurrency: config.advanced.concurrency,
|
|
616
|
-
timeoutMs: config.advanced.timeoutMs
|
|
617
|
-
});
|
|
594
|
+
const client = NotionClient7.fromConfig(config);
|
|
618
595
|
const vaultFs = new NodeVaultFS6(cwd, config.paths);
|
|
619
596
|
const orchestrator = new SyncOrchestrator6(config, stateDb, client, vaultFs);
|
|
620
597
|
console.log(dimText(" Scanning remote pages..."));
|
|
@@ -655,8 +632,7 @@ import {
|
|
|
655
632
|
StateDB as StateDB7,
|
|
656
633
|
NotionClient as NotionClient8,
|
|
657
634
|
SyncOrchestrator as SyncOrchestrator7,
|
|
658
|
-
NodeVaultFS as NodeVaultFS7
|
|
659
|
-
ConflictResolver
|
|
635
|
+
NodeVaultFS as NodeVaultFS7
|
|
660
636
|
} from "@im-nobsidian/core";
|
|
661
637
|
var resolveCommand = new Command8("resolve").description("\uCDA9\uB3CC\uC744 \uD574\uACB0\uD569\uB2C8\uB2E4").option("-s, --strategy <strategy>", "\uC790\uB3D9 \uD574\uACB0 \uC804\uB7B5 (local-first, remote-first, duplicate)").action(async (options) => {
|
|
662
638
|
const cwd = process.cwd();
|
|
@@ -664,14 +640,9 @@ var resolveCommand = new Command8("resolve").description("\uCDA9\uB3CC\uC744 \uD
|
|
|
664
640
|
try {
|
|
665
641
|
const config = await configManager.load();
|
|
666
642
|
const stateDb = StateDB7.open(configManager.dbPath);
|
|
667
|
-
const client =
|
|
668
|
-
token: config.notion.token,
|
|
669
|
-
concurrency: 3,
|
|
670
|
-
timeoutMs: 3e4
|
|
671
|
-
});
|
|
643
|
+
const client = NotionClient8.fromConfig(config);
|
|
672
644
|
const vaultFs = new NodeVaultFS7(cwd, config.paths);
|
|
673
645
|
const orchestrator = new SyncOrchestrator7(config, stateDb, client, vaultFs);
|
|
674
|
-
const resolver = new ConflictResolver(stateDb, vaultFs);
|
|
675
646
|
await orchestrator.status();
|
|
676
647
|
const conflictRecords = stateDb.getByStatus("conflict");
|
|
677
648
|
if (conflictRecords.length === 0) {
|
|
@@ -692,7 +663,7 @@ var resolveCommand = new Command8("resolve").description("\uCDA9\uB3CC\uC744 \uD
|
|
|
692
663
|
return;
|
|
693
664
|
}
|
|
694
665
|
const pullResult = await orchestrator.pull();
|
|
695
|
-
const results = await
|
|
666
|
+
const results = await orchestrator.resolveAllConflicts(pullResult.conflicts, strategy);
|
|
696
667
|
for (const result of results) {
|
|
697
668
|
const icon = result.success ? "\x1B[32m\u2713\x1B[0m" : "\x1B[31m\u2717\x1B[0m";
|
|
698
669
|
console.log(` ${icon} ${result.path} \u2192 ${result.choice}`);
|
|
@@ -700,7 +671,7 @@ var resolveCommand = new Command8("resolve").description("\uCDA9\uB3CC\uC744 \uD
|
|
|
700
671
|
} else {
|
|
701
672
|
const pullResult = await orchestrator.pull();
|
|
702
673
|
for (const conflict of pullResult.conflicts) {
|
|
703
|
-
await resolveInteractive(conflict,
|
|
674
|
+
await resolveInteractive(conflict, orchestrator);
|
|
704
675
|
}
|
|
705
676
|
}
|
|
706
677
|
stateDb.close();
|
|
@@ -710,13 +681,13 @@ var resolveCommand = new Command8("resolve").description("\uCDA9\uB3CC\uC744 \uD
|
|
|
710
681
|
process.exit(1);
|
|
711
682
|
}
|
|
712
683
|
});
|
|
713
|
-
async function resolveInteractive(conflict,
|
|
684
|
+
async function resolveInteractive(conflict, orchestrator) {
|
|
714
685
|
const path = conflict.syncRecord.obsidianPath;
|
|
715
686
|
console.log(`
|
|
716
687
|
${"\u2500".repeat(60)}`);
|
|
717
688
|
console.log(`\uD30C\uC77C: \x1B[1m${path}\x1B[0m`);
|
|
718
689
|
console.log(`${"\u2500".repeat(60)}`);
|
|
719
|
-
const diff =
|
|
690
|
+
const diff = orchestrator.generateConflictDiff(conflict);
|
|
720
691
|
const diffLines = diff.split("\n");
|
|
721
692
|
for (const line of diffLines) {
|
|
722
693
|
if (line.startsWith("- ")) {
|
|
@@ -738,7 +709,7 @@ ${"\u2500".repeat(60)}`);
|
|
|
738
709
|
{ name: "\uBCF5\uC81C (\uC6D0\uBCF8 \uC720\uC9C0 + .conflict \uD30C\uC77C \uC0DD\uC131)", value: "duplicate" }
|
|
739
710
|
]
|
|
740
711
|
});
|
|
741
|
-
const result = await
|
|
712
|
+
const result = await orchestrator.resolveConflict(conflict, choice);
|
|
742
713
|
if (result.success) {
|
|
743
714
|
console.log(`\x1B[32m\u2713 ${path} \u2192 ${choice}\uB85C \uD574\uACB0\x1B[0m`);
|
|
744
715
|
} else if (result.mergeHadConflicts) {
|
|
@@ -775,11 +746,7 @@ var watchCommand = new Command9("watch").description("\uD30C\uC77C \uBCC0\uACBD
|
|
|
775
746
|
const configManager = new ConfigManager9(cwd);
|
|
776
747
|
const config = await configManager.load();
|
|
777
748
|
const stateDb = StateDB8.open(configManager.dbPath);
|
|
778
|
-
const client =
|
|
779
|
-
token: config.notion.token,
|
|
780
|
-
concurrency: config.advanced.concurrency,
|
|
781
|
-
timeoutMs: config.advanced.timeoutMs
|
|
782
|
-
});
|
|
749
|
+
const client = NotionClient9.fromConfig(config);
|
|
783
750
|
const vaultFs = new NodeVaultFS8(cwd, config.paths);
|
|
784
751
|
const orchestrator = new SyncOrchestrator8(config, stateDb, client, vaultFs);
|
|
785
752
|
const debounceMs = parseInt(options.debounce, 10);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/format.ts","../src/commands/push.ts","../src/commands/pull.ts","../src/commands/sync.ts","../src/commands/status.ts","../src/commands/diff.ts","../src/commands/fetch.ts","../src/commands/resolve.ts","../src/commands/watch.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { pushCommand } from \"./commands/push.js\";\nimport { pullCommand } from \"./commands/pull.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { statusCommand } from \"./commands/status.js\";\nimport { diffCommand } from \"./commands/diff.js\";\nimport { fetchCommand } from \"./commands/fetch.js\";\nimport { resolveCommand } from \"./commands/resolve.js\";\nimport { watchCommand } from \"./commands/watch.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"im-nobsidian\")\n .description(\"Im-Nobsidian: Obsidian ↔ Notion 양방향 동기화 CLI\")\n .version(\"0.1.1\")\n .option(\"--verbose\", \"상세 로그 출력\")\n .option(\"--quiet\", \"최소 출력\");\n\nprogram.addCommand(initCommand);\nprogram.addCommand(pushCommand);\nprogram.addCommand(pullCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(diffCommand);\nprogram.addCommand(fetchCommand);\nprogram.addCommand(resolveCommand);\nprogram.addCommand(watchCommand);\n\nprogram.parseAsync().then(() => {\n setTimeout(() => process.exit(0), 100);\n});\n","import { Command } from \"commander\";\nimport { ConfigManager, NotionClient } from \"@im-nobsidian/core\";\nimport { input, confirm } from \"@inquirer/prompts\";\nimport ora from \"ora\";\nimport chalk from \"chalk\";\nimport { header, separator, icons, dimText } from \"../utils/format.js\";\n\nexport const initCommand = new Command(\"init\")\n .description(\"Im-Nobsidian 초기 설정\")\n .option(\"--token <token>\", \"Notion Integration Token\")\n .option(\"--root-page-id <id>\", \"루트 페이지 ID\")\n .option(\"--non-interactive\", \"비대화형 모드\")\n .action(async (options: { token?: string; rootPageId?: string; nonInteractive?: boolean }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n\n console.log(`\\n${header(chalk.cyan(\" Im-Nobsidian Setup\"))}`);\n console.log(` ${separator()}`);\n\n if (options.nonInteractive) {\n if (!options.token || !options.rootPageId) {\n console.error(\"비대화형 모드에서는 --token과 --root-page-id가 필수입니다.\");\n process.exitCode = 1;\n return;\n }\n\n if (!options.token.startsWith(\"ntn_\")) {\n console.error(\"토큰은 ntn_으로 시작해야 합니다.\");\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora(\"Notion 연결 확인 중...\").start();\n try {\n const client = new NotionClient({ token: options.token });\n await client.search({ pageSize: 1, filter: { property: \"object\", value: \"page\" } });\n spinner.stop();\n console.log(` ${icons.success} Token validated`);\n\n await configManager.init({ token: options.token, rootPageId: options.rootPageId });\n console.log(`\\n ${icons.success} Config saved to ${dimText(configManager.configPath)}`);\n console.log(` ${icons.success} State DB initialized`);\n console.log(\n `\\n ${header(chalk.green(\"Ready!\"))} Run ${chalk.cyan(\"nobsi sync\")} to start syncing.`,\n );\n } catch (error) {\n spinner.fail(\"Notion 연결 실패\");\n console.error(error instanceof Error ? error.message : error);\n process.exitCode = 1;\n }\n return;\n }\n\n const isInit = await configManager.isInitialized();\n if (isInit) {\n const overwrite = await confirm({\n message: \"이미 초기화되어 있습니다. 다시 설정할까요?\",\n default: false,\n });\n if (!overwrite) return;\n }\n\n const token = await input({\n message: \"Notion Integration Token:\",\n validate: (v) => v.startsWith(\"ntn_\") || \"ntn_으로 시작하는 토큰을 입력하세요\",\n });\n\n const spinner = ora(\"Notion 연결 확인 중...\").start();\n\n try {\n const client = new NotionClient({ token });\n const result = await client.search({\n pageSize: 10,\n filter: { property: \"object\", value: \"page\" },\n });\n spinner.stop();\n console.log(` ${icons.success} Token validated`);\n\n if (result.results.length === 0) {\n console.log(\n `\\n ${chalk.yellow(\"⚠\")} 접근 가능한 페이지가 없습니다. Integration에 페이지를 공유해주세요.`,\n );\n return;\n }\n\n console.log(`\\n Select root page:`);\n for (const [i, page] of result.results.entries()) {\n const title = extractPageTitle(page);\n console.log(` ${dimText(`${i + 1}.`)} ${title}`);\n }\n\n const rootPageId = await input({\n message: \"루트 페이지 ID (위에서 선택하거나 직접 입력):\",\n default: result.results[0]?.id,\n });\n\n await configManager.init({ token, rootPageId });\n console.log(`\\n ${icons.success} Config saved to ${dimText(configManager.configPath)}`);\n console.log(` ${icons.success} State DB initialized`);\n console.log(\n `\\n ${header(chalk.green(\"Ready!\"))} Run ${chalk.cyan(\"nobsi sync\")} to start syncing.`,\n );\n } catch (error) {\n spinner.fail(\"Notion 연결 실패\");\n console.error(error instanceof Error ? error.message : error);\n process.exitCode = 1;\n }\n });\n\nfunction extractPageTitle(page: Record<string, unknown>): string {\n const properties = page[\"properties\"] as Record<string, unknown> | undefined;\n if (!properties) return \"(제목 없음)\";\n\n for (const prop of Object.values(properties)) {\n const p = prop as { type?: string; title?: Array<{ plain_text?: string }> };\n if (p.type === \"title\" && p.title?.[0]?.plain_text) {\n return p.title[0].plain_text;\n }\n }\n return \"(제목 없음)\";\n}\n","import chalk from \"chalk\";\n\nexport const icons = {\n create: chalk.green(\"+\"),\n update: chalk.yellow(\"~\"),\n delete: chalk.red(\"-\"),\n success: chalk.green(\"✓\"),\n fail: chalk.red(\"✕\"),\n conflict: chalk.magenta(\"!\"),\n synced: chalk.green(\"●\"),\n modified: chalk.yellow(\"●\"),\n newFile: chalk.cyan(\"●\"),\n conflictDot: chalk.magenta(\"●\"),\n} as const;\n\nexport function header(text: string): string {\n return chalk.bold(text);\n}\n\nexport function separator(width = 35): string {\n return chalk.dim(\"━\".repeat(width));\n}\n\nexport function operationIcon(op: \"create\" | \"update\" | \"delete\"): string {\n return icons[op];\n}\n\nexport function operationLabel(op: \"create\" | \"update\" | \"delete\"): string {\n switch (op) {\n case \"create\":\n return chalk.green(\"created\");\n case \"update\":\n return chalk.yellow(\"updated\");\n case \"delete\":\n return chalk.red(\"deleted\");\n }\n}\n\nexport function summary(created: number, updated: number, deleted: number): string {\n const parts: string[] = [];\n if (created > 0) parts.push(chalk.green(`${created} created`));\n if (updated > 0) parts.push(chalk.yellow(`${updated} updated`));\n if (deleted > 0) parts.push(chalk.red(`${deleted} deleted`));\n if (parts.length === 0) parts.push(chalk.dim(\"no changes\"));\n return parts.join(\" \");\n}\n\nexport function duration(ms: number): string {\n return chalk.dim(`Done in ${(ms / 1000).toFixed(1)}s`);\n}\n\nexport function progress(current: number, total: number): string {\n return chalk.dim(`[${current}/${total}]`);\n}\n\nexport function dimText(text: string): string {\n return chalk.dim(text);\n}\n\nexport function failedItem(path: string, error: string): void {\n console.log(` ${icons.fail} ${path}: ${chalk.red(error)}`);\n}\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport {\n header,\n operationIcon,\n operationLabel,\n progress,\n summary,\n duration,\n failedItem,\n dimText,\n} from \"../utils/format.js\";\n\nexport const pushCommand = new Command(\"push\")\n .description(\"로컬 변경사항을 Notion에 반영\")\n .option(\"--dry-run\", \"실제 반영 없이 변경사항만 표시\")\n .option(\"-p, --path <paths...>\", \"특정 경로만 push\")\n .action(async (options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n timeoutMs: config.advanced.timeoutMs,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(`\\n${header(\" Pushing to Notion...\")}`);\n if (options.dryRun) console.log(dimText(\" (dry-run mode)\"));\n console.log(\"\");\n\n const result = await orchestrator.push({\n dryRun: options.dryRun,\n paths: options.path,\n onProgress: (current, total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n const prog = progress(current, total);\n console.log(` ${icon} ${item.path} ${prog} ${label}`);\n },\n });\n\n console.log(`\\n ${header(chalk.green(\"Push complete\"))}`);\n console.log(\n ` ${summary(result.created, result.updated, result.deleted)} ${dimText(`${result.failed.length} failed`)}`,\n );\n console.log(` ${duration(result.duration)}`);\n\n if (result.failed.length > 0) {\n console.log(\"\");\n for (const f of result.failed) {\n failedItem(f.path, f.error);\n }\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport {\n header,\n operationIcon,\n operationLabel,\n progress,\n summary,\n duration,\n icons,\n failedItem,\n dimText,\n} from \"../utils/format.js\";\n\nexport const pullCommand = new Command(\"pull\")\n .description(\"Notion 변경사항을 로컬에 반영\")\n .option(\"--dry-run\", \"실제 반영 없이 변경사항만 표시\")\n .option(\"-p, --path <paths...>\", \"특정 경로만 pull\")\n .action(async (options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n timeoutMs: config.advanced.timeoutMs,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(`\\n${header(\" Pulling from Notion...\")}`);\n if (options.dryRun) console.log(dimText(\" (dry-run mode)\"));\n console.log(\"\");\n\n const result = await orchestrator.pull({\n dryRun: options.dryRun,\n paths: options.path,\n onProgress: (current, total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n const prog = progress(current, total);\n console.log(` ${icon} ${item.path} ${prog} ${label}`);\n },\n });\n\n if (result.imageCount > 0) {\n console.log(\n `\\n ${icons.success} ${result.imageCount} images → ${dimText(\"attachments/\")}`,\n );\n }\n if (result.fileCount > 0) {\n console.log(` ${icons.success} ${result.fileCount} files → ${dimText(\"attachments/\")}`);\n }\n if (result.linkCount > 0) {\n console.log(` ${icons.success} ${result.linkCount} links resolved`);\n }\n\n console.log(`\\n ${header(chalk.green(\"Pull complete\"))}`);\n console.log(\n ` ${summary(result.created, result.updated, result.deleted)} ${dimText(`${result.failed.length} failed`)}`,\n );\n console.log(` ${duration(result.duration)}`);\n\n if (result.conflicts.length > 0) {\n console.log(\n `\\n ${icons.conflict} ${chalk.magenta(`${result.conflicts.length} conflicts`)} — run ${chalk.cyan(\"nobsi resolve\")}`,\n );\n }\n\n if (result.failed.length > 0) {\n console.log(\"\");\n for (const f of result.failed) {\n failedItem(f.path, f.error);\n }\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport {\n header,\n separator,\n operationIcon,\n operationLabel,\n summary,\n duration,\n icons,\n dimText,\n} from \"../utils/format.js\";\n\nexport const syncCommand = new Command(\"sync\")\n .description(\"양방향 동기화 (Pull → Push)\")\n .option(\"--dry-run\", \"실제 반영 없이 변경사항만 표시\")\n .action(async (options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n timeoutMs: config.advanced.timeoutMs,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(`\\n${header(\" Bidirectional Sync\")}`);\n console.log(` ${separator()}`);\n if (options.dryRun) console.log(dimText(\" (dry-run mode)\"));\n\n // Pull phase\n console.log(`\\n ${header(chalk.blue(\"▼ Pull\"))} ${dimText(\"(Notion → Obsidian)\")}`);\n\n const pullResult = await orchestrator.pull({\n dryRun: options.dryRun,\n onProgress: (_current, _total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n console.log(` ${icon} ${item.path} ${label}`);\n },\n });\n\n if (pullResult.imageCount > 0) {\n console.log(` ${icons.success} ${pullResult.imageCount} images downloaded`);\n }\n if (pullResult.linkCount > 0) {\n console.log(` ${icons.success} ${pullResult.linkCount} links resolved`);\n }\n\n // Push phase\n console.log(`\\n ${header(chalk.magenta(\"▲ Push\"))} ${dimText(\"(Obsidian → Notion)\")}`);\n\n const pushResult = await orchestrator.push({\n dryRun: options.dryRun,\n onProgress: (_current, _total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n console.log(` ${icon} ${item.path} ${label}`);\n },\n });\n\n // Summary\n const totalDuration = pullResult.duration + pushResult.duration;\n console.log(`\\n ${header(chalk.green(\"Sync complete\"))}`);\n console.log(\n ` ${chalk.blue(\"Pull:\")} ${summary(pullResult.created, pullResult.updated, pullResult.deleted)}`,\n );\n console.log(\n ` ${chalk.magenta(\"Push:\")} ${summary(pushResult.created, pushResult.updated, pushResult.deleted)}`,\n );\n console.log(` ${duration(totalDuration)}`);\n\n if (pullResult.conflicts.length > 0) {\n console.log(\n `\\n ${icons.conflict} ${chalk.magenta(`${pullResult.conflicts.length} conflicts`)} — run ${chalk.cyan(\"nobsi resolve\")}`,\n );\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport { header, separator, icons, dimText } from \"../utils/format.js\";\n\nexport const statusCommand = new Command(\"status\")\n .description(\"동기화 상태 확인 (--full: 원격 변경 포함)\")\n .option(\"--full\", \"Notion 원격 변경까지 양방향 확인 (API 호출, 느림)\")\n .action(async (opts: { full?: boolean }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n const status = opts.full ? await orchestrator.status() : await orchestrator.statusLocal();\n\n console.log(`\\n${header(\" Sync Status\")}`);\n console.log(` ${separator(50)}`);\n\n const rootId = config.notion.rootPageId;\n const direction = config.sync.direction === \"both\" ? \"bidirectional\" : config.sync.direction;\n console.log(` ${dimText(\"Root page:\")} ${rootId.slice(0, 8)}...`);\n console.log(` ${dimText(\"Direction:\")} ${direction}`);\n if (status.lastSyncAt) {\n const date = new Date(status.lastSyncAt);\n const iso =\n date.getFullYear() +\n \"-\" +\n String(date.getMonth() + 1).padStart(2, \"0\") +\n \"-\" +\n String(date.getDate()).padStart(2, \"0\") +\n \" \" +\n String(date.getHours()).padStart(2, \"0\") +\n \":\" +\n String(date.getMinutes()).padStart(2, \"0\") +\n \":\" +\n String(date.getSeconds()).padStart(2, \"0\");\n console.log(` ${dimText(\"Last sync:\")} ${iso}`);\n } else {\n console.log(` ${dimText(\"Last sync:\")} ${chalk.yellow(\"never\")}`);\n }\n\n // Tracked files summary\n const allRecords = stateDb.getAll();\n const total = allRecords.length;\n const synced = allRecords.filter((r) => r.status === \"synced\").length;\n const conflictCount = status.conflictRecords.length;\n const createdChanges = status.localChanges.filter((c) => c.type === \"created\");\n const modifiedChanges = status.localChanges.filter((c) => c.type === \"modified\");\n const remoteCreated = status.remoteChanges.filter((c) => c.type === \"created\");\n const remoteModified = status.remoteChanges.filter((c) => c.type === \"modified\");\n const remoteDeleted = status.remoteChanges.filter((c) => c.type === \"deleted\");\n\n console.log(`\\n ${header(`Tracked files: ${total}`)}`);\n console.log(` ${icons.synced} ${chalk.green(\"synced\")} ${synced}`);\n if (modifiedChanges.length > 0) {\n console.log(` ${icons.modified} ${chalk.yellow(\"modified\")} ${modifiedChanges.length}`);\n }\n if (createdChanges.length > 0) {\n console.log(` ${icons.newFile} ${chalk.cyan(\"new\")} ${createdChanges.length}`);\n }\n if (conflictCount > 0) {\n console.log(` ${icons.conflictDot} ${chalk.magenta(\"conflict\")} ${conflictCount}`);\n }\n\n // Modified files\n if (modifiedChanges.length > 0) {\n console.log(`\\n ${header(\"Modified files:\")}`);\n for (const c of modifiedChanges.slice(0, 10)) {\n console.log(\n ` ${chalk.yellow(\"~\")} ${c.path.padEnd(30)} ${dimText(\"(local changed)\")}`,\n );\n }\n if (modifiedChanges.length > 10) {\n console.log(dimText(` ... and ${modifiedChanges.length - 10} more`));\n }\n }\n\n // New files\n if (createdChanges.length > 0) {\n console.log(`\\n ${header(\"New files:\")}`);\n for (const c of createdChanges.slice(0, 10)) {\n console.log(` ${chalk.cyan(\"+\")} ${c.path.padEnd(30)} ${dimText(\"(untracked)\")}`);\n }\n if (createdChanges.length > 10) {\n console.log(dimText(` ... and ${createdChanges.length - 10} more`));\n }\n }\n\n // Remote changes (Notion-side)\n if (status.remoteChanges.length > 0) {\n console.log(`\\n ${header(`Remote changes (Notion): ${status.remoteChanges.length}`)}`);\n if (remoteCreated.length > 0) {\n console.log(` ${chalk.cyan(\"+\")} ${chalk.cyan(\"new\")} ${remoteCreated.length}`);\n }\n if (remoteModified.length > 0) {\n console.log(\n ` ${chalk.yellow(\"~\")} ${chalk.yellow(\"modified\")} ${remoteModified.length}`,\n );\n }\n if (remoteDeleted.length > 0) {\n console.log(` ${chalk.red(\"-\")} ${chalk.red(\"deleted\")} ${remoteDeleted.length}`);\n }\n for (const c of status.remoteChanges.slice(0, 10)) {\n const icon =\n c.type === \"created\"\n ? chalk.cyan(\"+\")\n : c.type === \"modified\"\n ? chalk.yellow(\"~\")\n : chalk.red(\"-\");\n console.log(` ${icon} ${c.pageId.slice(0, 8)}... ${dimText(`(${c.type})`)}`);\n }\n if (status.remoteChanges.length > 10) {\n console.log(dimText(` ... and ${status.remoteChanges.length - 10} more`));\n }\n }\n\n // Conflicts\n if (conflictCount > 0) {\n console.log(`\\n ${header(chalk.magenta(\"Conflicts:\"))}`);\n for (const r of status.conflictRecords) {\n console.log(\n ` ${icons.conflict} ${r.obsidianPath.padEnd(30)} ${dimText(\"(both sides changed)\")}`,\n );\n }\n }\n\n // Helpful commands\n const hasChanges =\n status.localChanges.length > 0 || status.remoteChanges.length > 0 || conflictCount > 0;\n if (hasChanges) {\n console.log(\"\");\n if (conflictCount > 0) {\n console.log(\n ` ${dimText(\"Run\")} ${chalk.cyan(\"nobsi resolve\")} ${dimText(\"to resolve conflicts\")}`,\n );\n }\n console.log(\n ` ${dimText(\"Run\")} ${chalk.cyan(\"nobsi sync\")} ${dimText(\"to push/pull changes\")}`,\n );\n } else {\n console.log(`\\n ${chalk.green(\"Everything up to date\")} ✓`);\n }\n if (!opts.full) {\n console.log(\n `\\n ${dimText(\"Run\")} ${chalk.cyan(\"nobsi status --full\")} ${dimText(\"to check Notion remote changes\")}`,\n );\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport { createTwoFilesPatch } from \"diff\";\n\nexport const diffCommand = new Command(\"diff\")\n .description(\"로컬과 Notion 간의 차이 표시\")\n .argument(\"[path]\", \"특정 파일 경로 (생략 시 변경된 모든 파일)\")\n .option(\"--color\", \"컬러 출력\", true)\n .action(async (targetPath: string | undefined, options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n timeoutMs: config.advanced.timeoutMs,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n const status = await orchestrator.statusLocal();\n\n const changes = targetPath\n ? status.localChanges.filter((c) => c.path === targetPath || c.path.startsWith(targetPath))\n : status.localChanges;\n\n if (changes.length === 0) {\n console.log(\"변경사항 없음\");\n return;\n }\n\n for (const change of changes) {\n const record = stateDb.getByPath(change.path);\n\n if (change.type === \"created\") {\n const content = await vaultFs.readFile(change.path);\n const patch = createTwoFilesPatch(\"/dev/null\", `b/${change.path}`, \"\", content);\n printPatch(patch, options.color, \"/dev/null\", `b/${change.path}`);\n } else if (change.type === \"deleted\") {\n if (record?.baseSnapshot) {\n const oldContent = record.baseSnapshot.toString(\"utf-8\");\n const patch = createTwoFilesPatch(`a/${change.path}`, \"/dev/null\", oldContent, \"\");\n printPatch(patch, options.color, `a/${change.path}`, \"/dev/null\");\n } else {\n console.log(`--- a/${change.path}`);\n console.log(`+++ /dev/null`);\n console.log(`(이전 스냅샷 없음)`);\n }\n } else if (change.type === \"modified\" && record?.baseSnapshot) {\n const currentContent = await vaultFs.readFile(change.path);\n const baseContent = record.baseSnapshot.toString(\"utf-8\");\n const patch = createTwoFilesPatch(\n `a/${change.path}`,\n `b/${change.path}`,\n baseContent,\n currentContent,\n );\n printPatch(patch, options.color, `a/${change.path}`, `b/${change.path}`);\n }\n\n console.log(\"\");\n }\n } finally {\n stateDb.close();\n }\n });\n\nfunction printPatch(patch: string, color: boolean, oldPath: string, newPath: string): void {\n for (const line of patch.split(\"\\n\")) {\n let output = line;\n if (line.startsWith(\"===\")) {\n output = \"===================================================================\";\n } else if (line.startsWith(\"--- \")) {\n output = `--- ${oldPath}`;\n } else if (line.startsWith(\"+++ \")) {\n output = `+++ ${newPath}`;\n }\n\n if (!color) {\n console.log(output);\n continue;\n }\n\n if (output.startsWith(\"+++\") || output.startsWith(\"---\")) {\n console.log(`\\x1b[1m${output}\\x1b[0m`);\n } else if (output.startsWith(\"+\")) {\n console.log(`\\x1b[32m${output}\\x1b[0m`);\n } else if (output.startsWith(\"-\")) {\n console.log(`\\x1b[31m${output}\\x1b[0m`);\n } else if (output.startsWith(\"@@\")) {\n console.log(`\\x1b[36m${output}\\x1b[0m`);\n } else {\n console.log(output);\n }\n }\n}\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport { header, separator, dimText } from \"../utils/format.js\";\n\nexport const fetchCommand = new Command(\"fetch\")\n .description(\"Notion 리모트 상태 스캔 (삭제 감지 포함)\")\n .action(async () => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n timeoutMs: config.advanced.timeoutMs,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(dimText(\" Scanning remote pages...\"));\n\n const result = await orchestrator.fetch();\n\n console.log(`\\n${header(\" Remote Scan\")}`);\n console.log(` ${separator(40)}`);\n\n if (result.newPages > 0) {\n console.log(` ${chalk.cyan(\"+\")} New pages: ${result.newPages}`);\n }\n if (result.modifiedPages > 0) {\n console.log(` ${chalk.yellow(\"~\")} Modified pages: ${result.modifiedPages}`);\n }\n if (result.deletedPages > 0) {\n console.log(` ${chalk.red(\"-\")} Deleted pages: ${result.deletedPages}`);\n }\n\n const total = result.newPages + result.modifiedPages + result.deletedPages;\n if (total === 0) {\n console.log(` ${chalk.green(\"Remote is up to date\")} ✓`);\n } else {\n console.log(\n `\\n ${dimText(\"Run\")} ${chalk.cyan(\"nobsi pull\")} ${dimText(\"to apply remote changes\")}`,\n );\n }\n\n console.log(dimText(`\\n Completed in ${(result.duration / 1000).toFixed(1)}s`));\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport { select, confirm } from \"@inquirer/prompts\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n ConflictResolver,\n} from \"@im-nobsidian/core\";\nimport type { Conflict, ResolutionChoice } from \"@im-nobsidian/core\";\n\nexport const resolveCommand = new Command(\"resolve\")\n .description(\"충돌을 해결합니다\")\n .option(\"-s, --strategy <strategy>\", \"자동 해결 전략 (local-first, remote-first, duplicate)\")\n .action(async (options: { strategy?: string }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n\n try {\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: 3,\n timeoutMs: 30000,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n const resolver = new ConflictResolver(stateDb, vaultFs);\n\n await orchestrator.status();\n const conflictRecords = stateDb.getByStatus(\"conflict\");\n\n if (conflictRecords.length === 0) {\n console.log(\"충돌이 없습니다.\");\n stateDb.close();\n return;\n }\n\n console.log(`\\n충돌 ${conflictRecords.length}건 발견\\n`);\n\n if (options.strategy) {\n const strategy = options.strategy as \"local-first\" | \"remote-first\" | \"duplicate\";\n const shouldProceed = await confirm({\n message: `${conflictRecords.length}건의 충돌을 '${strategy}' 전략으로 일괄 해결할까요?`,\n });\n\n if (!shouldProceed) {\n stateDb.close();\n return;\n }\n\n const pullResult = await orchestrator.pull();\n const results = await resolver.resolveAll(pullResult.conflicts, strategy);\n\n for (const result of results) {\n const icon = result.success ? \"\\x1b[32m✓\\x1b[0m\" : \"\\x1b[31m✗\\x1b[0m\";\n console.log(` ${icon} ${result.path} → ${result.choice}`);\n }\n } else {\n const pullResult = await orchestrator.pull();\n\n for (const conflict of pullResult.conflicts) {\n await resolveInteractive(conflict, resolver);\n }\n }\n\n stateDb.close();\n console.log(\"\\n충돌 해결 완료\");\n } catch (error) {\n console.error(\"오류:\", error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n\nasync function resolveInteractive(conflict: Conflict, resolver: ConflictResolver): Promise<void> {\n const path = conflict.syncRecord.obsidianPath;\n\n console.log(`\\n${\"─\".repeat(60)}`);\n console.log(`파일: \\x1b[1m${path}\\x1b[0m`);\n console.log(`${\"─\".repeat(60)}`);\n\n const diff = resolver.generateDiff(conflict);\n const diffLines = diff.split(\"\\n\");\n for (const line of diffLines) {\n if (line.startsWith(\"- \")) {\n console.log(`\\x1b[31m${line}\\x1b[0m`);\n } else if (line.startsWith(\"+ \")) {\n console.log(`\\x1b[32m${line}\\x1b[0m`);\n } else if (line.startsWith(\"---\") || line.startsWith(\"+++\")) {\n console.log(`\\x1b[1m${line}\\x1b[0m`);\n } else {\n console.log(line);\n }\n }\n\n const choice = await select<ResolutionChoice>({\n message: \"어떻게 해결할까요?\",\n choices: [\n { name: \"로컬 유지 (Obsidian 버전 유지)\", value: \"local\" },\n { name: \"원격 유지 (Notion 버전으로 덮어쓰기)\", value: \"remote\" },\n { name: \"자동 병합 (3-way merge)\", value: \"merge\" },\n { name: \"복제 (원본 유지 + .conflict 파일 생성)\", value: \"duplicate\" },\n ],\n });\n\n const result = await resolver.resolve(conflict, choice);\n\n if (result.success) {\n console.log(`\\x1b[32m✓ ${path} → ${choice}로 해결\\x1b[0m`);\n } else if (result.mergeHadConflicts) {\n console.log(`\\x1b[33m⚠ ${path} → 자동 병합 완료 (수동 확인 필요한 충돌 마커 있음)\\x1b[0m`);\n } else {\n console.log(`\\x1b[31m✗ ${path} → 해결 실패\\x1b[0m`);\n }\n}\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n WatchSyncService,\n} from \"@im-nobsidian/core\";\nimport type { SyncResult } from \"@im-nobsidian/core\";\n\nfunction formatResult(result: SyncResult): string {\n const pull = `Pull: +${result.pull.created} ~${result.pull.updated} -${result.pull.deleted}`;\n const push = `Push: +${result.push.created} ~${result.push.updated} -${result.push.deleted}`;\n const parts = [pull, push];\n\n if (result.conflicts.length > 0) {\n parts.push(`충돌 ${result.conflicts.length}건`);\n }\n\n return parts.join(\" | \");\n}\n\nfunction timestamp(): string {\n return new Date().toLocaleTimeString(\"ko-KR\", { hour12: false });\n}\n\nexport const watchCommand = new Command(\"watch\")\n .description(\"파일 변경 감지 + 자동 동기화\")\n .option(\"-d, --debounce <ms>\", \"디바운스 대기 시간(ms)\", \"2000\")\n .option(\"-i, --interval <seconds>\", \"풀 동기화 주기(초, 0이면 비활성)\", \"0\")\n .action(async (options: { debounce: string; interval: string }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n const client = new NotionClient({\n token: config.notion.token,\n concurrency: config.advanced.concurrency,\n timeoutMs: config.advanced.timeoutMs,\n });\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n const debounceMs = parseInt(options.debounce, 10);\n const intervalSec = parseInt(options.interval, 10);\n\n const service = new WatchSyncService(cwd, orchestrator, {\n debounceMs,\n onFileChange: (event, path) => {\n console.log(`[${timestamp()}] ${event}: ${path}`);\n },\n onSyncStart: () => {\n console.log(`[${timestamp()}] 동기화 시작...`);\n },\n onSyncComplete: (result) => {\n console.log(`[${timestamp()}] 동기화 완료 — ${formatResult(result)}`);\n },\n onSyncError: (error) => {\n console.error(`[${timestamp()}] 동기화 실패: ${error.message}`);\n },\n });\n\n let pullTimer: ReturnType<typeof setInterval> | null = null;\n\n const shutdown = async (): Promise<void> => {\n console.log(`\\n[${timestamp()}] 감시 종료 중...`);\n if (pullTimer) clearInterval(pullTimer);\n await service.stop();\n stateDb.close();\n console.log(`[${timestamp()}] 종료 완료`);\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => void shutdown());\n process.on(\"SIGTERM\", () => void shutdown());\n\n service.start();\n console.log(`[${timestamp()}] 파일 감시 시작 (debounce: ${debounceMs}ms)`);\n\n if (intervalSec > 0) {\n console.log(`[${timestamp()}] 풀 동기화 주기: ${intervalSec}초`);\n pullTimer = setInterval(async () => {\n if (service.isSyncing()) return;\n try {\n console.log(`[${timestamp()}] 주기적 동기화 시작...`);\n const result = await orchestrator.sync();\n console.log(`[${timestamp()}] 주기적 동기화 완료 — ${formatResult(result)}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`[${timestamp()}] 주기적 동기화 실패: ${msg}`);\n }\n }, intervalSec * 1000);\n }\n\n await new Promise(() => {});\n });\n"],"mappings":"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","names":["Command","chalk","chalk","spinner","Command","ConfigManager","NotionClient","chalk","Command","ConfigManager","NotionClient","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","confirm","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","Command"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/utils/format.ts","../src/commands/push.ts","../src/commands/pull.ts","../src/commands/sync.ts","../src/commands/status.ts","../src/commands/diff.ts","../src/commands/fetch.ts","../src/commands/resolve.ts","../src/commands/watch.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { pushCommand } from \"./commands/push.js\";\nimport { pullCommand } from \"./commands/pull.js\";\nimport { syncCommand } from \"./commands/sync.js\";\nimport { statusCommand } from \"./commands/status.js\";\nimport { diffCommand } from \"./commands/diff.js\";\nimport { fetchCommand } from \"./commands/fetch.js\";\nimport { resolveCommand } from \"./commands/resolve.js\";\nimport { watchCommand } from \"./commands/watch.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"im-nobsidian\")\n .description(\"Im-Nobsidian: Obsidian ↔ Notion 양방향 동기화 CLI\")\n .version(\"0.1.1\")\n .option(\"--verbose\", \"상세 로그 출력\")\n .option(\"--quiet\", \"최소 출력\");\n\nprogram.addCommand(initCommand);\nprogram.addCommand(pushCommand);\nprogram.addCommand(pullCommand);\nprogram.addCommand(syncCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(diffCommand);\nprogram.addCommand(fetchCommand);\nprogram.addCommand(resolveCommand);\nprogram.addCommand(watchCommand);\n\nprogram.parseAsync().then(() => {\n setTimeout(() => process.exit(0), 100);\n});\n","import { Command } from \"commander\";\nimport { ConfigManager, NotionClient } from \"@im-nobsidian/core\";\nimport { input, confirm } from \"@inquirer/prompts\";\nimport ora from \"ora\";\nimport chalk from \"chalk\";\nimport { header, separator, icons, dimText } from \"../utils/format.js\";\n\nexport const initCommand = new Command(\"init\")\n .description(\"Im-Nobsidian 초기 설정\")\n .option(\"--token <token>\", \"Notion Integration Token\")\n .option(\"--root-page-id <id>\", \"루트 페이지 ID\")\n .option(\"--non-interactive\", \"비대화형 모드\")\n .action(async (options: { token?: string; rootPageId?: string; nonInteractive?: boolean }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n\n console.log(`\\n${header(chalk.cyan(\" Im-Nobsidian Setup\"))}`);\n console.log(` ${separator()}`);\n\n if (options.nonInteractive) {\n if (!options.token || !options.rootPageId) {\n console.error(\"비대화형 모드에서는 --token과 --root-page-id가 필수입니다.\");\n process.exitCode = 1;\n return;\n }\n\n if (!options.token.startsWith(\"ntn_\")) {\n console.error(\"토큰은 ntn_으로 시작해야 합니다.\");\n process.exitCode = 1;\n return;\n }\n\n const spinner = ora(\"Notion 연결 확인 중...\").start();\n try {\n const client = new NotionClient({ token: options.token });\n await client.search({ pageSize: 1, filter: { property: \"object\", value: \"page\" } });\n spinner.stop();\n console.log(` ${icons.success} Token validated`);\n\n await configManager.init({ token: options.token, rootPageId: options.rootPageId });\n console.log(`\\n ${icons.success} Config saved to ${dimText(configManager.configPath)}`);\n console.log(` ${icons.success} State DB initialized`);\n console.log(\n `\\n ${header(chalk.green(\"Ready!\"))} Run ${chalk.cyan(\"nobsi sync\")} to start syncing.`,\n );\n } catch (error) {\n spinner.fail(\"Notion 연결 실패\");\n console.error(error instanceof Error ? error.message : error);\n process.exitCode = 1;\n }\n return;\n }\n\n const isInit = await configManager.isInitialized();\n if (isInit) {\n const overwrite = await confirm({\n message: \"이미 초기화되어 있습니다. 다시 설정할까요?\",\n default: false,\n });\n if (!overwrite) return;\n }\n\n const token = await input({\n message: \"Notion Integration Token:\",\n validate: (v) => v.startsWith(\"ntn_\") || \"ntn_으로 시작하는 토큰을 입력하세요\",\n });\n\n const spinner = ora(\"Notion 연결 확인 중...\").start();\n\n try {\n const client = new NotionClient({ token });\n const result = await client.search({\n pageSize: 10,\n filter: { property: \"object\", value: \"page\" },\n });\n spinner.stop();\n console.log(` ${icons.success} Token validated`);\n\n if (result.results.length === 0) {\n console.log(\n `\\n ${chalk.yellow(\"⚠\")} 접근 가능한 페이지가 없습니다. Integration에 페이지를 공유해주세요.`,\n );\n return;\n }\n\n console.log(`\\n Select root page:`);\n for (const [i, page] of result.results.entries()) {\n const title = extractPageTitle(page);\n console.log(` ${dimText(`${i + 1}.`)} ${title}`);\n }\n\n const rootPageId = await input({\n message: \"루트 페이지 ID (위에서 선택하거나 직접 입력):\",\n default: result.results[0]?.id,\n });\n\n await configManager.init({ token, rootPageId });\n console.log(`\\n ${icons.success} Config saved to ${dimText(configManager.configPath)}`);\n console.log(` ${icons.success} State DB initialized`);\n console.log(\n `\\n ${header(chalk.green(\"Ready!\"))} Run ${chalk.cyan(\"nobsi sync\")} to start syncing.`,\n );\n } catch (error) {\n spinner.fail(\"Notion 연결 실패\");\n console.error(error instanceof Error ? error.message : error);\n process.exitCode = 1;\n }\n });\n\nfunction extractPageTitle(page: Record<string, unknown>): string {\n const properties = page[\"properties\"] as Record<string, unknown> | undefined;\n if (!properties) return \"(제목 없음)\";\n\n for (const prop of Object.values(properties)) {\n const p = prop as { type?: string; title?: Array<{ plain_text?: string }> };\n if (p.type === \"title\" && p.title?.[0]?.plain_text) {\n return p.title[0].plain_text;\n }\n }\n return \"(제목 없음)\";\n}\n","import chalk from \"chalk\";\n\nexport const icons = {\n create: chalk.green(\"+\"),\n update: chalk.yellow(\"~\"),\n delete: chalk.red(\"-\"),\n success: chalk.green(\"✓\"),\n fail: chalk.red(\"✕\"),\n conflict: chalk.magenta(\"!\"),\n synced: chalk.green(\"●\"),\n modified: chalk.yellow(\"●\"),\n newFile: chalk.cyan(\"●\"),\n conflictDot: chalk.magenta(\"●\"),\n} as const;\n\nexport function header(text: string): string {\n return chalk.bold(text);\n}\n\nexport function separator(width = 35): string {\n return chalk.dim(\"━\".repeat(width));\n}\n\nexport function operationIcon(op: \"create\" | \"update\" | \"delete\"): string {\n return icons[op];\n}\n\nexport function operationLabel(op: \"create\" | \"update\" | \"delete\"): string {\n switch (op) {\n case \"create\":\n return chalk.green(\"created\");\n case \"update\":\n return chalk.yellow(\"updated\");\n case \"delete\":\n return chalk.red(\"deleted\");\n }\n}\n\nexport function summary(created: number, updated: number, deleted: number): string {\n const parts: string[] = [];\n if (created > 0) parts.push(chalk.green(`${created} created`));\n if (updated > 0) parts.push(chalk.yellow(`${updated} updated`));\n if (deleted > 0) parts.push(chalk.red(`${deleted} deleted`));\n if (parts.length === 0) parts.push(chalk.dim(\"no changes\"));\n return parts.join(\" \");\n}\n\nexport function duration(ms: number): string {\n return chalk.dim(`Done in ${(ms / 1000).toFixed(1)}s`);\n}\n\nexport function progress(current: number, total: number): string {\n return chalk.dim(`[${current}/${total}]`);\n}\n\nexport function dimText(text: string): string {\n return chalk.dim(text);\n}\n\nexport function failedItem(path: string, error: string): void {\n console.log(` ${icons.fail} ${path}: ${chalk.red(error)}`);\n}\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport {\n header,\n operationIcon,\n operationLabel,\n progress,\n summary,\n duration,\n failedItem,\n dimText,\n} from \"../utils/format.js\";\n\nexport const pushCommand = new Command(\"push\")\n .description(\"로컬 변경사항을 Notion에 반영\")\n .option(\"--dry-run\", \"실제 반영 없이 변경사항만 표시\")\n .option(\"-p, --path <paths...>\", \"특정 경로만 push\")\n .action(async (options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(`\\n${header(\" Pushing to Notion...\")}`);\n if (options.dryRun) console.log(dimText(\" (dry-run mode)\"));\n console.log(\"\");\n\n const result = await orchestrator.push({\n dryRun: options.dryRun,\n paths: options.path,\n onProgress: (current, total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n const prog = progress(current, total);\n console.log(` ${icon} ${item.path} ${prog} ${label}`);\n },\n });\n\n console.log(`\\n ${header(chalk.green(\"Push complete\"))}`);\n console.log(\n ` ${summary(result.created, result.updated, result.deleted)} ${dimText(`${result.failed.length} failed`)}`,\n );\n console.log(` ${duration(result.duration)}`);\n\n if (result.failed.length > 0) {\n console.log(\"\");\n for (const f of result.failed) {\n failedItem(f.path, f.error);\n }\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport {\n header,\n operationIcon,\n operationLabel,\n progress,\n summary,\n duration,\n icons,\n failedItem,\n dimText,\n} from \"../utils/format.js\";\n\nexport const pullCommand = new Command(\"pull\")\n .description(\"Notion 변경사항을 로컬에 반영\")\n .option(\"--dry-run\", \"실제 반영 없이 변경사항만 표시\")\n .option(\"-p, --path <paths...>\", \"특정 경로만 pull\")\n .action(async (options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(`\\n${header(\" Pulling from Notion...\")}`);\n if (options.dryRun) console.log(dimText(\" (dry-run mode)\"));\n console.log(\"\");\n\n const result = await orchestrator.pull({\n dryRun: options.dryRun,\n paths: options.path,\n onProgress: (current, total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n const prog = progress(current, total);\n console.log(` ${icon} ${item.path} ${prog} ${label}`);\n },\n });\n\n if (result.imageCount > 0) {\n console.log(\n `\\n ${icons.success} ${result.imageCount} images → ${dimText(\"attachments/\")}`,\n );\n }\n if (result.fileCount > 0) {\n console.log(` ${icons.success} ${result.fileCount} files → ${dimText(\"attachments/\")}`);\n }\n if (result.linkCount > 0) {\n console.log(` ${icons.success} ${result.linkCount} links resolved`);\n }\n\n console.log(`\\n ${header(chalk.green(\"Pull complete\"))}`);\n console.log(\n ` ${summary(result.created, result.updated, result.deleted)} ${dimText(`${result.failed.length} failed`)}`,\n );\n console.log(` ${duration(result.duration)}`);\n\n if (result.conflicts.length > 0) {\n console.log(\n `\\n ${icons.conflict} ${chalk.magenta(`${result.conflicts.length} conflicts`)} — run ${chalk.cyan(\"nobsi resolve\")}`,\n );\n }\n\n if (result.failed.length > 0) {\n console.log(\"\");\n for (const f of result.failed) {\n failedItem(f.path, f.error);\n }\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport {\n header,\n separator,\n operationIcon,\n operationLabel,\n summary,\n duration,\n icons,\n dimText,\n} from \"../utils/format.js\";\n\nexport const syncCommand = new Command(\"sync\")\n .description(\"양방향 동기화 (Pull → Push)\")\n .option(\"--dry-run\", \"실제 반영 없이 변경사항만 표시\")\n .action(async (options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(`\\n${header(\" Bidirectional Sync\")}`);\n console.log(` ${separator()}`);\n if (options.dryRun) console.log(dimText(\" (dry-run mode)\"));\n\n // Pull phase\n console.log(`\\n ${header(chalk.blue(\"▼ Pull\"))} ${dimText(\"(Notion → Obsidian)\")}`);\n\n const pullResult = await orchestrator.pull({\n dryRun: options.dryRun,\n onProgress: (_current, _total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n console.log(` ${icon} ${item.path} ${label}`);\n },\n });\n\n if (pullResult.imageCount > 0) {\n console.log(` ${icons.success} ${pullResult.imageCount} images downloaded`);\n }\n if (pullResult.linkCount > 0) {\n console.log(` ${icons.success} ${pullResult.linkCount} links resolved`);\n }\n\n // Push phase\n console.log(`\\n ${header(chalk.magenta(\"▲ Push\"))} ${dimText(\"(Obsidian → Notion)\")}`);\n\n const pushResult = await orchestrator.push({\n dryRun: options.dryRun,\n onProgress: (_current, _total, item) => {\n const icon = operationIcon(item.operation);\n const label = operationLabel(item.operation);\n console.log(` ${icon} ${item.path} ${label}`);\n },\n });\n\n // Summary\n const totalDuration = pullResult.duration + pushResult.duration;\n console.log(`\\n ${header(chalk.green(\"Sync complete\"))}`);\n console.log(\n ` ${chalk.blue(\"Pull:\")} ${summary(pullResult.created, pullResult.updated, pullResult.deleted)}`,\n );\n console.log(\n ` ${chalk.magenta(\"Push:\")} ${summary(pushResult.created, pushResult.updated, pushResult.deleted)}`,\n );\n console.log(` ${duration(totalDuration)}`);\n\n if (pullResult.conflicts.length > 0) {\n console.log(\n `\\n ${icons.conflict} ${chalk.magenta(`${pullResult.conflicts.length} conflicts`)} — run ${chalk.cyan(\"nobsi resolve\")}`,\n );\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport { header, separator, icons, dimText } from \"../utils/format.js\";\n\nexport const statusCommand = new Command(\"status\")\n .description(\"동기화 상태 확인 (--full: 원격 변경 포함)\")\n .option(\"--full\", \"Notion 원격 변경까지 양방향 확인 (API 호출, 느림)\")\n .action(async (opts: { full?: boolean }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n const status = opts.full ? await orchestrator.status() : await orchestrator.statusLocal();\n\n console.log(`\\n${header(\" Sync Status\")}`);\n console.log(` ${separator(50)}`);\n\n const rootId = config.notion.rootPageId;\n const direction = config.sync.direction === \"both\" ? \"bidirectional\" : config.sync.direction;\n console.log(` ${dimText(\"Root page:\")} ${rootId.slice(0, 8)}...`);\n console.log(` ${dimText(\"Direction:\")} ${direction}`);\n if (status.lastSyncAt) {\n const date = new Date(status.lastSyncAt);\n const iso =\n date.getFullYear() +\n \"-\" +\n String(date.getMonth() + 1).padStart(2, \"0\") +\n \"-\" +\n String(date.getDate()).padStart(2, \"0\") +\n \" \" +\n String(date.getHours()).padStart(2, \"0\") +\n \":\" +\n String(date.getMinutes()).padStart(2, \"0\") +\n \":\" +\n String(date.getSeconds()).padStart(2, \"0\");\n console.log(` ${dimText(\"Last sync:\")} ${iso}`);\n } else {\n console.log(` ${dimText(\"Last sync:\")} ${chalk.yellow(\"never\")}`);\n }\n\n // Tracked files summary\n const allRecords = stateDb.getAll();\n const total = allRecords.length;\n const synced = allRecords.filter((r) => r.status === \"synced\").length;\n const conflictCount = status.conflictRecords.length;\n const createdChanges = status.localChanges.filter((c) => c.type === \"created\");\n const modifiedChanges = status.localChanges.filter((c) => c.type === \"modified\");\n const remoteCreated = status.remoteChanges.filter((c) => c.type === \"created\");\n const remoteModified = status.remoteChanges.filter((c) => c.type === \"modified\");\n const remoteDeleted = status.remoteChanges.filter((c) => c.type === \"deleted\");\n\n console.log(`\\n ${header(`Tracked files: ${total}`)}`);\n console.log(` ${icons.synced} ${chalk.green(\"synced\")} ${synced}`);\n if (modifiedChanges.length > 0) {\n console.log(` ${icons.modified} ${chalk.yellow(\"modified\")} ${modifiedChanges.length}`);\n }\n if (createdChanges.length > 0) {\n console.log(` ${icons.newFile} ${chalk.cyan(\"new\")} ${createdChanges.length}`);\n }\n if (conflictCount > 0) {\n console.log(` ${icons.conflictDot} ${chalk.magenta(\"conflict\")} ${conflictCount}`);\n }\n\n // Modified files\n if (modifiedChanges.length > 0) {\n console.log(`\\n ${header(\"Modified files:\")}`);\n for (const c of modifiedChanges.slice(0, 10)) {\n console.log(\n ` ${chalk.yellow(\"~\")} ${c.path.padEnd(30)} ${dimText(\"(local changed)\")}`,\n );\n }\n if (modifiedChanges.length > 10) {\n console.log(dimText(` ... and ${modifiedChanges.length - 10} more`));\n }\n }\n\n // New files\n if (createdChanges.length > 0) {\n console.log(`\\n ${header(\"New files:\")}`);\n for (const c of createdChanges.slice(0, 10)) {\n console.log(` ${chalk.cyan(\"+\")} ${c.path.padEnd(30)} ${dimText(\"(untracked)\")}`);\n }\n if (createdChanges.length > 10) {\n console.log(dimText(` ... and ${createdChanges.length - 10} more`));\n }\n }\n\n // Remote changes (Notion-side)\n if (status.remoteChanges.length > 0) {\n console.log(`\\n ${header(`Remote changes (Notion): ${status.remoteChanges.length}`)}`);\n if (remoteCreated.length > 0) {\n console.log(` ${chalk.cyan(\"+\")} ${chalk.cyan(\"new\")} ${remoteCreated.length}`);\n }\n if (remoteModified.length > 0) {\n console.log(\n ` ${chalk.yellow(\"~\")} ${chalk.yellow(\"modified\")} ${remoteModified.length}`,\n );\n }\n if (remoteDeleted.length > 0) {\n console.log(` ${chalk.red(\"-\")} ${chalk.red(\"deleted\")} ${remoteDeleted.length}`);\n }\n for (const c of status.remoteChanges.slice(0, 10)) {\n const icon =\n c.type === \"created\"\n ? chalk.cyan(\"+\")\n : c.type === \"modified\"\n ? chalk.yellow(\"~\")\n : chalk.red(\"-\");\n console.log(` ${icon} ${c.pageId.slice(0, 8)}... ${dimText(`(${c.type})`)}`);\n }\n if (status.remoteChanges.length > 10) {\n console.log(dimText(` ... and ${status.remoteChanges.length - 10} more`));\n }\n }\n\n // Conflicts\n if (conflictCount > 0) {\n console.log(`\\n ${header(chalk.magenta(\"Conflicts:\"))}`);\n for (const r of status.conflictRecords) {\n console.log(\n ` ${icons.conflict} ${r.obsidianPath.padEnd(30)} ${dimText(\"(both sides changed)\")}`,\n );\n }\n }\n\n // Helpful commands\n const hasChanges =\n status.localChanges.length > 0 || status.remoteChanges.length > 0 || conflictCount > 0;\n if (hasChanges) {\n console.log(\"\");\n if (conflictCount > 0) {\n console.log(\n ` ${dimText(\"Run\")} ${chalk.cyan(\"nobsi resolve\")} ${dimText(\"to resolve conflicts\")}`,\n );\n }\n console.log(\n ` ${dimText(\"Run\")} ${chalk.cyan(\"nobsi sync\")} ${dimText(\"to push/pull changes\")}`,\n );\n } else {\n console.log(`\\n ${chalk.green(\"Everything up to date\")} ✓`);\n }\n if (!opts.full) {\n console.log(\n `\\n ${dimText(\"Run\")} ${chalk.cyan(\"nobsi status --full\")} ${dimText(\"to check Notion remote changes\")}`,\n );\n }\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport { createTwoFilesPatch } from \"diff\";\n\nexport const diffCommand = new Command(\"diff\")\n .description(\"로컬과 Notion 간의 차이 표시\")\n .argument(\"[path]\", \"특정 파일 경로 (생략 시 변경된 모든 파일)\")\n .option(\"--color\", \"컬러 출력\", true)\n .action(async (targetPath: string | undefined, options) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n const status = await orchestrator.statusLocal();\n\n const changes = targetPath\n ? status.localChanges.filter((c) => c.path === targetPath || c.path.startsWith(targetPath))\n : status.localChanges;\n\n if (changes.length === 0) {\n console.log(\"변경사항 없음\");\n return;\n }\n\n for (const change of changes) {\n const record = stateDb.getByPath(change.path);\n\n if (change.type === \"created\") {\n const content = await vaultFs.readFile(change.path);\n const patch = createTwoFilesPatch(\"/dev/null\", `b/${change.path}`, \"\", content);\n printPatch(patch, options.color, \"/dev/null\", `b/${change.path}`);\n } else if (change.type === \"deleted\") {\n if (record?.baseSnapshot) {\n const oldContent = record.baseSnapshot.toString(\"utf-8\");\n const patch = createTwoFilesPatch(`a/${change.path}`, \"/dev/null\", oldContent, \"\");\n printPatch(patch, options.color, `a/${change.path}`, \"/dev/null\");\n } else {\n console.log(`--- a/${change.path}`);\n console.log(`+++ /dev/null`);\n console.log(`(이전 스냅샷 없음)`);\n }\n } else if (change.type === \"modified\" && record?.baseSnapshot) {\n const currentContent = await vaultFs.readFile(change.path);\n const baseContent = record.baseSnapshot.toString(\"utf-8\");\n const patch = createTwoFilesPatch(\n `a/${change.path}`,\n `b/${change.path}`,\n baseContent,\n currentContent,\n );\n printPatch(patch, options.color, `a/${change.path}`, `b/${change.path}`);\n }\n\n console.log(\"\");\n }\n } finally {\n stateDb.close();\n }\n });\n\nfunction printPatch(patch: string, color: boolean, oldPath: string, newPath: string): void {\n for (const line of patch.split(\"\\n\")) {\n let output = line;\n if (line.startsWith(\"===\")) {\n output = \"===================================================================\";\n } else if (line.startsWith(\"--- \")) {\n output = `--- ${oldPath}`;\n } else if (line.startsWith(\"+++ \")) {\n output = `+++ ${newPath}`;\n }\n\n if (!color) {\n console.log(output);\n continue;\n }\n\n if (output.startsWith(\"+++\") || output.startsWith(\"---\")) {\n console.log(`\\x1b[1m${output}\\x1b[0m`);\n } else if (output.startsWith(\"+\")) {\n console.log(`\\x1b[32m${output}\\x1b[0m`);\n } else if (output.startsWith(\"-\")) {\n console.log(`\\x1b[31m${output}\\x1b[0m`);\n } else if (output.startsWith(\"@@\")) {\n console.log(`\\x1b[36m${output}\\x1b[0m`);\n } else {\n console.log(output);\n }\n }\n}\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport chalk from \"chalk\";\nimport { header, separator, dimText } from \"../utils/format.js\";\n\nexport const fetchCommand = new Command(\"fetch\")\n .description(\"Notion 리모트 상태 스캔 (삭제 감지 포함)\")\n .action(async () => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n try {\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n console.log(dimText(\" Scanning remote pages...\"));\n\n const result = await orchestrator.fetch();\n\n console.log(`\\n${header(\" Remote Scan\")}`);\n console.log(` ${separator(40)}`);\n\n if (result.newPages > 0) {\n console.log(` ${chalk.cyan(\"+\")} New pages: ${result.newPages}`);\n }\n if (result.modifiedPages > 0) {\n console.log(` ${chalk.yellow(\"~\")} Modified pages: ${result.modifiedPages}`);\n }\n if (result.deletedPages > 0) {\n console.log(` ${chalk.red(\"-\")} Deleted pages: ${result.deletedPages}`);\n }\n\n const total = result.newPages + result.modifiedPages + result.deletedPages;\n if (total === 0) {\n console.log(` ${chalk.green(\"Remote is up to date\")} ✓`);\n } else {\n console.log(\n `\\n ${dimText(\"Run\")} ${chalk.cyan(\"nobsi pull\")} ${dimText(\"to apply remote changes\")}`,\n );\n }\n\n console.log(dimText(`\\n Completed in ${(result.duration / 1000).toFixed(1)}s`));\n } finally {\n stateDb.close();\n }\n });\n","import { Command } from \"commander\";\nimport { select, confirm } from \"@inquirer/prompts\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n} from \"@im-nobsidian/core\";\nimport type { Conflict, ResolutionChoice } from \"@im-nobsidian/core\";\n\nexport const resolveCommand = new Command(\"resolve\")\n .description(\"충돌을 해결합니다\")\n .option(\"-s, --strategy <strategy>\", \"자동 해결 전략 (local-first, remote-first, duplicate)\")\n .action(async (options: { strategy?: string }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n\n try {\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n await orchestrator.status();\n const conflictRecords = stateDb.getByStatus(\"conflict\");\n\n if (conflictRecords.length === 0) {\n console.log(\"충돌이 없습니다.\");\n stateDb.close();\n return;\n }\n\n console.log(`\\n충돌 ${conflictRecords.length}건 발견\\n`);\n\n if (options.strategy) {\n const strategy = options.strategy as \"local-first\" | \"remote-first\" | \"duplicate\";\n const shouldProceed = await confirm({\n message: `${conflictRecords.length}건의 충돌을 '${strategy}' 전략으로 일괄 해결할까요?`,\n });\n\n if (!shouldProceed) {\n stateDb.close();\n return;\n }\n\n const pullResult = await orchestrator.pull();\n const results = await orchestrator.resolveAllConflicts(pullResult.conflicts, strategy);\n\n for (const result of results) {\n const icon = result.success ? \"\\x1b[32m✓\\x1b[0m\" : \"\\x1b[31m✗\\x1b[0m\";\n console.log(` ${icon} ${result.path} → ${result.choice}`);\n }\n } else {\n const pullResult = await orchestrator.pull();\n\n for (const conflict of pullResult.conflicts) {\n await resolveInteractive(conflict, orchestrator);\n }\n }\n\n stateDb.close();\n console.log(\"\\n충돌 해결 완료\");\n } catch (error) {\n console.error(\"오류:\", error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n\nasync function resolveInteractive(\n conflict: Conflict,\n orchestrator: SyncOrchestrator,\n): Promise<void> {\n const path = conflict.syncRecord.obsidianPath;\n\n console.log(`\\n${\"─\".repeat(60)}`);\n console.log(`파일: \\x1b[1m${path}\\x1b[0m`);\n console.log(`${\"─\".repeat(60)}`);\n\n const diff = orchestrator.generateConflictDiff(conflict);\n const diffLines = diff.split(\"\\n\");\n for (const line of diffLines) {\n if (line.startsWith(\"- \")) {\n console.log(`\\x1b[31m${line}\\x1b[0m`);\n } else if (line.startsWith(\"+ \")) {\n console.log(`\\x1b[32m${line}\\x1b[0m`);\n } else if (line.startsWith(\"---\") || line.startsWith(\"+++\")) {\n console.log(`\\x1b[1m${line}\\x1b[0m`);\n } else {\n console.log(line);\n }\n }\n\n const choice = await select<ResolutionChoice>({\n message: \"어떻게 해결할까요?\",\n choices: [\n { name: \"로컬 유지 (Obsidian 버전 유지)\", value: \"local\" },\n { name: \"원격 유지 (Notion 버전으로 덮어쓰기)\", value: \"remote\" },\n { name: \"자동 병합 (3-way merge)\", value: \"merge\" },\n { name: \"복제 (원본 유지 + .conflict 파일 생성)\", value: \"duplicate\" },\n ],\n });\n\n const result = await orchestrator.resolveConflict(conflict, choice);\n\n if (result.success) {\n console.log(`\\x1b[32m✓ ${path} → ${choice}로 해결\\x1b[0m`);\n } else if (result.mergeHadConflicts) {\n console.log(`\\x1b[33m⚠ ${path} → 자동 병합 완료 (수동 확인 필요한 충돌 마커 있음)\\x1b[0m`);\n } else {\n console.log(`\\x1b[31m✗ ${path} → 해결 실패\\x1b[0m`);\n }\n}\n","import { Command } from \"commander\";\nimport {\n ConfigManager,\n StateDB,\n NotionClient,\n SyncOrchestrator,\n NodeVaultFS,\n WatchSyncService,\n} from \"@im-nobsidian/core\";\nimport type { SyncResult } from \"@im-nobsidian/core\";\n\nfunction formatResult(result: SyncResult): string {\n const pull = `Pull: +${result.pull.created} ~${result.pull.updated} -${result.pull.deleted}`;\n const push = `Push: +${result.push.created} ~${result.push.updated} -${result.push.deleted}`;\n const parts = [pull, push];\n\n if (result.conflicts.length > 0) {\n parts.push(`충돌 ${result.conflicts.length}건`);\n }\n\n return parts.join(\" | \");\n}\n\nfunction timestamp(): string {\n return new Date().toLocaleTimeString(\"ko-KR\", { hour12: false });\n}\n\nexport const watchCommand = new Command(\"watch\")\n .description(\"파일 변경 감지 + 자동 동기화\")\n .option(\"-d, --debounce <ms>\", \"디바운스 대기 시간(ms)\", \"2000\")\n .option(\"-i, --interval <seconds>\", \"풀 동기화 주기(초, 0이면 비활성)\", \"0\")\n .action(async (options: { debounce: string; interval: string }) => {\n const cwd = process.cwd();\n const configManager = new ConfigManager(cwd);\n const config = await configManager.load();\n const stateDb = StateDB.open(configManager.dbPath);\n\n const client = NotionClient.fromConfig(config);\n const vaultFs = new NodeVaultFS(cwd, config.paths);\n const orchestrator = new SyncOrchestrator(config, stateDb, client, vaultFs);\n\n const debounceMs = parseInt(options.debounce, 10);\n const intervalSec = parseInt(options.interval, 10);\n\n const service = new WatchSyncService(cwd, orchestrator, {\n debounceMs,\n onFileChange: (event, path) => {\n console.log(`[${timestamp()}] ${event}: ${path}`);\n },\n onSyncStart: () => {\n console.log(`[${timestamp()}] 동기화 시작...`);\n },\n onSyncComplete: (result) => {\n console.log(`[${timestamp()}] 동기화 완료 — ${formatResult(result)}`);\n },\n onSyncError: (error) => {\n console.error(`[${timestamp()}] 동기화 실패: ${error.message}`);\n },\n });\n\n let pullTimer: ReturnType<typeof setInterval> | null = null;\n\n const shutdown = async (): Promise<void> => {\n console.log(`\\n[${timestamp()}] 감시 종료 중...`);\n if (pullTimer) clearInterval(pullTimer);\n await service.stop();\n stateDb.close();\n console.log(`[${timestamp()}] 종료 완료`);\n process.exit(0);\n };\n\n process.on(\"SIGINT\", () => void shutdown());\n process.on(\"SIGTERM\", () => void shutdown());\n\n service.start();\n console.log(`[${timestamp()}] 파일 감시 시작 (debounce: ${debounceMs}ms)`);\n\n if (intervalSec > 0) {\n console.log(`[${timestamp()}] 풀 동기화 주기: ${intervalSec}초`);\n pullTimer = setInterval(async () => {\n if (service.isSyncing()) return;\n try {\n console.log(`[${timestamp()}] 주기적 동기화 시작...`);\n const result = await orchestrator.sync();\n console.log(`[${timestamp()}] 주기적 동기화 완료 — ${formatResult(result)}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`[${timestamp()}] 주기적 동기화 실패: ${msg}`);\n }\n }, intervalSec * 1000);\n }\n\n await new Promise(() => {});\n });\n"],"mappings":"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","names":["Command","chalk","chalk","spinner","Command","ConfigManager","NotionClient","chalk","Command","ConfigManager","NotionClient","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","chalk","Command","ConfigManager","StateDB","NotionClient","NodeVaultFS","SyncOrchestrator","chalk","Command","confirm","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","Command","ConfigManager","StateDB","NotionClient","SyncOrchestrator","NodeVaultFS","Command"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "im-nobsidian",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI tool for Obsidian ↔ Notion bidirectional sync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"commander": "^12.0.0",
|
|
17
17
|
"diff": "^9.0.0",
|
|
18
18
|
"ora": "^8.0.0",
|
|
19
|
-
"@im-nobsidian/core": "0.
|
|
19
|
+
"@im-nobsidian/core": "0.2.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/diff": "^8.0.0",
|