{"ava":{"files":["./test/*.test.ts"],"serial":true,"require":["ts-node/register"],"extensions":["ts"],"compileEnhancements":false},"bugs":{"url":"https://github.com/andywer/threads/issues"},"dist":{"shasum":"64213d9969ec1718f3b604a06085e4d2e25c343f","tarball":"https://registry.npmjs.org/threads/-/threads-1.0.0-alpha.4.tgz","fileCount":53,"integrity":"sha512-kjOt05BnlGUlZOfK4BKZ0JyfBZ0Qj5LVny+1/7QbABdk4f5qzp3XSxkmOeGzDl8FV5CyKFjHIG+ONeRkuh0UQQ==","signatures":[{"sig":"MEYCIQDA1q7ubdcl7nRE/ieE7UPvyoBUK0yxjePlCaEahpkpyAIhAJ6R+rmSovgEpjnKctvA8ab4moRHCtqftAVX33OgAlR7","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":71781,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc/SzeCRA9TVsSAnZWagAA0MYP/1lqhtpiG6SIM6+NsrGU\n5+T9k9L2X7L00MvsoEm+cG9iB3Pd75gdVA61oJ1hqiuhXCp5MI3GtE0HSDGg\n29GW4fswTarFq6uWgRfVPSnxXrMhnuSLJZ4PorUHWS1sPbgy3+ttSBTkF6BM\nEkc5w4devcAEH9/WtnnLacN0mmtynsyRBQMZLj66CIPdU1FMBmo9APYXGwAT\nWSQLSKvkIXWMP7Mw+WrVJ7sPPZaMubNaKrSitdEB6feowzyOqOUPJ7Zdy5m/\nSofbzeT3LmJqEkukr7Klb7UNSlEEtvsnlI1q9Xl37emHBFRUogttpJMy1v+b\ngyDPaT29rstCFs152D/TWp6e55Fu/siP9xbDY0yCP+M386MNP0WuDqaQ5p+Q\nPlJrfKk1CllalLKhaARWp58XzYQ8w5pGpIxP/FGoeWn+X5guuZ4mj0ro6TC3\ntrrM8O8zO/O70klbwWV9OrLpL/uUCMtdCuoQ1LBRPkAz/TuhaROun7Q9mNnS\nlpBK+MrxlIwBv2kjL6Wz7NUOM5+WwTSrMaUgk8hCg5a0SiFGOuH2WW/qsHKo\nGnu/GSpUZ1NlEfVbAnM5mkl7/2/s442uuJxCWMWQsGA23YkXlzbiJ4CCNE5T\nJkLwCsdARaHxdkQbHnjJTXxzBF6fVRb7HNM4K0jk+ZbC+27CwSmulErpTC6A\nVtK9\r\n=E3Jw\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","name":"threads","author":{"url":"https://github.com/andywer","name":"Andy Wermke"},"readme":"<h1 align=\"center\">threads</h1>\n<p align=\"center\">\n  <a href=\"https://travis-ci.org/andywer/threads.js\" target=\"_blank\"><img alt=\"Build status\" src=\"https://img.shields.io/travis/andywer/threads.js/v1.svg?style=flat-square\"></a>\n  <a href=\"https://www.npmjs.com/package/threads/v/next\" target=\"_blank\"><img alt=\"npm (tag)\" src=\"https://img.shields.io/npm/v/threads/next.svg?style=flat-square\"></a>\n</p>\n\nVersion 1.0 - Work in progress 🛠\n\nComplete rewrite of the library with a new robust API, all functional, and all statically typed. It's still fully isomorphic – run the same code in the browser, in node.js or an electron app!\n\nDevelopment progress is tracked in 👉 [#100](https://github.com/andywer/threads.js/issues/100). Feel free to leave feedback there!\n\n## Installation\n\n```\nnpm install threads@next tiny-worker\n```\n\nIf you don't need to support node < 12 or you only want to build for the browser then you can also not install the `tiny-worker` package. It's an optional dependency and used as a fallback if `worker_threads` are not available.\n\n## Compatibility\n\n#### Platform: Web (browsers)\n\nUses [web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API).\n\n#### Platform: Node.js 12+\n\nUses native [worker threads](https://nodejs.org/api/worker_threads.html).\n\n#### Platform: Node.js < 12\n\nUses [`tiny-worker`](https://github.com/avoidwork/tiny-worker) as fallback if native worker threads are not available.\n\n## New Paradigm\n\nWe dropped inline functions support and instead focus on worker code residing in their own files.\nRunning inlined functions in a worker was nice for concise code samples, but offered limited value in real-world applications. Those inlined functions also had some built-in limitations that could not be overcome and that frequently got users confused.\n\nFocussing on worker code in distinct source modules also means we are focussing on using `threads` with bundlers like Webpack or Parcel in the front-end. In a node.js context you should be able to use a bundler as well, but you probably won't need to.\n\nThese changes also mean that we shall have worker code with `import`/`require()` that works in node.js just as well as bundled in browsers.\n\n## Usage\n\n### Concept\n\n```js\n// master.js\nimport { spawn, Thread, Worker } from \"threads\"\n\nasync function main() {\n  const add = await spawn(new Worker(\"./workers/add\"))\n  const sum = await add(2, 3)\n\n  console.log(`2 + 3 = ${sum}`)\n\n  await Thread.terminate(sum)\n}\n\nmain().catch(console.error)\n```\n\n```js\n// workers/add.js\nimport { expose } from \"threads/worker\"\n\nexpose(function add(a, b) {\n  return a + b\n})\n```\n\n#### spawn()\n\nThe return value of `add()` in the master code depends on the `add()` return value in the worker:\nIf the function returns a promise or an observable then you can just use the return value as such in the master code. If the function returns a primitive value, expect the master function to return a promise resolving to that value.\n\n#### expose()\n\nYou can `expose()` either a function or an object. In case of exposing an object, `spawn()` will asynchronously return an object exposing all the object's functions, following the same rules as functions directly `expose()`-ed.\n\n### Code Samples\n\n<details>\n<summary>Basics - Function thread</summary>\n\n```js\n// master.js\nimport { spawn, Thread, Worker } from \"threads\"\n\nconst fetchGithubProfile = await spawn(new Worker(\"./workers/fetch-github-profile\"))\nconst andywer = await fetchGithubProfile(\"andywer\")\n\nconsole.log(`User \"andywer\" has signed up on ${new Date(andywer.created_at).toLocaleString()}`)\n\nawait Thread.terminate(fetchGithubProfile)\n```\n\n```js\n// workers/fetch-github-profile.js\nimport fetch from \"isomorphic-fetch\"\nimport { expose } from \"threads/worker\"\n\nexpose(async function fetchGithubProfile(username) {\n  const response = await fetch(`https://api.github.com/users/${username}`)\n  return response.json()\n})\n```\n</details>\n\n<details>\n<summary>Basics - Module thread</summary>\n\n```js\n// master.js\nimport { spawn, Thread, Worker } from \"threads\"\n\nconst counter = await spawn(new Worker(\"./workers/counter\"))\nawait counter.increment()\nawait counter.increment()\nawait counter.decrement()\n\nconsole.log(`Counter is now at ${await counter.getCount()}`)\n\nawait Thread.terminate(counter)\n```\n\n```js\n// workers/counter.js\nimport { expose } from \"threads/worker\"\n\nlet currentCount = 0\n\nconst counter = {\n  getCount() {\n    return currentCount\n  },\n  increment() {\n    return ++currentCount\n  },\n  decrement() {\n    return --currentCount\n  }\n}\n\nexpose(counter)\n```\n</details>\n\n<details>\n<summary>TODO: Basics - Returning observables</summary>\n\nJust return an observable in your worker, subscribe to it in the master code. Fully transparent.\n</details>\n\n<details>\n<summary>TODO: Basics - Error handling</summary>\n\nFully transparent. The promise in the master code's call will be rejected with the error thrown in the worker, also yielding the worker error's stack trace.\n</details>\n\n<details>\n<summary>Thread pool</summary>\n\nA `Pool` allows you to create a set of worker threads and queue thread calls. The queued tasks are pulled from the queue and executed as previous tasks have finished.\n\nUse it if you have a lot of work to offload to other threads and don't want to drown them in a huge pile of work at once, but run it in a controlled way with limited concurrency.\n\n```js\nimport { spawn, Pool } from \"threads\"\n\nconst pool = Pool(() => spawn(new Worker(\"./workers/multiplier\")), 8 /* optional size */)\n\npool.events.subscribe(console.log)\n\npool.queue(async multiplier => {\n  const multiplied = await multiplier(2, 3)\n  console.log(`2 * 3 = ${multiplied}`)\n\n  // When this async call completes, the worker thread (`multiplier`) will\n  // be marked as available for new work scheduled via `pool.queue()`\n})\n\nawait pool.completed()\nawait pool.terminate()\n```\n\nNote that `pool.queue()` will schedule a task to be run in a deferred way. It might execute straight away or it might take a while until a new worker thread becomes available.\n\nThe promise returned by `pool.completed()` will resolve once the scheduled callbacks have been executed and completed. A failing job will also make the promise reject.\n\n</details>\n\n<details>\n<summary>Transferable objects</summary>\nUse `Transfer()` to mark [`transferable objects`](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Passing_data_by_transferring_ownership_(transferable_objects)) like ArrayBuffers to be transferred to the receiving thread. It can speed up your code a lot if you are working with big chunks of binary data.\n\n`Transfer()` comes in two flavors:\n* `Transfer(myBuffer: Transferable)`\n* `Transfer(someObjectOrArrayContainingMyBuffers: any, [myBuffer, /* ... */]: Transferable[])`\n\nUse it when calling a thread function or returning from a thread function:\n\n```js\n// master.js\nimport { spawn, Transfer, Worker } from \"threads\"\n\nconst xorBuffer = await spawn(new Worker(\"./workers/arraybuffer-xor\"))\nconst resultBuffer = await xorBuffer(Transfer(testData), 127)\n```\n\n```js\n// workers/arraybuffer-xor.js\nimport { expose, Transfer } from \"threads/worker\"\n\nexpose(function xorBuffer(username) {\n  const view = new Uint8Array(buffer)\n  view.forEach((byte, offset) => view.set([byte ^ value], offset))\n  return Transfer(buffer)\n})\n```\n\nWithout `Transfer()` the buffers would be copied on every call and every return. Using `Transfer()` only their ownership is transferred to the other thread instead to make sure it is accessible in a thread-safe way. This is a much faster operation.\n</details>\n\n<details>\n<summary>TODO: Cancelling a thread job</summary>\n</details>\n\n<details>\n<summary>TODO: Subscribe to thread debugging events</summary>\n</details>\n\n<details>\n<summary>Tests</summary>\n\nCheck out the [integration tests](./test) and [their workers](./test/workers) to see it in action.\n</details>\n\n### Usage with node.js\n\nWorks out of the box. Note that we wrap the native `Worker`, so `new Worker(\"./foo/bar\")` will resolve the path relative to the module that calls it, not relative to the current working directory.\n\nThat aligns it with the behavior when bundling the code with webpack or parcel.\n\n### Usage with Webpack\n\nUse with the [`worker-plugin`](https://github.com/GoogleChromeLabs/worker-plugin), so all `new Worker(\"./unbundled-path\")` expressions are detected and properly transformed transparently, so you don't need to explicitly use the `worker-loader` or define extra entry points.\n\nTODO\n\n### Usage with Parcel\n\nShould work out of the box without any extra plugins.\n\nThe only adjustment you need to do is to import `threads/register` once in the beginning (in the master code, not in the thread) to register the library's `Worker` for your platform as the global `Worker`.\n\nThis is necessary, since you cannot `import { Worker } from \"threads\"` or Parcel won't recognize `new Worker()` as a web worker anymore.\n\nTODO\n\n## API\n\nTODO\n\n## Debug\n\nWe are using the [`debug`](https://github.com/visionmedia/debug) package to provide opt-in debug logging. All the package's debug messages have a scope starting with `threads:`, with different sub-scopes.\n\nSet it to `DEBUG=threads:*` to enable all the library's debug logging. To run its tests with full debug logging, for instance:\n\n```\nDEBUG=threads:* npm test\n```\n\n## License\n\nMIT\n","browser":{"ts-node":false,"tiny-worker":false,"worker_threads":false,"ts-node/register":false,"./dist/master/implementation":"./dist/master/implementation.browser.js","./dist/worker/implementation":"./dist/worker/implementation.browser.js","./dist/master/implementation.node.js":false,"./dist/worker/implementation.tiny-worker.js":false,"./dist/worker/implementation.worker_threads.js":false},"gitHead":"1bcd242721cfa9888e0e44d6ed88efc532b5ab3a","license":"MIT","scripts":{"test":"run-s test:ava test:puppeteer","build":"tsc","prepare":"run-s build","pretest":"babel --plugins @babel/plugin-transform-typescript --plugins @babel/plugin-transform-modules-commonjs ./test/workers -d ./test/workers -x .ts","posttest":"tslint --project .","prebuild":"rimraf dist/","test:ava":"TS_NODE_FILES=true ava","test:puppeteer":"puppet-run plugin:mocha ./test/*.chromium*.ts"},"_npmUser":{"name":"andywer","email":"andy.dev@next-step-software.com"},"homepage":"https://github.com/andywer/threads#readme","keywords":["thread","web worker","pool","spawn","isomorphic","parallel","observable"],"repository":{"url":"git+https://github.com/andywer/threads.git","type":"git"},"_npmVersion":"6.9.0","description":"Easy to use, yet powerful multi-threading library for node.js and the browser!","directories":{},"maintainers":[{"name":"andywer","email":"andy@dev.next-step-software.com"}],"_nodeVersion":"10.15.3","dependencies":{"debug":"^4.1.1","callsites":"^3.1.0","tiny-worker":">= 2","is-observable":"^1.1.0","zen-observable":"^0.8.14","@types/zen-observable":"^0.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ava":"^1.4.1","chai":"^4.2.0","mocha":"^5.2.0","rimraf":"^2.6.3","tslint":"^5.16.0","ts-node":"^8.1.0","@babel/cli":"^7.4.4","puppet-run":"^0.5.0","typescript":"^3.4.5","@types/chai":"^4.1.7","@types/node":"^11.13.8","npm-run-all":"^4.1.5","tiny-worker":"^2.2.0","@types/debug":"^4.1.4","@types/mocha":"^5.2.6","@types/callsites":"^3.0.0","tslint-config-prettier":"^1.18.0","puppet-run-plugin-mocha":"^0.1.1","@babel/plugin-transform-typescript":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4"},"optionalDependencies":{"tiny-worker":">= 2"},"_npmOperationalInternal":{"tmp":"tmp/threads_1.0.0-alpha.4_1560095965646_0.2955492445904906","host":"s3://npm-registry-packages"},"_id":"threads@1.0.0-alpha.4","version":"1.0.0-alpha.4"}