diff --git a/README.md b/README.md
index 9228d9b..23350bf 100644
--- a/README.md
+++ b/README.md
@@ -12,23 +12,24 @@ This is a part of [Node3D](https://github.com/node-3d) project.
## Synopsis
-Helpers for Node.js addons and dependency packages:
+Helpers for Node.js **NAPI** addons and dependency packages:
-* C++ macros and shortcuts.
-* `consoleLog()` C++ helper.
-* `eventEmit()` C++ helper.
-* `getData()` C++ helper.
-* Crossplatform commands for GYP: `cp`, `rm`, `mkdir`.
* Supported platforms (x64): Windows, Linux, OSX.
+* C++ helpers:
+ * Macro shortcuts for NAPI.
+ * `consoleLog()` function.
+ * `eventEmit()` function.
+ * `getData()` function.
+* Module helpers:
+ * Crossplatform commands for GYP: `cp`, `rm`, `mkdir`.
+ * Deps unzip installer.
+ * Url-to-buffer downloader.
Useful links: [N-API Docs](https://nodejs.org/api/n-api.html),
[Napi Docs](https://github.com/nodejs/node-addon-api/blob/master/doc/setup.md),
[GYP Docs](https://gyp.gsrc.io/docs/UserDocumentation.md).
----
-
-
-## Contents
+**Jump to**:
[Snippets](#snippets)
@@ -107,16 +108,41 @@ On both Windows and Unix those commands now have the same result:
],
```
-Those are the directory paths to C++ include files for Addon Tools and Napi
-(which is preinstalled with Addon Tools)
+Those are the directory paths to C++ include files for **Addon Tools** and
+**Napi** (which is preinstalled with Addon Tools).
### Binary dependency package
-If you design a module with binary dependencies for several platforms, **Addon Tools**
-would encourage you to abide by the following rules:
+If you design a module with binary dependencies for several platforms,
+**Addon Tools** may help within the following guidelines:
-* Your binary directories are:
+* In **package.json** use a `"postinstall"` script to download the libraries.
+For example the following structure might work. Note that **Addon Tools** will
+append any given URL with ``/${platform}.zip``
+
+ ```
+ "config" : {
+ "install" : "v1.0.0"
+ },
+ "scripts": {
+ "postinstall": "install",
+ },
+ ```
+
+ where `config.install` is **YOUR install.js** is:
+
+ ```
+ const install = require('addon-tools-raub/install');
+ const prefix = 'https://github.com/user/addon/releases/download';
+ const tag = process.env.npm_package_config_install;
+ install(`${prefix}/${tag}`);
+ ```
+
+ **Addon Tools** will unzip the downloaded file into the platform binary
+ directory. E.g. on Windows it will be **bin-windows**.
+
+* Per platform binary directories:
* bin-windows
* bin-linux
@@ -129,69 +155,73 @@ is described [here](#indexjs).
module.exports = require('addon-tools-raub').paths(__dirname);
```
-
+* Publishing is done by attaching a zipped platform folder to the Github
+release. Zip file must NOT contain platform folder as a subfolder, but rather
+contain the final binaries. The tag of the release should be the same as in
+`npm_package_config_install` - that is the way installer will find it.
- Show binding.gyp
-
- ```
- {
- 'variables': {
- 'rm' : '
+* NOTE: You can publish your binaries to anywhere, not necessarily Github.
+Just tweak the **install.js** script as appropriate. The only limitation
+from **Addon Tools** is that it should be a zipped set of files/folders.
### Compiled addon
-It is easy to build a C++ addon with **Addon Tools**. To have a full picture, you
-can view the
-[official example](https://github.com/node-3d/addon-tools-raub/tree/master/examples/addon).
+With the advent of N-API the focus of compiled addons shifted towards the
+word "addons". Since ABI is now compatible across Node.js versions, now addons
+are just plain DLLs. Therefore distribution of the binaries is covered in the
+previous section. But for an addon you have to provide a GYP compilation step.
+N-API changes it's role to out-of-install compilation, so we can't/shouldnt
+put the file **binding.gyp** to the module root anymore.
-The main file for an addon is **binding.gyp**. Here's a snippet with most of the features.
+The workaround would be to have a separate directory within your project
+(with simplified package.json) for the sake of addon compilation.
-
-
-binding.gyp
+```
+{
+ "name": "build",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "addon-tools-raub": "5.0.0",
+ "deps-EXT_LIB": "1.0.0"
+ }
+}
+```
* Assume `EXT_LIB` is the name of a binary dependency.
* Assume `deps-EXT_LIB` is the name of an Addon Tools compliant dependency module.
* Assume `MY_ADDON` is the name of this addon's resulting binary.
-* Assume C++ code goes to `cpp` directory.
+* Assume C++ code goes to `cpp` subdirectory.
+
+That together with **binding.gyp**, this would be enough to get the addon compiled.
+Then the binaries are published to the Github release. When the addon
+is installed, its **index.js** is responsible for reexport of the binary.
+Just require the built module like this:
+
+```
+const { bin } = require('addon-tools-raub');
+const core = require(`./${bin}/MY_ADDON`);
+```
+
+
+
+See a snipped for binding.gyp here
+
+* Assume `EXT_LIB` is the name of a binary dependency.
+* Assume `deps-EXT_LIB` is the name of an Addon Tools compliant dependency module.
+* Assume `MY_ADDON` is the name of this addon's resulting binary.
+* Assume C++ code goes to `cpp` subdirectory.
```
{
'variables': {
- 'rm' : '
---
@@ -332,99 +333,55 @@ so that you can replace:
with
```
-#include // or event-emitter.hpp
+#include
```
-In gyp, the include directory should be set for your addon to know where to get it.
-As it was mentioned above, this can be done automatically. Also an actual path to the
-directory is exported from the module and is accessible like this:
+In gyp, the include directory should be set for your addon to know where
+to get it. An actual path to the directory is exported from the module
+and is accessible like this:
```
require('addon-tools-raub').include // a string
```
-Currently, there are following helpers in **addon-tools.hpp**:
+### Helpers in **addon-tools.hpp**:
-
-
-
-Handle scope
-
-* `NAN_HS` - creates a HandleScope. Also, you do not need them within `NAN_METHOD`,
-`NAN_SETTER`, and `NAN_GETTER`, as it is stated in
-[Nan doc](https://github.com/nodejs/nan/blob/master/doc/methods.md#api_nan_method).
-So it is most likely to be used in parts of code called from C++ land.
+Usually all the helpers work within the context of JS call. In this case we
+have `CallbackInfo info` passed as an argument.
```
-void windowFocusCB(GLFWwindow *window, int focused) { NAN_HS;
- ...
-}
-...
-glfwSetWindowFocusCallback(window, windowFocusCB);
+#define NAPI_ENV Napi::Env env = info.Env();
+#define NAPI_HS Napi::HandleScope scope(env);
```
-
-
-
-Method return
+Return value
-* `RET_VALUE(VAL)` - set method return value, where `VAL` is `v8::Local`.
-* `RET_UNDEFINED` - set method return value as `undefined`.
-* `RET_STR(VAL)` - set method return value, where `VAL` is `const char *`.
-* `RET_UTF8(VAL)` - set method return value, where `VAL` is `const char *`.
-* `RET_INT(VAL)` - set method return value, where `VAL` is `int32`.
-* `RET_INT32(VAL)` - set method return value, where `VAL` is `int32`.
-* `RET_UINT32(VAL)` - set method return value, where `VAL` is `uint32`.
-* `RET_NUM(VAL)` - set method return value, where `VAL` is `double`.
-* `RET_OFFS(VAL)` - set method return value, where `VAL` is `size_t`.
-* `RET_FLOAT(VAL)` - set method return value, where `VAL` is `float`.
-* `RET_DOUBLE(VAL)` - set method return value, where `VAL` is `double`.
-* `RET_EXT(VAL)` - set method return value, where `VAL` is `void *`.
-* `RET_BOOL(VAL)` - set method return value, where `VAL` is `bool`.
-* `RET_FUN(VAL)` - set method return value, where `VAL` is `Nan::Persistent`.
-* `RET_OBJ(VAL)` - set method return value, where `VAL` is `Nan::Persistent`.
+* `RET_VALUE(VAL)`- return a given Napi::Value.
+* `RET_UNDEFINED`- return `undefined`.
+* `RET_NULL` - return `null`.
+* `RET_STR(VAL)` - return `Napi::String`, expected `VAL` is `const char *`.
+* `RET_NUM(VAL)` - return `Napi::Number`, expected `VAL` is `double`.
+* `RET_EXT(VAL)` - return `Napi::External`, expected `VAL` is `void *`.
+* `RET_BOOL(VAL)` - return `Napi::Boolean`, expected `VAL` is `bool`.
+* `RET_FUN(VAL)` - return `Napi::Function`, expected `VAL` is a `napi_value`.
+* `RET_OBJ(VAL)` - return `Napi::Object`, expected `VAL` is a `napi_value`.
-
-
-Shortcut types
-
-* `V8_VAR_VAL` = `v8::Local`
-* `V8_VAR_OBJ` = `v8::Local`
-* `V8_VAR_ARR` = `v8::Local`
-* `V8_VAR_STR` = `v8::Local`
-* `V8_VAR_FUNC` = `v8::Local`
-* `V8_VAR_FT` = `v8::Local`
-* `V8_VAR_OT` = `v8::Local`
-* `V8_STORE_FT` = `Nan::Persistent`
-* `V8_STORE_FUNC` = `Nan::Persistent`
-* `V8_STORE_OBJ` = `Nan::Persistent`
-* `V8_STORE_VAL` = `Nan::Persistent`
-
-
-
New JS value
-* `JS_STR(...)` - create a string value
-* `JS_UTF8(...)` - same as JS_STR
-* `JS_INT(val)` - create an integer value
-* `JS_INT32(val)` - same as `JS_INT`
-* `JS_UINT32(val)` - same as `JS_INT`
-* `JS_NUM(val)` - create a numeric value
-* `JS_OFFS(val)` - same as `JS_NUM`, but has a cast designed to avoid `size_t -> double` warning
-* `JS_FLOAT(val)` - same as `JS_NUM`
-* `JS_DOUBLE(val)` - same as `JS_NUM`
-* `JS_EXT(val)` - create an external (pointer) value
-* `JS_BOOL(val)` - create a boolean value
-* `JS_FUN(val)` - get a function from persistent `Nan::Persistent`.
-* `JS_OBJ(val)` - get an object from persistent `Nan::Persistent`.
+* `JS_STR(VAL)` - create a `Napi::String` value.
+* `JS_NUM(VAL)` - create a `Napi::Number` value.
+* `JS_EXT(VAL)` - create a `Napi::External` (from pointer) value.
+* `JS_BOOL(VAL)` - create a `Napi::Boolean` value.
+* `JS_FUN(VAL)` - create a `Napi::Function` value.
+* `JS_OBJ(VAL)` - create a `Napi::Object` value.
@@ -434,8 +391,8 @@ glfwSetWindowFocusCallback(window, windowFocusCB);
Method check
These checks throw JS TypeError if not passed. Here `T` is always used as a typename
-in error messages. `C` is
-[v8::Value](https://v8docs.nodesource.com/node-0.8/dc/d0a/classv8_1_1_value.html)
+in error messages. `C` is a
+[Napi::Value](https://github.com/nodejs/node-addon-api/blob/master/doc/value.md#isboolean)
check method, like `IsObject()`. `I` is the index of argument as in `info[I]`,
starting from `0`.
@@ -445,7 +402,8 @@ starting from `0`.
* `CHECK_LET_ARG(I, C, T)` - check if argument `I` is approved by `C` check or empty.
* `CTOR_CHECK(T)` - check if method is called as a constructor
* `SETTER_CHECK(C, T)` - check if setter `value` is approved by `C` check.
-* `DES_CHECK` - within dynamic method check if the instance wasn't destroyed by `destroy()`.
+* `DES_CHECK` - within dynamic method check if the instance wasn't
+destroyed by `destroy()`.
@@ -454,34 +412,64 @@ starting from `0`.
Method arguments
-Two types of argument retrieval are supported: `REQ_` and `LET_`. The difference
-is that `LET_` allows the argument to be empty, using some zero-default in this case.
-`I` is the index of argument as in `info[I]`,
-starting from `0`. `VAR` is the name of the variable to be created.
+The idea is to ease the transition from what inside the `CallbackInfo` to
+what you work with in C++.
+Three types of argument retrieval are supported: `REQ_`, `USE_` and `LET_`.
+The difference:
+* `REQ_` - 2 params, requires an argument to have a value
+* `USE_` - 3 params, allows the argument to be empty and have a default
+* `LET_` - 2 params, is `USE_` with a preset zero-default.
+
+What it does, basically:
+```
+// REQ_DOUBLE_ARG(0, x)
+double x = info[0].ToNumber().DoubleValue();
+
+// USE_DOUBLE_ARG(0, x, 5.7)
+double x = IS_ARG_EMPTY(0) ? 5.7 : info[0].ToNumber().DoubleValue();
+
+// LET_DOUBLE_ARG(0, x)
+double x = IS_ARG_EMPTY(0) ? 0.0 : info[0].ToNumber().DoubleValue();
+```
+
+That extrapolates well to all the helpers below:
+* `REQ_STR_ARG` - JS `string` => C++ `std::string`.
+* `USE_STR_ARG`
+* `LET_STR_ARG` - default: `""`.
+* `REQ_INT32_ARG` - JS `number` => C++ `int32_t`.
+* `USE_INT32_ARG`
+* `LET_INT32_ARG` - default: `0`.
+* `REQ_INT_ARG` - JS `number` => C++ `int32_t`.
+* `USE_INT_ARG`
+* `LET_INT_ARG` - default: `0`.
+* `REQ_UINT32_ARG` - JS `number` => C++ `uint32_t`.
+* `USE_UINT32_ARG`
+* `LET_UINT32_ARG` - default: `0`.
+* `REQ_UINT_ARG` - JS `number` => C++ `uint32_t`.
+* `USE_UINT_ARG`
+* `LET_UINT_ARG` - default: `0`.
+* `REQ_BOOL_ARG` - JS `Boolean` => C++ `bool`.
+* `USE_BOOL_ARG`
+* `LET_BOOL_ARG` - default: `false`.
+* `REQ_OFFS_ARG` - JS `number` => C++ `size_t`.
+* `USE_OFFS_ARG`
+* `LET_OFFS_ARG` - default: `0`.
+* `REQ_DOUBLE_ARG` - JS `number` => C++ `double`.
+* `USE_DOUBLE_ARG`
+* `LET_DOUBLE_ARG` - default: `0.0`.
+* `REQ_FLOAT_ARG` - JS `number` => C++ `float`.
+* `USE_FLOAT_ARG`
+* `LET_FLOAT_ARG` - default: `0.f`.
+* `REQ_EXT_ARG` - JS `native` => C++ `void*`.
+* `USE_EXT_ARG`
+* `LET_EXT_ARG` - default: `nullptr`.
+* `REQ_FUN_ARG` - JS `function` => C++ `Napi::Function`.
+* `REQ_OBJ_ARG` - JS `object` => C++ `Napi::Object`.
+* `USE_OBJ_ARG`
+* `LET_OBJ_ARG` - default: `{}`.
+* `REQ_ARRV_ARG` - JS `ArrayBuffer` => C++ `Napi::ArrayBuffer`.
+* `REQ_BUF_ARG` - JS `Buffer` => C++ `Napi::Buffer`.
-* `REQ_UTF8_ARG(I, VAR)` - require `I`'th argument to be a `string`. Stored at `Nan::Utf8String VAR`.
-* `LET_UTF8_ARG(I, VAR)` - let optional `I`'th argument to be a `string`, the default is `""`. Stored at `Nan::Utf8String VAR`.
-* `REQ_STR_ARG(I, VAR)` - require `I`'th argument to be a `string`. Stored at `Nan::Utf8String VAR`.
-* `LET_STR_ARG(I, VAR)` - let optional `I`'th argument to be a `string`, the default is `""`. Stored at `Nan::Utf8String VAR`.
-* `REQ_INT32_ARG(I, VAR)` - require `I`'th argument to be a `number`. Stored at `int VAR`.
-* `LET_INT32_ARG(I, VAR)` - let optional `I`'th argument to be a `number`, the default is `0`. Stored at `int VAR`.
-* `REQ_INT32_ARG(I, VAR)` - require `I`'th argument to be a `number`. Stored at `int VAR`.
-* `LET_INT32_ARG(I, VAR)` - let optional `I`'th argument to be a `number`, the default is `0`. Stored at `int VAR`.
-* `REQ_UINT32_ARG(I, VAR)` - require `I`'th argument to be a `number`. Stored at `unsigned VAR`.
-* `LET_UINT32_ARG(I, VAR)` - let optional `I`'th argument to be a `number`, the default is `0`. Stored at `unsigned VAR`.
-* `REQ_BOOL_ARG(I, VAR)` - require `I`'th argument to be a `boolean`. Stored at `bool VAR`.
-* `LET_BOOL_ARG(I, VAR)` - let optional `I`'th argument to be a `boolean`, the default is `false`. Stored at `Nan::Utf8String VAR`.
-* `REQ_OFFS_ARG(I, VAR)` - require `I`'th argument to be a `number`. Stored at `size_t VAR`.
-* `LET_OFFS_ARG(I, VAR)` - let optional `I`'th argument to be a `number`, the default is `0`. Stored at `Nan::Utf8String VAR`.
-* `REQ_DOUBLE_ARG(I, VAR)` - require `I`'th argument to be a `number`. Stored at `double VAR`.
-* `LET_DOUBLE_ARG(I, VAR)` - let optional `I`'th argument to be a `number`, the default is `0.0`. Stored at `Nan::Utf8String VAR`.
-* `REQ_FLOAT_ARG(I, VAR)` - require `I`'th argument to be a `number`. Stored at `float VAR`.
-* `LET_FLOAT_ARG(I, VAR)` - let optional `I`'th argument to be a `number`, the default is `0.0f`. Stored at `Nan::Utf8String VAR`.
-* `REQ_EXT_ARG(I, VAR)` - require `I`'th argument to be an `external`. Stored at `Local VAR`.
-* `LET_EXT_ARG(I, VAR)` - let optional `I`'th argument to be an `external`, the default is `nullptr`. Stored at `Nan::Utf8String VAR`.
-* `REQ_FUN_ARG(I, VAR)` - require `I`'th argument to be a `function`. Stored at `Local VAR`.
-* `REQ_OBJ_ARG(I, VAR)` - require `I`'th argument to be an `object`. Stored at `Local
-
-
-
-
-Set properties
-
-Set-helpers for string and numeric keys. String keys are converted to JS strings
-automatically.
-
-* `SET_PROP(OBJ, KEY, VAL)`
-* `SET_I(ARR, I, VAL)`
-
@@ -519,18 +491,25 @@ automatically.
Simplified accessor assignment, adds accessors of NAME for OBJ. Read accessor is
assumed to have the name `NAME+'Getter'` and write accessor is `NAME+'Setter'`.
-* `ACCESSOR_RW(OBJ, NAME)` - add read and write accessors of NAME for OBJ.
-* `ACCESSOR_R(OBJ, NAME)` - read-only property.
+* `ACCESSOR_RW(CLASS, NAME)` - add read and write accessors NAME of CLASS.
+* `ACCESSOR_R(CLASS, NAME)` - add read accessor NAME of CLASS.
+* `ACCESSOR_M(CLASS, NAME)` - add method NAME of CLASS.
+
```
-void MyClass::init(Handle
@@ -540,26 +519,26 @@ NAN_SETTER(MyClass::messageSetter) { ...
Setter argument
-Useful addition to NAN_SETTER macro. Works similar to method arguments. But there
-is always only one required argument stored in `v`.
+Works similar to method arguments. But there is always `value`
+argument, from which a C++ value is extracted.
-* `SETTER_UTF8_ARG` - require the value to be a `string`. Stored at `Nan::Utf8String v`.
-* `SETTER_STR_ARG` - require the value to be a `string`. Stored at `Nan::Utf8String v`.
-* `SETTER_INT32_ARG` - require the value to be a `number`. Stored at `int v`.
-* `SETTER_INT_ARG` - require the value to be a `number`. Stored at `int v`.
-* `SETTER_UINT32_ARG` - require the value to be a `number`. Stored at `unsigned v`.
-* `SETTER_BOOL_ARG` - require the value to be a `boolean`. Stored at `bool v`.
-* `SETTER_OFFS_ARG` - require the value to be a `number`. Stored at `size_t v`.
-* `SETTER_DOUBLE_ARG` - require the value to be a `number`. Stored at `double v`.
-* `SETTER_FLOAT_ARG` - require the value to be a `number`. Stored at `float v`.
-* `SETTER_EXT_ARG` - require the value to be an `external`. Stored at `Local v`.
-* `SETTER_FUN_ARG` - require the value to be a `function`. Stored at `Local v`.
-* `SETTER_OBJ_ARG` - require the value to be an `object`. Stored at `Local