Compare commits

..

76 Commits

Author SHA1 Message Date
Luis Blanco 1ca78906a9 Use cpcpplint util 2023-10-10 19:07:30 +04:00
Luis Blanco 9d68a62da4 Add cpplint badge 2023-10-09 22:46:58 +04:00
Luis Blanco 6c19ce79c3 Fix python version 2 2023-10-09 22:36:38 +04:00
Luis Blanco fc8b31fe36 Fix python version 2023-10-09 22:27:23 +04:00
Luis Blanco c82e029e90 Fix cpplint cmd 2023-10-09 22:24:11 +04:00
Luis Blanco b501c07de1 Fix GH action 2023-10-09 22:21:43 +04:00
Luis Blanco aeb2eae343 Adjust TS comments 2023-10-09 22:15:37 +04:00
Luis Blanco 747e1f6205 Fix linguist attributes 2023-10-07 19:08:39 +04:00
Luis Blanco c9c391ffd0 Use 18.16 and new badges 2023-10-07 19:06:03 +04:00
Luis Blanco d5ffbd6ba8 Fix action name 2023-10-07 18:34:43 +04:00
Luis Blanco 1c0b3afac5 Update deps and remove jest 2023-10-07 18:11:00 +04:00
Luis Blanco afd180d7cf Fix destructive lowercase 2023-09-26 21:32:57 +04:00
Luis Blanco aa063f9eae Update deps 2023-05-08 19:20:24 +04:00
Luis Blanco 105964614f Make install less strict 2023-01-06 20:00:38 +04:00
Luis Blanco 4b31874a56 Use gz 2023-01-04 19:23:43 +04:00
Luis Blanco 3f306a4938 Fix actionPack description 2023-01-04 17:52:04 +04:00
Luis Blanco f9f3ac2a23 Use GZIP 2023-01-04 17:10:00 +04:00
Luis Blanco 9852e1e789 Fix readme 2 2023-01-04 15:31:42 +04:00
Luis Blanco a56e079de0 Fix readme 2023-01-04 15:19:22 +04:00
Luis Blanco abc49171eb Fix publish workflow 2023-01-04 15:08:14 +04:00
Luis Blanco 6bdcf9abe2 Use object assign 2023-01-04 15:07:41 +04:00
Luis Blanco 0564af1e96 Fix version string 2023-01-04 14:50:40 +04:00
Luis Blanco 104fad35ae Remove actionVersion 2023-01-04 14:43:26 +04:00
Luis Blanco 9c76216823 Fix action script 2023-01-04 14:00:32 +04:00
Luis Blanco 955e8b61a8 Adjust actions 2023-01-04 13:36:32 +04:00
Luis Blanco 05e53641c1 Fix requires 2023-01-04 13:22:46 +04:00
Luis Blanco ac0c472be9 Adjust tests 2023-01-04 12:54:39 +04:00
Luis Blanco b05666869a Fix build 2023-01-03 23:45:14 +04:00
Luis Blanco 40e4baeb56 Fix exports 2023-01-03 23:14:04 +04:00
Luis Blanco 3d02cfb49c Add actionVersion test 2023-01-03 22:55:49 +04:00
Luis Blanco fd165d935d Update module structure 2023-01-03 22:20:39 +04:00
Luis Blanco b532ca47bf Update dependencies 2023-01-02 17:09:33 +04:00
Luis Blanco da96b71507 Fix windows compile flags 2022-12-24 21:59:11 +04:00
Luis Blanco 30f5fce2ec Fix platform names 2022-12-24 21:51:35 +04:00
Luis Blanco 6e66f46a4a Allow unknown platforms 2022-12-24 17:20:48 +04:00
Luis Blanco a274cd227e Add aarch64 2022-12-24 17:10:35 +04:00
Luis Blanco d4ed519e71 Remove eslint action matrix 2022-12-10 12:08:42 +04:00
Luis Blanco 3f52e63257 Adjust eslint action 2022-12-10 12:03:00 +04:00
Luis Blanco cd8527cdb1 Fix inline modifier 2022-12-10 11:57:17 +04:00
Luis Blanco 12fe6b4569 Split github action jobs 2022-12-05 23:02:43 +04:00
Luis Blanco 341b5e67a2 Update workflows 2022-12-05 22:54:03 +04:00
Luis Blanco 5d4708dfdf Update info 2022-12-05 22:44:35 +04:00
Luis Blanco eafb17d791 Fix test 2022-12-05 20:03:13 +04:00
Luis Blanco edc530bb5e Export missing test method 2022-12-05 19:55:29 +04:00
Luis Blanco 018b5aca47 Update package lock 2022-12-05 19:52:23 +04:00
Luis Blanco 68731102df Update header 2022-12-05 19:47:08 +04:00
Luis Blanco b77a3cac96 Fix napi error message 2022-11-28 20:24:17 +04:00
Luis Blanco a0a7f6153c Improve download script 2022-09-28 22:37:31 +04:00
Luis Blanco fc183b9793 Merge branch 'master' of https://github.com/node-3d/addon-tools-raub 2022-09-25 12:44:51 +04:00
Luis Blanco 9857670794 Add peer meta 2022-09-25 12:44:26 +04:00
Luis Blanco a7028c0062
remove codeql 2022-09-24 19:44:32 +04:00
Luis Blanco 4ed13bb471
Adjust codeql 2022-09-24 19:38:39 +04:00
Luis Blanco f2f3c440f0
Try codeql 2022-09-24 19:30:21 +04:00
Luis Blanco f9fe9f0124 Adjust readme 2022-09-24 19:11:40 +04:00
Luis Blanco 847a68a2d2 Update deps 2022-09-24 19:02:48 +04:00
Luis Blanco c4d42eea40 Update CI 2021-04-25 11:20:46 +03:00
Luis Blanco 3224521e0c Change CI versions 2021-04-24 09:26:01 +03:00
Luis Blanco cd504c13a3 Remove old actions 2021-04-19 22:52:12 +03:00
Luis Blanco 29681a0b46 Try old actions 2021-04-19 20:38:39 +03:00
Luis Blanco 33b4892dfb Merge CI actions 2021-04-19 20:21:54 +03:00
Luis Blanco 410b704d3d Fix readme 2021-04-19 00:40:17 +03:00
Luis Blanco cca802d932 Fix TS 2021-04-19 00:31:04 +03:00
Luis Blanco 4b98f5f435 Fix lints 2021-04-03 16:07:45 +03:00
Luis Blanco 498de135cb Remove test package 2021-04-03 15:49:45 +03:00
Luis Blanco 3fea905be4 Fix linebreak lint 2021-04-03 15:27:28 +03:00
Luis Blanco 5dd1b40e10 Fix lint ci 2021-04-03 14:13:42 +03:00
Luis Blanco 5f52a14c85 Update workflows 2021-04-03 14:05:05 +03:00
Luis Blanco ae9fd3e8ba Automate NPM publish 2021-03-21 18:23:26 +03:00
Luis Blanco cb8e4841ba Try action Publish 2021-03-21 18:19:00 +03:00
Luis Blanco 0a1b289ce4 Fix scripts 2021-03-21 17:32:38 +03:00
Luis Blanco 773a356788 Fix node version 2021-03-21 17:20:09 +03:00
Luis Blanco 8a2c0187b2 Update deps and tests 2021-03-21 17:11:24 +03:00
Luis Blanco 5af58c65d3 Update deps 2020-08-09 11:32:58 +03:00
Luis Blanco acddbf669d Bump version 2020-04-23 09:35:05 +03:00
Luis Blanco ebdf6d780c
Merge pull request #2 from AlexVestin/patch-1
Use size of the typed array instead of underlying bufffer
2020-04-23 10:31:36 +04:00
AlexVestin d1ee793b75
Use size of the typed array instead of underlying bufffer
If an array is subarrayed from another array they will still have the same underlying buffer giving the wrong size here
2020-04-22 17:25:25 +02:00
67 changed files with 3877 additions and 2938 deletions

116
.eslintrc
View File

@ -1,116 +0,0 @@
{
"root": true,
"env": {
"node" : true,
"es6" : true,
"mocha" : true
},
"globals": {
"expect" : true,
"chai" : true,
"sinon" : true
},
"extends": ["eslint:recommended"],
"parserOptions": {
"ecmaVersion": 8,
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
},
"rules": {
"arrow-parens": ["error", "as-needed"],
"no-trailing-spaces": [
"error",
{
"skipBlankLines": true
}
],
"indent": [
"error",
"tab",
{
"SwitchCase": 1
}
],
"linebreak-style": [
"error",
"unix"
],
"max-len": ["error", 110],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
],
"no-multiple-empty-lines": ["error", { "max": 3, "maxEOF": 1, "maxBOF": 1 }],
"keyword-spacing": ["error", { "before": true, "after": true }],
"space-before-blocks": ["error"],
"space-before-function-paren": ["error", {"anonymous": "always", "named": "never", "asyncArrow": "always"}],
"space-infix-ops": ["error"],
"space-unary-ops": [
"error", {
"words": true,
"nonwords": false,
"overrides": {
"!": true
}
}
],
"spaced-comment": [0],
"camelcase": ["error"],
"no-tabs": [0],
"comma-dangle": [0],
"global-require": [0],
"func-names": [0],
"no-param-reassign": [0],
"no-underscore-dangle": [0],
"no-restricted-syntax": [
"error",
{
"selector": "LabeledStatement",
"message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
},
{
"selector": "WithStatement",
"message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
}
],
"no-mixed-operators": [0],
"no-plusplus": [0],
"comma-spacing": [0],
"default-case": [0],
"no-shadow": [0],
"no-console": [0],
"key-spacing": [0],
"no-return-assign": [0],
"consistent-return": [0],
"class-methods-use-this": [0],
"no-multi-spaces": [
"error",
{
"exceptions": {
"VariableDeclarator": true,
"Property": true,
"ImportDeclaration": true
}
}
],
"array-callback-return": [0],
"no-use-before-define": [
"error",
{
"functions": false,
"classes": true,
"variables": true
}
],
"padded-blocks": [0],
"space-in-parens": [0],
"valid-jsdoc": [0],
"no-unused-expressions": [0],
"import/no-dynamic-require": [0]
}
}

75
.eslintrc.json Normal file
View File

@ -0,0 +1,75 @@
{
"ignorePatterns": [
"src/**"
],
"extends": [
"eslint:recommended",
"plugin:node/recommended"
],
"parserOptions": {
"ecmaVersion": 2022
},
"env": {
"node": true,
"es6": true
},
"rules": {
"arrow-parens": ["error", "always"],
"no-trailing-spaces": [
"error",
{
"skipBlankLines": true
}
],
"indent": [
"error",
"tab",
{
"SwitchCase": 1
}
],
"operator-linebreak": [
"error",
"after",
{
"overrides": {
"?": "before",
":": "before"
}
}
],
"max-len": ["error", 110],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
],
"no-multiple-empty-lines": ["error", { "max": 3, "maxEOF": 1, "maxBOF": 1 }],
"keyword-spacing": ["error", { "before": true, "after": true }],
"space-before-blocks": ["error"],
"space-before-function-paren": ["error", {"anonymous": "always", "named": "never", "asyncArrow": "always"}],
"camelcase": ["error"],
"no-tabs": [0],
"global-require": [0],
"no-underscore-dangle": [0],
"no-plusplus": [0],
"no-shadow": [0],
"node/no-unpublished-require": [0],
"no-process-exit": [0],
"linebreak-style": [0],
"node/no-missing-require": [0],
"no-console": [0],
"node/no-unsupported-features/es-builtins": 0,
"node/no-unsupported-features/node-builtins": 0,
"func-names": [
"error",
"never",
{
"generators": "never"
}
]
}
}

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
test-addon/binding.gyp linguist-vendored

47
.github/workflows/cpplint.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: Cpplint
defaults:
run:
shell: bash
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
eslint:
name: Cpplint
runs-on: ubuntu-20.04
steps:
- name: Fetch Repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18.16.0
cache: 'npm'
- name: Install Modules
run: npm ci
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install Cpplint
run: pip install cpplint
- name: Run Cpplint
run: |
node -e "require('.').cpcpplint()"
cpplint --recursive ./test-addon
cpplint --recursive ./include

36
.github/workflows/eslint.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: ESLint
defaults:
run:
shell: bash
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
eslint:
name: ESLint
runs-on: ubuntu-20.04
steps:
- name: Fetch Repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18.16.0
cache: 'npm'
- name: Install Modules
run: npm ci
- name: Run ESLint
run: npm run eslint

46
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,46 @@
name: Publish to NPM
defaults:
run:
shell: bash
on:
workflow_dispatch
jobs:
Publish:
if: contains('["raub"]', github.actor)
runs-on: ubuntu-latest
steps:
- name: Fetch Repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18.16.0
cache: 'npm'
- name: Get Package Version
id: package-version
run: node -p "'version='+require('./package').version" >> $GITHUB_OUTPUT
- name: Publish
run: |
npm config set //registry.npmjs.org/:_authToken ${NPM_TOKEN}
npm publish --ignore-scripts
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.package-version.outputs.version }}
name: Release ${{ steps.package-version.outputs.version }}
body: Published at ${{ github.sha }}

43
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Test
defaults:
run:
shell: bash
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
unit-tests:
name: Unit Tests
strategy:
matrix:
os: [ubuntu-20.04, windows-2022, macos-11, [self-hosted, linux, ARM64]]
runs-on: ${{ matrix.os }}
steps:
- name: Fetch Repository
uses: actions/checkout@v3
with:
persist-credentials: false
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18.16.0
cache: 'npm'
- name: Install Modules
run: npm ci
- name: Build Sample Addon
run: npm run build-test
- name: Run Unit Tests
run: npm run test-ci

4
.gitignore vendored
View File

@ -4,8 +4,6 @@
.DS_Store .DS_Store
.project .project
.DS_Store .DS_Store
.vscode
.eslintrc
node_modules/ node_modules/
test/build/ test-addon/build/
*.log *.log

View File

@ -1,20 +0,0 @@
language: node_js
node_js:
- "12.13.0"
matrix:
include:
- name: "Linux"
os: linux
dist: xenial
sudo: false
- name: "MacOS"
os: osx
- name: "Windows"
os: windows
install:
- cd test
- npm ci

