1
0
Fork 0

feat: add utils from isolex

This commit is contained in:
ssube 2020-03-29 08:43:52 -05:00
parent 3b193a1437
commit e227fa6691
Signed by: ssube
GPG Key ID: 3EED7B957D362AF1
108 changed files with 2491 additions and 132 deletions

View File

@ -150,7 +150,7 @@ sonar-success:
script: script:
- make node_modules - make node_modules
- sonar-scanner - sonar-scanner
-Dsonar.projectKey=ssube_rollup-template -Dsonar.projectKey=ssube_js-utils
-Dsonar.projectVersion=${CI_COMMIT_REF_SLUG} -Dsonar.projectVersion=${CI_COMMIT_REF_SLUG}
-Dsonar.organization=ssube-github -Dsonar.organization=ssube-github
-Dsonar.sources=src/,test/ -Dsonar.sources=src/,test/

View File

@ -154,7 +154,6 @@
"error", "error",
"any", "any",
"Number", "Number",
"String",
"Boolean", "Boolean",
"Undefined" "Undefined"
], ],

View File

@ -2,5 +2,11 @@
"node_modules/chai/index.js": [ "node_modules/chai/index.js": [
"expect", "expect",
"use" "use"
],
"node_modules/lodash/lodash.js": [
"isFunction",
"isMap",
"isObject",
"isString"
] ]
} }

View File

@ -8,5 +8,5 @@
| Package | Description | | Package | Description |
| --- | --- | | --- | --- |
| [@apextoaster/rollup-template](./rollup-template.md) | | | [@apextoaster/js-utils](./js-utils.md) | |

View File

@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ArrayMapper](./js-utils.arraymapper.md) &gt; [(constructor)](./js-utils.arraymapper._constructor_.md)
## ArrayMapper.(constructor)
Constructs a new instance of the `ArrayMapper` class
<b>Signature:</b>
```typescript
constructor(options: ArrayMapperOptions);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| options | <code>ArrayMapperOptions</code> | |

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ArrayMapper](./js-utils.arraymapper.md) &gt; [map](./js-utils.arraymapper.map.md)
## ArrayMapper.map() method
<b>Signature:</b>
```typescript
map(input: Array<string>): Map<string, Array<string>>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| input | <code>Array&lt;string&gt;</code> | |
<b>Returns:</b>
`Map<string, Array<string>>`

View File

@ -0,0 +1,32 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ArrayMapper](./js-utils.arraymapper.md)
## ArrayMapper class
<b>Signature:</b>
```typescript
export declare class ArrayMapper
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(options)](./js-utils.arraymapper._constructor_.md) | | Constructs a new instance of the <code>ArrayMapper</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [rest](./js-utils.arraymapper.rest.md) | | <code>string</code> | |
| [skip](./js-utils.arraymapper.skip.md) | | <code>number</code> | |
| [take](./js-utils.arraymapper.take.md) | | <code>Array&lt;string&gt;</code> | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [map(input)](./js-utils.arraymapper.map.md) | | |

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ArrayMapper](./js-utils.arraymapper.md) &gt; [rest](./js-utils.arraymapper.rest.md)
## ArrayMapper.rest property
<b>Signature:</b>
```typescript
readonly rest: string;
```

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ArrayMapper](./js-utils.arraymapper.md) &gt; [skip](./js-utils.arraymapper.skip.md)
## ArrayMapper.skip property
<b>Signature:</b>
```typescript
readonly skip: number;
```

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ArrayMapper](./js-utils.arraymapper.md) &gt; [take](./js-utils.arraymapper.take.md)
## ArrayMapper.take property
<b>Signature:</b>
```typescript
readonly take: Array<string>;
```

View File

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [(constructor)](./js-utils.asynctracker._constructor_.md)
## AsyncTracker.(constructor)
Constructs a new instance of the `AsyncTracker` class
<b>Signature:</b>
```typescript
constructor();
```

View File

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [clear](./js-utils.asynctracker.clear.md)
## AsyncTracker.clear() method
<b>Signature:</b>
```typescript
clear(): void;
```
<b>Returns:</b>
`void`

View File

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [disable](./js-utils.asynctracker.disable.md)
## AsyncTracker.disable() method
<b>Signature:</b>
```typescript
disable(): void;
```
<b>Returns:</b>
`void`

View File

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [dump](./js-utils.asynctracker.dump.md)
## AsyncTracker.dump() method
<b>Signature:</b>
```typescript
dump(): void;
```
<b>Returns:</b>
`void`

View File

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [enable](./js-utils.asynctracker.enable.md)
## AsyncTracker.enable() method
<b>Signature:</b>
```typescript
enable(): void;
```
<b>Returns:</b>
`void`

View File

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [getStack](./js-utils.asynctracker.getstack.md)
## AsyncTracker.getStack() method
<b>Signature:</b>
```typescript
static getStack(): string;
```
<b>Returns:</b>
`string`

View File

@ -0,0 +1,38 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md)
## AsyncTracker class
Async resource tracker using node's internal hooks.
This probably won't work in a browser. It does not hold references to the resource, to avoid leaks. Adapted from https://gist.github.com/boneskull/7fe75b63d613fa940db7ec990a5f5843\#file-async-dump-js
<b>Signature:</b>
```typescript
export declare class AsyncTracker
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)()](./js-utils.asynctracker._constructor_.md) | | Constructs a new instance of the <code>AsyncTracker</code> class |
## Properties
| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [size](./js-utils.asynctracker.size.md) | | <code>number</code> | |
## Methods
| Method | Modifiers | Description |
| --- | --- | --- |
| [clear()](./js-utils.asynctracker.clear.md) | | |
| [disable()](./js-utils.asynctracker.disable.md) | | |
| [dump()](./js-utils.asynctracker.dump.md) | | |
| [enable()](./js-utils.asynctracker.enable.md) | | |
| [getStack()](./js-utils.asynctracker.getstack.md) | <code>static</code> | |

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [AsyncTracker](./js-utils.asynctracker.md) &gt; [size](./js-utils.asynctracker.size.md)
## AsyncTracker.size property
<b>Signature:</b>
```typescript
get size(): number;
```

