Adjust tests
This commit is contained in:
parent
b05666869a
commit
ac0c472be9
46
README.md
46
README.md
|
@ -9,10 +9,6 @@ This is a part of [Node3D](https://github.com/node-3d) project.
|
||||||
npm i addon-tools-raub
|
npm i addon-tools-raub
|
||||||
```
|
```
|
||||||
|
|
||||||
This module contains 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.
|
|
||||||
|
|
||||||
|
|
||||||
## include/addon-tools.hpp
|
## include/addon-tools.hpp
|
||||||
|
|
||||||
|
@ -36,42 +32,42 @@ DBG_EXPORT JS_METHOD(doSomething) { NAPI_ENV;
|
||||||
|
|
||||||
## index.js
|
## index.js
|
||||||
|
|
||||||
Main exports for cross-platform addon configuration.
|
JavaScript helpers for Node.js addon development. The short list of helpers:
|
||||||
|
```
|
||||||
|
'getBin', 'getPlatform', 'getInclude', 'getPaths',
|
||||||
|
'install', 'cpbin', 'download', 'read', 'write', 'copy', 'exists',
|
||||||
|
'mkdir', 'stat', 'isDir', 'isFile', 'dirUp', 'ensuredir', 'copysafe',
|
||||||
|
'readdir', 'subdirs', 'subfiles', 'traverse', 'copyall',
|
||||||
|
'rmdir', 'rm', 'WritableBuffer', 'actionVersion', 'actionZip',
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
See the [TypeScript definitions](/index.d.ts) with comments.
|
See the [TypeScript definitions](/index.d.ts) with comments.
|
||||||
|
|
||||||
> NOTE: the peer dependency `node-addon-api` is used by this helper.
|
|
||||||
|
|
||||||
Example for an ADDON's **index.js**:
|
### Example for an ADDON's **index.js**:
|
||||||
|
|
||||||
```
|
```
|
||||||
const { bin } = require('addon-tools-raub');
|
const { getBin } = require('addon-tools-raub');
|
||||||
const core = require(`./${bin}/ADDON`); // uses the platform-specific ADDON.node
|
const core = require(`./${getBin()}/ADDON`); // uses the platform-specific ADDON.node
|
||||||
```
|
```
|
||||||
|
|
||||||
Example for **binding.gyp**:
|
|
||||||
|
### Example for **binding.gyp**:
|
||||||
|
|
||||||
```
|
```
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
'<!@(node -p "require(\'addon-tools-raub\').include")',
|
'<!@(node -p "require(\'addon-tools-raub\').getInclude()")',
|
||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> 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
|
|
||||||
|
|
||||||
JS utils for Node.js modules and addons.
|
### Example of `cpbin` usage in **package.json :: scripts**:
|
||||||
|
|
||||||
```
|
```
|
||||||
const utils = require('addon-tools-raub/utils');
|
"build-all": "cd src && node-gyp rebuild -j max --silent && node -e \"require('addon-tools-raub').cpbin('segfault')\" && cd ..",
|
||||||
|
"build-only": "cd src && node-gyp build -j max --silent && node -e \"require('addon-tools-raub').cpbin('segfault')\" && cd ..",
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Example of `cpbin` usage in **package.json :: scripts**:
|
|
||||||
|
|
||||||
```
|
|
||||||
"build-all": "cd src && node-gyp rebuild -j max --silent && node -e \"require('addon-tools-raub/utils').cpbin('segfault')\" && cd ..",
|
|
||||||
"build-only": "cd src && node-gyp build -j max --silent && node -e \"require('addon-tools-raub/utils').cpbin('segfault')\" && cd ..",
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
See the [TypeScript definitions](/utils.d.ts) with comments.
|
|
||||||
|
|
|
@ -3,31 +3,36 @@
|
||||||
const tools = require('.');
|
const tools = require('.');
|
||||||
|
|
||||||
|
|
||||||
describe('index.js', () => {
|
describe('AT / include', () => {
|
||||||
describe(
|
const stringMethods = ['getBin', 'getPlatform', 'getInclude'];
|
||||||
'Properties',
|
|
||||||
() => ['bin', 'platform', 'include'].forEach(
|
|
||||||
(m) => it(`#${m} is a string`, () => {
|
|
||||||
expect(typeof tools[m]).toBe('string');
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
describe('#paths()', () => {
|
stringMethods.forEach((name) => {
|
||||||
|
describe(`#${name}()`, () => {
|
||||||
it('is a function', () => {
|
it('is a function', () => {
|
||||||
expect(typeof tools.paths).toBe('function');
|
expect(typeof tools[name]).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns an object', () => {
|
it('returns an object', () => {
|
||||||
expect(typeof tools.paths(__dirname)).toBe('object');
|
expect(typeof tools[name]()).toBe('string');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getPaths()', () => {
|
||||||
|
it('is a function', () => {
|
||||||
|
expect(typeof tools.getPaths).toBe('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns an object', () => {
|
||||||
|
expect(typeof tools.getPaths(__dirname)).toBe('object');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has "include" string', () => {
|
it('has "include" string', () => {
|
||||||
expect(typeof tools.paths(__dirname).include).toBe('string');
|
expect(typeof tools.getPaths(__dirname).include).toBe('string');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has "bin" string', () => {
|
it('has "bin" string', () => {
|
||||||
expect(typeof tools.paths(__dirname).include).toBe('string');
|
expect(typeof tools.getPaths(__dirname).include).toBe('string');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,38 +2,11 @@
|
||||||
|
|
||||||
## C++ Addon building
|
## 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-all": "cd src && node-gyp rebuild -j max --silent && node -e \"require('addon-tools-raub/utils').cpbin('ADDON')\" && cd ..",
|
|
||||||
"build-only": "cd src && node-gyp build -j max --silent && node -e \"require('addon-tools-raub/utils').cpbin('ADDON')\" && cd ..",
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"addon-tools-raub": "6.2.0",
|
|
||||||
"DEPS": "1.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
* `ADDON` - the name of this addon (and subsequently of its binary).
|
|
||||||
* `DEPS` - dependency package(s).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Binary distribution
|
### Binary distribution
|
||||||
|
|
||||||
In **package.json** use the `"postinstall"` script to download the libraries.
|
In **package.json** use the `"postinstall"` script to download the libraries.
|
||||||
For example the following structure might work. Note that **Addon Tools** will
|
For example the following structure might work. Note that **Addon Tools** will
|
||||||
append any given URL with `/${platform}.zip`
|
append any given URL with `/${getPlatform()}.zip`
|
||||||
|
|
||||||
In **package.json**:
|
In **package.json**:
|
||||||
|
|
||||||
|
@ -42,44 +15,35 @@ In **package.json**:
|
||||||
"postinstall": "node install",
|
"postinstall": "node install",
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"addon-tools-raub": "^6.2.0",
|
"addon-tools-raub": "^7.0.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"node-addon-api": "^5.0.0"
|
"node-addon-api": "^5.0.0"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Create the **install.js** file:
|
Create the **install.js** file, see `install` in [index.d.ts](/index.d.ts).
|
||||||
|
**Addon Tools** will unzip (using **tar**) the downloaded file into the platform binary
|
||||||
```
|
|
||||||
'use strict';
|
|
||||||
const { install } = require('addon-tools-raub/utils');
|
|
||||||
const prefix = 'https://github.com/node-3d/glfw-raub/releases/download';
|
|
||||||
const tag = '4.8.0';
|
|
||||||
install(`${prefix}/${tag}`);
|
|
||||||
```
|
|
||||||
|
|
||||||
**Addon Tools** will unzip (using **adm-zip**) the downloaded file into the platform binary
|
|
||||||
directory. E.g. on Windows it will be **bin-windows**.
|
directory. E.g. on Windows it will be **bin-windows**.
|
||||||
|
|
||||||
* For a dependency package:
|
* For a dependency package:
|
||||||
|
|
||||||
Place the following piece of code in the `index.js` without changes. Method `paths()`
|
Place the following piece of code into the `index.js` without changes.
|
||||||
is described [here](../README.md).
|
|
||||||
```
|
```
|
||||||
module.exports = require('addon-tools-raub').paths(__dirname);
|
module.exports = require('addon-tools-raub').getPaths(__dirname);
|
||||||
```
|
```
|
||||||
|
|
||||||
* For a compiled addon:
|
* For a compiled addon:
|
||||||
|
|
||||||
Require it in your **index.js** from the platform-specific directory.
|
Require the `ADDON.node` in your **index.js** from the platform-specific directory.
|
||||||
```
|
```
|
||||||
const { bin } = require('addon-tools-raub');
|
const { getBin } = require('addon-tools-raub');
|
||||||
const core = require(`./${bin}/ADDON`);
|
const core = require(`./${getBin()}/ADDON`);
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Publishing binaries is done by attaching a zipped platform folder to the GitHub
|
Publishing binaries is done by attaching a zipped platform folder to a GitHub
|
||||||
release. Zip file must NOT contain platform folder as a subfolder, but rather
|
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
|
contain the final binaries. The tag of the release should be the same as in
|
||||||
**install.js**.
|
**install.js**.
|
||||||
|
@ -114,75 +78,4 @@ from **Addon Tools** is that it should be a zipped set of files/folders.
|
||||||
],
|
],
|
||||||
```
|
```
|
||||||
|
|
||||||
The former contains both the path to include **Addon Tools** and the one for
|
See example of a working [**binding.gyp** here](/test-addon/binding.gyp)
|
||||||
**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' : 'ADDON',
|
|
||||||
'sources' : [
|
|
||||||
'cpp/addon.cpp',
|
|
||||||
],
|
|
||||||
'include_dirs' : [
|
|
||||||
'<!@(node -p "require(\'addon-tools-raub\').include")',
|
|
||||||
'<(DEPS_include)',
|
|
||||||
],
|
|
||||||
'cflags_cc': ['-std=c++17', '-fno-exceptions'],
|
|
||||||
'library_dirs': ['<(DEPS_bin)'],
|
|
||||||
'libraries': ['-lDEPS' ],
|
|
||||||
'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)',
|
|
||||||
],
|
|
||||||
'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'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
declare module "addon-tools-raub" {
|
declare module "addon-tools-raub" {
|
||||||
/**
|
/**
|
||||||
* Addon paths
|
* Get the internal paths for an addon
|
||||||
* Returns a set of platform dependent paths depending on input dir
|
* Returns a set of platform dependent paths depending on the input dir
|
||||||
*/
|
*/
|
||||||
export const paths: (dir: string) => Readonly<{
|
export const getPaths: (dir: string) => Readonly<{
|
||||||
/**
|
/**
|
||||||
* Path to binaries
|
* Path to binaries
|
||||||
* Platform binary directory absolute path for this `dir`
|
* Platform binary directory absolute path for this `dir`
|
||||||
|
@ -20,16 +20,231 @@ declare module "addon-tools-raub" {
|
||||||
type TPlatformDir = `bin-${TPlatformName}`;
|
type TPlatformDir = `bin-${TPlatformName}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Platform-dependent binary directory name
|
* Get the platform-specific binary directory name
|
||||||
*/
|
*/
|
||||||
export const bin: TPlatformDir;
|
export const getBin: () => TPlatformDir;
|
||||||
|
|
||||||
export const platform: TPlatformName;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main include directories
|
* Get the platform identifier
|
||||||
* Both 'addon-tools-raub' and 'node-addon-api' include paths.
|
|
||||||
* For binding.gyp: `'<!@(node -p "require(\'addon-tools-raub\').include")'`
|
|
||||||
*/
|
*/
|
||||||
export const include: string;
|
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 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 { 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) => void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package version for GitHub Actions
|
||||||
|
* Example of `actionVersion` usage in **Github Actions**:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* - name: Get Package Version
|
||||||
|
* id: package-version
|
||||||
|
* run: node -e \"require('addon-tools-raub').actionVersion()\" >> $GITHUB_OUTPUT
|
||||||
|
* - name: Create Release
|
||||||
|
* uses: softprops/action-gh-release@v1
|
||||||
|
* with:
|
||||||
|
* tag_name: ${{ steps.package-version.outputs.version }}
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export const actionVersion: () => void;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Package version for GitHub Actions
|
||||||
|
* Example of `actionZip` usage in **Github Actions**:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* - name: Zip Files
|
||||||
|
* id: zip-files
|
||||||
|
* run: node action-zip >> $GITHUB_OUTPUT
|
||||||
|
* - name: Store Binaries
|
||||||
|
* uses: softprops/action-gh-release@v1
|
||||||
|
* with:
|
||||||
|
* files: ${{ steps.zip-files.outputs.zip }}
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
export const actionZip: () => 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 extends Writable {
|
||||||
|
constructor();
|
||||||
|
/**
|
||||||
|
* Get the downloaded data
|
||||||
|
* Use `stream.get()` to obtain the data when writing was finished
|
||||||
|
*/
|
||||||
|
get(): Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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>;
|
||||||
}
|
}
|
||||||
|
|
3
index.js
3
index.js
|
@ -1,5 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...require('./include/index'),
|
...require('./include'),
|
||||||
|
...require('./utils'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const arrayArgMsg = 'Argument 0 must be of type `Array`';
|
const arrayArgMsg = 'Argument 0 must be of type `Array`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: LET_ARRAY_ARG', () => {
|
describe('AT / addon-tools.hpp / LET_ARRAY_ARG', () => {
|
||||||
it('exports letArrayStrArg', () => {
|
it('exports letArrayStrArg', () => {
|
||||||
expect(typeof test.letArrayStrArg).toBe('function');
|
expect(typeof test.letArrayStrArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const arrayArgMsg = 'Argument 0 must be of type `Array`';
|
const arrayArgMsg = 'Argument 0 must be of type `Array`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_ARRAY_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_ARRAY_ARG', () => {
|
||||||
it('exports reqArrayArg', () => {
|
it('exports reqArrayArg', () => {
|
||||||
expect(typeof test.reqArrayArg).toBe('function');
|
expect(typeof test.reqArrayArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const boolArgMsg = 'Argument 0 must be of type `Bool`';
|
const boolArgMsg = 'Argument 0 must be of type `Bool`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_BOOL_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_BOOL_ARG', () => {
|
||||||
it('exports reqBoolArg', () => {
|
it('exports reqBoolArg', () => {
|
||||||
expect(typeof test.reqBoolArg).toBe('function');
|
expect(typeof test.reqBoolArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const numArgMsg = 'Argument 0 must be of type `Number`';
|
const numArgMsg = 'Argument 0 must be of type `Number`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_DOUBLE_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_DOUBLE_ARG', () => {
|
||||||
it('exports reqDoubleArg', () => {
|
it('exports reqDoubleArg', () => {
|
||||||
expect(typeof test.reqDoubleArg).toBe('function');
|
expect(typeof test.reqDoubleArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const extArgMsg = 'Argument 0 must be of type `Pointer`';
|
const extArgMsg = 'Argument 0 must be of type `Pointer`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_EXT_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_EXT_ARG', () => {
|
||||||
it('exports reqExtArg', () => {
|
it('exports reqExtArg', () => {
|
||||||
expect(typeof test.reqExtArg).toBe('function');
|
expect(typeof test.reqExtArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const numArgMsg = 'Argument 0 must be of type `Number`';
|
const numArgMsg = 'Argument 0 must be of type `Number`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_FLOAT_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_FLOAT_ARG', () => {
|
||||||
it('exports reqFloatArg', () => {
|
it('exports reqFloatArg', () => {
|
||||||
expect(typeof test.reqFloatArg).toBe('function');
|
expect(typeof test.reqFloatArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const intArgMsg = 'Argument 0 must be of type `Int32`';
|
const intArgMsg = 'Argument 0 must be of type `Int32`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_INT_ARG / REQ_INT32_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_INT_ARG, REQ_INT32_ARG', () => {
|
||||||
it('exports reqIntArg', () => {
|
it('exports reqIntArg', () => {
|
||||||
expect(typeof test.reqIntArg).toBe('function');
|
expect(typeof test.reqIntArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const objArgMsg = 'Argument 0 must be of type `Object`';
|
const objArgMsg = 'Argument 0 must be of type `Object`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_OBJ_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_OBJ_ARG', () => {
|
||||||
it('exports reqObjArg', () => {
|
it('exports reqObjArg', () => {
|
||||||
expect(typeof test.reqObjArg).toBe('function');
|
expect(typeof test.reqObjArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const numArgMsg = 'Argument 0 must be of type `Number`';
|
const numArgMsg = 'Argument 0 must be of type `Number`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_OFFS_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_OFFS_ARG', () => {
|
||||||
it('exports reqOffsArg', () => {
|
it('exports reqOffsArg', () => {
|
||||||
expect(typeof test.reqOffsArg).toBe('function');
|
expect(typeof test.reqOffsArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const strArgMsg = 'Argument 0 must be of type `String`';
|
const strArgMsg = 'Argument 0 must be of type `String`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_STR_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_STR_ARG', () => {
|
||||||
it('exports reqStrArg', () => {
|
it('exports reqStrArg', () => {
|
||||||
expect(typeof test.reqStrArg).toBe('function');
|
expect(typeof test.reqStrArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
const uintArgMsg = 'Argument 0 must be of type `Uint32`';
|
const uintArgMsg = 'Argument 0 must be of type `Uint32`';
|
||||||
|
|
||||||
describe('addon-tools.hpp: REQ_UINT_ARG / REQ_UINT32_ARG', () => {
|
describe('AT / addon-tools.hpp / REQ_UINT_ARG, REQ_UINT32_ARG', () => {
|
||||||
it('exports reqUintArg', () => {
|
it('exports reqUintArg', () => {
|
||||||
expect(typeof test.reqUintArg).toBe('function');
|
expect(typeof test.reqUintArg).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
const test = require('./build/Release/test.node');
|
const test = require('./build/Release/test.node');
|
||||||
|
|
||||||
|
|
||||||
describe('addon-tools.hpp: Function arguments', () => {
|
describe('AT / addon-tools.hpp / Function arguments', () => {
|
||||||
|
|
||||||
describe('REQ_ARGS', () => {
|
describe('REQ_ARGS', () => {
|
||||||
it('exports reqArgs3', () => {
|
it('exports reqArgs3', () => {
|
||||||
expect(typeof test.reqArgs3).toBe('function');
|
expect(typeof test.reqArgs3).toBe('function');
|
||||||
|
@ -203,5 +202,4 @@ describe('addon-tools.hpp: Function arguments', () => {
|
||||||
expect(test.reqTypedArg(typed)).toEqual(typed);
|
expect(test.reqTypedArg(typed)).toEqual(typed);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,215 +0,0 @@
|
||||||
import type { Writable } from 'stream';
|
|
||||||
|
|
||||||
declare module "addon-tools-raub/utils" {
|
|
||||||
/**
|
|
||||||
* Install binaries
|
|
||||||
* 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 install = require('addon-tools-raub/install');
|
|
||||||
* const prefix = 'https://github.com/USER/ADDON-NAME/releases/download';
|
|
||||||
* const tag = 'v1.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) => void;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy binary
|
|
||||||
* Copies the addon binary from `src/build/Release` to the platform folder.
|
|
||||||
* ```
|
|
||||||
* declare const cpbin: (name: string) => Promise<void>;
|
|
||||||
* export default cpbin;
|
|
||||||
* ```
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
export const cpbin: (name: string) => Promise<void>;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Package version for GitHub Actions
|
|
||||||
* Example of `actionVersion` usage in **Github Actions**:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* - name: Get Package Version
|
|
||||||
* id: package-version
|
|
||||||
* run: node -e \"require('addon-tools-raub/utils').actionVersion()\" >> $GITHUB_OUTPUT
|
|
||||||
* - name: Create Release
|
|
||||||
* uses: softprops/action-gh-release@v1
|
|
||||||
* with:
|
|
||||||
* tag_name: ${{ steps.package-version.outputs.version }}
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export const actionVersion: () => void;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Package version for GitHub Actions
|
|
||||||
* Example of `actionZip` usage in **Github Actions**:
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* - name: Zip Files
|
|
||||||
* id: zip-files
|
|
||||||
* run: node action-zip >> $GITHUB_OUTPUT
|
|
||||||
* - name: Store Binaries
|
|
||||||
* uses: softprops/action-gh-release@v1
|
|
||||||
* with:
|
|
||||||
* files: ${{ steps.zip-files.outputs.zip }}
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
export const actionZip: () => 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 extends Writable {
|
|
||||||
constructor();
|
|
||||||
/**
|
|
||||||
* Get the downloaded data
|
|
||||||
* Use `stream.get()` to obtain the data when writing was finished
|
|
||||||
*/
|
|
||||||
get(): Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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>;
|
|
||||||
}
|
|
5
utils.js
5
utils.js
|
@ -1,5 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
...require('./utils/index'),
|
|
||||||
};
|
|
|
@ -7,7 +7,7 @@ const utils = require('.');
|
||||||
const packageJson = require('../package.json');
|
const packageJson = require('../package.json');
|
||||||
|
|
||||||
|
|
||||||
describe('utils.js', () => {
|
describe('AT / utils', () => {
|
||||||
const methods = [
|
const methods = [
|
||||||
'install', 'cpbin', 'download', 'read', 'write', 'copy', 'exists',
|
'install', 'cpbin', 'download', 'read', 'write', 'copy', 'exists',
|
||||||
'mkdir', 'stat', 'isDir', 'isFile', 'dirUp', 'ensuredir', 'copysafe',
|
'mkdir', 'stat', 'isDir', 'isFile', 'dirUp', 'ensuredir', 'copysafe',
|
||||||
|
|
Loading…
Reference in New Issue