{"id":46537479,"url":"https://github.com/winton/typectl","last_synced_at":"2026-03-07T00:10:48.176Z","repository":{"id":57383339,"uuid":"429647833","full_name":"winton/typectl","owner":"winton","description":"🚰 TypeScript control flow library","archived":false,"fork":false,"pushed_at":"2025-03-20T21:16:48.000Z","size":620,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-27T12:01:05.532Z","etag":null,"topics":["async","control-flow","promise","typescript"],"latest_commit_sha":null,"homepage":"","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/winton.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}},"created_at":"2021-11-19T02:42:01.000Z","updated_at":"2025-03-20T21:16:51.000Z","dependencies_parsed_at":"2022-09-26T16:50:23.433Z","dependency_job_id":null,"html_url":"https://github.com/winton/typectl","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/winton/typectl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winton%2Ftypectl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winton%2Ftypectl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winton%2Ftypectl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winton%2Ftypectl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/winton","download_url":"https://codeload.github.com/winton/typectl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/winton%2Ftypectl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30204114,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["async","control-flow","promise","typescript"],"created_at":"2026-03-07T00:10:44.216Z","updated_at":"2026-03-07T00:10:48.167Z","avatar_url":"https://github.com/winton.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🚰 typectl\n\nTypeScript control flow library\n\n```bash\nnpm install typectl\n```\n\n## Summary\n\n**Typectl** is a control flow library for executing and connecting independent functions. The API is designed to scale from both a development and performance perspective; there is no need for `await` and execution order remains optimal as functions are added.\n\nThe \"killer feature\" of typectl is `wrap`. Wrapping a function allows it to optionally receive the typed promise version of each argument. Wrapped functions do not execute until their arguments resolve and always return a typed promise.\n\nBy passing promise return values to successive wrapped functions, the most optimal execution order occurs naturally based on the \"race\" to execute functions as their arguments resolve.\n\nThe API also provides type-safe ways of transforming promise values without requiring their resolution, which aid in preparing arguments or final return values.\n\n### How it works\n\nControl flows are similar to a \"controller\", or a place where other functions are orchestrated. Within your control flow, do all of the following **without `await`**:\n\n1. Wrap any function so it accepts the promise version of its arguments and returns a promise (`wrap`).\n2. Pick values from promises with array or record values (`pick`). Function values are wrapped automatically.\n3. Execute functions independently, concurrently (`all`), or sequentially (`each`).\n4. Map promises to arrays, records, web streams, or any value (`toArray`, `toRecord`, `toStream`, `toValue`).\n\n### Dev features\n\n1. Type-safe ☔\n2. Dynamic imports ⚡\n3. Universal JS (Node and browser) 👽\n4. Small footprint (~2 kb compressed) 👣\n\n## Example\n\nThis code is also located at [`src/example`](src/example).\n\n### `functions.ts`\n\n```typescript\nexport function time() {\n  return new Date().getTime()\n}\n\nexport function plusOne(value: number) {\n  return value + 1\n}\n```\n\n### `controlFlow.ts`\n\n```typescript\nimport { all, pick, toArray, toRecord } from \"typectl\"\n\nexport default function () {\n  const functions = import(\"./functions\")\n  const time = pick(functions, \"time\")\n  const plusOne = pick(functions, \"plusOne\")\n  const times = all([time, time])\n  const timesPlusOne = toArray(times, plusOne)\n  const timesPlusOneRecord = toRecord(timesPlusOne)\n  return { times, timesPlusOneRecord }\n}\n```\n\n### `spec.ts`\n\n```typescript\nimport { pick } from \"typectl\"\nimport expect from \"expect\"\nimport controlFlow from \"./controlFlow\"\n\ndescribe(\"example\", () =\u003e {\n  it(\"runs control flow\", async () =\u003e {\n    const { times, timesPlusOneRecord } = controlFlow()\n\n    expect(await times).toEqual([\n      expect.any(Number),\n      expect.any(Number),\n    ])\n\n    expect(await timesPlusOneRecord).toEqual({\n      0: expect.any(Number),\n      1: expect.any(Number),\n    })\n\n    expect(await pick(times, 0)).toEqual(\n      (await pick(timesPlusOneRecord, 0)) - 1\n    )\n  })\n})\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwinton%2Ftypectl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwinton%2Ftypectl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwinton%2Ftypectl/lists"}