View File

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ChildProcessError](./js-utils.childprocesserror.md) &gt; [(constructor)](./js-utils.childprocesserror._constructor_.md)
## ChildProcessError.(constructor)
Constructs a new instance of the `ChildProcessError` class
<b>Signature:</b>
```typescript
constructor(msg?: string, ...nested: Array<Error>);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| msg | <code>string</code> | |
| nested | <code>Array&lt;Error&gt;</code> | |

View File

@ -0,0 +1,18 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ChildProcessError](./js-utils.childprocesserror.md)
## ChildProcessError class
<b>Signature:</b>
```typescript
export declare class ChildProcessError extends BaseError
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(msg, nested)](./js-utils.childprocesserror._constructor_.md) | | Constructs a new instance of the <code>ChildProcessError</code> class |

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [concat](./js-utils.concat.md)
## concat() function
<b>Signature:</b>
```typescript
export declare function concat(chunks: Array<Buffer>): Buffer;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| chunks | <code>Array&lt;Buffer&gt;</code> | |
<b>Returns:</b>
`Buffer`

View File

@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [countOf](./js-utils.countof.md)
## countOf() function
Calculate the "length" of an array or value.
Arrays return their length, single values return 1, and nil values return 0. This counts the number of elements that setOrPush would add.
<b>Signature:</b>
```typescript
export declare function countOf(val: unknown): number;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| val | <code>unknown</code> | |
<b>Returns:</b>
`number`

View File

@ -0,0 +1,23 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [defaultWhen](./js-utils.defaultwhen.md)
## defaultWhen() function
<b>Signature:</b>
```typescript
export declare function defaultWhen<TVal>(condition: boolean, ...items: Array<TVal>): TVal;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| condition | <code>boolean</code> | |
| items | <code>Array&lt;TVal&gt;</code> | |
<b>Returns:</b>
`TVal`

View File

@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [defer](./js-utils.defer.md)
## defer() function
Resolve after a set amount of time.
<b>Signature:</b>
```typescript
export declare function defer<T = undefined>(ms: number, val?: T): Promise<T>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| ms | <code>number</code> | |
| val | <code>T</code> | |
<b>Returns:</b>
`Promise<T>`

11
docs/api/js-utils.dict.md Normal file
View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [Dict](./js-utils.dict.md)
## Dict interface
<b>Signature:</b>
```typescript
export interface Dict<TVal>
```

View File

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [doesExist](./js-utils.doesexist.md)
## doesExist() function
Check if a variable is not nil.
<b>Signature:</b>
```typescript
export declare function doesExist<T>(val: Optional<T>): val is T;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| val | <code>Optional&lt;T&gt;</code> | |
<b>Returns:</b>
`val is T`

View File

@ -0,0 +1,23 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [encode](./js-utils.encode.md)
## encode() function
<b>Signature:</b>
```typescript
export declare function encode(chunks: Array<Buffer>, encoding: string): string;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| chunks | <code>Array&lt;Buffer&gt;</code> | |
| encoding | <code>string</code> | |
<b>Returns:</b>
`string`

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [entriesOf](./js-utils.entriesof.md)
## entriesOf() function
<b>Signature:</b>
```typescript
export declare function entriesOf<TVal>(map: Optional<MapLike<TVal>>): Array<[string, TVal]>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| map | <code>Optional&lt;MapLike&lt;TVal&gt;&gt;</code> | |
<b>Returns:</b>
`Array<[string, TVal]>`

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ExternalModule](./js-utils.externalmodule.md) &gt; [data](./js-utils.externalmodule.data.md)
## ExternalModule.data property
<b>Signature:</b>
```typescript
data?: unknown;
```

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ExternalModule](./js-utils.externalmodule.md) &gt; [export](./js-utils.externalmodule.export.md)
## ExternalModule.export property
<b>Signature:</b>
```typescript
export: string;
```

View File

@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ExternalModule](./js-utils.externalmodule.md)
## ExternalModule interface
<b>Signature:</b>
```typescript
export interface ExternalModule
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [data](./js-utils.externalmodule.data.md) | <code>unknown</code> | |
| [export](./js-utils.externalmodule.export.md) | <code>string</code> | |
| [require](./js-utils.externalmodule.require.md) | <code>string</code> | |

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ExternalModule](./js-utils.externalmodule.md) &gt; [require](./js-utils.externalmodule.require.md)
## ExternalModule.require property
<b>Signature:</b>
```typescript
require: string;
```

View File

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [filterNil](./js-utils.filternil.md)
## filterNil() function
Remove any null or undefined items from the list.
<b>Signature:</b>
```typescript
export declare function filterNil<TItem>(list: ArrayLike<Optional<TItem>>): Array<TItem>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| list | <code>ArrayLike&lt;Optional&lt;TItem&gt;&gt;</code> | |
<b>Returns:</b>
`Array<TItem>`

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [getTestLogger](./js-utils.gettestlogger.md)
## getTestLogger() function
<b>Signature:</b>
```typescript
export declare function getTestLogger(verbose?: boolean): Logger;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| verbose | <code>boolean</code> | |
<b>Returns:</b>
`Logger`

View File

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [InvalidArgumentError](./js-utils.invalidargumenterror.md) &gt; [(constructor)](./js-utils.invalidargumenterror._constructor_.md)
## InvalidArgumentError.(constructor)
Constructs a new instance of the `InvalidArgumentError` class
<b>Signature:</b>
```typescript
constructor(msg?: string, ...nested: Array<Error>);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| msg | <code>string</code> | |
| nested | <code>Array&lt;Error&gt;</code> | |

View File

@ -0,0 +1,18 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [InvalidArgumentError](./js-utils.invalidargumenterror.md)
## InvalidArgumentError class
<b>Signature:</b>
```typescript
export declare class InvalidArgumentError extends BaseError
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(msg, nested)](./js-utils.invalidargumenterror._constructor_.md) | | Constructs a new instance of the <code>InvalidArgumentError</code> class |

View File

@ -0,0 +1,15 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [isDebug](./js-utils.isdebug.md)
## isDebug() function
<b>Signature:</b>
```typescript
export declare function isDebug(): boolean;
```
<b>Returns:</b>
`boolean`

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [isNil](./js-utils.isnil.md)
## isNil() function
<b>Signature:</b>
```typescript
export declare function isNil<T>(val: Optional<T>): val is Nil;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| val | <code>Optional&lt;T&gt;</code> | |
<b>Returns:</b>
`val is Nil`

View File

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [makeDict](./js-utils.makedict.md)
## makeDict() function
Turns a map or dict into a dict
<b>Signature:</b>
```typescript
export declare function makeDict<TVal>(map: Optional<MapLike<TVal>>): Dict<TVal>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| map | <code>Optional&lt;MapLike&lt;TVal&gt;&gt;</code> | |
<b>Returns:</b>
`Dict<TVal>`

