https://github.com/someimportantcompany/graphql-keyvalue
Standalone GraphQL Scalar type for Key-Value hashes.
https://github.com/someimportantcompany/graphql-keyvalue
graphql keyvalue nodejs
Last synced: about 1 year ago
JSON representation
Standalone GraphQL Scalar type for Key-Value hashes.
- Host: GitHub
- URL: https://github.com/someimportantcompany/graphql-keyvalue
- Owner: someimportantcompany
- License: mit
- Created: 2021-04-08T19:59:16.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-07T06:34:49.000Z (over 3 years ago)
- Last Synced: 2025-01-31T23:44:36.210Z (about 1 year ago)
- Topics: graphql, keyvalue, nodejs
- Language: JavaScript
- Homepage:
- Size: 651 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# graphql-keyvalue
[](https://npm.im/graphql-keyvalue)
[](https://github.com/someimportantcompany/graphql-keyvalue/actions/workflows/ci.yml)
[](https://coveralls.io/github/someimportantcompany/graphql-keyvalue)
Standalone GraphQL Scalar type for Key-Value hashes in JavaScript.
```graphql
type User {
id: ID!
name: String!
state: KeyValue!
}
extend type Query {
user: User!
}
extend type Mutation {
updateUserState(id: ID!, state: KeyValue!) KeyValue!
}
```
## Install
```
$ npm install --save graphql graphql-keyvalue
```
From your codebase, you can either use predefined items (type definition & resolver) directly in your project or define the scalar yourself & include the scalar instance in your resolvers.
The following example uses [`graphql-tools`](https://npm.im/graphql-tools) & the predefined items:
```javascript
const assert = require('assert');
const { typeDefs: keyValueTypeDefs, resolvers: keyValueResolvers } = require('graphql-keyvalue');
const typeDefs = /* GraphQL */`
type User {
id: ID!
name: String!
email: String!
state: KeyValue!
}
type Query {
user(id: ID!): User!
}
type Mutation {
updateUserState(id: ID!, state: KeyValue!) KeyValue!
}
`;
const resolvers = {
Query: {
async user(_, { id }) {
const user = await getUser(id);
return user && user.id ? user : null;
},
},
Mutation: {
async updateUserState(_, { id, state }) {
const user = await getUser(id);
assert(user && user.id, 'User not found');
// Merge in the user state
user.state = { ...user.state, ...state };
await setUser(id, user);
return user.state;
},
},
};
const schema = makeExecutableSchema({
typeDefs: [ typeDefs, keyValueTypeDefs ],
resolvers: [ resolvers, keyValueResolvers ],
});
```
Whereas this example uses [`apollo-server`](https://npm.im/apollo-server) & includes the scalar instance `KeyValue` in its resolvers:
```javascript
const { ApolloServer, gql } = require('apollo-server');
const { KeyValue } = require('graphql-keyvalue');
const typeDefs = gql`
type User {
id: ID!
name: String!
email: String!
state: KeyValue!
}
type Query {
user(id: ID!): User!
}
type Mutation {
updateUserState(id: ID!, state: KeyValue!) KeyValue!
}
# @NOTE You must define the scalar yourself
scalar KeyValue
`;
const resolvers = {
Query: {
async user(_, { id }) {
const user = await getUser(id);
return user && user.id ? user : null;
},
},
Mutation: {
async updateUserState(_, { id, state }) {
const user = await getUser(id);
assert(user && user.id, 'User not found');
// Merge in the user state
user.state = { ...user.state, ...state };
await setUser(id, user);
return user.state;
},
},
KeyValue,
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
```
## Usage
Once the type definition & resolver is configured, you can send & receive simple key-value objects in GraphQL in both queries & mutations.
### Query
```graphql
query GetUser {
user(id: "1") {
id
name
state
}
}
```
```json
{
"data": {
"user": {
"id": "1",
"name": "jdrydn",
"state": {
"signedInWith": "APPLE",
"finishedOnboarding": true
}
}
}
}
```
### Mutation
```graphql
mutation UpdateUser {
updateUserState(id: "1", state: { "finishedOnboarding": true })
}
```
```json
{
"data": {
"updateUserState": {
"signedInWith": "APPLE",
"finishedOnboarding": true
}
}
}
```
## Notes
- The scalar will pass an object for input values & expects an object to be passed for output values.
- Trying to send/receive a JSON object/array will throw an error.
- **Why only one-level deep?** One of the benefits of GraphQL is the strictly typed schema that is produced. This isn't trying to defy the GraphQL schema, merely extend it to cover more use-cases.
- After more than one level? Check out [graphql-type-json](https://npmjs.im/graphql-type-json).
- Any questions or suggestions please [open an issue](https://github.com/someimportantcompany/graphql-keyvalue/issues).