{"id":13452605,"url":"https://github.com/creditkarma/thrift-server","last_synced_at":"2025-08-15T19:36:00.811Z","repository":{"id":39034527,"uuid":"97515605","full_name":"creditkarma/thrift-server","owner":"creditkarma","description":"Thrift core library in TypeScript","archived":false,"fork":false,"pushed_at":"2024-02-21T19:34:39.000Z","size":7987,"stargazers_count":40,"open_issues_count":34,"forks_count":15,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-03T18:41:49.680Z","etag":null,"topics":["microservices","nodejs","rpc","thrift","typescript"],"latest_commit_sha":null,"homepage":null,"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/creditkarma.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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}},"created_at":"2017-07-17T19:43:51.000Z","updated_at":"2023-09-21T15:23:40.000Z","dependencies_parsed_at":"2024-01-16T03:46:32.408Z","dependency_job_id":"d9c70073-dfcd-4768-87d9-e3d2f49b01f5","html_url":"https://github.com/creditkarma/thrift-server","commit_stats":{"total_commits":705,"total_committers":21,"mean_commits":33.57142857142857,"dds":"0.20283687943262407","last_synced_commit":"e3f1e620734155b7f7d3391a5e0c87a1a24744ed"},"previous_names":[],"tags_count":213,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creditkarma%2Fthrift-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creditkarma%2Fthrift-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creditkarma%2Fthrift-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/creditkarma%2Fthrift-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/creditkarma","download_url":"https://codeload.github.com/creditkarma/thrift-server/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248702143,"owners_count":21148114,"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":["microservices","nodejs","rpc","thrift","typescript"],"created_at":"2024-07-31T07:01:28.963Z","updated_at":"2025-04-13T10:44:26.589Z","avatar_url":"https://github.com/creditkarma.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Thrift Server\n\nA set of libraries for building microservices in Node.js, written in TypeScript.\n\nAs the name would suggest these libraries use [Apache Thrift](https://thrift.apache.org/) for service-to-service communication with RPC. All libraries come ready with distributed tracing through [Zipkin](https://zipkin.io/).\n\nThe available libraries:\n* [Thrift Server Hapi](./packages/thrift-server-hapi): Plugin to add Thrift support to Hapi.\n* [Thrift Server Express](./packages/thrift-server-express): Middleware to add Thrift support to Express.\n* [Thrift Client](./packages/thrift-client): Thrift HTTP client built on top of [Request](https://github.com/request/request) and a TCP client build on Node sockets. Both support communicating with services created by the Twitter [Finagle](https://github.com/twitter/finagle) project.\n\n*Note: Thrift Server is young and will still be undergoing some breaking changes before v1.0.0. The rule of thumb before 1.0.0 is that minor releases will potentially include breaking changes, but patch versions will not.*\n\n## Development\n\nTo build and run `thrift-server` locally you can follow these steps.\n\nFirst, clone the repo:\n\n```sh\n$ git clone https://github.com/creditkarma/thrift-server.git\n```\n\nBecause `thrift-server` is a mono-repo containing multiple libraries, we use [lerna](https://lernajs.io/) to manage inter-dependencies. Running common `npm` commands at the project root will run these commands in all the packages.\n\nInstall dependencies and build libraries:\n\n```sh\n$ cd thrift-server\n$ npm install\n$ npm run build\n```\n\nTo see things working you can run `npm test`:\n\n```sh\n$ npm test\n```\n\n## Building a Working Application\n\nLet's make a quick working application with the included libraries.\n\nWe'll do this step by step:\n\n* Create a project\n* Install dependencies\n* Define our service\n* Run codegen on our Thrift IDL\n* Create a service\n* Create a service client\n* Make service calls with our client\n\n### Create a Project Directory\n\nWe need a place to build things:\n\n```sh\n$ mkdir thrift-example\n$ cd thrift-example\n```\n\nNext initialize our workspace:\n\n```sh\n$ git init\n$ npm init\n```\n\nI create directories for our source code and our Thrift IDL:\n\n```sh\n$ mkdir thrift\n$ mkdir src\n```\n\n#### Setting up TypeScript\n\nI'm going to be using TypeScript so I'm going to add a `tsconfig.json` file to my project root.\n\nThat file looks like this:\n\n```json\n{\n    \"compilerOptions\": {\n        \"target\": \"es6\",\n        \"module\": \"commonjs\",\n        \"moduleResolution\": \"node\",\n        \"sourceMap\": true,\n        \"declaration\": true,\n        \"rootDir\": \"./src\",\n        \"outDir\": \"./dist\",\n        \"noEmitOnError\": true,\n        \"strict\": true,\n        \"noUnusedLocals\": true,\n        \"pretty\": true\n    },\n    \"exclude\": [\n        \"node_modules\",\n        \"dist\"\n    ]\n}\n```\n\nI'm also going to add some scripts to by `package.json` to build the TypeScript:\n\n```json\n\"scripts\": {\n    // ...\n    \"prebuild\": \"rm -rf dist\",\n    \"build\": \"tsc\",\n    // ...\n}\n```\n\n### Install Dependencies\n\nBecause Thrift Server is developed with TypeScript and recommended usage is with TypeScript, all Thrift Server libraries define dependencies as peer dependencies to avoid type collisions.\n\n```sh\n$ npm install --save-dev typescript\n$ npm install --save-dev @creditkarma/thrift-typescript\n$ npm install --save @creditkarma/thrift-server-core\n$ npm install --save @creditkarma/thrift-server-hapi\n$ npm install --save @creditkarma/thrift-client\n$ npm install --save request\n$ npm install --save @types/request\n$ npm install --save hapi\n$ npm install --save @types/hapi\n```\n\n### Example Service\n\nOur Thrift service contract looks like this:\n\n```c\nservice Calculator {\n  i32 add(1: i32 left, 2: i32 right)\n  i32 subtract(1: i32 left, 2: i32 right)\n}\n```\n\nI save this file in my project as `thrift/calculator.thrift`.\n\n### Generating Service Code\n\nWe generate TypeScript from our Thrift IDL using [thrift-typescript](https://github.com/creditkarma/thrift-typescript). In my `package.json` I add something like this:\n\n**v0.9.x of this library requires thrift-typescript v3.x**\n**v0.7.x - 0.8.x of this library requires thrift-typescript v2.x**\n\n```json\n\"scripts\": {\n    // ...\n    \"codegen\": \"thrift-typescript --target thrift-server --sourceDir thrift --outDir src/generated\",\n    // ...\n}\n```\n\nNo we can can generate our service interfaces by:\n\n```sh\n$ npm run codegen\n```\n\nIf everything went well there should now be a new file at `src/generated/calculator.ts`.\n\nEvery generated service exports 3 common types (others may be exported on a service-to-service basis). In the `\u003cservice-name\u003e.ts` file `service` becomes a `namespace` so there is now a `namespace` in `calculator.ts` called `Calculator`. The 3 types I mentioned are nested in this `namespace`.\n\nThe three common types:\n\n* IHandler: An interface for the service methods\n* Processor: A class that is constructed with an object of type `IHandler`. This handles decoding service requests and encoding service responses.\n* Client: A class that provides the public interface for consumers. This handles encoding service requests and decoding service responses.\n\n### Creating a Service\n\nTo create a Thrift service you need to first choose you Node Http server library. Thrift Server supports either Express or Hapi. For this example we are using Hapi, but the Express usage is almost identical.\n\nNo matter which option you choose Thrift support is added to the chosen server via plugin/middleware.\n\nWe need a new file. I'm calling mine `src/server.ts`.\n\nThe code to implement this service is pretty straight-forward:\n\n```typescript\nimport * as Hapi from 'hapi'\nimport { ThriftServerHapi } from '@creditkarma/thrift-server-hapi'\nimport { Calculator } from './generated/calculator'\n\nconst PORT: number = 8080\n\nconst server = new Hapi.Server()\n\nserver.connection({ port: PORT })\n\n/**\n * Implementation of our Thrift service.\n *\n * Notice the second parameter, \"context\" - this is the Hapi request object,\n * passed along to our service by the Hapi Thrift plugin. Thus, you have access to\n * all HTTP request data from within your service implementation.\n */\nconst serviceHandlers: Calculator.IHandler\u003cHapi.Request\u003e = {\n    add(left: number, right: number, context?: express.Request): number {\n        return left + right\n    },\n    subtract(left: number, right: number, context?: express.Request): number {\n        return left - right\n    },\n}\n\nconst processor: Calculator.Processor\u003cHapi.Request\u003e = new Calculator.Processor(serviceHandlers)\n\n/**\n * Register the Thrift plugin.\n *\n * This plugin adds a route to your server for handling Thrift requests. The path\n * option is the path to attach the route handler to and the handler is the\n * Thrift service processor instance.\n */\nserver.register(ThriftServerHapi\u003cCalculator.Processor\u003e({\n    path: '/thrift',\n    thriftOptions: {\n        serviceName: 'calculator-service',\n        handler: processor,\n    }\n}), err =\u003e {\n    if (err) {\n        throw err\n    }\n})\n\n/**\n * Start your hapi server\n */\nserver.start((err) =\u003e {\n    if (err) {\n        throw err\n    }\n    server.log('info', `Thrift service running on port ${PORT}`)\n})\n```\n\n### Creating a Service Client\n\nCreating a service client is similarly not that difficult.\n\nI'm adding the following code to a file called `src/client.ts`.\n\n```typescript\nimport {\n    createHttpClient,\n    RequestOptions,\n} from '@creditkaram/thrift-client'\n\nimport { Calculator } from './codegen/calculator'\n\n// Create Thrift client\nconst thriftClient: Calculator.Client\u003cRequestOptions\u003e = createHttpClient(Calculator.Client, {\n    serviceName: 'calculator-service',\n    hostName: 'localhost', // The host of the service to connect to\n    port: 8080, // The port of the service to connect to\n    requestOptions: {} // RequestOptions to pass to got\n})\n```\n\nThe `thrift-client` library uses [Request](https://github.com/request/request) as its underlying Http client. You will notice in the sample code the `requestOptions` parameter. This is optional and is passed through to the Request instance. This can be used to handle things like serving Thrift with TLS.\n\n### Making Service Calls\n\nOkay, so we have a service and a client, let's see this thing in action. To do that we're going to setup a simple web server in front of our Thrift client.\n\nBecause we're already using Hapi, let's add this to our `src/client.ts` file:\n\n```typescript\nimport {\n    createHttpClient,\n    RequestOptions,\n} from '@creditkaram/thrift-client'\n\nimport * as Hapi from 'hapi'\n\nimport { Calculator } from './codegen/calculator'\n\n// Create Thrift client\nconst thriftClient: Calculator.Client\u003cRequestOptions\u003e = createHttpClient(Calculator.Client, {\n    serviceName: 'calculator-service',\n    hostName: 'localhost',\n    port: 8080,\n    requestOptions: {} // RequestOptions to pass to got\n})\n\nconst server = new Hapi.Server({ debug: { request: ['error'] } })\n\nconst PORT = 9000\nserver.connection(PORT)\n\nserver.route({\n    method: 'GET',\n    path: '/add/{left}/{right}',\n    handler(request: Hapi.Request, reply: Hapi.ReplyWithContinue) {\n        thriftClient.add(request.params.left, request.params.right)\n            .then((response: RecommendationsResponse) =\u003e {\n                reply(response)\n            })\n            .catch((err: any) =\u003e {\n                reply(err)\n            })\n    },\n})\n\nserver.start((err: any) =\u003e {\n    if (err) {\n        throw err\n    }\n    server.log('info', `Web server running on port ${PORT}`)\n})\n```\n\nI'm also going to add a file `src/index.ts` that will start the service and the client.\n\n```typescript\nimport { fork } from 'child_process'\n\nconst clientProc = fork('./client.js')\nconst serverProc = fork('./server.js')\n\nfunction exit(code: number) {\n    clientProc.kill()\n    serverProc.kill()\n    process.exitCode = code\n}\n\nprocess.on('SIGINT', () =\u003e {\n    console.log('Caught interrupt signal')\n    exit(0)\n})\n```\n\nBack in `package.json` I'm going to add another script to start our app:\n\n```json\n\"scripts\": {\n    // ...\n    \"start\": \"npm run codegen \u0026\u0026 npm run build \u0026\u0026 node dist/index.js\",\n    // ...\n}\n```\n\nFinally, we can:\n\n```sh\n$ npm start\n```\n\nAnd:\n\n```sh\n$ curl http://localhost:9000/add/5/6\n```\n\n## Contributing\n\nFor more information about contributing new features and bug fixes, see our [Contribution Guidelines](./CONTRIBUTING.md).\nExternal contributors must sign Contributor License Agreement (CLA)\n\n## License\n\nThis project is licensed under [Apache License Version 2.0](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcreditkarma%2Fthrift-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcreditkarma%2Fthrift-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcreditkarma%2Fthrift-server/lists"}