redesign module system again after technological / enable-disable considerations

This commit is contained in:
dragonwocky 2020-07-16 19:00:36 +10:00
parent 26a82f400f
commit 0d2dfaca61
Signed by: dragonwocky
GPG Key ID: C7A48B7846AA706D
4 changed files with 202 additions and 182 deletions

View File

@ -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,39 +16,59 @@ _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` |
| ------------ | ---------------------------------------------------------------------------------------------------- |
| `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_ |
| 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 |
@ -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

View File

@ -0,0 +1,5 @@
module.exports = function () {
document.addEventListener('readystatechange', (ev) => {
console.log(ev);
});
};

123
pkg/helpers.md Normal file
View File

@ -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.

View File

@ -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"