notes.ts•4.88 kB
import { run } from '@jxa/run';
type Note = {
name: string;
content: string;
};
type CreateNoteResult = {
success: boolean;
note?: Note;
message?: string;
folderName?: string;
usedDefaultFolder?: boolean;
};
async function getAllNotes() {
const notes: Note[] = await run(() => {
const Notes = Application('Notes');
const notes = Notes.notes();
return notes.map((note: any) => ({
name: note.name(),
content: note.plaintext()
}));
});
return notes;
}
async function findNote(searchText: string) {
const notes: Note[] = await run((searchText: string) => {
const Notes = Application('Notes');
const notes = Notes.notes.whose({_or: [
{name: {_contains: searchText}},
{plaintext: {_contains: searchText}}
]})()
return notes.length > 0 ? notes.map((note: any) => ({
name: note.name(),
content: note.plaintext()
})) : [];
}, searchText);
if (notes.length === 0) {
const allNotes = await getAllNotes();
const closestMatch = allNotes.find(({name}) =>
name.toLowerCase().includes(searchText.toLowerCase())
);
return closestMatch ? [{
name: closestMatch.name,
content: closestMatch.content
}] : [];
}
return notes;
}
async function createNote(title: string, body: string, folderName: string = 'Claude'): Promise<CreateNoteResult> {
try {
// Format the body with proper markdown
const formattedBody = body
.replace(/^(#+)\s+(.+)$/gm, '$1 $2\n') // Add newline after headers
.replace(/^-\s+(.+)$/gm, '\n- $1') // Add newline before list items
.replace(/\n{3,}/g, '\n\n') // Remove excess newlines
.trim();
const result = await run((title: string, body: string, folderName: string) => {
const Notes = Application('Notes');
// Create the note
let targetFolder;
let usedDefaultFolder = false;
let actualFolderName = folderName;
try {
// Try to find the specified folder
const folders = Notes.folders();
for (let i = 0; i < folders.length; i++) {
if (folders[i].name() === folderName) {
targetFolder = folders[i];
break;
}
}
// If the specified folder doesn't exist
if (!targetFolder) {
if (folderName === 'Claude') {
// Try to create the Claude folder if it doesn't exist
Notes.make({new: 'folder', withProperties: {name: 'Claude'}});
usedDefaultFolder = true;
// Find it again after creation
const updatedFolders = Notes.folders();
for (let i = 0; i < updatedFolders.length; i++) {
if (updatedFolders[i].name() === 'Claude') {
targetFolder = updatedFolders[i];
break;
}
}
} else {
throw new Error(`Folder "${folderName}" not found`);
}
}
// Create the note in the specified folder or default folder
let newNote;
if (targetFolder) {
newNote = Notes.make({new: 'note', withProperties: {name: title, body: body}, at: targetFolder});
actualFolderName = folderName;
} else {
// Fall back to default folder
newNote = Notes.make({new: 'note', withProperties: {name: title, body: body}});
actualFolderName = 'Default';
}
return {
success: true,
note: {
name: title,
content: body
},
folderName: actualFolderName,
usedDefaultFolder: usedDefaultFolder
};
} catch (scriptError) {
throw new Error(`AppleScript error: ${scriptError.message || String(scriptError)}`);
}
}, title, formattedBody, folderName);
return result;
} catch (error) {
return {
success: false,
message: `Failed to create note: ${error instanceof Error ? error.message : String(error)}`
};
}
}
export default { getAllNotes, findNote, createNote };