Add comprehensive installation and setup documentation

- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
This commit is contained in:
Dorian
2026-01-27 17:18:21 +00:00
parent a81f655133
commit 0d073fa89e
22658 changed files with 4494151 additions and 6 deletions

View File

@@ -0,0 +1,78 @@
# it-queueless-pushable
[![codecov](https://img.shields.io/codecov/c/github/achingbrain/it.svg?style=flat-square)](https://codecov.io/gh/achingbrain/it)
[![CI](https://img.shields.io/github/actions/workflow/status/achingbrain/it/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/achingbrain/it/actions/workflows/js-test-and-release.yml?query=branch%3Amain)
> A pushable queue that waits until a value is consumed before accepting another
# About
<!--
!IMPORTANT!
Everything in this README between "# About" and "# Install" is automatically
generated and will be overwritten the next time the doc generator is run.
To make changes to this section, please update the @packageDocumentation section
of src/index.js or src/index.ts
To experiment with formatting, please run "npm run docs" from the root of this
repo and examine the changes made.
-->
A pushable async generator that waits until the current value is consumed
before allowing a new value to be pushed.
Useful for when you don't want to keep memory usage under control and/or
allow a downstream consumer to dictate how fast data flows through a pipe,
but you want to be able to apply a transform to that data.
## Example
```typescript
import { queuelessPushable } from 'it-queueless-pushable'
const pushable = queuelessPushable<string>()
// run asynchronously
Promise.resolve().then(async () => {
// push a value - the returned promise will not resolve until the value is
// read from the pushable
await pushable.push('hello')
})
// read a value
const result = await pushable.next()
console.info(result) // { done: false, value: 'hello' }
```
# Install
```console
$ npm i it-queueless-pushable
```
## Browser `<script>` tag
Loading this module through a script tag will make its exports available as `ItQueuelessPushable` in the global namespace.
```html
<script src="https://unpkg.com/it-queueless-pushable/dist/index.min.js"></script>
```
# API Docs
- <https://achingbrain.github.io/it/modules/it_queueless_pushable.html>
# License
Licensed under either of
- Apache 2.0, ([LICENSE-APACHE](https://github.com/achingbrain/it/blob/main/packages/it-queueless-pushable/LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT ([LICENSE-MIT](https://github.com/achingbrain/it/blob/main/packages/it-queueless-pushable/LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
# Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

View File

@@ -0,0 +1,4 @@
(function (root, factory) {(typeof module === 'object' && module.exports) ? module.exports = factory() : root.ItQueuelessPushable = factory()}(typeof self !== 'undefined' ? self : this, function () {
"use strict";var ItQueuelessPushable=(()=>{var a=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var x=(t,e)=>{for(var r in e)a(t,r,{get:e[r],enumerable:!0})},f=(t,e,r,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of d(e))!c.call(t,n)&&n!==r&&a(t,n,{get:()=>e[n],enumerable:!(i=h(e,n))||i.enumerable});return t};var v=t=>f(a({},"__esModule",{value:!0}),t);var N={};x(N,{queuelessPushable:()=>p});function s(){let t={};return t.promise=new Promise((e,r)=>{t.resolve=e,t.reject=r}),t}function w(t){return t.reason}async function l(t,e,r){if(e==null)return t;let i=r?.translateError??w;if(e.aborted)return t.catch(()=>{}),Promise.reject(i(e));let n;try{return await Promise.race([t,new Promise((m,o)=>{n=()=>{o(i(e))},e.addEventListener("abort",n)})])}finally{n!=null&&e.removeEventListener("abort",n)}}var u=class{readNext;haveNext;ended;nextResult;error;constructor(){this.ended=!1,this.readNext=s(),this.haveNext=s()}[Symbol.asyncIterator](){return this}async next(){if(this.nextResult==null&&await this.haveNext.promise,this.nextResult==null)throw new Error("HaveNext promise resolved but nextResult was undefined");let e=this.nextResult;return this.nextResult=void 0,this.readNext.resolve(),this.readNext=s(),e}async throw(e){return this.ended=!0,this.error=e,e!=null&&(this.haveNext.promise.catch(()=>{}),this.haveNext.reject(e)),{done:!0,value:void 0}}async return(){let e={done:!0,value:void 0};return this.ended=!0,this.nextResult=e,this.haveNext.resolve(),e}async push(e,r){await this._push(e,r)}async end(e,r){e!=null?await this.throw(e):await this._push(void 0,r)}async _push(e,r){if(e!=null&&this.ended)throw this.error??new Error("Cannot push value onto an ended pushable");for(;this.nextResult!=null;)await this.readNext.promise;e!=null?this.nextResult={done:!1,value:e}:(this.ended=!0,this.nextResult={done:!0,value:void 0}),this.haveNext.resolve(),this.haveNext=s(),await l(this.readNext.promise,r?.signal,r)}};function p(){return new u}return v(N);})();
return ItQueuelessPushable}));
//# sourceMappingURL=index.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,46 @@
/**
* @packageDocumentation
*
* A pushable async generator that waits until the current value is consumed
* before allowing a new value to be pushed.
*
* Useful for when you don't want to keep memory usage under control and/or
* allow a downstream consumer to dictate how fast data flows through a pipe,
* but you want to be able to apply a transform to that data.
*
* @example
*
* ```typescript
* import { queuelessPushable } from 'it-queueless-pushable'
*
* const pushable = queuelessPushable<string>()
*
* // run asynchronously
* Promise.resolve().then(async () => {
* // push a value - the returned promise will not resolve until the value is
* // read from the pushable
* await pushable.push('hello')
* })
*
* // read a value
* const result = await pushable.next()
* console.info(result) // { done: false, value: 'hello' }
* ```
*/
import type { AbortOptions } from 'abort-error';
import type { RaceSignalOptions } from 'race-signal';
export interface Pushable<T> extends AsyncGenerator<T, void, unknown> {
/**
* End the iterable after all values in the buffer (if any) have been yielded. If an
* error is passed the buffer is cleared immediately and the next iteration will
* throw the passed error
*/
end(err?: Error, options?: AbortOptions & RaceSignalOptions): Promise<void>;
/**
* Push a value into the iterable. Values are yielded from the iterable in the order
* they are pushed. Values not yet consumed from the iterable are buffered.
*/
push(value: T, options?: AbortOptions & RaceSignalOptions): Promise<void>;
}
export declare function queuelessPushable<T>(): Pushable<T>;
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,MAAM,WAAW,QAAQ,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;IACnE;;;;OAIG;IACH,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAE3E;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1E;AAsHD,wBAAgB,iBAAiB,CAAE,CAAC,KAAM,QAAQ,CAAC,CAAC,CAAC,CAEpD"}

View File

@@ -0,0 +1,125 @@
/**
* @packageDocumentation
*
* A pushable async generator that waits until the current value is consumed
* before allowing a new value to be pushed.
*
* Useful for when you don't want to keep memory usage under control and/or
* allow a downstream consumer to dictate how fast data flows through a pipe,
* but you want to be able to apply a transform to that data.
*
* @example
*
* ```typescript
* import { queuelessPushable } from 'it-queueless-pushable'
*
* const pushable = queuelessPushable<string>()
*
* // run asynchronously
* Promise.resolve().then(async () => {
* // push a value - the returned promise will not resolve until the value is
* // read from the pushable
* await pushable.push('hello')
* })
*
* // read a value
* const result = await pushable.next()
* console.info(result) // { done: false, value: 'hello' }
* ```
*/
import deferred from 'p-defer';
import { raceSignal } from 'race-signal';
class QueuelessPushable {
readNext;
haveNext;
ended;
nextResult;
error;
constructor() {
this.ended = false;
this.readNext = deferred();
this.haveNext = deferred();
}
[Symbol.asyncIterator]() {
return this;
}
async next() {
if (this.nextResult == null) {
// wait for the supplier to push a value
await this.haveNext.promise;
}
if (this.nextResult == null) {
throw new Error('HaveNext promise resolved but nextResult was undefined');
}
const nextResult = this.nextResult;
this.nextResult = undefined;
// signal to the supplier that we read the value
this.readNext.resolve();
this.readNext = deferred();
return nextResult;
}
async throw(err) {
this.ended = true;
this.error = err;
if (err != null) {
// this can cause unhandled promise rejections if nothing is awaiting the
// next value so attach a dummy catch listener to the promise
this.haveNext.promise.catch(() => { });
this.haveNext.reject(err);
}
const result = {
done: true,
value: undefined
};
return result;
}
async return() {
const result = {
done: true,
value: undefined
};
this.ended = true;
this.nextResult = result;
// let the consumer know we have a new value
this.haveNext.resolve();
return result;
}
async push(value, options) {
await this._push(value, options);
}
async end(err, options) {
if (err != null) {
await this.throw(err);
}
else {
// abortable return
await this._push(undefined, options);
}
}
async _push(value, options) {
if (value != null && this.ended) {
throw this.error ?? new Error('Cannot push value onto an ended pushable');
}
// wait for all values to be read
while (this.nextResult != null) {
await this.readNext.promise;
}
if (value != null) {
this.nextResult = { done: false, value };
}
else {
this.ended = true;
this.nextResult = { done: true, value: undefined };
}
// let the consumer know we have a new value
this.haveNext.resolve();
this.haveNext = deferred();
// wait for the consumer to have finished processing the value and requested
// the next one or for the passed signal to abort the waiting
await raceSignal(this.readNext.promise, options?.signal, options);
}
}
export function queuelessPushable() {
return new QueuelessPushable();
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,150 @@
{
"name": "it-queueless-pushable",
"version": "2.0.3",
"description": "A pushable queue that waits until a value is consumed before accepting another",
"author": "Alex Potsides <alex@achingbrain.net>",
"license": "Apache-2.0 OR MIT",
"homepage": "https://github.com/achingbrain/it/tree/main/packages/it-queueless-pushable#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/achingbrain/it.git"
},
"bugs": {
"url": "https://github.com/achingbrain/it/issues"
},
"publishConfig": {
"access": "public",
"provenance": true
},
"type": "module",
"types": "./dist/src/index.d.ts",
"files": [
"src",
"dist",
"!dist/test",
"!**/*.tsbuildinfo"
],
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"import": "./dist/src/index.js"
}
},
"release": {
"branches": [
"main"
],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits",
"releaseRules": [
{
"breaking": true,
"release": "major"
},
{
"revert": true,
"release": "patch"
},
{
"type": "feat",
"release": "minor"
},
{
"type": "fix",
"release": "patch"
},
{
"type": "docs",
"release": "patch"
},
{
"type": "test",
"release": "patch"
},
{
"type": "deps",
"release": "patch"
},
{
"scope": "no-release",
"release": false
}
]
}
],
[
"@semantic-release/release-notes-generator",
{
"preset": "conventionalcommits",
"presetConfig": {
"types": [
{
"type": "feat",
"section": "Features"
},
{
"type": "fix",
"section": "Bug Fixes"
},
{
"type": "chore",
"section": "Trivial Changes"
},
{
"type": "docs",
"section": "Documentation"
},
{
"type": "deps",
"section": "Dependencies"
},
{
"type": "test",
"section": "Tests"
}
]
}
}
],
"@semantic-release/changelog",
"@semantic-release/npm",
"@semantic-release/github",
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md",
"package.json"
]
}
]
]
},
"scripts": {
"build": "aegir build",
"lint": "aegir lint",
"dep-check": "aegir dep-check",
"clean": "aegir clean",
"test": "aegir test",
"test:node": "aegir test -t node --cov",
"test:chrome": "aegir test -t browser --cov",
"test:chrome-webworker": "aegir test -t webworker",
"test:firefox": "aegir test -t browser -- --browser firefox",
"test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
"release": "aegir release"
},
"dependencies": {
"abort-error": "^1.0.1",
"p-defer": "^4.0.1",
"race-signal": "^2.0.0"
},
"devDependencies": {
"aegir": "^47.0.16",
"delay": "^7.0.0",
"it-all": "^3.0.0",
"it-drain": "^3.0.0"
}
}