View File

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [makeMap](./js-utils.makemap.md)
## makeMap() function
Clone a map or map-like object into a new map.
<b>Signature:</b>
```typescript
export declare function makeMap<TVal>(val: Optional<MapLike<TVal>>): Map<string, TVal>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| val | <code>Optional&lt;MapLike&lt;TVal&gt;&gt;</code> | |
<b>Returns:</b>
`Map<string, TVal>`

View File

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [MapLike](./js-utils.maplike.md)
## MapLike type
A `Map` or dictionary object with string keys and `TVal` values.
<b>Signature:</b>
```typescript
export declare type MapLike<TVal> = Map<string, TVal> | Dict<TVal>;
```

75
docs/api/js-utils.md Normal file
View File

@ -0,0 +1,75 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md)
## js-utils package
## Classes
| Class | Description |
| --- | --- |
| [ArrayMapper](./js-utils.arraymapper.md) | |
| [AsyncTracker](./js-utils.asynctracker.md) | Async resource tracker using node's internal hooks.<!-- -->This probably won't work in a browser. It does not hold references to the resource, to avoid leaks. Adapted from https://gist.github.com/boneskull/7fe75b63d613fa940db7ec990a5f5843\#file-async-dump-js |
| [ChildProcessError](./js-utils.childprocesserror.md) | |
| [InvalidArgumentError](./js-utils.invalidargumenterror.md) | |
| [MissingKeyError](./js-utils.missingkeyerror.md) | |
| [NotFoundError](./js-utils.notfounderror.md) | |
| [NotImplementedError](./js-utils.notimplementederror.md) | |
| [TimeoutError](./js-utils.timeouterror.md) | |
## Functions
| Function | Description |
| --- | --- |
| [concat(chunks)](./js-utils.concat.md) | |
| [countOf(val)](./js-utils.countof.md) | Calculate the "length" of an array or value.<!-- -->Arrays return their length, single values return 1, and nil values return 0. This counts the number of elements that setOrPush would add. |
| [defaultWhen(condition, items)](./js-utils.defaultwhen.md) | |
| [defer(ms, val)](./js-utils.defer.md) | Resolve after a set amount of time. |
| [doesExist(val)](./js-utils.doesexist.md) | Check if a variable is not nil. |
| [encode(chunks, encoding)](./js-utils.encode.md) | |
| [entriesOf(map)](./js-utils.entriesof.md) | |
| [filterNil(list)](./js-utils.filternil.md) | Remove any null or undefined items from the list. |
| [getTestLogger(verbose)](./js-utils.gettestlogger.md) | |
| [isDebug()](./js-utils.isdebug.md) | |
| [isNil(val)](./js-utils.isnil.md) | |
| [makeDict(map)](./js-utils.makedict.md) | Turns a map or dict into a dict |
| [makeMap(val)](./js-utils.makemap.md) | Clone a map or map-like object into a new map. |
| [mergeList(parts)](./js-utils.mergelist.md) | Merge arguments, which may or may not be arrays, into one return that is definitely an array. |
| [mergeMap(target, source)](./js-utils.mergemap.md) | |
| [mustCoalesce(values)](./js-utils.mustcoalesce.md) | Return the first value that is not nil. |
| [mustExist(val)](./js-utils.mustexist.md) | Assert that a variable is not nil and return the value. |
| [mustFind(list, predicate)](./js-utils.mustfind.md) | Find a value matching the given predicate or throw. |
| [mustGet(map, key)](./js-utils.mustget.md) | Get an element from a Map and guard against nil values. |
| [pushMergeMap(args)](./js-utils.pushmergemap.md) | |
| [removePid(path)](./js-utils.removepid.md) | |
| [setOrPush(map, key, val)](./js-utils.setorpush.md) | Set a map key to a new array or push to the existing value. |
| [signal(signals)](./js-utils.signal.md) | |
| [spyLogger(spies)](./js-utils.spylogger.md) | |
| [timeout(ms, oper)](./js-utils.timeout.md) | Reject after a set amount of time if the original promise has not yet resolved. |
| [waitForChild(child)](./js-utils.waitforchild.md) | |
| [writePid(path)](./js-utils.writepid.md) | |
## Interfaces
| Interface | Description |
| --- | --- |
| [Dict](./js-utils.dict.md) | |
| [ExternalModule](./js-utils.externalmodule.md) | |
## Variables
| Variable | Description |
| --- | --- |
| [SIGNAL\_RELOAD](./js-utils.signal_reload.md) | |
| [SIGNAL\_RESET](./js-utils.signal_reset.md) | |
| [SIGNAL\_STOP](./js-utils.signal_stop.md) | |
## Type Aliases
| Type Alias | Description |
| --- | --- |
| [MapLike](./js-utils.maplike.md) | A <code>Map</code> or dictionary object with string keys and <code>TVal</code> values. |
| [ModuleCtor](./js-utils.modulector.md) | |
| [Nil](./js-utils.nil.md) | Unset value. |
| [Optional](./js-utils.optional.md) | Value that may be nil. |

View File

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [mergeList](./js-utils.mergelist.md)
## mergeList() function
Merge arguments, which may or may not be arrays, into one return that is definitely an array.
<b>Signature:</b>
```typescript
export declare function mergeList<TItem>(...parts: Array<TItem | Array<TItem>>): Array<TItem>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| parts | <code>Array&lt;TItem &#124; Array&lt;TItem&gt;&gt;</code> | |
<b>Returns:</b>
`Array<TItem>`

View File

@ -0,0 +1,23 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [mergeMap](./js-utils.mergemap.md)
## mergeMap() function
<b>Signature:</b>
```typescript
export declare function mergeMap<TKey, TVal>(target: Map<TKey, TVal>, source: Map<TKey, TVal> | Array<[TKey, TVal]>): Map<TKey, TVal>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| target | <code>Map&lt;TKey, TVal&gt;</code> | |
| source | <code>Map&lt;TKey, TVal&gt; &#124; Array&lt;[TKey, TVal]&gt;</code> | |
<b>Returns:</b>
`Map<TKey, TVal>`

View File

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [MissingKeyError](./js-utils.missingkeyerror.md) &gt; [(constructor)](./js-utils.missingkeyerror._constructor_.md)
## MissingKeyError.(constructor)
Constructs a new instance of the `MissingKeyError` class
<b>Signature:</b>
```typescript
constructor(msg?: string, ...nested: Array<Error>);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| msg | <code>string</code> | |
| nested | <code>Array&lt;Error&gt;</code> | |

