ig-types 6.13.6 → 6.14.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/Promise.js +193 -140
  2. package/README.md +62 -0
  3. package/package.json +1 -1
package/Promise.js CHANGED
@@ -1,11 +1,9 @@
1
1
  /**********************************************************************
2
- *
3
- *
4
- *
5
2
  *
6
3
  * This defines the following extensions to Promise:
7
4
  *
8
5
  * Promise.iter(seq)
6
+ * <promise>.iter()
9
7
  * Iterable promise object.
10
8
  * Similar to Promise.all(..) but adds basic iterator/generator
11
9
  * API and will resolve the items as they are ready (resolved).
@@ -19,6 +17,11 @@
19
17
  * Exposes the API to resolve/reject the promise object
20
18
  * externally.
21
19
  *
20
+ * <promise>.as(obj)
21
+ * Promise proxy.
22
+ * Proxies the methods available from obj to promise value.
23
+ *
24
+ *
22
25
  *
23
26
  *
24
27
  **********************************************/ /* c8 ignore next 2 */
@@ -28,18 +31,6 @@
28
31
 
29
32
  var object = require('ig-object')
30
33
 
31
- // XXX required for STOP...
32
- //var generator = require('./generator')
33
-
34
-
35
- /*********************************************************************/
36
-
37
- /* XXX not used yet...
38
- // NOTE: this is used in a similar fashion to Python's StopIteration...
39
- var STOP =
40
- module.STOP =
41
- object.STOP
42
- //*/
43
34
 
44
35
 
45
36
  //---------------------------------------------------------------------
@@ -48,13 +39,57 @@ module.STOP =
48
39
  // Like Promise.all(..) but adds ability to iterate through results
49
40
  // via generators .map(..)/.reduce(..) and friends...
50
41
  //
42
+ // NOTE: it would be nice to support throwing STOP (XXX) from the iterable
43
+ // promise but...
44
+ // - this is more complicated than simply using .smap(..) instead
45
+ // of .map(..) because the list can contain async promises...
46
+ // ...would need to wrap each .then(..) call in try-catch and
47
+ // manually handle the stop...
48
+ // ...then there's a question of derivative iterators etc.
49
+ // - another issue here is that the stop would happen in order of
50
+ // execution and not order of elements...
51
+ // XXX though stopping within a single level might be useful...
52
+ // NOTE: the following can not be implemented here:
53
+ // .splice(..) - can't both modify and return
54
+ // a result...
55
+ // .pop() / .shift() - can't modify the promise, use
56
+ // .first() / .last() instead.
57
+ // [Symbol.iterator]() - needs to be sync and we can't
58
+ // know the number of elements to
59
+ // return promises before the whole
60
+ // iterable promise is resolved.
61
+ // NOTE: we are not using async/await here as we need to control the
62
+ // type of promise returned in cases where we know we are returning
63
+ // an array...
64
+ // NOTE: there is no point in implementing a 1:1 version of this that
65
+ // would not support element expansion/contraction as it would only
66
+ // simplify a couple of methods that are 1:1 (like .map(..) and
67
+ // .some(..)) while methods like .filter(..) will throw everything
68
+ // back to the complex IterablePromise...
69
+ //
70
+ // XXX how do we handle errors/rejections???
71
+ //
72
+
73
+ // XXX should these be exported???
74
+ var iterPromiseProxy =
75
+ //module.iterPromiseProxy =
76
+ function(name){
77
+ return function(...args){
78
+ return this.constructor(
79
+ this.then(function(lst){
80
+ return lst[name](...args) })) } }
81
+ var promiseProxy =
82
+ //module.promiseProxy =
83
+ function(name){
84
+ return async function(...args){
85
+ return (await this)[name](...args) } }
51
86
 
52
87
  var IterablePromise =
53
88
  module.IterablePromise =