17
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${workspaceFolder}/**",
"${LocalAppData}/node-gyp/Cache/16.17.0/include/node",
"${LocalAppData}/node-gyp/Cache/18.16.0/include/node"
],
"windowsSdkVersion": "10.0.19041.0",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64"
}
],
"version": 4
}

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018 Luis Blanco Copyright (c) 2023 Luis Blanco
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

152
README.md
View File

@ -2,140 +2,74 @@
This is a part of [Node3D](https://github.com/node-3d) project. This is a part of [Node3D](https://github.com/node-3d) project.
[![NPM](https://nodei.co/npm/addon-tools-raub.png?compact=true)](https://www.npmjs.com/package/addon-tools-raub) [![NPM](https://badge.fury.io/js/addon-tools-raub.svg)](https://badge.fury.io/js/addon-tools-raub)
[![ESLint](https://github.com/node-3d/addon-tools-raub/actions/workflows/eslint.yml/badge.svg)](https://github.com/node-3d/addon-tools-raub/actions/workflows/eslint.yml)
[![Test](https://github.com/node-3d/addon-tools-raub/actions/workflows/test.yml/badge.svg)](https://github.com/node-3d/addon-tools-raub/actions/workflows/test.yml)
[![Cpplint](https://github.com/node-3d/addon-tools-raub/actions/workflows/cpplint.yml/badge.svg)](https://github.com/node-3d/addon-tools-raub/actions/workflows/cpplint.yml)
[![Build Status](https://api.travis-ci.com/node-3d/addon-tools-raub.svg?branch=master)](https://travis-ci.com/node-3d/addon-tools-raub) ```
[![CodeFactor](https://www.codefactor.io/repository/github/node-3d/addon-tools-raub/badge)](https://www.codefactor.io/repository/github/node-3d/addon-tools-raub) npm i -s addon-tools-raub
```
> npm i addon-tools-raub
## Synopsis ## include/addon-tools.hpp
This module contains numerous helpers for Node.js **NAPI**
addons and dependency packages. On this page, helper scripts
are described. For details on **addon-tools.hpp** and some
additional snippets follow the links below.
**Go to**:
* [include/addon-tools.hpp](doc/addon-tools.md)
Macro shortcuts for C++ addons using **NAPI**. Macro shortcuts for C++ addons using **NAPI**.
* [Es5 Class Wrapping](doc/class-wrapping.md) See [docs inside the folder](/include).
An alternative, lightweight native class-defining mechanism for addons. Example of an addon method definition:
* [Snippets](doc/snippets.md)
Some repetitive bits of code for addons. ```
// hpp:
#include <addon-tools.hpp>
DBG_EXPORT JS_METHOD(doSomething);
// cpp:
DBG_EXPORT JS_METHOD(doSomething) { NAPI_ENV;
LET_INT32_ARG(0, param0);
std::cout << "param0: " << param0 << std::endl;
RET_UNDEFINED;
}
```
## index.js ## index.js
Main exports for cross-platform addon configuration. JavaScript helpers for Node.js addon development. The short list of helpers:
* `paths(dir)` - function. Returns a set of platform dependent paths depending on
input `dir`.
* `bin` - platform binary directory absolute path.
* `include` - include directory for this `dir`.
* `include` - both `'addon-tools-raub'` and `'node-addon-api'` include paths.
Use with `node -p` through list context command expansion `<!@(...)`.
* `bin` - platform-dependent binary directory name.
* `platform` - platform name: `'windows', 'linux', 'osx'`.
## download.js
Downloads a file into the memory, **HTTP** or **HTTPS**.
`async WritableBuffer download(string url)` - accepts an **URL**, and
returns an in-memory buffer, when file is loaded.
Example use:
``` ```
download(srcUrl).then( 'getBin', 'getPlatform', 'getInclude', 'getPaths',
data => useData(data), 'install', 'cpbin', 'download', 'read', 'write', 'copy', 'exists',
err => emit('error', err) 'mkdir', 'stat', 'isDir', 'isFile', 'dirUp', 'ensuredir', 'copysafe',
); 'readdir', 'subdirs', 'subfiles', 'traverse', 'copyall',
// or 'rmdir', 'rm', 'WritableBuffer', 'actionPack',
const data = await download(srcUrl);
useData(data);
``` ```
## cpbin.js See the [TypeScript definitions](/index.d.ts) with comments.
Copies the addon binary from **src/build/Release** to the platform folder.
It is useful for development builds. Use it in your **src/package.json**:
```
"scripts": {
"build": "node-gyp rebuild && node -e \"require('addon-tools-raub/cpbin')('ADDON')\""
},
```
Here ADDON should be replaced with the name of your addon, without `.node` extension.
## install.js ### Example for an ADDON's **index.js**:
Downloads and unzips the platform specific binary for the calling package.
To use it, create a new script for your package, which may as well be named
**install.js**, with the following content:
``` ```
'use strict'; const { getBin } = require('addon-tools-raub');
const install = require('addon-tools-raub/install'); const core = require(`./${getBin()}/ADDON`); // uses the platform-specific ADDON.node
const prefix = 'https://github.com/USER/ADDON-NAME/releases/download';
const tag = process.env.npm_package_config_install;
install(`${prefix}/${tag}`);
```
* `prefix` - the constant base part of the download url.
* `tag` - the version-dependent part of the url,
here `process.env.npm_package_config_install` is taken
([automatically](https://docs.npmjs.com/misc/config#per-package-config-settings))
from **package.json**:
```
"config": {
"install": "v2.0.0"
},
"scripts": {
"postinstall": "node install"
},
``` ```
## writable-buffer.js ### Example for **binding.gyp**:
A [Writable](https://nodejs.org/api/stream.html#stream_writable_streams)
stream buffer, that is stored in-memory and can be fully
obtained when writing was finished. It is equivalent to stream-writing
a temporary file and then reading it into a `Buffer`.
Use `stream.get()` to obtain the data when writing was finished:
``` ```
const stream = new WritableBuffer(); 'include_dirs': [
// ... '<!@(node -p "require(\'addon-tools-raub\').getInclude()")',
sourceStream.pipe(stream); ],
sourceStream.on('end', () => useData(stream.get()));
``` ```
> NOTE: the optional `node-addon-api` dependency is used by the `getInclude()` helper. If not found,
the **napi.h** include path won't be a part of the returned string.
## utils.js
* `read` - (async) Reads a whole file to string, NOT A Buffer. ### Example of `cpbin` in **package.json :: scripts**:
* `write` - (async) Write a file.
* `copy` - (async) Copy a file. ```
* `exists` - (async) Check if a file/folder exists. "build": "cd src && node-gyp rebuild -j max --silent && node -e \"require('addon-tools-raub').cpbin('segfault')\" && cd ..",
* `mkdir` - (async) Create an empty folder. "build-only": "cd src && node-gyp build -j max --silent && node -e \"require('addon-tools-raub').cpbin('segfault')\" && cd ..",
* `stat` - (async) Get status on a file. ```
* `isDir` - (async) Check if the path is a folder.
* `isFile` - (async) Check if the path is a file.
* `dirUp` - Cut the path one folder up.
* `ensuredir` - (async) Like `mkdir -p`, makes sure a directory exists.
* `copysafe` - (async) Copy a file, `dest` folder is created if needed.
* `readdir` - (async) Get file/folder names of the 1st level.
* `subdirs` - (async) Get folder paths (concatenated with input) of the 1st level.
* `subfiles` - (async) Get file paths (concatenated with input) of the 1st level.
* `traverse` - (async) Get all nested files recursively.
* `copyall` - (async) Copy a folder with all the contained files.
* `rmdir` - (async) Like `rm -rf`, removes everything recursively.
* `rm` - (async) Remove a file. Must be a file, not a folder. Just `fs.unlink`.

View File

@ -1,31 +0,0 @@
'use strict';
const { copy, exists, mkdir, rm } = require('./utils');
const { bin } = require('.');
module.exports = async name => {
const srcDir = process.cwd().replace(/\\/g, '/');
if ( ! await exists(`${srcDir}/build/Release/${name}.node`) ) {
console.error(`Error. File "${srcDir}/build/Release/${name}.node" not found.`);
}
const binAbs = `${srcDir}/../${bin}`;
if ( ! await exists(binAbs) ) {
await mkdir(binAbs);
}
const destAbs = `${binAbs}/${name}.node`;
if (await exists(destAbs)) {
await rm(destAbs);
}
await copy(`${srcDir}/build/Release/${name}.node`, destAbs);
console.log(`The binary "${name}.node" was copied to "${bin}".`);
};

View File

@ -1,197 +0,0 @@
# Snippets
## C++ Addon building
**NAPI** addons are built separately from the installation, so we shouldn't
put the file **binding.gyp** to the module root anymore. It is better to have a
separate folder with a separate **package.json**, **binding.gyp** and the sources.
A snippet for **src/package.json**:
```
{
"name": "build",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "node-gyp rebuild && node -e \"require('addon-tools-raub/cpbin')('ADDON')\""
},
"dependencies": {
"addon-tools-raub": "5.0.0",
"DEPS": "1.0.0"
}
}
```
* `ADDON` - the name of this addon (and subsequently of its binary).
* `DEPS` - dependency package(s).
### Binary distribution
In **package.json** use the `"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",
},
```
Here `config.install` is the tag name to download the binaries from.
To use it, create the *install.js* file in your addon:
```
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**.
* For a dependency package:
Place the following piece of code in the `index.js` without changes. Method `paths()`
is described [here](../README.md).
```
module.exports = require('addon-tools-raub').paths(__dirname);
```
* For a compiled addon:
Require it in your **index.js** from the platform-specific directory.
```
const { bin } = require('addon-tools-raub');
const core = require(`./${bin}/ADDON`);
```
Publishing binaries 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.
> NOTE: You can publish your binaries to anywhere, not necessarily Github.
Just tweak **YOUR install.js** script as appropriate. The only limitation
from **Addon Tools** is that it should be a zipped set of files/folders.
### GYP Variables
```
'variables': {
'bin' : '<!(node -p "require(\'addon-tools-raub\').bin")',
'DEPS_include' : '<!(node -p "require(\'DEPS\').include")',
'DEPS_bin' : '<!(node -p "require(\'DEPS\').bin")',
},
```
* `bin` - the name of this platform's binary directory, e.g. *bin-linux*.
* `DEPS_include` - the include folder for some dependency package.
* `DEPS_bin` - the binary folder for some dependency package.
### Include directories
```
'include_dirs' : [
'<!@(node -p "require(\'addon-tools-raub\').include")',
'<(DEPS_include)',
],
```
The former contains both the path to include **Addon Tools** and the one for
**Napi** (which is preinstalled with Addon Tools). The latter can be any other
dependency include path(s).
<details>
<summary><b>See a snipped for src/binding.gyp here</b></summary>
* Assume `DEPS` is the name of an Addon Tools compliant dependency module.
* Assume `ADDON` is the name of this addon's resulting binary.
* Assume C++ code goes to `cpp` subdirectory.
```
{
'variables': {
'bin' : '<!(node -p "require(\'addon-tools-raub\').bin")',
'DEPS_include' : '<!(node -p "require(\'DEPS\').include")',
'DEPS_bin' : '<!(node -p "require(\'DEPS\').bin")',
},
'targets': [
{
'target_name' : 'bullet',
'sources' : [
'cpp/addon.cpp',
],
'include_dirs' : [
'<!@(node -p "require(\'addon-tools-raub\').include")',
'<(DEPS_include)',
],
'library_dirs' : [ '<(DEPS_bin)' ],
'libraries' : [ '-lDEPS' ],
'cflags!': ['-fno-exceptions'],
'cflags_cc!': ['-fno-exceptions'],
'conditions': [
[
'OS=="linux"',
{
'libraries': [
"-Wl,-rpath,'$$ORIGIN'",
"-Wl,-rpath,'$$ORIGIN/../node_modules/DEPS/<(bin)'",
"-Wl,-rpath,'$$ORIGIN/../../DEPS/<(bin)'",
],
'defines': ['__linux__'],
}
],
[
'OS=="mac"',
{
'libraries': [
'-Wl,-rpath,@loader_path',
'-Wl,-rpath,@loader_path/../node_modules/DEPS/<(bin)',
'-Wl,-rpath,@loader_path/../../DEPS/<(bin)',
],
'defines': ['__APPLE__'],
}
],
[
'OS=="win"',
{
'defines' : [
'WIN32_LEAN_AND_MEAN',
'VC_EXTRALEAN',
'_WIN32',
],
'msvs_settings' : {
'VCCLCompilerTool' : {
'AdditionalOptions' : [
'/GL', '/GF', '/EHsc', '/GS', '/Gy', '/GR-',
]
},
'VCLinkerTool' : {
'AdditionalOptions' : ['/RELEASE','/OPT:REF','/OPT:ICF','/LTCG'],
},
},
},
],
],
},
]
}
```
</details>

View File

@ -1,28 +0,0 @@
'use strict';
const https = require('https');
const http = require('http');
const WritableBuffer = require('./writable-buffer');
const protocols = { http, https };
module.exports = url => new Promise((res, rej) => {
url = url.toLowerCase();
const stream = new WritableBuffer();
const proto = protocols[url.match(/^https?/)[0]];
proto.get(url, response => {
response.pipe(stream);
response.on('end', () => res(stream.get()));
response.on('error', err => rej(err));
});
});

View File

@ -1,8 +1,9 @@
# include/addon-tools.hpp # include/addon-tools.hpp
There is a C++ header file, `addon-tools.hpp`, shipped with this package. It There is a C++ header file, `addon-tools.hpp`, shipped with this package. It
introduces several useful macros and utilities. Also it includes **Napi** introduces several useful macros and utilities. Also it includes **NAPI**
implicitly, so you can replace: implicitly, so you can replace:
``` ```
#include <napi.h> #include <napi.h>
``` ```
@ -10,18 +11,31 @@ with
``` ```
#include <addon-tools.hpp> #include <addon-tools.hpp>
``` ```
In **GYP**, the include directory should be set for your addon. In **GYP**, the include directory should be set for your addon.
An actual path to the directory is exported from the module An actual path to the directory is exported from the module
and is accessible like this: and is accessible with:
``` ```
require('addon-tools-raub').include // a string require('addon-tools-raub').getInclude() // a string
``` ```
For more examples, see [code snippets here](snippets.md).
### Helpers in **addon-tools.hpp**:
### ES5 Classes
The standard class-defining (i.e. exporting a JS class from the C++ side) tools
from **NAPI** are a bit repetitive and excessive. So instead, Addon Tools
comes with a set of helpers for old-school class definition.
Think of it as ES5 classes. Just a function, spawning instances that have their
constructor and prototype set accordingly. Such classes may be further extended
and/or manipulated from JS-land. See the [class-wrapping doc here](class-wrapping.md).
### Method Helpers
Usually all the helpers work within the context of a method. In this case we Usually all the helpers work within the context of a method. In this case we
have `CallbackInfo info` passed as an argument. And we can return `undefined` have `Napi::CallbackInfo info` passed as an argument. And we can return `undefined`
in case a problem has occured. So most of these macros are only usable in case a problem has occured. So most of these macros are only usable
within `Napi::Value`-returning functions. within `Napi::Value`-returning functions.
@ -30,6 +44,10 @@ within `Napi::Value`-returning functions.
#define NAPI_HS Napi::HandleScope scope(env); #define NAPI_HS Napi::HandleScope scope(env);
``` ```
Other global helpers:
* `DBG_EXPORT`- set symbol visibility (mainly for callstack traces). On Windows, that is
equal to exporting a symbol: `__declspec(dllexport)`. On Unix it does nothing.
<details> <details>
<summary><b>Return value</b></summary> <summary><b>Return value</b></summary>
@ -41,6 +59,7 @@ within `Napi::Value`-returning functions.
* `RET_NUM(VAL)` - return `Napi::Number`, expected `VAL` is of numeric type. * `RET_NUM(VAL)` - return `Napi::Number`, expected `VAL` is of numeric type.
* `RET_EXT(VAL)` - return `Napi::External`, expected `VAL` is a pointer. * `RET_EXT(VAL)` - return `Napi::External`, expected `VAL` is a pointer.
* `RET_BOOL(VAL)` - return `Napi::Boolean`, expected `VAL` is convertible to bool. * `RET_BOOL(VAL)` - return `Napi::Boolean`, expected `VAL` is convertible to bool.
* `RET_ARRAY_STR(VAL)` - return `Napi::Array`, expected `VAL` is `std::vector<std::string>`.
</details> </details>
@ -149,6 +168,7 @@ That extrapolates well to all the helpers below:
| `REQ_ARRAY_ARG` | `object` | `Napi::Array` | - | | `REQ_ARRAY_ARG` | `object` | `Napi::Array` | - |
| `USE_ARRAY_ARG` | `object` | `Napi::Array` | - | | `USE_ARRAY_ARG` | `object` | `Napi::Array` | - |
| `LET_ARRAY_ARG` | `object` | `Napi::Array` | `[]` | | `LET_ARRAY_ARG` | `object` | `Napi::Array` | `[]` |
| `LET_ARRAY_STR_ARG` | `object` | `std::vector<std::string>` | `std::vector<std::string>()` |
| `REQ_FUN_ARG` | `function` | `Napi::Function` | - | | `REQ_FUN_ARG` | `function` | `Napi::Function` | - |
| `REQ_ARRV_ARG` | `ArrayBuffer` | `Napi::ArrayBuffer` | - | | `REQ_ARRV_ARG` | `ArrayBuffer` | `Napi::ArrayBuffer` | - |
| `REQ_BUF_ARG` | `Buffer` | `Napi::Buffer<uint8_t>` | - | | `REQ_BUF_ARG` | `Buffer` | `Napi::Buffer<uint8_t>` | - |

View File

@ -11,6 +11,12 @@
#endif #endif
#ifdef _WIN32
#define DBG_EXPORT __declspec(dllexport)
#else
#define DBG_EXPORT
#endif
#define NAPI_ENV Napi::Env env = info.Env(); #define NAPI_ENV Napi::Env env = info.Env();
#define NAPI_HS Napi::HandleScope scope(env); #define NAPI_HS Napi::HandleScope scope(env);
@ -205,6 +211,46 @@
#define LET_ARRAY_ARG(I, VAR) USE_ARRAY_ARG(I, VAR, Napi::Array::New(env)) #define LET_ARRAY_ARG(I, VAR) USE_ARRAY_ARG(I, VAR, Napi::Array::New(env))
inline std::vector<std::string> arrayStrToVec(const Napi::Array &arr) {
uint32_t count = arr.Length();
std::vector<std::string> result(count);
for (uint32_t i = 0; i < count; i++) {
Napi::Value item = arr[i];
if (item.IsString()) {
result[i] = item.ToString().Utf8Value();
}
}
return result;
}
inline Napi::Array stringsToArray(Napi::Env env, const char **strings, size_t count) {
Napi::Array arr = JS_ARRAY;
for (size_t i = 0; i < count; i++) {
arr.Set(i, strings[i]);
}
return arr;
}
inline Napi::Array vecStrToArray(Napi::Env env, const std::vector<std::string> &strings) {
Napi::Array arr = JS_ARRAY;
size_t count = strings.size();
for (size_t i = 0; i < count; i++) {
arr.Set(i, strings[i]);
}
return arr;
}
#define LET_ARRAY_STR_ARG(I, VAR) \
USE_ARRAY_ARG(I, __ARRAY_ ## VAR, Napi::Array::New(env)); \
std::vector<std::string> VAR = arrayStrToVec(__ARRAY_ ## VAR);
#define RET_ARRAY_STR(VAL) RET_VALUE(vecStrToArray(env, VAL))
#define REQ_TYPED_ARRAY_ARG(I, VAR) \ #define REQ_TYPED_ARRAY_ARG(I, VAR) \
CHECK_REQ_ARG(I, IsTypedArray(), "TypedArray"); \ CHECK_REQ_ARG(I, IsTypedArray(), "TypedArray"); \
Napi::TypedArray VAR = info[I].As<Napi::TypedArray>(); Napi::TypedArray VAR = info[I].As<Napi::TypedArray>();
@ -330,7 +376,6 @@ inline Type* getArrayData(
Napi::Object obj, Napi::Object obj,
int *num = nullptr int *num = nullptr
) { ) {
Type *out = nullptr; Type *out = nullptr;
if (obj.IsTypedArray()) { if (obj.IsTypedArray()) {
@ -338,7 +383,7 @@ inline Type* getArrayData(
size_t offset = ta.ByteOffset(); size_t offset = ta.ByteOffset();
Napi::ArrayBuffer arr = ta.ArrayBuffer(); Napi::ArrayBuffer arr = ta.ArrayBuffer();
if (num) { if (num) {
*num = arr.ByteLength() / sizeof(Type); *num = ta.ByteLength() / sizeof(Type);
} }
uint8_t *base = reinterpret_cast<uint8_t *>(arr.Data()); uint8_t *base = reinterpret_cast<uint8_t *>(arr.Data());
out = reinterpret_cast<Type *>(base + offset); out = reinterpret_cast<Type *>(base + offset);
@ -356,16 +401,15 @@ inline Type* getArrayData(
} }
return out; return out;
} }
template<typename Type = uint8_t> template<typename Type = uint8_t>
inline Type* getBufferData( inline Type* getBufferData(
Napi::Env env, Napi::Env env,
Napi::Object obj, Napi::Object obj,
int *num = nullptr int *num = nullptr
) { ) {
Type *out = nullptr; Type *out = nullptr;
if (num) { if (num) {
@ -384,12 +428,10 @@ inline Type* getBufferData(
out = arr.Data(); out = arr.Data();
return out; return out;
} }
inline void *getData(Napi::Env env, Napi::Object obj) { inline void *getData(Napi::Env env, Napi::Object obj) {
void *out = nullptr; void *out = nullptr;
if (obj.IsTypedArray() || obj.IsArrayBuffer()) { if (obj.IsTypedArray() || obj.IsArrayBuffer()) {
@ -406,7 +448,6 @@ inline void *getData(Napi::Env env, Napi::Object obj) {
} }
return out; return out;
} }
@ -433,40 +474,12 @@ inline Napi::Value consoleLog(Napi::Env env, const std::string &message) {
inline void eventEmit( inline void eventEmit(
Napi::Object that,
const std::string &name,
int argc = 0,
const Napi::Value *argv = nullptr
) {
if ( ! that.Has("emit") ) {
return;
}
Napi::Env env = that.Env();
Napi::String eventName = JS_STR(name);
Napi::Function thatEmit = that.Get("emit").As<Napi::Function>();
std::vector<napi_value> args;
args.push_back(napi_value(eventName));
for (int i = 0; i < argc; i++) {
args.push_back(napi_value(argv[i]));
}
thatEmit.Call(that, args);
}
inline void eventEmitAsync(
Napi::Object that, Napi::Object that,
const std::string &name, const std::string &name,
int argc = 0, int argc = 0,
const Napi::Value *argv = nullptr, const Napi::Value *argv = nullptr,
napi_async_context context = nullptr napi_async_context context = nullptr
) { ) {
if (!that.Has("emit")) { if (!that.Has("emit")) {
return; return;
} }
@ -482,8 +495,11 @@ inline void eventEmitAsync(
args.push_back(napi_value(argv[i])); args.push_back(napi_value(argv[i]));
} }
if (context) {
thatEmit.MakeCallback(that, args, context); thatEmit.MakeCallback(that, args, context);
} else {
thatEmit.Call(that, args);
}
} }

View File

@ -31,7 +31,6 @@ public:
JS_DECLARE_METHOD(ClassName, ClassName, destroy); JS_DECLARE_METHOD(ClassName, ClassName, destroy);
bool _isDestroyed; bool _isDestroyed;
}; };
``` ```
@ -62,13 +61,10 @@ void ClassName::init(Napi::Env env, Napi::Object exports) {
} }
ClassName::ClassName(const Napi::CallbackInfo &info) { NAPI_ENV; ClassName::ClassName(const Napi::CallbackInfo &info) { NAPI_ENV;
super(info); super(info);
_isDestroyed = false; _isDestroyed = false;
// ... // ...
} }
ClassName::~ClassName() { ClassName::~ClassName() {

65
include/index.js Normal file
View File

@ -0,0 +1,65 @@
'use strict';
const path = require('node:path');
const nameWindows = 'windows';
const platformAndArch = `${process.platform}-${process.arch}`;
const platformNames = {
'win32-x64': nameWindows,
'linux-x64': 'linux',
'darwin-x64': 'osx',
'linux-arm64': 'aarch64',
};
const platformName = platformNames[platformAndArch] || platformAndArch;
const isWindows = platformName === nameWindows;
const getPaths = (dir) => {
dir = dir.replace(/\\/g, '/');
const bin = `${dir}/bin-${platformName}`;
const include = `${dir}/include`;
if (isWindows) {
process.env.path = `${bin};${process.env.path ? `${process.env.path}` : ''}`;
}
return { bin, include };
};
const getBin = () => {
return `bin-${platformName}`;
};
const getPlatform = () => {
return platformName;
};
const getInclude = () => {
let napi = null;
try {
napi = require('node-addon-api');
} catch (ex) {
// do nothing
}
const rootPath = path.resolve(`${__dirname}/..`).replace(/\\/g, '/');
const napiInclude = napi ? napi.include_dir.replace(/\\/g, '/') : '';
const thisInclude = `${rootPath}/include`;
const includePath = `${napiInclude} ${thisInclude}`;
return includePath;
};
module.exports = {
getPaths,
getBin,
getPlatform,
getInclude,
};

41
include/index.test.js Normal file
View File

@ -0,0 +1,41 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const tools = require('.');
describe('AT / include', () => {
const stringMethods = ['getBin', 'getPlatform', 'getInclude'];
stringMethods.forEach((name) => {
describe(`#${name}()`, () => {
it('is a function', () => {
assert.strictEqual(typeof tools[name], 'function');
});
it('returns an object', () => {
assert.strictEqual(typeof tools[name](), 'string');
});
});
});
describe('#getPaths()', () => {
it('is a function', () => {
assert.strictEqual(typeof tools.getPaths, 'function');
});
it('returns an object', () => {
assert.strictEqual(typeof tools.getPaths(__dirname), 'object');
});
it('has "include" string', () => {
assert.strictEqual(typeof tools.getPaths(__dirname).include, 'string');
});
it('has "bin" string', () => {
assert.strictEqual(typeof tools.getPaths(__dirname).include, 'string');
});
});
});

81
include/snippets.md Normal file
View File

@ -0,0 +1,81 @@
# Snippets
## C++ Addon building
### Binary distribution
In **package.json** use the `"postinstall"` script to download the libraries.
For example the following structure might work. Note that **Addon Tools** will
append any given URL with `/${getPlatform()}.gz`
In **package.json**:
```
"scripts": {
"postinstall": "node install",
},
"dependencies": {
"addon-tools-raub": "^7.0.0",
},
"devDependencies": {
"node-addon-api": "^5.0.0"
}
```
Create the **install.js** file, see `install` in [index.d.ts](/index.d.ts).
**Addon Tools** will unpack (using **tar**) the downloaded file into the platform binary
directory. E.g. on Windows it will be **bin-windows**.
* For a dependency package:
Place the following piece of code into the `index.js` without changes.
```
module.exports = require('addon-tools-raub').getPaths(__dirname);
```
* For a compiled addon:
Require the `ADDON.node` in your **index.js** from the platform-specific directory.
```
const { getBin } = require('addon-tools-raub');
const core = require(`./${getBin()}/ADDON`);
```
Publishing binaries is done by attaching a GZIPped platform folder to a 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
**install.js**.
> NOTE: You can publish your binaries to anywhere, not necessarily GitHub.
Just tweak **YOUR install.js** script as appropriate. The only limitation
from **Addon Tools** is that it should be a GZIPped set of files/folders.
### GYP Variables
```
'variables': {
'bin': '<!(node -p "require(\'addon-tools-raub\').getBin()")',
'DEPS_include': '<!(node -p "require(\'DEPS\').getInclude()")',
'DEPS_bin': '<!(node -p "require(\'DEPS\').getBin()")',
},
```
* `bin` - the name of this platform's binary directory, e.g. *bin-linux*.
* `DEPS_include` - the include folder for some dependency package.
* `DEPS_bin` - the binary folder for some dependency package.
### Include directories
```
'include_dirs' : [
'<!@(node -p "require(\'addon-tools-raub\').getInclude()")',
'<(DEPS_include)',
],
```
See example of a working [**binding.gyp** here](/test-addon/binding.gyp)

361
index.d.ts vendored Normal file
View File

@ -0,0 +1,361 @@
declare module "addon-tools-raub" {
type Stats = import('node:fs').Stats;
type Writable = import('node:stream').Writable;
type Readable = import('node:stream').Readable;
type WritableOptions = import('node:stream').WritableOptions;
/**
* Get the internal paths for an addon
*
* Returns a set of platform dependent paths depending on the input dir
*/
export const getPaths: (dir: string) => Readonly<{
/**
* Path to binaries
*
* Platform binary directory absolute path for this `dir`
*/
bin: string;
/**
* Path to include
*
* Include directory for this `dir`
*/
include: string;
}>;
type TPlatformName = 'windows' | 'linux' | 'osx' | 'aarch64';
type TPlatformDir = `bin-${TPlatformName}`;
/**
* Get the platform-specific binary directory name
*/
export const getBin: () => TPlatformDir;
/**
* Get the platform identifier
*/
export const getPlatform: () => TPlatformName;
/**
* Get the include directories for **binding.gyp**
*
* Both 'addon-tools-raub' and 'node-addon-api' include paths.
* In binding.gyp: `'<!@(node -p "require(\'addon-tools-raub\').getInclude()")'`
*/
export const getInclude: () => string;
/**
* Install binaries
*
* Downloads and unpacks the platform specific binary for the calling package.
* To use it, create a new script for your package, which may as well be named
* **install.js**, with the following content:
*
* ```
* 'use strict';
* const { install } = require('addon-tools-raub');
* const prefix = 'https://github.com/USER/ADDON-NAME/releases/download';
* const tag = '1.0.0';
* install(`${prefix}/${tag}`);
* ```
*
* * `prefix` - the constant base part of the download url.
* * `tag` - the version-dependent part of the url.
*
* ```
* "scripts": {
* "postinstall": "node install"
* },
* ```
*/
export const install: (folder: string) => Promise<boolean>;
/**
* Copy binary
*
* Copies the addon binary from `src/build/Release` to the platform-specific folder.
*
* ```
* "scripts": {
* * "build": "node-gyp rebuild && node -e \"require('addon-tools-raub').cpbin('ADDON')\""
* },
* ```
*
* Here ADDON should be replaced with the name of your addon, without `.node` extension.
*/
export const cpbin: (name: string) => Promise<void>;
/**
* Packs binaries into GZIP
*
* Example of `actionPack` usage in **Github Actions**:
*
* ```
* - name: Pack Files
* id: pack-files
* run: node -e "require('addon-tools-raub').actionPack()" >> $GITHUB_OUTPUT
* - name: Store Binaries
* uses: softprops/action-gh-release@v1
* with:
* files: ${{ steps.pack-files.outputs.pack }}
* ```
*/
export const actionPack: () => Promise<void>;
/**
* Download to memory
*
* Accepts an **URL**, and returns an in-memory file Buffer,
* when the file is loaded. Use for small files, as the whole
* file will be loaded into memory at once.
*
* ```
* download(srcUrl).then(data => useData(data), err => emit('error', err));
* ```
* or
* ```
* const data = await download(srcUrl);
* useData(data);
* ```
*/
export const download: (url: string) => Promise<Buffer>;
/**
* (async) Read a file
*
* Reads a whole file to string, NOT A Buffer
*/
type ComposeFnParam = (source: any) => void;
/**
* WritableBuffer
*
* A [Writable](https://nodejs.org/api/stream.html#stream_writable_streams)
* stream buffer, that is stored in-memory and can be fully
* obtained when writing was finished. It is equivalent to stream-writing
* a temporary file and then reading it into a `Buffer`.
*/
export class WritableBuffer implements Writable {
constructor();
/**
* Get the downloaded data
* Use `stream.get()` to obtain the data when writing was finished
*/
get(): Buffer;
// ----------- implements Writable
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableHighWaterMark: number;
readonly writableLength: number;
readonly writableObjectMode: boolean;
readonly writableCorked: number;
destroyed: boolean;
readonly closed: boolean;
readonly errored: Error | null;
readonly writableNeedDrain: boolean;
constructor(opts?: WritableOptions);
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
_writev?(
chunks: Array<{
chunk: any;
encoding: BufferEncoding;
}>,
callback: (error?: Error | null) => void,
): void;
_construct?(callback: (error?: Error | null) => void): void;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
_final(callback: (error?: Error | null) => void): void;
write(chunk: any, callback?: (error: Error | null | undefined) => void): boolean;
write(chunk: any, encoding: BufferEncoding, callback?: (error: Error | null | undefined) => void): boolean;
setDefaultEncoding(encoding: BufferEncoding): this;
end(cb?: () => void): this;
end(chunk: any, cb?: () => void): this;
end(chunk: any, encoding: BufferEncoding, cb?: () => void): this;
cork(): void;
uncork(): void;
destroy(error?: Error): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "pipe", listener: (src: Readable) => void): this;
addListener(event: "unpipe", listener: (src: Readable) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "drain"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "pipe", src: Readable): boolean;
emit(event: "unpipe", src: Readable): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "drain", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "pipe", listener: (src: Readable) => void): this;
on(event: "unpipe", listener: (src: Readable) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "drain", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "pipe", listener: (src: Readable) => void): this;
once(event: "unpipe", listener: (src: Readable) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "pipe", listener: (src: Readable) => void): this;
prependListener(event: "unpipe", listener: (src: Readable) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "pipe", listener: (src: Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: "close", listener: () => void): this;
removeListener(event: "drain", listener: () => void): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "finish", listener: () => void): this;
removeListener(event: "pipe", listener: (src: Readable) => void): this;
removeListener(event: "unpipe", listener: (src: Readable) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
pipe<T extends NodeJS.WritableStream>(
destination: T,
options?: {
end?: boolean | undefined;
},
): T;
compose<T extends NodeJS.ReadableStream>(
stream: T | ComposeFnParam | Iterable<T> | AsyncIterable<T>,
options?: { signal: AbortSignal },
): T;
off(eventName: string | symbol, listener: (...args: any[]) => void): this;
removeAllListeners(event?: string | symbol): this;
setMaxListeners(n: number): this;
getMaxListeners(): number;
listeners(eventName: string | symbol): Function[];
rawListeners(eventName: string | symbol): Function[];
emit(eventName: string | symbol, ...args: any[]): boolean;
listenerCount(eventName: string | symbol, listener?: Function): number;
eventNames(): Array<string | symbol>;
}
export const read: (name: string) => Promise<string>;
/**
* (async) Write a file
*/
export const write: (name: string, text: string) => Promise<void>;
/**
* (async) Copy a file
*/
export const copy: (src: string, dest: string) => Promise<void>;
/**
* (async) Check if a file/folder exists
*/
export const exists: (name: string) => Promise<boolean>;
/**
* (async) Create an empty folder
*/
export const mkdir: (name: string) => Promise<void>;
/**
* (async) Get status on a file
*/
export const stat: (name: string) => Promise<Stats>;
/**
* (async) Check if the path is a folder
*/
export const isDir: (name: string) => Promise<boolean>;
/**
* (async) Check if the path is a file
*/
export const isFile: (name: string) => Promise<boolean>;
/**
* Cut the path one folder up
*/
export const dirUp: (dir: string) => string;
/**
* (async) Create a directory
*
* Like `mkdir -p`, makes sure a directory exists
*/
export const ensuredir: (dir: string) => Promise<void>;
/**
* (async) Copy a file
*
* Copy a file, `dest` folder is created if needed
*/
export const copysafe: (src: string, dest: string) => Promise<void>;
/**
* (async) Read a directory
*
* Get file/folder names of the 1st level
*/
export const readdir: (src: string, dest: string) => Promise<ReadonlyArray<string>>;
/**
* (async) List subdirectories
*
* Get folder paths (concatenated with input) of the 1st level
*/
export const subdirs: (name: string) => Promise<ReadonlyArray<string>>;
/**
* (async) List nested files
*
* Get file paths (concatenated with input) of the 1st level
*/
export const subfiles: (name: string) => Promise<ReadonlyArray<string>>;
/**
* (async) Get all nested files recursively
*
* Folder paths are omitted by default.
* Order is: shallow-to-deep, each subdirectory lists dirs-then-files.
*/
export const traverse: (name: string, showDirs?: boolean) => Promise<ReadonlyArray<string>>;
/**
* (async) Copy a directory
*
* Copy a folder with all the contained files
*/
export const copyall: (src: string, dest: string) => Promise<void>;
/**
* (async) Remove a directory
*
* Like `rm -rf`, removes everything recursively
*/
export const rmdir: (name: string) => Promise<void>;
/**
* (async) Remove a file
*
* Must be a file, not a folder. Just `fs.unlink`.
*/
export const rm: (name: string) => Promise<void>;
}

