This repository has been archived by the owner on Jul 6, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Implement initial cache writer
- Loading branch information
0 parents
commit 18bc0c1
Showing
13 changed files
with
7,606 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
indent_size = 2 | ||
end_of_line = lf | ||
indent_style = space | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
node_modules | ||
/lib | ||
es | ||
types | ||
coverage | ||
.vscode | ||
yarn-error.log* | ||
package-lock.json | ||
package-lock.json.* | ||
bundles | ||
dist | ||
webpack-build | ||
.rts2_cache* | ||
cypress/screenshots | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/* | ||
!LICENSE | ||
!CHANGELOG.md | ||
!README.md | ||
!/dist/**/*.{d.ts,js,js.map} | ||
!/src/**/*.{d.ts,ts,tsx} | ||
__snapshots__/ | ||
test-utils/ | ||
*.test.js | ||
*.test.jsx | ||
*.test.ts | ||
*.test.d.ts | ||
*.test.tsx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
{ | ||
"name": "graphcache", | ||
"version": "0.1.0", | ||
"description": "A normalizing GraphQL cache configurable by defining exceptions to the rule", | ||
"main": "dist/graphcache.js", | ||
"module": "dist/graphcache.es.js", | ||
"types": "dist/types/index.d.ts", | ||
"source": "src/index.ts", | ||
"sideEffects": false, | ||
"scripts": { | ||
"prebuild": "rimraf dist", | ||
"build": "run-p build:types build:bundle", | ||
"build:clean": "rimraf dist", | ||
"build:types": "tsc -d --emitDeclarationOnly --outDir dist/types", | ||
"build:bundle": "microbundle --format es,cjs --no-compress", | ||
"build:prune": "rimraf dist/types/**/*.test.d.ts", | ||
"postbuild:bundle": "terser dist/graphcache.es.js -o dist/graphcache.es.min.js", | ||
"test": "jest", | ||
"bundlesize": "bundlesize", | ||
"lint": "tslint --project .", | ||
"check-formatting": "prettier --write src/**/*.{ts,tsx}", | ||
"prepublishOnly": "run-s build build:prune" | ||
}, | ||
"author": "Phil Plückthun <phil@kitten.sh>", | ||
"repository": "https://github.com/kitten/graphcache.git", | ||
"license": "MIT", | ||
"prettier": { | ||
"singleQuote": true, | ||
"trailingComma": "es5" | ||
}, | ||
"jest": { | ||
"setupFiles": [ | ||
"./scripts/setupTests.js" | ||
], | ||
"transform": { | ||
"^.+\\.tsx?$": "ts-jest" | ||
}, | ||
"testRegex": "(src/.*(\\.|/)(test|spec))\\.tsx?$", | ||
"moduleFileExtensions": [ | ||
"js", | ||
"jsx", | ||
"ts", | ||
"tsx", | ||
"json" | ||
], | ||
"collectCoverageFrom": [ | ||
"<rootDir>/src/**/*.{ts,tsx}" | ||
], | ||
"coveragePathIgnorePatterns": [ | ||
"<rootDir>/src.*/index.ts" | ||
] | ||
}, | ||
"lint-staged": { | ||
"*.{json,md}": [ | ||
"prettier --write", | ||
"git add" | ||
], | ||
"*.{ts,tsx}": [ | ||
"tslint --fix", | ||
"prettier --write", | ||
"git add" | ||
] | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged" | ||
} | ||
}, | ||
"bundlesize": [ | ||
{ | ||
"path": "./dist/*.min.js", | ||
"maxSize": "10 kB" | ||
} | ||
], | ||
"devDependencies": { | ||
"@types/graphql": "^14.0.7", | ||
"@types/jest": "^23.3.13", | ||
"bundlesize": "^0.17.0", | ||
"coveralls": "^3.0.0", | ||
"graphql": "^14.1.1", | ||
"graphql-tag": "^2.10.1", | ||
"husky": "^1.2.0", | ||
"jest": "^23.6.0", | ||
"lint-staged": "^8.1.0", | ||
"microbundle": "^0.9.0", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^1.15.2", | ||
"rimraf": "^2.6.2", | ||
"terser": "^3.16.1", | ||
"ts-jest": "^23.10.5", | ||
"tslint": "^5.11.0", | ||
"tslint-config-prettier": "^1.16.0", | ||
"tslint-react": "^3.6.0", | ||
"typescript": "^3.1.6" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0" | ||
}, | ||
"dependencies": { | ||
"graphql-anywhere": "^4.1.28" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
process.on('unhandledRejection', error => { | ||
throw error; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { Cache, Entity, Link } from './types'; | ||
|
||
export const createCache = (initial?: Cache): Cache => { | ||
const records = Object.create(null); | ||
const links = Object.create(null); | ||
if (initial !== undefined) { | ||
Object.assign(records, initial.records); | ||
Object.assign(links, initial.links); | ||
} | ||
|
||
return { records, links }; | ||
}; | ||
|
||
export const getOrCreateEntity = (cache: Cache, key: string): Entity => { | ||
const { records } = cache; | ||
let entity = records[key]; | ||
if (entity === undefined) { | ||
entity = records[key] = Object.create(null); | ||
} | ||
|
||
return entity; | ||
}; | ||
|
||
export const writeLink = (cache: Cache, linkKey: string, childKey: Link) => { | ||
const { links } = cache; | ||
links[linkKey] = childKey; | ||
}; | ||
|
||
export const deleteLink = (cache: Cache, linkKey: string) => { | ||
const { links } = cache; | ||
delete links[linkKey]; | ||
}; | ||
|
||
export const writeFieldValue = ( | ||
entity: Entity, | ||
fieldName: string, | ||
fieldValue: any | ||
) => { | ||
entity[fieldName] = fieldValue; | ||
}; | ||
|
||
export const deleteFieldValue = (entity: Entity, fieldName: string) => { | ||
delete entity[fieldName]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { Entity } from './types'; | ||
|
||
const isOperation = (typeName: string) => | ||
typeName === 'Query' || | ||
typeName === 'Mutation' || | ||
typeName === 'Subscription'; | ||
|
||
export const keyOfEntity = (entity: Entity): null | string => { | ||
const { __typename: typeName } = entity; | ||
const id = entity.id === undefined ? entity._id : entity.id; | ||
|
||
if (typeName === undefined || typeName === null) { | ||
return null; | ||
} else if (isOperation(typeName)) { | ||
return typeName; | ||
} else if (id === null || id === undefined) { | ||
return null; | ||
} | ||
|
||
return `${typeName}:${id}`; | ||
}; | ||
|
||
export const keyForLink = ( | ||
parentKey: string, | ||
fieldName: string, | ||
args: null | object | ||
) => { | ||
const key = `${parentKey}->${fieldName}`; | ||
return args ? `${key}(${JSON.stringify(args)})` : key; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import gql from 'graphql-tag'; | ||
|
||
import { createCache } from './cacheUtils'; | ||
import responseToCache from './responseToCache'; | ||
import { Cache } from './types'; | ||
|
||
let cache: Cache; | ||
|
||
beforeEach(() => { | ||
cache = createCache(); | ||
}); | ||
|
||
it('caches flat scalars', () => { | ||
const query = gql` | ||
{ | ||
__typename | ||
test | ||
} | ||
`; | ||
|
||
const response = { | ||
__typename: 'Query', | ||
test: 'value', | ||
}; | ||
|
||
responseToCache(cache, { query }, response); | ||
|
||
expect(cache).toEqual({ | ||
records: { | ||
Query: response, | ||
}, | ||
links: {}, | ||
}); | ||
}); | ||
|
||
it('caches embedded objects', () => { | ||
const query = gql` | ||
{ | ||
__typename | ||
test { | ||
__typename | ||
value | ||
} | ||
} | ||
`; | ||
|
||
const response = { | ||
__typename: 'Query', | ||
test: { __typename: null, value: '123' }, | ||
}; | ||
|
||
responseToCache(cache, { query }, response); | ||
|
||
expect(cache).toEqual({ | ||
records: { | ||
Query: response, | ||
}, | ||
links: {}, | ||
}); | ||
}); | ||
|
||
it('caches flat entities', () => { | ||
const query = gql` | ||
{ | ||
__typename | ||
test { | ||
__typename | ||
id | ||
} | ||
} | ||
`; | ||
|
||
const response = { | ||
__typename: 'Query', | ||
test: { | ||
__typename: 'Test', | ||
id: 'test', | ||
}, | ||
}; | ||
|
||
responseToCache(cache, { query }, response); | ||
|
||
expect(cache).toEqual({ | ||
records: { | ||
Query: { __typename: 'Query' }, | ||
'Test:test': response.test, | ||
}, | ||
links: { | ||
'Query->test': 'Test:test', | ||
}, | ||
}); | ||
}); | ||
|
||
it('caches entity lists', () => { | ||
const query = gql` | ||
{ | ||
__typename | ||
test { | ||
__typename | ||
id | ||
} | ||
} | ||
`; | ||
|
||
const response = { | ||
__typename: 'Query', | ||
test: [ | ||
{ | ||
__typename: 'Test', | ||
id: 'test', | ||
}, | ||
null, | ||
], | ||
}; | ||
|
||
responseToCache(cache, { query }, response); | ||
|
||
expect(cache).toEqual({ | ||
records: { | ||
Query: { __typename: 'Query' }, | ||
'Test:test': response.test[0], | ||
}, | ||
links: { | ||
'Query->test': ['Test:test', null], | ||
}, | ||
}); | ||
}); |
Oops, something went wrong.