View File

@ -0,0 +1,18 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [MissingKeyError](./js-utils.missingkeyerror.md)
## MissingKeyError class
<b>Signature:</b>
```typescript
export declare class MissingKeyError extends BaseError
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(msg, nested)](./js-utils.missingkeyerror._constructor_.md) | | Constructs a new instance of the <code>MissingKeyError</code> class |

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [ModuleCtor](./js-utils.modulector.md)
## ModuleCtor type
<b>Signature:</b>
```typescript
export declare type ModuleCtor = new (data: unknown) => Module;
```

View File

@ -0,0 +1,24 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [mustCoalesce](./js-utils.mustcoalesce.md)
## mustCoalesce() function
Return the first value that is not nil.
<b>Signature:</b>
```typescript
export declare function mustCoalesce<T>(...values: Array<Optional<T>>): T;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| values | <code>Array&lt;Optional&lt;T&gt;&gt;</code> | |
<b>Returns:</b>
`T`

View File

@ -0,0 +1,30 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [mustExist](./js-utils.mustexist.md)
## mustExist() function
Assert that a variable is not nil and return the value.
<b>Signature:</b>
```typescript
export declare function mustExist<T>(val: Optional<T>): T;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| val | <code>Optional&lt;T&gt;</code> | |
<b>Returns:</b>
`T`
val
## Exceptions
NotFoundError

View File

@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [mustFind](./js-utils.mustfind.md)
## mustFind() function
Find a value matching the given predicate or throw.
<b>Signature:</b>
```typescript
export declare function mustFind<TVal>(list: Array<Optional<TVal>>, predicate: PredicateC1<TVal>): TVal;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| list | <code>Array&lt;Optional&lt;TVal&gt;&gt;</code> | |
| predicate | <code>PredicateC1&lt;TVal&gt;</code> | |
<b>Returns:</b>
`TVal`

View File

@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [mustGet](./js-utils.mustget.md)
## mustGet() function
Get an element from a Map and guard against nil values.
<b>Signature:</b>
```typescript
export declare function mustGet<TKey, TVal>(map: Map<TKey, TVal>, key: TKey): TVal;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| map | <code>Map&lt;TKey, TVal&gt;</code> | |
| key | <code>TKey</code> | |
<b>Returns:</b>
`TVal`

13
docs/api/js-utils.nil.md Normal file
View File

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [Nil](./js-utils.nil.md)
## Nil type
Unset value.
<b>Signature:</b>
```typescript
export declare type Nil = null | undefined;
```

View File

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [NotFoundError](./js-utils.notfounderror.md) &gt; [(constructor)](./js-utils.notfounderror._constructor_.md)
## NotFoundError.(constructor)
Constructs a new instance of the `NotFoundError` class
<b>Signature:</b>
```typescript
constructor(msg?: string, ...nested: Array<Error>);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| msg | <code>string</code> | |
| nested | <code>Array&lt;Error&gt;</code> | |

View File

@ -0,0 +1,18 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [NotFoundError](./js-utils.notfounderror.md)
## NotFoundError class
<b>Signature:</b>
```typescript
export declare class NotFoundError extends BaseError
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(msg, nested)](./js-utils.notfounderror._constructor_.md) | | Constructs a new instance of the <code>NotFoundError</code> class |

View File

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [NotImplementedError](./js-utils.notimplementederror.md) &gt; [(constructor)](./js-utils.notimplementederror._constructor_.md)
## NotImplementedError.(constructor)
Constructs a new instance of the `NotImplementedError` class
<b>Signature:</b>
```typescript
constructor(msg?: string, ...nested: Array<Error>);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| msg | <code>string</code> | |
| nested | <code>Array&lt;Error&gt;</code> | |

View File

@ -0,0 +1,18 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [NotImplementedError](./js-utils.notimplementederror.md)
## NotImplementedError class
<b>Signature:</b>
```typescript
export declare class NotImplementedError extends BaseError
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(msg, nested)](./js-utils.notimplementederror._constructor_.md) | | Constructs a new instance of the <code>NotImplementedError</code> class |

View File

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [Optional](./js-utils.optional.md)
## Optional type
Value that may be nil.
<b>Signature:</b>
```typescript
export declare type Optional<T> = T | Nil;
```

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [pushMergeMap](./js-utils.pushmergemap.md)
## pushMergeMap() function
<b>Signature:</b>
```typescript
export declare function pushMergeMap<TKey, TVal>(...args: Array<Map<TKey, TVal | Array<TVal>>>): Map<TKey, Array<TVal>>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| args | <code>Array&lt;Map&lt;TKey, TVal &#124; Array&lt;TVal&gt;&gt;&gt;</code> | |
<b>Returns:</b>
`Map<TKey, Array<TVal>>`

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [removePid](./js-utils.removepid.md)
## removePid() function
<b>Signature:</b>
```typescript
export declare function removePid(path: string): Promise<void>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| path | <code>string</code> | |
<b>Returns:</b>
`Promise<void>`

View File

@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [setOrPush](./js-utils.setorpush.md)
## setOrPush() function
Set a map key to a new array or push to the existing value.
<b>Signature:</b>
```typescript
export declare function setOrPush<TKey, TVal>(map: Map<TKey, Array<TVal>>, key: TKey, val: TVal | Array<TVal>): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| map | <code>Map&lt;TKey, Array&lt;TVal&gt;&gt;</code> | |
| key | <code>TKey</code> | |
| val | <code>TVal &#124; Array&lt;TVal&gt;</code> | |
<b>Returns:</b>
`void`

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [signal](./js-utils.signal.md)
## signal() function
<b>Signature:</b>
```typescript
export declare function signal(...signals: Array<NodeJS.Signals>): Promise<NodeJS.Signals>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| signals | <code>Array&lt;NodeJS.Signals&gt;</code> | |
<b>Returns:</b>
`Promise<NodeJS.Signals>`

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [SIGNAL\_RELOAD](./js-utils.signal_reload.md)
## SIGNAL\_RELOAD variable
<b>Signature:</b>
```typescript
SIGNAL_RELOAD: NodeJS.Signals
```

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [SIGNAL\_RESET](./js-utils.signal_reset.md)
## SIGNAL\_RESET variable
<b>Signature:</b>
```typescript
SIGNAL_RESET: NodeJS.Signals
```

View File

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [SIGNAL\_STOP](./js-utils.signal_stop.md)
## SIGNAL\_STOP variable
<b>Signature:</b>
```typescript
SIGNAL_STOP: NodeJS.Signals
```

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [spyLogger](./js-utils.spylogger.md)
## spyLogger() function
<b>Signature:</b>
```typescript
export declare function spyLogger(spies: Partial<Logger>): Logger;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| spies | <code>Partial&lt;Logger&gt;</code> | |
<b>Returns:</b>
`Logger`