View File

@ -1,48 +1,3 @@
'use strict'; 'use strict';
const platformNames = { module.exports = Object.assign({}, require('./include'), require('./utils'));
win32 : 'windows',
linux : 'linux',
darwin : 'osx',
};
const platformName = platformNames[process.platform];
const isWindows = process.platform === 'win32';
if ( ! platformName ) {
console.log(`Error: UNKNOWN PLATFORM "${process.platform}"`);
}
const rootPath = __dirname.replace(/\\/g, '/');
const napiInclude = require('node-addon-api').include.replace(/\\/g, '/');
const thisInclude = `${rootPath}/include`;
const includePath = `${napiInclude} ${thisInclude}`;
const paths = dir => {
dir = dir.replace(/\\/g, '/');
const bin = `${dir}/bin-${platformName}`;
const include = `${dir}/include`;
if (isWindows) {
process.env.path = `${bin};${process.env.path ? `${process.env.path}` : ''}`;
}
return { bin, include };
};
module.exports = {
paths,
bin : `bin-${platformName}`,
platform : platformName,
include : includePath,
};

View File

@ -1,74 +0,0 @@
'use strict';
const https = require('https');
const http = require('http');
const fs = require('fs');
const AdmZip = require('adm-zip');
const { bin, platform } = require('.');
const { mkdir, rm } = require('./utils');
const protocols = { http, https };
const onError = msg => {
console.error(msg);
process.exit(-1);
};
const zipPath = `${bin}/${bin}.zip`;
const install = async (url, count = 1) => {
try {
const proto = protocols[url.match(/^https?/)[0]];
const response = await new Promise((res, rej) => {
const request = proto.get(url, response => res(response));
request.on('error', err => rej(err));
});
response.on('error', err => { throw err; });
// Handle redirects
if ([301, 302, 303, 307].includes(response.statusCode)) {
if (count < 5) {
return install(response.headers.location, count + 1);
}
console.log(url);
throw new Error('Error: Too many redirects.');
}
// Handle bad status
if (response.statusCode !== 200) {
console.log(url);
throw new Error(`Response status was ${response.statusCode}`);
}
await mkdir(bin);
await new Promise((res, rej) => {
const zipWriter = fs.createWriteStream(zipPath);
zipWriter.on('error', err => rej(err));
zipWriter.on('finish', () => res());
response.pipe(zipWriter);
});
const zip = new AdmZip(zipPath);
zip.extractAllTo(bin, true);
await rm(zipPath);
} catch (ex) {
onError(ex.message);
}
};
module.exports = folder => {
const url = `${folder}/${platform}.zip`;
install(url).then();
};