View File

@@ -0,0 +1,169 @@
/**
* @packageDocumentation
*
* A pushable async generator that waits until the current value is consumed
* before allowing a new value to be pushed.
*
* Useful for when you don't want to keep memory usage under control and/or
* allow a downstream consumer to dictate how fast data flows through a pipe,
* but you want to be able to apply a transform to that data.
*
* @example
*
* ```typescript
* import { queuelessPushable } from 'it-queueless-pushable'
*
* const pushable = queuelessPushable<string>()
*
* // run asynchronously
* Promise.resolve().then(async () => {
* // push a value - the returned promise will not resolve until the value is
* // read from the pushable
* await pushable.push('hello')
* })
*
* // read a value
* const result = await pushable.next()
* console.info(result) // { done: false, value: 'hello' }
* ```
*/
import deferred from 'p-defer'
import { raceSignal } from 'race-signal'
import type { AbortOptions } from 'abort-error'
import type { RaceSignalOptions } from 'race-signal'
export interface Pushable<T> extends AsyncGenerator<T, void, unknown> {
/**
* End the iterable after all values in the buffer (if any) have been yielded. If an
* error is passed the buffer is cleared immediately and the next iteration will
* throw the passed error
*/
end(err?: Error, options?: AbortOptions & RaceSignalOptions): Promise<void>
/**
* Push a value into the iterable. Values are yielded from the iterable in the order
* they are pushed. Values not yet consumed from the iterable are buffered.
*/
push(value: T, options?: AbortOptions & RaceSignalOptions): Promise<void>
}
class QueuelessPushable <T> implements Pushable<T> {
private readNext: PromiseWithResolvers<void>
private haveNext: PromiseWithResolvers<void>
private ended: boolean
private nextResult: IteratorResult<T> | undefined
private error?: Error
constructor () {
this.ended = false
this.readNext = deferred()
this.haveNext = deferred()
}
[Symbol.asyncIterator] (): AsyncGenerator<T, void, unknown> {
return this
}
async next (): Promise<IteratorResult<T, void>> {
if (this.nextResult == null) {
// wait for the supplier to push a value
await this.haveNext.promise
}
if (this.nextResult == null) {
throw new Error('HaveNext promise resolved but nextResult was undefined')
}
const nextResult = this.nextResult
this.nextResult = undefined
// signal to the supplier that we read the value
this.readNext.resolve()
this.readNext = deferred()
return nextResult
}
async throw (err?: Error): Promise<IteratorReturnResult<undefined>> {
this.ended = true
this.error = err
if (err != null) {
// this can cause unhandled promise rejections if nothing is awaiting the
// next value so attach a dummy catch listener to the promise
this.haveNext.promise.catch(() => {})
this.haveNext.reject(err)
}
const result: IteratorReturnResult<undefined> = {
done: true,
value: undefined
}
return result
}
async return (): Promise<IteratorResult<T>> {
const result: IteratorReturnResult<undefined> = {
done: true,
value: undefined
}
this.ended = true
this.nextResult = result
// let the consumer know we have a new value
this.haveNext.resolve()
return result
}
async push (value: T, options?: AbortOptions & RaceSignalOptions): Promise<void> {
await this._push(value, options)
}
async end (err?: Error, options?: AbortOptions & RaceSignalOptions): Promise<void> {
if (err != null) {
await this.throw(err)
} else {
// abortable return
await this._push(undefined, options)
}
}
private async _push (value?: T, options?: AbortOptions & RaceSignalOptions): Promise<void> {
if (value != null && this.ended) {
throw this.error ?? new Error('Cannot push value onto an ended pushable')
}
// wait for all values to be read
while (this.nextResult != null) {
await this.readNext.promise
}
if (value != null) {
this.nextResult = { done: false, value }
} else {
this.ended = true
this.nextResult = { done: true, value: undefined }
}
// let the consumer know we have a new value
this.haveNext.resolve()
this.haveNext = deferred()
// wait for the consumer to have finished processing the value and requested
// the next one or for the passed signal to abort the waiting
await raceSignal(
this.readNext.promise,
options?.signal,
options
)
}
}
export function queuelessPushable <T> (): Pushable<T> {
return new QueuelessPushable<T>()
}