{"id":26180624,"url":"https://github.com/mikemajesty/node-thread-decorator","last_synced_at":"2026-04-26T07:32:06.355Z","repository":{"id":280074370,"uuid":"940915210","full_name":"mikemajesty/node-thread-decorator","owner":"mikemajesty","description":"Simplifying Thread Management in Nodejs with Decorators","archived":false,"fork":false,"pushed_at":"2026-01-11T04:07:56.000Z","size":72,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-11T11:59:54.853Z","etag":null,"topics":["express-thread","nestjs-thread","node-multi-threading","node-threads"],"latest_commit_sha":null,"homepage":"","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/mikemajesty.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-01T03:41:01.000Z","updated_at":"2026-01-11T04:07:59.000Z","dependencies_parsed_at":"2025-03-01T04:34:39.765Z","dependency_job_id":null,"html_url":"https://github.com/mikemajesty/node-thread-decorator","commit_stats":null,"previous_names":["mikemajesty/node-thread-decorator"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/mikemajesty/node-thread-decorator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemajesty%2Fnode-thread-decorator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemajesty%2Fnode-thread-decorator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemajesty%2Fnode-thread-decorator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemajesty%2Fnode-thread-decorator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikemajesty","download_url":"https://codeload.github.com/mikemajesty/node-thread-decorator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikemajesty%2Fnode-thread-decorator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32289926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T06:26:00.361Z","status":"ssl_error","status_checked_at":"2026-04-26T06:25:58.791Z","response_time":129,"last_error":"SSL_read: 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":["express-thread","nestjs-thread","node-multi-threading","node-threads"],"created_at":"2025-03-11T21:56:54.268Z","updated_at":"2026-04-26T07:32:06.341Z","avatar_url":"https://github.com/mikemajesty.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Node Thread Decorator\n\n[![node version][node-image]][node-url]\n[![npm version](https://img.shields.io/npm/v/node-thread-decorator.svg?style=flat-square)](https://www.npmjs.com/package/node-thread-decorator)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)\n\n[node-image]: https://img.shields.io/badge/node.js-%3E=_18.0-green.svg?style=flat-square\n[node-url]: http://nodejs.org/download/\n\nA TypeScript decorator that executes class methods in separate Node.js worker threads, preventing CPU-intensive operations from blocking the main event loop.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [API Reference](#api-reference)\n- [Usage Examples](#usage-examples)\n- [Important Limitations](#important-limitations)\n- [Using External Dependencies](#using-external-dependencies)\n- [Best Practices](#best-practices)\n- [License](#license)\n\n## Installation\n\n```bash\nnpm install node-thread-decorator\n```\n\n## Quick Start\n\n```typescript\nimport { RunInNewThread } from 'node-thread-decorator';\n\nclass Calculator {\n  @RunInNewThread()\n  async heavyComputation(iterations: number): Promise\u003cnumber\u003e {\n    let result = 0;\n    for (let i = 0; i \u003c iterations; i++) {\n      result += Math.sqrt(i) * Math.sin(i);\n    }\n    return result;\n  }\n}\n\nconst calc = new Calculator();\nconst result = await calc.heavyComputation(10000000);\n```\n\n## API Reference\n\n### `@RunInNewThread(timeout?: number)`\n\nA method decorator that executes the decorated method in a separate worker thread.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `timeout` | `number` | No | Maximum execution time in milliseconds. If exceeded, the worker is terminated and an error is thrown. |\n\n**Returns:** `Promise\u003cT\u003e` - The decorated method always returns a Promise, even if the original method was synchronous.\n\n## Usage Examples\n\n### Basic Usage\n\n```typescript\nimport { RunInNewThread } from 'node-thread-decorator';\n\nclass MyService {\n  @RunInNewThread()\n  async processData(data: number[]): Promise\u003cnumber\u003e {\n    return data.reduce((sum, n) =\u003e sum + n, 0);\n  }\n}\n```\n\n### With Timeout\n\n```typescript\nclass MyService {\n  @RunInNewThread(5000) // 5 second timeout\n  async longRunningTask(): Promise\u003cstring\u003e {\n    // If this takes more than 5 seconds, it will throw an error\n    return 'completed';\n  }\n}\n```\n\n### NestJS Integration\n\n```typescript\nimport { Controller, Get } from '@nestjs/common';\nimport { RunInNewThread } from 'node-thread-decorator';\n\n@Controller()\nexport class HealthController {\n  @RunInNewThread()\n  heavyOperation(milliseconds: number): void {\n    const start = Date.now();\n    while (Date.now() - start \u003c milliseconds) {\n      // CPU-intensive work\n    }\n  }\n\n  @Get('/health')\n  async getHealth(): Promise\u003cstring\u003e {\n    await this.heavyOperation(10000); // Won't block the main thread\n    return 'OK';\n  }\n}\n```\n\n## Important Limitations\n\n### 1. Class Methods Only\n\nThe decorator **only works with class methods**. Standalone functions are not supported.\n\n```typescript\n// ✅ Supported - Class method\nclass MyClass {\n  @RunInNewThread()\n  async myMethod() { /* ... */ }\n}\n\n// ❌ Not Supported - Standalone function\n@RunInNewThread() // This won't work\nfunction myFunction() { /* ... */ }\n```\n\n### 2. No Access to External Scope (Closures)\n\nMethods executed in worker threads **cannot access variables, imports, or closures** from the original scope. Each worker runs in an isolated context.\n\n```typescript\nimport { someHelper } from './helpers';\n\nconst CONFIG = { maxRetries: 3 };\n\nclass MyService {\n  @RunInNewThread()\n  async process(): Promise\u003cvoid\u003e {\n    // ❌ This will fail - 'someHelper' is not defined in worker\n    someHelper();\n    \n    // ❌ This will fail - 'CONFIG' is not defined in worker\n    console.log(CONFIG.maxRetries);\n  }\n}\n```\n\n### 3. No Access to `this` Context\n\nThe `this` keyword inside decorated methods does **not** refer to the class instance. Instance properties and other methods are not accessible.\n\n```typescript\nclass MyService {\n  private value = 42;\n\n  @RunInNewThread()\n  async getValue(): Promise\u003cnumber\u003e {\n    // ❌ This will fail - 'this.value' is undefined in worker\n    return this.value;\n  }\n\n  @RunInNewThread()\n  async callOther(): Promise\u003cvoid\u003e {\n    // ❌ This will fail - 'this.otherMethod' is not a function in worker\n    this.otherMethod();\n  }\n\n  otherMethod() { /* ... */ }\n}\n```\n\n### 4. Arguments Must Be Serializable\n\nAll arguments passed to decorated methods must be serializable (transferable via `postMessage`). Functions, class instances, and circular references cannot be passed.\n\n```typescript\nclass MyService {\n  @RunInNewThread()\n  async process(data: unknown): Promise\u003cvoid\u003e {\n    // ...\n  }\n}\n\n// ✅ Supported types\nawait service.process({ name: 'John', age: 30 }); // Plain objects\nawait service.process([1, 2, 3]);                  // Arrays\nawait service.process('hello');                    // Primitives\nawait service.process(null);                       // null/undefined\n\n// ❌ Not supported\nawait service.process(() =\u003e {});                   // Functions\nawait service.process(new MyClass());              // Class instances\nawait service.process(circularRef);                // Circular references\n```\n\n## Using External Dependencies\n\nTo use external modules inside a decorated method, you must use `require()` **inside** the method body with the **absolute path** to the module.\n\n### Pattern for External Dependencies\n\n```typescript\nimport { RunInNewThread } from 'node-thread-decorator';\nimport path from 'path';\n\nclass MyService {\n  @RunInNewThread()\n  async processWithExternal(servicePath: string, data: number[]): Promise\u003cnumber\u003e {\n    // ✅ Correct - require() inside the method with absolute path\n    const { Calculator } = require(servicePath);\n    const calc = new Calculator();\n    return calc.sum(data);\n  }\n}\n\n// Usage - pass the absolute path as argument\nconst servicePath = path.resolve(__dirname, './services/calculator');\nconst result = await service.processWithExternal(servicePath, [1, 2, 3]);\n```\n\n### Using Node.js Built-in Modules\n\nBuilt-in modules can be required directly by name:\n\n```typescript\nclass MyService {\n  @RunInNewThread()\n  async readFileInThread(filePath: string): Promise\u003cstring\u003e {\n    const fs = require('fs');\n    const path = require('path');\n    return fs.readFileSync(filePath, 'utf-8');\n  }\n\n  @RunInNewThread()\n  async getSystemInfo(): Promise\u003cobject\u003e {\n    const os = require('os');\n    return {\n      cpus: os.cpus().length,\n      memory: os.totalmem(),\n      platform: os.platform()\n    };\n  }\n}\n```\n\n### Complete Example with External Service\n\n```typescript\n// services/calculator.ts\nexport class Calculator {\n  sum(numbers: number[]): number {\n    return numbers.reduce((a, b) =\u003e a + b, 0);\n  }\n\n  multiply(numbers: number[]): number {\n    return numbers.reduce((a, b) =\u003e a * b, 1);\n  }\n}\n\n// my-service.ts\nimport { RunInNewThread } from 'node-thread-decorator';\nimport path from 'path';\n\nclass MyService {\n  private readonly calculatorPath = path.resolve(__dirname, './services/calculator');\n\n  @RunInNewThread()\n  async calculate(calculatorPath: string, numbers: number[]): Promise\u003cnumber\u003e {\n    const { Calculator } = require(calculatorPath);\n    const calc = new Calculator();\n    return calc.sum(numbers);\n  }\n\n  async run(): Promise\u003cnumber\u003e {\n    // Pass the absolute path as an argument\n    return this.calculate(this.calculatorPath, [1, 2, 3, 4, 5]);\n  }\n}\n```\n\n## Best Practices\n\n### ✅ Do\n\n- Use for CPU-intensive operations (cryptography, data processing, complex calculations)\n- Pass all required data as arguments\n- Use `require()` inside the method for external dependencies\n- Always use absolute paths when requiring local modules\n- Handle errors with try/catch blocks\n- Set appropriate timeouts for long-running operations\n\n### ❌ Don't\n\n- Don't use for I/O-bound operations (the event loop handles these efficiently)\n- Don't try to access external scope variables\n- Don't use `this` to access instance properties\n- Don't pass non-serializable data as arguments\n- Don't use relative paths with `require()` inside workers\n\n### When to Use\n\n| Use Case | Recommendation |\n|----------|----------------|\n| Heavy mathematical computations | ✅ Use decorator |\n| Image/video processing | ✅ Use decorator |\n| Data encryption/hashing | ✅ Use decorator |\n| Database queries | ❌ Use async/await |\n| HTTP requests | ❌ Use async/await |\n| File I/O | ❌ Use async/await |\n\n## Contributors\n\n[\u003cimg alt=\"mikemajesty\" src=\"https://avatars1.githubusercontent.com/u/11630212?s=460\u0026v=4\u0026s=117\" width=\"117\"\u003e](https://github.com/mikemajesty)\n\n## License\n\nMIT License - see [LICENSE](https://opensource.org/licenses/mit-license.php) for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikemajesty%2Fnode-thread-decorator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikemajesty%2Fnode-thread-decorator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikemajesty%2Fnode-thread-decorator/lists"}