mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-11 15:59:03 +00:00
chore!: store config in electron-defined userData folder instead of home folder
- 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
This commit is contained in:
parent
f61ac3d8d9
commit
f999969c13
28
bin.mjs
28
bin.mjs
@ -13,14 +13,12 @@ import { createRequire } from "node:module";
|
|||||||
import {
|
import {
|
||||||
getAppPath,
|
getAppPath,
|
||||||
getBackupPath,
|
getBackupPath,
|
||||||
getConfigPath,
|
|
||||||
checkEnhancementVersion,
|
checkEnhancementVersion,
|
||||||
setNotionPath,
|
setNotionPath,
|
||||||
unpackApp,
|
unpackApp,
|
||||||
applyEnhancements,
|
applyEnhancements,
|
||||||
takeBackup,
|
takeBackup,
|
||||||
restoreBackup,
|
restoreBackup,
|
||||||
removeConfig,
|
|
||||||
} from "./scripts/enhance-desktop-app.mjs";
|
} from "./scripts/enhance-desktop-app.mjs";
|
||||||
import { existsSync } from "node:fs";
|
import { existsSync } from "node:fs";
|
||||||
const nodeRequire = createRequire(import.meta.url),
|
const nodeRequire = createRequire(import.meta.url),
|
||||||
@ -218,7 +216,6 @@ try {
|
|||||||
|
|
||||||
const appPath = getAppPath(),
|
const appPath = getAppPath(),
|
||||||
backupPath = getBackupPath(),
|
backupPath = getBackupPath(),
|
||||||
configPath = getConfigPath(),
|
|
||||||
insertVersion = checkEnhancementVersion();
|
insertVersion = checkEnhancementVersion();
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
@ -239,10 +236,6 @@ try {
|
|||||||
"manual-removal-instructions": `to remove the notion-enhancer from notion, uninstall notion and
|
"manual-removal-instructions": `to remove the notion-enhancer from notion, uninstall notion and
|
||||||
then install a vanilla version of the app from https://www.notion.so/desktop (mac,
|
then install a vanilla version of the app from https://www.notion.so/desktop (mac,
|
||||||
windows) or ${manifest.homepage}/getting-started/installation (linux)`,
|
windows) or ${manifest.homepage}/getting-started/installation (linux)`,
|
||||||
|
|
||||||
"config-found": `config found`,
|
|
||||||
"config-not-found": `config not found: nothing to remove`,
|
|
||||||
"prompt-config-removal": `remove?`,
|
|
||||||
};
|
};
|
||||||
const SUCCESS = chalk`{bold.whiteBright SUCCESS} {green ✔}`,
|
const SUCCESS = chalk`{bold.whiteBright SUCCESS} {green ✔}`,
|
||||||
FAILURE = chalk`{bold.whiteBright FAILURE} {red ✘}`,
|
FAILURE = chalk`{bold.whiteBright FAILURE} {red ✘}`,
|
||||||
@ -316,9 +309,8 @@ try {
|
|||||||
stopSpinner();
|
stopSpinner();
|
||||||
print` {grey * ${messages["version-applied"]}}\n`;
|
print` {grey * ${messages["version-applied"]}}\n`;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
};
|
},
|
||||||
|
interactiveRemoveEnhancements = async () => {
|
||||||
const interactiveRemoveEnhancements = async () => {
|
|
||||||
if (!appPath) {
|
if (!appPath) {
|
||||||
// notion not installed
|
// notion not installed
|
||||||
print` {red * ${messages["notion-not-found"]}}\n`;
|
print` {red * ${messages["notion-not-found"]}}\n`;
|
||||||
@ -331,19 +323,6 @@ try {
|
|||||||
}
|
}
|
||||||
print` {grey * ${messages["notion-found"]}: ${messages["not-applied"]}}\n`;
|
print` {grey * ${messages["notion-found"]}: ${messages["not-applied"]}}\n`;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
},
|
|
||||||
promptConfigRemoval = async () => {
|
|
||||||
if (existsSync(configPath)) {
|
|
||||||
print` {grey * ${messages["config-found"]}: ${configPath}}\n`;
|
|
||||||
// prettier-ignore
|
|
||||||
const promptRemoval = await promptConfirmation(messages["prompt-config-removal"]);
|
|
||||||
if (["Y", "y"].includes(promptRemoval)) {
|
|
||||||
print` `;
|
|
||||||
startSpinner();
|
|
||||||
await removeConfig();
|
|
||||||
stopSpinner();
|
|
||||||
} else print`\n`;
|
|
||||||
} else print` {grey * ${messages["config-not-found"]}}\n`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (args["_"][0]) {
|
switch (args["_"][0]) {
|
||||||
@ -357,7 +336,6 @@ try {
|
|||||||
case "remove": {
|
case "remove": {
|
||||||
print`{bold.whiteBright [NOTION-ENHANCER] REMOVE}\n`;
|
print`{bold.whiteBright [NOTION-ENHANCER] REMOVE}\n`;
|
||||||
const res = await interactiveRemoveEnhancements();
|
const res = await interactiveRemoveEnhancements();
|
||||||
await promptConfigRemoval();
|
|
||||||
print`${res}\n`;
|
print`${res}\n`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -366,8 +344,6 @@ try {
|
|||||||
printObject({
|
printObject({
|
||||||
appPath,
|
appPath,
|
||||||
backupPath,
|
backupPath,
|
||||||
configPath,
|
|
||||||
configExists: existsSync(configPath),
|
|
||||||
insertVersion,
|
insertVersion,
|
||||||
currentVersion: manifest.version,
|
currentVersion: manifest.version,
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,7 @@ import { createRequire } from "node:module";
|
|||||||
|
|
||||||
import patch from "./patch-desktop-app.mjs";
|
import patch from "./patch-desktop-app.mjs";
|
||||||
|
|
||||||
let __notionResources, __enhancerConfig;
|
let __notionResources;
|
||||||
const nodeRequire = createRequire(import.meta.url),
|
const nodeRequire = createRequire(import.meta.url),
|
||||||
manifest = nodeRequire("../package.json"),
|
manifest = nodeRequire("../package.json"),
|
||||||
platform =
|
platform =
|
||||||
@ -92,12 +92,6 @@ const setNotionPath = (path) => {
|
|||||||
getAppPath = () => ["app", "app.asar"].map(getResourcePath).find(existsSync),
|
getAppPath = () => ["app", "app.asar"].map(getResourcePath).find(existsSync),
|
||||||
getBackupPath = () =>
|
getBackupPath = () =>
|
||||||
["app.bak", "app.asar.bak"].map(getResourcePath).find(existsSync),
|
["app.bak", "app.asar.bak"].map(getResourcePath).find(existsSync),
|
||||||
getConfigPath = () => {
|
|
||||||
if (__enhancerConfig) return __enhancerConfig;
|
|
||||||
const home = platform === "wsl" ? polyfillWslEnv("HOMEPATH") : os.homedir();
|
|
||||||
__enhancerConfig = resolve(`${home}/.notion-enhancer.db`);
|
|
||||||
return __enhancerConfig;
|
|
||||||
},
|
|
||||||
checkEnhancementVersion = () => {
|
checkEnhancementVersion = () => {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const manifestPath = getResourcePath("app/node_modules/notion-enhancer/package.json");
|
const manifestPath = getResourcePath("app/node_modules/notion-enhancer/package.json");
|
||||||
@ -125,8 +119,8 @@ const unpackApp = async () => {
|
|||||||
// call patch-desktop-app.mjs on each file
|
// call patch-desktop-app.mjs on each file
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const notionScripts = (await readdirDeep(appPath))
|
const notionScripts = (await readdirDeep(appPath))
|
||||||
.filter((file) => file.endsWith(".js")),
|
.filter((file) => file.endsWith(".js")),
|
||||||
scriptUpdates = [];
|
scriptUpdates = [];
|
||||||
for (const file of notionScripts) {
|
for (const file of notionScripts) {
|
||||||
const scriptId = file.slice(appPath.length + 1, -3).replace(/\\/g, "/"),
|
const scriptId = file.slice(appPath.length + 1, -3).replace(/\\/g, "/"),
|
||||||
scriptContent = await fsp.readFile(file, { encoding: "utf8" }),
|
scriptContent = await fsp.readFile(file, { encoding: "utf8" }),
|
||||||
@ -170,23 +164,16 @@ const unpackApp = async () => {
|
|||||||
const appPath = getAppPath();
|
const appPath = getAppPath();
|
||||||
if (destPath !== appPath) await fsp.rm(appPath, { recursive: true });
|
if (destPath !== appPath) await fsp.rm(appPath, { recursive: true });
|
||||||
return true;
|
return true;
|
||||||
},
|
|
||||||
removeConfig = async () => {
|
|
||||||
if (!existsSync(getConfigPath())) return;
|
|
||||||
await fsp.rm(getConfigPath());
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getResourcePath,
|
getResourcePath,
|
||||||
getAppPath,
|
getAppPath,
|
||||||
getBackupPath,
|
getBackupPath,
|
||||||
getConfigPath,
|
|
||||||
checkEnhancementVersion,
|
checkEnhancementVersion,
|
||||||
setNotionPath,
|
setNotionPath,
|
||||||
unpackApp,
|
unpackApp,
|
||||||
applyEnhancements,
|
applyEnhancements,
|
||||||
takeBackup,
|
takeBackup,
|
||||||
restoreBackup,
|
restoreBackup,
|
||||||
removeConfig,
|
|
||||||
};
|
};
|
||||||
|
@ -48,80 +48,96 @@ const sendMessage = (channel, message) => {
|
|||||||
ipcRenderer.on(channel, listener);
|
ipcRenderer.on(channel, listener);
|
||||||
};
|
};
|
||||||
|
|
||||||
let __db;
|
let __db, __statements, __transactions;
|
||||||
const initDatabase = (namespace, fallbacks = {}) => {
|
const initDatabase = (namespace, fallbacks = {}) => {
|
||||||
if (Array.isArray(namespace)) namespace = namespace.join("__");
|
if (Array.isArray(namespace)) namespace = namespace.join("__");
|
||||||
namespace = namespace ? namespace + "__" : "";
|
namespace = namespace ? namespace + "__" : "";
|
||||||
const namespaceify = (key) =>
|
const namespaceify = (key) =>
|
||||||
key.startsWith(namespace) ? key : namespace + key;
|
key.startsWith(namespace) ? key : namespace + key;
|
||||||
|
|
||||||
// schema:
|
__db ??= (async () => {
|
||||||
// - ("profileIds") = $profileId[]
|
const { app, ipcRenderer } = require("electron"),
|
||||||
// - ("activeProfile") -> $profileId
|
isRenderer = process?.type === "renderer",
|
||||||
// - $profileId: ("profileName") -> string
|
userData = isRenderer
|
||||||
// - $profileId__enabledMods: ($modId) -> boolean
|
? await ipcRenderer.invoke("notion-enhancer", "get-user-data-folder")
|
||||||
// - $profileId__$modId: ($optionKey) -> value
|
: app.getPath("userData");
|
||||||
|
|
||||||
const table = "settings",
|
const table = "settings",
|
||||||
sqlite = require("better-sqlite3"),
|
sqlite = require("better-sqlite3"),
|
||||||
db = __db ?? sqlite(path.resolve(`${os.homedir()}/.notion-enhancer.db`)),
|
db = sqlite(path.resolve(`${userData}/notion-enhancer.db`)),
|
||||||
init = db.prepare(`CREATE TABLE IF NOT EXISTS ${table} (
|
init = db.prepare(`CREATE TABLE IF NOT EXISTS ${table} (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT PRIMARY KEY,
|
||||||
value TEXT
|
value TEXT
|
||||||
)`);
|
)`);
|
||||||
init.run();
|
init.run();
|
||||||
__db = db;
|
|
||||||
|
|
||||||
const insert = db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`),
|
// schema:
|
||||||
update = db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`),
|
// - ("profileIds") = $profileId[]
|
||||||
select = db.prepare(`SELECT * FROM ${table} WHERE key = ? LIMIT 1`),
|
// - ("activeProfile") -> $profileId
|
||||||
remove = db.prepare(`DELETE FROM ${table} WHERE key = ?`),
|
// - $profileId: ("profileName") -> string
|
||||||
removeMany = db.transaction((arr) => arr.forEach((key) => remove.run(key))),
|
// - $profileId__enabledMods: ($modId) -> boolean
|
||||||
dump = db.prepare(`SELECT * FROM ${table}`),
|
// - $profileId__$modId: ($optionKey) -> value
|
||||||
populate = db.transaction((obj) => {
|
__statements = {
|
||||||
for (const key in obj) {
|
insert: db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`),
|
||||||
if (select.get(key)) update.run(obj[key], key);
|
update: db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`),
|
||||||
else insert.run(key, obj[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 {
|
return {
|
||||||
// wrap methods in promises for consistency w/ chrome.storage
|
get: async (key) => {
|
||||||
get: (key) => {
|
await __db;
|
||||||
const fallback = fallbacks[key];
|
const fallback = fallbacks[key];
|
||||||
key = namespaceify(key);
|
key = namespaceify(key);
|
||||||
try {
|
try {
|
||||||
const value = JSON.parse(select.get(key)?.value);
|
const value = JSON.parse(__statements.select.get(key)?.value);
|
||||||
return Promise.resolve(value ?? fallback);
|
return value ?? fallback;
|
||||||
} catch {}
|
} catch {}
|
||||||
return Promise.resolve(fallback);
|
return fallback;
|
||||||
},
|
},
|
||||||
set: (key, value) => {
|
set: async (key, value) => {
|
||||||
|
await __db;
|
||||||
key = namespaceify(key);
|
key = namespaceify(key);
|
||||||
value = JSON.stringify(value);
|
value = JSON.stringify(value);
|
||||||
if (select.get(key) === undefined) {
|
__transactions.set({ [key]: value });
|
||||||
insert.run(key, value);
|
return true;
|
||||||
} else update.run(value, key);
|
|
||||||
return Promise.resolve(true);
|
|
||||||
},
|
},
|
||||||
remove: (keys) => {
|
remove: async (keys) => {
|
||||||
|
await __db;
|
||||||
keys = Array.isArray(keys) ? keys : [keys];
|
keys = Array.isArray(keys) ? keys : [keys];
|
||||||
keys = keys.map(namespaceify);
|
keys = keys.map(namespaceify);
|
||||||
removeMany(keys);
|
__transactions.remove(keys);
|
||||||
return Promise.resolve(true);
|
return true;
|
||||||
},
|
},
|
||||||
export: () => {
|
export: async () => {
|
||||||
const entries = dump
|
await __db;
|
||||||
|
const entries = __statements.dump
|
||||||
.all()
|
.all()
|
||||||
.filter(({ key }) => key.startsWith(namespace))
|
.filter(({ key }) => key.startsWith(namespace))
|
||||||
.map(({ key, value }) => [key.slice(namespace.length), value]);
|
.map(({ key, value }) => [key.slice(namespace.length), value]);
|
||||||
return Promise.resolve(Object.fromEntries(entries));
|
return Object.fromEntries(entries);
|
||||||
},
|
},
|
||||||
import: (obj) => {
|
import: async (obj) => {
|
||||||
|
await __db;
|
||||||
const entries = Object.entries(obj) //
|
const entries = Object.entries(obj) //
|
||||||
.map(([key, value]) => [key.slice(namespace.length), value]);
|
.map(([key, value]) => [key.slice(namespace.length), value]);
|
||||||
populate(Object.fromEntries(entries));
|
__transactions.set(Object.fromEntries(entries));
|
||||||
return Promise.resolve(true);
|
return true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -21,13 +21,18 @@ if (isElectron()) {
|
|||||||
app.exit();
|
app.exit();
|
||||||
};
|
};
|
||||||
|
|
||||||
ipcMain.on("notion-enhancer", (event, message) => {
|
ipcMain.on("notion-enhancer", (_event, message) => {
|
||||||
if (message === "open-menu") {
|
if (message === "open-menu") {
|
||||||
//
|
//
|
||||||
} else if (message === "reload-app") {
|
} else if (message === "reload-app") {
|
||||||
reloadApp();
|
reloadApp();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ipcMain.handle("notion-enhancer", (_event, message) => {
|
||||||
|
if (message === "get-user-data-folder") {
|
||||||
|
return app.getPath("userData");
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
const notionUrl = "https://www.notion.so/",
|
const notionUrl = "https://www.notion.so/",
|
||||||
isNotionTab = (tab) => tab?.url?.startsWith(notionUrl);
|
isNotionTab = (tab) => tab?.url?.startsWith(notionUrl);
|
||||||
|
Loading…
Reference in New Issue
Block a user