{"id":18486295,"url":"https://github.com/maxgfr/node-simple-context","last_synced_at":"2026-02-08T00:07:34.414Z","repository":{"id":37022766,"uuid":"487065339","full_name":"maxgfr/node-simple-context","owner":"maxgfr","description":"A minimalist context for node, inspired by React Context API","archived":false,"fork":false,"pushed_at":"2025-12-10T22:06:16.000Z","size":1938,"stargazers_count":1,"open_issues_count":9,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-11T09:42:32.969Z","etag":null,"topics":["async-hooks","async-local-storage","context","context-api","global-variables","node-context","promise","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/node-simple-context","language":"TypeScript","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/maxgfr.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-29T17:57:17.000Z","updated_at":"2025-12-04T20:18:42.000Z","dependencies_parsed_at":"2024-01-13T04:15:32.614Z","dependency_job_id":"64308bcc-d480-497d-80f7-6d7054b88d72","html_url":"https://github.com/maxgfr/node-simple-context","commit_stats":{"total_commits":256,"total_committers":4,"mean_commits":64.0,"dds":0.34375,"last_synced_commit":"711ec7202ef18f25c43988763f6c76c50b315abd"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":"maxgfr/typescript-swc-starter","purl":"pkg:github/maxgfr/node-simple-context","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fnode-simple-context","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fnode-simple-context/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fnode-simple-context/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fnode-simple-context/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxgfr","download_url":"https://codeload.github.com/maxgfr/node-simple-context/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fnode-simple-context/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29213562,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T23:58:20.073Z","status":"ssl_error","status_checked_at":"2026-02-07T23:58:07.729Z","response_time":63,"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-hooks","async-local-storage","context","context-api","global-variables","node-context","promise","typescript"],"created_at":"2024-11-06T12:48:54.908Z","updated_at":"2026-02-08T00:07:34.409Z","avatar_url":"https://github.com/maxgfr.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-simple-context\n\n`node-simple-context` is a helper to create a context in Node.js.\n\nThis library is highly inspired by [nctx](https://github.com/devthejo/nctx). You definitely should check it out! Thanks to [@devthejo](https://github.com/devthejo) for his help\n\n## Installation\n\n```sh\nnpm install node-simple-context\n```\n\n## API Reference\n\n### `createSimpleContext()`\n\nCreates a new `SimpleContext` instance.\n\n```ts\nimport { createSimpleContext } from 'node-simple-context';\n\nconst context = createSimpleContext();\n```\n\n### `SimpleContext` class\n\n#### `get\u003cT\u003e(key: string): T | undefined`\n\nRetrieves a value from the context by key.\n\n**Parameters:**\n- `key` - The key to retrieve. Must be a non-empty string.\n\n**Returns:** The value associated with the key, or `undefined` if not found.\n\n**Throws:** `TypeError` if key is not a string or is empty.\n\n**Example:**\n```ts\nconst userId = context.get\u003cstring\u003e('userId');\n```\n\n#### `set\u003cT\u003e(key: string, value: T): void`\n\nSets a value in the context by key.\n\n**Parameters:**\n- `key` - The key to set. Must be a non-empty string.\n- `value` - The value to associate with the key.\n\n**Throws:** `TypeError` if key is not a string or is empty.\n\n**Example:**\n```ts\ncontext.set('userId', '12345');\n```\n\n#### `delete(key: string): boolean`\n\nDeletes a value from the context by key.\n\n**Parameters:**\n- `key` - The key to delete. Must be a non-empty string.\n\n**Returns:** `true` if the operation succeeded (even if key didn't exist).\n\n**Throws:** `TypeError` if key is not a string or is empty.\n\n**Example:**\n```ts\ncontext.delete('userId');\n```\n\n#### `has(key: string): boolean`\n\nChecks if a key exists in the context.\n\n**Parameters:**\n- `key` - The key to check. Must be a non-empty string.\n\n**Returns:** `true` if the key exists, `false` otherwise.\n\n**Throws:** `TypeError` if key is not a string or is empty.\n\n**Example:**\n```ts\nif (context.has('userId')) {\n  console.log('User ID is set');\n}\n```\n\n#### `clear(): void`\n\nClears all values from the current context.\n\n**Example:**\n```ts\ncontext.clear();\n```\n\n#### `getAll(): Record\u003cstring, unknown\u003e`\n\nGets all key-value pairs from the current context as a plain object.\n\n**Returns:** A shallow copy of all key-value pairs in the current context.\n\n**Example:**\n```ts\nconst allValues = context.getAll();\nconsole.log(allValues); // { userId: '12345', sessionId: 'abc' }\n```\n\n#### `keys(): string[]`\n\nGets all keys from the current context.\n\n**Returns:** An array of all keys in the current context.\n\n**Example:**\n```ts\nconst keys = context.keys();\nconsole.log(keys); // ['userId', 'sessionId']\n```\n\n#### `size(): number`\n\nGets the number of key-value pairs in the current context.\n\n**Returns:** The number of entries in the context.\n\n**Example:**\n```ts\nconst count = context.size();\nconsole.log(count); // 2\n```\n\n#### `fork\u003cT\u003e(callback?: () =\u003e T): SimpleContext | T`\n\nCreates a new forked context or runs a callback within a forked context.\n\n**Parameters:**\n- `callback` - Optional callback to execute within the forked context.\n\n**Returns:** The `SimpleContext` instance (if no callback) or the callback's return value.\n\n**Behavior:**\n- When called without a callback, it creates a new context scope that inherits the current properties. Subsequent changes won't affect the parent context.\n- When called with a callback, it executes the callback within the forked context and returns the callback's return value.\n\n**Examples:**\n```ts\n// Without callback - for use with async operations\ncontext.fork().set('foo', 'bar');\n\n// With callback - execute and return value\nconst result = context.fork(() =\u003e {\n  context.set('foo', 'bar');\n  return 'hello';\n});\n```\n\n## Usage Examples\n\n### Basic usage\n\n#### 1. Create a new file `my-context.ts` in which you define your context.\n\n```ts\nimport { createSimpleContext } from 'node-simple-context';\n\nexport const contextA = createSimpleContext();\nexport const contextB = createSimpleContext();\n```\n\n#### 2. You now can set the context in your code wherever you want\n\n```ts\nimport { contextA, contextB } from './my-context';\n\ncontextA.set('foo', 'bar');\ncontextB.set('foo', 'baz');\n```\n\n#### 3. And, get your context value wherever you want\n\n```ts\nimport { contextA, contextB } from './my-context';\n\nconsole.log(contextA.get('foo')); // bar\nconsole.log(contextB.get('foo')); // baz\nconsole.log(contextA.get('xxx')); // undefined\n\n// in typescript\nconsole.log(contextA.get\u003cstring\u003e('foo')); // bar\n```\n\n### Using additional methods\n\n```ts\nconst context = createSimpleContext();\n\n// Set values\ncontext.set('userId', '12345');\ncontext.set('sessionId', 'abc-def');\n\n// Check if a key exists\nif (context.has('userId')) {\n  console.log('User is logged in');\n}\n\n// Get the number of entries\nconsole.log(context.size()); // 2\n\n// Get all keys\nconsole.log(context.keys()); // ['userId', 'sessionId']\n\n// Get all values\nconsole.log(context.getAll()); // { userId: '12345', sessionId: 'abc-def' }\n\n// Delete a specific key\ncontext.delete('sessionId');\n\n// Clear all values\ncontext.clear();\nconsole.log(context.size()); // 0\n```\n\n### Complex examples\n\n#### By forking your context\n\nThanks to [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html) API, you can `fork` your context in promise or async functions. As you can see below:\n\n\u003e You can also pass a callback in `fork` method to runs a function synchronously within a context and returns its return value which uses [run method from AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynclocalstoragerunstore-callback-args) (cf. [example](./src/__tests__/context.test.ts#L134))\n\n```ts\nconst context = createSimpleContext();\n\nconst func = (): string =\u003e {\n  const foo = context.get('foo');\n  return `foo=${foo}`;\n};\n\ncontext.fork();\ncontext.set('foo', 'bar');\n\nconst res = await Promise.all([\n  new Promise((resolve) =\u003e {\n    context.fork().set('foo', 'tata');\n    setTimeout(() =\u003e {\n      resolve(func());\n    }, 400);\n  }),\n  new Promise((resolve) =\u003e {\n    context.fork().set('foo', 'toto');\n    setTimeout(() =\u003e {\n      resolve(func());\n    }, 200);\n  }),\n  new Promise((resolve) =\u003e {\n    context.fork().set('foo', 'titi');\n    setTimeout(() =\u003e {\n      resolve(func());\n    }, 100);\n  }),\n  new Promise((resolve) =\u003e {\n    context.fork().set('foo', 'tutu');\n    setTimeout(() =\u003e {\n      resolve(func());\n    }, 600);\n  }),\n]);\n\nconsole.log(res); // ['foo=tata', 'foo=toto', 'foo=titi', 'foo=tutu']\n```\n\n#### By using multiple contexts\n\n```ts\nconst contextA = createSimpleContext();\nconst contextB = createSimpleContext();\nconst contextC = createSimpleContext();\nconst contextD = createSimpleContext();\n\nconst func = (context: SimpleContext): string =\u003e {\n  const foo = context.get('foo');\n  return `foo=${foo}`;\n};\n\nconst res = await Promise.all([\n  new Promise((resolve) =\u003e {\n    contextA.set('foo', 'tata');\n    setTimeout(() =\u003e {\n      resolve(func(contextA));\n    }, 400);\n  }),\n  new Promise((resolve) =\u003e {\n    contextB.set('foo', 'toto');\n    setTimeout(() =\u003e {\n      resolve(func(contextB));\n    }, 200);\n  }),\n  new Promise((resolve) =\u003e {\n    contextC.set('foo', 'titi');\n    setTimeout(() =\u003e {\n      resolve(func(contextC));\n    }, 100);\n  }),\n  new Promise((resolve) =\u003e {\n    contextD.set('foo', 'tutu');\n    setTimeout(() =\u003e {\n      resolve(func(contextD));\n    }, 600);\n  }),\n]);\n\nconsole.log(res); // ['foo=tata', 'foo=toto', 'foo=titi', 'foo=tutu']\n```\n\n#### By using multiple keys\n\n```ts\nconst context = createSimpleContext();\n\nconst func = (key: string): string =\u003e {\n  const foo = context.get(key);\n  return `foo=${foo}`;\n};\n\nconst res = await Promise.all([\n  new Promise((resolve) =\u003e {\n    context.set('foo1', 'tata');\n    setTimeout(() =\u003e {\n      resolve(func('foo1'));\n    }, 400);\n  }),\n  new Promise((resolve) =\u003e {\n    context.set('foo2', 'toto');\n    setTimeout(() =\u003e {\n      resolve(func('foo2'));\n    }, 200);\n  }),\n  new Promise((resolve) =\u003e {\n    context.set('foo3', 'titi');\n    setTimeout(() =\u003e {\n      resolve(func('foo3'));\n    }, 100);\n  }),\n  new Promise((resolve) =\u003e {\n    context.set('foo4', 'tutu');\n    setTimeout(() =\u003e {\n      resolve(func('foo4'));\n    }, 600);\n  }),\n]);\n\nconsole.log(res); // ['foo=tata', 'foo=toto', 'foo=titi', 'foo=tutu']\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fnode-simple-context","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxgfr%2Fnode-simple-context","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fnode-simple-context/lists"}