{"id":16185508,"url":"https://github.com/patrickhulce/asyncronaut","last_synced_at":"2025-04-07T13:15:37.978Z","repository":{"id":163768317,"uuid":"639108175","full_name":"patrickhulce/asyncronaut","owner":"patrickhulce","description":"A collection of modules for working with common async tasks in node and the browser.","archived":false,"fork":false,"pushed_at":"2023-07-10T15:35:25.000Z","size":837,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-19T00:49:09.658Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://patrickhulce.github.io/asyncronaut/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/patrickhulce.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-10T19:24:29.000Z","updated_at":"2024-01-10T16:32:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"3057d75d-e4d5-49c4-abac-9b104f7ffd69","html_url":"https://github.com/patrickhulce/asyncronaut","commit_stats":{"total_commits":63,"total_committers":1,"mean_commits":63.0,"dds":0.0,"last_synced_commit":"14a327747c39ba70dad0f1d95c6ddf3cc3bce08a"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickhulce%2Fasyncronaut","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickhulce%2Fasyncronaut/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickhulce%2Fasyncronaut/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patrickhulce%2Fasyncronaut/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patrickhulce","download_url":"https://codeload.github.com/patrickhulce/asyncronaut/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247657266,"owners_count":20974345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T07:14:28.261Z","updated_at":"2025-04-07T13:15:37.955Z","avatar_url":"https://github.com/patrickhulce.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# asyncronaut\n\nAsyncronaut is a hodgepodge of utilities to make working with common asynchronous tasks in JavaScript easier. It provides interfaces to effectively manage promises, task queues, pools, and streams, with advanced features like signal-based cancellation and discrete poll smoothing, retry, inspection and more.\n\nFor detailed usage and configuration options, please refer to the [official `asyncronaut` documentation](https://patrickhulce.github.io/asyncronaut/).\n\n## Installation\n\n```bash\nnpm i asyncronaut\n```\n\n## Usage\n\n### Promises\n\n```javascript\nimport {\n  delay,\n  withTimeout,\n  withRetry,\n  withInspection,\n  createDecomposedPromise,\n  flushAllMicrotasks,\n} from 'asyncronaut';\n```\n\n#### `withTimeout`\n\nAdds timeout management to an existing promise that respects existing abortController signals.\n\n```javascript\nimport {withTimeout} from 'asyncronaut/promises';\n\n// Create an AbortController\nconst abortController = new AbortController();\n\n// Link the abort controller to the promise and the timeout.\nconst fetchWithTimeout = withTimeout(\n  fetch('https://api.mysite.com/long', {signal: abortController.signal}),\n  {\n    timeoutMs: 3000,\n    abortController,\n  }\n);\n\nfetchWithTimeout.catch((error) =\u003e {\n  // The request will automatically be cancelled when timeout hits.\n  console.log('Request timed out');\n});\n```\n\n#### `createDecomposedPromise`\n\nCreates a promise with exposed resolve and reject methods.\n\n```javascript\nconst {promise, resolve, reject} = createDecomposedPromise();\nstream.on('error', reject);\nstream.on('close', resolve);\nreturn promise;\n```\n\n#### `withRetry`\n\nRetries a promise-returning function in case of failure.\n\n```javascript\nconst action = () =\u003e fetch('https://api.mysite.com/data');\nconst actionWithRetry = withRetry(action, {\n  retries: 3,\n  cleanup: () =\u003e fetch('https://api.mysite.com/reset'),\n});\n```\n\n#### `flushAllMicrotasks`\n\nFlushes all pending microtasks from the queue.\n\nUse case: In testing scenarios, we can ensure all microtasks are completed before asserting the test outcomes.\n\n```javascript\ntest('all microtasks are flushed', async () =\u003e {\n  // trigger some microtasks\n  Promise.resolve().then(() =\u003e console.log('Microtask completed'));\n  // flush all microtasks\n  await flushAllMicrotasks();\n  // Now we can assert the outcomes\n});\n```\n\n#### `withInspection`\n\nAugments a promise to enable synchronous inspection of its state.\n\n```javascript\nconst promise = fetch('https://api.mysite.com/data');\nconst inspectablePromise = withInspection(promise);\n\nawait delay(1_000);\n\nif (!inspectablePromise.isDone()) {\n  // Fetch is still pending after 1 second.\n}\n```\n\n### Task Queue\n\n```javascript\nimport {TaskQueue} from 'asyncronaut';\n```\n\n#### TaskQueue\n\nCreates a task queue with configurable concurrency and lifecycle events.\n\n```javascript\n// Task processing function\nconst onTask = async (task) =\u003e {\n  const {id, request, signal} = task;\n  console.log(`Processing task: ${id}`);\n  const response = await fetch(request.input);\n  return response.json();\n};\n\nconst taskQueue = new TaskQueue({onTask, maxConcurrentTasks: 5});\n// In case of an error, destroy the queue...\ntaskQueue.on('error', (err) =\u003e taskQueue.drain());\n\nfor (let i = 0; i \u003c 10; i++) {\n  taskQueue.enqueue(`https://api.mysite.com/resource/${i}`);\n}\n\n// Start processing tasks...\ntaskQueue.start();\n\n// Later on...\ntaskQueue.pause();\n\n// And later still...\ntaskQueue.start();\n\n// Wait for all tasks in the queue to finish...\nawait taskQueue.waitForCompletion();\n```\n\n### Streams\n\n```javascript\nimport {\n  fromNode,\n  createSmoothStreamViaPoll,\n  CHARACTER_SMOOTH_STREAM_OPTIONS,\n} from 'asyncronaut/streams/web';\n```\n\n#### `fromNode`\n\nConverts a Node.js readable stream to a web readable stream.\n\n```javascript\nconst nodeStream = fs.createReadStream('/path/to/file');\nconst webStream = fromNode(nodeStream);\n```\n\n#### `createSmoothStreamViaPoll`\n\nCreates a smooth stream of data fetched from a poll-based fetcher.\n\nUse case: Continuously fetching state updates from a remote server and streaming them to the client. This could be used to create a real-time dashboard or live-updating visual display.\n\n```javascript\nimport {createSmoothStreamViaPoll, CHARACTER_SMOOTH_STREAM_OPTIONS} from 'asyncronaut/streams/web';\n\nconst options = {\n  ...CHARACTER_SMOOTH_STREAM_OPTIONS,\n  poll: async () =\u003e {\n    // Fetch some text from a server\n    const response = await fetch('https://api.mysite.com/text');\n    const text = await response.text();\n    return {\n      state: text,\n      isDone: false, // or some condition to indicate completion\n    };\n  },\n};\n\nconst textStream = createSmoothStreamViaPoll(options);\n\n// Use smoothStream in a context expecting a web ReadableStream\n```\n\n## License\n\nAsyncronaut is [MIT licensed](https://opensource.org/license/mit/).\n\n# Contributing to Asyncronaut\n\nWe welcome contributions from everyone. This section will guide you through the initial setup and the contribution process.\n\n## Prerequisites\n\nYou should have Node.js and npm installed on your system. We cross-publish our packages in CommonJS and ES Modules formats. Please note that we do not use ESM for Express dependencies due to compatibility issues.\n\n## Getting Started\n\n1. Clone the repository:\n\n   ```bash\n   git clone https://github.com/patrickhulce/asyncronaut.git\n   cd asyncronaut\n   ```\n\n2. Install the dependencies:\n\n   ```bash\n   npm install\n   ```\n\n3. Build the project:\n\n   ```bash\n   npm run build\n   ```\n\n   This will generate the TypeScript declaration files and build the project.\n\n## Coding Style\n\nWe enforce a consistent coding style using ESLint for TypeScript, along with Prettier for code formatting. We strongly recommend you install these tools in your code editor before you begin. Our configuration will automatically apply our coding standards.\n\n## Running Tests\n\nWe use Jest for unit testing. To run the tests:\n\n```bash\nnpm test\n```\n\nThis command will lint the code, check types, and then run all unit tests. If you prefer, you can run Jest in watch mode as you make changes:\n\n```bash\nnpm run test:watch\n```\n\n## Submitting Changes\n\nBefore submitting your changes, please ensure your code passes all tests and adheres to our coding style. Once you're ready, you can submit a pull request (PR) to the main repository.\n\nWe use GitHub Actions for continuous integration (CI). Whenever a PR is created, the CI checks will automatically run.\n\n## Release Process\n\nWe use Semantic Release for automatic versioning and publishing of our packages. This tool uses the commit messages to determine the type of changes in the codebase and performs a release accordingly. Therefore, we require all commit messages to follow the [Conventional Commits specification](https://www.conventionalcommits.org/).\n\n## Conclusion\n\nThank you for your interest in contributing to Asyncronaut! Please feel free to open an issue if you have any questions or run into any issues. We look forward to your contributions!\n\n## Roadmap\n\n- promises\n  - `fromEvent`\n- streams\n  - node stream destroy\n- browsers / e2e\n  - browserPool\n  - pagePool\n  - renderPipeline\n  - test helpers\n- taskQueue\n  - maxQueuedTaskDuration\n  - postMessage / distributed support\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickhulce%2Fasyncronaut","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatrickhulce%2Fasyncronaut","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatrickhulce%2Fasyncronaut/lists"}