obsidian-zk 0.1.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 +226 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +49 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/db/index.d.ts +49 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +196 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.d.ts +6 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +37 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/init/scaffold.d.ts +3 -0
- package/dist/init/scaffold.d.ts.map +1 -0
- package/dist/init/scaffold.js +122 -0
- package/dist/init/scaffold.js.map +1 -0
- package/dist/init/updater.d.ts +2 -0
- package/dist/init/updater.d.ts.map +1 -0
- package/dist/init/updater.js +75 -0
- package/dist/init/updater.js.map +1 -0
- package/dist/init/wizard.d.ts +7 -0
- package/dist/init/wizard.d.ts.map +1 -0
- package/dist/init/wizard.js +28 -0
- package/dist/init/wizard.js.map +1 -0
- package/dist/luhmann.d.ts +7 -0
- package/dist/luhmann.d.ts.map +1 -0
- package/dist/luhmann.js +63 -0
- package/dist/luhmann.js.map +1 -0
- package/dist/server/index.d.ts +2 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +13 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/server.d.ts +6 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +381 -0
- package/dist/server/server.js.map +1 -0
- package/dist/tools/analysis.d.ts +38 -0
- package/dist/tools/analysis.d.ts.map +1 -0
- package/dist/tools/analysis.js +44 -0
- package/dist/tools/analysis.js.map +1 -0
- package/dist/tools/capture.d.ts +16 -0
- package/dist/tools/capture.d.ts.map +1 -0
- package/dist/tools/capture.js +43 -0
- package/dist/tools/capture.js.map +1 -0
- package/dist/tools/index-mgmt.d.ts +15 -0
- package/dist/tools/index-mgmt.d.ts.map +1 -0
- package/dist/tools/index-mgmt.js +12 -0
- package/dist/tools/index-mgmt.js.map +1 -0
- package/dist/tools/literature.d.ts +30 -0
- package/dist/tools/literature.d.ts.map +1 -0
- package/dist/tools/literature.js +63 -0
- package/dist/tools/literature.js.map +1 -0
- package/dist/tools/manage.d.ts +60 -0
- package/dist/tools/manage.d.ts.map +1 -0
- package/dist/tools/manage.js +65 -0
- package/dist/tools/manage.js.map +1 -0
- package/dist/tools/permanent.d.ts +24 -0
- package/dist/tools/permanent.d.ts.map +1 -0
- package/dist/tools/permanent.js +74 -0
- package/dist/tools/permanent.js.map +1 -0
- package/dist/tools/search.d.ts +24 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +50 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/vault/parser.d.ts +14 -0
- package/dist/vault/parser.d.ts.map +1 -0
- package/dist/vault/parser.js +92 -0
- package/dist/vault/parser.js.map +1 -0
- package/dist/vault/scanner.d.ts +6 -0
- package/dist/vault/scanner.d.ts.map +1 -0
- package/dist/vault/scanner.js +44 -0
- package/dist/vault/scanner.js.map +1 -0
- package/dist/vault/writer.d.ts +6 -0
- package/dist/vault/writer.d.ts.map +1 -0
- package/dist/vault/writer.js +71 -0
- package/dist/vault/writer.js.map +1 -0
- package/package.json +33 -0
- package/templates/CLAUDE.md.template +59 -0
- package/templates/claude/agents/zk-analyzer.md +40 -0
- package/templates/claude/skills/zk-capture/SKILL.md +25 -0
- package/templates/claude/skills/zk-connect/SKILL.md +23 -0
- package/templates/claude/skills/zk-daily/SKILL.md +17 -0
- package/templates/claude/skills/zk-literature/SKILL.md +33 -0
- package/templates/claude/skills/zk-manage/SKILL.md +29 -0
- package/templates/claude/skills/zk-permanent/SKILL.md +30 -0
- package/templates/claude/skills/zk-promote/SKILL.md +30 -0
- package/templates/claude/skills/zk-reflect/SKILL.md +17 -0
- package/templates/claude/skills/zk-review/SKILL.md +22 -0
- package/templates/vault-folders/Templates/Fleeting Note.md +31 -0
- package/templates/vault-folders/Templates/Literature Note.md +61 -0
- package/templates/vault-folders/Templates/MOC.md +48 -0
- package/templates/vault-folders/Templates/Permanent Note.md +49 -0
- package/templates/vault-folders/Templates/Project Note.md +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# obsidian-zk — Obsidian Zettelkasten MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server for AI-assisted Zettelkasten in Obsidian. Luhmann numbering, typed connections, SQLite metadata cache.
|
|
4
|
+
|
|
5
|
+
Works with [Claude Code](https://claude.ai/code) — exposes tools and prompts via [Model Context Protocol](https://modelcontextprotocol.io/).
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- **CRUD** for fleeting, literature, and permanent notes with proper frontmatter
|
|
10
|
+
- **Luhmann numbering** — auto-generates `zk_id` with alternating numbers/letters (`1 → 1a → 1a1 → 1a1a`)
|
|
11
|
+
- **Connection search** — finds related notes by shared tags, keywords, link proximity
|
|
12
|
+
- **Vault analysis** — unprocessed notes, orphans, emerging theme clusters
|
|
13
|
+
- **MCP prompts** — guided workflows as slash commands (`/zk:capture`, `/zk:promote`, etc.)
|
|
14
|
+
- **SQLite index** — fast metadata queries without scanning files every time
|
|
15
|
+
|
|
16
|
+
No embeddings — Claude judges semantic relevance directly in context.
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
### 1. Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npx obsidian-zk init
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Interactive wizard:
|
|
27
|
+
- Detects or asks for vault path
|
|
28
|
+
- Creates folder structure (`1-Fleeting/`, `2-Literature/`, `3-Permanent/`, etc.)
|
|
29
|
+
- Copies note templates, skills, and agents into `.claude/`
|
|
30
|
+
- Creates `CLAUDE.md` with project instructions
|
|
31
|
+
- Sets up SQLite database in `.zk/`
|
|
32
|
+
- Configures MCP server in `.mcp.json`
|
|
33
|
+
|
|
34
|
+
### 2. Use
|
|
35
|
+
|
|
36
|
+
Open vault directory in Claude Code:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cd your-vault
|
|
40
|
+
claude
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The MCP server starts automatically. Use prompts:
|
|
44
|
+
|
|
45
|
+
| Command | What it does |
|
|
46
|
+
|---------|-------------|
|
|
47
|
+
| `/zk:capture` | Quick fleeting note from a thought |
|
|
48
|
+
| `/zk:literature` | Literature note from pasted source |
|
|
49
|
+
| `/zk:permanent` | Atomic permanent note with auto Luhmann ID |
|
|
50
|
+
| `/zk:promote` | Convert fleeting → permanent |
|
|
51
|
+
| `/zk:manage` | Edit/archive/delete by Luhmann number |
|
|
52
|
+
| `/zk:review` | Vault health report |
|
|
53
|
+
| `/zk:daily` | Morning briefing |
|
|
54
|
+
| `/zk:connect` | Find and create connections for a note |
|
|
55
|
+
| `/zk:reflect` | Deep reflection on vault themes |
|
|
56
|
+
|
|
57
|
+
### 3. Update
|
|
58
|
+
|
|
59
|
+
After upgrading the package:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx obsidian-zk update
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Syncs skills/agents, runs DB migrations.
|
|
66
|
+
|
|
67
|
+
## How it works
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Claude Code ←→ MCP Server (obsidian-zk serve) ←→ SQLite DB + Vault files
|
|
71
|
+
│
|
|
72
|
+
├── Tools (zk_capture, zk_permanent, zk_find_connections, ...)
|
|
73
|
+
└── Prompts (/zk:capture, /zk:promote, /zk:review, ...)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Architecture
|
|
77
|
+
|
|
78
|
+
| Component | Choice |
|
|
79
|
+
|-----------|--------|
|
|
80
|
+
| MCP SDK | `@modelcontextprotocol/sdk` (stdio transport) |
|
|
81
|
+
| Database | `better-sqlite3` — single `.zk/zettelkasten.db` file |
|
|
82
|
+
| Semantic search | Claude itself — no embeddings infra needed |
|
|
83
|
+
| Vault I/O | Node.js `fs` — direct file read/write |
|
|
84
|
+
|
|
85
|
+
### MCP Tools
|
|
86
|
+
|
|
87
|
+
**CRUD:**
|
|
88
|
+
- `zk_capture` — create fleeting note
|
|
89
|
+
- `zk_literature` — create literature note
|
|
90
|
+
- `zk_permanent` — create permanent note with Luhmann ID
|
|
91
|
+
- `zk_manage` — edit/archive/delete by ID
|
|
92
|
+
- `zk_promote` — mark fleeting as processed
|
|
93
|
+
|
|
94
|
+
**Search & connections:**
|
|
95
|
+
- `zk_find_connections` — candidates by tags + links + keywords
|
|
96
|
+
- `zk_cluster_detect` — emerging themes without MOCs
|
|
97
|
+
|
|
98
|
+
**Analysis:**
|
|
99
|
+
- `zk_list` — filter notes by type/status/folder
|
|
100
|
+
- `zk_unprocessed` — notes needing processing
|
|
101
|
+
- `zk_orphans` — notes with no incoming links
|
|
102
|
+
- `zk_next_id` — next Luhmann ID
|
|
103
|
+
- `zk_find_by_id` — resolve ID → path
|
|
104
|
+
- `zk_list_ids` — all numbered notes
|
|
105
|
+
- `zk_review` — full vault health report
|
|
106
|
+
|
|
107
|
+
**Index:**
|
|
108
|
+
- `zk_reindex` — full vault re-scan
|
|
109
|
+
- `zk_status` — DB stats
|
|
110
|
+
|
|
111
|
+
### Database schema
|
|
112
|
+
|
|
113
|
+
```sql
|
|
114
|
+
CREATE TABLE notes (
|
|
115
|
+
path TEXT PRIMARY KEY,
|
|
116
|
+
title TEXT, zk_id TEXT, type TEXT, status TEXT,
|
|
117
|
+
folder TEXT, tags TEXT, summary TEXT,
|
|
118
|
+
created TEXT, modified TEXT, content_hash TEXT
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
CREATE TABLE links (
|
|
122
|
+
source TEXT, target TEXT, link_type TEXT,
|
|
123
|
+
PRIMARY KEY (source, target)
|
|
124
|
+
);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Incremental indexing — compares `content_hash`, only updates changed files.
|
|
128
|
+
|
|
129
|
+
## Zettelkasten method
|
|
130
|
+
|
|
131
|
+
### Note types
|
|
132
|
+
|
|
133
|
+
| Folder | Type | Atomic? | Lifecycle |
|
|
134
|
+
|--------|------|---------|-----------|
|
|
135
|
+
| `1-Fleeting/` | Raw thoughts | No | unprocessed → processed |
|
|
136
|
+
| `2-Literature/` | Source summaries | Partial | unprocessed → processed |
|
|
137
|
+
| `3-Permanent/` | One idea per note | **Yes** | draft → finalized |
|
|
138
|
+
| `4-MOC/` | Topic indexes | No | — |
|
|
139
|
+
| `5-Projects/` | Active goals | No | active → completed |
|
|
140
|
+
|
|
141
|
+
### Luhmann numbering
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
1, 2, 3 — independent threads
|
|
145
|
+
1a, 1b — branches from 1
|
|
146
|
+
1a1, 1a2 — sub-branches from 1a
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Connection types
|
|
150
|
+
|
|
151
|
+
- **Підтримує** (Supports) — reinforces another idea
|
|
152
|
+
- **Суперечить** (Contradicts) — challenges another idea
|
|
153
|
+
- **Розширює** (Extends) — builds upon another idea
|
|
154
|
+
- **Пов'язано** (Related) — topically connected
|
|
155
|
+
|
|
156
|
+
### Workflow
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
Thought → /zk:capture → Fleeting note
|
|
160
|
+
Source → /zk:literature → Literature note
|
|
161
|
+
↓
|
|
162
|
+
/zk:promote (or /zk:permanent)
|
|
163
|
+
↓
|
|
164
|
+
Permanent note (auto zk_id) ←→ connections
|
|
165
|
+
↓
|
|
166
|
+
MOC (when 3+ related notes cluster)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Development
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
git clone https://github.com/user/obsidian-zk.git
|
|
173
|
+
cd obsidian-zk
|
|
174
|
+
npm install
|
|
175
|
+
npm run build # compile TypeScript
|
|
176
|
+
npm run dev # watch mode
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Test locally:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# Start server against a test vault
|
|
183
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' \
|
|
184
|
+
| node dist/cli/index.js serve --vault /path/to/vault
|
|
185
|
+
|
|
186
|
+
# Or configure in Claude Code
|
|
187
|
+
claude mcp add obsidian-zk -- node /path/to/obsidian-zk/dist/cli/index.js serve --vault .
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Project structure
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
src/
|
|
194
|
+
├── cli/index.ts # CLI: init, update, serve
|
|
195
|
+
├── init/
|
|
196
|
+
│ ├── wizard.ts # Interactive setup
|
|
197
|
+
│ ├── scaffold.ts # Copy templates, create folders
|
|
198
|
+
│ └── updater.ts # Sync templates, run migrations
|
|
199
|
+
├── server/
|
|
200
|
+
│ ├── index.ts # Stdio transport entry
|
|
201
|
+
│ └── server.ts # Tool + prompt registration
|
|
202
|
+
├── vault/
|
|
203
|
+
│ ├── parser.ts # Frontmatter, wikilinks, body
|
|
204
|
+
│ ├── scanner.ts # File discovery
|
|
205
|
+
│ └── writer.ts # Note creation/editing
|
|
206
|
+
├── db/
|
|
207
|
+
│ ├── schema.ts # SQLite schema
|
|
208
|
+
│ └── index.ts # DB connection + indexing
|
|
209
|
+
├── tools/ # MCP tool implementations
|
|
210
|
+
└── luhmann.ts # ID generation + sorting
|
|
211
|
+
templates/ # Copied to user vault on init
|
|
212
|
+
├── claude/skills/ # 9 SKILL.md files
|
|
213
|
+
├── claude/agents/ # zk-analyzer agent
|
|
214
|
+
├── vault-folders/ # Default folder structure + note templates
|
|
215
|
+
└── CLAUDE.md.template # Project instructions
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Requirements
|
|
219
|
+
|
|
220
|
+
- Node.js ≥ 18
|
|
221
|
+
- [Claude Code](https://claude.ai/code)
|
|
222
|
+
- [Obsidian](https://obsidian.md/) (for viewing/editing notes)
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry: init, update, serve subcommands.
|
|
4
|
+
*/
|
|
5
|
+
import { resolve } from "node:path";
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const command = args[0];
|
|
8
|
+
async function main() {
|
|
9
|
+
switch (command) {
|
|
10
|
+
case "init": {
|
|
11
|
+
const { runWizard } = await import("../init/wizard.js");
|
|
12
|
+
const { scaffold } = await import("../init/scaffold.js");
|
|
13
|
+
const answers = await runWizard(process.cwd());
|
|
14
|
+
scaffold(answers);
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
case "update": {
|
|
18
|
+
const { update } = await import("../init/updater.js");
|
|
19
|
+
const vaultFlag = args.indexOf("--vault");
|
|
20
|
+
const vaultPath = vaultFlag >= 0 ? args[vaultFlag + 1] : ".";
|
|
21
|
+
update(vaultPath);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
case "serve": {
|
|
25
|
+
const { startServer } = await import("../server/index.js");
|
|
26
|
+
const vaultFlag = args.indexOf("--vault");
|
|
27
|
+
const vaultPath = vaultFlag >= 0 ? args[vaultFlag + 1] : ".";
|
|
28
|
+
await startServer(resolve(vaultPath));
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
default:
|
|
32
|
+
console.log(`obsidian-zk — Obsidian Zettelkasten MCP Server
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
obsidian-zk init Interactive setup wizard
|
|
36
|
+
obsidian-zk update Sync templates & run migrations
|
|
37
|
+
obsidian-zk serve --vault . Start MCP server (called by Claude Code)
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
--vault PATH Vault path (default: current directory)
|
|
41
|
+
`);
|
|
42
|
+
process.exit(command ? 1 : 0);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
main().catch((err) => {
|
|
46
|
+
console.error(err);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA;;GAEG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;AAExB,KAAK,UAAU,IAAI;IACjB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;YACxD,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC/C,QAAQ,CAAC,OAAO,CAAC,CAAC;YAClB,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACtD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC7D,MAAM,CAAC,SAAS,CAAC,CAAC;YAClB,MAAM;QACR,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC7D,MAAM,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;YACtC,MAAM;QACR,CAAC;QAED;YACE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;CASjB,CAAC,CAAC;YACG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database connection + indexing.
|
|
3
|
+
*/
|
|
4
|
+
import Database from "better-sqlite3";
|
|
5
|
+
export declare class ZkDatabase {
|
|
6
|
+
db: Database.Database;
|
|
7
|
+
vaultRoot: string;
|
|
8
|
+
constructor(vaultRoot: string);
|
|
9
|
+
reindex(): {
|
|
10
|
+
added: number;
|
|
11
|
+
updated: number;
|
|
12
|
+
removed: number;
|
|
13
|
+
};
|
|
14
|
+
getNoteByPath(relPath: string): any;
|
|
15
|
+
getNoteById(zkId: string): any;
|
|
16
|
+
getNotesByType(type: string): any[];
|
|
17
|
+
getNotesByStatus(status: string): any[];
|
|
18
|
+
getNotesByFolder(folder: string): any[];
|
|
19
|
+
listNotes(filters: {
|
|
20
|
+
type?: string;
|
|
21
|
+
status?: string;
|
|
22
|
+
folder?: string;
|
|
23
|
+
}): any[];
|
|
24
|
+
getAllZkIds(): Map<string, {
|
|
25
|
+
path: string;
|
|
26
|
+
title: string;
|
|
27
|
+
}>;
|
|
28
|
+
getUnprocessed(type?: string): any[];
|
|
29
|
+
getOrphans(folder?: string): any[];
|
|
30
|
+
getLinksFrom(relPath: string): any[];
|
|
31
|
+
getLinksTo(title: string): any[];
|
|
32
|
+
findConnections(notePath: string): {
|
|
33
|
+
path: string;
|
|
34
|
+
title: string;
|
|
35
|
+
score: number;
|
|
36
|
+
reasons: string[];
|
|
37
|
+
summary: string;
|
|
38
|
+
type: string;
|
|
39
|
+
}[];
|
|
40
|
+
getStats(): {
|
|
41
|
+
total: any;
|
|
42
|
+
byType: any[];
|
|
43
|
+
byStatus: any[];
|
|
44
|
+
linkCount: any;
|
|
45
|
+
lastIndex: any;
|
|
46
|
+
};
|
|
47
|
+
close(): void;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAQtC,qBAAa,UAAU;IACrB,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;gBAEN,SAAS,EAAE,MAAM;IAW7B,OAAO,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IA6E9D,aAAa,CAAC,OAAO,EAAE,MAAM,GACkD,GAAG;IAGlF,WAAW,CAAC,IAAI,EAAE,MAAM,GACqD,GAAG;IAGhF,cAAc,CAAC,IAAI,EAAE,MAAM,GACiD,GAAG,EAAE;IAGjF,gBAAgB,CAAC,MAAM,EAAE,MAAM,GACiD,GAAG,EAAE;IAGrF,gBAAgB,CAAC,MAAM,EAAE,MAAM,GACiD,GAAG,EAAE;IAGrF,SAAS,CAAC,OAAO,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAOtB,GAAG,EAAE;IAGrD,WAAW,IAAI,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAO3D,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAKoB,GAAG,EAAE;IAGrD,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAUsB,GAAG,EAAE;IAGrD,YAAY,CAAC,OAAO,EAAE,MAAM,GACqD,GAAG,EAAE;IAGtF,UAAU,CAAC,KAAK,EAAE,MAAM,GACuD,GAAG,EAAE;IAGpF,eAAe,CAAC,QAAQ,EAAE,MAAM;cAQJ,MAAM;eAAS,MAAM;eAAS,MAAM;iBAAW,MAAM,EAAE;iBAAW,MAAM;cAAQ,MAAM;;IA2BlH,QAAQ;;;;;;;IASR,KAAK;CAGN"}
|
package/dist/db/index.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database connection + indexing.
|
|
3
|
+
*/
|
|
4
|
+
import Database from "better-sqlite3";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { readFileSync, existsSync, mkdirSync } from "node:fs";
|
|
7
|
+
import { join, dirname, basename } from "node:path";
|
|
8
|
+
import { CREATE_TABLES, SCHEMA_VERSION } from "./schema.js";
|
|
9
|
+
import { scanVault } from "../vault/scanner.js";
|
|
10
|
+
import { parseFrontmatter, getBody, getTags, getWikilinks } from "../vault/parser.js";
|
|
11
|
+
export class ZkDatabase {
|
|
12
|
+
db;
|
|
13
|
+
vaultRoot;
|
|
14
|
+
constructor(vaultRoot) {
|
|
15
|
+
this.vaultRoot = vaultRoot;
|
|
16
|
+
const dbDir = join(vaultRoot, ".zk");
|
|
17
|
+
if (!existsSync(dbDir))
|
|
18
|
+
mkdirSync(dbDir, { recursive: true });
|
|
19
|
+
const dbPath = join(dbDir, "zettelkasten.db");
|
|
20
|
+
this.db = new Database(dbPath);
|
|
21
|
+
this.db.pragma("journal_mode = WAL");
|
|
22
|
+
this.db.exec(CREATE_TABLES);
|
|
23
|
+
this.db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run("schema_version", String(SCHEMA_VERSION));
|
|
24
|
+
}
|
|
25
|
+
reindex() {
|
|
26
|
+
const notes = scanVault(this.vaultRoot);
|
|
27
|
+
const currentPaths = new Set(notes.map((n) => n.relPath));
|
|
28
|
+
let added = 0, updated = 0, removed = 0;
|
|
29
|
+
// Remove deleted notes
|
|
30
|
+
const dbPaths = this.db.prepare("SELECT path FROM notes").all();
|
|
31
|
+
const removePaths = dbPaths.filter((r) => !currentPaths.has(r.path));
|
|
32
|
+
const deleteNote = this.db.prepare("DELETE FROM notes WHERE path = ?");
|
|
33
|
+
const deleteLinks = this.db.prepare("DELETE FROM links WHERE source = ?");
|
|
34
|
+
for (const { path } of removePaths) {
|
|
35
|
+
deleteNote.run(path);
|
|
36
|
+
deleteLinks.run(path);
|
|
37
|
+
removed++;
|
|
38
|
+
}
|
|
39
|
+
// Upsert notes
|
|
40
|
+
const getHash = this.db.prepare("SELECT content_hash FROM notes WHERE path = ?");
|
|
41
|
+
const upsert = this.db.prepare(`
|
|
42
|
+
INSERT OR REPLACE INTO notes (path, title, zk_id, type, status, folder, tags, summary, created, modified, content_hash)
|
|
43
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
44
|
+
`);
|
|
45
|
+
const insertLink = this.db.prepare("INSERT OR REPLACE INTO links (source, target, link_type) VALUES (?, ?, ?)");
|
|
46
|
+
const transaction = this.db.transaction(() => {
|
|
47
|
+
for (const note of notes) {
|
|
48
|
+
const fullPath = join(this.vaultRoot, note.relPath);
|
|
49
|
+
let content;
|
|
50
|
+
try {
|
|
51
|
+
content = readFileSync(fullPath, "utf-8");
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const hash = createHash("md5").update(content).digest("hex");
|
|
57
|
+
const existing = getHash.get(note.relPath);
|
|
58
|
+
if (existing?.content_hash === hash)
|
|
59
|
+
continue;
|
|
60
|
+
const fm = parseFrontmatter(fullPath);
|
|
61
|
+
const body = getBody(fullPath);
|
|
62
|
+
const title = basename(note.relPath, ".md");
|
|
63
|
+
const folder = dirname(note.relPath).split("/")[0] || "";
|
|
64
|
+
const tags = getTags(fm);
|
|
65
|
+
const summary = body.trim().slice(0, 200);
|
|
66
|
+
upsert.run(note.relPath, title, fm.zk_id || null, fm.type || null, fm.status || null, folder, JSON.stringify(tags), summary, fm.date || null, fm.last_modified || null, hash);
|
|
67
|
+
// Update links
|
|
68
|
+
deleteLinks.run(note.relPath);
|
|
69
|
+
const wikilinks = getWikilinks(fullPath);
|
|
70
|
+
for (const target of wikilinks) {
|
|
71
|
+
insertLink.run(note.relPath, target, null);
|
|
72
|
+
}
|
|
73
|
+
if (existing)
|
|
74
|
+
updated++;
|
|
75
|
+
else
|
|
76
|
+
added++;
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
transaction();
|
|
80
|
+
this.db.prepare("INSERT OR REPLACE INTO meta (key, value) VALUES (?, ?)").run("last_index", new Date().toISOString());
|
|
81
|
+
return { added, updated, removed };
|
|
82
|
+
}
|
|
83
|
+
getNoteByPath(relPath) {
|
|
84
|
+
return this.db.prepare("SELECT * FROM notes WHERE path = ?").get(relPath);
|
|
85
|
+
}
|
|
86
|
+
getNoteById(zkId) {
|
|
87
|
+
return this.db.prepare("SELECT * FROM notes WHERE zk_id = ?").get(zkId);
|
|
88
|
+
}
|
|
89
|
+
getNotesByType(type) {
|
|
90
|
+
return this.db.prepare("SELECT * FROM notes WHERE type = ?").all(type);
|
|
91
|
+
}
|
|
92
|
+
getNotesByStatus(status) {
|
|
93
|
+
return this.db.prepare("SELECT * FROM notes WHERE status = ?").all(status);
|
|
94
|
+
}
|
|
95
|
+
getNotesByFolder(folder) {
|
|
96
|
+
return this.db.prepare("SELECT * FROM notes WHERE folder = ?").all(folder);
|
|
97
|
+
}
|
|
98
|
+
listNotes(filters) {
|
|
99
|
+
let sql = "SELECT * FROM notes WHERE 1=1";
|
|
100
|
+
const params = [];
|
|
101
|
+
if (filters.type) {
|
|
102
|
+
sql += " AND type = ?";
|
|
103
|
+
params.push(filters.type);
|
|
104
|
+
}
|
|
105
|
+
if (filters.status) {
|
|
106
|
+
sql += " AND status = ?";
|
|
107
|
+
params.push(filters.status);
|
|
108
|
+
}
|
|
109
|
+
if (filters.folder) {
|
|
110
|
+
sql += " AND folder = ?";
|
|
111
|
+
params.push(filters.folder);
|
|
112
|
+
}
|
|
113
|
+
sql += " ORDER BY path";
|
|
114
|
+
return this.db.prepare(sql).all(...params);
|
|
115
|
+
}
|
|
116
|
+
getAllZkIds() {
|
|
117
|
+
const rows = this.db.prepare("SELECT zk_id, path, title FROM notes WHERE zk_id IS NOT NULL AND zk_id != ''").all();
|
|
118
|
+
const map = new Map();
|
|
119
|
+
for (const r of rows)
|
|
120
|
+
map.set(r.zk_id, { path: r.path, title: r.title });
|
|
121
|
+
return map;
|
|
122
|
+
}
|
|
123
|
+
getUnprocessed(type) {
|
|
124
|
+
let sql = "SELECT * FROM notes WHERE status IN ('unprocessed', 'draft')";
|
|
125
|
+
const params = [];
|
|
126
|
+
if (type) {
|
|
127
|
+
sql += " AND type = ?";
|
|
128
|
+
params.push(type);
|
|
129
|
+
}
|
|
130
|
+
sql += " ORDER BY folder, path";
|
|
131
|
+
return this.db.prepare(sql).all(...params);
|
|
132
|
+
}
|
|
133
|
+
getOrphans(folder) {
|
|
134
|
+
// Notes with no incoming links
|
|
135
|
+
let sql = `
|
|
136
|
+
SELECT n.* FROM notes n
|
|
137
|
+
LEFT JOIN links l ON l.target = n.title
|
|
138
|
+
WHERE l.target IS NULL
|
|
139
|
+
`;
|
|
140
|
+
const params = [];
|
|
141
|
+
if (folder) {
|
|
142
|
+
sql += " AND n.folder = ?";
|
|
143
|
+
params.push(folder);
|
|
144
|
+
}
|
|
145
|
+
sql += " ORDER BY n.path";
|
|
146
|
+
return this.db.prepare(sql).all(...params);
|
|
147
|
+
}
|
|
148
|
+
getLinksFrom(relPath) {
|
|
149
|
+
return this.db.prepare("SELECT * FROM links WHERE source = ?").all(relPath);
|
|
150
|
+
}
|
|
151
|
+
getLinksTo(title) {
|
|
152
|
+
return this.db.prepare("SELECT * FROM links WHERE target = ?").all(title);
|
|
153
|
+
}
|
|
154
|
+
findConnections(notePath) {
|
|
155
|
+
const note = this.getNoteByPath(notePath);
|
|
156
|
+
if (!note)
|
|
157
|
+
return [];
|
|
158
|
+
const noteTags = JSON.parse(note.tags || "[]");
|
|
159
|
+
const noteTitle = note.title;
|
|
160
|
+
const existingLinks = new Set(this.getLinksFrom(notePath).map((l) => l.target));
|
|
161
|
+
const allNotes = this.db.prepare("SELECT * FROM notes WHERE path != ?").all(notePath);
|
|
162
|
+
const candidates = [];
|
|
163
|
+
for (const other of allNotes) {
|
|
164
|
+
if (existingLinks.has(other.title))
|
|
165
|
+
continue;
|
|
166
|
+
let score = 0;
|
|
167
|
+
const reasons = [];
|
|
168
|
+
// Shared tags
|
|
169
|
+
const otherTags = JSON.parse(other.tags || "[]");
|
|
170
|
+
const shared = noteTags.filter((t) => otherTags.includes(t));
|
|
171
|
+
score += shared.length * 2;
|
|
172
|
+
reasons.push(...shared.map((t) => `tag:${t}`));
|
|
173
|
+
// Keyword overlap in summary
|
|
174
|
+
const noteWords = new Set((note.summary || "").toLowerCase().match(/[а-яієїґa-z]{4,}/g) ?? []);
|
|
175
|
+
const otherWords = (other.summary || "").toLowerCase().match(/[а-яієїґa-z]{4,}/g) ?? [];
|
|
176
|
+
const kwMatches = otherWords.filter((w) => noteWords.has(w)).length;
|
|
177
|
+
score += kwMatches;
|
|
178
|
+
if (score >= 2) {
|
|
179
|
+
candidates.push({ path: other.path, title: other.title, score, reasons, summary: other.summary || "", type: other.type || "" });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return candidates.sort((a, b) => b.score - a.score).slice(0, 15);
|
|
183
|
+
}
|
|
184
|
+
getStats() {
|
|
185
|
+
const total = this.db.prepare("SELECT COUNT(*) as c FROM notes").get().c;
|
|
186
|
+
const byType = this.db.prepare("SELECT type, COUNT(*) as c FROM notes GROUP BY type").all();
|
|
187
|
+
const byStatus = this.db.prepare("SELECT status, COUNT(*) as c FROM notes GROUP BY status").all();
|
|
188
|
+
const linkCount = this.db.prepare("SELECT COUNT(*) as c FROM links").get().c;
|
|
189
|
+
const lastIndex = this.db.prepare("SELECT value FROM meta WHERE key = 'last_index'").get()?.value;
|
|
190
|
+
return { total, byType, byStatus, linkCount, lastIndex };
|
|
191
|
+
}
|
|
192
|
+
close() {
|
|
193
|
+
this.db.close();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/db/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite schema + migrations.
|
|
3
|
+
*/
|
|
4
|
+
export declare const SCHEMA_VERSION = 1;
|
|
5
|
+
export declare const CREATE_TABLES = "\nCREATE TABLE IF NOT EXISTS notes (\n path TEXT PRIMARY KEY,\n title TEXT,\n zk_id TEXT,\n type TEXT,\n status TEXT,\n folder TEXT,\n tags TEXT,\n summary TEXT,\n created TEXT,\n modified TEXT,\n content_hash TEXT\n);\n\nCREATE TABLE IF NOT EXISTS links (\n source TEXT NOT NULL,\n target TEXT NOT NULL,\n link_type TEXT,\n PRIMARY KEY (source, target)\n);\n\nCREATE TABLE IF NOT EXISTS meta (\n key TEXT PRIMARY KEY,\n value TEXT\n);\n\nCREATE INDEX IF NOT EXISTS idx_notes_type ON notes(type);\nCREATE INDEX IF NOT EXISTS idx_notes_status ON notes(status);\nCREATE INDEX IF NOT EXISTS idx_notes_zk_id ON notes(zk_id);\nCREATE INDEX IF NOT EXISTS idx_links_target ON links(target);\n";
|
|
6
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,eAAO,MAAM,aAAa,msBA+BzB,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite schema + migrations.
|
|
3
|
+
*/
|
|
4
|
+
export const SCHEMA_VERSION = 1;
|
|
5
|
+
export const CREATE_TABLES = `
|
|
6
|
+
CREATE TABLE IF NOT EXISTS notes (
|
|
7
|
+
path TEXT PRIMARY KEY,
|
|
8
|
+
title TEXT,
|
|
9
|
+
zk_id TEXT,
|
|
10
|
+
type TEXT,
|
|
11
|
+
status TEXT,
|
|
12
|
+
folder TEXT,
|
|
13
|
+
tags TEXT,
|
|
14
|
+
summary TEXT,
|
|
15
|
+
created TEXT,
|
|
16
|
+
modified TEXT,
|
|
17
|
+
content_hash TEXT
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
CREATE TABLE IF NOT EXISTS links (
|
|
21
|
+
source TEXT NOT NULL,
|
|
22
|
+
target TEXT NOT NULL,
|
|
23
|
+
link_type TEXT,
|
|
24
|
+
PRIMARY KEY (source, target)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE IF NOT EXISTS meta (
|
|
28
|
+
key TEXT PRIMARY KEY,
|
|
29
|
+
value TEXT
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
CREATE INDEX IF NOT EXISTS idx_notes_type ON notes(type);
|
|
33
|
+
CREATE INDEX IF NOT EXISTS idx_notes_status ON notes(status);
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_notes_zk_id ON notes(zk_id);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_links_target ON links(target);
|
|
36
|
+
`;
|
|
37
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+B5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/init/scaffold.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA4BjD,wBAAgB,QAAQ,CAAC,OAAO,EAAE,aAAa,QA+F9C"}
|