在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):monojack/graphql-normalizr开源软件地址(OpenSource Url):https://github.com/monojack/graphql-normalizr开源编程语言(OpenSource Language):JavaScript 100.0%开源软件介绍(OpenSource Introduction):graphql-normalizrNormalize GraphQL responses for persisting in the client cache/state.
TL;DR: Transforms: {
"data": {
"findUser": [
{
"__typename": "User",
"id": "5a6efb94b0e8c36f99fba013",
"email": "[email protected]",
"posts": [
{
"__typename": "BlogPost",
"id": "5a6efb94b0e8c36f99fba016",
"title": "Dolorem voluptatem molestiae",
"comments": [
{
"__typename": "Comment",
"id": "5a6efb94b0e8c36f99fba019",
"message": "Alias quod est voluptatibus aut quis sunt aut numquam."
},
{
"__typename": "Comment",
"id": "5a6efb94b0e8c36f99fba01b",
"message": "Harum quia asperiores nemo."
},
{
"__typename": "Comment",
"id": "5a6efb94b0e8c36f99fba01c",
"message": "Vel veniam consectetur laborum."
},
{
"__typename": "Comment",
"id": "5a6efb94b0e8c36f99fba01e",
"message": "Possimus beatae vero recusandae beatae quas ut commodi laboriosam."
}
]
}
]
}
]
}
} into: {
"comments": {
"5a6efb94b0e8c36f99fba019": {
"id": "5a6efb94b0e8c36f99fba019",
"message": "Alias quod est voluptatibus aut quis sunt aut numquam."
},
"5a6efb94b0e8c36f99fba01b": {
"id": "5a6efb94b0e8c36f99fba01b",
"message": "Harum quia asperiores nemo."
},
"5a6efb94b0e8c36f99fba01c": {
"id": "5a6efb94b0e8c36f99fba01c",
"message": "Vel veniam consectetur laborum."
},
"5a6efb94b0e8c36f99fba01e": {
"id": "5a6efb94b0e8c36f99fba01e",
"message": "Possimus beatae vero recusandae beatae quas ut commodi laboriosam."
}
},
"blogPosts": {
"5a6efb94b0e8c36f99fba016": {
"id": "5a6efb94b0e8c36f99fba016",
"title": "Dolorem voluptatem molestiae",
"comments": [
"5a6efb94b0e8c36f99fba019",
"5a6efb94b0e8c36f99fba01b",
"5a6efb94b0e8c36f99fba01c",
"5a6efb94b0e8c36f99fba01e"
]
}
},
"users": {
"5a6efb94b0e8c36f99fba013": {
"id": "5a6efb94b0e8c36f99fba013",
"email": "[email protected]",
"posts": ["5a6efb94b0e8c36f99fba016"]
}
}
} MotivationWe all love GraphQL and we want to use it. There are tons of libraries and clients out there that help us do that with ease, but there is still one problem... How do you persist that data? Yes, everything is all great when the response mirrors the exact structure we asked for, but we don't want to cache it that way, do we? We probably want a normalized version of that data which we can persist to our store and read/modify it efficiently. Flux or Redux stores work best with normalized data and there are also GraphQL clients you can use to execute queries on the local cache/state (blips or apollo-link-state), in which case, we definitely need to persist normalized data. GraphQLNormalizr is simple, fast, light-weight and it provides all the tools needed to do just that, the only requirement is that you include the Table of contentsInstallationnpm install graphql-normalizr API by exampleThe GraphQLNormalizr constructor function returns an object containing 3 methods: Depending on how you write your queries, you may or may not use If your queries already ask for GraphQLNormalizrimport { GraphQLNormalizr } from 'graphql-normalizr'
// const config = ...
const normalizer = new GraphQLNormalizr(config) config: optional - the configuration object containing information for instantiating the client. it takes the following props: idKey
Default is "id". Configures a custom Consider the following GraphQL response: const response = {
data: {
findUser: {
__typename: 'User',
uid: '5a6efb94b0e8c36f99fba013',
email: '[email protected]',
},
},
} Normalize the data with our custom // using destructuring to get the `normalize` method of the client
const { normalize } = new GraphQLNormalizr({ idKey: 'uid' })
normalize(response)
// =>
// {
// users: {
// '5a6efb94b0e8c36f99fba013' : {
// uid: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]'
// }
// }
// } useConnections
Default is NOTE: The connections implementation needs to be according to the specification const response = {
data: {
findUser: {
__typename: 'User',
id: '5a6efb94b0e8c36f99fba013',
email: '[email protected]',
friends: {
__typename: 'FriendsConnection',
totalCount: 3,
edges: [
{
node: {
__typename: 'User',
id: '5a6cf127c2b20834f6551481',
email: '[email protected]',
},
cursor: 'Y3Vyc29yMg==',
},
{
node: {
__typename: 'User',
id: '5a6cf127c2b20834f6551482',
email: '[email protected]',
},
cursor: 'Y3Vyc29yMw==',
},
],
pageInfo: {
endCursor: 'Y3Vyc29yMw==',
hasNextPage: false,
},
},
},
},
}
const { normalize } = new GraphQLNormalizr({
useConnections: true,
})
normalize(response)
// =>
// {
// users: {
// '5a6efb94b0e8c36f99fba013': {
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]',
// friends: ['5a6cf127c2b20834f6551481', '5a6cf127c2b20834f6551482'],
// },
// '5a6cf127c2b20834f6551481': {
// id: '5a6cf127c2b20834f6551481',
// email: '[email protected]',
// },
// '5a6cf127c2b20834f6551482': {
// id: '5a6cf127c2b20834f6551482',
// email: '[email protected]',
// },
// },
// } typeMap
By default the entity name will be the plural form of the type name, converted to camel case, ( const response = {
data: {
findUser: {
__typename: 'User',
id: '5a6efb94b0e8c36f99fba013',
email: '[email protected]',
},
},
}
const { normalize } = new GraphQLNormalizr({
typeMap: { User: 'accounts' },
})
normalize(response)
// =>
// {
// accounts: {
// '5a6efb94b0e8c36f99fba013' : {
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]'
// }
// }
// } exclude
Prevent normalization of specified fields const response = {
data: {
allUsers: [
{
__typename: 'User',
id: '5a6efb94b0e8c36f99fba013',
email: '[email protected]',
preferences: null
posts: [
{
__typename: 'BlogPost',
id: '5a6cf127c2b20834f6551484',
likes: 10,
title: 'Sunt ut aut',
tags: {},
}
]
},
{
__typename: 'User',
id: '5a6efb94b0e8c36f99fba013',
email: '[email protected]',
preferences: { foo: 'apple', bar: 1, baz: { a: 'b' }, quux: null, }
posts: [
{
__typename: 'BlogPost',
id: '5a6cf127c2b20834f6551485',
likes: 23,
title: 'Nesciunt esse',
tags: [],
}
]
},
],
},
} Normalize the data excluding the // using destructuring to get the `normalize` method of the client
const { normalize } = new GraphQLNormalizr({ exclude: { users: [ 'preferences' ], blogPosts: [ 'tags' ] } })
normalize(response)
// =>
// {
// users: {
// '5a6efb94b0e8c36f99fba013': {,
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]',
// preferences: null
// },
// '5a6efb94b0e8c36f99fba013': {
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]',
// preferences: { foo: 'apple', bar: 1, baz: { a: 'b' }, quux: null, }
// },
// },
// blogPosts: {
// '5a6cf127c2b20834f6551484': {
// id: '5a6cf127c2b20834f6551484',
// likes: 10,
// title: 'Sunt ut aut',
// tags: {},
// },
// '5a6cf127c2b20834f6551485': {
// id: '5a6cf127c2b20834f6551485',
// likes: 23,
// title: 'Nesciunt esse',
// tags: [],
// },
// }
// } plural
Default is const { normalize } = new GraphQLNormalizr({
plural: false,
})
normalize(response)
// =>
// {
// user: {
// '5a6efb94b0e8c36f99fba013' : {
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]'
// }
// }
// } casing
You can also specify the preferred casing for entity names. Again, consider the above response example. // casing: 'lower'
// User => user
// casing: 'upper'
// User => USER
// casing: 'camel'
// PrimaryAddress => primaryAddress
// casing: 'pascal'
// PrimaryAddress => PrimaryAddress
// casing: 'snake'
// PrimaryAddress => primary_address
// casing: 'kebab'
// PrimaryAddress => primary-address Combine lists
Default is For the same response object in our previous example: const { normalize } = new GraphQLNormalizr({
lists: true,
})
normalize(response)
// =>
// {
// users: [
// {
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]'
// }
// ]
// } typenames
Default is const { normalize } = new GraphQLNormalizr({
typenames: true,
})
normalize(response)
// =>
// {
// users: {
// '5a6efb94b0e8c36f99fba013' : {
// __typename: 'User',
// id: '5a6efb94b0e8c36f99fba013',
// email: '[email protected]'
// }
// }
// } typePointers
Default is const { normalize } = new GraphQLNormalizr({
typePointers: true,
})
// ['5a6cf127c2b20834f655148a', '5a6cf127c2b20834f655148b', '5a6cf127c2b20834f655148c']
users: [
{
_id: '5a6cf127c2b20834f655148a', // '_id' or the specified key
collection: 'members', // type Member
},
{
_id: '5a6cf127c2b20834f655148b', // '_id' or the specified key
collection: 'authors', // type Author
},
{
_id: '5a6cf127c2b20834f655148c', // '_id' or the specified key
collection: 'members', // type Member
},
], caching
Default is const { normalize } = new GraphQLNormalizr({
caching: true,
})
const normalized = normalize(response)
const cached = normalize(response)
cached === normalized // => true
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论