notes API cleanup

This commit is contained in:
nicwands
2026-02-23 14:19:07 -05:00
parent 7a670aab92
commit 9ac9d73b0a
8 changed files with 48 additions and 64 deletions

View File

@@ -61,9 +61,7 @@ const updateNote = (relativePath, content) => {
fs.writeFileSync(fullPath, content, "utf-8"); fs.writeFileSync(fullPath, content, "utf-8");
return true; return true;
}; };
const notes = { const notesAPI = {
ensureBaseDir,
sanitizeRelativePath,
readAllNotesRecursive, readAllNotesRecursive,
createNote, createNote,
createDirectory, createDirectory,
@@ -123,27 +121,18 @@ electron.app.whenReady().then(() => {
utils.optimizer.watchWindowShortcuts(window); utils.optimizer.watchWindowShortcuts(window);
}); });
createWindow(); createWindow();
notes.ensureBaseDir(); ensureBaseDir();
electron.app.on("activate", function() { electron.app.on("activate", function() {
if (electron.BrowserWindow.getAllWindows().length === 0) createWindow(); if (electron.BrowserWindow.getAllWindows().length === 0) createWindow();
}); });
electron.ipcMain.on("open-note-window", (_, noteId) => { electron.ipcMain.on("open-note-window", (_, noteId) => {
createNoteWindow(noteId); createNoteWindow(noteId);
}); });
electron.ipcMain.handle("notes:list", () => { electron.ipcMain.handle("notesAPI:call", async (_, method, args) => {
return notes.readAllNotesRecursive(); if (!notesAPI[method]) {
}); throw new Error("Invalid method");
electron.ipcMain.handle("notes:create", (_, { path: path2, content }) => { }
return notes.createNote(path2, content); return notesAPI[method](...args);
});
electron.ipcMain.handle("notes:createDir", (_, path2) => {
return notes.createDirectory(path2);
});
electron.ipcMain.handle("notes:read", (_, path2) => {
return notes.readNote(path2);
});
electron.ipcMain.handle("notes:update", (_, { path: path2, content }) => {
return notes.updateNote(path2, content);
}); });
}); });
electron.app.on("window-all-closed", () => { electron.app.on("window-all-closed", () => {

View File

@@ -3,16 +3,15 @@ const electron = require("electron");
const api = { const api = {
openNoteWindow: (noteId) => { openNoteWindow: (noteId) => {
electron.ipcRenderer.send("open-note-window", noteId); electron.ipcRenderer.send("open-note-window", noteId);
}, }
listNotes: () => electron.ipcRenderer.invoke("notes:list"), };
createNote: (path, content) => electron.ipcRenderer.invoke("notes:create", { path, content }), const notesAPI = {
createNoteDir: (path) => electron.ipcRenderer.invoke("notes:createDir", path), call: (method, ...args) => electron.ipcRenderer.invoke("notesAPI:call", method, args)
readNote: (path) => electron.ipcRenderer.invoke("notes:read", path),
updateNote: (path, content) => electron.ipcRenderer.invoke("notes:update", { path, content })
}; };
if (process.contextIsolated) { if (process.contextIsolated) {
try { try {
electron.contextBridge.exposeInMainWorld("api", api); electron.contextBridge.exposeInMainWorld("api", api);
electron.contextBridge.exposeInMainWorld("notesAPI", notesAPI);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }

View File

@@ -1,6 +1,6 @@
import { electronApp, optimizer, is } from '@electron-toolkit/utils' import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import { app, shell, BrowserWindow, ipcMain } from 'electron' import { app, shell, BrowserWindow, ipcMain } from 'electron'
import notes from './notesStorage' import notesAPI, { ensureBaseDir } from './notesAPI'
import { join } from 'path' import { join } from 'path'
const preloadPath = join(__dirname, '../preload/index.js') const preloadPath = join(__dirname, '../preload/index.js')
@@ -78,7 +78,7 @@ app.whenReady().then(() => {
createWindow() createWindow()
// Ensure data directory is present // Ensure data directory is present
notes.ensureBaseDir() ensureBaseDir()
app.on('activate', function () { app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the // On macOS it's common to re-create a window in the app when the
@@ -91,21 +91,12 @@ app.whenReady().then(() => {
createNoteWindow(noteId) createNoteWindow(noteId)
}) })
// File access // Handle calls to Notes API
ipcMain.handle('notes:list', () => { ipcMain.handle('notesAPI:call', async (_, method, args) => {
return notes.readAllNotesRecursive() if (!notesAPI[method]) {
}) throw new Error('Invalid method')
ipcMain.handle('notes:create', (_, { path, content }) => { }
return notes.createNote(path, content) return notesAPI[method](...args)
})
ipcMain.handle('notes:createDir', (_, path) => {
return notes.createDirectory(path)
})
ipcMain.handle('notes:read', (_, path) => {
return notes.readNote(path)
})
ipcMain.handle('notes:update', (_, { path, content }) => {
return notes.updateNote(path, content)
}) })
}) })

View File

@@ -3,14 +3,13 @@ import fs from 'fs'
import { join, relative, dirname } from 'path' import { join, relative, dirname } from 'path'
const BASE_DIR = join(app.getPath('userData'), 'notes-storage') const BASE_DIR = join(app.getPath('userData'), 'notes-storage')
export const ensureBaseDir = () => { export const ensureBaseDir = () => {
if (!fs.existsSync(BASE_DIR)) { if (!fs.existsSync(BASE_DIR)) {
fs.mkdirSync(BASE_DIR, { recursive: true }) fs.mkdirSync(BASE_DIR, { recursive: true })
} }
} }
export const sanitizeRelativePath = (relativePath) => { const sanitizeRelativePath = (relativePath) => {
const resolved = join(BASE_DIR, relativePath) const resolved = join(BASE_DIR, relativePath)
if (!resolved.startsWith(BASE_DIR)) { if (!resolved.startsWith(BASE_DIR)) {
throw new Error('Invalid path') throw new Error('Invalid path')
@@ -18,7 +17,7 @@ export const sanitizeRelativePath = (relativePath) => {
return resolved return resolved
} }
export const readAllNotesRecursive = (dir = BASE_DIR, base = BASE_DIR) => { const readAllNotesRecursive = (dir = BASE_DIR, base = BASE_DIR) => {
const entries = fs.readdirSync(dir, { withFileTypes: true }) const entries = fs.readdirSync(dir, { withFileTypes: true })
let results = [] let results = []
@@ -43,7 +42,7 @@ export const readAllNotesRecursive = (dir = BASE_DIR, base = BASE_DIR) => {
return results return results
} }
export const createNote = (relativePath, content = '') => { const createNote = (relativePath, content = '') => {
const fullPath = sanitizeRelativePath(relativePath) const fullPath = sanitizeRelativePath(relativePath)
fs.mkdirSync(dirname(fullPath), { recursive: true }) fs.mkdirSync(dirname(fullPath), { recursive: true })
@@ -52,13 +51,13 @@ export const createNote = (relativePath, content = '') => {
return true return true
} }
export const createDirectory = (relativePath) => { const createDirectory = (relativePath) => {
const fullPath = sanitizeRelativePath(relativePath) const fullPath = sanitizeRelativePath(relativePath)
fs.mkdirSync(fullPath, { recursive: true }) fs.mkdirSync(fullPath, { recursive: true })
return true return true
} }
export const readNote = (relativePath) => { const readNote = (relativePath) => {
const fullPath = sanitizeRelativePath(relativePath) const fullPath = sanitizeRelativePath(relativePath)
if (!fs.existsSync(fullPath)) { if (!fs.existsSync(fullPath)) {
@@ -68,7 +67,7 @@ export const readNote = (relativePath) => {
return fs.readFileSync(fullPath, 'utf-8') return fs.readFileSync(fullPath, 'utf-8')
} }
export const updateNote = (relativePath, content) => { const updateNote = (relativePath, content) => {
const fullPath = sanitizeRelativePath(relativePath) const fullPath = sanitizeRelativePath(relativePath)
if (!fs.existsSync(fullPath)) { if (!fs.existsSync(fullPath)) {
@@ -81,8 +80,6 @@ export const updateNote = (relativePath, content) => {
} }
export default { export default {
ensureBaseDir,
sanitizeRelativePath,
readAllNotesRecursive, readAllNotesRecursive,
createNote, createNote,
createDirectory, createDirectory,

View File

@@ -5,18 +5,18 @@ const api = {
openNoteWindow: (noteId) => { openNoteWindow: (noteId) => {
ipcRenderer.send('open-note-window', noteId) ipcRenderer.send('open-note-window', noteId)
}, },
listNotes: () => ipcRenderer.invoke('notes:list'), }
createNote: (path, content) =>
ipcRenderer.invoke('notes:create', { path, content }), // Implement notes API
createNoteDir: (path) => ipcRenderer.invoke('notes:createDir', path), const notesAPI = {
readNote: (path) => ipcRenderer.invoke('notes:read', path), call: (method, ...args) =>
updateNote: (path, content) => ipcRenderer.invoke('notesAPI:call', method, args),
ipcRenderer.invoke('notes:update', { path, content }),
} }
if (process.contextIsolated) { if (process.contextIsolated) {
try { try {
contextBridge.exposeInMainWorld('api', api) contextBridge.exposeInMainWorld('api', api)
contextBridge.exposeInMainWorld('notesAPI', notesAPI)
} catch (error) { } catch (error) {
console.error(error) console.error(error)
} }

View File

@@ -8,7 +8,7 @@ export default () => {
const fetchNotes = async () => { const fetchNotes = async () => {
try { try {
loading.value = true loading.value = true
notes.value = await window.api.listNotes() notes.value = await window.notesAPI.call('readAllNotesRecursive')
} catch (err) { } catch (err) {
error.value = err.message error.value = err.message
} finally { } finally {
@@ -17,22 +17,22 @@ export default () => {
} }
const createNote = async (path, content = '') => { const createNote = async (path, content = '') => {
await window.api.createNote(path, content) await window.notesAPI.call('createNote', path, content)
await fetchNotes() await fetchNotes()
} }
const createDirectory = async (path) => { const createDirectory = async (path) => {
await window.api.createNoteDir(path) await window.notesAPI.call('createDirectory', path)
await fetchNotes() await fetchNotes()
} }
const readNote = async (path) => { const readNote = async (path) => {
console.log(path) console.log(path)
return await window.api.readNote(path) return await window.notesAPI.call('readNote', path)
} }
const updateNote = async (path, content) => { const updateNote = async (path, content) => {
return await window.api.updateNote(path, content) return await window.notesAPI.call('updateNote', path, content)
} }
return { return {

View File

@@ -1,6 +1,6 @@
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
export function useOpenNote() { export default () => {
const router = useRouter() const router = useRouter()
function openNote(noteId, options = {}) { function openNote(noteId, options = {}) {

View File

@@ -22,7 +22,9 @@
<script setup> <script setup>
import { format } from 'fecha' import { format } from 'fecha'
import { useOpenNote } from '@/composables/useOpenNote' import useOpenNote from '@/composables/useOpenNote'
import useNotes from '@/composables/useNotes'
import { onMounted } from 'vue'
const capitulum = [ const capitulum = [
{ {
@@ -61,6 +63,12 @@ const summarium = [
] ]
const { openNote } = useOpenNote() const { openNote } = useOpenNote()
const { notes, fetchNotes } = useNotes()
onMounted(async () => {
await fetchNotes()
console.log(notes.value)
})
const formatDate = (date) => { const formatDate = (date) => {
return format(date, 'MM/DD/YYYY') return format(date, 'MM/DD/YYYY')