{"id":19903396,"url":"https://github.com/stargate/stargate-grpc-node-client","last_synced_at":"2025-05-03T00:31:03.668Z","repository":{"id":44869914,"uuid":"410067414","full_name":"stargate/stargate-grpc-node-client","owner":"stargate","description":"A JS gRPC client for https://stargate.io","archived":false,"fork":false,"pushed_at":"2022-01-21T14:15:37.000Z","size":186,"stargazers_count":4,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-08-09T17:13:28.147Z","etag":null,"topics":["grpc","javascript","nodejs","stargate","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/stargate.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2021-09-24T18:39:41.000Z","updated_at":"2023-06-10T19:23:32.000Z","dependencies_parsed_at":"2022-09-10T19:11:49.600Z","dependency_job_id":null,"html_url":"https://github.com/stargate/stargate-grpc-node-client","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stargate%2Fstargate-grpc-node-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stargate%2Fstargate-grpc-node-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stargate%2Fstargate-grpc-node-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stargate%2Fstargate-grpc-node-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stargate","download_url":"https://codeload.github.com/stargate/stargate-grpc-node-client/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224343041,"owners_count":17295566,"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":["grpc","javascript","nodejs","stargate","typescript"],"created_at":"2024-11-12T20:23:34.895Z","updated_at":"2024-11-12T20:23:35.654Z","avatar_url":"https://github.com/stargate.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Stargate Node gRPC Client\n\nThis package provides the ability for Node applications to communicate with the [Stargate data gateway](https://stargate.io/) via gRPC.\n\n**Note: This package is for use in applications running on Node servers, NOT gRPC web clients running in browsers.**\n\n- [Quick start guide](#quick-start-guide)\n  * [Connecting](#connecting)\n  * [Authentication](#authentication)\n    + [Generating authentication metadata](#generating-authentication-metadata)\n  * [Querying](#querying)\n  * [Processing the result set](#processing-the-result-set)\n    + [Reading primitive values](#reading-primitive-values)\n    + [Reading CQL data types](#reading-cql-data-types)\n  * [Promise support](#promise-support)\n  * [Example uses](#example-uses)\n- [Issue Management](#issue-management)\n\n## Quick start guide\n\nTo begin, you'll need to add the necessary dependency to your project:\n\nUsing NPM:\n\n```shell\nnpm i @stargate-oss/stargate-grpc-node-client\n```\n\nUsing Yarn:\n\n```shell\nyarn add @stargate-oss/stargate-grpc-node-client\n```\n\nIf you don't already have access to a Stargate deployment one can be started quickly for testing using the following Docker\ncommand to run Stargate locally in developer mode and expose port 8090 for gRPC connections:\n\n```shell\ndocker run --name stargate \\\n  -p 8081:8081 \\\n  -p 8090:8090 \\\n  -d \\\n  -e CLUSTER_NAME=stargate \\\n  -e CLUSTER_VERSION=3.11 \\\n  -e DEVELOPER_MODE=true \\\n  stargateio/stargate-3_11:v1.0.40\n```\n\nEnsure the local instance of Stargate is running properly by tailing the logs for the container with `docker logs -f stargate`. When you see this message, Stargate is ready for traffic:\n\n`Finished starting bundles.`\n\n### Connecting\n\nTo connect to your Stargate instance set up the client as follows. This example assumes that you're running Stargate locally\nwith the default credentials of `cassandra/cassandra`. For more information regarding authentication please see the\n[Stargate authentication and authorization docs](https://stargate.io/docs/stargate/1.0/developers-guide/authnz.html).\n\n```typescript\nimport * as grpc from \"@grpc/grpc-js\";\nimport { StargateClient, StargateTableBasedToken, Query, Response, promisifyStargateClient } from \"@stargate-oss/stargate-grpc-node-client\";\n\n// Create a client for Stargate/Cassandra authentication using the default C* username and password\nconst creds = new StargateTableBasedToken({authEndpoint: 'http://localhost:8081/v1/auth', username: 'cassandra', password: 'cassandra'});\n\n// Create the gRPC client, passing it the address of the gRPC endpoint\nconst stargateClient = new StargateClient('localhost:8090', grpc.credentials.createInsecure());\n\n// Create a promisified version of the client, so we don't need to use callbacks\nconst promisifiedClient = promisifyStargateClient(stargateClient);\n```\n\n### Authentication\n\nThis client supports both table-based and JWT-based authentication to Stargate.\n\nFor table-based auth, use the `StargateTableBasedToken` class:\n\n```typescript\nconst tableBasedToken = new StargateTableBasedToken({authEndpoint: 'http://localhost:8081/v1/auth', username: 'cassandra', password: 'cassandra'});\n```\n\nFor JWT-based auth, use the `StargateBearerToken` class and pass your token in directly:\n\n```typescript\nconst bearerToken = new StargateBearerToken('my-token');\n```\n\n#### Generating authentication metadata\n\nIf you're connecting to Stargate through insecure gRPC credentials - e.g. to a local Stargate instance - you must manually generate metadata for each call, like so:\n\n```typescript\nconst stargateClient = new StargateClient(grpcEndpoint, grpc.credentials.createInsecure());\n\nconst promisifiedClient = promisifyStargateClient(stargateClient);\n\nconst authenticationMetadata = await creds.generateMetadata({service_url: 'http://localhost:8081/v1/auth'});\nawait promisifiedClient.executeQuery(query, authenticationMetadata);\n```\n\nThis is because the Node gRPC implementation [does not allow composing insecure credentials.](https://github.com/grpc/grpc-node/issues/543)\n\nHowever, if you're using secure gRPC credentials - e.g. connecting to a remote Stargate instance like an Astra database - you can simply include the token metadata generator when constructing the client. The metadata will automatically be generated on every call to the client:\n\n```typescript\nconst bearerToken = new StargateBearerToken('my-token');\nconst credentials = grpc.credentials.combineChannelCredentials(grpc.credentials.createSsl(), bearerToken);\n\nconst stargateClient = new StargateClient(grpcEndpoint, credentials);\nconst promisifiedClient = promisifyStargateClient(stargateClient);\n\n// No need to pass metadata; the credentials passed to the client constructor will do that for us\nawait promisifiedClient.executeQuery(query);\n```\n\nThe examples in this README are designed to work with a local Stargate instance, so they use the insecure approach.\n\n### Querying\n\nA simple query can be performed by passing a CQL query to the client:\n\n```typescript\nconst query = new Query();\nquery.setCql('select cluster_name from system.local');\n\n// Must manually generate auth metadata if using insecure creds - see authentication section above for details\nconst authenticationMetadata = await creds.generateMetadata({service_url: 'http://localhost:8081/v1/auth'});\nawait promisifiedClient.executeQuery(query, authenticationMetadata);\n```\n\nData definition (DDL) queries are supported in the same manner:\n\n```typescript\n// Create a new keyspace\nconst createKeyspaceStatement = new Query();\ncreateKeyspaceStatement.setCql(\"CREATE KEYSPACE IF NOT EXISTS ks1 WITH REPLICATION = {'class' : 'SimpleStrategy', 'replication_factor' : 1};\");\n\nawait promisifiedClient.executeQuery(query, authenticationMetadata);\n\n// Create a new table\nconst createTableStatement = new Query();\ncreateTableStatement.setCql(\"CREATE TABLE IF NOT EXISTS ks1.tbl2 (key text PRIMARY KEY,value text);\");\n\nawait promisifiedClient.executeQuery(query, authenticationMetadata);\n```\n\nParameterized queries are also supported:\n\n```typescript\nconst query = new Query();\nquery.setCql(\"select * from system_schema.keyspaces where keyspace_name = ?\");\n\nconst keyspaceNameValue = new Value();\nkeyspaceNameValue.setString(\"system\");\n\nconst queryValues = new Values();\nqueryValues.setValuesList([keyspaceNameValue]);\n\nquery.setValues(queryValues);\n\nconst queryParameters = new QueryParameters();\nqueryParameters.setTracing(false);\nqueryParameters.setSkipMetadata(false);\n\nquery.setParameters(queryParameters);\n\nconst response = await promisifiedClient.executeQuery(query, metadata);\n```\n\nIf you would like to use a [batch statement](https://cassandra.apache.org/doc/latest/cassandra/cql/dml.html#batch_statement), the client also provides an `executeBatch()` function for this purpose:\n\n```typescript\nconst insertOne = new BatchQuery();\nconst insertTwo = new BatchQuery();\n\ninsertOne.setCql(`INSERT INTO ${KEYSPACE}.test (key, value) VALUES('a', 1)`);\ninsertTwo.setCql(`INSERT INTO ${KEYSPACE}.test (key, value) VALUES('b', 2)`);\n\nconst batch = new Batch();\nbatch.setQueriesList([insertOne, insertTwo]);\n\nawait promisifiedClient.executeBatch(batch, authenticationMetadata);\n```\n\n### Processing the result set\n\nAfter executing a query a response will be returned containing rows for a SELECT statement, otherwise the returned payload will be unset. You can call `getResultSet()` on the response to grab a ResultSet that's easier to work with. Note the function can return `undefined` if no ResultSet was returned, so you'll need to check it's defined or cast it.\n\n```typescript\n// Insert a record into the table\nconst insert = new Query();\ninsert.setCql(\"INSERT INTO ks1.tbl2 (key, value) VALUES ('a', 'alpha');\");\nawait promisifiedClient.executeQuery(insert, authenticationMetadata);\n\n// Read the data back out\nconst read = new Query();\nread.setCql(\"SELECT key, value FROM ks1.tbl2\");\nconst result = await promisifiedClient.executeQuery(read, authenticationMetadata);\n\nconst resultSet = result.getResultSet();\n\nif (resultSet) {\n  const firstRow = resultSet.getRowsList()[0];\n  // We call getString() here because we know the type being returned. See below for details on working with types.\n  const key = firstRow.getValuesList()[0].getString();\n  console.log(`key: ${key}`);\n}\n```\n\n#### Reading primitive values\n\nIndividual values from queries will be returned as a `Value` object. These objects have boolean `hasX()` methods, where X is the possible type of a value.\n\nThere are corresponding `getX()` methods on the `Value` type that will return the value, if present. If the value does not represent type X, calling `getX()` will not throw an error. You'll get `undefined` or another falsy value based on the expected data type.\n\n```typescript\nconst firstValueInRow = row.getValuesList()[0]; // Assume we know this is a string\n\nconst isString = firstValueInRow.hasString(); // will resolve to true\nconst stringValue = firstValueInRow.getString(); // will resolve to the string value\n\nconst isInt = firstValueInRow.hasInt(); // false\nconst intValue = firstValueInRow.getInt(); // 0 - zero value for this data type\n```\n\n#### Reading CQL data types\n\nThe built-in `toX()` methods for `Value`s representing more complicated types like UUIDs can be hard to work with. This library exposes helper functions to translate a `Value` into a more easily used type:\n\n- `toUUIDString`\n- `toCQLTime`\n\nUnlike the built-in `toX()` methods, these helper functions _will_ throw an error if the conversion fails.\n\nHere's an example of processing a UUID:\n\n```typescript\nconst insert = new Query();\ninsert.setCql(\"INSERT INTO ks1.tbl2 (id) VALUES (f066f76d-5e96-4b52-8d8a-0f51387df76b);\");\nawait promisifiedClient.executeQuery(insert, authenticationMetadata);\n\n// Read the data back out\nconst read = new Query();\nread.setCql(\"SELECT id FROM ks1.tbl2\");\nconst result = await promisifiedClient.executeQuery(read, authenticationMetadata);\n\nconst resultSet = result.getResultSet();\n\nif (resultSet) {\n  const firstRow = resultSet.getRowsList()[0];\n  const idValue = firstRow.getValuesList()[0];\n  try {\n  const uuidAsString = toUUIDString(idValue);\n  console.log(`UUID: ${uuidAsString}`);\n  } catch (e) {\n    console.error(`Conversion of Value to UUID string failed: ${e}`);\n  }\n}\n```\n\n### Promise support\n\nThe Node gRPC implementation uses callbacks by default. If you'd prefer promises, this library provides a utility function to create a promisified version of the Stargate gRPC client. The promise will reject if an error occurs:\n\n```typescript\nimport {\n  StargateClient,\n  promisifyStargateClient,\n} from \"@stargate-oss/stargate-grpc-node-client\";\n\nconst stargateClient = new StargateClient(\n  \"localhost:8090\",\n  grpc.credentials.createInsecure()\n);\n\nconst promisifiedClient = promisifyStargateClient(stargateClient);\ntry {\n  const queryResult = await promisifiedClient.executeQuery(\n    query,\n    metadata,\n    callOptions\n  );\n  const batchResult = await promisifiedClient.executeBatch(\n    query,\n    metadata,\n    callOptions\n  );\n} catch (e) {\n  // something went wrong\n}\n```\n\nThe `metadata` and `callOptions` arguments are both optional.\n\n### Example uses\n\nSee the integration tests at `src/client/client.test.ts` for more example uses of this client. The [DEV_GUIDE.md](DEV_GUIDE.md) has instructions on how to run the integration tests locally as well.\n\n## Issue Management\n\nYou can reference the [CONTRIBUTING.md](CONTRIBUTING.md) and [DEV_GUIDE.md](DEV_GUIDE.md) for a full description of how to get involved but the short of it is below.\n\n- If you've found a bug (use the bug label) or want to request a new feature (use the enhancement label), file a GitHub issue\n- If you're not sure about it or want to chat, reach out on our [Discord](https://discord.gg/GravUqY)\n- If you want to write some user docs 🎉 head over to the [stargate/docs](https://github.com/stargate/docs) repo, Pull Requests accepted!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstargate%2Fstargate-grpc-node-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstargate%2Fstargate-grpc-node-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstargate%2Fstargate-grpc-node-client/lists"}