From 0d2dfaca613576275ac02faf6a2161282530f454 Mon Sep 17 00:00:00 2001
From: dragonwocky <thedragonring.bod@gmail.com>
Date: Thu, 16 Jul 2020 19:00:36 +1000
Subject: [PATCH] redesign module system again after technological /
 enable-disable considerations

---
 DOCUMENTATION.md | 244 +++++++++++++----------------------------------
 loader/hack.js   |   5 +
 pkg/helpers.md   | 123 ++++++++++++++++++++++++
 yarn.lock        |  12 +--
 4 files changed, 202 insertions(+), 182 deletions(-)
 create mode 100644 pkg/helpers.md

diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md
index ee43fe9..910c506 100644
--- a/DOCUMENTATION.md
+++ b/DOCUMENTATION.md
@@ -1,4 +1,4 @@
-# documentation placeholder
+# documentation
 
 ended up here? this is a wip version of the enhancer, and this file is yet to be completed.
 if you're interested in using the project, switch back to the [master branch](https://github.com/dragonwocky/notion-enhancer).
@@ -16,41 +16,61 @@ _and explore the contents of your local extracted `app.asar`._
 _explore [the existing modules](https://github.com/dragonwocky/notion-enhancer/tree/js/mods/)_
 _for examples of implementing what's described below._
 
-each directory in the `mods` folder is considered a module, and consist of 5 files:
+each directory in the `mods` folder is considered a module, with the entry points `mod.js` and `styles.css`
 
-| file          | description                                                                                                                                                          |
-| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `meta.js`     | **required:** entry point, describes the module                                                                                                                      |
-| `hack.js`     | **optional:** executed on enhancement (useful for e.g. find/replace on files, modding that can't be done just through insertion)                                     |
-| `main.js`     | **optional:** executed on app launch in the "main" process (singular, shared between all apps - consider it a backend) of `app/main/main.js`                         |
-| `renderer.js` | **optional:** executed on window launch in the "renderer" process (per-window, the client-side js one might expect to run on a website) of `app/renderer/preload.js` |
-| `styles.css`  | **optional:** css file automatically inserted into each app window via the `enhancement://` protocol                                                                 |
+| file         | description                                                                                          |
+| ------------ | ---------------------------------------------------------------------------------------------------- |
+| `mod.js`     | **required:** describes the module and contains functional javascript                                |
+| `styles.css` | **optional:** css file automatically inserted into each app window via the `enhancement://` protocol |
 
 ---
 
-### meta
+### mod.js
 
-`module.exports = {}`
+```js
+// not valid js!
+// a visual representation of the contents/type
+// of this file's exported object.
+module.exports = {
+  id: String of uuidv4,
+  type: String in ['extension', 'theme'],
+  name: String of short_name,
+  desc: String of paragraph,
+  version: String of semver,
+  author: String of github_username,
+  thumbnail?: String of [relative_file, url],
+  options?: {
+    key: String,
+    label: String,
+    type: String in ['toggle', 'select', 'input', 'file'],
+    value: Boolean or Array<String> or String or null
+  },
+  hacks?: {
+    [k: 'insert-point' (e.g. 'main/createWindow.js')]: function (store) {}
+  }
+};
+```
 
 | key       | value                                                                                           | type              |
 | --------- | ----------------------------------------------------------------------------------------------- | ----------------- |
 | id        | **required:** uuidv4                                                                            | _string_          |
 | type      | **required:** 'extension' or 'theme'                                                            | _string_          |
 | name      | **required:** short name (e.g. 'frameless window')                                              | _string_          |
-| desc      | **optional:** 1-3 sentence description of what the module is/does                               | _string_          |
+| desc      | **optional:** 1-3 sentence description of what the module is/does.                              | _string_          |
 | version   | **required:** semver (e.g. '0.3.7')                                                             | _string_          |
 | author    | **required:** github username                                                                   | _string_          |
 | thumbnail | **optional:** image: relative file or url                                                       | _string_          |
 | options   | **optional:** see below: options made available in the enhancer menu (accessible from the tray) | _array\<object\>_ |
+| hacks     | **optional:** see below: code inserted at various points                                        | _object_          |
 
-`module.exports.options = {}`
+#### options
 
-| key   | value                                                         | type      |
-| ----- | ------------------------------------------------------------- | --------- |
-| key   | **required:** key to save value to the mod `store`            | _string_  |
-| label | **required:** short description of option to be shown in menu | _string_  |
-| type  | **required:** input type (see below)                          | _string_  |
-| value | **optional:** default or possible value/s for option          | see below |
+| key   | value                                                              | type      |
+| ----- | ------------------------------------------------------------------ | --------- |
+| key   | **required:** key to save value to the mod `store`                 | _string_  |
+| label | **required:** short description/name of option to be shown in menu | _string_  |
+| type  | **required:** input type (see below)                               | _string_  |
+| value | **optional:** default or possible value/s for option               | see below |
 
 | type   | value             |
 | ------ | ----------------- |
@@ -59,175 +79,47 @@ each directory in the `mods` folder is considered a module, and consist of 5 fil
 | input  | _string_          |
 | file   | none              |
 
----
+#### hacks
 
-### scripting
-
-`hack.js`
-
-```js
-module.exports = function (store, __notion) {};
-```
-
-`main.js` `renderer.js`
-
-```js
-module.exports = function (store) {};
-```
-
-the **`store`** argument allows access to the module settings/options defined in `meta.js`, set in the menu,
-or used internally by the module. each module store is saved to + automatically syncs with `~/.notion-enhancer/id.json`.
+each "hack" is a function taking a single **`store`** argument, which allows
+access to the module settings/options defined in `mod.js` (those set in the menu,
+or used internally by the module). each module store is saved to + automatically syncs with `~/.notion-enhancer/id.json`.
 it can be initialised with `const data = store({ defaults })`, then used as if it were a normal object.
 
-the **`__notion`** argument gives the filepath of the app parent folder.
-use it for e.g. find/replace on pre-existing app code in `__notion/app/renderer/createWindow.js`
-to make the window frameless.
+this hack is applied to whichever file is set as the function key. these can be found within the `app` folder.
 
-#### shell output
+files under the `main` folder are executed on app launch in a process shared
+between all app windows (consider it a backend). files under the `renderer` folder are
+executed on window launch in a pre-window process: the client-side javascript
+normally expected to run on a webpage.
 
-`hack.js` files may communicate with the user during enhancement.
+unless scripts need to change app logic (e.g. to add the tray menu),
+they should usually be applied to `renderer/preload.js` to interact
+with the app window itself.
 
-these communications should be in the following format:
+e.g.
 
 ```js
-// used by modules
-console.info(' ...information.');
-console.warn(' * warning.');
-console.warn(' > prompt?');
-console.warn(' -- response to user input.');
-// used internally
-console.info('=== title ===');
-console.error('### error ###');
-(console.error || console.info)(' ~~ exit.');
+// sayhi.js
+module.exports = function (store) {
+  document.addEventListener('readystatechange', (event) => {
+    if (document.readyState !== 'complete') return false;
+    const data = store({ name: 'dragonwocky' });
+    console.log(data.name);
+  });
+};
+// mod.js
+module.exports.hacks = {
+  'renderer/preload.js': require('./sayhi.js'),
+};
 ```
 
-#### helpers
+#### the `enhancement://` protocol
 
-```js
-const helpers = require('../../pkg/helpers.js');
-```
-
-shared variables/classes/functions can be found in the `helpers.js` file: for consistency of error handling and
-cross-platform functionality these **should** be used to achieve their purpose.
+to be documented
 
 ---
 
-```js
-class EnhancerError(message) {}
-```
+## styling
 
-use `throw new helpers.EnhancerError(message)` if ever something occurs that would cause enhancement to fail,
-but is not caused by faulty programming: e.g. if a file that is known to exist cannot be found.
-
----
-
-```js
-const is_wsl;
-```
-
-use `helpers.is_wsl` to check if the enhancer was run from the windows subsystem for linux.
-
-primarily used for internal handling of filepaths (e.g. in the `helpers.realpath` and `helpers.getNotion` functions).
-
----
-
-```js
-const data_folder;
-```
-
-use `helpers.data_folder` to get the absolute path of the directory configuration/version
-data is saved to by the enhancer.
-
-if used immediately after being accessed, it should always work. however, if fetching its value during enhancement
-and then inserting it into something that will not be executed until the app is opened, it must be put through
-`helpers.realpath` before insertion.
-
----
-
-```js
-function realpath(hack_path) {
-  return runtime_path;
-}
-```
-
-use `helpers.realpath(hack_path)` to transform a path valid at enhancement time into one valid when the app is opened.
-this is particularly useful for wsl compatibility, so every filepath that is fetched during enhancement
-and then inserted into something that will not be executed until the app is opened should be put through this.
-
-primarily used for internal handling of filepaths (e.g. for the modloader).
-
----
-
-```js
-async function getNotion() {
-  return notion_app_path;
-}
-```
-
-use `await helpers.getNotion()` to get the notion app parent folder path
-(used to acquire the \_\_notion argument above).
-
-primarily used for internal modding of the app (e.g. to apply the modloader and patch launch scripts).
-
----
-
-```js
-function getJSON(from) {
-  return data;
-}
-```
-
-use `helpers.getJSON(from)` to read/parse a JSON file. if the file has invalid contents or does not exist,
-an empty object will be returned.
-
-primarily used for internal data management (e.g. in the module `store()`).
-
----
-
-```js
-function readline() {
-  return Promise(input);
-}
-```
-
-use `helpers.readline()` to receive user input from the terminal/shell/prompt during enhancement.
-
-example usage:
-
-```js
-// situation: conflicting file found.
-let overwrite;
-do {
-  // using stdout.write means that there is no newline
-  // between prompt and input.
-  process.stdout.write(' > overwrite? [Y/n]: ');
-  overwrite = await helpers.readline();
-  // ask for a Y/n until a valid answer is received.
-  // pressing enter without input is assumed to be a "yes".
-} while (overwrite && !['y', 'n'].includes(overwrite.toLowerCase()));
-overwrite = !overwrite || overwrite.toLowerCase() == 'y';
-if (overwrite) {
-  console.info(' -- overwriting file.');
-  // do stuff
-} else console.info(' -- keeping file: skipping step.');
-```
-
----
-
-```js
-async function exec(command[, options]) {
- return child_process;
-}
-```
-
-use `helpers.exec()` to execute shell commands. it is a promisified version of node.js's
-[child_process.exec(command[, options][, callback])](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback).
-
-primarily used for internal processes (e.g. unpacking asar, fetching windows app path from the wsl).
-for security reasons this should not be used by modules.
-
----
-
-#### styling
-
-css vars to be documented
+to be documented
diff --git a/loader/hack.js b/loader/hack.js
index e69de29..e986e53 100644
--- a/loader/hack.js
+++ b/loader/hack.js
@@ -0,0 +1,5 @@
+module.exports = function () {
+  document.addEventListener('readystatechange', (ev) => {
+    console.log(ev);
+  });
+};
diff --git a/pkg/helpers.md b/pkg/helpers.md
new file mode 100644
index 0000000..4f8bf69
--- /dev/null
+++ b/pkg/helpers.md
@@ -0,0 +1,123 @@
+# `helpers.js`
+
+these shared variables/classes/functions (used for consistency of error handling and
+cross-platform functionality) were previously documented in the [module-creation docs](../DOCUMENTATION.md).
+however, to ensure things can be toggled on/off no non-core code is executed on enhancement.
+it is unlikely any of these will need to be used, so they were removed from the main docs in
+an attempt to keep things as simple as possible.
+
+---
+
+```js
+class EnhancerError(message) {}
+```
+
+use `throw new helpers.EnhancerError(message)` if ever something occurs that would cause enhancement to fail,
+but is not caused by faulty programming: e.g. if a file that is known to exist cannot be found.
+
+---
+
+```js
+const is_wsl;
+```
+
+use `helpers.is_wsl` to check if the enhancer was run from the windows subsystem for linux.
+
+primarily used for internal handling of filepaths (e.g. in the `helpers.realpath` and `helpers.getNotion` functions).
+
+---
+
+```js
+const data_folder;
+```
+
+use `helpers.data_folder` to get the absolute path of the directory configuration/version
+data is saved to by the enhancer.
+
+if used immediately after being accessed, it should always work. however, if fetching its value during enhancement
+and then inserting it into something that will not be executed until the app is opened, it must be put through
+`helpers.realpath` before insertion.
+
+---
+
+```js
+function realpath(hack_path) {
+  return runtime_path;
+}
+```
+
+use `helpers.realpath(hack_path)` to transform a path valid at enhancement time into one valid when the app is opened.
+this is particularly useful for wsl compatibility, so every filepath that is fetched during enhancement
+and then inserted into something that will not be executed until the app is opened should be put through this.
+
+primarily used for internal handling of filepaths (e.g. for the modloader).
+
+---
+
+```js
+async function getNotion() {
+  return notion_app_path;
+}
+```
+
+use `await helpers.getNotion()` to get the notion app parent folder path
+(used to acquire the \_\_notion argument above).
+
+primarily used for internal modding of the app (e.g. to apply the modloader and patch launch scripts).
+
+---
+
+```js
+function getJSON(from) {
+  return data;
+}
+```
+
+use `helpers.getJSON(from)` to read/parse a JSON file. if the file has invalid contents or does not exist,
+an empty object will be returned.
+
+primarily used for internal data management (e.g. in the module `store()`).
+
+---
+
+```js
+function readline() {
+  return Promise(input);
+}
+```
+
+use `helpers.readline()` to receive user input from the terminal/shell/prompt during enhancement.
+
+example usage:
+
+```js
+console.warn(' * conflicting file found.');
+let overwrite;
+do {
+  // using stdout.write means that there is no newline
+  // between prompt and input.
+  process.stdout.write(' > overwrite? [Y/n]: ');
+  overwrite = await helpers.readline();
+  // ask for a Y/n until a valid answer is received.
+  // pressing enter without input is assumed to be a "yes".
+} while (overwrite && !['y', 'n'].includes(overwrite.toLowerCase()));
+overwrite = !overwrite || overwrite.toLowerCase() == 'y';
+if (overwrite) {
+  console.info(' -- overwriting file.');
+  // do stuff
+} else console.info(' -- keeping file: skipping step.');
+```
+
+---
+
+```js
+async function exec(command[, options]) {
+ return child_process;
+}
+```
+
+use `helpers.exec()` to execute shell commands. it is a promisified version of node.js's
+[child_process.exec(command[, options][, callback])](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback).
+
+primarily used for internal processes (e.g. unpacking asar, fetching windows app path from the wsl).
+for security reasons this should not be used by modules.
diff --git a/yarn.lock b/yarn.lock
index 03f4044..4c61620 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16,9 +16,9 @@
   integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
 
 "@types/node@*":
-  version "14.0.22"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.22.tgz#23ea4d88189cec7d58f9e6b66f786b215eb61bdc"
-  integrity sha512-emeGcJvdiZ4Z3ohbmw93E/64jRzUHAItSHt8nF7M4TGgQTiWqFVGB8KNpLGFmUHmHLvjvBgFwVlqNcq+VuGv9g==
+  version "14.0.23"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806"
+  integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==
 
 asar@^3.0.3:
   version "3.0.3"
@@ -51,9 +51,9 @@ brace-expansion@^1.1.7:
     concat-map "0.0.1"
 
 cac@^6.5.12:
-  version "6.5.13"
-  resolved "https://registry.yarnpkg.com/cac/-/cac-6.5.13.tgz#8d9be6dce0afb707c76c5962bf9cc6571f4c933a"
-  integrity sha512-pt643//kQb3S6syXMJ/EIfNZpivKeFpCdnnPbJ3Iq9ZVZyXQcQjXvzVMWTEQuUspp+rHUlhZYZZfnviP88VuYA==
+  version "6.6.1"
+  resolved "https://registry.yarnpkg.com/cac/-/cac-6.6.1.tgz#3dde3f6943f45d42a56729ea3573c08b3e7b6a6d"
+  integrity sha512-uhki4T3Ax68hw7Dufi0bATVAF8ayBSwOKUEJHjObPrUN4tlQ8Lf7oljpTje/mArLxYN0D743c2zJt4C1bVTCqg==
 
 chromium-pickle-js@^0.2.0:
   version "0.2.0"