@vaultctl/core 0.3.1 → 0.4.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.
Files changed (2) hide show
  1. package/README.md +167 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,167 @@
1
+ # @vaultctl/core
2
+
3
+ Core library for structured Obsidian vault operations. Provides frontmatter parsing, wikilink resolution, tag management, search, health checks, and template rendering — all as pure TypeScript with zero CLI dependencies.
4
+
5
+ This is the library package. For the CLI tool, see [`vaultctl`](https://www.npmjs.com/package/vaultctl).
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @vaultctl/core
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```typescript
16
+ import {
17
+ loadVault,
18
+ searchNotes,
19
+ listTags,
20
+ findByTag,
21
+ addTag,
22
+ removeTag,
23
+ renameTag,
24
+ checkHealth,
25
+ listTemplates,
26
+ renderTemplate,
27
+ parseNote,
28
+ safeJoin,
29
+ } from '@vaultctl/core';
30
+
31
+ // Load all notes from a vault
32
+ const notes = await loadVault('/path/to/vault');
33
+
34
+ // Search notes by content and frontmatter
35
+ const results = searchNotes(notes, {
36
+ query: 'meeting notes',
37
+ type: 'project',
38
+ status: 'active',
39
+ tag: 'work',
40
+ });
41
+
42
+ // Tag operations
43
+ const tags = listTags(notes); // all tags with counts
44
+ const tagged = findByTag(notes, 'status/active');
45
+ await addTag('/path/to/vault', '01_Projects/my-project.md', 'priority/high');
46
+ await removeTag('/path/to/vault', '01_Projects/my-project.md', 'priority/high');
47
+ const renamed = await renameTag('/path/to/vault', notes, 'old-tag', 'new-tag');
48
+
49
+ // Health checks
50
+ const issues = await checkHealth('/path/to/vault', notes);
51
+ const linksOnly = await checkHealth('/path/to/vault', notes, ['broken-links']);
52
+
53
+ // Templates
54
+ const templates = await listTemplates('/path/to/vault');
55
+ const content = await renderTemplate('/path/to/vault', 'project', 'My Project');
56
+
57
+ // Parse a single note
58
+ const note = parseNote('/path/to/vault', 'relative/path.md', fileContent);
59
+
60
+ // Safe path joining (prevents path traversal)
61
+ const safePath = safeJoin('/path/to/vault', 'notes/file.md');
62
+ ```
63
+
64
+ ## API
65
+
66
+ ### Vault
67
+
68
+ | Function | Description |
69
+ |----------|-------------|
70
+ | `loadVault(path)` | Load and parse all `.md` files in a vault |
71
+ | `resolveVaultPath(options?)` | Find vault root via flag, env, or directory walk |
72
+ | `safeJoin(vaultPath, relativePath)` | Join paths with traversal protection |
73
+
74
+ ### Search
75
+
76
+ | Function | Description |
77
+ |----------|-------------|
78
+ | `searchNotes(notes, options)` | Filter notes by query, type, status, and/or tag |
79
+
80
+ **`SearchOptions`**: `{ query?, type?, status?, tag? }`
81
+
82
+ ### Tags
83
+
84
+ | Function | Description |
85
+ |----------|-------------|
86
+ | `listTags(notes)` | List all tags with usage counts |
87
+ | `findByTag(notes, tag)` | Find notes containing a tag |
88
+ | `addTag(vault, path, tag)` | Add a tag to a note's frontmatter |
89
+ | `removeTag(vault, path, tag)` | Remove a tag from a note |
90
+ | `renameTag(vault, notes, old, new)` | Rename a tag across the vault |
91
+
92
+ Tags are validated on write — must start with a letter and contain only letters, numbers, hyphens, underscores, or `/` for hierarchy.
93
+
94
+ ### Health
95
+
96
+ | Function | Description |
97
+ |----------|-------------|
98
+ | `checkHealth(vault, notes, checks?)` | Run health checks on the vault |
99
+
100
+ **`CheckName`**: `'broken-links' | 'orphans' | 'stale' | 'frontmatter'`
101
+
102
+ ### Templates
103
+
104
+ | Function | Description |
105
+ |----------|-------------|
106
+ | `listTemplates(vault)` | List available `_templates/tpl-*.md` templates |
107
+ | `renderTemplate(vault, name, title?)` | Render a template with date/title substitution |
108
+
109
+ ### Parsing
110
+
111
+ | Function | Description |
112
+ |----------|-------------|
113
+ | `parseNote(vault, path, content)` | Parse a markdown file into a `Note` object |
114
+ | `parseFrontmatter(content)` | Extract YAML frontmatter |
115
+ | `stringifyFrontmatter(fm, body)` | Serialize frontmatter + body back to markdown |
116
+ | `parseWikilinks(content)` | Extract `[[wikilinks]]` from content |
117
+ | `parseInlineTags(content)` | Extract `#hashtags` from content |
118
+
119
+ ## Types
120
+
121
+ ```typescript
122
+ interface Note {
123
+ path: string;
124
+ filename: string;
125
+ folder: string;
126
+ frontmatter: Frontmatter;
127
+ body: string;
128
+ wikilinks: WikiLink[];
129
+ inlineTags: string[];
130
+ }
131
+
132
+ interface Frontmatter {
133
+ type?: string;
134
+ status?: string;
135
+ tags?: string[];
136
+ created?: string;
137
+ updated?: string;
138
+ [key: string]: unknown;
139
+ }
140
+
141
+ interface WikiLink {
142
+ raw: string;
143
+ target: string;
144
+ alias?: string;
145
+ resolved?: string | null;
146
+ }
147
+
148
+ interface HealthIssue {
149
+ check: string;
150
+ path: string;
151
+ message: string;
152
+ severity: 'error' | 'warning' | 'info';
153
+ }
154
+
155
+ interface VaultStats {
156
+ totalNotes: number;
157
+ notesByType: Record<string, number>;
158
+ notesByStatus: Record<string, number>;
159
+ totalTags: number;
160
+ brokenLinks: number;
161
+ orphanedNotes: number;
162
+ }
163
+ ```
164
+
165
+ ## License
166
+
167
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaultctl/core",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "Core library for structured Obsidian vault operations — frontmatter, wikilinks, tags, search, and health checks",
5
5
  "type": "module",
6
6
  "license": "MIT",