View File

@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [timeout](./js-utils.timeout.md)
## timeout() function
Reject after a set amount of time if the original promise has not yet resolved.
<b>Signature:</b>
```typescript
export declare function timeout<T>(ms: number, oper: Promise<T>): Promise<T>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| ms | <code>number</code> | |
| oper | <code>Promise&lt;T&gt;</code> | |
<b>Returns:</b>
`Promise<T>`

View File

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [TimeoutError](./js-utils.timeouterror.md) &gt; [(constructor)](./js-utils.timeouterror._constructor_.md)
## TimeoutError.(constructor)
Constructs a new instance of the `TimeoutError` class
<b>Signature:</b>
```typescript
constructor(msg?: string, ...nested: Array<Error>);
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| msg | <code>string</code> | |
| nested | <code>Array&lt;Error&gt;</code> | |

View File

@ -0,0 +1,18 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [TimeoutError](./js-utils.timeouterror.md)
## TimeoutError class
<b>Signature:</b>
```typescript
export declare class TimeoutError extends BaseError
```
## Constructors
| Constructor | Modifiers | Description |
| --- | --- | --- |
| [(constructor)(msg, nested)](./js-utils.timeouterror._constructor_.md) | | Constructs a new instance of the <code>TimeoutError</code> class |

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [waitForChild](./js-utils.waitforchild.md)
## waitForChild() function
<b>Signature:</b>
```typescript
export declare function waitForChild(child: ChildProcessWithoutNullStreams): Promise<ChildResult>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| child | <code>ChildProcessWithoutNullStreams</code> | |
<b>Returns:</b>
`Promise<ChildResult>`

View File

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/js-utils](./js-utils.md) &gt; [writePid](./js-utils.writepid.md)
## writePid() function
<b>Signature:</b>
```typescript
export declare function writePid(path: string): Promise<void>;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| path | <code>string</code> | |
<b>Returns:</b>
`Promise<void>`

View File

@ -1,6 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [@apextoaster/rollup-template](./rollup-template.md)
## rollup-template package

View File