1309
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{ {
"author": "Luis Blanco <luisblanco1337@gmail.com>", "author": "Luis Blanco <luisblanco1337@gmail.com>",
"name": "addon-tools-raub", "name": "addon-tools-raub",
"version": "5.1.0", "version": "7.4.0",
"description": "Helpers for Node.js addons and dependency packages", "description": "Helpers for Node.js addons and dependency packages",
"license": "MIT", "license": "MIT",
"main": "index.js", "main": "index.js",
@ -19,26 +19,42 @@
], ],
"files": [ "files": [
"include", "include",
"download.js",
"cpbin.js",
"index.js",
"install.js",
"utils.js", "utils.js",
"writable-buffer.js", "utils.d.ts",
"index.js",
"index.d.ts",
"utils",
"LICENSE", "LICENSE",
"package.json", "package.json",
"README.md" "README.md"
], ],
"engines": { "engines": {
"node": ">=12.13.0", "node": ">=18.16.0",
"npm": ">=6.12.0" "npm": ">=9.5.1"
},
"scripts": {
"eslint": "eslint .",
"test": "node --test --watch .",
"test-ci": "node --test",
"build-test": "cd test-addon && node-gyp rebuild -j max --silent && cd .."
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/node-3d/addon-tools-raub.git" "url": "https://github.com/node-3d/addon-tools-raub.git"
}, },
"dependencies": { "peerDependencies": {
"adm-zip": "0.4.14", "node-addon-api": "^7.0.0"
"node-addon-api": "2.0.0" },
"peerDependenciesMeta": {
"node-addon-api": {
"optional": true
}
},
"devDependencies": {
"@types/node": "^20.8.3",
"eslint": "^8.51.0",
"eslint-plugin-node": "^11.1.0",
"node-addon-api": "^7.0.0",
"typescript": "^5.2.2"
} }
} }

37
test-addon/binding.gyp vendored Normal file
View File

@ -0,0 +1,37 @@
{
'targets': [{
'target_name': 'test',
'sources': [
'test.cpp',
],
'cflags_cc': ['-std=c++17', '-fno-exceptions'],
'include_dirs': [
'<!@(node -p "require(\'..\').getInclude()")',
],
'conditions': [
['OS=="linux"', {
'defines': ['__linux__'],
}],
['OS=="mac"', {
'MACOSX_DEPLOYMENT_TARGET': '10.9',
'defines': ['__APPLE__'],
'CLANG_CXX_LIBRARY': 'libc++',
'OTHER_CFLAGS': ['-std=c++17', '-fno-exceptions'],
}],
['OS=="win"', {
'defines' : ['WIN32_LEAN_AND_MEAN', 'VC_EXTRALEAN', '_WIN32', '_HAS_EXCEPTIONS=0'],
'msvs_settings' : {
'VCCLCompilerTool' : {
'AdditionalOptions' : [
'/O2','/Oy','/GL','/GF','/Gm-', '/std:c++17',
'/EHa-s-c-','/MT','/GS','/Gy','/GR-','/Gd',
],
},
'VCLinkerTool' : {
'AdditionalOptions' : ['/DEBUG:NONE', '/LTCG', '/OPT:NOREF'],
},
},
}],
],
}],
}

View File

@ -0,0 +1,45 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const arrayArgLetMsg = { message: 'Argument 0 must be of type `Array` or be `null`/`undefined`' };
describe('AT / HPP / LET_ARRAY_ARG', () => {
it('exports letArrayStrArg', () => {
assert.strictEqual(typeof test.letArrayStrArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letArrayStrArg('1'), arrayArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.letArrayStrArg(1), arrayArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letArrayStrArg(true), arrayArgLetMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.letArrayStrArg(test.retExt()), arrayArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letArrayStrArg({}), arrayArgLetMsg);
});
it('accepts an empty arg', () => {
assert.ok(Array.isArray(test.letArrayStrArg()));
});
it('accepts undefined', () => {
assert.ok(Array.isArray(test.letArrayStrArg(undefined)));
});
it('accepts null', () => {
assert.ok(Array.isArray(test.letArrayStrArg(null)));
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.letArrayStrArg([])));
});
it('returns same array', () => {
assert.deepStrictEqual(test.letArrayStrArg(['a', 'b']),['a', 'b']);
});
});

View File

