From 65094d3df637739e7aa940757c9c3c2c1fd0cb11 Mon Sep 17 00:00:00 2001 From: nicwands Date: Fri, 8 May 2026 13:34:43 -0400 Subject: [PATCH] stop tracking out folder --- out/main/index.js | 604 ------------------------------------------ out/preload/index.mjs | 54 ---- 2 files changed, 658 deletions(-) delete mode 100644 out/main/index.js delete mode 100644 out/preload/index.mjs diff --git a/out/main/index.js b/out/main/index.js deleted file mode 100644 index c393b0b..0000000 --- a/out/main/index.js +++ /dev/null @@ -1,604 +0,0 @@ -import "dotenv/config"; -import { electronApp, optimizer, is } from "@electron-toolkit/utils"; -import { app, ipcMain, BrowserWindow, dialog, shell } from "electron"; -import filesystemPlugin from "@takerofnotes/plugin-filesystem"; -import supabasePlugin from "@takerofnotes/plugin-supabase"; -import s3Plugin from "@takerofnotes/plugin-s3"; -import postgresPlugin from "@takerofnotes/plugin-postgre-sql"; -import Ajv from "ajv"; -import sodium from "libsodium-wrappers"; -import { v4 } from "uuid"; -import { Index } from "flexsearch"; -import { join } from "path"; -import __cjs_mod__ from "node:module"; -const __filename = import.meta.filename; -const __dirname = import.meta.dirname; -const require2 = __cjs_mod__.createRequire(import.meta.url); -const createPluginManager = (registry) => { - let activePluginId = null; - let adapter = null; - return { - listPlugins() { - return registry.list(); - }, - getPlugin(pluginId) { - return registry.get(pluginId); - }, - getAdapter(pluginId, adapterConfig = {}) { - const plugin = registry.get(pluginId); - if (!plugin) { - throw new Error(`Plugin not found: ${pluginId}`); - } - return plugin.createAdapter(adapterConfig); - }, - setActivePlugin(pluginId, adapterConfig = {}) { - activePluginId = pluginId; - adapter = this.getAdapter(pluginId, adapterConfig); - return adapter; - }, - async testPlugin(pluginId, adapterConfig = {}) { - const plugin = registry.get(pluginId); - if (!plugin) { - throw new Error(`Plugin not found: ${pluginId}`); - } - const adapter2 = this.getAdapter(pluginId, adapterConfig); - await adapter2.init(); - return await adapter2.testConnection(); - }, - getActiveAdapter() { - return adapter; - }, - getActivePluginId() { - return activePluginId; - } - }; -}; -class PluginRegistry { - constructor() { - this.plugins = /* @__PURE__ */ new Map(); - } - register(plugin) { - if (!plugin.id) { - throw new Error("Plugin must have an id"); - } - this.plugins.set(plugin.id, plugin); - } - get(id) { - return this.plugins.get(id); - } - list() { - return Array.from(this.plugins.values()).map((plugin) => ({ - id: plugin.id, - name: plugin.name, - description: plugin.description, - configSchema: plugin.configSchema - })); - } -} -const ajv = new Ajv({ allErrors: true, strict: false }); -const getDefaultConfig = () => { - return { - activeAdapter: "browser", - theme: "dark", - enableBlackletter: "true", - openNotesInNewWindow: "true" - }; -}; -const CONFIG_SCHEMA = { - type: "object", - properties: { - activeAdapter: { type: "string" }, - theme: { type: "string", enum: ["dark", "light"] }, - encryptionKey: { type: "string" }, - adapters: { type: "object" } - }, - required: ["activeAdapter"], - additionalProperties: true -}; -const validateConfig = ajv.compile(CONFIG_SCHEMA); -const convertSchemaToJson = (schemaArray) => { - const properties = {}; - const required = []; - for (const field of schemaArray) { - properties[field.key] = { type: "string" }; - if (field.required) { - required.push(field.key); - } - } - return { - type: "object", - properties, - required, - additionalProperties: false - }; -}; -const validateAdapterConfigs = (adapters, pluginManager) => { - if (!adapters || !pluginManager) return { valid: true, errors: [] }; - const errors = []; - for (const [adapterId, adapterConfig] of Object.entries(adapters)) { - const plugin = pluginManager.getPlugin(adapterId); - if (!plugin?.configSchema) continue; - const schema = convertSchemaToJson(plugin.configSchema); - const validate = ajv.compile(schema); - const valid = validate(adapterConfig); - if (!valid) { - const adapterErrors = validate.errors.map( - (e) => `${adapterId}${e.instancePath}: ${e.message}` - ); - errors.push(...adapterErrors); - } - } - return { valid: errors.length === 0, errors }; -}; -const createConfigManager = (storage, pluginManager) => { - let config = null; - return { - async loadConfig() { - if (config) return config; - const stored = await storage.load(); - config = stored || getDefaultConfig(); - if (!stored) { - await storage.save(config); - } - return config; - }, - getConfig() { - return config; - }, - async setConfig(newConfig) { - const valid = validateConfig(newConfig); - if (!valid) { - const errors = validateConfig.errors.map((e) => `${e.instancePath || "root"}: ${e.message}`).join("; "); - throw new Error(`Config validation failed: ${errors}`); - } - const adapterValidation = validateAdapterConfigs( - newConfig.adapters, - pluginManager - ); - if (!adapterValidation.valid) { - throw new Error( - `Adapter config validation failed: ${adapterValidation.errors.join("; ")}` - ); - } - config = newConfig; - await storage.save(newConfig); - }, - async refreshConfig() { - config = await storage.load(); - } - }; -}; -class NotesAPI { - constructor(adapter, encryptionKey = null) { - if (!adapter) { - throw new Error("NotesAPI requires a storage adapter"); - } - this.adapter = adapter; - this.notesCache = /* @__PURE__ */ new Map(); - this.categories = /* @__PURE__ */ new Set(); - this.encryptionKey = encryptionKey; - this._sodiumReady = false; - this._decryptionFailures = []; - this.index = new Index({ - tokenize: "forward" - }); - } - async _initSodium() { - if (!this._sodiumReady) { - await sodium.ready; - this._sodiumReady = true; - } - } - _hexToUint8Array(hex) { - return Uint8Array.from( - hex.match(/.{1,2}/g), - (byte) => parseInt(byte, 16) - ); - } - _concatUint8Arrays(a, b) { - const result = new Uint8Array(a.length + b.length); - result.set(a, 0); - result.set(b, a.length); - return result; - } - _uint8ArrayToBase64(bytes) { - return btoa(String.fromCharCode(...bytes)); - } - _base64ToUint8Array(base64) { - const binary = atob(base64); - return Uint8Array.from(binary, (c) => c.charCodeAt(0)); - } - _encrypt(note) { - if (!this.encryptionKey) { - throw new Error("Encryption key not set"); - } - const key = this._hexToUint8Array(this.encryptionKey); - if (key.length !== 32) { - throw new Error( - "Encryption key must be 64 hex characters (32 bytes)" - ); - } - const nonce = sodium.randombytes_buf(sodium.crypto_secretbox_NONCEBYTES); - const message = JSON.stringify(note); - const ciphertext = sodium.crypto_secretbox_easy( - new TextEncoder().encode(message), - nonce, - key - ); - const combined = this._concatUint8Arrays(nonce, ciphertext); - return this._uint8ArrayToBase64(combined); - } - _decrypt(encryptedData) { - if (!this.encryptionKey) { - throw new Error("Encryption key not set"); - } - const key = this._hexToUint8Array(this.encryptionKey); - if (key.length !== 32) { - throw new Error( - "Encryption key must be 64 hex characters (32 bytes)" - ); - } - let combined; - try { - combined = this._base64ToUint8Array(encryptedData); - } catch (e) { - throw new Error("Invalid encrypted data: not valid base64"); - } - if (combined.length < sodium.crypto_secretbox_NONCEBYTES + sodium.crypto_secretbox_MACBYTES) { - throw new Error("Invalid encrypted data: too short"); - } - const nonce = combined.slice(0, sodium.crypto_secretbox_NONCEBYTES); - const ciphertext = combined.slice(sodium.crypto_secretbox_NONCEBYTES); - let decrypted; - try { - decrypted = sodium.crypto_secretbox_open_easy( - ciphertext, - nonce, - key - ); - } catch (e) { - throw new Error("Decryption failed: wrong key or corrupted data"); - } - if (!decrypted) { - throw new Error("Decryption failed: no data returned"); - } - const decryptedStr = new TextDecoder().decode(decrypted); - try { - return JSON.parse(decryptedStr); - } catch (e) { - throw new Error( - `Decryption succeeded but invalid JSON: ${decryptedStr}` - ); - } - } - async init() { - await this._initSodium(); - await this.adapter.init(); - this.notesCache.clear(); - this.categories.clear(); - this._decryptionFailures = []; - const encryptedNotes = await this.adapter.getAll(); - for (const encryptedNote of encryptedNotes) { - const noteId = encryptedNote.id || "unknown"; - try { - const note = this._decrypt(encryptedNote.data || encryptedNote); - this.notesCache.set(note.id, note); - if (note.category) { - this.categories.add(note.category); - } - const searchText = note.plainText || this._extractPlainText(note.content); - this.index.add(note.id, note.title + "\n" + searchText); - } catch (error) { - console.error("Failed to decrypt note:", error); - this._decryptionFailures.push(noteId); - } - } - } - getDecryptionFailures() { - return [...this._decryptionFailures]; - } - _extractPlainText(content) { - if (!content) return ""; - if (typeof content === "string") return content; - const extractText = (node) => { - if (typeof node === "string") return node; - if (!node || !node.content) return ""; - return node.content.map(extractText).join(" "); - }; - return extractText(content); - } - getCategories() { - return Array.from(this.categories).sort(); - } - getCategoryNotes(categoryName = null) { - return Array.from(this.notesCache.values()).filter((n) => n.category === categoryName).sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt)).map((n) => ({ ...n })); - } - getNote(id) { - const note = this.notesCache.get(id); - console.log(this.notesCache, id); - return note ? { ...note } : null; - } - async createNote(metadata = {}, content = "", plainText = "") { - const id = v4(); - const now = (/* @__PURE__ */ new Date()).toISOString(); - const note = { - id, - title: metadata.title || "Untitled", - category: metadata.category || null, - createdAt: now, - updatedAt: now, - content, - plainText - }; - const encryptedNote = { - id: note.id, - data: this._encrypt(note) - }; - this.notesCache.set(id, note); - if (note.category) { - this.categories.add(note.category); - } - this.index.add(id, note.title + "\n" + plainText); - await this.adapter.create(encryptedNote); - return note; - } - async deleteNote(id) { - const note = this.notesCache.get(id); - const category = note?.category; - await this.adapter.delete(id); - this.notesCache.delete(id); - this.index.remove(id); - if (category) { - const notesWithCategory = Array.from( - this.notesCache.values() - ).filter((n) => n.category === category); - if (notesWithCategory.length === 0) { - this.categories.delete(category); - } - } - if (this._decryptionFailures.includes(id)) { - this._decryptionFailures = this._decryptionFailures.filter( - (id2) => id2 !== id2 - ); - } - } - async updateNote(id, updates = {}) { - const note = this.notesCache.get(id); - if (!note) throw new Error("Note not found"); - const allowedFields = ["title", "category", "content", "plainText"]; - for (const key of Object.keys(updates)) { - if (!allowedFields.includes(key)) { - throw new Error(`Invalid update field: ${key}`); - } - } - const oldCategory = note.category; - const updatedNote = { - ...note, - ...updates, - updatedAt: (/* @__PURE__ */ new Date()).toISOString() - }; - const encryptedNote = { - id: updatedNote.id, - data: this._encrypt(updatedNote) - }; - this.notesCache.set(id, updatedNote); - if (updates.category !== void 0) { - if (oldCategory) { - const notesWithOldCategory = Array.from( - this.notesCache.values() - ).filter((n) => n.category === oldCategory && n.id !== id); - if (notesWithOldCategory.length === 0) { - this.categories.delete(oldCategory); - } - } - if (updatedNote.category) { - this.categories.add(updatedNote.category); - } - } - const searchText = updatedNote.plainText || this._extractPlainText(updatedNote.content); - this.index.update(id, updatedNote.title + "\n" + searchText); - await this.adapter.update(encryptedNote); - return updatedNote; - } - search(query) { - const ids = this.index.search(query, { - limit: 50, - suggest: true - }); - return ids.map((id) => this.notesCache.get(id)); - } -} -const generateEncryptionKey = () => { - const array = new Uint8Array(32); - crypto.getRandomValues(array); - return Array.from(array).map((b) => b.toString(16).padStart(2, "0")).join(""); -}; -const initPluginManager = (runtime, plugins) => { - const registry = new PluginRegistry(); - for (const plugin of plugins) { - registry.register(plugin); - } - return createPluginManager(registry); -}; -const initConfigManager = async (runtime, pluginManager) => { - let storage; - { - const { createNodeStorage } = await import("./NodeStorage-B8VFtrTS.js"); - const filesystemPlugin2 = (await import("@takerofnotes/plugin-filesystem")).default; - storage = createNodeStorage(filesystemPlugin2); - } - return createConfigManager(storage, pluginManager); -}; -const initializeCore = async (runtime, { plugins }) => { - const pluginManager = initPluginManager(runtime, plugins); - const configManager = await initConfigManager(runtime, pluginManager); - const config = await configManager.loadConfig(); - const activeConfig = config.adapters?.[config.activeAdapter] || {}; - pluginManager.setActivePlugin(config.activeAdapter, activeConfig); - let notesAPI = null; - let initPromise = null; - const getNotesAPI = async () => { - console.log("getNotesAPI before: ", notesAPI); - if (notesAPI) return notesAPI; - if (!initPromise) { - initPromise = (async () => { - const latestConfig = await configManager.loadConfig(); - let encryptionKey = latestConfig?.encryptionKey; - if (!encryptionKey) { - encryptionKey = generateEncryptionKey(); - await configManager.setConfig({ - ...latestConfig, - encryptionKey - }); - } - const pluginId = latestConfig?.activeAdapter || "filesystem"; - const adapterConfig = latestConfig?.adapters?.[pluginId] || {}; - const adapter = pluginManager.getAdapter( - pluginId, - adapterConfig - ); - notesAPI = new NotesAPI(adapter, encryptionKey); - await notesAPI.init(); - console.log("getNotesAPI after: ", notesAPI); - return notesAPI; - })(); - } - return initPromise; - }; - return { - runtime, - pluginManager, - configManager, - getNotesAPI - }; -}; -const DEFAULT_WINDOW_SIZE = { width: 354, height: 549 }; -const DEFAULT_MOVE_WINDOW_SIZE = { width: 708, height: 549 }; -const preloadPath = join(__dirname, "../preload/index.mjs"); -const rendererPath = join(__dirname, "../renderer/index.html"); -function createWindow() { - const mainWindow = new BrowserWindow({ - width: DEFAULT_WINDOW_SIZE.width, - height: DEFAULT_WINDOW_SIZE.height, - show: false, - autoHideMenuBar: true, - webPreferences: { - preload: preloadPath, - sandbox: false - } - }); - mainWindow.on("ready-to-show", () => { - mainWindow.show(); - }); - mainWindow.webContents.setWindowOpenHandler((details) => { - shell.openExternal(details.url); - return { action: "deny" }; - }); - if (is.dev && process.env["ELECTRON_RENDERER_URL"]) { - mainWindow.loadURL(process.env["ELECTRON_RENDERER_URL"]); - } else { - mainWindow.loadFile(rendererPath); - } -} -function createNoteWindow(noteId) { - const noteWindow = new BrowserWindow({ - width: DEFAULT_WINDOW_SIZE.width, - height: DEFAULT_WINDOW_SIZE.height, - autoHideMenuBar: true, - webPreferences: { - preload: preloadPath, - contextIsolation: true, - nodeIntegration: false, - sandbox: false - } - }); - if (is.dev && process.env["ELECTRON_RENDERER_URL"]) { - noteWindow.loadURL( - `${process.env["ELECTRON_RENDERER_URL"]}/#/note/${noteId}` - ); - } else { - noteWindow.loadFile(rendererPath, { - hash: `/note/${noteId}` - }); - } -} -app.whenReady().then(async () => { - ipcMain.on("open-note-window", (_, noteId) => { - createNoteWindow(noteId); - }); - const broadcastNoteChange = (event, data) => { - BrowserWindow.getAllWindows().forEach((win) => { - win.webContents.send(event, data); - }); - }; - const { pluginManager, configManager } = await initializeCore( - "electron-main", - { - plugins: [ - filesystemPlugin, - s3Plugin, - postgresPlugin, - supabasePlugin - ] - } - ); - ipcMain.handle("pluginManager:call", async (_, method, ...args) => { - const methodCall = await pluginManager[method](...args); - if (method === "setActivePlugin") { - broadcastNoteChange("plugin-changed"); - } - return methodCall; - }); - ipcMain.handle("configManager:call", async (_, method, ...args) => { - return await configManager[method](...args); - }); - ipcMain.handle("adapter:call", async (_, method, ...args) => { - const adapter = pluginManager.getActiveAdapter(); - if (!adapter[method]) { - throw new Error(`Invalid adapter method: ${method}`); - } - return await adapter[method](...args); - }); - ipcMain.on("note-changed", (_, event, data) => { - broadcastNoteChange(event, data); - }); - ipcMain.handle("move-opened", (_) => { - const activeWindow = BrowserWindow.getFocusedWindow(); - const windowSize = activeWindow.getSize(); - if (windowSize[0] < DEFAULT_MOVE_WINDOW_SIZE.width) { - activeWindow.setSize( - DEFAULT_MOVE_WINDOW_SIZE.width, - DEFAULT_MOVE_WINDOW_SIZE.height - ); - } - }); - ipcMain.handle("move-closed", (_) => { - const activeWindow = BrowserWindow.getFocusedWindow(); - const windowSize = activeWindow.getSize(); - if (windowSize[0] === 708) { - activeWindow.setSize( - DEFAULT_WINDOW_SIZE.width, - DEFAULT_WINDOW_SIZE.height - ); - } - }); - ipcMain.handle("open-directory-dialog", async () => { - const result = await dialog.showOpenDialog({ - properties: ["openDirectory"] - }); - return result.canceled ? null : result.filePaths[0]; - }); - electronApp.setAppUserModelId("com.electron"); - app.on("browser-window-created", (_, window) => { - optimizer.watchWindowShortcuts(window); - }); - createWindow(); - app.on("activate", function() { - if (BrowserWindow.getAllWindows().length === 0) createWindow(); - }); -}); -app.on("window-all-closed", () => { - if (process.platform !== "darwin") { - app.quit(); - } -}); diff --git a/out/preload/index.mjs b/out/preload/index.mjs deleted file mode 100644 index 1cc75f7..0000000 --- a/out/preload/index.mjs +++ /dev/null @@ -1,54 +0,0 @@ -import { contextBridge, ipcRenderer } from "electron"; -const api = { - pluginManagerCall: (method, ...args) => ipcRenderer.invoke( - "pluginManager:call", - method, - ...args.length ? args : [] - ), - configManagerCall: (method, ...args) => ipcRenderer.invoke( - "configManager:call", - method, - ...args.length ? args : [] - ), - adapterCall: (method, ...args) => ipcRenderer.invoke( - "adapter:call", - method, - ...args.length ? args : [] - ), - openNoteWindow: (noteId) => { - ipcRenderer.send("open-note-window", noteId); - }, - onNoteCreated: (callback) => { - ipcRenderer.on("note-created", (_, data) => callback(data)); - }, - onNoteUpdated: (callback) => { - ipcRenderer.on("note-updated", (_, data) => callback(data)); - }, - onNoteDeleted: (callback) => { - ipcRenderer.on("note-deleted", (_, data) => callback(data)); - }, - onPluginChanged: (callback) => { - ipcRenderer.on("plugin-changed", (_, data) => callback(data)); - }, - notifyNoteChanged: (event, data) => { - ipcRenderer.send("note-changed", event, data); - }, - moveOpened: () => { - ipcRenderer.invoke("move-opened"); - }, - moveClosed: () => { - ipcRenderer.invoke("move-closed"); - }, - openDirectoryDialog: () => { - return ipcRenderer.invoke("open-directory-dialog"); - } -}; -if (process.contextIsolated) { - try { - contextBridge.exposeInMainWorld("api", api); - } catch (error) { - console.error(error); - } -} else { - window.api = api; -}