Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

graphql-react

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-react - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

21

changelog.md
# graphql-react changelog
## 3.0.0
### Major
- The `Query` (and the internal `GraphQLQuery`) component take an `operation` prop instead of separate `variables` and `query` props. This makes the implementation a little more elegant, is more consistent with the `GraphQL.query` API and allows sending custom GraphQL operation fields.
- New internal event system, fixing [#10](https://github.com/jaydenseric/graphql-react/issues/10). Now the `loading` parameter of `Query` component render functions change when identical requests are loaded elsewhere in the app.
### Minor
- Improved `Provider` and `Consumer` component display names in React dev tools:
- `Context.Provider` → `GraphQLContext.Provider`
- `Context.Consumer` → `GraphQLContext.Consumer`
### Patch
- Updated dependencies.
- Updated package scripts and config for the new [`husky`](https://npm.im/husky) version.
- Removed the package `module` field. Webpack by default resolves extensionless paths the same way Node.js in `--experimental-modules` mode does; `.mjs` files are preferred. Tools misconfigured or unable to resolve `.mjs` can get confused when `module` points to an `.mjs` ESM file and they attempt to resolve named imports from `.js` CJS files.
- Renamed the `Operation` type `GraphQLOperation`.
- Use [jsDelivr](https://jsdelivr.com) for the readme logo instead of [RawGit](https://rawgit.com) as they are shutting down.
## 2.0.1

@@ -4,0 +25,0 @@

102

lib/components.js

@@ -18,4 +18,6 @@ 'use strict'

const { Provider, Consumer } = _react.default.createContext()
const GraphQLContext = _react.default.createContext()
GraphQLContext.displayName = 'GraphQLContext'
const { Provider, Consumer } = GraphQLContext
exports.Consumer = Consumer

@@ -28,45 +30,37 @@ exports.Provider = Provider

this.handleCacheUpdate = requestCache => {
if (!requestCache && this.props.loadOnReset) this.load()
else
this.onFetch = ({ fetchOptionsHash }) => {
if (fetchOptionsHash === this.state.fetchOptionsHash)
this.setState({
requestCache
loading: true
})
}
this.operation = () => ({
variables: this.props.variables,
query: this.props.query
})
this.onCache = ({ fetchOptionsHash }) => {
if (fetchOptionsHash === this.state.fetchOptionsHash)
this.setState({
loading: false,
requestCache: this.props.graphql.cache[fetchOptionsHash]
})
}
this.onReset = ({ exceptFetchOptionsHash }) => {
if (exceptFetchOptionsHash !== this.state.fetchOptionsHash)
if (this.props.loadOnReset) this.load()
else
this.setState({
requestCache: null
})
}
this.load = () => {
const stateUpdate = {
loading: true
}
const { fetchOptionsHash, cache, request } = this.props.graphql.query({
operation: this.operation(),
operation: this.props.operation,
fetchOptionsOverride: this.props.fetchOptionsOverride,
resetOnLoad: this.props.resetOnLoad
})
if (fetchOptionsHash !== this.state.fetchOptionsHash) {
stateUpdate.fetchOptionsHash = fetchOptionsHash
this.props.graphql.offCacheUpdate(
this.state.fetchOptionsHash,
this.handleCacheUpdate
)
this.props.graphql.onCacheUpdate(
fetchOptionsHash,
this.handleCacheUpdate
)
}
if (cache) stateUpdate.requestCache = cache
this.setState(stateUpdate, () =>
request.then(() =>
this.setState({
loading: false
})
)
)
this.setState({
loading: true,
fetchOptionsHash,
cache
})
return request

@@ -81,3 +75,3 @@ }

const fetchOptions = props.graphql.constructor.fetchOptions(
this.operation()
props.operation
)

@@ -89,7 +83,7 @@ if (props.fetchOptionsOverride) props.fetchOptionsOverride(fetchOptions)

this.state.requestCache = props.graphql.cache[this.state.fetchOptionsHash]
this.props.graphql.onCacheUpdate(
this.state.fetchOptionsHash,
this.handleCacheUpdate
)
}
this.props.graphql.on('fetch', this.onFetch)
this.props.graphql.on('cache', this.onCache)
this.props.graphql.on('reset', this.onReset)
}

@@ -101,18 +95,16 @@

componentDidUpdate({ query, variables }) {
if (
this.props.loadOnReset &&
this.state.fetchOptionsHash &&
(query !== this.props.query ||
!(0, _fastDeepEqual.default)(variables, this.props.variables))
)
this.load()
componentDidUpdate({ operation }) {
if (!(0, _fastDeepEqual.default)(operation, this.props.operation))
if (this.props.loadOnMount) this.load()
else
this.setState({
fetchOptionsHash: null,
requestCache: null
})
}
componentWillUnmount() {
if (this.state.fetchOptionsHash)
this.props.graphql.offCacheUpdate(
this.state.fetchOptionsHash,
this.handleCacheUpdate
)
this.props.graphql.off('fetch', this.onFetch)
this.props.graphql.off('cache', this.onCache)
this.props.graphql.off('reset', this.onReset)
}

@@ -136,4 +128,3 @@

fetchOptionsOverride: _propTypes.default.func,
variables: _propTypes.default.object,
query: _propTypes.default.string.isRequired,
operation: _propTypes.default.object.isRequired,
loadOnMount: _propTypes.default.bool,

@@ -161,4 +152,3 @@ loadOnReset: _propTypes.default.bool,

fetchOptionsOverride: _propTypes.default.func,
variables: _propTypes.default.object,
query: _propTypes.default.string.isRequired,
operation: _propTypes.default.object.isRequired,
loadOnMount: _propTypes.default.bool,

@@ -165,0 +155,0 @@ loadOnReset: _propTypes.default.bool,

@@ -12,34 +12,44 @@ 'use strict'

var _extractFiles = require('extract-files')
var _fnv1a = _interopRequireDefault(require('fnv1a'))
var _extractFiles = require('extract-files')
var _mitt = _interopRequireDefault(require('mitt'))
class GraphQL {
constructor({ cache = {} } = {}) {
this.requests = {}
this.listeners = {}
static requestBody(operation) {
const files = (0, _extractFiles.extractFiles)(operation)
this.onCacheUpdate = (fetchOptionsHash, callback) => {
if (!this.listeners[fetchOptionsHash])
this.listeners[fetchOptionsHash] = []
this.listeners[fetchOptionsHash].push(callback)
}
if (files.length) {
const form = new FormData()
form.append('operations', JSON.stringify(operation))
form.append(
'map',
JSON.stringify(
files.reduce((map, { path }, index) => {
map[`${index}`] = [path]
return map
}, {})
)
)
files.forEach(({ file }, index) => form.append(index, file, file.name))
return form
} else return JSON.stringify(operation)
}
this.offCacheUpdate = (fetchOptionsHash, callback) => {
if (this.listeners[fetchOptionsHash]) {
this.listeners[fetchOptionsHash] = this.listeners[
fetchOptionsHash
].filter(listenerCallback => listenerCallback !== callback)
if (!this.listeners[fetchOptionsHash].length)
delete this.listeners[fetchOptionsHash]
static fetchOptions(operation) {
const fetchOptions = {
url: '/graphql',
method: 'POST',
headers: {
Accept: 'application/json'
}
}
fetchOptions.body = this.requestBody(operation)
if (typeof fetchOptions.body === 'string')
fetchOptions.headers['Content-Type'] = 'application/json'
return fetchOptions
}
this.emitCacheUpdate = (fetchOptionsHash, requestCache) => {
if (this.listeners[fetchOptionsHash])
this.listeners[fetchOptionsHash].forEach(callback =>
callback(requestCache)
)
}
constructor({ cache = {} } = {}) {
this.reset = exceptFetchOptionsHash => {

@@ -54,5 +64,5 @@ let fetchOptionsHashes = Object.keys(this.cache)

)
fetchOptionsHashes.forEach(fetchOptionsHash =>
this.emitCacheUpdate(fetchOptionsHash)
)
this.emit('reset', {
exceptFetchOptionsHash
})
}

@@ -71,2 +81,5 @@

)
this.emit('fetch', {
fetchOptionsHash
})
return (this.requests[fetchOptionsHash] = fetcher(url, options))

@@ -98,4 +111,6 @@ .then(

this.cache[fetchOptionsHash] = requestCache
this.emitCacheUpdate(fetchOptionsHash, requestCache)
delete this.requests[fetchOptionsHash]
this.emit('cache', {
fetchOptionsHash
})
return requestCache

@@ -121,37 +136,8 @@ })

this.cache = cache
this.requests = {}
const { on, off, emit } = (0, _mitt.default)()
this.on = on
this.off = off
this.emit = emit
}
static requestBody(operation) {
const files = (0, _extractFiles.extractFiles)(operation)
if (files.length) {
const form = new FormData()
form.append('operations', JSON.stringify(operation))
form.append(
'map',
JSON.stringify(
files.reduce((map, { path }, index) => {
map[`${index}`] = [path]
return map
}, {})
)
)
files.forEach(({ file }, index) => form.append(index, file, file.name))
return form
} else return JSON.stringify(operation)
}
static fetchOptions(operation) {
const fetchOptions = {
url: '/graphql',
method: 'POST',
headers: {
Accept: 'application/json'
}
}
fetchOptions.body = this.requestBody(operation)
if (typeof fetchOptions.body === 'string')
fetchOptions.headers['Content-Type'] = 'application/json'
return fetchOptions
}
}

@@ -158,0 +144,0 @@

{
"name": "graphql-react",
"version": "2.0.1",
"version": "3.0.0",
"description": "A lightweight GraphQL client for React.",

@@ -31,3 +31,2 @@ "license": "MIT",

"main": "lib",
"module": "lib/index.mjs",
"sideEffects": false,

@@ -42,6 +41,7 @@ "engines": {

"dependencies": {
"@babel/runtime": "^7.0.0",
"@babel/runtime": "^7.1.2",
"extract-files": "^4.0.0",
"fast-deep-equal": "^2.0.1",
"fnv1a": "^1.0.1",
"mitt": "^1.1.3",
"object-assign": "^4.1.1",

@@ -51,4 +51,4 @@ "prop-types": "^15.6.1"

"devDependencies": {
"@babel/cli": "^7.1.0",
"@babel/core": "^7.1.0",
"@babel/cli": "^7.1.2",
"@babel/core": "^7.1.2",
"@babel/plugin-proposal-class-properties": "^7.1.0",

@@ -59,6 +59,6 @@ "@babel/plugin-proposal-object-rest-spread": "^7.0.0",

"@babel/preset-react": "^7.0.0",
"babel-eslint": "^10.0.0",
"babel-eslint": "^10.0.1",
"babel-plugin-transform-replace-object-assign": "^2.0.0",
"cross-fetch": "^2.2.2",
"eslint": "^5.6.0",
"eslint": "^5.7.0",
"eslint-config-env": "^1.1.0",

@@ -68,7 +68,7 @@ "eslint-config-prettier": "^3.1.0",

"eslint-plugin-node": "^7.0.1",
"eslint-plugin-prettier": "^2.6.2",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-react": "^7.11.1",
"graphql": "^14.0.2",
"graphql-api-koa": "^1.1.0",
"husky": "^1.0.0",
"graphql-api-koa": "^2.0.0",
"husky": "^1.1.2",
"jsdoc-md": "^1.6.0",

@@ -81,3 +81,3 @@ "koa": "^2.5.3",

"react-dom": "^16.5.2",
"size-limit": "^0.20.0",
"size-limit": "^0.20.1",
"tap": "^12.0.1",

@@ -100,5 +100,9 @@ "watch": "^1.0.2"

"prepublishOnly": "npm run prepare && npm test",
"watch": "watch 'npm run prepublishOnly --silent' src --interval 1",
"precommit": "lint-staged"
"watch": "watch 'npm run prepublishOnly --silent' src --interval 1"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {

@@ -105,0 +109,0 @@ "*.{mjs,js}": "eslint",

@@ -1,2 +0,2 @@

![graphql-react logo](https://cdn.rawgit.com/jaydenseric/graphql-react/b2e60e80/graphql-react-logo.svg)
![graphql-react logo](https://cdn.jsdelivr.net/gh/jaydenseric/graphql-react@0.1.0/graphql-react-logo.svg)

@@ -72,5 +72,5 @@ # graphql-react

}}
variables={{ name }}
query={
/* GraphQL */ `
operation={{
variables: { name },
query: /* GraphQL */ `
query pokemon($name: String!) {

@@ -83,3 +83,3 @@ pokemon(name: $name) {

`
}
}}
>

@@ -145,4 +145,4 @@ {({ loading, data }) =>

- [Examples](#examples-8)
- [type GraphQLOperation](#type-graphqloperation)
- [type HttpError](#type-httperror)
- [type Operation](#type-operation)
- [type QueryRender](#type-queryrender)

@@ -178,3 +178,3 @@ - [Examples](#examples-9)

| `options` | [Object](https://mdn.io/object) | Options. |
| `options.operation` | [Operation](#type-operation) | GraphQL operation object. |
| `options.operation` | [GraphQLOperation](#type-graphqloperation) | GraphQL operation. |
| `options.fetchOptionsOverride` | [FetchOptionsOverride](#type-fetchoptionsoverride)? | Overrides default GraphQL request [fetch options](#type-fetchoptions). |

@@ -189,5 +189,5 @@ | `options.resetOnLoad` | [boolean](https://mdn.io/boolean)? = `false` | Should the [GraphQL cache](#graphql-instance-property-cache) reset when the query loads. |

| Parameter | Type | Description |
| :----------------------- | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `exceptFetchOptionsHash` | [string](https://mdn.io/string)? | A [fetch options](#type-fetchoptions) hash to exempt a request from cache deletion. Useful for resetting cache after a mutation, preserving the mutation cache. |
| Parameter | Type | Description |
| :----------------------- | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `exceptFetchOptionsHash` | [string](https://mdn.io/string)? | A [fetch options](#type-fetchoptions) hash for cache to exempt from deletion. Useful for resetting cache after a mutation, preserving the mutation cache. |

@@ -305,4 +305,3 @@ ##### Examples

| `props` | [Object](https://mdn.io/object) | Component props. |
| `props.variables` | [Object](https://mdn.io/object)? | GraphQL query variables. |
| `props.query` | [string](https://mdn.io/string) | GraphQL query. |
| `props.operation` | [GraphQLOperation](#type-graphqloperation) | GraphQL operation. |
| `props.fetchOptionsOverride` | [FetchOptionsOverride](#type-fetchoptionsoverride)? | Overrides default GraphQL request [fetch options](#type-fetchoptions). |

@@ -328,12 +327,14 @@ | `props.loadOnMount` | [boolean](https://mdn.io/boolean)? = `false` | Should the query load when the component mounts. |

> fetchOptionsOverride={options => {
> options.url = 'https://api.example.com/graphql'
> options.url = 'https://api.example.com/graphql'
> }}
> variables={{ userId }}
> query={`
> query user($userId: ID!) {
> user(userId: $userId) {
> name
> operation={
> variables: { userId },
> query: `
> query user($userId: ID!) {
> user(userId: $userId) {
> name
> }
> }
> }
> `}
> `
> }
> >

@@ -373,10 +374,12 @@ > {({

> }}
> variables={{ articleId }}
> query={`
> mutation clapArticle($articleId: ID!) {
> clapArticle(articleId: $articleId) {
> clapCount
> operation={
> variables: { articleId },
> query: `
> mutation clapArticle($articleId: ID!) {
> clapArticle(articleId: $articleId) {
> clapCount
> }
> }
> }
> `}
> `
> }
> >

@@ -457,6 +460,6 @@ > {({

| Parameter | Type | Description |
| :------------- | :--------------------------------- | :------------------------------------- |
| `fetchOptions` | [FetchOptions](#type-fetchoptions) | Default GraphQL request fetch options. |
| `operation` | [Operation](#type-operation)? | A GraphQL operation object. |
| Parameter | Type | Description |
| :------------- | :------------------------------------------ | :------------------------------------- |
| `fetchOptions` | [FetchOptions](#type-fetchoptions) | Default GraphQL request fetch options. |
| `operation` | [GraphQLOperation](#type-graphqloperation)? | GraphQL operation. |

@@ -474,2 +477,13 @@ #### Examples

### type GraphQLOperation
A GraphQL operation. Additional properties may be used; all are sent to the GraphQL server.
**Type:** [Object](https://mdn.io/object)
| Property | Type | Description |
| :---------- | :------------------------------ | :---------------------------- |
| `query` | [string](https://mdn.io/string) | GraphQL queries or mutations. |
| `variables` | [Object](https://mdn.io/object) | Variables used by the query. |
### type HttpError

@@ -486,13 +500,2 @@

### type Operation
A GraphQL operation object. Additional properties may be used; all are sent to the GraphQL server.
**Type:** [Object](https://mdn.io/object)
| Property | Type | Description |
| :---------- | :------------------------------ | :---------------------------- |
| `query` | [string](https://mdn.io/string) | GraphQL queries or mutations. |
| `variables` | [Object](https://mdn.io/object) | Variables used by the query. |
### type QueryRender

@@ -499,0 +502,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc