@cardmagic/notes 1.0.1
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/LICENSE +21 -0
- package/README.md +207 -0
- package/dist/attachments.d.ts +10 -0
- package/dist/attachments.d.ts.map +1 -0
- package/dist/attachments.js +122 -0
- package/dist/attachments.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +180 -0
- package/dist/cli.js.map +1 -0
- package/dist/formatter.d.ts +12 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +129 -0
- package/dist/formatter.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer.d.ts +24 -0
- package/dist/indexer.d.ts.map +1 -0
- package/dist/indexer.js +483 -0
- package/dist/indexer.js.map +1 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +274 -0
- package/dist/mcp.js.map +1 -0
- package/dist/searcher.d.ts +17 -0
- package/dist/searcher.d.ts.map +1 -0
- package/dist/searcher.js +203 -0
- package/dist/searcher.js.map +1 -0
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Lucas Carlson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# @cardmagic/notes
|
|
2
|
+
|
|
3
|
+
CLI and MCP server to search and browse Apple Notes with fuzzy matching.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Fuzzy search** - Find notes even with typos using MiniSearch
|
|
8
|
+
- **Full-text search** - Searches note titles, snippets, and body content
|
|
9
|
+
- **PDF text extraction** - Automatically extracts and indexes text from PDF attachments
|
|
10
|
+
- **Folder browsing** - List and filter notes by folder
|
|
11
|
+
- **Fast indexing** - SQLite FTS5 + MiniSearch for quick searches across thousands of notes
|
|
12
|
+
- **Dual mode** - Use as CLI tool or MCP server for Claude Code integration
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Install globally
|
|
18
|
+
npm install -g @cardmagic/notes
|
|
19
|
+
|
|
20
|
+
# Or with pnpm
|
|
21
|
+
pnpm add -g @cardmagic/notes
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Requirements
|
|
25
|
+
|
|
26
|
+
- **macOS** - Reads from Apple Notes database
|
|
27
|
+
- **Full Disk Access** - Terminal/IDE needs access to `~/Library/Group Containers/`
|
|
28
|
+
- **pdftotext** (optional) - For PDF text extraction
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Install pdftotext for PDF support
|
|
32
|
+
brew install poppler
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## CLI Usage
|
|
36
|
+
|
|
37
|
+
### Search notes
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Fuzzy search
|
|
41
|
+
notes search "recipe chocolate"
|
|
42
|
+
|
|
43
|
+
# Filter by folder
|
|
44
|
+
notes search "taxes" --folder "2024"
|
|
45
|
+
|
|
46
|
+
# Limit results
|
|
47
|
+
notes search "meeting" --limit 5
|
|
48
|
+
|
|
49
|
+
# Filter by date
|
|
50
|
+
notes search "project" --after 2024-01-01
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Browse notes
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Recent notes
|
|
57
|
+
notes recent
|
|
58
|
+
notes recent --limit 10
|
|
59
|
+
|
|
60
|
+
# List all folders
|
|
61
|
+
notes folders
|
|
62
|
+
|
|
63
|
+
# Notes in a specific folder
|
|
64
|
+
notes folder "Recipes"
|
|
65
|
+
notes folder "Work" --limit 20
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Read a note
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Get note ID from search results, then read full content
|
|
72
|
+
notes read 12345
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Manage index
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Show index statistics
|
|
79
|
+
notes stats
|
|
80
|
+
|
|
81
|
+
# Update index (incremental - only processes changed notes)
|
|
82
|
+
notes index
|
|
83
|
+
|
|
84
|
+
# Force full rebuild
|
|
85
|
+
notes index --force
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The index uses **incremental updates** by default:
|
|
89
|
+
- Tracks modification timestamps to detect changed notes
|
|
90
|
+
- Only reprocesses notes modified since last index
|
|
91
|
+
- Detects and removes deleted notes
|
|
92
|
+
- Much faster than full rebuild for small changes
|
|
93
|
+
|
|
94
|
+
## MCP Server
|
|
95
|
+
|
|
96
|
+
Run as an MCP server for Claude Code integration:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
notes --mcp
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Available Tools
|
|
103
|
+
|
|
104
|
+
| Tool | Description |
|
|
105
|
+
|------|-------------|
|
|
106
|
+
| `search_notes` | Fuzzy search through notes |
|
|
107
|
+
| `recent_notes` | Get recently modified notes |
|
|
108
|
+
| `read_note` | Read full note content by ID |
|
|
109
|
+
| `list_folders` | List all folders with note counts |
|
|
110
|
+
| `notes_in_folder` | List notes in a specific folder |
|
|
111
|
+
| `get_note_stats` | Get index statistics |
|
|
112
|
+
|
|
113
|
+
### Claude Code Configuration
|
|
114
|
+
|
|
115
|
+
Add to your MCP settings:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"mcpServers": {
|
|
120
|
+
"notes": {
|
|
121
|
+
"command": "notes",
|
|
122
|
+
"args": ["--mcp"]
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## PDF Text Extraction
|
|
129
|
+
|
|
130
|
+
PDF attachments in Notes are automatically extracted and indexed when:
|
|
131
|
+
|
|
132
|
+
1. **pdftotext is installed** - `brew install poppler`
|
|
133
|
+
2. **PDF has been viewed** - Notes caches PDFs locally when opened
|
|
134
|
+
|
|
135
|
+
The extracted text is appended to the note body, making PDF content fully searchable.
|
|
136
|
+
|
|
137
|
+
### How it works
|
|
138
|
+
|
|
139
|
+
- PDFs are cached at `~/Library/Group Containers/group.com.apple.notes/Library/Caches/Paper/`
|
|
140
|
+
- Each PDF bundle contains the file in `Assets.bundle/`
|
|
141
|
+
- Text is extracted using `pdftotext` and indexed with the parent note
|
|
142
|
+
|
|
143
|
+
### Limitations
|
|
144
|
+
|
|
145
|
+
- PDFs stored only in iCloud (never opened locally) won't be indexed
|
|
146
|
+
- Password-protected PDFs cannot be extracted
|
|
147
|
+
- Scanned PDFs without OCR won't have searchable text
|
|
148
|
+
|
|
149
|
+
## Data Locations
|
|
150
|
+
|
|
151
|
+
| Data | Path |
|
|
152
|
+
|------|------|
|
|
153
|
+
| Notes database | `~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite` |
|
|
154
|
+
| PDF cache | `~/Library/Group Containers/group.com.apple.notes/Library/Caches/Paper/` |
|
|
155
|
+
| Search index | `~/.notes/index.db` |
|
|
156
|
+
| Fuzzy index | `~/.notes/fuzzy.json` |
|
|
157
|
+
| Stats | `~/.notes/stats.json` |
|
|
158
|
+
|
|
159
|
+
## Development
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Clone and install
|
|
163
|
+
git clone https://github.com/cardmagic/notes
|
|
164
|
+
cd notes
|
|
165
|
+
pnpm install
|
|
166
|
+
|
|
167
|
+
# Build
|
|
168
|
+
pnpm build
|
|
169
|
+
|
|
170
|
+
# Watch mode
|
|
171
|
+
pnpm dev
|
|
172
|
+
|
|
173
|
+
# Link globally for testing
|
|
174
|
+
pnpm link --global
|
|
175
|
+
|
|
176
|
+
# Type check
|
|
177
|
+
pnpm typecheck
|
|
178
|
+
|
|
179
|
+
# Lint
|
|
180
|
+
pnpm lint
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Project Structure
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
src/
|
|
187
|
+
├── index.ts # Entry point - routes to CLI or MCP
|
|
188
|
+
├── cli.ts # Commander-based CLI
|
|
189
|
+
├── mcp.ts # MCP server implementation
|
|
190
|
+
├── indexer.ts # Builds search indexes from Notes database
|
|
191
|
+
├── searcher.ts # Query engine with fuzzy matching
|
|
192
|
+
├── attachments.ts # PDF text extraction
|
|
193
|
+
├── formatter.ts # Terminal output formatting
|
|
194
|
+
└── types.ts # TypeScript types and utilities
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Privacy
|
|
198
|
+
|
|
199
|
+
This tool only reads your local Notes database. No data is sent externally. The search index is stored locally in `~/.notes/`.
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT
|
|
204
|
+
|
|
205
|
+
## Author
|
|
206
|
+
|
|
207
|
+
Lucas Carlson
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get text from all PDF attachments in Notes
|
|
3
|
+
* Returns a map of noteId (database ID) -> extracted PDF text
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractAllPdfText(): Map<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Get the note key format used in extractAllPdfText
|
|
8
|
+
*/
|
|
9
|
+
export declare function getNoteKey(noteDbId: number): string;
|
|
10
|
+
//# sourceMappingURL=attachments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"AAsGA;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAkCvD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readdirSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import Database from 'better-sqlite3';
|
|
6
|
+
const PAPER_CACHE_DIR = join(homedir(), 'Library/Group Containers/group.com.apple.notes/Library/Caches/Paper');
|
|
7
|
+
const NOTES_DB_PATH = join(homedir(), 'Library/Group Containers/group.com.apple.notes/NoteStore.sqlite');
|
|
8
|
+
/**
|
|
9
|
+
* Get PDF attachments from the Notes database
|
|
10
|
+
*/
|
|
11
|
+
function getPdfAttachmentsFromDb() {
|
|
12
|
+
try {
|
|
13
|
+
const db = new Database(NOTES_DB_PATH, { readonly: true });
|
|
14
|
+
const query = db.prepare(`
|
|
15
|
+
SELECT
|
|
16
|
+
a.Z_PK as attachmentId,
|
|
17
|
+
a.ZNOTE as noteId,
|
|
18
|
+
n.ZTITLE1 as noteTitle,
|
|
19
|
+
a.ZFILENAME as attachmentName,
|
|
20
|
+
a.ZIDENTIFIER as contentIdentifier,
|
|
21
|
+
a.ZTYPEUTI as typeUti
|
|
22
|
+
FROM ZICCLOUDSYNCINGOBJECT a
|
|
23
|
+
JOIN ZICCLOUDSYNCINGOBJECT n ON a.ZNOTE = n.Z_PK
|
|
24
|
+
WHERE a.Z_ENT = 5
|
|
25
|
+
AND (a.ZTYPEUTI = 'com.adobe.pdf' OR a.ZTYPEUTI = 'com.apple.paper.doc.pdf')
|
|
26
|
+
AND a.ZIDENTIFIER IS NOT NULL
|
|
27
|
+
`);
|
|
28
|
+
const rows = query.all();
|
|
29
|
+
db.close();
|
|
30
|
+
return rows;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Find the cached file for a given UUID in the Paper cache
|
|
38
|
+
*/
|
|
39
|
+
function findCachedFile(uuid) {
|
|
40
|
+
const bundlePath = join(PAPER_CACHE_DIR, `${uuid}.bundle`, 'Assets.bundle');
|
|
41
|
+
if (!existsSync(bundlePath)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const files = readdirSync(bundlePath);
|
|
46
|
+
for (const file of files) {
|
|
47
|
+
const filePath = join(bundlePath, file);
|
|
48
|
+
// Check if it's a PDF
|
|
49
|
+
try {
|
|
50
|
+
const result = execSync(`file "${filePath}"`, { encoding: 'utf-8', timeout: 5000 });
|
|
51
|
+
if (result.includes('PDF')) {
|
|
52
|
+
return filePath;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extract text from a PDF file using pdftotext
|
|
67
|
+
*/
|
|
68
|
+
function extractPdfText(pdfPath) {
|
|
69
|
+
try {
|
|
70
|
+
const text = execSync(`pdftotext "${pdfPath}" - 2>/dev/null`, {
|
|
71
|
+
encoding: 'utf-8',
|
|
72
|
+
timeout: 30000,
|
|
73
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
74
|
+
});
|
|
75
|
+
return text.trim();
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return '';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get text from all PDF attachments in Notes
|
|
83
|
+
* Returns a map of noteId (database ID) -> extracted PDF text
|
|
84
|
+
*/
|
|
85
|
+
export function extractAllPdfText() {
|
|
86
|
+
const pdfTextByNote = new Map();
|
|
87
|
+
// Check if pdftotext is available
|
|
88
|
+
try {
|
|
89
|
+
execSync('which pdftotext', { encoding: 'utf-8' });
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// pdftotext not installed, skip PDF extraction
|
|
93
|
+
return pdfTextByNote;
|
|
94
|
+
}
|
|
95
|
+
const attachments = getPdfAttachmentsFromDb();
|
|
96
|
+
for (const att of attachments) {
|
|
97
|
+
if (!att.contentIdentifier)
|
|
98
|
+
continue;
|
|
99
|
+
const cachedPath = findCachedFile(att.contentIdentifier);
|
|
100
|
+
if (cachedPath) {
|
|
101
|
+
const text = extractPdfText(cachedPath);
|
|
102
|
+
if (text) {
|
|
103
|
+
const noteKey = `note_${att.noteId}`;
|
|
104
|
+
const attachmentLabel = att.attachmentName || 'PDF Attachment';
|
|
105
|
+
// Append to existing text for this note (note may have multiple PDFs)
|
|
106
|
+
const existing = pdfTextByNote.get(noteKey) || '';
|
|
107
|
+
const combined = existing
|
|
108
|
+
? `${existing}\n\n--- ${attachmentLabel} ---\n\n${text}`
|
|
109
|
+
: `--- ${attachmentLabel} ---\n\n${text}`;
|
|
110
|
+
pdfTextByNote.set(noteKey, combined);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return pdfTextByNote;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get the note key format used in extractAllPdfText
|
|
118
|
+
*/
|
|
119
|
+
export function getNoteKey(noteDbId) {
|
|
120
|
+
return `note_${noteDbId}`;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=attachments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.js","sourceRoot":"","sources":["../src/attachments.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAgMA,wBAAgB,MAAM,IAAI,IAAI,CAE7B"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf-8'));
|
|
7
|
+
import { buildIndex, updateIndex, indexNeedsRebuild } from './indexer.js';
|
|
8
|
+
import { searchNotes, getRecentNotes, getNoteById, getNotesInFolder, listFolders, getNoteStats, closeConnections, } from './searcher.js';
|
|
9
|
+
import { formatSearchResults, formatNoteList, formatFolderList, formatStats, formatIndexProgress, formatNote, } from './formatter.js';
|
|
10
|
+
const program = new Command();
|
|
11
|
+
program
|
|
12
|
+
.name('notes')
|
|
13
|
+
.description('CLI tool to search and browse Apple Notes')
|
|
14
|
+
.version(pkg.version);
|
|
15
|
+
program
|
|
16
|
+
.command('search <query>')
|
|
17
|
+
.description('Search notes with fuzzy matching')
|
|
18
|
+
.option('-l, --limit <number>', 'Maximum results to return', '20')
|
|
19
|
+
.option('-f, --folder <name>', 'Filter by folder name')
|
|
20
|
+
.option('-a, --after <date>', 'Only notes modified after this date (YYYY-MM-DD)')
|
|
21
|
+
.action(async (query, options) => {
|
|
22
|
+
try {
|
|
23
|
+
const results = await searchNotes(query, {
|
|
24
|
+
limit: parseInt(options.limit, 10),
|
|
25
|
+
folder: options.folder,
|
|
26
|
+
after: options.after,
|
|
27
|
+
});
|
|
28
|
+
console.log(formatSearchResults(results, query));
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error('Error:', error.message);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
closeConnections();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
program
|
|
39
|
+
.command('recent')
|
|
40
|
+
.description('Show most recent notes')
|
|
41
|
+
.option('-l, --limit <number>', 'Maximum notes to return', '20')
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
try {
|
|
44
|
+
const notes = await getRecentNotes(parseInt(options.limit, 10));
|
|
45
|
+
console.log(formatNoteList(notes));
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
console.error('Error:', error.message);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
closeConnections();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
program
|
|
56
|
+
.command('read <id>')
|
|
57
|
+
.description('Read a note by ID')
|
|
58
|
+
.action(async (id) => {
|
|
59
|
+
try {
|
|
60
|
+
const noteId = parseInt(id, 10);
|
|
61
|
+
if (isNaN(noteId)) {
|
|
62
|
+
console.error('Invalid note ID');
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
const note = await getNoteById(noteId);
|
|
66
|
+
if (!note) {
|
|
67
|
+
console.error('Note not found');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
console.log(formatNote(note, true));
|
|
71
|
+
if (note.body) {
|
|
72
|
+
console.log('\n--- Content ---\n');
|
|
73
|
+
console.log(note.body);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error('Error:', error.message);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
closeConnections();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
program
|
|
85
|
+
.command('folder <name>')
|
|
86
|
+
.description('List notes in a folder')
|
|
87
|
+
.option('-l, --limit <number>', 'Maximum notes to return', '50')
|
|
88
|
+
.option('-a, --after <date>', 'Only notes modified after this date (YYYY-MM-DD)')
|
|
89
|
+
.action(async (name, options) => {
|
|
90
|
+
try {
|
|
91
|
+
const notes = await getNotesInFolder(name, {
|
|
92
|
+
limit: parseInt(options.limit, 10),
|
|
93
|
+
after: options.after,
|
|
94
|
+
});
|
|
95
|
+
console.log(formatNoteList(notes));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.error('Error:', error.message);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
closeConnections();
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
program
|
|
106
|
+
.command('folders')
|
|
107
|
+
.description('List all folders')
|
|
108
|
+
.option('-l, --limit <number>', 'Maximum folders to return', '50')
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
try {
|
|
111
|
+
const folders = await listFolders(parseInt(options.limit, 10));
|
|
112
|
+
console.log(formatFolderList(folders));
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error('Error:', error.message);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
closeConnections();
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
program
|
|
123
|
+
.command('index')
|
|
124
|
+
.description('Update or rebuild the search index')
|
|
125
|
+
.option('-f, --force', 'Force full rebuild (default is incremental update)')
|
|
126
|
+
.action(async (options) => {
|
|
127
|
+
try {
|
|
128
|
+
if (options.force) {
|
|
129
|
+
console.log('Rebuilding entire index...\n');
|
|
130
|
+
const stats = await buildIndex(progress => {
|
|
131
|
+
const msg = progress.message ? ` ${progress.message}` : '';
|
|
132
|
+
process.stdout.write('\r' + formatIndexProgress(progress).split('\n').join(' | ') + msg);
|
|
133
|
+
});
|
|
134
|
+
console.log('\n\n');
|
|
135
|
+
console.log(formatStats(stats));
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (!indexNeedsRebuild()) {
|
|
139
|
+
console.log('Index is up to date.');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
console.log('Updating index...\n');
|
|
143
|
+
const result = await updateIndex(progress => {
|
|
144
|
+
const msg = progress.message ? ` ${progress.message}` : '';
|
|
145
|
+
process.stdout.write('\r' + formatIndexProgress(progress).split('\n').join(' | ') + msg);
|
|
146
|
+
});
|
|
147
|
+
console.log('\n\n');
|
|
148
|
+
console.log(`Updated ${result.updated} notes, removed ${result.deleted} deleted notes.`);
|
|
149
|
+
console.log(formatStats(result));
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error('Error:', error.message);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
program
|
|
158
|
+
.command('stats')
|
|
159
|
+
.description('Show index statistics')
|
|
160
|
+
.action(async () => {
|
|
161
|
+
try {
|
|
162
|
+
const stats = await getNoteStats();
|
|
163
|
+
if (!stats) {
|
|
164
|
+
console.log('No index found. Run "notes index" first.');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
console.log(formatStats(stats));
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
console.error('Error:', error.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
closeConnections();
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
export function runCli() {
|
|
178
|
+
program.parse(process.argv);
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IndexedNote, SearchResult, FolderInfo, IndexStats } from './types.js';
|
|
2
|
+
import type { IndexProgress } from './indexer.js';
|
|
3
|
+
export declare function formatDate(unixTimestamp: number): string;
|
|
4
|
+
export declare function formatNote(note: IndexedNote, showBody?: boolean): string;
|
|
5
|
+
export declare function formatSearchResult(result: SearchResult, query: string): string;
|
|
6
|
+
export declare function formatFolder(folder: FolderInfo): string;
|
|
7
|
+
export declare function formatStats(stats: IndexStats): string;
|
|
8
|
+
export declare function formatIndexProgress(progress: IndexProgress): string;
|
|
9
|
+
export declare function formatNoteList(notes: IndexedNote[]): string;
|
|
10
|
+
export declare function formatSearchResults(results: SearchResult[], query: string): string;
|
|
11
|
+
export declare function formatFolderList(folders: FolderInfo[]): string;
|
|
12
|
+
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../src/formatter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAWxD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,UAAQ,GAAG,MAAM,CA0BtE;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,GACZ,MAAM,CA2BR;AAkBD,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAOvD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAiBrD;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAyBnE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,CAM3D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAM9D"}
|