@arcsine/nodesh
Advanced tools
Comparing version 1.2.0 to 1.2.1
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const helper_1=require("../helper");class TransformOperators{$notEmpty(){return this.$filter(a=>a!==void 0&&null!==a&&("string"!=typeof a||""!==a.trim()))}async*$tap(a){for await(const b of this)a&&(await a(b)),yield b}async*$unique(a=(a,b)=>a===b){let b;for await(const c of this)(await a(c,b))||(b=c,yield c)}async*$sort(a){for await(const b of this.$collect())yield*b.sort(a)}async*$batch(a){let b=[];for await(const c of this)b.push(c),b.length===a&&(yield b,b=[]);b.length&&(yield b)}async*$pair(a,b){["function","object"].includes(typeof a)&&"apply"in a&&(a=a()),b=null!==b&&void 0!==b?b:"string"==typeof a?"repeat":"empty";let c=a.$iterable;"repeat"===b&&(c=c.$repeat());let d=c[Symbol.asyncIterator]();for await(const c of this){const a=await d.next();if(a.done)if("exact"===b)break;else"empty"===b&&(d=[void 0].$repeat()[Symbol.asyncIterator](),a.value=void 0);const e=a.value;yield[c,e]}}async*$join(a){const b=this[Symbol.asyncIterator]();let c;const d=helper_1.GlobalHelpers.$of(a).$repeat()[Symbol.asyncIterator]();let e=!0;do c=await b.next(),e||c.done||(yield(await d.next()).value),yield c.value,e=!1;while(!c.done)}}exports.TransformOperators=TransformOperators; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const helper_1=require("../helper");class TransformOperators{$notEmpty(){return this.$filter(a=>a!==void 0&&null!==a&&("string"!=typeof a||""!==a.trim()))}async*$tap(a){for await(const b of this)a&&(await a(b)),yield b}async*$unique(a=(a,b)=>a===b){let b;for await(const c of this)(await a(c,b))||(b=c,yield c)}async*$sort(a){for await(const b of this.$collect())yield*b.sort(a)}async*$batch(a){let b=[];for await(const c of this)b.push(c),b.length===a&&(yield b,b=[]);b.length&&(yield b)}async*$pair(a,b){["function","object"].includes(typeof a)&&"apply"in a&&(a=a()),b=null!==b&&void 0!==b?b:"string"==typeof a?"repeat":"empty";let c=a.$iterable;"repeat"===b&&(c=c.$repeat());let d=c[Symbol.asyncIterator]();for await(const c of this){const a=await d.next();if(a.done)if("exact"===b)break;else"empty"===b&&(d=[void 0].$repeat()[Symbol.asyncIterator](),a.value=void 0);const e=a.value;yield[c,e]}}async*$join(a){const b=this[Symbol.asyncIterator]();let c;const d=helper_1.GlobalHelpers.$of(a).$repeat()[Symbol.asyncIterator]();for(let e=!0;c=await b.next(),!c.done;)e?e=!1:yield(await d.next()).value,yield c.value}}exports.TransformOperators=TransformOperators; |
@@ -1,1 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const async_1=require("./async");class RegisterUtil{static registerAsyncable(a){RegisterUtil.properties({$iterable:function(){var a,b;const c=this;return(null===(a=this)||void 0===a?void 0:a[Symbol.asyncIterator])?this:(null===(b=this)||void 0===b?void 0:b[Symbol.iterator])?async function*(){yield*c}():async function*(){yield c}()}},a.prototype)}static registerThenable(a){RegisterUtil.properties({then:{get(){return a=>(Promise.resolve().then(()=>{const b=this.$values;async_1.AsyncUtil.trackWithTimer(b),a(b)}),this)},configurable:!0}},a.prototype)}static properties(a,b){for(const c of Object.keys(a)){let d=a[c];"apply"in d&&(d={get:d}),d.configurable=!0,Object.defineProperty(b,c,d)}}static createOperator(a){return function(...b){const c=a.call(this.$iterable,...b);return c instanceof Promise&&async_1.AsyncUtil.trackWithTimer(c),c}}static registerOperators(a,b=Object){Array.isArray(a)||(a=[a]);for(const{name:c,prototype:d}of a)if(c)for(const a of Object.getOwnPropertyNames(d)){if("constructor"===a)continue;let c=Object.getOwnPropertyDescriptor(d,a);c.get||(c={get(){return RegisterUtil.createOperator(d[a])}}),c.configurable=!0,Object.defineProperty(b.prototype,a,c)}}}exports.RegisterUtil=RegisterUtil; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const async_1=require("./async");class RegisterUtil{static registerAsyncable(a){RegisterUtil.properties({$iterable:function(){var a,b;const c=this;return(null===(a=this)||void 0===a?void 0:a[Symbol.asyncIterator])?this:(null===(b=this)||void 0===b?void 0:b[Symbol.iterator])?async function*(){yield*c}():async function*(){yield c}()}},a.prototype)}static registerThenable(a){RegisterUtil.properties({then:{get(){return a=>(Promise.resolve().then(()=>{const b=this.$values;async_1.AsyncUtil.trackWithTimer(b),a(b)}),this)},configurable:!0}},a.prototype)}static properties(a,b){for(const c of Object.keys(a)){let d=a[c];"apply"in d&&(d={get:d}),d.configurable=!0,Object.defineProperty(b,c,d)}}static createOperator(a){return function(...b){const c=a.call(this.$iterable,...b);return c instanceof Promise&&async_1.AsyncUtil.trackWithTimer(c),c}}static registerOperators(a,b=Object){Array.isArray(a)||(a=[a]);for(const{name:c,prototype:d}of a)if(c)for(const a of Object.getOwnPropertyNames(d)){if("constructor"===a)continue;let c=Object.getOwnPropertyDescriptor(d,a);c.get||(c={get(){return RegisterUtil.createOperator(d[a])}}),Object.defineProperty(b.prototype,a,{...c,configurable:!0})}}}exports.RegisterUtil=RegisterUtil; |
{ | ||
"name": "@arcsine/nodesh", | ||
"version": "1.2.0", | ||
"version": "1.2.1", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "scripts": { |
659
README.md
@@ -276,2 +276,9 @@ # Node Shell | ||
* [Core](#core) | ||
* [File](#file) | ||
* [Transform](#transform) | ||
* [Text](#text) | ||
* [Limit](#limit) | ||
* [Exec](#exec) | ||
* [Export](#export) | ||
* [Advanced](#advanced) | ||
@@ -435,1 +442,653 @@ | ||
``` | ||
### File | ||
Some of the most common shell operations are iterating through files, | ||
and operating upon those files. To support this, the framework supports | ||
producing files as a sequence of file objects or filenames, given a file | ||
extension or a regex pattern. With `String`s and `RegExp`s supporting the | ||
`Symbol.asyncIterator` property, these are the most common way of finding files. | ||
#### $read | ||
This operator will treat the inbound string sequence as file names, and will convert the filename (based on IOType) | ||
* `text` (default) - The sequence will produce as series of lines of text | ||
* `binary` - The sequence will produce a series of `Buffer` objects | ||
If singleValue is set to true, this produce a single value for the whole stream instead of chunk by chunk. This | ||
mode can be easier to work with for certain operations, but is much more memory intensive. | ||
```typescript | ||
$read(this: AsyncIterable<string>, config?: Omit<ReadStreamConfig, 'mode'>): $AsyncIterable<string>; | ||
$read(this: AsyncIterable<string>, config: ReadStreamConfig<'text'>): $AsyncIterable<string>; | ||
$read(this: AsyncIterable<string>, config: ReadStreamConfig<'binary'>): $AsyncIterable<Buffer>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read('binary') // Read as a series of buffers | ||
.$reduce((acc, buffer) => { | ||
return acc + buffer.length; | ||
}, 0); // Count number of bytes in file | ||
``` | ||
```javascript | ||
'<file>' | ||
.$read('binary', true) // Read as a single buffer | ||
.$map(buffer => buffer.length) // Count number of bytes in file | ||
``` | ||
#### $dir | ||
`dir` provides the ability to recursively search for files within a file system. It expects as the | ||
input sequence type: | ||
* A `string` which represents a suffix search on file names (e.g. `.csv`) | ||
* A `RegExp` which represents a file pattern to search on (e.g. `/path\/sub\/.*[.]js/`) | ||
In addition to the input sequence type, there is an optional config to affect the output. | ||
By default the output of this sequence will be a series of file names, relative to the `process.cwd()` | ||
that will be eligible for reading or any other file operation. | ||
```typescript | ||
$dir(this: AsyncIterable<string | RegExp>, config: ReadDirConfig & {full: true;}): $AsyncIterable<ScanEntry>; | ||
$dir(this: AsyncIterable<string | RegExp>, config?: Omit<ReadDirConfig, 'full'>): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'.csv' | ||
.$dir({ full: true }) // List all '.csv' files, recursively | ||
.$forEach(f => { | ||
// Display the filename, and it's modification time | ||
console.log(f.file, f.stats.mtime); | ||
}); | ||
``` | ||
### Transform | ||
Standard operators regarding common patterns for transformations | ||
#### $notEmpty | ||
This is a special type of filter that excludes `null`, `undefined` and `''`. | ||
Useful for removing empty values. | ||
```typescript | ||
$notEmpty<T>(this: AsyncIterable<T>): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$notEmpty() // Return all non-empty lines of the file | ||
``` | ||
#### $tap | ||
`$tap` provides the ability to inspect the sequence without affecting it's production. The function passed in | ||
can produce a promise that will be waited on, if needed. | ||
```typescript | ||
$tap<T>(this: AsyncIterable<T>, visit?: PromFunc<T, any>): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'.csv' | ||
.$dir() | ||
.$tap(({stats}) => collectMetrics(stats)) | ||
// Stream unchanged, but was able to track file stat information | ||
``` | ||
#### $unique | ||
`$unique` will ensure the output sequence does not have any consecutive duplicates, similar to the unix `uniq` command. | ||
The uniqueness is only guaranteed linearly, to allow for streaming. Otherwise this would need to wait | ||
for all data before proceeding. You can also specify a custom equality function as needed. | ||
```typescript | ||
$unique<T>(this: AsyncIterable<T>, compare?: PromFunc2<T, T, boolean>): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
[1, 2, 2, 3, 4, 5, 5, 1, 7] | ||
.$unique() // Will produce [1, 2, 3, 4, 5, 1, 7] | ||
// The final 1 repeats as it's not duplicated in sequence | ||
``` | ||
#### $sort | ||
`$sort` is a blocking operation as it requires all the data to be able to sort properly. This means it will wait | ||
on the entire sequence before producing new data. The function operates identically to how `Array.prototype.sort` behaves. | ||
```typescript | ||
$sort<T>(this: AsyncIterable<T>, compare?: (a: T, b: T) => number): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() // Now a sequence of lines | ||
.$sort() // Sort lines alphabetically | ||
// Now a sequence of sorted lines | ||
``` | ||
#### $batch | ||
Allows for iterative grouping of streamed data, and produces a sequence of arrays. Each array will be `$batch` sized, | ||
except for the final array which will be at most `batch` size. | ||
```typescript | ||
$batch<T>(this: AsyncIterable<T>, size: number): $AsyncIterable<T[]>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() // Generator of file lines | ||
.$batch(20) // Generator of array of lines, at most 20 items in length | ||
.$map(lines => lines.sort()) // Sort each batch | ||
// Generator of sorted list strings | ||
``` | ||
#### $pair | ||
`$pair` allows for combining two sets of data into a single sequence of pairs. | ||
The second value can either be a single value, which will be added to every item, | ||
or it could be an iterable element that will match with each item as possible. If the second | ||
iterator runs out, the remaining values can be affected by the mode parameter: | ||
* `'empty'` - Fill in with `undefined` once the second iterator is exhausted. This is default for iterable values. | ||
* `'repeat'` - Loop iteration on the secondary iterator. This is default for string values. | ||
* `'exact'` - Stop the emitting values once the secondary iterator is exhausted. | ||
```typescript | ||
$pair<T, U>(this: AsyncIterable<T>, value: OrCallable<U | Iterable<U> | AsyncIterable<U>>, mode?: PairMode): $AsyncIterable<[T, U]>; | ||
``` | ||
Example | ||
```javascript | ||
'.ts' | ||
.$dir() // List all '.ts' files | ||
.$flatMap(file => file | ||
.$read() // Read each file as a sequence of lines | ||
.$pair(file) // Combine each line with the file name | ||
.$map(([a,b]) => [b, a]) // Reverse the order of the columns | ||
) | ||
// Generator of file lines with, file name attached | ||
``` | ||
#### $join | ||
This operator allows for combining a sequence of elements with a join element | ||
```typescript | ||
$join<T>(this: AsyncIterable<T>, joiner: T | $AsyncIterable<T>): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() // Read as a series of lines | ||
.$join('\n') | ||
// Produces a sequence of lines inter-spliced with new lines | ||
``` | ||
### Text | ||
Support for common textual operations. | ||
As text operators, these only apply to sequences that | ||
produce string values. | ||
#### $columns | ||
`$columns` is similar to the unix `awk` in that it allows for production of | ||
columns from a single line of text. This is useful for dealing with column | ||
oriented output. The separator defaults to all whitespace but can tailored | ||
as needed by regex or string. | ||
```typescript | ||
$columns(this: AsyncIterable<string>, sep?: string | RegExp): $AsyncIterable<string[]>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>.tsv' // Tab-separated file | ||
.$read() // Read as lines | ||
.$columns('\t') // Separate on tabs | ||
// Now an array of tuples (as defined by tabs in the tsv) | ||
``` | ||
#### $columns | ||
Supports passing in column names to produce objects instead of tuples. These values will be | ||
matched with the columns produced by the separator. Any row that is shorter than the names | ||
array will have undefined for the associated keys. | ||
```typescript | ||
$columns<V extends readonly string[]>(this: AsyncIterable<string>, config: V | ColumnsConfig<V>): $AsyncIterable<Record<V[number], string>>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>.tsv' // Tab-separated file | ||
.$read() // Read as lines | ||
.$columns({names: ['Name', 'Age', 'Major'], sep: '\t'}) // Separate on tabs | ||
// Now an array of objects { Name: string, Age: string, Major: string } (as defined by tabs in the tsv) | ||
``` | ||
#### $tokens | ||
This operator allows for producing a single sequence of tokens out of lines of text. The default separator is whitespace. | ||
```typescript | ||
$tokens(this: AsyncIterable<string>, sep?: Pattern): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() // Read file as lines | ||
.$tokens() // Convert to words | ||
.$filter(x => x.length > 5) // Retain only words 6-chars or longer | ||
``` | ||
#### $match | ||
`$match` is similar to tokens, but will emit based on a pattern instead of | ||
just word boundaries. | ||
Additionally, mode will determine what is emitted when a match is found (within a single line): | ||
* `undefined` - (default) Return entire line | ||
* `'extract'` - Return only matched element | ||
* `'negate'` - Return only lines that do not match | ||
```typescript | ||
$match(this: AsyncIterable<string>, regex: Pattern, mode?: 'extract' | 'negate'): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$match(/(FIXME|TODO)/, 'negate') | ||
// Exclude all lines that include FIXME or TODO | ||
``` | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$match(/\d{3}(-)?\d{3}(-)?\d{4}/, 'extract) | ||
// Return all phone numbers in the sequence | ||
``` | ||
#### $replace | ||
`$replace` behaves identically to `String.prototype.replace`, but will only operate | ||
on a single sequence value at a time. | ||
```typescript | ||
$replace(this: AsyncIterable<string>, pattern: Pattern, sub: string | Replacer): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$replace(/TODO/, 'FIXME') | ||
// All occurrences replaced | ||
``` | ||
#### $replace | ||
`$replace` also supports a mode where you can pass in a series of tokens, and replacements, and will apply all | ||
consistently. The largest token will win if there is any overlap. | ||
```typescript | ||
$replace(this: AsyncIterable<string>, pattern: Record<string, string>): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>.html' | ||
.$read() | ||
.$replace({ | ||
'<': '<', | ||
'>': '>', | ||
'"': '"' | ||
}) | ||
// Html special chars escaped | ||
``` | ||
#### $trim | ||
`$trim` behaves identically to `String.prototype.trim`, but will only operate on a single sequence value at a time | ||
```typescript | ||
$trim(this: AsyncIterable<string>): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$trim() | ||
// Cleans leading/trailing whitespace per line | ||
``` | ||
#### $toString | ||
`$toString` is a convenience method for converting an entire block of | ||
text into a single string. This is useful when looking for patterns that | ||
may span multiple lines. | ||
```typescript | ||
$toString(this: AsyncIterable<string>): $AsyncIterable<string>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>.html' | ||
.$read() | ||
.$toString() // Convert to a single string | ||
.$replace(/<[^>]+?>/) // Remove all HTML tags | ||
``` | ||
### Limit | ||
Support for limiting sequence values based on ordering | ||
#### $first | ||
This will return the first `n` elements with a default of a single element. | ||
```typescript | ||
$first<T>(this: AsyncIterable<T>, n?: number): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$first(10) // Read first 10 lines | ||
``` | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$first() // Read first line | ||
``` | ||
#### $skip | ||
This will return all but the first `n` elements. | ||
```typescript | ||
$skip<T>(this: AsyncIterable<T>, n: number): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>.csv' | ||
.$read() | ||
.$skip(1) // Skip header | ||
``` | ||
#### $last | ||
This will return the last `n` elements with a default of a single element. | ||
Since this method requires knowledge of the length of the sequence to | ||
work properly, this now becomes a blocking operator. | ||
```typescript | ||
$last<T>(this: AsyncIterable<T>, n?: number): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$last(7) // Read last 7 lines of file | ||
``` | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$last() // Read last line of file | ||
``` | ||
#### $repeat | ||
This will repeat the first `n` elements with a default of all elements. | ||
```typescript | ||
$repeat<T>(this: AsyncIterable<T>, n?: number): $AsyncIterable<T>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$first(10) // Read first 10 lines | ||
``` | ||
### Exec | ||
Support for dealing with execution of external programs | ||
#### $exec | ||
Pipe the entire sequence as input into the command to be executed. Allow for args and flags to be | ||
appended to the command as needed. If the output is specified as 'binary', the generator | ||
will return a sequence of `Buffer`s, otherwise will return `string`s | ||
```typescript | ||
$exec(cmd: string, config?: string[] | Omit<ExecConfig, 'mode'>): $AsyncIterable<string>; | ||
$exec(cmd: string, config: ExecConfig<'text'>): $AsyncIterable<string>; | ||
$exec(cmd: string, config: ExecConfig<'binary'>): $AsyncIterable<Buffer>; | ||
$exec(cmd: string, config: ExecConfig<'raw'>): $AsyncIterable<Readable>; | ||
``` | ||
Example | ||
```javascript | ||
'.ts' | ||
.$dir() // Get all files | ||
.$read() // Read all files | ||
.$exec('wc', ['-l']) // Execute word count for all files | ||
// Run in a single operation | ||
``` | ||
```javascript | ||
'.ts' | ||
.$dir() // Get all files | ||
.$read() // Read all files | ||
.$exec('npx', { | ||
args: ['tslint'], | ||
spawn : { | ||
env : { NO_COLOR: '1' } | ||
} | ||
}) // Tslint every file | ||
// Run in a single operation | ||
``` | ||
### Export | ||
Support for exporting data from a sequence | ||
#### $stream | ||
Converts a sequence into a node stream. This readable stream should be | ||
considered standard, and usable in any place a stream is expected. The mode | ||
determines if the stream is string or `Buffer` oriented. | ||
```typescript | ||
$stream<T>(this: AsyncIterable<T>, mode?: IOType): Readable; | ||
``` | ||
Example | ||
```javascript | ||
const stream = '<file>.png' | ||
.$read('binary') // Read file as binary | ||
.$exec('convert', ['-size=100x20']) // Pipe to convert function | ||
.$stream('binary') // Read converted output into NodeJS stream | ||
stream.pipe(fs.createWriteStream('out.png')); // Write out | ||
``` | ||
#### $write | ||
Emits the sequence contents to a write stream. If the write stream is a string, it | ||
is considered to be a file name. Buffer contents are written as is. String contents | ||
are written as lines. | ||
```typescript | ||
$write<T extends string | Buffer | any>(this: AsyncIterable<T>, writable: Writable | string): Promise<void>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>.png' | ||
.$read('binary') // Read file as binary | ||
.$exec('convert', ['-size=100x20']) // Pipe to convert function | ||
.$write('out.png') // Write file out | ||
``` | ||
#### $writeFinal | ||
Writes the entire stream to a file, as a final step. The write stream will not be created until all the values | ||
have been emitted. This is useful for reading and writing the same file. | ||
```typescript | ||
$writeFinal(this: AsyncIterable<Buffer | string>, file: string): Promise<void>; | ||
export declare class ExportPropOperators<T> { | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() | ||
.$replace(/TEMP/, 'final') | ||
.$writeFinal('<file>'); | ||
``` | ||
#### $values | ||
Extract all sequence contents into a single array and return | ||
as a promise | ||
```typescript | ||
get $values(this: AsyncIterable<T>): Promise<T[]>; | ||
``` | ||
Example | ||
```javascript | ||
const values = await '<file>.csv' | ||
.$read() | ||
.$csv('Width', 'Depth', 'Height'])// Convert to objects | ||
.$map(({Width, Height, Depth}) => | ||
int(Width) * int(Height) * int(Depth) // Compute volume | ||
) | ||
.$values // Get all values; | ||
``` | ||
#### $value | ||
Extract first sequence element and return as a promise | ||
```typescript | ||
get $value(this: AsyncIterable<T>): Promise<T>; | ||
``` | ||
Example | ||
```javascript | ||
const name = await 'What is your name?' | ||
.$prompt() // Prompt for name | ||
.$value // Get single value | ||
``` | ||
#### $stdout | ||
Simple method that allows any sequence to be automatically written to stdout | ||
```typescript | ||
get $stdout(this: AsyncIterable<T>): Writable; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() // Read file | ||
.$map(line => line.length) // Convert each line to it's length | ||
.$stdout // Pipe to stdout | ||
``` | ||
#### $console | ||
Simple property that allows any sequence to be automatically called with `console.log` | ||
```typescript | ||
get $console(this: AsyncIterable<T>): Promise<void>; | ||
``` | ||
Example | ||
```javascript | ||
'<file>' | ||
.$read() // Read file | ||
.$json() | ||
.$console // Log out objects | ||
``` | ||
### Advanced | ||
Advanced operators represent more complex use cases. | ||
#### $parallel | ||
Run iterator in parallel, returning values in order of first completion. If the passed in function produces | ||
an async generator, only the first value will be used. This is because the method needs an array of promises | ||
and an AsyncIterable cannot produce an array of promises as it's length is unknown until all promises are | ||
resolved. | ||
The default concurrency limit is number of processors minus one. This means the operator will process the sequence in order | ||
until there are `concurrent` pending tasks, and will only fetch the next item once there is capacity. | ||
```typescript | ||
$parallel<T, U = T>(this: AsyncIterable<T>, op: (item: T) => AsyncIterable<U> | Promise<U>, concurrent?: number): $AsyncIterable<U>; | ||
``` | ||
Example | ||
```javascript | ||
[10, 9, 8, 7, 6, 5, 4, 2, 1] | ||
.$parallel(x => (x).$wait(x * 1000)) | ||
.$console | ||
``` |
97100
1093