54
89
  object.Constructor('IterablePromise', Promise, {
55
- // XXX
56
- //STOP: object.STOP,
57
-
90
+ // packed array...
91
+ //
92
+ // Holds promise state.
58
93
  //
59
94
  // Format:
60
95
  // [
@@ -64,16 +99,27 @@ object.Constructor('IterablePromise', Promise, {
64
99
  // ...
65
100
  // ]
66
101
  //
67
- __list: null,
102
+ // This format has several useful features:
103
+ // - concatenating packed list results in a packed list
104
+ // - adding an iterable promise (as-is) into a packed list results
105
+ // in a packed list
106
+ //
107
+ // NOTE: in general iterable promises are implicitly immutable, so
108
+ // it is not recomended to ever edit this inplace...
109
+ // NOTE: we are not isolation any internals to enable users to
110
+ // responsibly extend the code.
111
+ __packed: null,
68
112
 
69
- // low-level .__list handlers/helpers...
113
+ // low-level .__packed handlers/helpers...
70
114
  //
71
115
  // NOTE: these can be useful for debugging and extending...
72
- __pack: function(list, handler){
116
+ //
117
+ // pack and oprionally transform/handle an array (sync)...
118
+ __pack: function(list, handler=undefined){
73
119
  var that = this
74
120
  // handle iterable promise list...
75
121
  if(list instanceof IterablePromise){
76
- return this.__handle(list.__list, handler) }
122
+ return this.__handle(list.__packed, handler) }
77
123
  // handle promise list...
78
124
  if(list instanceof Promise){
79
125
  return list.then(function(list){
@@ -97,11 +143,12 @@ object.Constructor('IterablePromise', Promise, {
97
143
  : !handle ?
98
144
  elem
99
145
  : handler(elem) }) },
100
- __handle: function(list, handler){
146
+ // transform/handle packed array (sync)...
147
+ __handle: function(list, handler=undefined){
101
148
  var that = this
102
149
  if(typeof(list) == 'function'){
103
150
  handler = list
104
- list = this.__list }
151
+ list = this.__packed }
105
152
  if(!handler){
106
153
  return list }
107
154
  // handle promise list...
@@ -121,50 +168,28 @@ object.Constructor('IterablePromise', Promise, {
121
168
  return elem.flat() })
122
169
  : [handler(elem)] })
123
170
  .flat() },
124
- __unpack: function(list){
171
+ // unpack array (async)...
172
+ __unpack: async function(list){
125
173
  list = list
126
- ?? this.__list
174
+ ?? this.__packed
127
175
  // handle promise list...
128
- if(list instanceof Promise){
129
- var that = this
130
- return list.then(function(list){
131
- return that.__unpack(list) }) }
132
- // do the work...
133
- return Promise.all(list)
134
- .then(function(list){
135
- return list.flat() }) },
176
+ return list instanceof Promise ?
177
+ this.__unpack(await list)
178
+ // do the work...
179
+ : (await Promise.all(list))
180
+ .flat() },
136
181
 
137
182
 
138
183
  // iterator methods...
139
184
  //
140
185
  // These will return a new IterablePromise instance...
141
186
  //
142
- // When called from a resolved promise these will return a new
143
- // resolved promise with updated values...
144
- //
145
- // When called from a rejected promise these will return a rejected
146
- // with the same reason promise...
147
- //
148
- //
149
187
  // NOTE: these are different to Array's equivalents in that the handler
150
188
  // is called not in the order of the elements but rather in order
151
189
  // of promise resolution...
152
190
  // NOTE: index of items is unknowable because items can expand and
153
- // contract depending on handlrs (e.g. .filter(..) can remove
191
+ // contract depending on handlers (e.g. .filter(..) can remove
154
192
  // items)...
155
- // This the following can not be implemented here:
156
- // .slice(..)
157
- // .splice(..)
158
- // .values() / .keys()
159
- // .at(..)
160
- // [Symbol.iterator]() - needs to be sync...
161
- // The followng methods are questionable:
162
- // .indexOf(..)
163
- // .includes(..)
164
- // .some(..) / .every(..)
165
- // .sort(..)
166
- //
167
- // XXX should these support STOP???
168
193
  map: function(func){
169
194
  return this.constructor(this,
170
195
  function(e){
@@ -186,13 +211,11 @@ object.Constructor('IterablePromise', Promise, {
186
211
  : _filter(e) }) },
187
212
  // NOTE: this does not return an iterable promise as we can't know
188
213
  // what the user reduces to...
189
- // XXX we could look at the initial state though...
190
214
  // NOTE: the items can be handled out of order because the nested
191
- // promises can resolve in any order.
192
- // XXX doc how to go around this...
215
+ // promises can resolve in any order...
193
216
  // NOTE: since order of execution can not be guaranteed there is no
194
- // point in implementing .reduceRight(..)
195
- // XXX should func be able to return a promise???
217
+ // point in implementing .reduceRight(..) in the same way
218
+ // (see below)...
196
219
  reduce: function(func, res){
197
220
  return this.constructor(this,
198
221
  function(e){
@@ -200,14 +223,7 @@ object.Constructor('IterablePromise', Promise, {
200
223
  return [] })
201
224
  .then(function(){
202
225
  return res }) },
203
- /* // XXX since order of execution is not fixed there is no point in
204
- // adding this.
205
- reduceRight: function(func, res){
206
- return this
207
- .reverse()
208
- .reduce(...arguments)
209
- .reverse() },
210
- //*/
226
+
211
227
  flat: function(depth=1){
212
228
  return this.constructor(this,
213
229
  function(e){
@@ -219,7 +235,7 @@ object.Constructor('IterablePromise', Promise, {
219
235
  e
220
236
  : [e] }) },
221
237
  reverse: function(){
222
- var lst = this.__list
238
+ var lst = this.__packed
223
239
  return this.constructor(
224
240
  lst instanceof Promise ?
225
241
  lst.then(function(elems){
@@ -256,7 +272,7 @@ object.Constructor('IterablePromise', Promise, {
256
272
  [cur, ...other]
257
273
  : other instanceof Promise ?
258
274
  [...cur, other]
259
- : cur.concat(other),
275
+ : [...cur, ...other],
260
276
  'raw') },
261
277
  push: function(elem){
262
278
  return this.concat([elem]) },
@@ -264,15 +280,69 @@ object.Constructor('IterablePromise', Promise, {
264
280
  return this.constructor([elem])
265
281
  .concat(this) },
266
282
 
267
- // XXX do we need these?
268
- // .pop()
269
- // .shift()
270
- // .first() / .last()
271
- // .at(..)
272
- // ...would be nice if these could stop everything that's not
273
- // needed to execute...
274
-
275
283
 
284
+ // XXX thses need to stop once an element is found so we cant simply
285
+ // use .map(..) or .reduce(..)...
286
+ // XXX .find(func) / .findIndex(func)
287
+
288
+
289
+ // proxy methods...
290
+ //
291
+ // These require the whole promise to resolve to trigger.
292
+ //
293
+ // An exception to this would be .at(0)/.first() and .at(-1)/.last()
294
+ // that can get the target element if it's accessible.
295
+ //
296
+ // NOTE: methods that are guaranteed to return an array will return
297
+ // an iterable promise (created with iterPromiseProxy(..))...
298
+ //
299
+ at: async function(i){
300
+ var list = this.__packed
301
+ return ((i != 0 && i != -1)
302
+ || list instanceof Promise
303
+ || list.at(i) instanceof Promise) ?
304
+ (await this).at(i)
305
+ // NOTE: we can only reason about first/last explicit elements,
306
+ // anything else is non-deterministic...
307
+ : list.at(i) instanceof Promise ?
308
+ [await list.at(i)].flat().at(i)
309
+ : list.at(i) instanceof Array ?
310
+ list.at(i).at(i)
311
+ : list.at(i) },
312
+ first: function(){
313
+ return this.at(0) },
314
+ last: function(){
315
+ return this.at(-1) },
316
+
317
+ // NOTE: unlike .reduce(..) this needs the parent fully resolved
318
+ // to be able to iterate from the end.
319
+ // XXX ???
320
+ reduceRight: promiseProxy('reduceRight'),
321
+
322
+ // NOTE: there is no way we can do a sync generator returning
323
+ // promises for values because any promise in .__packed makes the
324
+ // value count/index non-deterministic...
325
+ sort: iterPromiseProxy('sort'),
326
+ // XXX we could have a special-case here for .slice()/slice(0, -1)
327
+ // and possibly othets, should we???
328
+ slice: iterPromiseProxy('slice'),
329
+
330
+ entries: iterPromiseProxy('entries'),
331
+ keys: iterPromiseProxy('keys'),
332
+ // XXX we could possibly make this better via .map(..)
333
+ values: iterPromiseProxy('values'),
334
+
335
+ indexOf: promiseProxy('indexOf'),
336
+ lastIndexOf: promiseProxy('lastIndexOf'),
337
+ includes: promiseProxy('includes'),
338
+
339
+ every: promiseProxy('every'),
340
+ // XXX this can be lazy... (???)
341
+ some: promiseProxy('some'),
342
+
343
+
344
+ // promise api...
345
+ //
276
346
  // Overload .then(..), .catch(..) and .finally(..) to return a plain
277
347
  // Promise instnace...
278
348
  //
@@ -298,6 +368,13 @@ object.Constructor('IterablePromise', Promise, {
298
368
  : p },
299
369
 
300
370
 
371
+ // this is defined globally as Promise.prototype.iter(.,)
372
+ //
373
+ // for details see: PromiseMixin(..) below...
374
+ //iter: function(handler=undefined){ ... },
375
+
376
+
377
+ // constructor...
301
378
  //
302
379
  // Promise.iter([ .. ])
303
380
  // -> iterable-promise
@@ -307,20 +384,21 @@ object.Constructor('IterablePromise', Promise, {
307
384
  //
308
385
  //
309
386
  // handler(e)
310
- // -> [value]
387
+ // -> [value, ..]
311
388
  // -> []
389
+ // -> <promise>
312
390
  //
313
391
  //
314
- // NOTE: element index is unknowable untill the full list is expanded
392
+ // NOTE: element index is unknowable until the full list is expanded
315
393
  // as handler(..)'s return value can expand to any number of
316
394
  // items...
317
395
  // XXX we can make the index a promise, then if the client needs
318
396
  // the value they can wait for it...
319
397
  //
320
398
  //
321
- // Spectial cases usefull for extending this constructor...
399
+ // Special cases useful for extending this constructor...
322
400
  //
323
- // Set raw .__list without any pre-processing...
401
+ // Set raw .__packed without any pre-processing...
324
402
  // Promise.iter([ .. ], 'raw')
325
403
  // -> iterable-promise
326
404
  //
@@ -328,46 +406,13 @@ object.Constructor('IterablePromise', Promise, {
328
406
  // Promise.iter(false)
329
407
  // -> iterable-promise
330
408
  //
331
- //
332
- // XXX if list is an iterator, can we fill this async???
333
- // XXX iterator/generator as input:
334
- // - do we unwind here or externally?
335
- // ...feels like with the generator external unwinding is
336
- // needed...
337
- // XXX would be nice to support trowing STOP...
338
- // - this is more complicated than simply suing .smap(..) instead
339
- // of .map(..) because the list can contain async promises...
340
- // ...would need to wrap each .then(..) call in try-catch and
341
- // manually handle the stop...
342
- // - another issue here is that the stop would happen in order of
343
- // execution and not order of elements...
344
- // XXX DOC:
345
- // inputs:
346
- // - Chaining -- list instanceof IterablePromise
347
- // After all the promises resolve .flat() should
348
- // turn this into the input list.
349
- // For this to work we'll need to at least wrap all
350
- // arrays and promise results in arrays.
351
- // (currently each value is wrapped)
352
- // -> __list
353
- // - promise (value | array)
354
- // - array of:
355
- // - array
356
- // - value
357
- // - promise (value | array)
358
- // - New
359
- // - promise (value | array)
360
- // - value (non-array)
361
- // - array of:
362
- // - value
363
- // - promise (value)
364
409
  __new__: function(_, list, handler){
365
410
  // instance...
366
411
  var promise
367
412
  var obj = Reflect.construct(
368
413
  IterablePromise.__proto__,
369
414
  [function(resolve, reject){
370
- // NOTE: this is here for Promise compatibilty...
415
+ // NOTE: this is here for Promise compatibility...
371
416
  if(typeof(list) == 'function'){
372
417
  return list.call(this, ...arguments) }
373
418
  // initial reject...
@@ -376,17 +421,17 @@ object.Constructor('IterablePromise', Promise, {
376
421
  promise = {resolve, reject} }],
377
422
  IterablePromise)
378
423
 
424
+ // populate new instance...
379
425
  if(promise){
426
+ // handle/pack input data...
380
427
  if(handler != 'raw'){
381
428
  list = list instanceof IterablePromise ?
382
- this.__handle(list.__list, handler)
429
+ this.__handle(list.__packed, handler)
383
430
  : this.__pack(list, handler) }
384
-
385
- Object.defineProperty(obj, '__list', {
431
+ Object.defineProperty(obj, '__packed', {
386
432
  value: list,
387
433
  enumerable: false,
388
434
  })
389
-
390
435
  // handle promise state...
391
436
  this.__unpack(list)
392
437
  .then(function(list){
@@ -446,13 +491,14 @@ object.Constructor('InteractivePromise', Promise, {
446
491
  // register a handler...
447
492
  } else {
448
493
  var h = obj == null ?
449
- // NOTE: we need to get the handlers from .__message_handlers
450
- // unless we are not fully defined yet, then use the
451
- // bootstrap container (handlers)...
452
- // ...since we can call onmessage(..) while the promise
453
- // is still defined there is no way to .send(..) until it
454
- // returns a promise object, this races here are highly
455
- // unlikely...
494
+ // NOTE: we need to get the handlers from
495
+ // .__message_handlers unless we are not
496
+ // fully defined yet, then use the bootstrap
497
+ // container (handlers)...
498
+ // ...since we can call onmessage(..) while
499
+ // the promise is still defined there is no
500
+ // way to .send(..) until it returns a promise
501
+ // object, this races here are highly unlikely...
456
502
  handlers
457
503
  : (obj.__message_handlers =
458
504
  obj.__message_handlers ?? [])
@@ -539,10 +585,13 @@ object.Constructor('CooperativePromise', Promise, {
539
585
  var ProxyPromise =
540
586
  module.ProxyPromise =
541
587
  object.Constructor('ProxyPromise', Promise, {
542
- __new__: function(context, constructor){
543
- var proto = 'prototype' in constructor ?
544
- constructor.prototype
545
- : constructor
588
+
589
+ then: IterablePromise.prototype.then,
590
+
591
+ __new__: function(context, other, nooverride=false){
592
+ var proto = 'prototype' in other ?
593
+ other.prototype
594
+ : other
546
595
  var obj = Reflect.construct(
547
596
  ProxyPromise.__proto__,
548
597
  [function(resolve, reject){
@@ -553,6 +602,9 @@ object.Constructor('ProxyPromise', Promise, {
553
602
  // NOTE: we are not using object.deepKeys(..) here as we need
554
603
  // the key origin not to trigger property getters...
555
604
  var seen = new Set()
605
+ nooverride = nooverride instanceof Array ?
606
+ new Set(nooverride)
607
+ : nooverride
556
608
  while(proto != null){
557
609
  Object.entries(Object.getOwnPropertyDescriptors(proto))
558
610
  .forEach(function([key, value]){
@@ -567,11 +619,15 @@ object.Constructor('ProxyPromise', Promise, {
567
619
  && Object.prototype.run === value.value)
568
620
  && !value.enumerable){
569
621
  return }
622
+ // do not override existing methods...
623
+ if(nooverride === true ?
624
+ key in obj
625
+ : nooverride instanceof Set ?
626
+ nooverride.has(key)
627
+ : nooverride){
628
+ return }
570
629
  // proxy...
571
- obj[key] = function(...args){
572
- // XXX should we also .catch(..) here???
573
- return context.then(function(res){
574
- return res[key](...args) }) } })
630
+ obj[key] = promiseProxy(key) })
575
631
  proto = proto.__proto__ }
576
632
  return obj },
577
633
  })
@@ -591,14 +647,11 @@ object.Mixin('PromiseMixin', 'soft', {
591
647
  PromiseMixin(Promise)
592
648
 
593
649
 
594
- // XXX EXPEREMENTAL...
595
650
  var PromiseProtoMixin =
596
651
  module.PromiseProtoMixin =
597
652
  object.Mixin('PromiseProtoMixin', 'soft', {
598
653
  as: ProxyPromise,
599
-
600
- // XXX
601
- iter: function(handler){
654
+ iter: function(handler=undefined){
602
655
  return IterablePromise(this, handler) },
603
656
  })
604
657
 
@@ -608,4 +661,4 @@ PromiseProtoMixin(Promise.prototype)
608
661
 
609
662
 
610
663
  /**********************************************************************
611
- * vim:set ts=4 sw=4 : */ return module })
664
+ * vim:set ts=4 sw=4 nowrap : */ return module })
package/README.md CHANGED
@@ -77,6 +77,9 @@ Library of JavaScript type extensions, types and utilities.
77
77
  - [`<promise-iter>.reverse()`](#promise-iterreverse)
78
78
  - [`<promise-iter>.concat(..)`](#promise-iterconcat)
79
79
  - [`<promise-iter>.push(..)` / `<promise-iter>.unshift(..)`](#promise-iterpush--promise-iterunshift)
80
+ - [`<promise-iter>.at(..)` / `<promise-iter>.first()` / `<promise-iter>.last()`](#promise-iterat--promise-iterfirst--promise-iterlast)
81
+ - [Array proxy methods returning `<promise-iter>`](#array-proxy-methods-returning-promise-iter)
82
+ - [Array proxy methods returning a `<promise>`](#array-proxy-methods-returning-a-promise)
80
83
  - [`<promise-iter>.then(..)` / `<promise-iter>.catch(..)` / `<promise-iter>.finally(..)`](#promise-iterthen--promise-itercatch--promise-iterfinally)
81
84
  - [Advanced handler](#advanced-handler)
82
85
  - [Promise proxies](#promise-proxies)
@@ -1508,6 +1511,17 @@ promise, even if the original is resolved.
1508
1511
  If all values are resolved the `<promise-iter>` will resolve on the next
1509
1512
  execution frame.
1510
1513
 
1514
+ There are two types of iterator methods here, both are transparent but different
1515
+ in how they process values:
1516
+ - *Parallel methods*
1517
+ These handle elements as soon as they are available even if the parent promise
1518
+ is not yet resolved.
1519
+ <!-- XXX list -->
1520
+ - *Proxies*
1521
+ These methods simply wait for the main promise to resolve and then call the
1522
+ appropriate method on the result.
1523
+ <!-- XXX list + mark definitions as "(proxy)" -->
1524
+
1511
1525
  <!--
1512
1526
  XXX should we support generators as input?
1513
1527
  ...not sure about the control flow direction here, on one hand the generator
@@ -1652,6 +1666,54 @@ and [`<array>.unshift(..)`](https://developer.mozilla.org/en-US/docs/Web/JavaScr
1652
1666
  see them for more info.
1653
1667
 
1654
1668
 
1669
+ #### `<promise-iter>.at(..)` / `<promise-iter>.first()` / `<promise-iter>.last()`
1670
+
1671
+ Proxies to the appropriate array methods with a special-case: when getting elements
1672
+ at positions `0` or `-1` (i.e. `.first()` / `.last()`) these _can_ resolve before the
1673
+ parent `<promise-iter>`.
1674
+
1675
+ XXX
1676
+
1677
+
1678
+ #### Array proxy methods returning `<promise-iter>`
1679
+
1680
+ - `<promise-iter>.sort(..)`
1681
+ - `<promise-iter>.slice(..)`
1682
+ - `<promise-iter>.entries()` / `<promise-iter>.keys()` / `<promise-iter>.values()`
1683
+
1684
+ These methods are proxies to the appropriate array methods.
1685
+
1686
+ ```bnf
1687
+ <promise-iter>.<method>(..)
1688
+ -> <promise-iter>
1689
+ ```
1690
+
1691
+ These methods need the parent `<promise-iter>` to resolve before resolving themselves.
1692
+
1693
+ XXX links...
1694
+
1695
+
1696
+ #### Array proxy methods returning a `<promise>`
1697
+
1698
+ - `<promise-iter>.indexOf(..)`
1699
+ - `<promise-iter>.includes(..)`
1700
+ - `<promise-iter>.every(..)` / `<promise-iter>.some(..)`
1701
+
1702
+ These methods are proxies to the appropriate array methods.
1703
+
1704
+ ```bnf
1705
+ <promise-iter>.<method>(..)
1706
+ -> <promise>
1707
+ ```
1708
+
1709
+ These methods need the parent `<promise-iter>` to resolve before resolving themselves.
1710
+
1711
+ Since the equivalent array methods do not return iterables these will return a basic
1712
+ (non-iterable) `<promise>`.
1713
+
1714
+ XXX links...
1715
+
1716
+
1655
1717
  #### `<promise-iter>.then(..)` / `<promise-iter>.catch(..)` / `<promise-iter>.finally(..)`
1656
1718
 
1657
1719
  An extension to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ig-types",
3
- "version": "6.13.6",
3
+ "version": "6.14.1",
4
4
  "description": "Generic JavaScript types and type extensions...",
5
5
  "main": "main.js",
6
6
  "scripts": {