@ -0,0 +1,109 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const arrayArgMsg = { message: 'Argument 0 must be of type `Array`' };
const arrayArgLetMsg = { message: 'Argument 0 must be of type `Array` or be `null`/`undefined`' };
describe('AT / HPP / REQ_ARRAY_ARG', () => {
it('exports reqArrayArg', () => {
assert.strictEqual(typeof test.reqArrayArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqArrayArg(), arrayArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqArrayArg(undefined), arrayArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqArrayArg(null), arrayArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqArrayArg('1'), arrayArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqArrayArg(1), arrayArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqArrayArg(true), arrayArgMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.reqArrayArg(test.retExt()), arrayArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqArrayArg({}), arrayArgMsg);
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.reqArrayArg([])));
});
});
describe('addon-tools.hpp: LET_ARRAY_ARG', () => {
it('exports letArrayArg', () => {
assert.strictEqual(typeof test.letArrayArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letArrayArg('1'), arrayArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.letArrayArg(1), arrayArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letArrayArg(true), arrayArgLetMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.letArrayArg(test.retExt()), arrayArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letArrayArg({}), arrayArgLetMsg);
});
it('accepts an empty arg', () => {
assert.ok(Array.isArray(test.letArrayArg()));
});
it('accepts undefined', () => {
assert.ok(Array.isArray(test.letArrayArg(undefined)));
});
it('accepts null', () => {
assert.ok(Array.isArray(test.letArrayArg(null)));
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.letArrayArg([])));
});
});
describe('addon-tools.hpp: USE_ARRAY_ARG', () => {
it('exports useArrayArg', () => {
assert.strictEqual(typeof test.useArrayArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useArrayArg('1'), arrayArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.useArrayArg(1), arrayArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useArrayArg(true), arrayArgLetMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.useArrayArg(test.retExt()), arrayArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useArrayArg({}), arrayArgLetMsg);
});
it('accepts an empty arg', () => {
assert.ok(Array.isArray(test.useArrayArg()));
});
it('accepts undefined', () => {
assert.ok(Array.isArray(test.useArrayArg(undefined)));
});
it('accepts null', () => {
assert.ok(Array.isArray(test.useArrayArg(null)));
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.useArrayArg([])));
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const boolArgMsg = { message: 'Argument 0 must be of type `Bool`' };
const boolArgLetMsg = { message: 'Argument 0 must be of type `Bool` or be `null`/`undefined`' };
describe('AT / HPP / REQ_BOOL_ARG', () => {
it('exports reqBoolArg', () => {
assert.strictEqual(typeof test.reqBoolArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqBoolArg(), boolArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqBoolArg(undefined), boolArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqBoolArg(null), boolArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqBoolArg('1'), boolArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqBoolArg(1), boolArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqBoolArg({}), boolArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqBoolArg([]), boolArgMsg);
});
it('accepts a boolean', () => {
assert.ok(test.reqBoolArg(true));
});
});
describe('addon-tools.hpp: LET_BOOL_ARG', () => {
it('exports letBoolArg', () => {
assert.strictEqual(typeof test.letBoolArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letBoolArg('1'), boolArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.letBoolArg(1), boolArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letBoolArg({}), boolArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letBoolArg([]), boolArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letBoolArg(), false);
});
it('accepts undefined', () => {
assert.strictEqual(test.letBoolArg(undefined), false);
});
it('accepts null', () => {
assert.strictEqual(test.letBoolArg(null), false);
});
it('accepts a boolean', () => {
assert.ok(test.letBoolArg(true));
});
});
describe('addon-tools.hpp: USE_BOOL_ARG', () => {
it('exports useBoolArg', () => {
assert.strictEqual(typeof test.useBoolArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useBoolArg('1'), boolArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.useBoolArg(1), boolArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useBoolArg({}), boolArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useBoolArg([]), boolArgLetMsg);
});
it('accepts an empty arg', () => {
assert.ok(test.useBoolArg());
});
it('accepts undefined', () => {
assert.ok(test.useBoolArg(undefined));
});
it('accepts null', () => {
assert.ok(test.useBoolArg(null));
});
it('accepts a boolean', () => {
assert.ok(test.useBoolArg(true));
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const numArgMsg = { message: 'Argument 0 must be of type `Number`' };
const numArgLetMsg = { message: 'Argument 0 must be of type `Number` or be `null`/`undefined`' };
describe('AT / HPP / REQ_DOUBLE_ARG', () => {
it('exports reqDoubleArg', () => {
assert.strictEqual(typeof test.reqDoubleArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqDoubleArg(), numArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqDoubleArg(undefined), numArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqDoubleArg(null), numArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqDoubleArg('1'), numArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqDoubleArg(true), numArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqDoubleArg({}), numArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqDoubleArg([]), numArgMsg);
});
it('accepts a number', () => {
assert.strictEqual(test.reqDoubleArg(55), 55);
});
});
describe('addon-tools.hpp: LET_DOUBLE_ARG', () => {
it('exports letDoubleArg', () => {
assert.strictEqual(typeof test.letDoubleArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letDoubleArg('1'), numArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letDoubleArg(true), numArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letDoubleArg({}), numArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letDoubleArg([]), numArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letDoubleArg(), 0);
});
it('accepts undefined', () => {
assert.strictEqual(test.letDoubleArg(undefined), 0);
});
it('accepts null', () => {
assert.strictEqual(test.letDoubleArg(null), 0);
});
it('accepts a number', () => {
assert.strictEqual(test.letDoubleArg(55), 55);
});
});
describe('addon-tools.hpp: USE_DOUBLE_ARG', () => {
it('exports useDoubleArg', () => {
assert.strictEqual(typeof test.useDoubleArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useDoubleArg('1'), numArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useDoubleArg(true), numArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useDoubleArg({}), numArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useDoubleArg([]), numArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.useDoubleArg(), 10);
});
it('accepts undefined', () => {
assert.strictEqual(test.useDoubleArg(undefined), 10);
});
it('accepts null', () => {
assert.strictEqual(test.useDoubleArg(null), 10);
});
it('accepts a number', () => {
assert.strictEqual(test.useDoubleArg(55), 55);
});
});

View File

@ -0,0 +1,109 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const extArgMsg = { message: 'Argument 0 must be of type `Pointer`' };
const extArgLetMsg = { message: 'Argument 0 must be of type `Pointer` or be `null`/`undefined`' };
describe('AT / HPP / REQ_EXT_ARG', () => {
it('exports reqExtArg', () => {
assert.strictEqual(typeof test.reqExtArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqExtArg(), extArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqExtArg(undefined), extArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqExtArg(null), extArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqExtArg('1'), extArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqExtArg(1), extArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqExtArg(true), extArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqExtArg({}), extArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqExtArg([]), extArgMsg);
});
it('accepts a pointer', () => {
assert.strictEqual(typeof test.reqExtArg(test.retExt()), 'object');
});
});
describe('addon-tools.hpp: LET_EXT_ARG', () => {
it('exports letExtArg', () => {
assert.strictEqual(typeof test.letExtArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letExtArg('1'), extArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.letExtArg(1), extArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letExtArg(true), extArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letExtArg({}), extArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letExtArg([]), extArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(typeof test.letExtArg(), 'object');
});
it('accepts undefined', () => {
assert.strictEqual(typeof test.letExtArg(undefined), 'object');
});
it('accepts null', () => {
assert.strictEqual(typeof test.letExtArg(null), 'object');
});
it('accepts a pointer', () => {
assert.strictEqual(typeof test.reqExtArg(test.retExt()), 'object');
});
});
describe('addon-tools.hpp: USE_EXT_ARG', () => {
it('exports useExtArg', () => {
assert.strictEqual(typeof test.useExtArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useExtArg('1'), extArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.useExtArg(1), extArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useExtArg(true), extArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useExtArg({}), extArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useExtArg([]), extArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(typeof test.useExtArg(), 'object');
});
it('accepts undefined', () => {
assert.strictEqual(typeof test.useExtArg(undefined), 'object');
});
it('accepts null', () => {
assert.strictEqual(typeof test.useExtArg(null), 'object');
});
it('accepts a number', () => {
assert.strictEqual(typeof test.useExtArg(test.retExt()), 'object');
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const numArgMsg = { message: 'Argument 0 must be of type `Number`' };
const numArgLetMsg = { message: 'Argument 0 must be of type `Number` or be `null`/`undefined`' };
describe('AT / HPP / REQ_FLOAT_ARG', () => {
it('exports reqFloatArg', () => {
assert.strictEqual(typeof test.reqFloatArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqFloatArg(), numArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqFloatArg(undefined), numArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqFloatArg(null), numArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqFloatArg('1'), numArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqFloatArg(true), numArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqFloatArg({}), numArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqFloatArg([]), numArgMsg);
});
it('accepts a number', () => {
assert.strictEqual(test.reqFloatArg(55), 55);
});
});
describe('addon-tools.hpp: LET_FLOAT_ARG', () => {
it('exports letFloatArg', () => {
assert.strictEqual(typeof test.letFloatArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letFloatArg('1'), numArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letFloatArg(true), numArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letFloatArg({}), numArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letFloatArg([]), numArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letFloatArg(), 0);
});
it('accepts undefined', () => {
assert.strictEqual(test.letFloatArg(undefined), 0);
});
it('accepts null', () => {
assert.strictEqual(test.letFloatArg(null), 0);
});
it('accepts a number', () => {
assert.strictEqual(test.letFloatArg(55), 55);
});
});
describe('addon-tools.hpp: USE_FLOAT_ARG', () => {
it('exports useFloatArg', () => {
assert.strictEqual(typeof test.useFloatArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useFloatArg('1'), numArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useFloatArg(true), numArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useFloatArg({}), numArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useFloatArg([]), numArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.useFloatArg(), 10);
});
it('accepts undefined', () => {
assert.strictEqual(test.useFloatArg(undefined), 10);
});
it('accepts null', () => {
assert.strictEqual(test.useFloatArg(null), 10);
});
it('accepts a number', () => {
assert.strictEqual(test.useFloatArg(55), 55);
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const intArgMsg = { message: 'Argument 0 must be of type `Int32`' };
const intArgLetMsg = { message: 'Argument 0 must be of type `Int32` or be `null`/`undefined`' };
describe('AT / HPP / REQ_INT_ARG, REQ_INT32_ARG', () => {
it('exports reqIntArg', () => {
assert.strictEqual(typeof test.reqIntArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqIntArg(), intArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqIntArg(undefined), intArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqIntArg(null), intArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqIntArg('1'), intArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqIntArg(true), intArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqIntArg({}), intArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqIntArg([]), intArgMsg);
});
it('accepts a number', () => {
assert.strictEqual(test.reqIntArg(55), 55);
});
});
describe('addon-tools.hpp: LET_INT_ARG / LET_INT32_ARG', () => {
it('exports letIntArg', () => {
assert.strictEqual(typeof test.letIntArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letIntArg('1'), intArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letIntArg(true), intArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letIntArg({}), intArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letIntArg([]), intArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letIntArg(), 0);
});
it('accepts undefined', () => {
assert.strictEqual(test.letIntArg(undefined), 0);
});
it('accepts null', () => {
assert.strictEqual(test.letIntArg(null), 0);
});
it('accepts a number', () => {
assert.strictEqual(test.letIntArg(55), 55);
});
});
describe('addon-tools.hpp: USE_INT_ARG / USE_INT32_ARG', () => {
it('exports useIntArg', () => {
assert.strictEqual(typeof test.useIntArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useIntArg('1'), intArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useIntArg(true), intArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useIntArg({}), intArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useIntArg([]), intArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.useIntArg(), 10);
});
it('accepts undefined', () => {
assert.strictEqual(test.useIntArg(undefined), 10);
});
it('accepts null', () => {
assert.strictEqual(test.useIntArg(null), 10);
});
it('accepts a number', () => {
assert.strictEqual(test.useIntArg(55), 55);
});
});

View File

@ -0,0 +1,109 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const objArgMsg = { message: 'Argument 0 must be of type `Object`' };
const objArgLetMsg = { message: 'Argument 0 must be of type `Object` or be `null`/`undefined`' };
describe('AT / HPP / REQ_OBJ_ARG', () => {
it('exports reqObjArg', () => {
assert.strictEqual(typeof test.reqObjArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqObjArg(), objArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqObjArg(undefined), objArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqObjArg(null), objArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqObjArg('1'), objArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqObjArg(1), objArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqObjArg(true), objArgMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.reqObjArg(test.retExt()), objArgMsg);
});
it('accepts an object', () => {
assert.strictEqual(typeof test.reqObjArg({}), 'object');
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.reqObjArg([])));
});
});
describe('addon-tools.hpp: LET_OBJ_ARG', () => {
it('exports letObjArg', () => {
assert.strictEqual(typeof test.letObjArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letObjArg('1'), objArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.letObjArg(1), objArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letObjArg(true), objArgLetMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.letObjArg(test.retExt()), objArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(typeof test.letObjArg(), 'object');
});
it('accepts undefined', () => {
assert.strictEqual(typeof test.letObjArg(undefined), 'object');
});
it('accepts null', () => {
assert.strictEqual(typeof test.letObjArg(null), 'object');
});
it('accepts an object', () => {
assert.strictEqual(typeof test.letObjArg({}), 'object');
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.letObjArg([])));
});
});
describe('addon-tools.hpp: USE_OBJ_ARG', () => {
it('exports useObjArg', () => {
assert.strictEqual(typeof test.useObjArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useObjArg('1'), objArgLetMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.useObjArg(1), objArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useObjArg(true), objArgLetMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.useObjArg(test.retExt()), objArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(typeof test.useObjArg(), 'object');
});
it('accepts undefined', () => {
assert.strictEqual(typeof test.useObjArg(undefined), 'object');
});
it('accepts null', () => {
assert.strictEqual(typeof test.useObjArg(null), 'object');
});
it('accepts an object', () => {
assert.strictEqual(typeof test.useObjArg({}), 'object');
});
it('accepts an array', () => {
assert.ok(Array.isArray(test.useObjArg([])));
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const numArgMsg = { message: 'Argument 0 must be of type `Number`' };
const numArgLetMsg = { message: 'Argument 0 must be of type `Number` or be `null`/`undefined`' };
describe('AT / HPP / REQ_OFFS_ARG', () => {
it('exports reqOffsArg', () => {
assert.strictEqual(typeof test.reqOffsArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqOffsArg(), numArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqOffsArg(undefined), numArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqOffsArg(null), numArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqOffsArg('1'), numArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqOffsArg(true), numArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqOffsArg({}), numArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqOffsArg([]), numArgMsg);
});
it('accepts a number', () => {
assert.strictEqual(test.reqOffsArg(55), 55);
});
});
describe('addon-tools.hpp: LET_OFFS_ARG', () => {
it('exports letOffsArg', () => {
assert.strictEqual(typeof test.letOffsArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letOffsArg('1'), numArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letOffsArg(true), numArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letOffsArg({}), numArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letOffsArg([]), numArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letOffsArg(), 0);
});
it('accepts undefined', () => {
assert.strictEqual(test.letOffsArg(undefined), 0);
});
it('accepts null', () => {
assert.strictEqual(test.letOffsArg(null), 0);
});
it('accepts a number', () => {
assert.strictEqual(test.letOffsArg(55), 55);
});
});
describe('addon-tools.hpp: USE_OFFS_ARG', () => {
it('exports useOffsArg', () => {
assert.strictEqual(typeof test.useOffsArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useOffsArg('1'), numArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useOffsArg(true), numArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useOffsArg({}), numArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useOffsArg([]), numArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.useOffsArg(), 10);
});
it('accepts undefined', () => {
assert.strictEqual(test.useOffsArg(undefined), 10);
});
it('accepts null', () => {
assert.strictEqual(test.useOffsArg(null), 10);
});
it('accepts a number', () => {
assert.strictEqual(test.useOffsArg(55), 55);
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const strArgMsg = { message: 'Argument 0 must be of type `String`' };
const strArgLetMsg = { message: 'Argument 0 must be of type `String` or be `null`/`undefined`' };
describe('AT / HPP / REQ_STR_ARG', () => {
it('exports reqStrArg', () => {
assert.strictEqual(typeof test.reqStrArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqStrArg(), strArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqStrArg(undefined), strArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqStrArg(null), strArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqStrArg(1), strArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqStrArg(true), strArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqStrArg({}), strArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqStrArg([]), strArgMsg);
});
it('accepts a string', () => {
assert.strictEqual(test.reqStrArg('1abc'), '1abc');
});
});
describe('addon-tools.hpp: LET_STR_ARG', () => {
it('exports letStrArg', () => {
assert.strictEqual(typeof test.letStrArg, 'function');
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.letStrArg(1), strArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letStrArg(true), strArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letStrArg({}), strArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letStrArg([]), strArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letStrArg(), '');
});
it('accepts undefined', () => {
assert.strictEqual(test.letStrArg(undefined), '');
});
it('accepts null', () => {
assert.strictEqual(test.letStrArg(null), '');
});
it('accepts a string', () => {
assert.strictEqual(test.letStrArg('1abc'), '1abc');
});
});
describe('addon-tools.hpp: USE_STR_ARG', () => {
it('exports useStrArg', () => {
assert.strictEqual(typeof test.useStrArg, 'function');
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.useStrArg(1), strArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useStrArg(true), strArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useStrArg({}), strArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useStrArg([]), strArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.useStrArg(), 'default');
});
it('accepts undefined', () => {
assert.strictEqual(test.useStrArg(undefined), 'default');
});
it('accepts null', () => {
assert.strictEqual(test.useStrArg(null), 'default');
});
it('accepts a string', () => {
assert.strictEqual(test.useStrArg('1abc'), '1abc');
});
});

View File

@ -0,0 +1,100 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
const uintArgMsg = { message: 'Argument 0 must be of type `Uint32`' };
const uintArgLetMsg = { message: 'Argument 0 must be of type `Uint32` or be `null`/`undefined`' };
describe('AT / HPP / REQ_UINT_ARG, REQ_UINT32_ARG', () => {
it('exports reqUintArg', () => {
assert.strictEqual(typeof test.reqUintArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqUintArg(), uintArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqUintArg(undefined), uintArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqUintArg(null), uintArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqUintArg('1'), uintArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqUintArg(true), uintArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqUintArg({}), uintArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqUintArg([]), uintArgMsg);
});
it('accepts a number', () => {
assert.strictEqual(test.reqUintArg(55), 55);
});
});
describe('addon-tools.hpp: LET_UINT_ARG / LET_UINT32_ARG', () => {
it('exports letUintArg', () => {
assert.strictEqual(typeof test.letUintArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.letUintArg('1'), uintArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.letUintArg(true), uintArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.letUintArg({}), uintArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.letUintArg([]), uintArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.letUintArg(), 0);
});
it('accepts undefined', () => {
assert.strictEqual(test.letUintArg(undefined), 0);
});
it('accepts null', () => {
assert.strictEqual(test.letUintArg(null), 0);
});
it('accepts a number', () => {
assert.strictEqual(test.letUintArg(55), 55);
});
});
describe('addon-tools.hpp: USE_UINT_ARG / USE_UINT32_ARG', () => {
it('exports useUintArg', () => {
assert.strictEqual(typeof test.useUintArg, 'function');
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.useUintArg('1'), uintArgLetMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.useUintArg(true), uintArgLetMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.useUintArg({}), uintArgLetMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.useUintArg([]), uintArgLetMsg);
});
it('accepts an empty arg', () => {
assert.strictEqual(test.useUintArg(), 10);
});
it('accepts undefined', () => {
assert.strictEqual(test.useUintArg(undefined), 10);
});
it('accepts null', () => {
assert.strictEqual(test.useUintArg(null), 10);
});
it('accepts a number', () => {
assert.strictEqual(test.useUintArg(55), 55);
});
});

211
test-addon/hpp-arg.test.js Normal file
View File

@ -0,0 +1,211 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const test = require('./build/Release/test.node');
describe('AT / HPP / Function arguments', () => {
const arg3Msg = { message: 'Expected at least 3 arguments' };
describe('REQ_ARGS', () => {
it('exports reqArgs3', () => {
assert.strictEqual(typeof test.reqArgs3, 'function');
});
it('throws if no args passed', () => {
assert.throws(() => test.reqArgs3(), arg3Msg);
});
it('throws if 1 arg passed', () => {
assert.throws(() => test.reqArgs3(1), arg3Msg);
});
it('returns true if 3 args passed', () => {
assert.ok(test.reqArgs3(1, 2, 3));
});
it('returns true if 5 args passed', () => {
assert.ok(test.reqArgs3(1, 2, 3, 4, 5));
});
});
describe('IS_ARG_EMPTY', () => {
it('exports isArg0Empty', () => {
assert.strictEqual(typeof test.isArg0Empty, 'function');
});
it('returns true for absent arg', () => {
assert.ok(test.isArg0Empty());
});
it('returns true for undefined arg', () => {
assert.ok(test.isArg0Empty(undefined));
});
it('returns true for null arg', () => {
assert.ok(test.isArg0Empty(null));
});
it('returns false for non-empty value', () => {
assert.strictEqual(test.isArg0Empty(1), false);
});
});
// ------------------------------ FUN_ARG
const funArgMsg = { message: 'Argument 0 must be of type `Function`' };
describe('REQ_FUN_ARG', () => {
it('exports reqFunArg', () => {
assert.strictEqual(typeof test.reqFunArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqFunArg(), funArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqFunArg(undefined), funArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqFunArg(null), funArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqFunArg('1'), funArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqFunArg(1), funArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqFunArg(true), funArgMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.reqFunArg(test.retExt()), funArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqFunArg({}), funArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqFunArg([]), funArgMsg);
});
it('accepts a function', () => {
assert.strictEqual(typeof test.reqFunArg(() => {}), 'function');
});
});
// ------------------------------ ARRV_ARG
const arrvArgMsg = { message: 'Argument 0 must be of type `ArrayBuffer`' };
describe('REQ_ARRV_ARG', () => {
it('exports reqArrvArg', () => {
assert.strictEqual(typeof test.reqArrvArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqArrvArg(), arrvArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqArrvArg(undefined), arrvArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqArrvArg(null), arrvArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqArrvArg('1'), arrvArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqArrvArg(1), arrvArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqArrvArg(true), arrvArgMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.reqArrvArg(test.retExt()), arrvArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqArrvArg({}), arrvArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqArrvArg([]), arrvArgMsg);
});
it('accepts an array buffer', () => {
const { buffer } = new Uint8Array([1, 2, 3]);
assert.strictEqual(test.reqArrvArg(buffer), buffer);
});
});
// ------------------------------ BUF_ARG
const bufArgMsg = { message: 'Argument 0 must be of type `Buffer`' };
describe('REQ_BUF_ARG', () => {
it('exports reqBufArg', () => {
assert.strictEqual(typeof test.reqBufArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqBufArg(), bufArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqBufArg(undefined), bufArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqBufArg(null), bufArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqBufArg('1'), bufArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqBufArg(1), bufArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqBufArg(true), bufArgMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.reqBufArg(test.retExt()), bufArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqBufArg({}), bufArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqBufArg([]), bufArgMsg);
});
it('accepts a buffer', () => {
const buffer = Buffer.from([1, 2, 3]);
assert.strictEqual(test.reqBufArg(buffer), buffer);
});
});
// ------------------------------ TYPED_ARRAY_ARG
const typedArgMsg = { message: 'Argument 0 must be of type `TypedArray`' };
describe('REQ_TYPED_ARRAY_ARG', () => {
it('exports reqTypedArg', () => {
assert.strictEqual(typeof test.reqTypedArg, 'function');
});
it('throws if arg was not passed', () => {
assert.throws(() => test.reqTypedArg(), typedArgMsg);
});
it('throws if arg was passed undefined', () => {
assert.throws(() => test.reqTypedArg(undefined), typedArgMsg);
});
it('throws if arg was passed null', () => {
assert.throws(() => test.reqTypedArg(null), typedArgMsg);
});
it('throws if arg was passed a string', () => {
assert.throws(() => test.reqTypedArg('1'), typedArgMsg);
});
it('throws if arg was passed a number', () => {
assert.throws(() => test.reqTypedArg(1), typedArgMsg);
});
it('throws if arg was passed a boolean', () => {
assert.throws(() => test.reqTypedArg(true), typedArgMsg);
});
it('throws if arg was passed a pointer', () => {
assert.throws(() => test.reqTypedArg(test.retExt()), typedArgMsg);
});
it('throws if arg was passed an object', () => {
assert.throws(() => test.reqTypedArg({}), typedArgMsg);
});
it('throws if arg was passed an array', () => {
assert.throws(() => test.reqTypedArg([]), typedArgMsg);
});
it('accepts a typed array', () => {
const typed = new Uint8Array([1, 2, 3]);
assert.strictEqual(test.reqTypedArg(typed), typed);
});
});
});

View File

@ -3,12 +3,12 @@
JS_METHOD(empty) { NAPI_ENV; JS_METHOD(empty) { NAPI_ENV;
NAPI_HS; NAPI_HS;
return env.Undefined(); RET_UNDEFINED;
} }
JS_METHOD(throwing) { NAPI_ENV; JS_METHOD(throwing) { NAPI_ENV;
JS_THROW("Some error"); JS_THROW("Some error");
return env.Undefined(); RET_UNDEFINED;
} }
JS_METHOD(retUndefined) { NAPI_ENV; JS_METHOD(retUndefined) { NAPI_ENV;
@ -202,6 +202,11 @@ JS_METHOD(letArrayArg) { NAPI_ENV;
RET_VALUE(arg); RET_VALUE(arg);
} }
JS_METHOD(letArrayStrArg) { NAPI_ENV;
LET_ARRAY_STR_ARG(0, arg);
RET_ARRAY_STR(arg);
}
JS_METHOD(reqFunArg) { NAPI_ENV; JS_METHOD(reqFunArg) { NAPI_ENV;
REQ_FUN_ARG(0, arg); REQ_FUN_ARG(0, arg);
RET_VALUE(arg); RET_VALUE(arg);
@ -229,7 +234,6 @@ JS_METHOD(reqTypedArg) { NAPI_ENV;
); );
Napi::Object init(Napi::Env env, Napi::Object exports) { Napi::Object init(Napi::Env env, Napi::Object exports) {
TEST_SET_METHOD(empty); TEST_SET_METHOD(empty);
TEST_SET_METHOD(throwing); TEST_SET_METHOD(throwing);
@ -285,13 +289,14 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
TEST_SET_METHOD(useArrayArg); TEST_SET_METHOD(useArrayArg);
TEST_SET_METHOD(letArrayArg); TEST_SET_METHOD(letArrayArg);
TEST_SET_METHOD(letArrayStrArg);
TEST_SET_METHOD(reqFunArg); TEST_SET_METHOD(reqFunArg);
TEST_SET_METHOD(reqArrvArg); TEST_SET_METHOD(reqArrvArg);
TEST_SET_METHOD(reqBufArg); TEST_SET_METHOD(reqBufArg);
TEST_SET_METHOD(reqTypedArg); TEST_SET_METHOD(reqTypedArg);
return exports; return exports;
} }
NODE_API_MODULE(test, init) NODE_API_MODULE(test, init)

View File

@ -1,50 +0,0 @@
{
'targets': [
{
'target_name': 'test',
'sources': [
'test.cpp',
],
'cflags!': ['-fno-exceptions'],
'cflags_cc!': ['-fno-exceptions'],
'include_dirs': [
'<!@(node -p "require(\'..\').include")',
],
'conditions': [
[
'OS=="linux"',
{
'defines': ['__linux__'],
}
],
[
'OS=="mac"',
{
'defines': ['__APPLE__'],
}
],
[
'OS=="win"',
{
'defines' : [
'WIN32_LEAN_AND_MEAN',
'VC_EXTRALEAN',
'_WIN32',
],
'msvs_settings' : {
'VCCLCompilerTool' : {
'AdditionalOptions' : [
'/O2','/Oy','/GL','/GF','/Gm-',
'/EHsc','/MT','/GS','/Gy','/GR-','/Gd',
]
},
'VCLinkerTool' : {
'AdditionalOptions' : ['/OPT:REF','/OPT:ICF','/LTCG']
},
},
},
],
],
},
],
}

850
test/package-lock.json generated
View File

@ -1,850 +0,0 @@
{
"name": "test",
"version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ansi-colors": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
"integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw=="
},
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"binary-extensions": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
"integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow=="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
"integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"pathval": "^1.1.0",
"type-detect": "^4.0.5"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
},
"chokidar": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz",
"integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==",
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.2.0"
}
},
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
}
}
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"requires": {
"type-detect": "^4.0.0"
}
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"requires": {
"object-keys": "^1.0.12"
}
},
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
},
"es-abstract": {
"version": "1.17.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
"integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.1.5",
"is-regex": "^1.0.5",
"object-inspect": "^1.7.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.0",
"string.prototype.trimleft": "^2.1.1",
"string.prototype.trimright": "^2.1.1"
}
},
"es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"requires": {
"is-callable": "^1.1.4",
"is-date-object": "^1.0.1",
"is-symbol": "^1.0.2"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"requires": {
"locate-path": "^3.0.0"
}
},
"flat": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
"integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
"requires": {
"is-buffer": "~2.0.3"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
"integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
},
"glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
"requires": {
"is-glob": "^4.0.1"
}
},
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA=="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-buffer": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A=="
},
"is-callable": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
"integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
},
"is-date-object": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"is-regex": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
"requires": {
"has": "^1.0.3"
}
},
"is-symbol": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"requires": {
"has-symbols": "^1.0.1"
}
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"js-yaml": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"log-symbols": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz",
"integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==",
"requires": {
"chalk": "^2.4.2"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mkdirp": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz",
"integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==",
"requires": {
"minimist": "^1.2.5"
}
},
"mocha": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.1.tgz",
"integrity": "sha512-3qQsu3ijNS3GkWcccT5Zw0hf/rWvu1fTN9sPvEd81hlwsr30GX2GcDSSoBxo24IR8FelmrAydGC6/1J5QQP4WA==",
"requires": {
"ansi-colors": "3.2.3",
"browser-stdout": "1.3.1",
"chokidar": "3.3.0",
"debug": "3.2.6",
"diff": "3.5.0",
"escape-string-regexp": "1.0.5",
"find-up": "3.0.0",
"glob": "7.1.3",
"growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "3.13.1",
"log-symbols": "3.0.0",
"minimatch": "3.0.4",
"mkdirp": "0.5.3",
"ms": "2.1.1",
"node-environment-flags": "1.0.6",
"object.assign": "4.1.0",
"strip-json-comments": "2.0.1",
"supports-color": "6.0.0",
"which": "1.3.1",
"wide-align": "1.1.3",
"yargs": "13.3.2",
"yargs-parser": "13.1.2",
"yargs-unparser": "1.6.0"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
},
"node-environment-flags": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz",
"integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==",
"requires": {
"object.getownpropertydescriptors": "^2.0.3",
"semver": "^5.7.0"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"object-inspect": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
"integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
"object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
"requires": {
"define-properties": "^1.1.2",
"function-bind": "^1.1.1",
"has-symbols": "^1.0.0",
"object-keys": "^1.0.11"
}
},
"object.getownpropertydescriptors": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
"integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.0-next.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"p-limit": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"pathval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
"integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA="
},
"picomatch": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg=="
},
"readdirp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz",
"integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==",
"requires": {
"picomatch": "^2.0.4"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"string.prototype.trimleft": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz",
"integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==",
"requires": {
"define-properties": "^1.1.3",
"function-bind": "^1.1.1"
}
},
"string.prototype.trimright": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz",
"integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==",
"requires": {
"define-properties": "^1.1.3",
"function-bind": "^1.1.1"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"supports-color": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
"integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
"requires": {
"has-flag": "^3.0.0"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
},
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"requires": {
"isexe": "^2.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"requires": {
"string-width": "^1.0.2 || 2"
}
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
}
}
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
},
"yargs": {
"version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.2"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
}
}
}
},
"yargs-parser": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
},
"yargs-unparser": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
"integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
"requires": {
"flat": "^4.1.0",
"lodash": "^4.17.15",
"yargs": "^13.3.0"
}
}
}
}

