{"id":15046950,"url":"https://github.com/theinternetfolks/context","last_synced_at":"2025-07-13T22:08:12.067Z","repository":{"id":57165967,"uuid":"437788702","full_name":"theinternetfolks/context","owner":"theinternetfolks","description":"Library to help you create a context that can be used to reference data, without prop drilling, in Node-based environments.","archived":false,"fork":false,"pushed_at":"2025-02-26T17:25:57.000Z","size":3126,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-13T05:18:48.444Z","etag":null,"topics":["bun","context","context-api","nodejs"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@theinternetfolks/context","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theinternetfolks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-12-13T08:14:59.000Z","updated_at":"2025-02-26T17:26:00.000Z","dependencies_parsed_at":"2025-02-14T03:43:01.904Z","dependency_job_id":null,"html_url":"https://github.com/theinternetfolks/context","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/theinternetfolks/context","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theinternetfolks%2Fcontext","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theinternetfolks%2Fcontext/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theinternetfolks%2Fcontext/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theinternetfolks%2Fcontext/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theinternetfolks","download_url":"https://codeload.github.com/theinternetfolks/context/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theinternetfolks%2Fcontext/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265212840,"owners_count":23728613,"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":["bun","context","context-api","nodejs"],"created_at":"2024-09-24T20:53:47.668Z","updated_at":"2025-07-13T22:08:12.058Z","avatar_url":"https://github.com/theinternetfolks.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![The Internet Folks Logo](https://www.theinternetfolks.com/svg/tiflogo.svg)](https://theinternetfolks.com)\n\n# @theinternetfolks/context\n\n[![GitHub license](https://img.shields.io/github/license/theinternetfolks/context.svg)](https://github.com/theinternetfolks/context/blob/master/LICENSE)\n[![Maintainer](https://img.shields.io/badge/maintainer-monkfromearth-green)](https://github.com/monkfromearth)\n\nLibrary to help you create a context that can be used to reference data, without prop drilling, in Node-based environments.\n\nThe inspiration comes from the concept of [Context](https://reactjs.org/docs/context.html) in React.\n\n\u003e Prop drilling is the process of getting data from component A to component Z by passing it through multiple layers of intermediary React components. Instead of manually passing props down, Context provides a way to share values between components.\n\nPassing data to child functions in Node-based environments is a challenge. You could use a static class that works as your storage, but in cases where the application might be accessed in parallel, this approach fails. There is a definite need for a context-like concept.\n\nInstead of doing this:\n\n```javascript\ncallFunction1(originalData) {\n    callFunction2(someData, originalData);\n}\n\ncallFunction2(someData, originalData) {\n    processOtherDataToo(someData);\n    callFunction3(originalData);\n}\n\ncallFunction3(originalData) {\n    callFunction4(originalData);\n}\n\ncallFunction4(originalData) {\n    useTheOriginalDataFinally(originalData);\n}\n```\n\nYou can do this:\n\n```javascript\ncallFunction1(originalData) {\n    Context.set(originalData);\n    callFunction2(someData);\n}\n\ncallFunction2(someData) {\n    processOtherDataToo(someData);\n    callFunction3();\n}\n\ncallFunction3() {\n    callFunction4();\n}\n\ncallFunction4() {\n    const data = Context.get();\n    useTheOriginalDataFinally(data);\n}\n```\n\nThe library uses [Async Local Storage](https://nodejs.org/api/async_context.html#class-asynclocalstorage) internally, which provides an API to track the lifetime of asynchronous resources in a Node application.\n\n## Installation\n\nInstall with npm:\n\n```bash\nnpm install @theinternetfolks/context\n```\n\nInstall with pnpm:\n\n```bash\npnpm add @theinternetfolks/context\n```\n\nInstall with bun:\n\n```bash\nbun add @theinternetfolks/context\n```\n\nInstall with yarn:\n\n```bash\nyarn add @theinternetfolks/context\n```\n\n## Features\n\n- Lightweight implementation using native `AsyncLocalStorage`\n- TypeScript typings with interfaces support\n- Works with all kinds of async functions (`Promises`, `Timeouts`, `TCPWrap`, `UDP`, etc.)\n\n## Usage/Examples\n\n### Example 1: Simple Function Call\n\n```javascript\nconst { Context } = require(\"@theinternetfolks/context\");\n\nconst SomeFunction = () =\u003e {\n  const data = Context.get();\n  console.log(`Name: ${data.name}`);\n};\n\n(() =\u003e {\n  Context.init(); // initialize the context for this run\n  Context.set({ name: \"The Internet Folks\" });\n  SomeFunction();\n})();\n```\n\n**Output**:\n```bash\nName: The Internet Folks\n```\n\n### Example 2: Parent-Child Function Calls\n\n```javascript\nconst { Context } = require(\"@theinternetfolks/context\");\n\nconst ChildFunction = () =\u003e {\n  const data = Context.get();\n  console.log(`Name from Context: ${data.name} in Child`);\n};\n\nconst ParentFunction = () =\u003e {\n  const data = Context.get();\n  console.log(`Name from Context: ${data.name} in Parent`);\n  ChildFunction();\n};\n\n(() =\u003e {\n  Context.init(); // initialize the context for this run\n  Context.set({ name: \"The Internet Folks\" });\n  ParentFunction();\n})();\n```\n\n### Example 3: Usage in Express.js (Per-Request Context)\n\n```javascript\nconst express = require(\"express\");\nconst { Context } = require(\"@theinternetfolks/context\");\n\nconst app = express();\n\napp.use(express.json());\n\napp.use((req, res, next) =\u003e {\n  Context.init(); // initialize the context for the request\n  Context.set({ host: req.get(\"host\") });\n  next();\n});\n\napp.get(\"/\", (req, res) =\u003e {\n  const data = Context.get();\n  return res.json({ host: data?.host });\n});\n\napp.listen(3000, () =\u003e {\n  console.log(\"Server running on port 3000\");\n});\n```\n\n### Example 4: Express.js with TypeScript\n\n```typescript\nimport express from \"express\";\nimport { Context } from \"@theinternetfolks/context\";\n\ninterface IPayload {\n    host: string;\n}\n\nconst app = express();\n\napp.use(express.json());\n\napp.use((req, res, next) =\u003e {\n  Context.init(); // initialize the context for the request\n  Context.set({ host: req.get(\"host\") });\n  next();\n});\n\napp.get(\"/\", (req, res) =\u003e {\n  const context = Context.get\u003cIPayload\u003e();\n\n  setTimeout(() =\u003e {\n    console.log(context?.host);\n  }, 2500);\n\n  return res.json({ host: context?.host });\n});\n\napp.listen(6174, () =\u003e {\n  console.log(\"Server running on port 6174\");\n});\n```\n\n## Documentation\n\n#### API Methods\n\n- `static init(): void;`\n  Initializes a new context. This **must** be called before setting data.\n\n- `static get\u003cT\u003e(key?: string | null): T;`\n  Retrieves the stored data in the context.\n\n- `static set(data: Record\u003cstring, any\u003e): boolean;`\n  Stores data in the context.\n\n- `static remove(key?: string): void;`\n  Deletes the data stored in the context.\n\n- `static run\u003cT\u003e(fn: () =\u003e T | Promise\u003cT\u003e, initialData?: Record\u003cstring, any\u003e): T | Promise\u003cT\u003e;`\n  Runs a function with an isolated context.\n\n## Tests\n\n- Uses Bun Test Suite for unit testing.\n- Load tested with k6 to ensure no data leakage across requests.\n\n[Test Coverage](https://theinternetfolks.github.io/context/coverage/)\n\n## Authors\n\n- Sameer Khan ([@monkfromearth](https://github.com/monkfromearth))\n\n## Careers at The Internet Folks\n\nAt The Internet Folks, we’re a team of ambitious builders driven by curiosity and a passion for crafting high-performance, scalable software. We tackle complex engineering challenges, push the boundaries of innovation, and create technology that makes a real impact.\n\nIf you love solving hard problems, designing clean architectures, and building systems that scale, we’d love to have you on board. Here, you’ll work with some of the sharpest minds, ship fast, and grow even faster.\n\n🚀 Explore open roles and join us: [Explore Now](https://theinternetfolks.com/careers)\n\nLet’s build something extraordinary—together.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheinternetfolks%2Fcontext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheinternetfolks%2Fcontext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheinternetfolks%2Fcontext/lists"}