mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-10 23:39:03 +00:00
- cli can no longer detect where config will be, so config-related cli prompts have been removed - should avoid file conflicts and enable portable builds - users can export their data in the more readable .json format from the profiles section of the menu and no longer require direct access to the config file
158 lines
5.0 KiB
JavaScript
158 lines
5.0 KiB
JavaScript
/**
|
|
* notion-enhancer
|
|
* (c) 2022 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
|
|
* (https://notion-enhancer.github.io/) under the MIT license
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
const fs = require("fs"),
|
|
os = require("os"),
|
|
path = require("path"),
|
|
notionRequire = (target) => require(`../../../${target}`);
|
|
|
|
const platform = process.platform,
|
|
enhancerVersion = require("notion-enhancer/package.json").version,
|
|
enhancerUrl = (target) =>
|
|
`notion://www.notion.so/__notion-enhancer/${target.replace(/^\//, "")}`;
|
|
|
|
const readFile = (file) => {
|
|
// prettier-ignore
|
|
file = file.replace(/^https:\/\/www\.notion\.so\//, "notion://www.notion.so/");
|
|
const useFetch = file.startsWith("http") || file.startsWith("notion://");
|
|
if (useFetch) return fetch(file).then((res) => res.text());
|
|
return fs.readFileSync(path.resolve(`${__dirname}/../${file}`), "utf-8");
|
|
},
|
|
readJson = (file) => {
|
|
// prettier-ignore
|
|
file = file.replace(/^https:\/\/www\.notion\.so\//, "notion://www.notion.so/");
|
|
const useFetch = file.startsWith("http") || file.startsWith("notion://");
|
|
if (useFetch) return fetch(file).then((res) => res.json());
|
|
return require(path.resolve(`${__dirname}/../${file}`));
|
|
},
|
|
reloadApp = () => {
|
|
const { app, ipcRenderer } = require("electron");
|
|
if (app) {
|
|
const args = process.argv.slice(1).filter((arg) => arg !== "--startup");
|
|
app.relaunch({ args });
|
|
app.exit();
|
|
} else ipcRenderer.send("notion-enhancer", "reload-app");
|
|
};
|
|
|
|
const sendMessage = (channel, message) => {
|
|
const { ipcRenderer } = require("electron");
|
|
ipcRenderer.send(channel, message);
|
|
},
|
|
onMessage = (channel, listener) => {
|
|
const { ipcRenderer } = require("electron");
|
|
ipcRenderer.on(channel, listener);
|
|
};
|
|
|
|
let __db, __statements, __transactions;
|
|
const initDatabase = (namespace, fallbacks = {}) => {
|
|
if (Array.isArray(namespace)) namespace = namespace.join("__");
|
|
namespace = namespace ? namespace + "__" : "";
|
|
const namespaceify = (key) =>
|
|
key.startsWith(namespace) ? key : namespace + key;
|
|
|
|
__db ??= (async () => {
|
|
const { app, ipcRenderer } = require("electron"),
|
|
isRenderer = process?.type === "renderer",
|
|
userData = isRenderer
|
|
? await ipcRenderer.invoke("notion-enhancer", "get-user-data-folder")
|
|
: app.getPath("userData");
|
|
|
|
const table = "settings",
|
|
sqlite = require("better-sqlite3"),
|
|
db = sqlite(path.resolve(`${userData}/notion-enhancer.db`)),
|
|
init = db.prepare(`CREATE TABLE IF NOT EXISTS ${table} (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT
|
|
)`);
|
|
init.run();
|
|
|
|
// schema:
|
|
// - ("profileIds") = $profileId[]
|
|
// - ("activeProfile") -> $profileId
|
|
// - $profileId: ("profileName") -> string
|
|
// - $profileId__enabledMods: ($modId) -> boolean
|
|
// - $profileId__$modId: ($optionKey) -> value
|
|
__statements = {
|
|
insert: db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`),
|
|
update: db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`),
|
|
select: db.prepare(`SELECT * FROM ${table} WHERE key = ? LIMIT 1`),
|
|
delete: db.prepare(`DELETE FROM ${table} WHERE key = ?`),
|
|
dump: db.prepare(`SELECT * FROM ${table}`),
|
|
};
|
|
__transactions = {
|
|
remove: db.transaction((arr) => {
|
|
arr.forEach((key) => __statements.delete.run(key));
|
|
}),
|
|
set: db.transaction((obj) => {
|
|
for (const key in obj) {
|
|
if (__statements.select.get(key) === undefined) {
|
|
__statements.insert.run(key, obj[key]);
|
|
} else __statements.update.run(obj[key], key);
|
|
}
|
|
}),
|
|
};
|
|
return db;
|
|
})();
|
|
|
|
return {
|
|
get: async (key) => {
|
|
await __db;
|
|
const fallback = fallbacks[key];
|
|
key = namespaceify(key);
|
|
try {
|
|
const value = JSON.parse(__statements.select.get(key)?.value);
|
|
return value ?? fallback;
|
|
} catch {}
|
|
return fallback;
|
|
},
|
|
set: async (key, value) => {
|
|
await __db;
|
|
key = namespaceify(key);
|
|
value = JSON.stringify(value);
|
|
__transactions.set({ [key]: value });
|
|
return true;
|
|
},
|
|
remove: async (keys) => {
|
|
await __db;
|
|
keys = Array.isArray(keys) ? keys : [keys];
|
|
keys = keys.map(namespaceify);
|
|
__transactions.remove(keys);
|
|
return true;
|
|
},
|
|
export: async () => {
|
|
await __db;
|
|
const entries = __statements.dump
|
|
.all()
|
|
.filter(({ key }) => key.startsWith(namespace))
|
|
.map(({ key, value }) => [key.slice(namespace.length), value]);
|
|
return Object.fromEntries(entries);
|
|
},
|
|
import: async (obj) => {
|
|
await __db;
|
|
const entries = Object.entries(obj) //
|
|
.map(([key, value]) => [key.slice(namespace.length), value]);
|
|
__transactions.set(Object.fromEntries(entries));
|
|
return true;
|
|
},
|
|
};
|
|
};
|
|
|
|
globalThis.__enhancerApi ??= {};
|
|
Object.assign(globalThis.__enhancerApi, {
|
|
notionRequire,
|
|
platform,
|
|
enhancerUrl,
|
|
enhancerVersion,
|
|
readFile,
|
|
readJson,
|
|
reloadApp,
|
|
sendMessage,
|
|
onMessage,
|
|
initDatabase,
|
|
});
|