View File

@ -1,15 +0,0 @@
{
"name": "test",
"version": "0.0.0",
"private": true,
"main": "mocha",
"scripts": {
"test": "mocha",
"build": "node-gyp rebuild",
"preinstall": "cd .. && npm ci"
},
"dependencies": {
"chai": "4.2.0",
"mocha": "7.1.1"
}
}

View File

@ -1,106 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const arrayArgMsg = 'Argument 0 must be of type `Array`';
describe('REQ_ARRAY_ARG', () => {
it('exports reqArrayArg', () => {
expect(test.reqArrayArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqArrayArg()).to.throw(arrayArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqArrayArg(undefined)).to.throw(arrayArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqArrayArg(null)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqArrayArg('1')).to.throw(arrayArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqArrayArg(1)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqArrayArg(true)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.reqArrayArg(test.retExt())).to.throw(arrayArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqArrayArg({})).to.throw(arrayArgMsg);
});
it('accepts an array', () => {
expect(test.reqArrayArg([])).to.be.an('array');
});
});
describe('LET_ARRAY_ARG', () => {
it('exports letArrayArg', () => {
expect(test.letArrayArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letArrayArg('1')).to.throw(arrayArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.letArrayArg(1)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letArrayArg(true)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.letArrayArg(test.retExt())).to.throw(arrayArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letArrayArg({})).to.throw(arrayArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letArrayArg()).to.be.an('array');
});
it('accepts undefined', () => {
expect(test.letArrayArg(undefined)).to.be.an('array');
});
it('accepts null', () => {
expect(test.letArrayArg(null)).to.be.an('array');
});
it('accepts an array', () => {
expect(test.letArrayArg([])).to.be.an('array');
});
});
describe('USE_ARRAY_ARG', () => {
it('exports useArrayArg', () => {
expect(test.useArrayArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useArrayArg('1')).to.throw(arrayArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.useArrayArg(1)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useArrayArg(true)).to.throw(arrayArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.useArrayArg(test.retExt())).to.throw(arrayArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useArrayArg({})).to.throw(arrayArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useArrayArg()).to.be.an('array');
});
it('accepts undefined', () => {
expect(test.useArrayArg(undefined)).to.be.an('array');
});
it('accepts null', () => {
expect(test.useArrayArg(null)).to.be.an('array');
});
it('accepts an array', () => {
expect(test.useArrayArg([])).to.be.an('array');
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const boolArgMsg = 'Argument 0 must be of type `Bool`';
describe('REQ_BOOL_ARG', () => {
it('exports reqBoolArg', () => {
expect(test.reqBoolArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqBoolArg()).to.throw(boolArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqBoolArg(undefined)).to.throw(boolArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqBoolArg(null)).to.throw(boolArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqBoolArg('1')).to.throw(boolArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqBoolArg(1)).to.throw(boolArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqBoolArg({})).to.throw(boolArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqBoolArg([])).to.throw(boolArgMsg);
});
it('accepts a boolean', () => {
expect(test.reqBoolArg(true)).to.be.equal(true);
});
});
describe('LET_BOOL_ARG', () => {
it('exports letBoolArg', () => {
expect(test.letBoolArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letBoolArg('1')).to.throw(boolArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.letBoolArg(1)).to.throw(boolArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letBoolArg({})).to.throw(boolArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letBoolArg([])).to.throw(boolArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letBoolArg()).to.be.equal(false);
});
it('accepts undefined', () => {
expect(test.letBoolArg(undefined)).to.be.equal(false);
});
it('accepts null', () => {
expect(test.letBoolArg(null)).to.be.equal(false);
});
it('accepts a boolean', () => {
expect(test.letBoolArg(true)).to.be.equal(true);
});
});
describe('USE_BOOL_ARG', () => {
it('exports useBoolArg', () => {
expect(test.useBoolArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useBoolArg('1')).to.throw(boolArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.useBoolArg(1)).to.throw(boolArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useBoolArg({})).to.throw(boolArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useBoolArg([])).to.throw(boolArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useBoolArg()).to.be.equal(true);
});
it('accepts undefined', () => {
expect(test.useBoolArg(undefined)).to.be.equal(true);
});
it('accepts null', () => {
expect(test.useBoolArg(null)).to.be.equal(true);
});
it('accepts a boolean', () => {
expect(test.useBoolArg(true)).to.be.equal(true);
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const numArgMsg = 'Argument 0 must be of type `Number`';
describe('REQ_DOUBLE_ARG', () => {
it('exports reqDoubleArg', () => {
expect(test.reqDoubleArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqDoubleArg()).to.throw(numArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqDoubleArg(undefined)).to.throw(numArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqDoubleArg(null)).to.throw(numArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqDoubleArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqDoubleArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqDoubleArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqDoubleArg([])).to.throw(numArgMsg);
});
it('accepts a number', () => {
expect(test.reqDoubleArg(55)).to.be.equal(55);
});
});
describe('LET_DOUBLE_ARG', () => {
it('exports letDoubleArg', () => {
expect(test.letDoubleArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letDoubleArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letDoubleArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letDoubleArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letDoubleArg([])).to.throw(numArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letDoubleArg()).to.be.equal(0);
});
it('accepts undefined', () => {
expect(test.letDoubleArg(undefined)).to.be.equal(0);
});
it('accepts null', () => {
expect(test.letDoubleArg(null)).to.be.equal(0);
});
it('accepts a number', () => {
expect(test.letDoubleArg(55)).to.be.equal(55);
});
});
describe('USE_DOUBLE_ARG', () => {
it('exports useDoubleArg', () => {
expect(test.useDoubleArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useDoubleArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useDoubleArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useDoubleArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useDoubleArg([])).to.throw(numArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useDoubleArg()).to.be.equal(10);
});
it('accepts undefined', () => {
expect(test.useDoubleArg(undefined)).to.be.equal(10);
});
it('accepts null', () => {
expect(test.useDoubleArg(null)).to.be.equal(10);
});
it('accepts a number', () => {
expect(test.useDoubleArg(55)).to.be.equal(55);
});
});

View File

@ -1,106 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const extArgMsg = 'Argument 0 must be of type `Pointer`';
describe('REQ_EXT_ARG', () => {
it('exports reqExtArg', () => {
expect(test.reqExtArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqExtArg()).to.throw(extArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqExtArg(undefined)).to.throw(extArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqExtArg(null)).to.throw(extArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqExtArg('1')).to.throw(extArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqExtArg(1)).to.throw(extArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqExtArg(true)).to.throw(extArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqExtArg({})).to.throw(extArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqExtArg([])).to.throw(extArgMsg);
});
it('accepts a pointer', () => {
expect(test.reqExtArg(test.retExt())).to.be.an('object');
});
});
describe('LET_EXT_ARG', () => {
it('exports letExtArg', () => {
expect(test.letExtArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letExtArg('1')).to.throw(extArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.letExtArg(1)).to.throw(extArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letExtArg(true)).to.throw(extArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letExtArg({})).to.throw(extArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letExtArg([])).to.throw(extArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letExtArg()).to.be.an('object');
});
it('accepts undefined', () => {
expect(test.letExtArg(undefined)).to.be.an('object');
});
it('accepts null', () => {
expect(test.letExtArg(null)).to.be.an('object');
});
it('accepts a pointer', () => {
expect(test.reqExtArg(test.retExt())).to.be.an('object');
});
});
describe('USE_EXT_ARG', () => {
it('exports useExtArg', () => {
expect(test.useExtArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useExtArg('1')).to.throw(extArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.useExtArg(1)).to.throw(extArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useExtArg(true)).to.throw(extArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useExtArg({})).to.throw(extArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useExtArg([])).to.throw(extArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useExtArg()).to.be.an('object');
});
it('accepts undefined', () => {
expect(test.useExtArg(undefined)).to.be.an('object');
});
it('accepts null', () => {
expect(test.useExtArg(null)).to.be.an('object');
});
it('accepts a number', () => {
expect(test.useExtArg(test.retExt())).to.be.an('object');
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const numArgMsg = 'Argument 0 must be of type `Number`';
describe('REQ_FLOAT_ARG', () => {
it('exports reqFloatArg', () => {
expect(test.reqFloatArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqFloatArg()).to.throw(numArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqFloatArg(undefined)).to.throw(numArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqFloatArg(null)).to.throw(numArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqFloatArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqFloatArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqFloatArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqFloatArg([])).to.throw(numArgMsg);
});
it('accepts a number', () => {
expect(test.reqFloatArg(55)).to.be.equal(55);
});
});
describe('LET_FLOAT_ARG', () => {
it('exports letFloatArg', () => {
expect(test.letFloatArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letFloatArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letFloatArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letFloatArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letFloatArg([])).to.throw(numArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letFloatArg()).to.be.equal(0);
});
it('accepts undefined', () => {
expect(test.letFloatArg(undefined)).to.be.equal(0);
});
it('accepts null', () => {
expect(test.letFloatArg(null)).to.be.equal(0);
});
it('accepts a number', () => {
expect(test.letFloatArg(55)).to.be.equal(55);
});
});
describe('USE_FLOAT_ARG', () => {
it('exports useFloatArg', () => {
expect(test.useFloatArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useFloatArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useFloatArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useFloatArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useFloatArg([])).to.throw(numArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useFloatArg()).to.be.equal(10);
});
it('accepts undefined', () => {
expect(test.useFloatArg(undefined)).to.be.equal(10);
});
it('accepts null', () => {
expect(test.useFloatArg(null)).to.be.equal(10);
});
it('accepts a number', () => {
expect(test.useFloatArg(55)).to.be.equal(55);
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const intArgMsg = 'Argument 0 must be of type `Int32`';
describe('REQ_INT_ARG / REQ_INT32_ARG', () => {
it('exports reqIntArg', () => {
expect(test.reqIntArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqIntArg()).to.throw(intArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqIntArg(undefined)).to.throw(intArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqIntArg(null)).to.throw(intArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqIntArg('1')).to.throw(intArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqIntArg(true)).to.throw(intArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqIntArg({})).to.throw(intArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqIntArg([])).to.throw(intArgMsg);
});
it('accepts a number', () => {
expect(test.reqIntArg(55)).to.be.equal(55);
});
});
describe('LET_INT_ARG / LET_INT32_ARG', () => {
it('exports letIntArg', () => {
expect(test.letIntArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letIntArg('1')).to.throw(intArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letIntArg(true)).to.throw(intArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letIntArg({})).to.throw(intArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letIntArg([])).to.throw(intArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letIntArg()).to.be.equal(0);
});
it('accepts undefined', () => {
expect(test.letIntArg(undefined)).to.be.equal(0);
});
it('accepts null', () => {
expect(test.letIntArg(null)).to.be.equal(0);
});
it('accepts a number', () => {
expect(test.letIntArg(55)).to.be.equal(55);
});
});
describe('USE_INT_ARG / USE_INT32_ARG', () => {
it('exports useIntArg', () => {
expect(test.useIntArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useIntArg('1')).to.throw(intArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useIntArg(true)).to.throw(intArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useIntArg({})).to.throw(intArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useIntArg([])).to.throw(intArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useIntArg()).to.be.equal(10);
});
it('accepts undefined', () => {
expect(test.useIntArg(undefined)).to.be.equal(10);
});
it('accepts null', () => {
expect(test.useIntArg(null)).to.be.equal(10);
});
it('accepts a number', () => {
expect(test.useIntArg(55)).to.be.equal(55);
});
});

View File

@ -1,106 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const objArgMsg = 'Argument 0 must be of type `Object`';
describe('REQ_OBJ_ARG', () => {
it('exports reqObjArg', () => {
expect(test.reqObjArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqObjArg()).to.throw(objArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqObjArg(undefined)).to.throw(objArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqObjArg(null)).to.throw(objArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqObjArg('1')).to.throw(objArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqObjArg(1)).to.throw(objArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqObjArg(true)).to.throw(objArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.reqObjArg(test.retExt())).to.throw(objArgMsg);
});
it('accepts an object', () => {
expect(test.reqObjArg({})).to.be.an('object');
});
it('accepts an array', () => {
expect(test.reqObjArg([])).to.be.an('array');
});
});
describe('LET_OBJ_ARG', () => {
it('exports letObjArg', () => {
expect(test.letObjArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letObjArg('1')).to.throw(objArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.letObjArg(1)).to.throw(objArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letObjArg(true)).to.throw(objArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.letObjArg(test.retExt())).to.throw(objArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letObjArg()).to.be.an('object');
});
it('accepts undefined', () => {
expect(test.letObjArg(undefined)).to.be.an('object');
});
it('accepts null', () => {
expect(test.letObjArg(null)).to.be.an('object');
});
it('accepts an object', () => {
expect(test.letObjArg({})).to.be.an('object');
});
it('accepts an array', () => {
expect(test.letObjArg([])).to.be.an('array');
});
});
describe('USE_OBJ_ARG', () => {
it('exports useObjArg', () => {
expect(test.useObjArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useObjArg('1')).to.throw(objArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.useObjArg(1)).to.throw(objArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useObjArg(true)).to.throw(objArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.useObjArg(test.retExt())).to.throw(objArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useObjArg()).to.be.an('object');
});
it('accepts undefined', () => {
expect(test.useObjArg(undefined)).to.be.an('object');
});
it('accepts null', () => {
expect(test.useObjArg(null)).to.be.an('object');
});
it('accepts an object', () => {
expect(test.useObjArg({})).to.be.an('object');
});
it('accepts an array', () => {
expect(test.useObjArg([])).to.be.an('array');
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const numArgMsg = 'Argument 0 must be of type `Number`';
describe('REQ_OFFS_ARG', () => {
it('exports reqOffsArg', () => {
expect(test.reqOffsArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqOffsArg()).to.throw(numArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqOffsArg(undefined)).to.throw(numArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqOffsArg(null)).to.throw(numArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqOffsArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqOffsArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqOffsArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqOffsArg([])).to.throw(numArgMsg);
});
it('accepts a number', () => {
expect(test.reqOffsArg(55)).to.be.equal(55);
});
});
describe('LET_OFFS_ARG', () => {
it('exports letOffsArg', () => {
expect(test.letOffsArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letOffsArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letOffsArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letOffsArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letOffsArg([])).to.throw(numArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letOffsArg()).to.be.equal(0);
});
it('accepts undefined', () => {
expect(test.letOffsArg(undefined)).to.be.equal(0);
});
it('accepts null', () => {
expect(test.letOffsArg(null)).to.be.equal(0);
});
it('accepts a number', () => {
expect(test.letOffsArg(55)).to.be.equal(55);
});
});
describe('USE_OFFS_ARG', () => {
it('exports useOffsArg', () => {
expect(test.useOffsArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useOffsArg('1')).to.throw(numArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useOffsArg(true)).to.throw(numArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useOffsArg({})).to.throw(numArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useOffsArg([])).to.throw(numArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useOffsArg()).to.be.equal(10);
});
it('accepts undefined', () => {
expect(test.useOffsArg(undefined)).to.be.equal(10);
});
it('accepts null', () => {
expect(test.useOffsArg(null)).to.be.equal(10);
});
it('accepts a number', () => {
expect(test.useOffsArg(55)).to.be.equal(55);
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const strArgMsg = 'Argument 0 must be of type `String`';
describe('REQ_STR_ARG', () => {
it('exports reqStrArg', () => {
expect(test.reqStrArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqStrArg()).to.throw(strArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqStrArg(undefined)).to.throw(strArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqStrArg(null)).to.throw(strArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqStrArg(1)).to.throw(strArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqStrArg(true)).to.throw(strArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqStrArg({})).to.throw(strArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqStrArg([])).to.throw(strArgMsg);
});
it('accepts a string', () => {
expect(test.reqStrArg('1abc')).to.be.equal('1abc');
});
});
describe('LET_STR_ARG', () => {
it('exports letStrArg', () => {
expect(test.letStrArg).to.be.a('function');
});
it('throws if arg was passed a number', () => {
expect(() => test.letStrArg(1)).to.throw(strArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letStrArg(true)).to.throw(strArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letStrArg({})).to.throw(strArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letStrArg([])).to.throw(strArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letStrArg()).to.be.equal('');
});
it('accepts undefined', () => {
expect(test.letStrArg(undefined)).to.be.equal('');
});
it('accepts null', () => {
expect(test.letStrArg(null)).to.be.equal('');
});
it('accepts a string', () => {
expect(test.letStrArg('1abc')).to.be.equal('1abc');
});
});
describe('USE_STR_ARG', () => {
it('exports useStrArg', () => {
expect(test.useStrArg).to.be.a('function');
});
it('throws if arg was passed a number', () => {
expect(() => test.useStrArg(1)).to.throw(strArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useStrArg(true)).to.throw(strArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useStrArg({})).to.throw(strArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useStrArg([])).to.throw(strArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useStrArg()).to.be.equal('default');
});
it('accepts undefined', () => {
expect(test.useStrArg(undefined)).to.be.equal('default');
});
it('accepts null', () => {
expect(test.useStrArg(null)).to.be.equal('default');
});
it('accepts a string', () => {
expect(test.useStrArg('1abc')).to.be.equal('1abc');
});
});

View File

@ -1,97 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
const uintArgMsg = 'Argument 0 must be of type `Uint32`';
describe('REQ_UINT_ARG / REQ_UINT32_ARG', () => {
it('exports reqUintArg', () => {
expect(test.reqUintArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqUintArg()).to.throw(uintArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqUintArg(undefined)).to.throw(uintArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqUintArg(null)).to.throw(uintArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqUintArg('1')).to.throw(uintArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqUintArg(true)).to.throw(uintArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqUintArg({})).to.throw(uintArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqUintArg([])).to.throw(uintArgMsg);
});
it('accepts a number', () => {
expect(test.reqUintArg(55)).to.be.equal(55);
});
});
describe('LET_UINT_ARG / LET_UINT32_ARG', () => {
it('exports letUintArg', () => {
expect(test.letUintArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.letUintArg('1')).to.throw(uintArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.letUintArg(true)).to.throw(uintArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.letUintArg({})).to.throw(uintArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.letUintArg([])).to.throw(uintArgMsg);
});
it('accepts an empty arg', () => {
expect(test.letUintArg()).to.be.equal(0);
});
it('accepts undefined', () => {
expect(test.letUintArg(undefined)).to.be.equal(0);
});
it('accepts null', () => {
expect(test.letUintArg(null)).to.be.equal(0);
});
it('accepts a number', () => {
expect(test.letUintArg(55)).to.be.equal(55);
});
});
describe('USE_UINT_ARG / USE_UINT32_ARG', () => {
it('exports useUintArg', () => {
expect(test.useUintArg).to.be.a('function');
});
it('throws if arg was passed a string', () => {
expect(() => test.useUintArg('1')).to.throw(uintArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.useUintArg(true)).to.throw(uintArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.useUintArg({})).to.throw(uintArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.useUintArg([])).to.throw(uintArgMsg);
});
it('accepts an empty arg', () => {
expect(test.useUintArg()).to.be.equal(10);
});
it('accepts undefined', () => {
expect(test.useUintArg(undefined)).to.be.equal(10);
});
it('accepts null', () => {
expect(test.useUintArg(null)).to.be.equal(10);
});
it('accepts a number', () => {
expect(test.useUintArg(55)).to.be.equal(55);
});
});

View File

@ -1,219 +0,0 @@
'use strict';
const { expect } = require('chai');
const test = require('./build/Release/test.node');
describe('Function arguments', () => {
describe('REQ_ARGS', () => {
it('exports reqArgs3', () => {
expect(test.reqArgs3).to.be.a('function');
});
it('throws if no args passed', () => {
expect(() => test.reqArgs3()).to.throw('Expected at least 3 arguments');
});
it('throws if 1 arg passed', () => {
expect(() => test.reqArgs3(1)).to.throw('Expected at least 3 arguments');
});
it('returns true if 3 args passed', () => {
expect(test.reqArgs3(1, 2, 3)).to.be.true;
});
it('returns true if 5 args passed', () => {
expect(test.reqArgs3(1, 2, 3, 4, 5)).to.be.true;
});
});
describe('IS_ARG_EMPTY', () => {
it('exports isArg0Empty', () => {
expect(test.isArg0Empty).to.be.a('function');
});
it('returns true for absent arg', () => {
expect(test.isArg0Empty()).to.be.true;
});
it('returns true for undefined arg', () => {
expect(test.isArg0Empty(undefined)).to.be.true;
});
it('returns true for null arg', () => {
expect(test.isArg0Empty(null)).to.be.true;
});
it('returns false for non-empty value', () => {
expect(test.isArg0Empty(1)).to.be.false;
});
});
require('./test-hpp-arg-str');
require('./test-hpp-arg-int');
require('./test-hpp-arg-uint');
require('./test-hpp-arg-bool');
require('./test-hpp-arg-offs');
require('./test-hpp-arg-double');
require('./test-hpp-arg-float');
require('./test-hpp-arg-ext');
require('./test-hpp-arg-obj');
require('./test-hpp-arg-array');
// ------------------------------ FUN_ARG
const funArgMsg = 'Argument 0 must be of type `Function`';
describe('REQ_FUN_ARG', () => {
it('exports reqFunArg', () => {
expect(test.reqFunArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqFunArg()).to.throw(funArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqFunArg(undefined)).to.throw(funArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqFunArg(null)).to.throw(funArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqFunArg('1')).to.throw(funArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqFunArg(1)).to.throw(funArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqFunArg(true)).to.throw(funArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.reqFunArg(test.retExt())).to.throw(funArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqFunArg({})).to.throw(funArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqFunArg([])).to.throw(funArgMsg);
});
it('accepts a function', () => {
expect(test.reqFunArg(() => {})).to.be.a('function');
});
});
// ------------------------------ ARRV_ARG
const arrvArgMsg = 'Argument 0 must be of type `ArrayBuffer`';
describe('REQ_ARRV_ARG', () => {
it('exports reqArrvArg', () => {
expect(test.reqArrvArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqArrvArg()).to.throw(arrvArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqArrvArg(undefined)).to.throw(arrvArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqArrvArg(null)).to.throw(arrvArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqArrvArg('1')).to.throw(arrvArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqArrvArg(1)).to.throw(arrvArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqArrvArg(true)).to.throw(arrvArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.reqArrvArg(test.retExt())).to.throw(arrvArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqArrvArg({})).to.throw(arrvArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqArrvArg([])).to.throw(arrvArgMsg);
});
it('accepts an array buffer', () => {
const { buffer } = new Uint8Array([1, 2, 3]);
expect(test.reqArrvArg(buffer)).to.be.equal(buffer);
});
});
// ------------------------------ BUF_ARG
const bufArgMsg = 'Argument 0 must be of type `Buffer`';
describe('REQ_BUF_ARG', () => {
it('exports reqBufArg', () => {
expect(test.reqBufArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqBufArg()).to.throw(bufArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqBufArg(undefined)).to.throw(bufArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqBufArg(null)).to.throw(bufArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqBufArg('1')).to.throw(bufArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqBufArg(1)).to.throw(bufArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqBufArg(true)).to.throw(bufArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.reqBufArg(test.retExt())).to.throw(bufArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqBufArg({})).to.throw(bufArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqBufArg([])).to.throw(bufArgMsg);
});
it('accepts a buffer', () => {
const buffer = Buffer.from([1, 2, 3]);
expect(test.reqBufArg(buffer)).to.be.equal(buffer);
});
});
// ------------------------------ TYPED_ARRAY_ARG
const typedArgMsg = 'Argument 0 must be of type `TypedArray`';
describe('REQ_TYPED_ARRAY_ARG', () => {
it('exports reqTypedArg', () => {
expect(test.reqTypedArg).to.be.a('function');
});
it('throws if arg was not passed', () => {
expect(() => test.reqTypedArg()).to.throw(typedArgMsg);
});
it('throws if arg was passed undefined', () => {
expect(() => test.reqTypedArg(undefined)).to.throw(typedArgMsg);
});
it('throws if arg was passed null', () => {
expect(() => test.reqTypedArg(null)).to.throw(typedArgMsg);
});
it('throws if arg was passed a string', () => {
expect(() => test.reqTypedArg('1')).to.throw(typedArgMsg);
});
it('throws if arg was passed a number', () => {
expect(() => test.reqTypedArg(1)).to.throw(typedArgMsg);
});
it('throws if arg was passed a boolean', () => {
expect(() => test.reqTypedArg(true)).to.throw(typedArgMsg);
});
it('throws if arg was passed a pointer', () => {
expect(() => test.reqTypedArg(test.retExt())).to.throw(typedArgMsg);
});
it('throws if arg was passed an object', () => {
expect(() => test.reqTypedArg({})).to.throw(typedArgMsg);
});
it('throws if arg was passed an array', () => {
expect(() => test.reqTypedArg([])).to.throw(typedArgMsg);
});
it('accepts a typed array', () => {
const typed = new Uint8Array([1, 2, 3]);
expect(test.reqTypedArg(typed)).to.be.equal(typed);
});
});
});

View File

@ -1,8 +0,0 @@
'use strict';
describe('addon-tools.hpp', () => {
require('./test-hpp-arg');
});

View File

@ -1,39 +0,0 @@
'use strict';
const { expect } = require('chai');
describe('index.js', () => {
const tools = require('..');
describe(
'Properties',
() => ['bin', 'platform', 'include'].forEach(
m => it(`#${m} is a string`, () => {
expect(tools[m]).to.be.a('string');
})
)
);
describe('#paths()', () => {
it('is a function', () => {
expect(tools.paths).to.be.a('function');
});
it('returns an object', () => {
expect(tools.paths(__dirname)).to.be.an('object');
});
it('has "include" string', () => {
expect(tools.paths(__dirname).include).to.be.a('string');
});
it('has "bin" string', () => {
expect(tools.paths(__dirname).include).to.be.a('string');
});
});
});

View File

@ -1,4 +0,0 @@
'use strict';
require('./test-index');
require('./test-hpp');

View File

@ -1,15 +1,18 @@
set noparent set noparent
linelength=110 linelength=110
filter=-legal/copyright
filter=-build/include_order
filter=-build/header_guard filter=-build/header_guard
filter=-build/namespaces filter=-build/include
filter=-build/include_order
filter=-build/include_what_you_use filter=-build/include_what_you_use
filter=-build/namespaces
filter=-legal/copyright
filter=-readability/todo
filter=-runtime/indentation_namespace
filter=-whitespace/blank_line filter=-whitespace/blank_line
filter=-whitespace/braces
filter=-whitespace/comments filter=-whitespace/comments
filter=-whitespace/tab
filter=-whitespace/end_of_line filter=-whitespace/end_of_line
filter=-whitespace/indent filter=-whitespace/indent
filter=-whitespace/operators filter=-whitespace/operators
filter=-whitespace/parens filter=-whitespace/parens
filter=-readability/todo filter=-whitespace/tab

20
utils/action-pack.js Normal file
View File

@ -0,0 +1,20 @@
'use strict';
const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);
const { getPlatform, getBin } = require('../include');
const actionPack = async () => {
try {
await exec(`cd ${getBin()} && tar -czf ../${getPlatform()}.gz *`);
console.log(`pack=${getPlatform()}.gz`);
} catch (error) {
console.error(error);
process.exit(-1);
}
};
module.exports = { actionPack };

31
utils/cpbin.js Normal file
View File

@ -0,0 +1,31 @@
'use strict';
const { copy, exists, mkdir, rm } = require('./files');
const { getBin } = require('../include');
const cpbin = async (name) => {
const srcDir = process.cwd().replace(/\\/g, '/');
if (!await exists(`${srcDir}/build/Release/${name}.node`) ) {
console.error(`Error. File "${srcDir}/build/Release/${name}.node" not found.`);
}
const binAbs = `${srcDir}/../${getBin()}`;
if (!await exists(binAbs)) {
await mkdir(binAbs);
}
const destAbs = `${binAbs}/${name}.node`;
if (await exists(destAbs)) {
await rm(destAbs);
}
await copy(`${srcDir}/build/Release/${name}.node`, destAbs);
console.log(`The binary "${name}.node" was copied to "${getBin()}".`);
};
module.exports = { cpbin };

24
utils/cpcpplint.js Normal file
View File

@ -0,0 +1,24 @@
'use strict';
const { copy, exists } = require('./files');
const cpcpplint = async () => {
const cpplintDest = `${process.cwd()}/CPPLINT.cfg`.replace(/\\/g, '/');
const cpplintSrc = `${__dirname}/CPPLINT.cfg`.replace(/\\/g, '/');
if (!await exists(cpplintSrc) ) {
console.error('Error. File "CPPLINT.cfg" not found.');
return;
}
if (await exists(cpplintDest) ) {
console.warn('Warning. Dest "CPPLINT.cfg" exists and will be overwritten.');
}
await copy(cpplintSrc, cpplintDest);
console.log(`"CPPLINT.cfg" was copied to "${cpplintDest}".`);
};
module.exports = { cpcpplint };

46
utils/download.js Normal file
View File

@ -0,0 +1,46 @@
'use strict';
const https = require('node:https');
const http = require('node:http');
const { WritableBuffer } = require('./writable-buffer');
const protocols = { http, https };
const downloadRecursive = async (url, count = 1) => {
const stream = new WritableBuffer();
const proto = protocols[url.match(/^https?/i)[0].toLowerCase()];
const response = await new Promise((res, rej) => {
const request = proto.get(url, (response) => res(response));
request.on('error', (err) => rej(err));
});
// Handle redirects
if ([301, 302, 303, 307].includes(response.statusCode)) {
if (count < 5) {
return downloadRecursive(response.headers.location, count + 1);
}
console.log(url);
throw new Error('Error: Too many redirects.');
}
// Handle bad status
if (response.statusCode !== 200) {
console.log(url);
throw new Error(`Response status was ${response.statusCode}`);
}
response.pipe(stream);
return new Promise((res, rej) => {
response.on('error', (err) => rej(err));
response.on('end', () => res(stream.get()));
});
};
const download = (url) => downloadRecursive(url);
module.exports = { download };

View File

@ -1,9 +1,10 @@
'use strict'; 'use strict';
const fs = require('fs'); const fs = require('node:fs');
// (async) Reads a whole file to string, NOT A Buffer // (async) Reads a whole file to string, NOT A Buffer
const read = name => new Promise( const read = (name) => new Promise(
(res, rej) => fs.readFile( (res, rej) => fs.readFile(
name, name,
(err, data) => (err ? rej(err) : res(data.toString())) (err, data) => (err ? rej(err) : res(data.toString()))
@ -13,7 +14,7 @@ const read = name => new Promise(
// (async) Write a file // (async) Write a file
const write = (name, text) => new Promise( const write = (name, text) => new Promise(
(res, rej) => fs.writeFile(name, text, err => (err ? rej(err) : res())) (res, rej) => fs.writeFile(name, text, (err) => (err ? rej(err) : res()))
); );
@ -21,7 +22,7 @@ const write = (name, text) => new Promise(
const copy = async (src, dest) => { const copy = async (src, dest) => {
try { try {
await new Promise( await new Promise(
(res, rej) => fs.copyFile(src, dest, err => (err ? rej(err) : res())) (res, rej) => fs.copyFile(src, dest, (err) => (err ? rej(err) : res()))
); );
} catch (e) { } catch (e) {
if (e.code !== 'EBUSY') { if (e.code !== 'EBUSY') {
@ -32,46 +33,46 @@ const copy = async (src, dest) => {
// (async) Check if a file/folder exists // (async) Check if a file/folder exists
const exists = name => new Promise( const exists = (name) => new Promise(
res => fs.access( (res) => fs.access(
name, name,
fs.constants.F_OK, fs.constants.F_OK,
err => res(err ? false : true) (err) => res(err ? false : true)
) )
); );
// (async) Create an empty folder // (async) Create an empty folder
const mkdir = async name => { const mkdir = async (name) => {
if (await exists(name)) { if (await exists(name)) {
return; return;
} }
return new Promise( return new Promise(
(res, rej) => fs.mkdir(name, err => (err ? rej(err) : res())) (res, rej) => fs.mkdir(name, (err) => (err ? rej(err) : res()))
); );
}; };
// (async) Get status on a file // (async) Get status on a file
const stat = name => new Promise( const stat = (name) => new Promise(
(res, rej) => fs.stat(name, (err, stats) => (err ? rej(err) : res(stats))) (res, rej) => fs.stat(name, (err, stats) => (err ? rej(err) : res(stats)))
); );
// (async) Check if the path is a folder // (async) Check if the path is a folder
const isDir = async name => (await stat(name)).isDirectory(); const isDir = async (name) => (await stat(name)).isDirectory();
// (async) Check if the path is a file // (async) Check if the path is a file
const isFile = async name => (await stat(name)).isFile(); const isFile = async (name) => (await stat(name)).isFile();
// Cut the path one folder up // Cut the path one folder up
const dirUp = dir => dir.replace(/\\/g, '/').split('/').slice(0, -1).join('/'); const dirUp = (dir) => dir.replace(/\\/g, '/').split('/').slice(0, -1).join('/');
// (async) Like `mkdir -p`, makes sure a directory exists // (async) Like `mkdir -p`, makes sure a directory exists
const ensuredir = async dir => { const ensuredir = async (dir) => {
if (await exists(dir) && await isDir(dir)) { if (await exists(dir) && await isDir(dir)) {
return; return;
} }
@ -88,7 +89,7 @@ const copysafe = async (src, dest) => {
// (async) Get file/folder names of the 1st level // (async) Get file/folder names of the 1st level
const readdir = name => new Promise( const readdir = (name) => new Promise(
(res, rej) => fs.readdir( (res, rej) => fs.readdir(
name, name,
(err, dirents) => (err ? rej(err) : res(dirents)) (err, dirents) => (err ? rej(err) : res(dirents))
@ -97,18 +98,18 @@ const readdir = name => new Promise(
// (async) Get folder paths (concatenated with input) of the 1st level // (async) Get folder paths (concatenated with input) of the 1st level
const subdirs = async name => { const subdirs = async (name) => {
const all = await readdir(name); const all = await readdir(name);
const mapped = await Promise.all(all.map(d => isDir(`${name}/${d}`))); const mapped = await Promise.all(all.map((d) => isDir(`${name}/${d}`)));
return all.filter((_, i) => mapped[i]); return all.filter((_, i) => mapped[i]);
}; };
// (async) Get file paths (concatenated with input) of the 1st level // (async) Get file paths (concatenated with input) of the 1st level
const subfiles = async name => { const subfiles = async (name) => {
const all = await readdir(name); const all = await readdir(name);
const mapped = await Promise.all(all.map(d => isFile(`${name}/${d}`))); const mapped = await Promise.all(all.map((d) => isFile(`${name}/${d}`)));
return all.filter((_, i) => mapped[i]).map(f => `${name}/${f}`); return all.filter((_, i) => mapped[i]).map((f) => `${name}/${f}`);
}; };
@ -121,7 +122,7 @@ const traverse = async (name, showDirs = false) => {
while (stack.length) { while (stack.length) {
const dir = stack.pop(); const dir = stack.pop();
dirs.push(dir); dirs.push(dir);
(await subdirs(dir)).forEach(d => stack.push(`${dir}/${d}`)); (await subdirs(dir)).forEach((d) => stack.push(`${dir}/${d}`));
} }
return (showDirs ? dirs : []).concat( return (showDirs ? dirs : []).concat(
...(await Promise.all(dirs.map(subfiles))) ...(await Promise.all(dirs.map(subfiles)))
@ -145,7 +146,7 @@ const copyall = async (src, dest) => {
// (async) Like `rm -rf`, removes everything recursively // (async) Like `rm -rf`, removes everything recursively
const rmdir = async name => { const rmdir = async (name) => {
if (!await exists(name)) { if (!await exists(name)) {
return; return;
} }
@ -156,7 +157,7 @@ const rmdir = async name => {
await new Promise( await new Promise(
(res, rej) => fs[dir ? 'rmdir' : 'unlink']( (res, rej) => fs[dir ? 'rmdir' : 'unlink'](
target, target,
err => (err ? rej(err) : res()) (err) => (err ? rej(err) : res())
) )
); );
} }
@ -164,12 +165,12 @@ const rmdir = async name => {
// (async) Remove a file. Must be a file, not a folder. Just `fs.unlink`. // (async) Remove a file. Must be a file, not a folder. Just `fs.unlink`.
const rm = async name => { const rm = async (name) => {
if (!await exists(name)) { if (!await exists(name)) {
return; return;
} }
await new Promise( await new Promise(
(res, rej) => fs.unlink(name, err => (err ? rej(err) : res())) (res, rej) => fs.unlink(name, (err) => (err ? rej(err) : res()))
); );
}; };

13
utils/index.js Normal file
View File

@ -0,0 +1,13 @@
'use strict';
module.exports = Object.assign(
{},
require('./action-pack'),
require('./cpbin'),
require('./cpcpplint'),
require('./download'),
require('./files'),
require('./install'),
require('./writable-buffer'),
);

72
utils/install.js Normal file
View File

@ -0,0 +1,72 @@
'use strict';
const fs = require('node:fs');
const https = require('node:https');
const http = require('node:http');
const util = require('node:util');
const exec = util.promisify(require('node:child_process').exec);
const { getBin, getPlatform } = require('../include');
const { mkdir, rmdir, rm } = require('./files');
const protocols = { http, https };
const installRecursive = async (url, count = 1) => {
try {
const proto = protocols[url.match(/^https?/)[0]];
const response = await new Promise((res, rej) => {
const request = proto.get(url, (response) => res(response));
request.on('error', (err) => rej(err));
});
response.on('error', (err) => { throw err; });
// Handle redirects
if ([301, 302, 303, 307].includes(response.statusCode)) {
if (count < 5) {
return installRecursive(response.headers.location, count + 1);
}
console.warn(url);
throw new Error('Error: Too many redirects.');
}
// Handle bad status
if (response.statusCode !== 200) {
console.warn(url);
throw new Error(`Response status was ${response.statusCode}`);
}
await rmdir(getBin());
await mkdir(getBin());
const packPath = `${getBin()}/${getPlatform()}.gz`;
await new Promise((res, rej) => {
const packWriter = fs.createWriteStream(packPath);
packWriter.on('error', (err) => rej(err));
packWriter.on('finish', () => res());
response.pipe(packWriter);
});
const { stderr } = await exec(`tar -xzf ${packPath} --directory ${getBin()}`);
if (stderr) {
console.warn(stderr);
}
await rm(packPath);
return true;
} catch (error) {
console.error(error.message);
return false;
}
};
const install = async (folder) => {
const url = `${folder}/${getPlatform()}.gz`;
return installRecursive(url);
};
module.exports = { install };

22
utils/utils.test.js Normal file
View File

@ -0,0 +1,22 @@
'use strict';
const assert = require('node:assert').strict;
const { describe, it } = require('node:test');
const utils = require('.');
describe('AT / utils', () => {
const methods = [
'install', 'cpbin', 'download', 'read', 'write', 'copy', 'exists',
'mkdir', 'stat', 'isDir', 'isFile', 'dirUp', 'ensuredir', 'copysafe',
'readdir', 'subdirs', 'subfiles', 'traverse', 'copyall',
'rmdir', 'rm', 'WritableBuffer', 'actionPack',
];
methods.forEach((name) => {
it(`exports the "${name}" function`, () => {
assert.strictEqual(typeof utils[name], 'function');
});
});
});

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
const { Writable } = require('stream'); const { Writable } = require('node:stream');
const CHUNK_SIZE = 1024; const CHUNK_SIZE = 1024;
const INITIAL_SIZE = 8 * CHUNK_SIZE; const INITIAL_SIZE = 8 * CHUNK_SIZE;
@ -8,32 +9,26 @@ const INCREMENT_SIZE = 8 * CHUNK_SIZE;
class WritableBuffer extends Writable { class WritableBuffer extends Writable {
constructor() { constructor() {
super(); super();
this._buffer = new Buffer(INITIAL_SIZE); this._buffer = Buffer.alloc(INITIAL_SIZE);
this._size = 0; this._size = 0;
} }
get() { get() {
if (!this._size) { if (!this._size) {
return null; return null;
} }
const data = new Buffer(this._size); const data = Buffer.alloc(this._size);
this._buffer.copy(data, 0, 0, this._size); this._buffer.copy(data, 0, 0, this._size);
return data; return data;
} }
_increaseAsNeeded(incomingSize) { _increaseAsNeeded(incomingSize) {
if ((this._buffer.length - this._size) >= incomingSize) { if ((this._buffer.length - this._size) >= incomingSize) {
return; return;
} }
@ -41,25 +36,21 @@ class WritableBuffer extends Writable {
const freeSpace = this._buffer.length - this._size; const freeSpace = this._buffer.length - this._size;
const factor = Math.ceil((incomingSize - freeSpace) / INCREMENT_SIZE); const factor = Math.ceil((incomingSize - freeSpace) / INCREMENT_SIZE);
const newBuffer = new Buffer(this._buffer.length + (INCREMENT_SIZE * factor)); const newBuffer = Buffer.alloc(this._buffer.length + (INCREMENT_SIZE * factor));
this._buffer.copy(newBuffer, 0, 0, this._size); this._buffer.copy(newBuffer, 0, 0, this._size);
this._buffer = newBuffer; this._buffer = newBuffer;
} }
_write(chunk, encoding, callback) { _write(chunk, encoding, callback) {
this._increaseAsNeeded(chunk.length); this._increaseAsNeeded(chunk.length);
chunk.copy(this._buffer, this._size, 0); chunk.copy(this._buffer, this._size, 0);
this._size += chunk.length; this._size += chunk.length;
callback(); callback();
}
} }
} module.exports = { WritableBuffer };
module.exports = WritableBuffer;