{"id":24992343,"url":"https://github.com/joshlong145/span","last_synced_at":"2025-09-07T21:15:09.238Z","repository":{"id":44428716,"uuid":"512596222","full_name":"joshLong145/Span","owner":"joshLong145","description":"Web Worker Abstraction For Deno Runtime","archived":false,"fork":false,"pushed_at":"2025-03-12T15:52:34.000Z","size":4466,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-12T02:13:42.263Z","etag":null,"topics":["async-await","deno","javascript","jsr","postmessage","typescript","webassembly","webworkers"],"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/joshLong145.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,"zenodo":null}},"created_at":"2022-07-11T02:50:59.000Z","updated_at":"2025-03-12T15:52:38.000Z","dependencies_parsed_at":"2024-01-11T05:15:30.382Z","dependency_job_id":"1d50ee19-e271-4b39-9167-2efd5fc2f6d9","html_url":"https://github.com/joshLong145/Span","commit_stats":null,"previous_names":["joshlong145/span"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/joshLong145/Span","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshLong145%2FSpan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshLong145%2FSpan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshLong145%2FSpan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshLong145%2FSpan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshLong145","download_url":"https://codeload.github.com/joshLong145/Span/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshLong145%2FSpan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274096064,"owners_count":25221561,"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","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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-await","deno","javascript","jsr","postmessage","typescript","webassembly","webworkers"],"created_at":"2025-02-04T13:55:04.794Z","updated_at":"2025-09-07T21:15:09.209Z","avatar_url":"https://github.com/joshLong145.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Span: Worker Pooling abstraction\n\n[![Deno module](https://shield.deno.dev/x/span)](https://deno.land/x/span)\n[![JSR](https://jsr.io/badges/@joshlong145/span)](https://jsr.io/@joshlong145/span)\n[![Unit Test CI](https://github.com/joshLong145/Span/actions/workflows/test.yml/badge.svg)](https://github.com/joshLong145/Span/actions/workflows/test.yml)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"200px\" height=\"200px\" src=\"https://github.com/joshLong145/DenoWebWorkerBridge/blob/master/images/worker-friend.png?raw=true\" /\u003e\n\u003c/p\u003e\n\n`Span` provides a simplified way to use Web Workers in Deno and other JavaScript\nruntimes. Abstracting the complexities of WebWorkers through a\npooling abstraction. Allowing you to define methods within a class that are\nautomatically translated into functions executed in a Web Worker. This module\nhelps manage execution state and shared memory using `SharedArrayBuffer`.\n\n## Features\n\n- **Class-based Definition**: Define methods in a class extending\n  `WorkerDefinition`, which are then converted into functions that run in a Web\n  Worker.\n- **Shared Memory**: Utilize `SharedArrayBuffer` to cache and manage execution\n  state.\n- **Pooling**: Support for parallelization through an internal `Worker Pool` to\n  allow for true parallel task execution.\n- **WebAssembly (WASM) Support**: Integrate and interact with WASM modules\n  compiled from languages such as GoLang and Rust.\n\n**note** when compiling rust through `wasm bidgen` only `--target web` is known\nto be supported.\n\n## Installation\n\nInstall via Deno:\n\n```bash\ndeno install -A -f https://deno.land/x/span/mod.ts\n```\n\nInstall via JSR (for use with Deno)\n\n```bash\ndeno add @joshlong145/span\n```\n\n## Example JS\n\n```javascript\nclass Example extends WorkerDefinition {\n  public constructor() {\n    super();\n  }\n\n  addOne = (\n    buffer: SharedArrayBuffer,\n    args: Record\u003cstring, any\u003e,\n  ): SharedArrayBuffer =\u003e {\n    console.log(\"param name value: \", args.name);\n    const arr = new Int8Array(buffer);\n    arr[0] += 1;\n    return buffer;\n  }\n\n  fib = (\n    buffer: SharedArrayBuffer,\n    module: Record\u003cstring, any\u003e,\n  ): SharedArrayBuffer =\u003e {\n    let i;\n    const arr = new Uint8Array(buffer);\n    arr[0] = 0;\n    arr[1] = 1;\n\n    for (i = 2; i \u003c= module.count; i++) {\n      arr[i] = arr[i - 2] + arr[i - 1];\n      console.log(arr[i]);\n    }\n    \n    return buffer;\n  }\n}\n\nconst example: Example = new Example();\n\nconst wrapper: InstanceWrapper\u003cExample\u003e = new InstanceWrapper\u003cExample\u003e(\n  example,\n  {} as InstanceConfiguration,\n);\n\nwrapper.start();\n\nawait example.execute(\"addOne\", {name: 'foo'}).promise.then((buf: SharedArrayBuffer) =\u003e {\n  console.log(\"add one result: \", new Int32Array(buf));\n});\nawait example.execute(\"addOne\", { name: \"foo\" }).promise.then(\n  (buf: SharedArrayBuffer) =\u003e {\n    console.log(\"add one result \", new Int32Array(buf)[0]);\n  },\n);\n\nawait example.execute(\"fib\", {count: 10}).promise.then((buffer: SharedArrayBuffer) =\u003e {\n  console.log('fib result ', new Uint8Array(buffer));\n  console.log('last fib number', new Uint8Array(buffer)[10]);\n});\n```\n\nUsage of generated code\n\n```javascript\nclass Example extends WorkerDefinition {\n  public constructor() {\n    super();\n  }\n\n  addOne = (\n    buffer: SharedArrayBuffer,\n    args: Record\u003cstring, any\u003e,\n  ): SharedArrayBuffer =\u003e {\n    console.log(\"param name value: \", args.name);\n    const arr = new Int8Array(buffer);\n    arr[0] += 1;\n    return buffer;\n  }\n\n  fib = (\n    buffer: SharedArrayBuffer,\n    module: Record\u003cstring, any\u003e,\n  ): SharedArrayBuffer =\u003e {\n    let i;\n    const arr = new Uint8Array(buffer);\n    arr[0] = 0;\n    arr[1] = 1;\n\n    for (i = 2; i \u003c= module.count; i++) {\n      arr[i] = arr[i - 2] + arr[i - 1];\n      console.log(arr[i]);\n    }\n    \n    return buffer;\n  }\n}\nconst example: Example = new Example();\n\nconst wrapper: InstanceWrapper\u003cExample\u003e = new InstanceWrapper\u003cExample\u003e(\n  example,\n  {\n    outputPath: \"/path/to/gen/output\"\n  } as InstanceConfiguration,\n);\n\nwrapper.create();\nimport { foo } from \"\u003cpath/to/bridge.js\u003e\";\nawait foo().then(() =\u003e {\n  console.log(\"bar\");\n});\n```\n\n## Usage in process (uses example from above)\n\n```javascript\nconst example: WorkerDefinition = new Example();\n\nconst wrapper: InstanceWrapper\u003cExample\u003e = new InstanceWrapper\u003cExample\u003e(example, {\n    outputPath: 'output'\n});\n\nwrapper.start();\nawait example.execute('fib' {count: 10}).promise.then((buffer: SharedArrayBuffer) =\u003e {\n  console.log(\"final fib number\", new Uint8Array(buffer)[10]);\n});\n\nexample.terminateWorker();\n```\n\n# Example JS With WASM\n\nThe below example uses a WASM module compiled from `Golang` using `tiny-go`.\nBelow we provide the go WASM runtime as an `addon` and give a callback for\nloading the module at the given file path.\n\n```javascript\nclass Example extends WorkerDefinition {\n\n    public constructor() {\n        super();\n    }\n\n    addOne = (buffer: SharedArrayBuffer, module: any) =\u003e {\n        let arr = new Int8Array(buffer);\n        arr[0] += 1\n        //@ts-ignore\n        self.primeGenerator()\n        return arr.buffer\n    }\n}\n\nconst example: Example = new Example();\n\nconst wrapper: InstanceWrapper\u003cExample\u003e = new InstanceWrapper\u003cExample\u003e(example, {\n     addons: [\n      \"./lib/wasm_exec_tiny.js\",\n    ],\n    modulePath: \"./examples/wasm/primes-2.wasm\",\n    addonLoader: (path: string) =\u003e {\n      return Deno.readTextFileSync(path);\n    },\n    moduleLoader: (path: string) =\u003e {\n      const fd = Deno.openSync(path);\n      //import { readAllSync } from 'https://deno.land/std/io/read_all.ts';\n      return readAllSync(fd);\n    },\n});\n\nwrapper.start();\n\nawait example.execute(\"addOne\").promise.then((buf: SharedArrayBuffer) =\u003e {\n    console.log(\"buffer returned \", new Int32Array(buf))\n});\n\nexample.terminateWorker();\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshlong145%2Fspan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshlong145%2Fspan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshlong145%2Fspan/lists"}