{"id":15287865,"url":"https://github.com/morglod/rpct-js","last_synced_at":"2025-04-13T06:09:12.053Z","repository":{"id":37851757,"uuid":"204554826","full_name":"Morglod/rpct-js","owner":"Morglod","description":"RPC universal toolkit with lots of session environment \u0026 callbacks support","archived":false,"fork":false,"pushed_at":"2023-01-04T11:01:42.000Z","size":1021,"stargazers_count":7,"open_issues_count":13,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-13T06:08:32.100Z","etag":null,"topics":["callbacks","figma","figma-plugin","figma-plugins","figma-rpc","rpc","rpc-framework","rpc-library","socket","streams","transport","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Morglod.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}},"created_at":"2019-08-26T20:21:17.000Z","updated_at":"2024-04-02T13:08:57.000Z","dependencies_parsed_at":"2023-02-02T09:32:01.706Z","dependency_job_id":null,"html_url":"https://github.com/Morglod/rpct-js","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Frpct-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Frpct-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Frpct-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Morglod%2Frpct-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Morglod","download_url":"https://codeload.github.com/Morglod/rpct-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248670435,"owners_count":21142904,"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":["callbacks","figma","figma-plugin","figma-plugins","figma-rpc","rpc","rpc-framework","rpc-library","socket","streams","transport","typescript"],"created_at":"2024-09-30T15:38:58.939Z","updated_at":"2025-04-13T06:09:12.019Z","avatar_url":"https://github.com/Morglod.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![NPM Version](https://badge.fury.io/js/rpct.svg?style=flat)](https://www.npmjs.com/package/rpct)\n\n# rpct\n\nRPC toolkit.\n\nGoal: make simpliest for usage, zero-effort remote control library.\n\nApi\u003cMethods\u003e -\u003e Transport -\u003e { ... session ... } -\u003e Transport -\u003e Api\u003cMethods\u003e\n\nApi operates with messages.  \nIt can receive message and invoke local method.  \nIt can emit message and send to remote api to invoke remote method.  \nIt can pass callbacks as arguments.  \nIt raises up remote exceptions.  \n\nFully TypeScript'ed.\n\nApi can be easily extended with [middlewares \u0026 hooks](./src/middlewares).\n\nTransport operates with data serialization and deserialization. It resend messages over any session to remote connected Transport.\n\nBrowser minified sizes:  \n* 17kb (without compression)\n* 4kb (gzipped)\n\n#### Example\n\nLocal:\n```ts\nlet counter = 0;\nsetInterval(() =\u003e counter++, 1000);\n\nfunction listenCounter(onChange) {\n    watchProperty(() =\u003e counter).on('change', onChange);\n}\n\n// ...\n\nnew Api({\n    listenCounter,\n}, transport);\n```\n\nRemote:\n```ts\n// ...\n\napi.listenCounter(bindCallback(counter =\u003e {\n    console.log('counter', counter);\n}));\n```\n\n## Some stats\n\njson stream without callbacks:  \n0.1ms per request\n9600rps\n\njson stream with callbacks:  \n0.2ms per request\n5000rps\n\n## Usage\n\nInstall from npm:\n```\nnpm i rpct\n```\n\nPick browser minified version and use global `RPCT` object:\n```html\n\u003cscript src=\"https://unpkg.com/rpct/browser/rpct.min.js\"\u003e\u003c/script\u003e\n```\n\nOr import browser, lightweight version for bundling:\n```ts\nimport * as rpct from 'rpct/browser';\n```\n\n[check out browser examples](./browser)\n\n## Transports\n\nas Transport may be implemented any environment, eg:\n\n* Streams\n* Socket.io\n* DOM Window\n* System sockets\n* Figma UI-plugin\n* WebSockets\n\n[check out examples](./src/examples)\n\nWith stream trasport you can use any streamable format like [json](./src/examples/pipe-socket-json.ts) or [msgpack](./src/examples/pong-pipe-socket-msgpack.ts).\n\n## Figma Plugin Example\n\nDefine \"protocol\":\n```ts\ninterface PluginMethods {\n    createRectangle(width: number, height: number): string;\n}\n\ninterface UIMethods {}\n```\n\nIn ui:\n```ts\npluginApi = connectToPlugin\u003cPluginMethods, UIMethods\u003e({});\n\n// invoke createRectangle(100, 50)\ncreatedNodeId = await pluginApi.callMethod('createRectangle', 100, 50);\n```\n\nIn plugin:\n```ts\nuiApi = connectToUI\u003cPluginMethods, UIMethods\u003e(figma, {\n    createRectangle(width, height) {\n        const rect = figma.createRectangle();\n        rect.resize(width, height);\n        figma.currentPage.appendChild(rect);\n        return rect.id;\n    }\n});\n```\n\nYou can use minified version from CDN (global `RPCT` object):\n```html\n\u003cscript src=\"https://unpkg.com/rpct/browser/rpct.min.js\"\u003e\u003c/script\u003e\n```\n\n## Window-Frame Example\n\nConnect to frame, call remote `sum` method and pass numbers \u0026 callbacks.  \nRemote method do sums and call remote callbacks.\n\nParent window script:\n```js\nvar frame = document.getElementById('target');\n\nvar streamTransport = RPCT.connectToDOM(window, frame.contentWindow);\nvar api = RPCT.proxyMapRemote(new RPCT.Api({}, streamTransport));\n\napi.sum(\n    10, 20, // a, b\n    sumResult =\u003e console.log('sum:', sumResult), // sumCallback\n    mulResult =\u003e console.log('mul:', mulResult), // mulCallback\n);\n```\n\nInner frame script:\n```js\nvar streamTransport = RPCT.connectToDOM(window, window.parent);\n\nvar remoteApi = new RPCT.Api({\n    // api methods here\n    sum(a, b, sumCallback, mulCallback) {\n        console.log(`called sum(${a}, ${b})`);\n        sumCallback(a + b);\n        mulCallback(a * b);\n    },\n}, streamTransport);\n```\n\n## Watch remote counter?\n\nIn this code we call server's `listenCounter` method, pass client's callback for `onChange` event.  \nThen client will print `counter 0, 1, 2, 3...`.\n\nThis is [fully working example](./src/examples/watch-changes.ts).\n\n```ts\n// Open local session for testing\nconst session = simpleCrossStream\u003cITransportProtocol\u003e();\n\ntype ApiSchema = {\n    listenCounter(\n        onChange: (x: number) =\u003e void,\n    ): void;\n};\n\n(async function server() {\n    // counter\n    let counter = 0;\n    setInterval(() =\u003e counter++, 1000);\n\n    function listenCounter(onChange: (x: number) =\u003e void) {\n        watchProperty(() =\u003e counter).on('change', onChange);\n    }\n\n    const remoteStreamTransport = new DuplexStreamTransport(session.a, undefined, 'remote');\n    const remoteApi = new Api\u003c{}, ApiSchema\u003e({\n        listenCounter,\n    }, remoteStreamTransport);\n})();\n\n(async function client() {\n    const localStreamTransport = new DuplexStreamTransport(session.b, undefined, 'local');\n    const localApi = new Api\u003cApiSchema, {}\u003e({}, localStreamTransport);\n    const api = proxyMapRemote(localApi);\n\n    api.listenCounter(bindCallback(counter =\u003e {\n        console.log('counter', counter);\n    }));\n})();\n\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorglod%2Frpct-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmorglod%2Frpct-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmorglod%2Frpct-js/lists"}