{"id":19493577,"url":"https://github.com/fwextensions/figma-await-ipc","last_synced_at":"2025-04-25T20:31:18.915Z","repository":{"id":194155882,"uuid":"686216378","full_name":"fwextensions/figma-await-ipc","owner":"fwextensions","description":"A simple await-able replacement for postMessage in Figma plugins","archived":false,"fork":false,"pushed_at":"2023-11-18T03:32:07.000Z","size":435,"stargazers_count":14,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-20T23:47:19.513Z","etag":null,"topics":["await","figma","figma-api","figma-plugin","ipc","postmessage"],"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/fwextensions.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}},"created_at":"2023-09-02T04:06:19.000Z","updated_at":"2025-04-12T19:10:14.000Z","dependencies_parsed_at":"2023-11-10T21:27:19.202Z","dependency_job_id":"a93433f8-3ada-43bd-bf4c-b2043e60efaa","html_url":"https://github.com/fwextensions/figma-await-ipc","commit_stats":null,"previous_names":["fwextensions/figma-await-call","fwextensions/figma-await-ipc"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fwextensions%2Ffigma-await-ipc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fwextensions%2Ffigma-await-ipc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fwextensions%2Ffigma-await-ipc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fwextensions%2Ffigma-await-ipc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fwextensions","download_url":"https://codeload.github.com/fwextensions/figma-await-ipc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250890367,"owners_count":21503483,"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":["await","figma","figma-api","figma-plugin","ipc","postmessage"],"created_at":"2024-11-10T21:26:38.773Z","updated_at":"2025-04-25T20:31:18.638Z","avatar_url":"https://github.com/fwextensions.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# figma-await-ipc\n\n\u003e A simple `await`-able replacement for `postMessage()` in Figma plugins\n\nFigma plugins typically use `postMessage()` to send data back and forth between the main and UI threads, but managing all those asynchronous events and handlers can be tedious.  With `figma-await-ipc`, you can simply `await` the response to get a synchronous-style flow, like:\n\n```typescript\nconst title = await call(\"getProperty\", \"title\");\nfigma.currentPage.selection[0].characters = title;\n```\n\n\n## Installation\n\n```shell\nnpm install figma-await-ipc\n```\n\n\n## Usage\n\nIn a Figma plugin, the code that has access to the document API and the code that renders the UI are in different contexts, so you need to use `postMessage()` to send a request for data from one thread to the other.  The other thread then needs to listen for the `\"message\"` event and respond by calling `postMessage()` to send back the requested data.  The source thread then *also* needs to listen for the `\"message\"` event to receive the requested data.\n\nAll of this asynchronous event handling is an awkward fit for what is conceptually a synchronous function call.  The `figma-await-ipc` package wraps this process with a simpler interface.\n\nThe package's `call()` function lets you essentially call a named function in the other thread, while awaiting the promised result.  Any parameters you pass to `call()` after the function name will be passed into the receiving function:\n\n```typescript\n// main.ts\nimport { call } from \"figma-await-ipc\";\n\ntry {\n  const title = await call(\"getProperty\", \"title\");\n  figma.currentPage.selection[0].characters = title;\n} catch (error) {\n  console.error(\"Error fetching name property:\", error);\n}\n```\n\nIf the called \"function\" throws an exception in the other thread, that error will be caught and then rethrown in the current thread, so you should wrap the `call()` in a `try/catch` when you know that may happen.\n\nYou can also use a standard `then()` method to handle the returned promise:\n\n```typescript\ncall(\"getProperty\", \"title\")\n  .then((title) =\u003e figma.currentPage.selection[0].characters = title)\n  .catch(console.error);\n```\n\nOf course, making a call from one thread won't do anything if there's nothing in the other thread to receive that call.  So every `call()` to a particular name must be paired with a `receive()` in the other thread to provide a function that will respond to that name:\n\n```typescript\n// ui.tsx\nimport { receive } from \"figma-await-ipc\";\n\nconst storedProperties = { ... };\n\nreceive(\"getProperty\", (key) =\u003e {\n  if (!(key in storedProperties)) {\n    throw new Error(`Unsupported property: ${key}`);\n  }\n\n  return storedProperties[key];\n});\n```\n\nAny number of `call()/receive()` pairs can exist within a plugin.\n\nNote that if your code awaits a call to a name that has no receiver registered in the other thread, then it will be queued, and execution will hang at that point.  The call will be connected if a receiver is later registered for that name.  This is useful if one thread starts making calls before the other thread is fully initialized.\n\n\n## API\n\n\n### `call(name, [...data])`\n\nMakes a call between the main and UI threads, in either direction.\n\n* `name`: The name of the receiver in the other thread that is expected to respond to this call.\n* `...data`: Zero or more parameters to send to the receiver.  They must be of types that can be passed through `postMessage()` via the [structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm).\n\nReturns a promise that should be awaited until the other side responds, and which will be resolved with the return value of the receiver function.\n\nIf the receiver function throws an exception, that exception will be rethrown from `call()`, so you should use `try/catch` or `.catch()` to handle that case.\n\n\u003cbr\u003e\n\n### `receive(name, receiverFn)`\n\nRegisters a function to receive calls with a particular name.  It will receive whatever parameters are passed to the `call()` function.\n\n* `name`: The name of the receiver.\n* `receiverFn`: The function that will receive calls to the `name` parameter.\n\nWhen a call is received, the return value from `receiverFn` will be sent back to the caller.  If it returns a promise, then no response will be sent to the caller until the promise resolves.\n\nCalls to a name that has no receiver will be queued until one is registered, at which point they will be delivered to that new `receiverFn` in order.\n\nOnly a single function can respond to any given name, so subsequent calls to `receive()` will replace the previously registered function.\n\n\u003cbr\u003e\n\n### `ignore(name)`\n\nUnregisters the receiver for a given function name.\n\n* `name`: The name of the receiver to unregister.\n\nSubsequent calls from the other thread to the unregistered name will be queued until a new function is registered for it.\n\n\n## License\n\n[MIT](./LICENSE) © [John Dunning](https://github.com/fwextensions)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffwextensions%2Ffigma-await-ipc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffwextensions%2Ffigma-await-ipc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffwextensions%2Ffigma-await-ipc/lists"}