@adviser/cement 0.4.62 → 0.4.64-dev
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.
- package/cjs/app-context.cjs.map +1 -1
- package/cjs/app-context.d.ts.map +1 -1
- package/cjs/base-sys-abstraction.cjs.map +1 -1
- package/cjs/base-sys-abstraction.d.ts.map +1 -1
- package/cjs/bin2text.cjs.map +1 -1
- package/cjs/bin2text.d.ts.map +1 -1
- package/cjs/coerce-binary.cjs.map +1 -1
- package/cjs/coerce-binary.d.ts.map +1 -1
- package/cjs/crypto.cjs.map +1 -1
- package/cjs/crypto.d.ts.map +1 -1
- package/cjs/future.cjs.map +1 -1
- package/cjs/future.d.ts.map +1 -1
- package/cjs/http_header.cjs.map +1 -1
- package/cjs/http_header.d.ts.map +1 -1
- package/cjs/index.cjs +1 -0
- package/cjs/index.cjs.map +1 -1
- package/cjs/index.d.ts +1 -0
- package/cjs/index.d.ts.map +1 -1
- package/cjs/is-json.cjs.map +1 -1
- package/cjs/is-json.d.ts.map +1 -1
- package/cjs/is-promise.cjs.map +1 -1
- package/cjs/is-promise.d.ts.map +1 -1
- package/cjs/keyed-ng.cjs +93 -0
- package/cjs/keyed-ng.cjs.map +1 -0
- package/cjs/keyed-ng.d.ts +51 -0
- package/cjs/keyed-ng.d.ts.map +1 -0
- package/cjs/keyed-ng.test.cjs +151 -0
- package/cjs/keyed-ng.test.cjs.map +1 -0
- package/cjs/keyed-ng.test.d.ts +2 -0
- package/cjs/keyed-ng.test.d.ts.map +1 -0
- package/cjs/lru-map-set.cjs +2 -1
- package/cjs/lru-map-set.cjs.map +1 -1
- package/cjs/lru-map-set.d.ts +4 -1
- package/cjs/lru-map-set.d.ts.map +1 -1
- package/cjs/on-func.cjs.map +1 -1
- package/cjs/on-func.d.ts.map +1 -1
- package/cjs/option.cjs.map +1 -1
- package/cjs/option.d.ts.map +1 -1
- package/cjs/poller.cjs +8 -3
- package/cjs/poller.cjs.map +1 -1
- package/cjs/poller.d.ts +9 -2
- package/cjs/poller.d.ts.map +1 -1
- package/cjs/promise-sleep.cjs.map +1 -1
- package/cjs/promise-sleep.d.ts.map +1 -1
- package/cjs/resolve-once.cjs +84 -43
- package/cjs/resolve-once.cjs.map +1 -1
- package/cjs/resolve-once.d.ts +31 -34
- package/cjs/resolve-once.d.ts.map +1 -1
- package/cjs/resolve-once.test.cjs +119 -31
- package/cjs/resolve-once.test.cjs.map +1 -1
- package/cjs/result.cjs.map +1 -1
- package/cjs/result.d.ts.map +1 -1
- package/cjs/runtime.cjs.map +1 -1
- package/cjs/runtime.d.ts.map +1 -1
- package/cjs/sys-env.cjs.map +1 -1
- package/cjs/sys-env.d.ts.map +1 -1
- package/cjs/timeouted.cjs.map +1 -1
- package/cjs/timeouted.d.ts.map +1 -1
- package/cjs/tracer.cjs.map +1 -1
- package/cjs/tracer.d.ts.map +1 -1
- package/cjs/txt-en-decoder.cjs +2 -5
- package/cjs/txt-en-decoder.cjs.map +1 -1
- package/cjs/txt-en-decoder.d.ts +1 -1
- package/cjs/txt-en-decoder.d.ts.map +1 -1
- package/cjs/uri.cjs.map +1 -1
- package/cjs/uri.d.ts.map +1 -1
- package/cjs/utils/coerce-uint8.cjs.map +1 -1
- package/cjs/utils/coerce-uint8.d.ts.map +1 -1
- package/cjs/utils/console-write-stream.cjs.map +1 -1
- package/cjs/utils/console-write-stream.d.ts.map +1 -1
- package/cjs/utils/consume.cjs.map +1 -1
- package/cjs/utils/consume.d.ts.map +1 -1
- package/cjs/utils/fanout-write-stream.cjs.map +1 -1
- package/cjs/utils/fanout-write-stream.d.ts.map +1 -1
- package/cjs/utils/get-params-result.cjs.map +1 -1
- package/cjs/utils/get-params-result.d.ts.map +1 -1
- package/cjs/utils/rebuffer.cjs.map +1 -1
- package/cjs/utils/rebuffer.d.ts.map +1 -1
- package/cjs/utils/relative-path.cjs.map +1 -1
- package/cjs/utils/relative-path.d.ts.map +1 -1
- package/cjs/utils/sorted-object.cjs.map +1 -1
- package/cjs/utils/sorted-object.d.ts.map +1 -1
- package/cjs/utils/stream-map.cjs.map +1 -1
- package/cjs/utils/stream-map.d.ts.map +1 -1
- package/cjs/utils/stream2string.cjs.map +1 -1
- package/cjs/utils/stream2string.d.ts.map +1 -1
- package/cjs/utils/string2stream.cjs.map +1 -1
- package/cjs/utils/string2stream.d.ts.map +1 -1
- package/cjs/utils/stripper.cjs.map +1 -1
- package/cjs/utils/stripper.d.ts.map +1 -1
- package/cjs/utils/to-sorted.cjs.map +1 -1
- package/cjs/utils/to-sorted.d.ts.map +1 -1
- package/cjs/utils/uint8array-equal.cjs.map +1 -1
- package/cjs/utils/uint8array-equal.d.ts.map +1 -1
- package/cjs/version.cjs +1 -1
- package/cjs/version.cjs.map +1 -1
- package/cjs/version.d.ts.map +1 -1
- package/deno.json +1 -1
- package/esm/app-context.d.ts.map +1 -1
- package/esm/app-context.js.map +1 -1
- package/esm/base-sys-abstraction.d.ts.map +1 -1
- package/esm/base-sys-abstraction.js.map +1 -1
- package/esm/bin2text.d.ts.map +1 -1
- package/esm/bin2text.js.map +1 -1
- package/esm/coerce-binary.d.ts.map +1 -1
- package/esm/coerce-binary.js.map +1 -1
- package/esm/crypto.d.ts.map +1 -1
- package/esm/crypto.js.map +1 -1
- package/esm/future.d.ts.map +1 -1
- package/esm/future.js.map +1 -1
- package/esm/http_header.d.ts.map +1 -1
- package/esm/http_header.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/is-json.d.ts.map +1 -1
- package/esm/is-json.js.map +1 -1
- package/esm/is-promise.d.ts.map +1 -1
- package/esm/is-promise.js.map +1 -1
- package/esm/keyed-ng.d.ts +51 -0
- package/esm/keyed-ng.d.ts.map +1 -0
- package/esm/keyed-ng.js +89 -0
- package/esm/keyed-ng.js.map +1 -0
- package/esm/keyed-ng.test.d.ts +2 -0
- package/esm/keyed-ng.test.d.ts.map +1 -0
- package/esm/keyed-ng.test.js +149 -0
- package/esm/keyed-ng.test.js.map +1 -0
- package/esm/lru-map-set.d.ts +4 -1
- package/esm/lru-map-set.d.ts.map +1 -1
- package/esm/lru-map-set.js +2 -1
- package/esm/lru-map-set.js.map +1 -1
- package/esm/on-func.d.ts.map +1 -1
- package/esm/on-func.js.map +1 -1
- package/esm/option.d.ts.map +1 -1
- package/esm/option.js.map +1 -1
- package/esm/poller.d.ts +9 -2
- package/esm/poller.d.ts.map +1 -1
- package/esm/poller.js +8 -3
- package/esm/poller.js.map +1 -1
- package/esm/promise-sleep.d.ts.map +1 -1
- package/esm/promise-sleep.js.map +1 -1
- package/esm/resolve-once.d.ts +31 -34
- package/esm/resolve-once.d.ts.map +1 -1
- package/esm/resolve-once.js +83 -41
- package/esm/resolve-once.js.map +1 -1
- package/esm/resolve-once.test.js +119 -31
- package/esm/resolve-once.test.js.map +1 -1
- package/esm/result.d.ts.map +1 -1
- package/esm/result.js.map +1 -1
- package/esm/runtime.d.ts.map +1 -1
- package/esm/runtime.js.map +1 -1
- package/esm/sys-env.d.ts.map +1 -1
- package/esm/sys-env.js.map +1 -1
- package/esm/timeouted.d.ts.map +1 -1
- package/esm/timeouted.js.map +1 -1
- package/esm/tracer.d.ts.map +1 -1
- package/esm/tracer.js.map +1 -1
- package/esm/txt-en-decoder.d.ts +1 -1
- package/esm/txt-en-decoder.d.ts.map +1 -1
- package/esm/txt-en-decoder.js +2 -5
- package/esm/txt-en-decoder.js.map +1 -1
- package/esm/uri.d.ts.map +1 -1
- package/esm/uri.js.map +1 -1
- package/esm/utils/coerce-uint8.d.ts.map +1 -1
- package/esm/utils/coerce-uint8.js.map +1 -1
- package/esm/utils/console-write-stream.d.ts.map +1 -1
- package/esm/utils/console-write-stream.js.map +1 -1
- package/esm/utils/consume.d.ts.map +1 -1
- package/esm/utils/consume.js.map +1 -1
- package/esm/utils/fanout-write-stream.d.ts.map +1 -1
- package/esm/utils/fanout-write-stream.js.map +1 -1
- package/esm/utils/get-params-result.d.ts.map +1 -1
- package/esm/utils/get-params-result.js.map +1 -1
- package/esm/utils/rebuffer.d.ts.map +1 -1
- package/esm/utils/rebuffer.js.map +1 -1
- package/esm/utils/relative-path.d.ts.map +1 -1
- package/esm/utils/relative-path.js.map +1 -1
- package/esm/utils/sorted-object.d.ts.map +1 -1
- package/esm/utils/sorted-object.js.map +1 -1
- package/esm/utils/stream-map.d.ts.map +1 -1
- package/esm/utils/stream-map.js.map +1 -1
- package/esm/utils/stream2string.d.ts.map +1 -1
- package/esm/utils/stream2string.js.map +1 -1
- package/esm/utils/string2stream.d.ts.map +1 -1
- package/esm/utils/string2stream.js.map +1 -1
- package/esm/utils/stripper.d.ts.map +1 -1
- package/esm/utils/stripper.js.map +1 -1
- package/esm/utils/to-sorted.d.ts.map +1 -1
- package/esm/utils/to-sorted.js.map +1 -1
- package/esm/utils/uint8array-equal.d.ts.map +1 -1
- package/esm/utils/uint8array-equal.js.map +1 -1
- package/esm/version.d.ts.map +1 -1
- package/esm/version.js +1 -1
- package/esm/version.js.map +1 -1
- package/package.json +7 -4
- package/src/app-context.ts +111 -5
- package/src/base-sys-abstraction.ts +244 -0
- package/src/bin2text.ts +37 -0
- package/src/coerce-binary.ts +41 -0
- package/src/crypto.ts +35 -0
- package/src/future.ts +45 -1
- package/src/http_header.ts +277 -1
- package/src/index.ts +1 -0
- package/src/is-json.ts +21 -0
- package/src/is-promise.ts +26 -0
- package/src/keyed-ng.ts +628 -0
- package/src/lru-map-set.ts +52 -2
- package/src/on-func.ts +38 -0
- package/src/option.ts +27 -0
- package/src/poller.ts +65 -17
- package/src/promise-sleep.ts +32 -4
- package/src/resolve-once.ts +596 -93
- package/src/result.ts +50 -0
- package/src/runtime.ts +75 -2
- package/src/sys-env.ts +57 -0
- package/src/timeouted.ts +92 -0
- package/src/tracer.ts +41 -0
- package/src/txt-en-decoder.ts +2 -5
- package/src/uri.ts +76 -4
- package/src/utils/coerce-uint8.ts +60 -0
- package/src/utils/console-write-stream.ts +34 -0
- package/src/utils/consume.ts +106 -0
- package/src/utils/fanout-write-stream.ts +45 -0
- package/src/utils/get-params-result.ts +37 -0
- package/src/utils/rebuffer.ts +42 -0
- package/src/utils/relative-path.ts +108 -0
- package/src/utils/sorted-object.ts +50 -0
- package/src/utils/stream-map.ts +90 -0
- package/src/utils/stream2string.ts +35 -0
- package/src/utils/string2stream.ts +30 -0
- package/src/utils/stripper.ts +34 -0
- package/src/utils/to-sorted.ts +34 -0
- package/src/utils/uint8array-equal.ts +20 -0
- package/ts/cjs/app-context.d.ts.map +1 -1
- package/ts/cjs/app-context.js.map +1 -1
- package/ts/cjs/base-sys-abstraction.d.ts.map +1 -1
- package/ts/cjs/base-sys-abstraction.js.map +1 -1
- package/ts/cjs/bin2text.d.ts.map +1 -1
- package/ts/cjs/bin2text.js.map +1 -1
- package/ts/cjs/coerce-binary.d.ts.map +1 -1
- package/ts/cjs/coerce-binary.js.map +1 -1
- package/ts/cjs/crypto.d.ts.map +1 -1
- package/ts/cjs/crypto.js.map +1 -1
- package/ts/cjs/future.d.ts.map +1 -1
- package/ts/cjs/future.js.map +1 -1
- package/ts/cjs/http_header.d.ts.map +1 -1
- package/ts/cjs/http_header.js.map +1 -1
- package/ts/cjs/index.d.ts +1 -0
- package/ts/cjs/index.d.ts.map +1 -1
- package/ts/cjs/index.js +1 -0
- package/ts/cjs/index.js.map +1 -1
- package/ts/cjs/is-json.d.ts.map +1 -1
- package/ts/cjs/is-json.js.map +1 -1
- package/ts/cjs/is-promise.d.ts.map +1 -1
- package/ts/cjs/is-promise.js.map +1 -1
- package/ts/cjs/keyed-ng.d.ts +51 -0
- package/ts/cjs/keyed-ng.d.ts.map +1 -0
- package/ts/cjs/keyed-ng.js +93 -0
- package/ts/cjs/keyed-ng.js.map +1 -0
- package/ts/cjs/keyed-ng.test.d.ts +2 -0
- package/ts/cjs/keyed-ng.test.d.ts.map +1 -0
- package/ts/cjs/keyed-ng.test.js +151 -0
- package/ts/cjs/keyed-ng.test.js.map +1 -0
- package/ts/cjs/lru-map-set.d.ts +4 -1
- package/ts/cjs/lru-map-set.d.ts.map +1 -1
- package/ts/cjs/lru-map-set.js +2 -1
- package/ts/cjs/lru-map-set.js.map +1 -1
- package/ts/cjs/on-func.d.ts.map +1 -1
- package/ts/cjs/on-func.js.map +1 -1
- package/ts/cjs/option.d.ts.map +1 -1
- package/ts/cjs/option.js.map +1 -1
- package/ts/cjs/poller.d.ts +9 -2
- package/ts/cjs/poller.d.ts.map +1 -1
- package/ts/cjs/poller.js +8 -3
- package/ts/cjs/poller.js.map +1 -1
- package/ts/cjs/promise-sleep.d.ts.map +1 -1
- package/ts/cjs/promise-sleep.js.map +1 -1
- package/ts/cjs/resolve-once.d.ts +31 -34
- package/ts/cjs/resolve-once.d.ts.map +1 -1
- package/ts/cjs/resolve-once.js +84 -43
- package/ts/cjs/resolve-once.js.map +1 -1
- package/ts/cjs/resolve-once.test.js +119 -31
- package/ts/cjs/resolve-once.test.js.map +1 -1
- package/ts/cjs/result.d.ts.map +1 -1
- package/ts/cjs/result.js.map +1 -1
- package/ts/cjs/runtime.d.ts.map +1 -1
- package/ts/cjs/runtime.js.map +1 -1
- package/ts/cjs/sys-env.d.ts.map +1 -1
- package/ts/cjs/sys-env.js.map +1 -1
- package/ts/cjs/timeouted.d.ts.map +1 -1
- package/ts/cjs/timeouted.js.map +1 -1
- package/ts/cjs/tracer.d.ts.map +1 -1
- package/ts/cjs/tracer.js.map +1 -1
- package/ts/cjs/txt-en-decoder.d.ts +1 -1
- package/ts/cjs/txt-en-decoder.d.ts.map +1 -1
- package/ts/cjs/txt-en-decoder.js +2 -5
- package/ts/cjs/txt-en-decoder.js.map +1 -1
- package/ts/cjs/uri.d.ts.map +1 -1
- package/ts/cjs/uri.js.map +1 -1
- package/ts/cjs/utils/coerce-uint8.d.ts.map +1 -1
- package/ts/cjs/utils/coerce-uint8.js.map +1 -1
- package/ts/cjs/utils/console-write-stream.d.ts.map +1 -1
- package/ts/cjs/utils/console-write-stream.js.map +1 -1
- package/ts/cjs/utils/consume.d.ts.map +1 -1
- package/ts/cjs/utils/consume.js.map +1 -1
- package/ts/cjs/utils/fanout-write-stream.d.ts.map +1 -1
- package/ts/cjs/utils/fanout-write-stream.js.map +1 -1
- package/ts/cjs/utils/get-params-result.d.ts.map +1 -1
- package/ts/cjs/utils/get-params-result.js.map +1 -1
- package/ts/cjs/utils/rebuffer.d.ts.map +1 -1
- package/ts/cjs/utils/rebuffer.js.map +1 -1
- package/ts/cjs/utils/relative-path.d.ts.map +1 -1
- package/ts/cjs/utils/relative-path.js.map +1 -1
- package/ts/cjs/utils/sorted-object.d.ts.map +1 -1
- package/ts/cjs/utils/sorted-object.js.map +1 -1
- package/ts/cjs/utils/stream-map.d.ts.map +1 -1
- package/ts/cjs/utils/stream-map.js.map +1 -1
- package/ts/cjs/utils/stream2string.d.ts.map +1 -1
- package/ts/cjs/utils/stream2string.js.map +1 -1
- package/ts/cjs/utils/string2stream.d.ts.map +1 -1
- package/ts/cjs/utils/string2stream.js.map +1 -1
- package/ts/cjs/utils/stripper.d.ts.map +1 -1
- package/ts/cjs/utils/stripper.js.map +1 -1
- package/ts/cjs/utils/to-sorted.d.ts.map +1 -1
- package/ts/cjs/utils/to-sorted.js.map +1 -1
- package/ts/cjs/utils/uint8array-equal.d.ts.map +1 -1
- package/ts/cjs/utils/uint8array-equal.js.map +1 -1
- package/ts/cjs/version.d.ts.map +1 -1
- package/ts/cjs/version.js +1 -1
- package/ts/cjs/version.js.map +1 -1
- package/ts/esm/app-context.d.ts.map +1 -1
- package/ts/esm/app-context.js.map +1 -1
- package/ts/esm/base-sys-abstraction.d.ts.map +1 -1
- package/ts/esm/base-sys-abstraction.js.map +1 -1
- package/ts/esm/bin2text.d.ts.map +1 -1
- package/ts/esm/bin2text.js.map +1 -1
- package/ts/esm/coerce-binary.d.ts.map +1 -1
- package/ts/esm/coerce-binary.js.map +1 -1
- package/ts/esm/crypto.d.ts.map +1 -1
- package/ts/esm/crypto.js.map +1 -1
- package/ts/esm/future.d.ts.map +1 -1
- package/ts/esm/future.js.map +1 -1
- package/ts/esm/http_header.d.ts.map +1 -1
- package/ts/esm/http_header.js.map +1 -1
- package/ts/esm/index.d.ts +1 -0
- package/ts/esm/index.d.ts.map +1 -1
- package/ts/esm/index.js +1 -0
- package/ts/esm/index.js.map +1 -1
- package/ts/esm/is-json.d.ts.map +1 -1
- package/ts/esm/is-json.js.map +1 -1
- package/ts/esm/is-promise.d.ts.map +1 -1
- package/ts/esm/is-promise.js.map +1 -1
- package/ts/esm/keyed-ng.d.ts +51 -0
- package/ts/esm/keyed-ng.d.ts.map +1 -0
- package/ts/esm/keyed-ng.js +89 -0
- package/ts/esm/keyed-ng.js.map +1 -0
- package/ts/esm/keyed-ng.test.d.ts +2 -0
- package/ts/esm/keyed-ng.test.d.ts.map +1 -0
- package/ts/esm/keyed-ng.test.js +149 -0
- package/ts/esm/keyed-ng.test.js.map +1 -0
- package/ts/esm/lru-map-set.d.ts +4 -1
- package/ts/esm/lru-map-set.d.ts.map +1 -1
- package/ts/esm/lru-map-set.js +2 -1
- package/ts/esm/lru-map-set.js.map +1 -1
- package/ts/esm/on-func.d.ts.map +1 -1
- package/ts/esm/on-func.js.map +1 -1
- package/ts/esm/option.d.ts.map +1 -1
- package/ts/esm/option.js.map +1 -1
- package/ts/esm/poller.d.ts +9 -2
- package/ts/esm/poller.d.ts.map +1 -1
- package/ts/esm/poller.js +8 -3
- package/ts/esm/poller.js.map +1 -1
- package/ts/esm/promise-sleep.d.ts.map +1 -1
- package/ts/esm/promise-sleep.js.map +1 -1
- package/ts/esm/resolve-once.d.ts +31 -34
- package/ts/esm/resolve-once.d.ts.map +1 -1
- package/ts/esm/resolve-once.js +83 -41
- package/ts/esm/resolve-once.js.map +1 -1
- package/ts/esm/resolve-once.test.js +119 -31
- package/ts/esm/resolve-once.test.js.map +1 -1
- package/ts/esm/result.d.ts.map +1 -1
- package/ts/esm/result.js.map +1 -1
- package/ts/esm/runtime.d.ts.map +1 -1
- package/ts/esm/runtime.js.map +1 -1
- package/ts/esm/sys-env.d.ts.map +1 -1
- package/ts/esm/sys-env.js.map +1 -1
- package/ts/esm/timeouted.d.ts.map +1 -1
- package/ts/esm/timeouted.js.map +1 -1
- package/ts/esm/tracer.d.ts.map +1 -1
- package/ts/esm/tracer.js.map +1 -1
- package/ts/esm/txt-en-decoder.d.ts +1 -1
- package/ts/esm/txt-en-decoder.d.ts.map +1 -1
- package/ts/esm/txt-en-decoder.js +2 -5
- package/ts/esm/txt-en-decoder.js.map +1 -1
- package/ts/esm/uri.d.ts.map +1 -1
- package/ts/esm/uri.js.map +1 -1
- package/ts/esm/utils/coerce-uint8.d.ts.map +1 -1
- package/ts/esm/utils/coerce-uint8.js.map +1 -1
- package/ts/esm/utils/console-write-stream.d.ts.map +1 -1
- package/ts/esm/utils/console-write-stream.js.map +1 -1
- package/ts/esm/utils/consume.d.ts.map +1 -1
- package/ts/esm/utils/consume.js.map +1 -1
- package/ts/esm/utils/fanout-write-stream.d.ts.map +1 -1
- package/ts/esm/utils/fanout-write-stream.js.map +1 -1
- package/ts/esm/utils/get-params-result.d.ts.map +1 -1
- package/ts/esm/utils/get-params-result.js.map +1 -1
- package/ts/esm/utils/rebuffer.d.ts.map +1 -1
- package/ts/esm/utils/rebuffer.js.map +1 -1
- package/ts/esm/utils/relative-path.d.ts.map +1 -1
- package/ts/esm/utils/relative-path.js.map +1 -1
- package/ts/esm/utils/sorted-object.d.ts.map +1 -1
- package/ts/esm/utils/sorted-object.js.map +1 -1
- package/ts/esm/utils/stream-map.d.ts.map +1 -1
- package/ts/esm/utils/stream-map.js.map +1 -1
- package/ts/esm/utils/stream2string.d.ts.map +1 -1
- package/ts/esm/utils/stream2string.js.map +1 -1
- package/ts/esm/utils/string2stream.d.ts.map +1 -1
- package/ts/esm/utils/string2stream.js.map +1 -1
- package/ts/esm/utils/stripper.d.ts.map +1 -1
- package/ts/esm/utils/stripper.js.map +1 -1
- package/ts/esm/utils/to-sorted.d.ts.map +1 -1
- package/ts/esm/utils/to-sorted.js.map +1 -1
- package/ts/esm/utils/uint8array-equal.d.ts.map +1 -1
- package/ts/esm/utils/uint8array-equal.js.map +1 -1
- package/ts/esm/version.d.ts.map +1 -1
- package/ts/esm/version.js +1 -1
- package/ts/esm/version.js.map +1 -1
package/src/resolve-once.ts
CHANGED
|
@@ -1,17 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for executing functions once and caching results, with support for both
|
|
3
|
+
* synchronous and asynchronous operations, sequential execution, and keyed collections.
|
|
4
|
+
*
|
|
5
|
+
* ## Main Classes
|
|
6
|
+
*
|
|
7
|
+
* - **ResolveOnce**: Ensures a function executes only once, automatically handling sync/async
|
|
8
|
+
* - **ResolveSeq**: Executes functions sequentially, maintaining order even with concurrent calls
|
|
9
|
+
* - **Keyed**: Base class for managing keyed instances with LRU caching
|
|
10
|
+
* - **KeyedResolveOnce**: Map of ResolveOnce instances indexed by keys
|
|
11
|
+
* - **KeyedResolveSeq**: Map of ResolveSeq instances indexed by keys
|
|
12
|
+
* - **Lazy**: Function wrapper that executes once and caches the result
|
|
13
|
+
*
|
|
14
|
+
* @module resolve-once
|
|
15
|
+
*/
|
|
16
|
+
|
|
1
17
|
import { Future } from "./future.js";
|
|
2
18
|
import { UnPromisify } from "./is-promise.js";
|
|
3
19
|
import { isPromise } from "./is-promise.js";
|
|
4
|
-
import {
|
|
20
|
+
import { UnregFn } from "./lru-map-set.js";
|
|
5
21
|
import { Result } from "./result.js";
|
|
6
22
|
import { Option } from "./option.js";
|
|
23
|
+
import { KeyedIf, KeyedNg, KeyedNgItem, KeyedNgItemWithoutValue, KeyedNgOptions } from "./keyed-ng.js";
|
|
7
24
|
|
|
8
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Internal item representing a queued function in a ResolveSeq sequence.
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
9
29
|
interface ResolveSeqItem<C, T, R> {
|
|
10
30
|
readonly future: Future<T>;
|
|
11
31
|
readonly fn: (c: C) => R;
|
|
12
32
|
readonly id?: number;
|
|
13
33
|
}
|
|
14
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Executes functions sequentially, one at a time, ensuring order of execution.
|
|
37
|
+
*
|
|
38
|
+
* ResolveSeq maintains a queue of functions and executes them in order, waiting for each
|
|
39
|
+
* to complete before starting the next. This is useful when you need to ensure operations
|
|
40
|
+
* happen in a specific sequence, even when multiple operations are queued concurrently.
|
|
41
|
+
*
|
|
42
|
+
* @template T - The return type of the functions
|
|
43
|
+
* @template CTX - Optional context type passed to each function
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const seq = new ResolveSeq<number>();
|
|
48
|
+
*
|
|
49
|
+
* // Multiple calls are queued and executed in order
|
|
50
|
+
* const p1 = seq.add(() => asyncOperation1());
|
|
51
|
+
* const p2 = seq.add(() => asyncOperation2());
|
|
52
|
+
* const p3 = seq.add(() => asyncOperation3());
|
|
53
|
+
*
|
|
54
|
+
* // Operations execute sequentially: op1 -> op2 -> op3
|
|
55
|
+
* await Promise.all([p1, p2, p3]);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
15
58
|
export class ResolveSeq<T, CTX extends NonNullable<object> = object> {
|
|
16
59
|
readonly ctx?: CTX;
|
|
17
60
|
readonly _seqFutures: ResolveSeqItem<CTX, T, unknown>[] = [];
|
|
@@ -19,11 +62,21 @@ export class ResolveSeq<T, CTX extends NonNullable<object> = object> {
|
|
|
19
62
|
constructor(ctx?: CTX) {
|
|
20
63
|
this.ctx = ctx;
|
|
21
64
|
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Resets the sequence (currently a no-op).
|
|
68
|
+
*/
|
|
22
69
|
reset(): void {
|
|
23
70
|
/* noop */
|
|
24
71
|
}
|
|
25
72
|
|
|
26
73
|
readonly _flushWaiting: Future<void>[] = [];
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns a promise that resolves when all currently queued items complete.
|
|
77
|
+
*
|
|
78
|
+
* @returns A promise that resolves when the queue is empty
|
|
79
|
+
*/
|
|
27
80
|
flush(): Promise<void> {
|
|
28
81
|
if (this._seqFutures.length > 0) {
|
|
29
82
|
const waitForFlush = new Future<void>();
|
|
@@ -32,6 +85,11 @@ export class ResolveSeq<T, CTX extends NonNullable<object> = object> {
|
|
|
32
85
|
}
|
|
33
86
|
return Promise.resolve();
|
|
34
87
|
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Internal method to process items in the queue sequentially.
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
35
93
|
async _step(item?: ResolveSeqItem<CTX, T, Promise<T> | T>): Promise<void> {
|
|
36
94
|
if (!item) {
|
|
37
95
|
// done
|
|
@@ -55,6 +113,17 @@ export class ResolveSeq<T, CTX extends NonNullable<object> = object> {
|
|
|
55
113
|
}
|
|
56
114
|
return this._step(this._seqFutures[0] as ResolveSeqItem<CTX, T, Promise<T> | T>);
|
|
57
115
|
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Adds a function to the sequence queue for sequential execution.
|
|
119
|
+
*
|
|
120
|
+
* The function will be executed after all previously queued functions complete.
|
|
121
|
+
* Returns a promise that resolves with the function's result.
|
|
122
|
+
*
|
|
123
|
+
* @param fn - The function to execute
|
|
124
|
+
* @param id - Optional identifier for tracking
|
|
125
|
+
* @returns A promise that resolves with the function's result
|
|
126
|
+
*/
|
|
58
127
|
add<R extends Promise<T> | T>(fn: (c: CTX) => R, id?: number): R {
|
|
59
128
|
const future = new Future<T>();
|
|
60
129
|
this._seqFutures.push({ future, fn, id });
|
|
@@ -65,22 +134,33 @@ export class ResolveSeq<T, CTX extends NonNullable<object> = object> {
|
|
|
65
134
|
}
|
|
66
135
|
}
|
|
67
136
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// ResolveOnce
|
|
77
|
-
// cases SyncMode, AsyncMode
|
|
78
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Represents the current state of a resolve operation.
|
|
139
|
+
* - `initial`: Not yet started
|
|
140
|
+
* - `processed`: Completed
|
|
141
|
+
* - `waiting`: Waiting for async operation
|
|
142
|
+
* - `processing`: Currently executing
|
|
143
|
+
*/
|
|
79
144
|
type ResolveState = "initial" | "processed" | "waiting" | "processing";
|
|
80
145
|
|
|
81
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Type helper that unwraps Promise types to their resolved value type.
|
|
148
|
+
*
|
|
149
|
+
* @template R - The type to unwrap
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* type A = ResultOnce<Promise<number>>; // Promise<number>
|
|
154
|
+
* type B = ResultOnce<string>; // string
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
82
157
|
export type ResultOnce<R> = R extends Promise<infer T> ? Promise<T> : R;
|
|
83
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Interface defining the contract for ResolveOnce-like objects.
|
|
161
|
+
* @template R - The return type
|
|
162
|
+
* @template CTX - Optional context type
|
|
163
|
+
*/
|
|
84
164
|
export interface ResolveOnceIf<R, CTX = void> {
|
|
85
165
|
get ready(): boolean;
|
|
86
166
|
get value(): UnPromisify<R> | undefined;
|
|
@@ -91,6 +171,16 @@ export interface ResolveOnceIf<R, CTX = void> {
|
|
|
91
171
|
reset<R>(fn?: (c?: CTX) => R): ResultOnce<R>;
|
|
92
172
|
}
|
|
93
173
|
|
|
174
|
+
/**
|
|
175
|
+
* Synchronous version of ResolveOnce for functions that return non-promise values.
|
|
176
|
+
*
|
|
177
|
+
* This class is used internally by ResolveOnce when it detects a synchronous function.
|
|
178
|
+
* It executes the function once and caches the result or error for subsequent calls.
|
|
179
|
+
*
|
|
180
|
+
* @template T - The return type
|
|
181
|
+
* @template CTX - Optional context type
|
|
182
|
+
* @internal
|
|
183
|
+
*/
|
|
94
184
|
export class SyncResolveOnce<T, CTX = void> {
|
|
95
185
|
state: ResolveState = "initial";
|
|
96
186
|
|
|
@@ -99,14 +189,23 @@ export class SyncResolveOnce<T, CTX = void> {
|
|
|
99
189
|
|
|
100
190
|
readonly queueLength = 0;
|
|
101
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Gets the cached value if available.
|
|
194
|
+
*/
|
|
102
195
|
get value(): T | undefined {
|
|
103
196
|
return this.#value;
|
|
104
197
|
}
|
|
105
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Gets the cached error if one occurred.
|
|
201
|
+
*/
|
|
106
202
|
get error(): Error | undefined {
|
|
107
203
|
return this.#error;
|
|
108
204
|
}
|
|
109
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Returns true if the function has been executed.
|
|
208
|
+
*/
|
|
110
209
|
get ready(): boolean {
|
|
111
210
|
return this.state === "processed";
|
|
112
211
|
}
|
|
@@ -116,6 +215,14 @@ export class SyncResolveOnce<T, CTX = void> {
|
|
|
116
215
|
this.#ctx = ctx;
|
|
117
216
|
}
|
|
118
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Executes the function once and caches the result.
|
|
220
|
+
* Subsequent calls return the cached value without re-executing.
|
|
221
|
+
*
|
|
222
|
+
* @param fn - The function to execute
|
|
223
|
+
* @returns The result of the function
|
|
224
|
+
* @throws Error if the function returned a promise (use AsyncResolveOnce instead)
|
|
225
|
+
*/
|
|
119
226
|
resolve(fn: (ctx?: CTX) => T): T {
|
|
120
227
|
if (this.state === "initial") {
|
|
121
228
|
this.state = "processed";
|
|
@@ -134,6 +241,12 @@ export class SyncResolveOnce<T, CTX = void> {
|
|
|
134
241
|
return this.#value as T;
|
|
135
242
|
}
|
|
136
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Resets the cached state, allowing the function to be executed again.
|
|
246
|
+
*
|
|
247
|
+
* @param fn - Optional function to execute immediately after reset
|
|
248
|
+
* @returns The result if fn provided, undefined otherwise
|
|
249
|
+
*/
|
|
137
250
|
reset(fn?: (c?: CTX) => T): T | undefined {
|
|
138
251
|
this.state = "initial";
|
|
139
252
|
this.#value = undefined;
|
|
@@ -145,6 +258,11 @@ export class SyncResolveOnce<T, CTX = void> {
|
|
|
145
258
|
}
|
|
146
259
|
}
|
|
147
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Internal helper for AsyncResolveOnce that manages a single async resolution.
|
|
263
|
+
* Handles queuing of multiple concurrent requests for the same async operation.
|
|
264
|
+
* @internal
|
|
265
|
+
*/
|
|
148
266
|
class AsyncResolveItem<T> {
|
|
149
267
|
readonly id = Math.random();
|
|
150
268
|
#state: ResolveState = "initial";
|
|
@@ -170,6 +288,9 @@ class AsyncResolveItem<T> {
|
|
|
170
288
|
return this.#queue.length;
|
|
171
289
|
}
|
|
172
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Returns true if this item has completed and has no pending futures.
|
|
293
|
+
*/
|
|
173
294
|
isDisposable(): boolean {
|
|
174
295
|
return this.#state === "processed" && this.#queue.length === 0;
|
|
175
296
|
}
|
|
@@ -197,11 +318,13 @@ class AsyncResolveItem<T> {
|
|
|
197
318
|
throw new Error("AsyncResolveItem.#promiseResult impossible");
|
|
198
319
|
}
|
|
199
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Resolves the async operation, queuing the request if already in progress.
|
|
323
|
+
*/
|
|
200
324
|
resolve(): T {
|
|
201
325
|
if (this.#state === "initial") {
|
|
202
326
|
this.#state = "waiting";
|
|
203
327
|
const future = new Future<UnPromisify<T>>();
|
|
204
|
-
// console.log("asyncItem addQueue#initial", this.id, this.#queue.length);
|
|
205
328
|
this.#queue.push(future);
|
|
206
329
|
this.#toResolve
|
|
207
330
|
.then((value) => {
|
|
@@ -223,7 +346,6 @@ class AsyncResolveItem<T> {
|
|
|
223
346
|
}
|
|
224
347
|
if (this.#state === "waiting") {
|
|
225
348
|
const future = new Future<UnPromisify<T>>();
|
|
226
|
-
// console.log("asyncItem addQueue#waiting", this.id, this.#queue.length);
|
|
227
349
|
this.#queue.push(future);
|
|
228
350
|
return future.asPromise() as T;
|
|
229
351
|
}
|
|
@@ -231,8 +353,18 @@ class AsyncResolveItem<T> {
|
|
|
231
353
|
}
|
|
232
354
|
}
|
|
233
355
|
|
|
356
|
+
/**
|
|
357
|
+
* Asynchronous version of ResolveOnce for functions that return promises.
|
|
358
|
+
*
|
|
359
|
+
* This class is used internally by ResolveOnce when it detects an async function.
|
|
360
|
+
* It executes the async function once and caches the result for subsequent calls.
|
|
361
|
+
* Multiple concurrent calls while waiting will all receive the same promise result.
|
|
362
|
+
*
|
|
363
|
+
* @template T - The return type (Promise or value)
|
|
364
|
+
* @template CTX - Optional context type
|
|
365
|
+
* @internal
|
|
366
|
+
*/
|
|
234
367
|
export class AsyncResolveOnce<T, CTX = void> {
|
|
235
|
-
// readonly id = Math.random();
|
|
236
368
|
state: ResolveState = "initial";
|
|
237
369
|
|
|
238
370
|
readonly #queue: AsyncResolveItem<T>[] = [];
|
|
@@ -250,13 +382,23 @@ export class AsyncResolveOnce<T, CTX = void> {
|
|
|
250
382
|
return r;
|
|
251
383
|
}
|
|
252
384
|
|
|
385
|
+
/**
|
|
386
|
+
* Returns the total number of queued futures across all items.
|
|
387
|
+
*/
|
|
253
388
|
get queueLength(): number {
|
|
254
389
|
return this.#queue.reduce((acc, r) => acc + r.queuelength, this.#queue.length);
|
|
255
390
|
}
|
|
256
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Returns true if the async operation has started.
|
|
394
|
+
*/
|
|
257
395
|
get ready(): boolean {
|
|
258
396
|
return this.state !== "initial";
|
|
259
397
|
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Gets the cached resolved value if available.
|
|
401
|
+
*/
|
|
260
402
|
get value(): UnPromisify<T> | undefined {
|
|
261
403
|
if (this.state === "initial") {
|
|
262
404
|
return undefined;
|
|
@@ -264,6 +406,9 @@ export class AsyncResolveOnce<T, CTX = void> {
|
|
|
264
406
|
return this.#active().value;
|
|
265
407
|
}
|
|
266
408
|
|
|
409
|
+
/**
|
|
410
|
+
* Gets the cached error if one occurred.
|
|
411
|
+
*/
|
|
267
412
|
get error(): Error | undefined {
|
|
268
413
|
if (this.state === "initial") {
|
|
269
414
|
return undefined;
|
|
@@ -271,6 +416,13 @@ export class AsyncResolveOnce<T, CTX = void> {
|
|
|
271
416
|
return this.#active().error;
|
|
272
417
|
}
|
|
273
418
|
|
|
419
|
+
/**
|
|
420
|
+
* Executes the async function once and caches the result.
|
|
421
|
+
* Subsequent calls return the cached promise without re-executing.
|
|
422
|
+
*
|
|
423
|
+
* @param fn - The async function to execute
|
|
424
|
+
* @returns A promise that resolves to the function's result
|
|
425
|
+
*/
|
|
274
426
|
resolve(fn: (ctx?: CTX) => T): T {
|
|
275
427
|
if (this.state === "initial") {
|
|
276
428
|
this.state = "waiting";
|
|
@@ -285,7 +437,6 @@ export class AsyncResolveOnce<T, CTX = void> {
|
|
|
285
437
|
} catch (e) {
|
|
286
438
|
promiseResult = Promise.reject(e as Error);
|
|
287
439
|
}
|
|
288
|
-
// console.log("asyncOnce addQueue#initial", this.id, this.#queue.length);
|
|
289
440
|
this.#queue.push(new AsyncResolveItem(promiseResult));
|
|
290
441
|
}
|
|
291
442
|
// remove all disposable items
|
|
@@ -299,6 +450,12 @@ export class AsyncResolveOnce<T, CTX = void> {
|
|
|
299
450
|
return this.#active().resolve();
|
|
300
451
|
}
|
|
301
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Resets the cached state, allowing the function to be executed again.
|
|
455
|
+
*
|
|
456
|
+
* @param fn - Optional function to execute immediately after reset
|
|
457
|
+
* @returns The result if fn provided, undefined otherwise
|
|
458
|
+
*/
|
|
302
459
|
reset(fn?: (c?: CTX) => T): T {
|
|
303
460
|
this.state = "initial";
|
|
304
461
|
if (fn) {
|
|
@@ -308,6 +465,30 @@ export class AsyncResolveOnce<T, CTX = void> {
|
|
|
308
465
|
}
|
|
309
466
|
}
|
|
310
467
|
|
|
468
|
+
/**
|
|
469
|
+
* Ensures a function is executed only once, caching and returning the result for subsequent calls.
|
|
470
|
+
*
|
|
471
|
+
* ResolveOnce automatically detects whether the function returns a synchronous value or a Promise,
|
|
472
|
+
* and handles both cases appropriately. All subsequent calls will receive the same cached result.
|
|
473
|
+
* Supports optional context parameter and can be reset to allow re-execution.
|
|
474
|
+
*
|
|
475
|
+
* @template T - The return type of the function (can be synchronous or Promise)
|
|
476
|
+
* @template CTX - Optional context type passed to the function
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* ```typescript
|
|
480
|
+
* const expensiveOp = new ResolveOnce<number>();
|
|
481
|
+
*
|
|
482
|
+
* // First call executes the function
|
|
483
|
+
* const result1 = expensiveOp.once(() => computeExpensiveValue());
|
|
484
|
+
*
|
|
485
|
+
* // Subsequent calls return cached result
|
|
486
|
+
* const result2 = expensiveOp.once(() => computeExpensiveValue()); // Not executed
|
|
487
|
+
*
|
|
488
|
+
* // Reset to allow re-execution
|
|
489
|
+
* expensiveOp.reset();
|
|
490
|
+
* ```
|
|
491
|
+
*/
|
|
311
492
|
export class ResolveOnce<T, CTX = void> implements ResolveOnceIf<T, CTX> {
|
|
312
493
|
#state: ResolveState = "initial";
|
|
313
494
|
|
|
@@ -382,6 +563,11 @@ export class ResolveOnce<T, CTX = void> implements ResolveOnceIf<T, CTX> {
|
|
|
382
563
|
|
|
383
564
|
reset<R>(fn?: (c: CTX) => R): ResultOnce<R> {
|
|
384
565
|
if (this.#state === "initial") {
|
|
566
|
+
if (!fn) {
|
|
567
|
+
// eslint-disable-next-line no-console
|
|
568
|
+
console.warn("ResolveOnce.reset called but not yet resolved and no fn given");
|
|
569
|
+
return undefined as ResultOnce<R>;
|
|
570
|
+
}
|
|
385
571
|
return this.once(fn as (c: CTX) => R);
|
|
386
572
|
}
|
|
387
573
|
if (this.#state === "processing") {
|
|
@@ -393,97 +579,364 @@ export class ResolveOnce<T, CTX = void> implements ResolveOnceIf<T, CTX> {
|
|
|
393
579
|
}
|
|
394
580
|
}
|
|
395
581
|
|
|
396
|
-
|
|
397
|
-
|
|
582
|
+
// /**
|
|
583
|
+
// * Configuration parameters for Keyed instances.
|
|
584
|
+
// * @template K - The key type
|
|
585
|
+
// * @template V - The value type
|
|
586
|
+
// */
|
|
587
|
+
// export interface KeyedParam<K, V> {
|
|
588
|
+
// readonly lru: Partial<LRUParam<V, K>>;
|
|
589
|
+
// }
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Represents a key-value pair where the value is wrapped in a Result.
|
|
593
|
+
* @template K - The key type
|
|
594
|
+
* @template V - The value type
|
|
595
|
+
*/
|
|
596
|
+
export interface KeyItem<K, V> {
|
|
597
|
+
readonly key: K;
|
|
598
|
+
readonly value: Result<V>;
|
|
398
599
|
}
|
|
399
600
|
|
|
400
|
-
|
|
601
|
+
/**
|
|
602
|
+
* Configuration parameters for KeyedResolvOnce, excluding the createValue factory.
|
|
603
|
+
* @template K - The key type
|
|
604
|
+
* @template V - The value type
|
|
605
|
+
* @template CTX - The context type
|
|
606
|
+
*/
|
|
607
|
+
export type AddKeyedParam<K, V, CTX extends NonNullable<object>> = Omit<KeyedNgOptions<K, V, CTX>, "createValue">;
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Type helper that adds a key property to a context object.
|
|
611
|
+
* @template X - The context type
|
|
612
|
+
* @template K - The key type
|
|
613
|
+
*/
|
|
614
|
+
export type WithKey<X extends NonNullable<object>, K> = X & { readonly key: K };
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Type helper that adds an optional reset method to a value type.
|
|
618
|
+
* @template V - The value type
|
|
619
|
+
*/
|
|
620
|
+
export type WithOptionalReset<V> = V & { readonly reset?: () => void };
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Represents an item in a KeyedResolvOnce collection with its resolved result.
|
|
624
|
+
* @template K - The key type
|
|
625
|
+
* @template T - The value type
|
|
626
|
+
* @template CTX - The context type
|
|
627
|
+
*/
|
|
628
|
+
export interface KeyedResolveOnceItem<K, T, CTX extends NonNullable<object>> {
|
|
629
|
+
/** The key associated with this item */
|
|
630
|
+
readonly key: K;
|
|
631
|
+
/** The resolved value wrapped in a Result (Ok or Err) */
|
|
632
|
+
readonly value: Result<T>;
|
|
633
|
+
/** The complete KeyedNgItem containing metadata */
|
|
634
|
+
readonly item: KeyedNgItem<K, ResolveOnce<WithOptionalReset<T>, KeyedNgItemWithoutValue<K, CTX>>, CTX>;
|
|
635
|
+
}
|
|
401
636
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
637
|
+
/**
|
|
638
|
+
* Keyed collection of ResolveOnce instances.
|
|
639
|
+
*
|
|
640
|
+
* Manages a map of ResolveOnce instances indexed by keys, with optional LRU caching.
|
|
641
|
+
* Each key gets its own ResolveOnce instance that can be accessed and manipulated independently.
|
|
642
|
+
* Values can optionally have a reset() method for cleanup on deletion.
|
|
643
|
+
*
|
|
644
|
+
* @template T - The return type of the ResolveOnce instances (must include optional reset)
|
|
645
|
+
* @template K - The key type (defaults to string)
|
|
646
|
+
* @template CTX - Optional context type (defaults to empty object)
|
|
647
|
+
* @template PT - Plain type of T without reset (for internal use)
|
|
648
|
+
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```typescript
|
|
651
|
+
* const cache = new KeyedResolvOnce<number, string>();
|
|
652
|
+
*
|
|
653
|
+
* // Each key gets its own ResolveOnce
|
|
654
|
+
* const result1 = cache.get('key1').once(() => expensiveCalc1());
|
|
655
|
+
* const result2 = cache.get('key2').once(() => expensiveCalc2());
|
|
656
|
+
*
|
|
657
|
+
* // Delete specific key
|
|
658
|
+
* cache.delete('key1');
|
|
659
|
+
*
|
|
660
|
+
* // Iterate over all resolved entries
|
|
661
|
+
* cache.forEach((item) => {
|
|
662
|
+
* console.log(item.key, item.value.Ok);
|
|
663
|
+
* });
|
|
664
|
+
* ```
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* ```typescript
|
|
668
|
+
* // With custom key type and context
|
|
669
|
+
* interface UserKey { org: string; id: string; }
|
|
670
|
+
* interface UserContext { apiKey: string; }
|
|
671
|
+
*
|
|
672
|
+
* const users = new KeyedResolvOnce<User, UserKey, UserContext>({
|
|
673
|
+
* key2string: (key) => `${key.org}:${key.id}`,
|
|
674
|
+
* ctx: { apiKey: 'default' },
|
|
675
|
+
* lru: { max: 100 }
|
|
676
|
+
* });
|
|
677
|
+
*
|
|
678
|
+
* const user = users.get({ org: 'acme', id: '123' })
|
|
679
|
+
* .once(({ givenKey, ctx }) => fetchUser(givenKey, ctx));
|
|
680
|
+
* ```
|
|
681
|
+
*/
|
|
682
|
+
export class KeyedResolvOnce<T extends WithOptionalReset<PT>, K = string, CTX extends NonNullable<object> = object, PT = T>
|
|
683
|
+
implements
|
|
684
|
+
Omit<
|
|
685
|
+
// KeyedIf<ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>, WithOptionalReset<T>, K>
|
|
686
|
+
KeyedIf<
|
|
687
|
+
KeyedNgItem<K, ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>, CTX>,
|
|
688
|
+
ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>,
|
|
689
|
+
K,
|
|
690
|
+
CTX
|
|
691
|
+
>,
|
|
692
|
+
"entries" | "forEach" | "onSet" | "onDelete" | "values" | "setParam"
|
|
693
|
+
>
|
|
694
|
+
{
|
|
695
|
+
/** @internal */
|
|
696
|
+
readonly _keyed: KeyedNg<K, ResolveOnce<WithOptionalReset<T>, KeyedNgItemWithoutValue<K, CTX>>, CTX>;
|
|
406
697
|
|
|
407
|
-
|
|
698
|
+
/**
|
|
699
|
+
* Creates a new KeyedResolvOnce instance.
|
|
700
|
+
*
|
|
701
|
+
* @param kp - Configuration options (key2string, ctx, lru)
|
|
702
|
+
*/
|
|
703
|
+
constructor(kp: Partial<AddKeyedParam<K, T, CTX>> = {}) {
|
|
704
|
+
this._keyed = new KeyedNg({
|
|
705
|
+
createValue: (
|
|
706
|
+
item: KeyedNgItem<K, ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>, CTX>,
|
|
707
|
+
): ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>> => {
|
|
708
|
+
return new ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>({
|
|
709
|
+
...item,
|
|
710
|
+
ctx: kp.ctx ?? item.ctx,
|
|
711
|
+
});
|
|
712
|
+
},
|
|
713
|
+
key2string: kp.key2string,
|
|
714
|
+
ctx: kp.ctx as CTX,
|
|
715
|
+
lru: kp.lru,
|
|
716
|
+
});
|
|
717
|
+
}
|
|
408
718
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
719
|
+
/**
|
|
720
|
+
* Returns all keys currently in the collection.
|
|
721
|
+
*
|
|
722
|
+
* @returns Array of all keys
|
|
723
|
+
*/
|
|
724
|
+
keys(): K[] {
|
|
725
|
+
return this._keyed.keys();
|
|
413
726
|
}
|
|
414
727
|
|
|
415
|
-
|
|
416
|
-
|
|
728
|
+
/**
|
|
729
|
+
* Returns all resolved items with their values wrapped in Result.
|
|
730
|
+
*
|
|
731
|
+
* Only includes items that have been resolved (ready state).
|
|
732
|
+
* Each item contains the key, Result-wrapped value, and full item metadata.
|
|
733
|
+
*
|
|
734
|
+
* @returns Array of all resolved items
|
|
735
|
+
*
|
|
736
|
+
* @example
|
|
737
|
+
* ```typescript
|
|
738
|
+
* const items = cache.values();
|
|
739
|
+
* items.forEach(({ key, value }) => {
|
|
740
|
+
* if (value.Ok) {
|
|
741
|
+
* console.log(key, value.unwrap());
|
|
742
|
+
* } else {
|
|
743
|
+
* console.error(key, value.unwrapErr());
|
|
744
|
+
* }
|
|
745
|
+
* });
|
|
746
|
+
* ```
|
|
747
|
+
*/
|
|
748
|
+
values(): KeyedResolveOnceItem<K, T, CTX>[] {
|
|
749
|
+
return this._keyed
|
|
750
|
+
.values()
|
|
751
|
+
.filter((i) => i.value.ready)
|
|
752
|
+
.map((item) => ({
|
|
753
|
+
key: item.givenKey,
|
|
754
|
+
value: item.value.error ? Result.Err<T>(item.value.error) : Result.Ok<T>(item.value.value as T),
|
|
755
|
+
item,
|
|
756
|
+
}));
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Registers a callback that fires when a new ResolveOnce instance is created.
|
|
761
|
+
*
|
|
762
|
+
* @param fn - Callback receiving the key and ResolveOnce instance
|
|
763
|
+
* @returns Unregister function
|
|
764
|
+
*/
|
|
765
|
+
onSet(fn: (key: K, value: ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>) => void): UnregFn {
|
|
766
|
+
return this._keyed.onSet((item) => {
|
|
767
|
+
fn(item.givenKey, item.value);
|
|
768
|
+
});
|
|
417
769
|
}
|
|
418
770
|
|
|
419
|
-
|
|
420
|
-
|
|
771
|
+
/**
|
|
772
|
+
* Registers a callback that fires when a ResolveOnce instance is deleted.
|
|
773
|
+
*
|
|
774
|
+
* @param fn - Callback receiving the key and ResolveOnce instance
|
|
775
|
+
* @returns Unregister function
|
|
776
|
+
*/
|
|
777
|
+
onDelete(fn: (key: K, value: ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>) => void): UnregFn {
|
|
778
|
+
return this._keyed.onDelete((item) => {
|
|
779
|
+
fn(item.givenKey, item.value);
|
|
780
|
+
});
|
|
421
781
|
}
|
|
422
782
|
|
|
423
|
-
|
|
424
|
-
|
|
783
|
+
/**
|
|
784
|
+
* Updates the LRU parameters dynamically.
|
|
785
|
+
*
|
|
786
|
+
* @param params - New LRU parameters
|
|
787
|
+
*/
|
|
788
|
+
setParam(params: Partial<AddKeyedParam<K, ResolveOnce<T, CTX>, CTX>>): void {
|
|
789
|
+
this._keyed.setParam({ lru: params.lru });
|
|
425
790
|
}
|
|
426
791
|
|
|
427
|
-
|
|
428
|
-
|
|
792
|
+
/**
|
|
793
|
+
* Asynchronously gets or creates a ResolveOnce for a key resolved from a promise.
|
|
794
|
+
*
|
|
795
|
+
* @param key - Function returning a promise that resolves to the key
|
|
796
|
+
* @returns Promise resolving to the ResolveOnce instance
|
|
797
|
+
*/
|
|
798
|
+
asyncGet(key: () => Promise<K>): Promise<ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>> {
|
|
799
|
+
return this._keyed.asyncGet(key);
|
|
429
800
|
}
|
|
430
801
|
|
|
431
|
-
|
|
802
|
+
/**
|
|
803
|
+
* Gets or creates a ResolveOnce instance for the given key.
|
|
804
|
+
*
|
|
805
|
+
* This is the primary method for accessing ResolveOnce instances. Each unique
|
|
806
|
+
* key gets its own instance that persists across calls.
|
|
807
|
+
*
|
|
808
|
+
* @param key - The key or function returning the key
|
|
809
|
+
* @param ctx - Optional context override for this operation
|
|
810
|
+
* @returns The ResolveOnce instance for this key
|
|
811
|
+
*
|
|
812
|
+
* @example
|
|
813
|
+
* ```typescript
|
|
814
|
+
* const result = cache.get('myKey').once(({ refKey, givenKey, ctx }) => {
|
|
815
|
+
* return computeValue(givenKey, ctx);
|
|
816
|
+
* });
|
|
817
|
+
* ```
|
|
818
|
+
*/
|
|
819
|
+
get(key: K | (() => K), ctx?: CTX): ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>> {
|
|
432
820
|
if (typeof key === "function") {
|
|
433
821
|
key = (key as () => K)();
|
|
434
822
|
}
|
|
435
|
-
|
|
436
|
-
if (!keyed) {
|
|
437
|
-
keyed = this.factory({ ...this.#ctx, key: key });
|
|
438
|
-
this._map.set(key, keyed);
|
|
439
|
-
}
|
|
440
|
-
return keyed;
|
|
823
|
+
return this._keyed.getItem(key, ctx).value;
|
|
441
824
|
}
|
|
442
825
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
826
|
+
/**
|
|
827
|
+
* Gets or creates the complete KeyedNgItem for a key.
|
|
828
|
+
*
|
|
829
|
+
* Useful when you need access to the full item structure including metadata.
|
|
830
|
+
*
|
|
831
|
+
* @param key - The key to get
|
|
832
|
+
* @param ctx - Optional context override
|
|
833
|
+
* @returns The complete KeyedNgItem
|
|
834
|
+
*/
|
|
835
|
+
getItem(key: K, ctx?: CTX): KeyedNgItem<K, ResolveOnce<T, KeyedNgItemWithoutValue<K, CTX>>, CTX> {
|
|
836
|
+
return this._keyed.getItem(key, ctx);
|
|
448
837
|
}
|
|
449
838
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
839
|
+
/**
|
|
840
|
+
* Checks if a key exists in the collection.
|
|
841
|
+
*
|
|
842
|
+
* @param key - The key or function returning the key
|
|
843
|
+
* @returns True if the key exists
|
|
844
|
+
*/
|
|
845
|
+
has(key: K | (() => K)): boolean {
|
|
846
|
+
return this._keyed.has(key);
|
|
847
|
+
}
|
|
453
848
|
|
|
849
|
+
/**
|
|
850
|
+
* Deletes an entry from the collection.
|
|
851
|
+
*
|
|
852
|
+
* Triggers onDelete callbacks before removal.
|
|
853
|
+
*
|
|
854
|
+
* @param key - The key to delete
|
|
855
|
+
*/
|
|
454
856
|
delete(key: K): void {
|
|
455
|
-
this.
|
|
857
|
+
this._keyed.delete(key);
|
|
456
858
|
}
|
|
457
859
|
|
|
860
|
+
/**
|
|
861
|
+
* Resets and removes an entry from the collection.
|
|
862
|
+
*
|
|
863
|
+
* Calls the optional reset() method on the value before deletion,
|
|
864
|
+
* allowing for cleanup operations.
|
|
865
|
+
*
|
|
866
|
+
* @param key - The key to reset and delete
|
|
867
|
+
*/
|
|
458
868
|
unget(key: K): void {
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
this.
|
|
869
|
+
const item = this._keyed.getItem(key);
|
|
870
|
+
item.value.reset?.();
|
|
871
|
+
return this._keyed.delete(item.givenKey);
|
|
462
872
|
}
|
|
463
873
|
|
|
874
|
+
/**
|
|
875
|
+
* Resets all entries by calling their optional reset() methods.
|
|
876
|
+
*
|
|
877
|
+
* Does not remove entries from the collection, only resets their state.
|
|
878
|
+
* Useful for cleanup without losing the collection structure.
|
|
879
|
+
*/
|
|
464
880
|
reset(): void {
|
|
465
|
-
|
|
466
|
-
|
|
881
|
+
for (const v of this._keyed.values()) {
|
|
882
|
+
v.value.reset?.();
|
|
883
|
+
}
|
|
467
884
|
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
export interface KeyItem<K, V> {
|
|
471
|
-
readonly key: K;
|
|
472
|
-
readonly value: Result<V>;
|
|
473
|
-
}
|
|
474
885
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
886
|
+
/**
|
|
887
|
+
* Iterates over all completed entries, yielding key-result pairs.
|
|
888
|
+
*
|
|
889
|
+
* Only yields entries that have been resolved (ready state).
|
|
890
|
+
* Values are wrapped in Result to distinguish success from error.
|
|
891
|
+
*
|
|
892
|
+
* @param fn - Callback receiving KeyItem and index
|
|
893
|
+
*
|
|
894
|
+
* @example
|
|
895
|
+
* ```typescript
|
|
896
|
+
* cache.forEach((item, idx) => {
|
|
897
|
+
* console.log(idx, item.key);
|
|
898
|
+
* if (item.value.Ok) {
|
|
899
|
+
* console.log('Success:', item.value.unwrap());
|
|
900
|
+
* } else {
|
|
901
|
+
* console.error('Error:', item.value.unwrapErr());
|
|
902
|
+
* }
|
|
903
|
+
* });
|
|
904
|
+
* ```
|
|
905
|
+
*/
|
|
906
|
+
forEach(fn: (ki: KeyItem<K, T>, idx: number) => void): void {
|
|
907
|
+
for (const [item, idx] of this._keyed.entries()) {
|
|
908
|
+
const v = item.value;
|
|
909
|
+
const k = item.givenKey;
|
|
910
|
+
if (!v.ready) {
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
if (v.error) {
|
|
914
|
+
fn({ key: k, value: Result.Err<T>(v.error) }, idx);
|
|
915
|
+
} else {
|
|
916
|
+
fn({ key: k, value: Result.Ok<T>(v.value as T) }, idx);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
483
919
|
}
|
|
484
920
|
|
|
485
|
-
|
|
486
|
-
|
|
921
|
+
/**
|
|
922
|
+
* Returns an iterable of all completed entries.
|
|
923
|
+
*
|
|
924
|
+
* Only yields entries that have been resolved. Values are wrapped in Result.
|
|
925
|
+
*
|
|
926
|
+
* @returns Iterable of KeyItem entries
|
|
927
|
+
*
|
|
928
|
+
* @example
|
|
929
|
+
* ```typescript
|
|
930
|
+
* for (const item of cache.entries()) {
|
|
931
|
+
* console.log(item.key, item.value.Ok);
|
|
932
|
+
* }
|
|
933
|
+
* ```
|
|
934
|
+
*/
|
|
935
|
+
*entries(): Iterable<KeyItem<K, T>> {
|
|
936
|
+
/* this is not optimal, but sufficient for now */
|
|
937
|
+
for (const [item] of this._keyed.entries()) {
|
|
938
|
+
const v = item.value;
|
|
939
|
+
const k = item.givenKey;
|
|
487
940
|
if (!v.ready) {
|
|
488
941
|
continue;
|
|
489
942
|
}
|
|
@@ -494,29 +947,58 @@ export class KeyedResolvOnce<T, K = string, CTX extends NonNullable<object> = ob
|
|
|
494
947
|
}
|
|
495
948
|
}
|
|
496
949
|
}
|
|
950
|
+
}
|
|
497
951
|
|
|
952
|
+
/**
|
|
953
|
+
* Keyed collection of ResolveSeq instances.
|
|
954
|
+
*
|
|
955
|
+
* Manages a map of ResolveSeq instances indexed by keys, with optional LRU caching.
|
|
956
|
+
* Each key gets its own ResolveSeq instance for sequential execution of operations.
|
|
957
|
+
*
|
|
958
|
+
* @template VALUEType - The return type of the ResolveSeq instances
|
|
959
|
+
* @template KEYType - The key type
|
|
960
|
+
* @template CTX - Optional context type
|
|
961
|
+
*
|
|
962
|
+
* @example
|
|
963
|
+
* ```typescript
|
|
964
|
+
* const sequences = new KeyedResolvSeq<number, string>();
|
|
965
|
+
*
|
|
966
|
+
* // Each key gets its own sequential executor
|
|
967
|
+
* sequences.get('user1').add(() => updateUser1());
|
|
968
|
+
* sequences.get('user2').add(() => updateUser2());
|
|
969
|
+
* ```
|
|
970
|
+
*/
|
|
971
|
+
export class KeyedResolvSeq<
|
|
972
|
+
VALUEType extends NonNullable<unknown>,
|
|
973
|
+
KEYType = string,
|
|
974
|
+
CTX extends NonNullable<object> = object,
|
|
975
|
+
> extends KeyedNg<KEYType, ResolveSeq<VALUEType, KeyedNgItemWithoutValue<KEYType, CTX>>, CTX> {
|
|
498
976
|
/**
|
|
977
|
+
* Creates a new KeyedResolvSeq instance.
|
|
499
978
|
*
|
|
500
|
-
* @
|
|
979
|
+
* @param kp - Configuration options (key2string, ctx, lru)
|
|
501
980
|
*/
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
super((ctx) => new ResolveSeq<T, AddKey<CTX, K>>(ctx), kp);
|
|
981
|
+
constructor(kp: Partial<Omit<KeyedNgOptions<KEYType, VALUEType, CTX>, "createValue">> = {}) {
|
|
982
|
+
super({
|
|
983
|
+
createValue: (
|
|
984
|
+
item: KeyedNgItem<KEYType, ResolveSeq<VALUEType, KeyedNgItemWithoutValue<KEYType, CTX>>, CTX>,
|
|
985
|
+
): ResolveSeq<VALUEType, KeyedNgItemWithoutValue<KEYType, CTX>> => {
|
|
986
|
+
return new ResolveSeq<VALUEType, KeyedNgItemWithoutValue<KEYType, CTX>>({
|
|
987
|
+
...item,
|
|
988
|
+
ctx: kp.ctx ?? item.ctx,
|
|
989
|
+
});
|
|
990
|
+
},
|
|
991
|
+
key2string: kp.key2string,
|
|
992
|
+
ctx: kp.ctx as CTX,
|
|
993
|
+
lru: kp.lru,
|
|
994
|
+
});
|
|
517
995
|
}
|
|
518
996
|
}
|
|
519
997
|
|
|
998
|
+
/**
|
|
999
|
+
* Internal helper class for the Lazy function.
|
|
1000
|
+
* @internal
|
|
1001
|
+
*/
|
|
520
1002
|
class LazyContainer<T> {
|
|
521
1003
|
readonly resolveOnce = new ResolveOnce<T>();
|
|
522
1004
|
|
|
@@ -526,8 +1008,29 @@ class LazyContainer<T> {
|
|
|
526
1008
|
}
|
|
527
1009
|
}
|
|
528
1010
|
|
|
529
|
-
|
|
530
|
-
|
|
1011
|
+
/**
|
|
1012
|
+
* Creates a lazy-evaluated version of a function that executes only once and caches the result.
|
|
1013
|
+
*
|
|
1014
|
+
* The returned function will execute the original function on first call and return
|
|
1015
|
+
* the cached result for all subsequent calls, regardless of arguments. This is useful
|
|
1016
|
+
* for expensive computations or resource initialization.
|
|
1017
|
+
*
|
|
1018
|
+
* @template Args - The argument types of the function
|
|
1019
|
+
* @template Return - The return type of the function
|
|
1020
|
+
* @param fn - The function to make lazy
|
|
1021
|
+
* @returns A wrapped function that executes once and caches the result
|
|
1022
|
+
*
|
|
1023
|
+
* @example
|
|
1024
|
+
* ```typescript
|
|
1025
|
+
* const getConfig = Lazy(() => {
|
|
1026
|
+
* console.log('Loading config...');
|
|
1027
|
+
* return { apiKey: 'secret' };
|
|
1028
|
+
* });
|
|
1029
|
+
*
|
|
1030
|
+
* getConfig(); // Logs "Loading config..." and returns config
|
|
1031
|
+
* getConfig(); // Returns cached config without logging
|
|
1032
|
+
* ```
|
|
1033
|
+
*/
|
|
531
1034
|
export function Lazy<Args extends readonly unknown[], Return>(fn: (...args: Args) => Return): (...args: Args) => Return {
|
|
532
1035
|
const lazy = new LazyContainer<Return>();
|
|
533
1036
|
return lazy.call(fn);
|