{"id":16372563,"url":"https://github.com/bencompton/ghost-rpc","last_synced_at":"2026-03-13T20:30:19.410Z","repository":{"id":44776523,"uuid":"374717830","full_name":"bencompton/ghost-rpc","owner":"bencompton","description":"Develop the full-stack in the browser, test the full-stack with fast integration tests, and deploy the back-end in Node.js, all with minimum effort and maximum re-use.","archived":false,"fork":false,"pushed_at":"2022-05-23T11:09:16.000Z","size":907,"stargazers_count":0,"open_issues_count":2,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-31T17:25:43.449Z","etag":null,"topics":["fastify","node-js","rpc"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bencompton.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}},"created_at":"2021-06-07T15:38:30.000Z","updated_at":"2021-11-08T16:27:06.000Z","dependencies_parsed_at":"2022-07-20T17:18:42.690Z","dependency_job_id":null,"html_url":"https://github.com/bencompton/ghost-rpc","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/bencompton%2Fghost-rpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bencompton%2Fghost-rpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bencompton%2Fghost-rpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bencompton%2Fghost-rpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bencompton","download_url":"https://codeload.github.com/bencompton/ghost-rpc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239921877,"owners_count":19718842,"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":["fastify","node-js","rpc"],"created_at":"2024-10-11T03:11:47.197Z","updated_at":"2026-03-13T20:30:19.353Z","avatar_url":"https://github.com/bencompton.png","language":"TypeScript","readme":"\u003cimg src=\"./assets/infographic.png\" alt=\"Ghost RPC Logo\" /\u003e\n\n## Overview\n\nThe primary use case for Ghost RPC is to allow you to develop the full stack in the browser with mock data, create fast and stable full-stack integration tests with the same mock data, and then run your back-end in Node.js everywhere else, all with minimum effort and maximum re-use.\n\nGhost RPC is designed for extreme productivity, testability, and minimal boilerplate for browser-based front-ends with Node.js back-ends. Ghost RPC leverages JavaScript proxies and provides a fluent TypeScript / JavaScript API to allow you to define and invoke your services and create highly testable apps with minimal wasted effort.\n\nWhile RESTful semantics are useful for creating standards-based APIs that can be exposed to various consumers, when the only goal is to invoke some code on the back-end (e.g., from a React SPA), and your API is only called from your front-end, RESTful semantics are overkill. In this case, a lot of time and energy is wasted adhering to HTTP semantics, like using the correct verb, HTTP status code, etc., and this additional effort yields little benefit. Ghost RPC is a productive alternative to Node.js RESTful APIs.\n\n## Installation\n\nGhost RPC:\n\n```bash\nnpm install ghost-rpc\n```\n\nFastify plug-in:\n\n```\nnpm install ghost-rpc-fastify\n```\n\n## Ghost RPC in Action\n\nLet's assume your app has the following service classes that comprise your back-end API:\n\n```typescript\n// services/add-subtract-service.ts\n\nexport class AddSubtractService {\n  public add(x: number, y: number) {\n    return x + y;\n  }\n\n  public subtract(x: number, y: number) {\n    return x - y;\n  }\n}\n\n// services/multiply-divide-service.ts\n\nexport class MultiplyDivideService {\n  public multiply(x: number, y: number) {\n    return number1 * number2;\n  }\n\n  public divide(x: number, y: number) {\n    return x / y;\n  }\n}\n```\n\nThe first step with Ghost RPC is to create a factory for your services to allow Ghost RPC to instantiate a fresh instance of the appropriate service class per request. If using TypeScript, you would also create an interface representing all of the services in your app, as shown below.\n\n```typescript\n  // services/index.ts\n\n  import { ServicesFactory } from 'ghost-rpc';\n\n  import { CalculatorService } from './services/calculator-service';\n  import { TodoService } from './services/todo-service';\n\n  export interface IAppServices {\n    addSubtractService: AddSubtractService;\n    multiplyDivideService: MultiplyDivideService;\n  }\n\n  export const servicesFactory: ServicesFactory\u003cIAppServices\u003e = {\n    addSubtractService: () =\u003e new AddSubtractService(),\n    multiplyDivideService: () =\u003e new MultiplyDivideService()\n  } \n```\n\nNext, we use the ghost-rpc-fastify plug-in to expose all of your services on the URL path of your choosing (e.g., /api/):\n\n```typescript\n  import { createFastifyMiddleware }\n  import { servicesFactory } from './services/';\n\n  const server = fastify();\n  const ghostRpcMiddleware = createFastifyMiddleware('/api/', servicesFactory);\n  server.register(ghostRpcMiddleware);\n  \n  ...\n```\n\nTo call your services hosted in Fastify, you would create a Ghost RPC proxy with a HTTP Transport Handler (specifying the same URL path you used above, e.g., /api/):\n\n```typescript\nimport { createProxy, createHttpTransportHandler } from 'ghost-rpc';\n\nimport { IAppServices } from './services/';\n\nconst handler = createHttpTransportHandler('/api/');\nconst proxy = createProxy\u003cIAppServices\u003e(handler);\n\nconst sum = await proxy.addSubtractService.add(2, 2);\nconsole.log(sum); // 4\n\nconst product = await proxy.multiplyDivideService.divide(4, 2);\nconsole.log(product); // 2\n```\n\nWhen you setup your services in Node.js via the Fastify plug-in and configure the client proxy with an HTTP Transport Handler, each method invocation on a service proxy from the client-side results in Ghost RPC generating an HTTP POST request with JSON payloads in the request and response bodies to a human-readable URL like `https://mydomain.com/api/addSubtractService/add`.\n\nOn the other hand, to run the full-stack in the browser for development or leverage your services in integration tests, the only difference is that you pass a Local Handler instead of an HTTP Transport Handler into your proxy. The local handler directly invokes methods in your service classes with no I/O rather than using HTTP to connect to your services running in Node.js.\n\n```typescript\nimport { createProxy, createLocalHandler } from 'ghost-rpc';\n\nimport { IAppServices, servicesFactory } from './services/';\n\nconst handler = createLocalHandler(servicesFactory);\nconst proxy = createProxy\u003cIAppServices\u003e(handler);\n\nconst sum = await proxy.addSubtractService.add(2, 2);\n\nconsole.log(sum); // 4\n```\n\n## Examples\n\n* [Shopping Cart App](./examples/shopping-cart-app) - A demo showcasing Ghost RPC with React, Redux and TypeORM + SQL.js. The same service classes, database schema, data access logic, and front-end Redux state management logic are exercised from integration tests, the full stack running in the browser (mock mode), and the stack separated between the browser and Node.js (full mode).\n\n* [Benchmark](./examples/benchmark) - Compares the performance of Ghost RPC Fastify to plain Fastify\n\n## API Docs (WIP)\n\n* Proxies\n* Service factories\n* Local / Transport Handlers\n* Pre-request hooks\n* Global request and response params\n* Error handling\n\n## Future Plans\n\n* Additional transport handlers (e.g, binary instead of HTTP + JSON)\n* Middleware plug-ins for auth, etc. with the ability to use decorators to apply middleware per service class / method\n* Support for other Node.js frameworks (e.g., Express, Hapi)\n* Ability to run as a stand-alone server with no need for Fastify, Express, etc.\n* Deno support\n* Possibly support FaaS deployments (e.g., AWS Lambda)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbencompton%2Fghost-rpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbencompton%2Fghost-rpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbencompton%2Fghost-rpc/lists"}