@ -2,7 +2,7 @@
"name": "@apextoaster/js-utils", "name": "@apextoaster/js-utils",
"version": "0.1.1", "version": "0.1.1",
"description": "utility functions", "description": "utility functions",
"main": "out/index.js", "main": "out/main.js",
"types": "out/index.d.ts", "types": "out/index.d.ts",
"typings": "out/index.d.ts", "typings": "out/index.d.ts",
"directories": { "directories": {
@ -28,6 +28,7 @@
"@types/chai-as-promised": "7.1.2", "@types/chai-as-promised": "7.1.2",
"@types/lodash": "^4.14.149", "@types/lodash": "^4.14.149",
"@types/mocha": "7.0.2", "@types/mocha": "7.0.2",
"@types/node": "^13.9.5",
"@types/sinon-chai": "3.2.3", "@types/sinon-chai": "3.2.3",
"@types/source-map-support": "0.5.1", "@types/source-map-support": "0.5.1",
"@typescript-eslint/eslint-plugin": "2.25.0", "@typescript-eslint/eslint-plugin": "2.25.0",

View File

@ -1,9 +1,7 @@
import JSON_DATA from './resource/json.json';
import YAML_DATA from './resource/yaml.yml';
import { VERSION_INFO } from './version'; import { VERSION_INFO } from './version';
export async function main(argv: Array<string>): Promise<number> { export async function main(argv: Array<string>): Promise<number> {
/* eslint-disable-next-line no-console */ /* eslint-disable-next-line no-console */
console.log('Hello World!', VERSION_INFO, JSON_DATA, YAML_DATA, argv); console.log('Hello World!', VERSION_INFO, argv);
return 1; return 1;
} }

View File

@ -1,3 +0,0 @@
# Entity
Database entities.

View File

@ -0,0 +1,7 @@
import { BaseError } from 'noicejs';
export class ChildProcessError extends BaseError {
constructor(msg = 'child process exited with error status', ...nested: Array<Error>) {
super(msg, ...nested);
}
}

View File

@ -0,0 +1,7 @@
import { BaseError } from 'noicejs';
export class InvalidArgumentError extends BaseError {
constructor(msg = 'invalid argument passed', ...nested: Array<Error>) {
super(msg, ...nested);
}
}

View File

@ -0,0 +1,7 @@
import { BaseError } from 'noicejs';
export class MissingKeyError extends BaseError {
constructor(msg = 'missing key', ...nested: Array<Error>) {
super(msg, ...nested);
}
}

View File

@ -0,0 +1,7 @@
import { BaseError } from 'noicejs';
export class NotFoundError extends BaseError {
constructor(msg = 'value not found', ...nested: Array<Error>) {
super(msg, ...nested);
}
}

View File

@ -0,0 +1,7 @@
import { BaseError } from 'noicejs';
export class NotImplementedError extends BaseError {
constructor(msg = 'method not implemented', ...nested: Array<Error>) {
super(msg, ...nested);
}
}

View File

@ -0,0 +1,7 @@
import { BaseError } from 'noicejs';
export class TimeoutError extends BaseError {
constructor(msg = 'operation timed out', ...nested: Array<Error>) {
super(msg, ...nested);
}
}

View File

@ -1,12 +1,63 @@
import { main } from './app'; export { ChildProcessError } from './error/ChildProcessError';
export { InvalidArgumentError } from './error/InvalidArgumentError';
export { MissingKeyError } from './error/MissingKeyError';
export { NotFoundError } from './error/NotFoundError';
export { NotImplementedError } from './error/NotImplementedError';
export { TimeoutError } from './error/TimeoutError';
const STATUS_ERROR = 1; export {
AsyncTracker,
} from './test/AsyncTracker';
export {
getTestLogger,
spyLogger,
} from './test/Logger';
/** export {
* This is the main entry-point to the program and the only file not included in the main bundle. Nil,
*/ Optional,
main(process.argv).then((status) => process.exit(status)).catch((err: Error) => { countOf,
// eslint-disable-next-line no-console defaultWhen,
console.error('uncaught error during main:', err); doesExist,
process.exit(STATUS_ERROR); filterNil,
}); isNil,
mergeList,
mustCoalesce,
mustExist,
mustFind,
} from './utils';
export {
ArrayMapper,
} from './utils/ArrayMapper';
export {
defer,
timeout,
} from './utils/Async';
export {
concat,
encode,
} from './utils/Buffer';
export { waitForChild } from './utils/Child';
export { ExternalModule, ModuleCtor } from './utils/ExternalModule';
export { isDebug } from './utils/Env';
export {
Dict,
MapLike,
entriesOf,
makeDict,
makeMap,
mergeMap,
mustGet,
pushMergeMap,
setOrPush,
} from './utils/Map';
export {
removePid,
writePid,
} from './utils/PidFile';
export {
SIGNAL_RELOAD,
SIGNAL_RESET,
SIGNAL_STOP,
signal,
} from './utils/Signal';

View File

@ -1,5 +0,0 @@
import { VERSION_INFO } from './version';
export default {
VERSION_INFO,
};

View File

@ -1,3 +0,0 @@
# Migration
Database schema migrations for the entities.

View File

@ -1,3 +0,0 @@
# Module
Dependency injection modules.

View File

@ -1,3 +0,0 @@
{
"foo": {}
}

View File

@ -1 +0,0 @@
foo: {}

79
src/test/AsyncTracker.ts Normal file
View File

@ -0,0 +1,79 @@
import { AsyncHook, createHook } from 'async_hooks';
import { isNil } from '../utils';
import { isDebug } from '../utils/Env';
export interface TrackedResource {
source: string;
triggerAsyncId: number;
type: string;
}
/**
* Async resource tracker using node's internal hooks.
*
* This probably won't work in a browser. It does not hold references to the resource, to avoid leaks.
* Adapted from https://gist.github.com/boneskull/7fe75b63d613fa940db7ec990a5f5843#file-async-dump-js
*/
export class AsyncTracker {
public static getStack(): string {
const err = new Error();
if (isNil(err.stack)) {
return 'no stack trace available';
} else {
return err.stack; // TODO: filterStack(err.stack);
}
}
private readonly hook: AsyncHook;
private readonly resources: Map<number, TrackedResource>;
constructor() {
this.resources = new Map();
this.hook = createHook({
destroy: (id: number) => {
this.resources.delete(id);
},
init: (id: number, type: string, triggerAsyncId: number) => {
const source = AsyncTracker.getStack();
// @TODO: exclude async hooks, including this one
this.resources.set(id, {
source,
triggerAsyncId,
type,
});
},
promiseResolve: (id: number) => {
this.resources.delete(id);
},
});
}
public clear() {
this.resources.clear();
}
public disable() {
this.hook.disable();
}
/* eslint-disable no-console, no-invalid-this */
public dump() {
console.error(`tracking ${this.resources.size} async resources`);
this.resources.forEach((res, id) => {
console.error(`${id}: ${res.type}`);
if (isDebug()) {
console.error(res.source);
console.error('\n');
}
});
}
public enable() {
this.hook.enable();
}
public get size(): number {
return this.resources.size;
}
}

19
src/test/Logger.ts Normal file
View File

@ -0,0 +1,19 @@
import { ConsoleLogger, Logger, NullLogger } from 'noicejs';
const ENV_DEBUG = 'DEBUG';
export function getTestLogger(verbose = false): Logger {
if (verbose || process.env[ENV_DEBUG] === 'TRUE') {
return new ConsoleLogger();
} else {
return new NullLogger();
}
}
export function spyLogger(spies: Partial<Logger>): Logger {
const logger = {
...spies,
child: () => logger,
} as Logger;
return logger;
}

41
src/utils/ArrayMapper.ts Normal file
View File

@ -0,0 +1,41 @@
import { setOrPush } from './Map';
export interface ArrayMapperOptions {
rest: string;
skip: number;
take: Array<string>;
}
export class ArrayMapper {
public readonly rest: string;
public readonly skip: number;
public readonly take: Array<string>;
constructor(options: ArrayMapperOptions) {
this.rest = options.rest;
this.skip = options.skip;
this.take = Array.from(options.take);
}
public map(input: Array<string>): Map<string, Array<string>> {
const result = new Map();
input.forEach((it, idx) => {
if (idx < this.skip) {
return;
}
const skipdx = idx - this.skip;
if (skipdx < this.take.length) {
setOrPush(result, this.take[skipdx], it);
} else {
setOrPush(result, this.rest, it);
}
});
if (!result.has(this.rest)) {
result.set(this.rest, []);
}
return result;
}
}

38
src/utils/Async.ts Normal file
View File

@ -0,0 +1,38 @@
import { TimeoutError } from '../error/TimeoutError';
/**
* Resolve after a set amount of time.
*/
export function defer<T = undefined>(ms: number, val?: T): Promise<T> {
return new Promise((res, rej) => {
setTimeout(() => {
res(val);
}, ms);
});
}
/**
* Reject after a set amount of time if the original promise has not yet resolved.
*/
export function timeout<T>(ms: number, oper: Promise<T>): Promise<T> {
const limit = new Promise<T>((res, rej) => {
setTimeout(() => {
rej(new TimeoutError());
}, ms);
});
return Promise.race([limit, oper]);
}
export async function waitFor(cb: () => boolean, step: number, count: number): Promise<void> {
let accum = 0;
while (accum < count) {
await defer(step);
if (cb()) {
return;
}
accum += 1;
}
throw new TimeoutError();
}

12
src/utils/Buffer.ts Normal file
View File

@ -0,0 +1,12 @@
export function concat(chunks: Array<Buffer>): Buffer {
const sum = chunks.map((it) => it.length).reduce((p, c) => p + c, 0);
return Buffer.concat(chunks, sum);
}
export function encode(chunks: Array<Buffer>, encoding: string): string {
if (chunks.length === 0) {
return '';
}
return concat(chunks).toString(encoding);
}

84
src/utils/Child.ts Normal file
View File

@ -0,0 +1,84 @@
import { ChildProcessWithoutNullStreams, spawn } from 'child_process';
import { BaseError } from 'noicejs';
import { Writable } from 'stream';
import { doesExist, Optional } from '.';
import { ChildProcessError } from '../error/ChildProcessError';
import { encode } from './Buffer';
import { NameValuePair } from './Map';
export interface ChildOptions {
args: Array<string>;
command: string;
cwd: string;
env: Array<NameValuePair<string>>;
timeout: number;
}
export interface ChildResult {
status: number;
stderr: string;
stdout: string;
}
export type ChildSpawner = typeof spawn;
const CHILD_ENCODING = 'utf-8';
const CHILD_EVENT = 'child process emitted error event';
const CHILD_STATUS = 'child process exited with error status';
const CHILD_OUTPUT = 'child process emitted error output';
export function waitForChild(child: ChildProcessWithoutNullStreams): Promise<ChildResult> {
return new Promise((res, rej) => {
const stderr: Array<Buffer> = [];
const stdout: Array<Buffer> = [];
child.stderr.on('data', (chunk) => {
stderr.push(chunk);
});
child.stdout.on('data', (chunk) => {
stdout.push(chunk);
});
child.on('error', (err: Error | number) => {
if (err instanceof Error) {
rej(new ChildProcessError(CHILD_EVENT, err));
}
});
child.on('close', (status: number) => {
const errors = encode(stderr, CHILD_ENCODING);
if (status > 0) {
const msg = `${CHILD_STATUS}: ${status}`;
rej(new ChildProcessError(msg, new BaseError(errors)));
return;
}
if (errors.length > 0) {
rej(new ChildProcessError(CHILD_OUTPUT, new BaseError(errors)));
return;
}
res({
status,
stderr: errors,
stdout: encode(stdout, CHILD_ENCODING),
});
});
});
}
export function writeValue(stream: Writable, value: string): Promise<boolean> {
return new Promise<boolean>((res, rej) => {
stream.write(value, (err: Optional<Error>) => {
if (doesExist(err)) {
rej(err);
} else {
stream.end(() => {
res(true);
});
}
});
});
}

3
src/utils/Env.ts Normal file
View File

@ -0,0 +1,3 @@
export function isDebug() {
return Reflect.has(process.env, 'DEBUG');
}

View File

@ -0,0 +1,14 @@
import { Module } from 'noicejs';
export interface ExternalModule {
data?: unknown;
export: string;
require: string;
}
export type ModuleCtor = new (data: unknown) => Module;
export function isModule(it: object): it is ModuleCtor {
const p = Reflect.getPrototypeOf(it);
return p === Module || p instanceof Module;
}

185
src/utils/Map.ts Normal file
View File

@ -0,0 +1,185 @@
import { isMap, isObject, isString } from 'lodash';
import { doesExist, isNil, mergeList, mustExist, Optional } from '.';
import { NotFoundError } from '../error/NotFoundError';
export interface Dict<TVal> {
[key: string]: TVal;
}
/**
* A `Map` or dictionary object with string keys and `TVal` values.
*/
export type MapLike<TVal> = Map<string, TVal> | Dict<TVal>;
/**
* Get an element from a Map and guard against nil values.
*/
export function mustGet<TKey, TVal>(map: Map<TKey, TVal>, key: TKey): TVal {
const val = map.get(key);
return mustExist(val);
}
export function getOrDefault<TKey, TVal>(map: Map<TKey, TVal>, key: TKey, defaultValue: TVal): TVal {
if (map.has(key)) {
const data = map.get(key);
if (doesExist(data)) {
return data;
}
}
return defaultValue;
}
export function getHead<TKey, TVal>(map: Map<TKey, Array<TVal>>, key: TKey): TVal {
const value = map.get(key);
if (isNil(value) || value.length === 0) {
throw new NotFoundError();
}
return value[0];
}
export function getHeadOrDefault<TKey, TVal>(map: Map<TKey, Array<Optional<TVal>>>, key: TKey, defaultValue: TVal): TVal {
if (!map.has(key)) {
return defaultValue;
}
const data = map.get(key);
if (isNil(data)) {
return defaultValue;
}
const [head] = data;
if (isNil(head)) {
return defaultValue;
}
return head;
}
/**
* Set a map key to a new array or push to the existing value.
* @param map The destination map and source of existing values.
* @param key The key to get and set.
* @param val The value to add.
*/
export function setOrPush<TKey, TVal>(map: Map<TKey, Array<TVal>>, key: TKey, val: TVal | Array<TVal>) {
const prev = map.get(key);
if (doesExist(prev)) {
map.set(key, mergeList(prev, val));
} else {
if (Array.isArray(val)) {
map.set(key, val);
} else {
map.set(key, [val]);
}
}
}
export function mergeMap<TKey, TVal>(target: Map<TKey, TVal>, source: Map<TKey, TVal> | Array<[TKey, TVal]>) {
for (const [k, v] of source) {
target.set(k, v);
}
return target;
}
export function pushMergeMap<TKey, TVal>(...args: Array<Map<TKey, TVal | Array<TVal>>>): Map<TKey, Array<TVal>> {
const out = new Map();
for (const arg of args) {
for (const [key, val] of arg) {
setOrPush(out, key, val);
}
}
return out;
}
/**
* Clone a map or map-like object into a new map.
*/
export function makeMap<TVal>(val: Optional<MapLike<TVal>>): Map<string, TVal> {
// nil: empty map
if (isNil(val)) {
return new Map();
}
// already a map: make a copy
if (isMap(val)) {
return new Map(val.entries());
}
// otherwise: dict
return new Map(Object.entries(val));
}
/**
* Turns a map or dict into a dict
*/
export function makeDict<TVal>(map: Optional<MapLike<TVal>>): Dict<TVal> {
if (isNil(map)) {
return {};
}
if (isMap(map)) {
const result: Dict<TVal> = {};
for (const [key, val] of map) {
result[key] = val;
}
return result;
}
return map;
}
export interface NameValuePair<TVal> {
name: string;
value: TVal;
}
export function pairsToMap<TVal>(pairs: Array<NameValuePair<TVal>>): Map<string, TVal> {
const map = new Map();
for (const p of pairs) {
map.set(p.name, p.value);
}
return map;
}
export function dictValuesToArrays<TVal>(map: MapLike<TVal>): Dict<Array<TVal>> {
const data: Dict<Array<TVal>> = {};
for (const [key, value] of makeMap(map)) {
if (Array.isArray(value)) {
data[key] = value;
} else {
data[key] = [value];
}
}
return data;
}
export function normalizeMap(map: MapLike<unknown>): Dict<Array<string>> {
const data: Dict<Array<string>> = {};
for (const [key, value] of makeMap(map)) {
if (Array.isArray(value)) {
data[key] = value;
} else if (isString(value)) {
data[key] = [value];
} else if (isObject(value)) {
data[key] = [value.toString()];
}
}
return data;
}
export function entriesOf<TVal>(map: Optional<MapLike<TVal>>): Array<[string, TVal]> {
if (map instanceof Map) {
return Array.from(map.entries());
}
if (map instanceof Object) {
return Object.entries(map);
}
return [];
}

36
src/utils/PidFile.ts Normal file
View File

@ -0,0 +1,36 @@
import { open, unlink, write } from 'fs';
import { pid } from 'process';
import { doesExist, Optional } from '.';
type OptionalErrno = Optional<NodeJS.ErrnoException>;
export async function writePid(path: string): Promise<void> {
return new Promise((res, rej) => {
open(path, 'wx', (openErr: OptionalErrno, fd: number) => {
if (doesExist(openErr)) {
rej(openErr);
} else {
write(fd, pid.toString(), 0, 'utf8', (writeErr: OptionalErrno) => {
if (doesExist(writeErr)) {
rej(writeErr);
} else {
res();
}
});
}
});
});
}
export async function removePid(path: string): Promise<void> {
return new Promise((res, rej) => {
unlink(path, (err: OptionalErrno) => {
if (doesExist(err)) {
rej(err);
} else {
res();
}
});
});
}

36
src/utils/Reflect.ts Normal file
View File

@ -0,0 +1,36 @@
import { isFunction } from 'lodash';
import { doesExist, isNil } from '.';
export function getConstructor(val: object) {
return val.constructor;
}
export function getMethods<TValue extends object>(value: TValue): Set<Function> {
const methods = new Set<Function>();
for (const name of Object.getOwnPropertyNames(value)) {
const desc = Object.getOwnPropertyDescriptor(value, name);
if (isNil(desc)) {
continue;
}
const method = desc.value;
if (isFunction(method)) {
methods.add(method);
}
}
const proto = Reflect.getPrototypeOf(value);
if (proto !== value && doesExist(proto)) {
for (const m of getMethods(proto)) {
methods.add(m);
}
}
return methods;
}
export function constructorName(val: object) {
return getConstructor(Reflect.getPrototypeOf(val)).name;
}

18
src/utils/Signal.ts Normal file
View File

@ -0,0 +1,18 @@
export const SIGNAL_RELOAD: NodeJS.Signals = 'SIGHUP';
export const SIGNAL_RESET: NodeJS.Signals = 'SIGINT';
export const SIGNAL_STOP: NodeJS.Signals = 'SIGTERM';
export function signal(...signals: Array<NodeJS.Signals>): Promise<NodeJS.Signals> {
return new Promise((res, _) => {
function handler(fired: NodeJS.Signals) {
for (const s of signals) {
process.removeListener(s, handler);
}
res(fired);
}
for (const sig of signals) {
process.on(sig, handler);
}
});
}

23
src/utils/String.ts Normal file
View File

@ -0,0 +1,23 @@
export function leftPad(val: string, min = 8, fill = '0'): string {
if (val.length < min) {
const len = min - val.length;
const pre = Array(len).fill(fill).join('').slice(0, len);
return `${pre}${val}`;
} else {
return val;
}
}
export function trim(val: string, max: number, tail = '...'): string {
if (val.length <= max) {
return val;
}
if (max < tail.length) {
return val.substr(0, max);
}
const start = val.substr(0, max - tail.length);
return `${start}${tail}`;
}

119
src/utils/index.ts Normal file
View File

@ -0,0 +1,119 @@
import { NotFoundError } from '../error/NotFoundError';
/**
* Unset value.
*/
/* eslint-disable-next-line @typescript-eslint/ban-types */
export type Nil = null | undefined;
/**
* Value that may be nil.
*/
export type Optional<T> = T | Nil;
/**
* Comparison (filter) predicate for a single value.
*/
export type PredicateC1<TVal> = (val: TVal, idx: number, list: Array<TVal>) => boolean;
/**
* Comparison (sort) predicate for two values.
*/
export type PredicateC2<TVal> = (pval: TVal, nval: TVal, idx: number, list: Array<TVal>) => number;
/**
* Reduction predicate for two values.
*/
export type PredicateR2<TVal> = (pval: TVal, nval: TVal, idx: number, list: Array<TVal>) => TVal;
/* eslint-disable-next-line @typescript-eslint/ban-types */
export function isNil<T>(val: Optional<T>): val is Nil {
/* eslint-disable-next-line no-null/no-null */
return val === null || val === undefined;
}
/**
* Calculate the "length" of an array or value.
*
* Arrays return their length, single values return 1, and nil values return 0.
* This counts the number of elements that setOrPush would add.
*/
export function countOf(val: unknown): number {
if (Array.isArray(val)) {
return val.length;
}
if (doesExist(val)) {
return 1;
}
return 0;
}
export function defaultWhen<TVal>(condition: boolean, ...items: Array<TVal>): TVal {
if (condition) {
return items[0];
} else {
return items[1];
}
}
/**
* Remove any null or undefined items from the list.
*/
export function filterNil<TItem>(list: ArrayLike<Optional<TItem>>): Array<TItem> {
return Array.from(list).filter(doesExist);
}
/**
* Merge arguments, which may or may not be arrays, into one return that is definitely an array.
*/
export function mergeList<TItem>(...parts: Array<TItem | Array<TItem>>): Array<TItem> {
const out = [];
for (const part of parts) {
if (Array.isArray(part)) {
out.push(...part);
} else {
out.push(part);
}
}
return out;
}
/**
* Find a value matching the given predicate or throw.
*/
export function mustFind<TVal>(list: Array<Optional<TVal>>, predicate: PredicateC1<TVal>): TVal {
const val = filterNil(list).find(predicate);
return mustExist(val);
}
/**
* Check if a variable is not nil.
*/
export function doesExist<T>(val: Optional<T>): val is T {
return !isNil(val);
}
/**
* Assert that a variable is not nil and return the value.
*
* @throws NotFoundError
* @returns val
*/
export function mustExist<T>(val: Optional<T>): T {
if (isNil(val)) {
throw new NotFoundError();
}
return val;
}
/**
* Return the first value that is not nil.
*/
export function mustCoalesce<T>(...values: Array<Optional<T>>): T {
return mustFind(values, doesExist);
}

Some files were not shown because too many files have changed in this diff Show More