├── .babelrc
├── .gitignore
├── .npmignore
├── README.md
├── lerna.json
├── package.json
├── packages
├── apollo-fragment-react-codegen
│ ├── .npmignore
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── config.ts
│ │ ├── index.ts
│ │ └── visitor.ts
│ ├── tsconfig.json
│ └── tslint.json
├── apollo-fragment-react
│ ├── .npmignore
│ ├── example
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── public
│ │ │ ├── favicon.ico
│ │ │ └── index.html
│ │ └── src
│ │ │ ├── App.js
│ │ │ ├── graphql
│ │ │ ├── link.js
│ │ │ └── schema.js
│ │ │ ├── index.css
│ │ │ └── index.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── index.tsx
│ │ └── mocks
│ │ │ ├── enzymeAdapter.ts
│ │ │ ├── mockLink.ts
│ │ │ └── mockSchema.ts
│ ├── tsconfig.json
│ └── tslint.json
├── apollo-fragment-utils
│ ├── .npmignore
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── __tests__
│ │ │ └── index.test.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ └── tslint.json
├── apollo-fragment-vue
│ ├── .npmignore
│ ├── example
│ │ ├── .gitignore
│ │ ├── babel.config.js
│ │ ├── package.json
│ │ ├── public
│ │ │ ├── favicon.ico
│ │ │ └── index.html
│ │ ├── src
│ │ │ ├── App.vue
│ │ │ ├── assets
│ │ │ │ └── logo.png
│ │ │ ├── components
│ │ │ │ └── HelloWorld.vue
│ │ │ ├── graphql
│ │ │ │ ├── link.js
│ │ │ │ ├── personFragment.js
│ │ │ │ └── schema.js
│ │ │ └── main.js
│ │ └── vue.config.js
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ │ ├── ApolloFragment.js
│ │ └── index.ts
│ ├── tsconfig.json
│ └── tslint.json
└── apollo-link-state-fragment
│ ├── .npmignore
│ ├── package.json
│ ├── rollup.config.js
│ ├── src
│ ├── __tests__
│ │ └── index.ts
│ ├── index.ts
│ └── mocks
│ │ ├── mockLink.ts
│ │ └── mockSchema.ts
│ ├── tsconfig.json
│ └── tslint.json
└── tsconfig.json
/.babelrc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abhiaiyer91/apollo-fragment/17e2f414fdcbc4d452538fd00f92c5957e3b9765/.babelrc
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 | *.pid.lock
11 |
12 | # Directory for instrumented libs generated by jscoverage/JSCover
13 | lib-cov
14 |
15 | # Coverage directory used by tools like istanbul
16 | coverage
17 |
18 | # nyc test coverage
19 | .nyc_output
20 |
21 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
22 | .grunt
23 |
24 | # node-waf configuration
25 | .lock-wscript
26 |
27 | # Compiled binary addons (http://nodejs.org/api/addons.html)
28 | build/Release
29 |
30 | # Dependency directories
31 | node_modules/
32 | jspm_packages
33 |
34 | # Optional npm cache directory
35 | .npm
36 |
37 | # Optional eslint cache
38 | .eslintcache
39 |
40 | # Optional REPL history
41 | .node_repl_history
42 |
43 | # Output of 'npm pack'
44 | *.tgz
45 |
46 | # Yarn Integrity file
47 | .yarn-integrity
48 |
49 | # lock files
50 | yarn.lock
51 | package-lock.json
52 |
53 | # Compiled
54 | dist
55 | lib
56 |
57 | .idea
58 | .DS_Store
59 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | dist/tests/
2 | src/
3 | tests/
4 | .travis.yml
5 | tsconfig.json
6 | tslint.json
7 | typings.d.ts
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apollo Fragment
2 |
3 | Apollo Fragment holds libraries aimed at connecting UI components to GraphQL
4 | fragments in the Apollo Cache.
5 |
6 | `apollo-link-state-fragment` exposes a `cacheRedirect` and `withClientState`
7 | configuration for querying fragments from the cache.
8 |
9 | `apollo-fragment-react` exposes an `ApolloFragment` query component that will
10 | connect your component to a fragment in cache and automatically watch all
11 | changes to it.
12 |
13 | `apollo-fragment-vue` exposes an `ApolloFragment` Vue component that will
14 | connect your component to a fragment in cache and automatically watch all
15 | changes to it.
16 |
17 | ## Background
18 |
19 | Read about this library here: https://medium.com/open-graphql/fragment-driven-uis-with-apollo-17d933fa1cbe
20 |
21 | ## React
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ## Vue
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | ## Link State
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | ## Installation
46 |
47 | It is simple to add to your current apollo client setup:
48 |
49 | ```bash
50 | # installing cache addons and react package
51 | yarn add apollo-link-state-fragment apollo-fragment-react -S
52 | ```
53 |
54 | or
55 |
56 | ```bash
57 | # installing cache addons and react package
58 | yarn add apollo-link-state-fragment apollo-fragment-vue -S
59 | ```
60 |
61 | ## Usage
62 |
63 | To get started you will want to add the `fragmentCacheRedirect` to your
64 | `InMemoryCache` cacheRedirect map.
65 |
66 | ```js
67 | import { InMemoryCache } from "apollo-cache-inmemory";
68 | import { fragmentCacheRedirect } from "apollo-link-state-fragment";
69 |
70 | const cache = new InMemoryCache({
71 | cacheRedirects: {
72 | Query: {
73 | ...fragmentCacheRedirect(),
74 | },
75 | },
76 | });
77 | ```
78 |
79 | Next, import the `fragmentLinkState` and pass in the cache.
80 |
81 | ```js
82 | import { ApolloClient } from "apollo-client";
83 | import { ApolloLink } from "apollo-link";
84 | import { InMemoryCache } from "apollo-cache-inmemory";
85 | import {
86 | fragmentCacheRedirect,
87 | fragmentLinkState,
88 | } from "apollo-link-state-fragment";
89 |
90 | const cache = new InMemoryCache({
91 | cacheRedirects: {
92 | Query: {
93 | ...fragmentCacheRedirect(),
94 | },
95 | },
96 | });
97 |
98 | const client = new ApolloClient({
99 | link: ApolloLink.from([fragmentLinkState(cache), new HttpLink()]),
100 | cache: new InMemoryCache(),
101 | });
102 | ```
103 |
104 | Once you have your client setup to make these kind of queries against the cache,
105 | we can now use the View layer integrations: All we have to do is pass the id of
106 | the fragment you're looking for, and the selection set in a named fragment.
107 |
108 | ## React
109 |
110 | ```jsx
111 | import { useApolloFragment } from "apollo-fragment-react";
112 |
113 | const fragment = `
114 | fragment fragmentFields on Person {
115 | idea
116 | name
117 | __typename
118 | }
119 | `;
120 |
121 | function App() {
122 | const { data } = useApolloFragment(fragment, "1");
123 |
124 | return (
125 |
126 |
127 | This component is "watching" a fragment in the cache, it will render the
128 | persons name once the data enters
129 |
130 | {data && `Person Name: ${data.name || ""}`}
131 |
132 |
148 |
149 | );
150 | }
151 | ```
152 |
153 | ## Vue
154 |
155 | ```html
156 |
157 |
158 |
159 | This list is created by calling a GraphQL Fragment with ApolloFragment
160 |
161 |
162 |
163 | Loading...
164 |
165 |
166 | An error occured
167 |
168 |
169 |
170 |
ID: {{data.id}} - {{data.name}}
171 |
172 |
173 |
174 |
177 |
178 |
179 |
180 |
181 |
182 |
201 | ```
202 |
203 | In our examples above, We have used the `ApolloFragment` query component to bind
204 | the current value of the fragment in cache. When a user clicks to load a list of
205 | people, our component subscribed to a user with id "1", will rerender and
206 | display the person's name.
207 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "2.1.2",
3 | "packages": ["packages/*"],
4 | "version": "independent",
5 | "hoist": false
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "license": "MIT",
4 | "scripts": {
5 | "bootstrap": "yarn install && lerna bootstrap",
6 | "postbootstrap": "npm run build",
7 | "build": "lerna run -- build",
8 | "test": "lerna run -- test",
9 | "prelint": "npm run lint-fix",
10 | "lint": "lerna run -- lint",
11 | "lint-fix": "prettier --trailing-comma all --single-quote --write \"packages/*/{src,tests,test,benchmark}/**/*.{j,t}s*\"",
12 | "lint-staged": "lint-staged",
13 | "filesize": "lerna run -- filesize && bundlesize",
14 | "type-check": "lerna run -- type-check",
15 | "coverage": "lerna run -- coverage",
16 | "coverage:upload": "codecov",
17 | "danger": "danger run --verbose",
18 | "predeploy": "npm run build",
19 | "deploy": "lerna publish -m \"chore: Publish\" --independent"
20 | },
21 | "bundlesize": [
22 | {
23 | "name": "apollo-link-state-fragment",
24 | "path": "./packages/apollo-link-state-fragment/lib/bundle.min.js",
25 | "maxSize": "3 Kb"
26 | }
27 | ],
28 | "jest": {
29 | "globals": {
30 | "ts-jest": {
31 | "useBabelrc": false,
32 | "mapCoverage": true
33 | }
34 | },
35 | "mapCoverage": true,
36 | "transform": {
37 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js"
38 | }
39 | },
40 | "lint-staged": {
41 | "*.ts*": [
42 | "prettier --trailing-comma all --single-quote --write",
43 | "git add"
44 | ],
45 | "*.js*": [
46 | "prettier --trailing-comma all --single-quote --write",
47 | "git add"
48 | ],
49 | "*.json*": [
50 | "prettier --write",
51 | "git add"
52 | ]
53 | },
54 | "pre-commit": "lint-staged",
55 | "dependencies": {},
56 | "devDependencies": {
57 | "@types/enzyme": "^3.1.10",
58 | "@types/jest": "22.1.x",
59 | "@types/react": "^16.3.14",
60 | "@types/zen-observable": "0.5.3",
61 | "bundlesize": "0.15.3",
62 | "codecov": "3.0.0",
63 | "danger": "1.2.0",
64 | "lerna": "2.5.1",
65 | "lint-staged": "5.0.0",
66 | "pre-commit": "1.2.2",
67 | "prettier": "^1.19.1",
68 | "react-scripts": "^1.1.1",
69 | "ts-jest": "21.2.3",
70 | "typescript": "^4.1.2",
71 | "vue-apollo": "^3.0.0-beta.19"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/.npmignore:
--------------------------------------------------------------------------------
1 | dist/tests/
2 | src/
3 | tests/
4 | .travis.yml
5 | tsconfig.json
6 | tslint.json
7 | typings.d.ts
8 | example/
9 | __tests__/
10 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/README.md:
--------------------------------------------------------------------------------
1 | # Apollo Fragment React Codegen
2 | This package contains a plugin for [GraphQL Code Generator](https://graphql-code-generator.com/)
3 | that allows to generate React hooks with corresponding TypeScript types
4 | based on `useApolloFragment` from `apollo-fragment-react` and GraphQL fragments defined in your app.
5 |
6 | ## Setup
7 | This package **requires** [TypeScript React Apollo](https://graphql-code-generator.com/docs/plugins/typescript-react-apollo) plugin
8 | to be installed and setup to generate fragment documents and types.
9 |
10 | First, install the package:
11 | ```bash
12 | yarn add -D apollo-fragment-react-codegen
13 | ```
14 | Then register the plugin in GraphQL Code Generator config (`codegen.yml` by default):
15 | ```yml
16 | generates:
17 | path/to/file.ts:
18 | plugins:
19 | - typescript
20 | - typescript-operations
21 | - typescript-react-apollo
22 | - apollo-fragment-react-codegen
23 | config:
24 | withHooks: true
25 | ```
26 | Now, whenever you run your codegen script, it will also generate React hooks based on existing fragment definitions
27 | which you then can use in your code instead of `useApolloFragment`.
28 |
29 | ## Usage
30 | Suppose you have some existing code to read user name and avatar from Apollo Client cache using `useApolloFragment`:
31 | ```typescript
32 | // UserAvatar.tsx
33 | import gql from 'graphql-tag'
34 | import { useApolloFragment } from 'apollo-fragment-react'
35 | import { User } from 'src/generated.ts'
36 |
37 | const userAvatarAndNameFragment = gql`
38 | fragment userAvatarAndNameFragment on User {
39 | name
40 | avatarUrl
41 | }
42 | `
43 |
44 | type FragmentData = Pick
45 |
46 | export function UserAvatar(userId: string) {
47 | const { data: userData } = useApolloFragment(userId)
48 |
49 | if (!userData) {
50 | return null
51 | }
52 |
53 | return
54 | }
55 | ```
56 | To leverage GraphQL codegen, let's move the fragment definiton into a `.graphql` file:
57 | ```graphql
58 | # fragments.graphql
59 |
60 | fragment userAvatarAndName on User {
61 | name
62 | avatarUrl
63 | }
64 | ```
65 | and make sure that we include this file in the codegen configuration:
66 | ```yml
67 | documents:
68 | - "src/**/*.graphql"
69 | # OR
70 | # - "src/**/fragments.graphql"
71 | ```
72 | Now, when we run the codegen script, the generated file should also include something like this:
73 | ```typescript
74 | export function useUserAvatarAndNameFragment(id: string) {
75 | return useApolloFragment(
76 | UserAvatarAndNameFragmentDoc,
77 | id
78 | )
79 | }
80 | export type UserAvatarAndNameFragmentHookResult = ReturnType<
81 | typeof useUserAvatarAndNameFragment
82 | >
83 | ```
84 | Next we can update our `UserAvatar` component:
85 | ```typescript
86 | // UserAvatar.tsx
87 | import { useUserAvatarAndNameFragment } from 'src/generated.ts'
88 |
89 | export function UserAvatar(userId: string) {
90 | const { data: userData } = useUserAvatarAndNameFragment(userId)
91 |
92 | if (!userData) {
93 | return null
94 | }
95 |
96 | return
97 | }
98 | ```
99 | `useUserAvatarAndNameFragment` is just a wrapper around `useApolloFragment` which reduce the amount of boilerplate and also properly types the return value.
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo-fragment-react-codegen",
3 | "version": "0.7.2",
4 | "description": "A plugin for graphql-code-generator that allows to generate React hooks based on fragment definitions",
5 | "author": "Aleksei Ustiuzhanin ",
6 | "license": "MIT",
7 | "main": "lib/index.js",
8 | "module": "lib/index.esm.js",
9 | "typings": "lib/index.d.ts",
10 | "typescript": {
11 | "definition": "lib/index.d.ts"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/abhiaiyer91/apollo-fragment.git"
16 | },
17 | "bugs": {
18 | "url": "https://github.com/abhiaiyer91/apollo-fragment/issues"
19 | },
20 | "homepage": "https://github.com/abhiaiyer91/apollo-fragment#readme",
21 | "scripts": {
22 | "build": "tsc -p .",
23 | "clean": "rimraf lib/* && rimraf coverage/*",
24 | "prelint": "npm run lint-fix",
25 | "lint-fix": "prettier --trailing-comma all --single-quote --write \"src/**/*.{j,t}s*\"",
26 | "lint": "tslint --type-check -p tsconfig.json -c tslint.json src/*.ts",
27 | "lint-staged": "lint-staged",
28 | "prebuild": "npm run clean",
29 | "prepublishOnly": "npm run clean && npm run build",
30 | "test": "jest",
31 | "coverage": "npm run lint && jest --coverage",
32 | "watch": "trap 'kill -9 %1' SIGINT; tsc -w -p ."
33 | },
34 | "peerDependencies": {
35 | "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0",
36 | "graphql-tag": "^2.0.0"
37 | },
38 | "devDependencies": {
39 | "@types/graphql": "^14.5.0",
40 | "@types/jest": "22.1.x",
41 | "codecov": "3.0.0",
42 | "danger": "1.2.0",
43 | "graphql": "^15.1.0",
44 | "graphql-tag": "^2.0.0",
45 | "jest": "21.2.1",
46 | "lint-staged": "4.3.0",
47 | "pre-commit": "1.2.2",
48 | "prettier": "1.7.4",
49 | "rimraf": "2.6.1",
50 | "ts-jest": "21.1.4",
51 | "tslint": "5.8.0",
52 | "typescript": "^4.1.2"
53 | },
54 | "jest": {
55 | "mapCoverage": true,
56 | "transform": {
57 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js"
58 | },
59 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
60 | "moduleFileExtensions": [
61 | "ts",
62 | "tsx",
63 | "js",
64 | "json"
65 | ]
66 | },
67 | "dependencies": {
68 | "@graphql-codegen/plugin-helpers": "^1.15.4",
69 | "@graphql-codegen/visitor-plugin-common": "^1.15.4",
70 | "pascal-case": "^3.1.1"
71 | },
72 | "lint-staged": {
73 | "*.ts*": [
74 | "prettier --trailing-comma all --single-quote --write",
75 | "git add"
76 | ],
77 | "*.js*": [
78 | "prettier --trailing-comma all --single-quote --write",
79 | "git add"
80 | ],
81 | "*.json*": [
82 | "prettier --write",
83 | "git add"
84 | ]
85 | },
86 | "pre-commit": "lint-staged"
87 | }
88 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/src/config.ts:
--------------------------------------------------------------------------------
1 | import { RawClientSideBasePluginConfig } from '@graphql-codegen/visitor-plugin-common';
2 |
3 | /**
4 | * @description This plugin generates hooks based on apollo-fragment-react with TypeScript typings.
5 | *
6 | * It requires typescript-react-apollo to be setup to generate fragment documents.
7 | */
8 | export interface ApolloFragmentReactRawPluginConfig
9 | extends RawClientSideBasePluginConfig {
10 | /**
11 | * @description Customize the package where apollo-fragment-react lib is loaded from.
12 | * @default "apollo-fragment-react"
13 | */
14 | apolloFragmentReactImportFrom?: string;
15 | /**
16 | * @description Allows you to enable/disable the generation of docblocks in generated code.
17 | * Some IDE's (like VSCode) add extra inline information with docblocks, you can disable this feature if your preferred IDE does not.
18 | * @default true
19 | *
20 | * @exampleMarkdown
21 | * ```yml
22 | * generates:
23 | * path/to/file.ts:
24 | * plugins:
25 | * - typescript
26 | * - typescript-operations
27 | * - typescript-react-apollo
28 | * - apollo-fragment-react-codegen
29 | * config:
30 | * addDocBlocks: true
31 | * ```
32 | */
33 | addDocBlocks?: boolean;
34 | }
35 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/src/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Types,
3 | PluginValidateFn,
4 | PluginFunction,
5 | } from '@graphql-codegen/plugin-helpers';
6 | import {
7 | GraphQLSchema,
8 | concatAST,
9 | Kind,
10 | FragmentDefinitionNode,
11 | } from 'graphql';
12 | import { LoadedFragment } from '@graphql-codegen/visitor-plugin-common';
13 | import { ApolloFragmentReactVisitor } from './visitor';
14 | import { extname } from 'path';
15 | import { ApolloFragmentReactRawPluginConfig } from './config';
16 |
17 | export const plugin: PluginFunction<
18 | ApolloFragmentReactRawPluginConfig,
19 | Types.ComplexPluginOutput
20 | > = (
21 | schema: GraphQLSchema,
22 | documents: Types.DocumentFile[],
23 | config: ApolloFragmentReactRawPluginConfig,
24 | ) => {
25 | const allAst = concatAST(documents.map(v => v.document));
26 |
27 | const allFragments: LoadedFragment[] = [
28 | ...(allAst.definitions.filter(
29 | d => d.kind === Kind.FRAGMENT_DEFINITION,
30 | ) as FragmentDefinitionNode[]).map(fragmentDef => ({
31 | node: fragmentDef,
32 | name: fragmentDef.name.value,
33 | onType: fragmentDef.typeCondition.name.value,
34 | isExternal: false,
35 | })),
36 | ...(config.externalFragments || []),
37 | ];
38 |
39 | const visitor = new ApolloFragmentReactVisitor(
40 | schema,
41 | allFragments,
42 | config,
43 | documents,
44 | );
45 |
46 | return {
47 | prepend: visitor.getImports(),
48 | content: visitor.fragments,
49 | };
50 | };
51 |
52 | export const validate: PluginValidateFn = async (
53 | _schema: GraphQLSchema,
54 | _documents: Types.DocumentFile[],
55 | _config: ApolloFragmentReactRawPluginConfig,
56 | outputFile: string,
57 | ) => {
58 | if (extname(outputFile) !== '.ts' && extname(outputFile) !== '.tsx') {
59 | throw new Error(
60 | `Plugin "apollo-fragment-react-codegen" requires extension to be ".ts" or ".tsx"!`,
61 | );
62 | }
63 | };
64 |
65 | export { ApolloFragmentReactVisitor };
66 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/src/visitor.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ClientSideBaseVisitor,
3 | ClientSideBasePluginConfig,
4 | getConfigValue,
5 | LoadedFragment,
6 | } from '@graphql-codegen/visitor-plugin-common';
7 | import { ApolloFragmentReactRawPluginConfig } from './config';
8 | import autoBind from 'auto-bind';
9 | import { GraphQLSchema, FragmentDefinitionNode } from 'graphql';
10 | import { Types } from '@graphql-codegen/plugin-helpers';
11 | import { pascalCase } from 'pascal-case';
12 |
13 | export interface ReactApolloPluginConfig extends ClientSideBasePluginConfig {
14 | apolloFragmentReactImportFrom: string;
15 | withResultType: boolean;
16 | addDocBlocks: boolean;
17 | }
18 |
19 | export class ApolloFragmentReactVisitor extends ClientSideBaseVisitor<
20 | ApolloFragmentReactRawPluginConfig,
21 | ReactApolloPluginConfig
22 | > {
23 | imports: Set;
24 |
25 | constructor(
26 | schema: GraphQLSchema,
27 | fragments: LoadedFragment[],
28 | rawConfig: ApolloFragmentReactRawPluginConfig,
29 | documents: Types.DocumentFile[],
30 | ) {
31 | super(schema, fragments, rawConfig, {
32 | apolloFragmentReactImportFrom: getConfigValue(
33 | rawConfig.apolloFragmentReactImportFrom,
34 | `apollo-fragment-react`,
35 | ),
36 | addDocBlocks: getConfigValue(rawConfig.addDocBlocks, true),
37 | });
38 |
39 | this._documents = documents;
40 | this.imports = new Set();
41 |
42 | autoBind(this);
43 | }
44 |
45 | public getImports(): string[] {
46 | const baseImports = super.getImports();
47 |
48 | if (!this.fragments) {
49 | return baseImports;
50 | }
51 |
52 | return [...baseImports, ...this.imports];
53 | }
54 |
55 | protected _generateFragment(fragmentDocument: FragmentDefinitionNode) {
56 | this.imports.add(this.getApolloFragmentReactImport());
57 | const hooks = this._buildHooks(fragmentDocument);
58 |
59 | return [hooks, ''].filter(a => a).join('\n');
60 | }
61 |
62 | private getApolloFragmentReactImport(): string {
63 | return `import { useApolloFragment } from '${this.config.apolloFragmentReactImportFrom}';`;
64 | }
65 |
66 | private _buildHooksJSDoc(operationName: string): string {
67 | return `
68 | /**
69 | * __use${operationName}__
70 | * To read a fragment data from Apollo Cache, call \`use${operationName}\` and pass it the ID of the cached object.
71 | * When your component renders, \`use${operationName}\` returns an object from Apollo Client cache that contains data property
72 | * you can use to render your UI.
73 | *
74 | * @param id a string representing the ID of the cached object that will be passed into the useApolloFragment
75 | *
76 | * @example
77 | * const { data } = use${operationName}('fragment-id');
78 | */`;
79 | }
80 |
81 | private _buildHooks(fragment: FragmentDefinitionNode): string {
82 | const suffix = this._getHookSuffix(fragment.name.value);
83 | const operationName: string = this.convertName(fragment.name.value, {
84 | suffix,
85 | useTypesPrefix: false,
86 | });
87 |
88 | const hookFns = [
89 | `export function use${operationName}(id: string) {
90 | return useApolloFragment<${this.getFragmentName(
91 | fragment,
92 | )}>(${this.getFragmentVariableName(fragment)}, id);
93 | }`,
94 | ];
95 |
96 | if (this.config.addDocBlocks) {
97 | hookFns.unshift(this._buildHooksJSDoc(operationName));
98 | }
99 |
100 | const hookResults = [
101 | `export type ${operationName}HookResult = ReturnType;`,
102 | ];
103 |
104 | return [...hookFns, ...hookResults].join('\n');
105 | }
106 |
107 | private _getHookSuffix(name: string) {
108 | if (name.includes('Fragment')) {
109 | return '';
110 | }
111 | return pascalCase(`fragment`);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./src",
4 | "outDir": "lib",
5 | "esModuleInterop": true,
6 | "allowSyntheticDefaultImports": true,
7 | "importHelpers": true,
8 | "experimentalDecorators": true,
9 | "module": "commonjs",
10 | "target": "esnext",
11 | "lib": ["es6", "esnext", "es2015", "dom"],
12 | "suppressImplicitAnyIndexErrors": true,
13 | "moduleResolution": "node",
14 | "emitDecoratorMetadata": true,
15 | "sourceMap": true,
16 | "declaration": true,
17 | "noImplicitThis": true,
18 | "alwaysStrict": true,
19 | "noImplicitReturns": true,
20 | "noUnusedLocals": true,
21 | "resolveJsonModule": true,
22 | "skipLibCheck": true
23 | },
24 | "include": ["./src"]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react-codegen/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "ban": false,
4 | "class-name": true,
5 | "eofline": true,
6 | "forin": true,
7 | "interface-name": [true, "never-prefix"],
8 | "jsdoc-format": true,
9 | "label-position": true,
10 | "member-access": true,
11 | "member-ordering": [
12 | true,
13 | {
14 | "order": [
15 | "static-field",
16 | "instance-field",
17 | "constructor",
18 | "public-instance-method",
19 | "protected-instance-method",
20 | "private-instance-method"
21 | ]
22 | }
23 | ],
24 | "no-any": false,
25 | "no-arg": true,
26 | "no-bitwise": true,
27 | "no-conditional-assignment": true,
28 | "no-consecutive-blank-lines": false,
29 | "no-console": [true, "log", "debug", "info", "time", "timeEnd", "trace"],
30 | "no-construct": true,
31 | "no-debugger": true,
32 | "no-duplicate-variable": true,
33 | "no-empty": true,
34 | "no-eval": true,
35 | "no-inferrable-types": false,
36 | "no-internal-module": true,
37 | "no-null-keyword": false,
38 | "no-require-imports": false,
39 | "no-shadowed-variable": true,
40 | "no-switch-case-fall-through": true,
41 | "no-trailing-whitespace": true,
42 | "no-unused-expression": true,
43 | "no-var-keyword": true,
44 | "no-var-requires": true,
45 | "object-literal-sort-keys": false,
46 | "radix": true,
47 | "switch-default": true,
48 | "triple-equals": [true, "allow-null-check"],
49 | "typedef": [
50 | false,
51 | "call-signature",
52 | "parameter",
53 | "arrow-parameter",
54 | "property-declaration",
55 | "variable-declaration",
56 | "member-variable-declaration"
57 | ],
58 | "variable-name": [
59 | true,
60 | "check-format",
61 | "allow-leading-underscore",
62 | "ban-keywords"
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/.npmignore:
--------------------------------------------------------------------------------
1 | dist/tests/
2 | src/
3 | tests/
4 | .travis.yml
5 | tsconfig.json
6 | tslint.json
7 | typings.d.ts
8 | example/
9 | __tests__/
10 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | coverage
3 | build
4 | .DS_Store
5 | .env
6 | npm-debug.log
7 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "name": "apollo-client-error-template",
4 | "version": "0.1.0",
5 | "devDependencies": {
6 | "gh-pages": "^1.0.0",
7 | "react-scripts": "1.0.16"
8 | },
9 | "dependencies": {
10 | "apollo-cache-inmemory": "^1.0.0",
11 | "apollo-client": "^2.3.1",
12 | "apollo-fragment-react": "^0.1.0",
13 | "apollo-link": "^1.0.0",
14 | "apollo-link-state": "^0.4.1",
15 | "apollo-link-state-fragment": "^0.1.0",
16 | "graphql": "^0.11.7",
17 | "graphql-tag": "^2.5.0",
18 | "react": "^16.0.0",
19 | "react-apollo": "^2.1.4",
20 | "react-dom": "^16.0.0"
21 | },
22 | "scripts": {
23 | "start": "react-scripts start",
24 | "build": "react-scripts build",
25 | "test": "react-scripts test --env=jsdom",
26 | "deploy":
27 | "PUBLIC_URL=/react-apollo-error-template/$(git symbolic-ref --short HEAD) npm run build && gh-pages-clean && gh-pages -d build --dest $(git symbolic-ref --short HEAD) --remote"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abhiaiyer91/apollo-fragment/17e2f414fdcbc4d452538fd00f92c5957e3b9765/packages/apollo-fragment-react/example/public/favicon.ico
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 | React App
17 |
18 |
19 |
20 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { graphql } from 'react-apollo';
3 | import gql from 'graphql-tag';
4 | import { ApolloFragment } from 'apollo-fragment-react';
5 |
6 | const fragment = `
7 | fragment fragmentFields on Person {
8 | id
9 | name
10 | __typename
11 | }
12 | `;
13 |
14 | let ListView = function ListView({ data: { loading, people } }) {
15 | return (
16 |
17 | {loading ? (
18 | Loading…
19 | ) : (
20 |
21 | {people &&
22 | people.map(person => - {person.name}
)}
23 |
24 | )}
25 |
26 | );
27 | };
28 |
29 | ListView = graphql(
30 | gql`
31 | query peeps {
32 | people {
33 | id
34 | name
35 | }
36 | }
37 | `,
38 | )(ListView);
39 |
40 | export default class App extends Component {
41 | constructor() {
42 | super();
43 | this.state = {
44 | showView: false,
45 | };
46 | }
47 | render() {
48 | const { showView } = this.state;
49 |
50 | return (
51 |
52 |
55 |
56 |
57 | {({ data }) => {
58 | return (
59 |
60 |
61 | This component is "watching" a fragment, it will render the
62 | persons name once the list view renders
63 |
64 | {data && `Person Name: ${data.name || ''}`}
65 |
66 | );
67 | }}
68 |
69 |
70 |
71 |
72 |
73 | {showView && }
74 |
75 |
82 |
83 | );
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/src/graphql/link.js:
--------------------------------------------------------------------------------
1 | import { graphql, print } from 'graphql';
2 | import { ApolloLink, Observable } from 'apollo-link';
3 | import { schema } from './schema';
4 |
5 | export const link = new ApolloLink(operation => {
6 | return new Observable(observer => {
7 | const { query, operationName, variables } = operation;
8 | delay(300)
9 | .then(() =>
10 | graphql(schema, print(query), null, null, variables, operationName),
11 | )
12 | .then(result => {
13 | observer.next(result);
14 | observer.complete();
15 | })
16 | .catch(observer.error.bind(observer));
17 | });
18 | });
19 |
20 | function delay(ms) {
21 | return new Promise(resolve => {
22 | setTimeout(() => {
23 | resolve();
24 | }, ms);
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/src/graphql/schema.js:
--------------------------------------------------------------------------------
1 | import {
2 | GraphQLSchema,
3 | GraphQLObjectType,
4 | GraphQLID,
5 | GraphQLString,
6 | GraphQLList,
7 | } from 'graphql';
8 |
9 | const PersonType = new GraphQLObjectType({
10 | name: 'Person',
11 | fields: {
12 | id: { type: GraphQLID },
13 | name: { type: GraphQLString },
14 | },
15 | });
16 |
17 | const peopleData = [
18 | { id: 1, name: 'John Smith' },
19 | { id: 2, name: 'Sara Smith' },
20 | { id: 3, name: 'Budd Deey' },
21 | ];
22 |
23 | const QueryType = new GraphQLObjectType({
24 | name: 'Query',
25 | fields: {
26 | people: {
27 | type: new GraphQLList(PersonType),
28 | resolve: () => peopleData,
29 | },
30 | },
31 | });
32 |
33 | export const schema = new GraphQLSchema({ query: QueryType });
34 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: sans-serif;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/example/src/index.js:
--------------------------------------------------------------------------------
1 | import './index.css';
2 |
3 | import React from 'react';
4 | import { render } from 'react-dom';
5 | import { ApolloLink } from 'apollo-link';
6 | import { ApolloClient } from 'apollo-client';
7 | import { ApolloProvider } from 'react-apollo';
8 | import { InMemoryCache } from 'apollo-cache-inmemory';
9 | import {
10 | fragmentCacheRedirect,
11 | fragmentLinkState,
12 | } from 'apollo-link-state-fragment';
13 | import { link } from './graphql/link';
14 | import App from './App';
15 |
16 | const cache = new InMemoryCache({
17 | cacheRedirects: {
18 | Query: {
19 | ...fragmentCacheRedirect(),
20 | },
21 | },
22 | });
23 |
24 | const client = new ApolloClient({
25 | cache,
26 | link: ApolloLink.from([fragmentLinkState(cache), link]),
27 | });
28 |
29 | render(
30 |
31 |
32 | ,
33 | document.getElementById('root'),
34 | );
35 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo-fragment-react",
3 | "version": "0.7.1",
4 | "description": "A React hook to connect React components to GraphQL fragments in Apollo Client cache",
5 | "author": "Abhi Aiyer ",
6 | "license": "MIT",
7 | "main": "./lib/bundle.umd.js",
8 | "module": "./lib/index.js",
9 | "jsnext:main": "./lib/index.js",
10 | "typings": "./lib/index.d.ts",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/abhiaiyer91/apollo-fragment.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/abhiaiyer91/apollo-fragment/issues"
17 | },
18 | "homepage": "https://github.com/abhiaiyer91/apollo-fragment#readme",
19 | "scripts": {
20 | "build:browser": "browserify ./lib/bundle.umd.js -o=./lib/bundle.js --i apollo-link --i apollo-utilities --i graphql-anywhere && npm run minify:browser",
21 | "build": "tsc -p .",
22 | "bundle": "rollup -c",
23 | "clean": "rimraf lib/* && rimraf coverage/*",
24 | "filesize": "npm run build && npm run build:browser && bundlesize",
25 | "prelint": "npm run lint-fix",
26 | "lint-fix": "prettier --trailing-comma all --single-quote --write \"src/**/*.{j,t}s*\"",
27 | "lint": "tslint --type-check -p tsconfig.json -c tslint.json src/*.ts",
28 | "lint-staged": "lint-staged",
29 | "minify:browser": "uglifyjs -c -m -o ./lib/bundle.min.js -- ./lib/bundle.js",
30 | "postbuild": "npm run bundle",
31 | "prebuild": "npm run clean",
32 | "prepublishOnly": "npm run clean && npm run build",
33 | "test": "jest",
34 | "coverage": "npm run lint && jest --coverage",
35 | "watch": "trap 'kill -9 %1' SIGINT; tsc -w -p . & rollup -w -c"
36 | },
37 | "bundlesize": [
38 | {
39 | "name": "apollo-fragment-react",
40 | "path": "./lib/bundle.min.js",
41 | "threshold": "1 Kb"
42 | }
43 | ],
44 | "peerDependencies": {
45 | "@apollo/client": "^3.5.6"
46 | },
47 | "devDependencies": {
48 | "@types/graphql": "0.11.5",
49 | "@types/jest": "22.1.x",
50 | "apollo-cache-inmemory": "^1.1.5",
51 | "@apollo/client": "^3.5.6",
52 | "apollo-link": "^1.0.0",
53 | "browserify": "14.5.0",
54 | "bundlesize": "0.15.3",
55 | "codecov": "3.0.0",
56 | "danger": "1.2.0",
57 | "enzyme": "^3.3.0",
58 | "enzyme-adapter-react-16": "^1.1.1",
59 | "graphql": "0.11.7",
60 | "graphql-tag": "2.5.0",
61 | "jest": "21.2.1",
62 | "lint-staged": "4.3.0",
63 | "pre-commit": "1.2.2",
64 | "prettier": "1.7.4",
65 | "react": "^16.8.6",
66 | "react-dom": "^16.8.6",
67 | "rimraf": "2.6.1",
68 | "rollup": "0.56.x",
69 | "rollup-plugin-local-resolve": "1.0.x",
70 | "rollup-plugin-sourcemaps": "0.4.x",
71 | "ts-jest": "21.1.4",
72 | "tslint": "5.8.0",
73 | "typescript": "^4.1.2",
74 | "uglify-js": "3.1.5"
75 | },
76 | "jest": {
77 | "mapCoverage": true,
78 | "transform": {
79 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js"
80 | },
81 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
82 | "moduleFileExtensions": [
83 | "ts",
84 | "tsx",
85 | "js",
86 | "json"
87 | ],
88 | "setupFiles": [
89 | "/src/mocks/enzymeAdapter.ts"
90 | ]
91 | },
92 | "dependencies": {
93 | "apollo-fragment-utils": "^0.2.1",
94 | "apollo-utilities": "^1.0.12",
95 | "compose-tiny": "^1.1.3"
96 | },
97 | "lint-staged": {
98 | "*.ts*": [
99 | "prettier --trailing-comma all --single-quote --write",
100 | "git add"
101 | ],
102 | "*.js*": [
103 | "prettier --trailing-comma all --single-quote --write",
104 | "git add"
105 | ],
106 | "*.json*": [
107 | "prettier --write",
108 | "git add"
109 | ]
110 | },
111 | "pre-commit": "lint-staged"
112 | }
113 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-local-resolve';
2 | import sourcemaps from 'rollup-plugin-sourcemaps';
3 |
4 | const globals = {
5 | // Apollo
6 | 'apollo-client': 'apollo.core',
7 | 'apollo-cache': 'apolloCache.core',
8 | 'apollo-link': 'apolloLink.core',
9 | 'apollo-utilities': 'apollo.utilities',
10 |
11 | 'graphql-anywhere/lib/async': 'graphqlAnywhere.async',
12 | };
13 |
14 | export default {
15 | input: 'lib/index.js',
16 | output: {
17 | file: 'lib/bundle.umd.js',
18 | format: 'umd',
19 | name: 'apolloFragmentReact.state',
20 | exports: 'named',
21 | sourcemap: true,
22 | globals,
23 | },
24 | external: Object.keys(globals),
25 | onwarn,
26 | plugins: [resolve(), sourcemaps()],
27 | };
28 |
29 | function onwarn(message) {
30 | const suppressed = ['UNRESOLVED_IMPORT', 'THIS_IS_UNDEFINED'];
31 |
32 | if (!suppressed.find(code => message.code === code)) {
33 | return console.warn(message.message);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { ApolloClient, InMemoryCacheConfig } from '@apollo/client';
3 | import { useQuery, QueryResult } from '@apollo/client/react';
4 | import { DocumentNode, Location } from 'graphql';
5 | import { getFragmentInfo, buildFragmentQuery } from 'apollo-fragment-utils';
6 |
7 | type FragmentQueryData = {
8 | getFragment?: TData;
9 | };
10 |
11 | export type SupportedFragment = DocumentNode | string;
12 |
13 | type Omit = Pick>;
14 |
15 | export type ApolloFragmentResult = Omit<
16 | QueryResult>,
17 | 'data'
18 | > & {
19 | data: TData | undefined;
20 | };
21 |
22 | export function useApolloFragment(
23 | fragment: SupportedFragment,
24 | id: string,
25 | ): ApolloFragmentResult {
26 | const fragmentQuery = React.useMemo(() => createFragmentQuery(fragment), [
27 | fragment,
28 | ]);
29 |
30 | const { data, client, ...rest } = useQuery>(
31 | fragmentQuery.query,
32 | {
33 | fetchPolicy: 'cache-only',
34 | variables: {
35 | id,
36 | __typename: fragmentQuery.fragmentTypeName,
37 | },
38 | },
39 | );
40 |
41 | const fragmentData = data && data.getFragment;
42 |
43 | if (!fragmentData) {
44 | checkDataCompleteness({
45 | fragmentQuery,
46 | id,
47 | client,
48 | });
49 | }
50 |
51 | return {
52 | data: fragmentData,
53 | client,
54 | ...rest,
55 | };
56 | }
57 |
58 | export const fragmentCacheConfig: Required> = {
62 | typePolicies: {
63 | Query: {
64 | fields: {
65 | getFragment(_, { args, toReference }) {
66 | return toReference({
67 | id: args ? args.id : undefined,
68 | __typename: args ? args.__typename : undefined,
69 | });
70 | },
71 | },
72 | },
73 | },
74 | };
75 |
76 | type FragmentQuery = {
77 | query: DocumentNode;
78 | fragmentTypeName: string;
79 | fragmentSource: string;
80 | };
81 |
82 | function createFragmentQuery(fragment: SupportedFragment): FragmentQuery {
83 | const { fragmentTypeName, fragmentName } = getFragmentInfo(fragment);
84 |
85 | return {
86 | query: buildFragmentQuery({ fragment, fragmentName }),
87 | fragmentTypeName: fragmentTypeName,
88 | fragmentSource:
89 | typeof fragment === `string`
90 | ? fragment
91 | : (fragment.loc as Location).source.body,
92 | };
93 | }
94 |
95 | function checkDataCompleteness({
96 | fragmentQuery,
97 | id,
98 | client,
99 | }: {
100 | fragmentQuery: FragmentQuery;
101 | id: string;
102 | client: ApolloClient;
103 | }): void {
104 | // Only perform completeness check for non-production code
105 | if (process.env.NODE_ENV === 'production') {
106 | return;
107 | }
108 |
109 | const diff = client.cache.diff({
110 | query: fragmentQuery.query,
111 | variables: {
112 | id,
113 | __typename: fragmentQuery.fragmentTypeName,
114 | },
115 | previousResult: undefined,
116 | optimistic: true,
117 | });
118 |
119 | if (diff.complete === true) {
120 | return;
121 | }
122 |
123 | const fragmentData = diff.result && diff.result.getFragment;
124 | const noData = Object.keys(fragmentData || {}).length === 0;
125 |
126 | if (noData) {
127 | return;
128 | }
129 | const dataWithoutTypename = { ...fragmentData, __typename: undefined };
130 |
131 | const errorMessage = `
132 | Unable to resolve fragment fields for ${fragmentQuery.fragmentTypeName}:${id}:
133 | ${fragmentQuery.fragmentSource.trimRight()}
134 |
135 | Available data:
136 | ${JSON.stringify(dataWithoutTypename, null, 2)}
137 |
138 | Make sure that the fields requested in the fragment are fetched by some query`;
139 |
140 | console.error(errorMessage);
141 | }
142 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/src/mocks/enzymeAdapter.ts:
--------------------------------------------------------------------------------
1 | import * as Enzyme from 'enzyme';
2 | const Adapter = require('enzyme-adapter-react-16');
3 |
4 | Enzyme.configure({ adapter: new Adapter() });
5 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/src/mocks/mockLink.ts:
--------------------------------------------------------------------------------
1 | import { graphql, print, ExecutionResult } from 'graphql';
2 | import { ApolloLink, FetchResult, Observable } from '@apollo/client';
3 | import { schema } from './mockSchema';
4 |
5 | export default new ApolloLink(operation => {
6 | return new Observable(observer => {
7 | const { query, operationName, variables } = operation;
8 | delay(300)
9 | .then(() =>
10 | graphql(schema, print(query), null, null, variables, operationName),
11 | )
12 | .then((result: ExecutionResult) => {
13 | observer.next(result);
14 | observer.complete();
15 | })
16 | .catch(observer.error.bind(observer));
17 | });
18 | });
19 |
20 | function delay(ms: number) {
21 | return new Promise(resolve => {
22 | setTimeout(() => {
23 | resolve();
24 | }, ms);
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/src/mocks/mockSchema.ts:
--------------------------------------------------------------------------------
1 | import {
2 | GraphQLSchema,
3 | GraphQLObjectType,
4 | GraphQLID,
5 | GraphQLString,
6 | GraphQLList,
7 | } from 'graphql';
8 |
9 | const PersonType = new GraphQLObjectType({
10 | name: 'Person',
11 | fields: {
12 | id: { type: GraphQLID },
13 | name: { type: GraphQLString },
14 | },
15 | });
16 |
17 | const peopleData = [
18 | { id: 1, name: 'John Smith' },
19 | { id: 2, name: 'Sara Smith' },
20 | { id: 3, name: 'Budd Deey' },
21 | ];
22 |
23 | const QueryType = new GraphQLObjectType({
24 | name: 'Query',
25 | fields: {
26 | people: {
27 | type: new GraphQLList(PersonType),
28 | resolve: () => peopleData,
29 | },
30 | },
31 | });
32 |
33 | export const schema = new GraphQLSchema({ query: QueryType });
34 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": false,
4 | "declaration": true,
5 | "experimentalDecorators": true,
6 | "jsx": "react",
7 | "lib": ["es2015", "dom"],
8 | "module": "es2015",
9 | "moduleResolution": "node",
10 | "noUnusedParameters": true,
11 | "outDir": "lib",
12 | "pretty": true,
13 | "removeComments": true,
14 | "skipLibCheck": true,
15 | "sourceMap": true,
16 | "strict": true,
17 | "target": "es5"
18 | },
19 | "include": ["./typings/**/*", "./src/index.tsx", "./test/**/*"],
20 | "exclude": ["./node_modules", "./dist", "./lib", "./src/mocks"]
21 | }
22 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-react/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "ban": false,
4 | "class-name": true,
5 | "eofline": true,
6 | "forin": true,
7 | "interface-name": [true, "never-prefix"],
8 | "jsdoc-format": true,
9 | "label-position": true,
10 | "member-access": true,
11 | "member-ordering": [
12 | true,
13 | {
14 | "order": [
15 | "static-field",
16 | "instance-field",
17 | "constructor",
18 | "public-instance-method",
19 | "protected-instance-method",
20 | "private-instance-method"
21 | ]
22 | }
23 | ],
24 | "no-any": false,
25 | "no-arg": true,
26 | "no-bitwise": true,
27 | "no-conditional-assignment": true,
28 | "no-consecutive-blank-lines": false,
29 | "no-console": [true, "log", "debug", "info", "time", "timeEnd", "trace"],
30 | "no-construct": true,
31 | "no-debugger": true,
32 | "no-duplicate-variable": true,
33 | "no-empty": true,
34 | "no-eval": true,
35 | "no-inferrable-types": false,
36 | "no-internal-module": true,
37 | "no-null-keyword": false,
38 | "no-require-imports": false,
39 | "no-shadowed-variable": true,
40 | "no-switch-case-fall-through": true,
41 | "no-trailing-whitespace": true,
42 | "no-unused-expression": true,
43 | "no-var-keyword": true,
44 | "no-var-requires": true,
45 | "object-literal-sort-keys": false,
46 | "radix": true,
47 | "switch-default": true,
48 | "triple-equals": [true, "allow-null-check"],
49 | "typedef": [
50 | false,
51 | "call-signature",
52 | "parameter",
53 | "arrow-parameter",
54 | "property-declaration",
55 | "variable-declaration",
56 | "member-variable-declaration"
57 | ],
58 | "variable-name": [
59 | true,
60 | "check-format",
61 | "allow-leading-underscore",
62 | "ban-keywords"
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/.npmignore:
--------------------------------------------------------------------------------
1 | dist/tests/
2 | src/
3 | tests/
4 | .travis.yml
5 | tsconfig.json
6 | tslint.json
7 | typings.d.ts
8 | example/
9 | __tests__/
10 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo-fragment-utils",
3 | "version": "0.2.1",
4 | "description": "A set of utils to help components to GraphQL fragments",
5 | "author": "Abhi Aiyer ",
6 | "license": "MIT",
7 | "main": "./lib/bundle.umd.js",
8 | "module": "./lib/index.js",
9 | "jsnext:main": "./lib/index.js",
10 | "typings": "./lib/index.d.ts",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/abhiaiyer91/apollo-fragment.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/abhiaiyer91/apollo-fragment/issues"
17 | },
18 | "homepage": "https://github.com/abhiaiyer91/apollo-fragment#readme",
19 | "scripts": {
20 | "build:browser": "browserify ./lib/bundle.umd.js -o=./lib/bundle.js --i apollo-link --i apollo-utilities --i graphql-anywhere && npm run minify:browser",
21 | "build": "tsc -p .",
22 | "bundle": "rollup -c",
23 | "clean": "rimraf lib/* && rimraf coverage/*",
24 | "filesize": "npm run build && npm run build:browser && bundlesize",
25 | "prelint": "npm run lint-fix",
26 | "lint-fix": "prettier --trailing-comma all --single-quote --write \"src/**/*.{j,t}s*\"",
27 | "lint": "tslint --type-check -p tsconfig.json -c tslint.json src/*.ts",
28 | "lint-staged": "lint-staged",
29 | "minify:browser": "uglifyjs -c -m -o ./lib/bundle.min.js -- ./lib/bundle.js",
30 | "postbuild": "npm run bundle",
31 | "prebuild": "npm run clean",
32 | "prepublishOnly": "npm run clean && npm run build",
33 | "test": "jest",
34 | "coverage": "npm run lint && jest --coverage",
35 | "watch": "trap 'kill -9 %1' SIGINT; tsc -w -p . & rollup -w -c"
36 | },
37 | "bundlesize": [
38 | {
39 | "name": "apollo-fragment-utils",
40 | "path": "./lib/bundle.min.js",
41 | "threshold": "1 Kb"
42 | }
43 | ],
44 | "devDependencies": {
45 | "@types/graphql": "0.11.5",
46 | "@types/jest": "22.1.x",
47 | "apollo-cache-inmemory": "^1.1.5",
48 | "apollo-client": "^2.2.0",
49 | "apollo-link": "^1.0.0",
50 | "browserify": "14.5.0",
51 | "bundlesize": "0.15.3",
52 | "codecov": "3.0.0",
53 | "danger": "1.2.0",
54 | "graphql": "0.11.7",
55 | "graphql-tag": "2.5.0",
56 | "jest": "21.2.1",
57 | "lint-staged": "4.3.0",
58 | "pre-commit": "1.2.2",
59 | "prettier": "1.7.4",
60 | "rimraf": "2.6.1",
61 | "rollup": "0.56.x",
62 | "rollup-plugin-local-resolve": "1.0.x",
63 | "rollup-plugin-sourcemaps": "0.4.x",
64 | "ts-jest": "21.1.4",
65 | "tslint": "5.8.0",
66 | "typescript": "^4.1.2",
67 | "uglify-js": "3.1.5"
68 | },
69 | "dependencies": {
70 | "apollo-utilities": "^1.0.12"
71 | },
72 | "jest": {
73 | "mapCoverage": true,
74 | "transform": {
75 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js"
76 | },
77 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
78 | "moduleFileExtensions": [
79 | "ts",
80 | "tsx",
81 | "js",
82 | "json"
83 | ]
84 | },
85 | "lint-staged": {
86 | "*.ts*": [
87 | "prettier --trailing-comma all --single-quote --write",
88 | "git add"
89 | ],
90 | "*.js*": [
91 | "prettier --trailing-comma all --single-quote --write",
92 | "git add"
93 | ],
94 | "*.json*": [
95 | "prettier --write",
96 | "git add"
97 | ]
98 | },
99 | "pre-commit": "lint-staged"
100 | }
101 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-local-resolve';
2 | import sourcemaps from 'rollup-plugin-sourcemaps';
3 |
4 | export default {
5 | input: 'lib/index.js',
6 | output: {
7 | file: 'lib/bundle.umd.js',
8 | format: 'umd',
9 | name: 'apolloFragmentUtils.state',
10 | exports: 'named',
11 | sourcemap: true,
12 | },
13 | onwarn,
14 | plugins: [resolve(), sourcemaps()],
15 | };
16 |
17 | function onwarn(message) {
18 | const suppressed = ['UNRESOLVED_IMPORT', 'THIS_IS_UNDEFINED'];
19 |
20 | if (!suppressed.find(code => message.code === code)) {
21 | return console.warn(message.message);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/src/__tests__/index.test.ts:
--------------------------------------------------------------------------------
1 | import gql from 'graphql-tag';
2 | import { getFragmentInfo, buildFragmentQuery } from '../';
3 |
4 | describe('getFragmentInfo', () => {
5 | it('should return correct fragment name and typename for string fragments', () => {
6 | const fragment = `
7 | fragment testFragment on Person {
8 | name
9 | avatar
10 | }
11 | `;
12 |
13 | const fragmentInfo = getFragmentInfo(fragment);
14 |
15 | expect(fragmentInfo.fragmentName).toBe('testFragment');
16 | expect(fragmentInfo.fragmentTypeName).toBe('Person');
17 | });
18 |
19 | it('should return correct fragment name and typename for fragments parsed into GraphQL AST', () => {
20 | const fragment = gql`
21 | fragment testFragment on Person {
22 | name
23 | avatar
24 | }
25 | `;
26 |
27 | const fragmentInfo = getFragmentInfo(fragment);
28 |
29 | expect(fragmentInfo.fragmentName).toBe('testFragment');
30 | expect(fragmentInfo.fragmentTypeName).toBe('Person');
31 | });
32 | });
33 |
34 | describe('buildFragmentQuery', () => {
35 | const expectedQuery = gql`
36 | query getFragment($id: ID, $__typename: String) {
37 | getFragment(id: $id, __typename: $__typename) @client {
38 | ...testFragment
39 | }
40 | }
41 |
42 | fragment testFragment on Person {
43 | name
44 | avatar
45 | }
46 | `;
47 |
48 | it('should return a valid query based on a string fragment', () => {
49 | const fragment = `
50 | fragment testFragment on Person {
51 | name
52 | avatar
53 | }
54 | `;
55 |
56 | const fragmentQuery = buildFragmentQuery({
57 | fragment,
58 | fragmentName: `testFragment`,
59 | });
60 |
61 | expect(fragmentQuery).toEqual(expectedQuery);
62 | });
63 |
64 | it('should return a valid query based on a fragment parsed into GraphQL AST', () => {
65 | const fragment = gql`
66 | fragment testFragment on Person {
67 | name
68 | avatar
69 | }
70 | `;
71 |
72 | const fragmentQuery = buildFragmentQuery({
73 | fragment,
74 | fragmentName: `testFragment`,
75 | });
76 |
77 | expect(fragmentQuery).toEqual(expectedQuery);
78 | });
79 | });
80 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/src/index.ts:
--------------------------------------------------------------------------------
1 | import gql from 'graphql-tag';
2 | import { DocumentNode } from 'graphql';
3 |
4 | export function getFragmentInfo(fragment: string | DocumentNode) {
5 | const fragmentAST = typeof fragment === `string` ? gql(fragment) : fragment;
6 | const fragmentDefinitions =
7 | fragmentAST.definitions && fragmentAST.definitions[0];
8 | const fragmentName = fragmentDefinitions && fragmentDefinitions.name.value;
9 | const fragmentTypeName =
10 | fragmentDefinitions && fragmentDefinitions.typeCondition.name.value;
11 |
12 | return {
13 | fragmentName,
14 | fragmentTypeName,
15 | };
16 | }
17 |
18 | export type buildFragmentQueryType = {
19 | fragment: string | DocumentNode;
20 | fragmentName: string;
21 | };
22 |
23 | export function buildFragmentQuery({
24 | fragment,
25 | fragmentName,
26 | }: buildFragmentQueryType): DocumentNode {
27 | return gql`
28 | query getFragment($id: ID, $__typename: String) {
29 | getFragment(id: $id, __typename: $__typename) @client {
30 | ...${fragmentName}
31 | }
32 | }
33 | ${fragment}
34 | `;
35 | }
36 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": false,
4 | "declaration": true,
5 | "experimentalDecorators": true,
6 | "lib": ["es2015", "dom"],
7 | "module": "es2015",
8 | "moduleResolution": "node",
9 | "noUnusedParameters": true,
10 | "outDir": "lib",
11 | "pretty": true,
12 | "removeComments": true,
13 | "skipLibCheck": true,
14 | "sourceMap": true,
15 | "strict": true,
16 | "target": "es5"
17 | },
18 | "include": ["./typings/**/*", "./src/index.ts", "./__tests__/**/*"],
19 | "exclude": ["./node_modules", "./dist", "./lib", "./src/mocks"]
20 | }
21 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-utils/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "ban": false,
4 | "class-name": true,
5 | "eofline": true,
6 | "forin": true,
7 | "interface-name": [true, "never-prefix"],
8 | "jsdoc-format": true,
9 | "label-position": true,
10 | "member-access": true,
11 | "member-ordering": [
12 | true,
13 | {
14 | "order": [
15 | "static-field",
16 | "instance-field",
17 | "constructor",
18 | "public-instance-method",
19 | "protected-instance-method",
20 | "private-instance-method"
21 | ]
22 | }
23 | ],
24 | "no-any": false,
25 | "no-arg": true,
26 | "no-bitwise": true,
27 | "no-conditional-assignment": true,
28 | "no-consecutive-blank-lines": false,
29 | "no-console": [true, "log", "debug", "info", "time", "timeEnd", "trace"],
30 | "no-construct": true,
31 | "no-debugger": true,
32 | "no-duplicate-variable": true,
33 | "no-empty": true,
34 | "no-eval": true,
35 | "no-inferrable-types": false,
36 | "no-internal-module": true,
37 | "no-null-keyword": false,
38 | "no-require-imports": false,
39 | "no-shadowed-variable": true,
40 | "no-switch-case-fall-through": true,
41 | "no-trailing-whitespace": true,
42 | "no-unused-expression": true,
43 | "no-var-keyword": true,
44 | "no-var-requires": true,
45 | "object-literal-sort-keys": false,
46 | "radix": true,
47 | "switch-default": true,
48 | "triple-equals": [true, "allow-null-check"],
49 | "typedef": [
50 | false,
51 | "call-signature",
52 | "parameter",
53 | "arrow-parameter",
54 | "property-declaration",
55 | "variable-declaration",
56 | "member-variable-declaration"
57 | ],
58 | "variable-name": [
59 | true,
60 | "check-format",
61 | "allow-leading-underscore",
62 | "ban-keywords"
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/.npmignore:
--------------------------------------------------------------------------------
1 | dist/tests/
2 | src/
3 | tests/
4 | .travis.yml
5 | tsconfig.json
6 | tslint.json
7 | typings.d.ts
8 | example/
9 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/app'],
3 | };
4 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "apollo-fragment-utils": "^0.1.0"
12 | },
13 | "devDependencies": {
14 | "@vue/cli-plugin-babel": "^3.0.0-beta.15",
15 | "@vue/cli-plugin-eslint": "^3.0.0-beta.15",
16 | "@vue/cli-service": "^3.0.0-beta.15",
17 | "ts-loader": "^4.4.2",
18 | "vue-template-compiler": "^2.5.16"
19 | },
20 | "eslintConfig": {
21 | "root": true,
22 | "env": {
23 | "node": true
24 | },
25 | "extends": ["plugin:vue/essential", "eslint:recommended"],
26 | "rules": {},
27 | "parserOptions": {
28 | "parser": "babel-eslint"
29 | }
30 | },
31 | "postcss": {
32 | "plugins": {
33 | "autoprefixer": {}
34 | }
35 | },
36 | "browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]
37 | }
38 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abhiaiyer91/apollo-fragment/17e2f414fdcbc4d452538fd00f92c5957e3b9765/packages/apollo-fragment-vue/example/public/favicon.ico
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | example
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |

4 |
5 |
6 |
7 |
8 |
19 |
20 |
30 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abhiaiyer91/apollo-fragment/17e2f414fdcbc4d452538fd00f92c5957e3b9765/packages/apollo-fragment-vue/example/src/assets/logo.png
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 |
6 |
9 |
10 |
11 | Loading...
12 |
13 |
14 | An error occured
15 |
16 |
17 |
18 |
This list is created by calling a GraphQL Query with ApolloQuery
19 |
20 |
ID: {{people.id}} - {{people.name}}
21 |
22 |
23 |
24 |
25 | No result :(
26 |
27 |
28 |
29 |
This list is created by calling a GraphQL Fragment with ApolloFragment
30 |
34 |
35 | Loading...
36 |
37 |
38 | An error occured
39 |
40 |
41 |
42 |
43 |
ID: {{data.id}} - {{data.name}}
44 |
45 |
46 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
80 |
81 |
82 |
98 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/graphql/link.js:
--------------------------------------------------------------------------------
1 | import { graphql, print } from 'graphql';
2 | import { ApolloLink, Observable } from 'apollo-link';
3 | import { schema } from './schema';
4 |
5 | export const link = new ApolloLink(operation => {
6 | return new Observable(observer => {
7 | const { query, operationName, variables } = operation;
8 | delay(300)
9 | .then(() =>
10 | graphql(schema, print(query), null, null, variables, operationName),
11 | )
12 | .then(result => {
13 | observer.next(result);
14 | observer.complete();
15 | })
16 | .catch(observer.error.bind(observer));
17 | });
18 | });
19 |
20 | function delay(ms) {
21 | return new Promise(resolve => {
22 | setTimeout(() => {
23 | resolve();
24 | }, ms);
25 | });
26 | }
27 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/graphql/personFragment.js:
--------------------------------------------------------------------------------
1 | export default `fragment fragmentFields on Person {
2 | id
3 | name
4 | __typename
5 | }`;
6 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/graphql/schema.js:
--------------------------------------------------------------------------------
1 | import {
2 | GraphQLSchema,
3 | GraphQLObjectType,
4 | GraphQLID,
5 | GraphQLString,
6 | GraphQLList,
7 | } from 'graphql';
8 |
9 | const PersonType = new GraphQLObjectType({
10 | name: 'Person',
11 | fields: {
12 | id: { type: GraphQLID },
13 | name: { type: GraphQLString },
14 | },
15 | });
16 |
17 | const peopleData = [
18 | { id: '1', name: 'John Smith' },
19 | { id: '2', name: 'Sara Smith' },
20 | { id: '3', name: 'Budd Deey' },
21 | ];
22 |
23 | const QueryType = new GraphQLObjectType({
24 | name: 'Query',
25 | fields: {
26 | people: {
27 | type: new GraphQLList(PersonType),
28 | resolve: () => peopleData,
29 | },
30 | },
31 | });
32 |
33 | export const schema = new GraphQLSchema({ query: QueryType });
34 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import App from './App.vue';
3 | import { ApolloClient } from 'apollo-client';
4 | import { ApolloLink } from 'apollo-link';
5 | import { InMemoryCache } from 'apollo-cache-inmemory';
6 | import VueApollo from 'vue-apollo';
7 | import {
8 | fragmentCacheRedirect,
9 | fragmentLinkState,
10 | } from 'apollo-link-state-fragment';
11 | import ApolloFragment from '../../lib';
12 | import { link } from './graphql/link';
13 |
14 | Vue.config.productionTip = false;
15 |
16 | const cache = new InMemoryCache({
17 | cacheRedirects: {
18 | Query: {
19 | ...fragmentCacheRedirect(),
20 | },
21 | },
22 | });
23 |
24 | const client = new ApolloClient({
25 | cache,
26 | link: ApolloLink.from([fragmentLinkState(cache), link]),
27 | });
28 |
29 | // Install the vue plugin
30 | Vue.use(VueApollo);
31 | Vue.use(ApolloFragment);
32 |
33 | const apolloProvider = new VueApollo({
34 | defaultClient: client,
35 | });
36 |
37 | new Vue({
38 | render: h => h(App),
39 | provide: apolloProvider.provide(),
40 | }).$mount('#app');
41 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/example/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | chainWebpack: config => {
3 | const lintRule = config.module.rule('eslint');
4 |
5 | lintRule.uses.clear();
6 | config.resolve.extensions.prepend('.ts');
7 | config.resolve.extensions.prepend('.mjs');
8 |
9 | config.module
10 | .rule('mjs')
11 | .test(/\.mjs$/)
12 | .type('javascript/auto');
13 |
14 | config.module
15 | .rule('ts')
16 | .test(/\.tsx?$/)
17 | .use('ts-loader')
18 | .loader('ts-loader');
19 | },
20 | };
21 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo-fragment-vue",
3 | "version": "0.1.5",
4 | "description": "A Query component to connect Vue components to GraphQL fragments",
5 | "author": "Abhi Aiyer ",
6 | "license": "MIT",
7 | "main": "./lib/bundle.umd.js",
8 | "module": "./lib/index.js",
9 | "jsnext:main": "./lib/index.js",
10 | "typings": "./lib/index.d.ts",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/abhiaiyer91/apollo-fragment.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/abhiaiyer91/apollo-fragment/issues"
17 | },
18 | "homepage": "https://github.com/abhiaiyer91/apollo-fragment#readme",
19 | "scripts": {
20 | "build:browser": "browserify ./lib/bundle.umd.js -o=./lib/bundle.js --i apollo-link --i apollo-utilities --i graphql-anywhere && npm run minify:browser",
21 | "build": "tsc -p .",
22 | "bundle": "rollup -c",
23 | "clean": "rimraf lib/* && rimraf coverage/*",
24 | "filesize": "npm run build && npm run build:browser && bundlesize",
25 | "prelint": "npm run lint-fix",
26 | "lint-fix": "prettier --trailing-comma all --single-quote --write \"src/**/*.{j,t}s*\"",
27 | "lint": "tslint --type-check -p tsconfig.json -c tslint.json src/*.ts",
28 | "lint-staged": "lint-staged",
29 | "minify:browser": "uglifyjs -c -m -o ./lib/bundle.min.js -- ./lib/bundle.js",
30 | "postbuild": "npm run bundle",
31 | "prebuild": "npm run clean",
32 | "prepublishOnly": "npm run clean && npm run build",
33 | "test": "jest",
34 | "coverage": "npm run lint && jest --coverage",
35 | "watch": "trap 'kill -9 %1' SIGINT; tsc -w -p . & rollup -w -c"
36 | },
37 | "bundlesize": [
38 | {
39 | "name": "apollo-fragment-vue",
40 | "path": "./lib/bundle.min.js",
41 | "threshold": "1 Kb"
42 | }
43 | ],
44 | "peerDependencies": {
45 | "apollo-link-state": "0.4.1",
46 | "vue-apollo": "^3.0.0-beta.19"
47 | },
48 | "devDependencies": {
49 | "@types/graphql": "0.11.5",
50 | "@types/jest": "22.1.x",
51 | "apollo-cache-inmemory": "^1.1.5",
52 | "apollo-client": "^2.2.0",
53 | "apollo-link": "^1.0.0",
54 | "browserify": "14.5.0",
55 | "bundlesize": "0.15.3",
56 | "codecov": "3.0.0",
57 | "danger": "1.2.0",
58 | "graphql": "0.11.7",
59 | "graphql-tag": "2.9.2",
60 | "lint-staged": "4.3.0",
61 | "pre-commit": "1.2.2",
62 | "prettier": "1.7.4",
63 | "rimraf": "2.6.1",
64 | "rollup": "0.56.x",
65 | "rollup-plugin-local-resolve": "1.0.x",
66 | "rollup-plugin-sourcemaps": "0.4.x",
67 | "ts-jest": "21.1.4",
68 | "tslint": "5.8.0",
69 | "typescript": "^4.1.2",
70 | "uglify-js": "3.1.5",
71 | "vue": "^2.5.16",
72 | "vue-apollo": "3.0.0-beta.19"
73 | },
74 | "dependencies": {
75 | "apollo-fragment-utils": "^0.2.1",
76 | "apollo-utilities": "^1.0.12"
77 | },
78 | "lint-staged": {
79 | "*.ts*": [
80 | "prettier --trailing-comma all --single-quote --write",
81 | "git add"
82 | ],
83 | "*.js*": [
84 | "prettier --trailing-comma all --single-quote --write",
85 | "git add"
86 | ],
87 | "*.json*": [
88 | "prettier --write",
89 | "git add"
90 | ]
91 | },
92 | "pre-commit": "lint-staged"
93 | }
94 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-local-resolve';
2 | import sourcemaps from 'rollup-plugin-sourcemaps';
3 |
4 | const globals = {
5 | // Apollo
6 | 'apollo-client': 'apollo.core',
7 | 'apollo-cache': 'apolloCache.core',
8 | 'apollo-link': 'apolloLink.core',
9 | 'apollo-utilities': 'apollo.utilities',
10 |
11 | 'graphql-anywhere/lib/async': 'graphqlAnywhere.async',
12 | };
13 |
14 | export default {
15 | input: 'lib/index.js',
16 | output: {
17 | file: 'lib/bundle.umd.js',
18 | format: 'umd',
19 | name: 'apolloFragmentReact.state',
20 | exports: 'named',
21 | sourcemap: true,
22 | globals,
23 | },
24 | external: Object.keys(globals),
25 | onwarn,
26 | plugins: [resolve(), sourcemaps()],
27 | };
28 |
29 | function onwarn(message) {
30 | const suppressed = ['UNRESOLVED_IMPORT', 'THIS_IS_UNDEFINED'];
31 |
32 | if (!suppressed.find(code => message.code === code)) {
33 | return console.warn(message.message);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/src/ApolloFragment.js:
--------------------------------------------------------------------------------
1 | import { ApolloQuery } from 'vue-apollo';
2 | import { getFragmentInfo, buildFragmentQuery } from 'apollo-fragment-utils';
3 |
4 | function isDataFilled(data) {
5 | return Object.keys(data).length > 0;
6 | }
7 |
8 | const CApolloFragment = {
9 | ...ApolloQuery,
10 | name: 'ApolloFragment',
11 | props: {
12 | fragment: {
13 | type: String,
14 | required: true,
15 | },
16 | id: {
17 | type: String,
18 | required: true,
19 | },
20 | tag: {
21 | type: String,
22 | default: 'div',
23 | },
24 | },
25 | data(props) {
26 | const { id, fragment } = this.$options.propsData;
27 | const { fragmentTypeName, fragmentName } = getFragmentInfo(fragment);
28 | const query = buildFragmentQuery({ fragment, fragmentName });
29 |
30 | return {
31 | ...ApolloQuery.data(),
32 | query,
33 | variables: {
34 | id,
35 | __typename: fragmentTypeName,
36 | },
37 | };
38 | },
39 | apollo: {
40 | $client() {
41 | return this.clientId;
42 | },
43 | query() {
44 | return {
45 | ...ApolloQuery.apollo.query(),
46 | query() {
47 | return this.$data.query;
48 | },
49 | variables() {
50 | return this.$data.variables;
51 | },
52 | skip: false,
53 | fetchPolicy: 'cache-only',
54 | result(result) {
55 | const { errors, loading, networkStatus } = result;
56 | let { error } = result;
57 | result = Object.assign({}, result);
58 |
59 | if (errors && errors.length) {
60 | error = new Error(`Apollo errors occured (${errors.length})`);
61 | error.graphQLErrors = errors;
62 | }
63 |
64 | let data = {};
65 |
66 | if (loading) {
67 | Object.assign(data, this.$_previousData, result.data);
68 | } else if (error) {
69 | Object.assign(
70 | data,
71 | this.$apollo.queries.query.observer.getLastResult() || {},
72 | result.data,
73 | );
74 | } else {
75 | data = result.data;
76 | this.$_previousData = result.data;
77 | }
78 |
79 | this.result = {
80 | data: isDataFilled(data) ? data.getFragment : undefined,
81 | loading,
82 | error,
83 | networkStatus,
84 | };
85 |
86 | this.times = ++this.$_times;
87 |
88 | this.$emit('result', this.result);
89 | },
90 | error(error) {
91 | this.result.loading = false;
92 | this.result.error = error;
93 | this.$emit('error', error);
94 | },
95 | };
96 | },
97 | },
98 | };
99 |
100 | export default CApolloFragment;
101 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/src/index.ts:
--------------------------------------------------------------------------------
1 | import CApolloFragment from './ApolloFragment';
2 |
3 | function install(Vue) {
4 | Vue.component('apollo-fragment', CApolloFragment);
5 | Vue.component('ApolloFragment', CApolloFragment);
6 | }
7 |
8 | CApolloFragment.install = install;
9 |
10 | // Components
11 | export default CApolloFragment;
12 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig",
3 | "compilerOptions": {
4 | "rootDir": "./src",
5 | "outDir": "lib",
6 | "allowJs": true
7 | },
8 | "include": ["./src/*.ts"],
9 | "exclude": ["./node_modules", "./dist", "./lib"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/apollo-fragment-vue/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "ban": false,
4 | "class-name": true,
5 | "eofline": true,
6 | "forin": true,
7 | "interface-name": [true, "never-prefix"],
8 | "jsdoc-format": true,
9 | "label-position": true,
10 | "member-access": true,
11 | "member-ordering": [
12 | true,
13 | {
14 | "order": [
15 | "static-field",
16 | "instance-field",
17 | "constructor",
18 | "public-instance-method",
19 | "protected-instance-method",
20 | "private-instance-method"
21 | ]
22 | }
23 | ],
24 | "no-any": false,
25 | "no-arg": true,
26 | "no-bitwise": true,
27 | "no-conditional-assignment": true,
28 | "no-consecutive-blank-lines": false,
29 | "no-console": [true, "log", "debug", "info", "time", "timeEnd", "trace"],
30 | "no-construct": true,
31 | "no-debugger": true,
32 | "no-duplicate-variable": true,
33 | "no-empty": true,
34 | "no-eval": true,
35 | "no-inferrable-types": false,
36 | "no-internal-module": true,
37 | "no-null-keyword": false,
38 | "no-require-imports": false,
39 | "no-shadowed-variable": true,
40 | "no-switch-case-fall-through": true,
41 | "no-trailing-whitespace": true,
42 | "no-unused-expression": true,
43 | "no-var-keyword": true,
44 | "no-var-requires": true,
45 | "object-literal-sort-keys": false,
46 | "radix": true,
47 | "switch-default": true,
48 | "triple-equals": [true, "allow-null-check"],
49 | "typedef": [
50 | false,
51 | "call-signature",
52 | "parameter",
53 | "arrow-parameter",
54 | "property-declaration",
55 | "variable-declaration",
56 | "member-variable-declaration"
57 | ],
58 | "variable-name": [
59 | true,
60 | "check-format",
61 | "allow-leading-underscore",
62 | "ban-keywords"
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/.npmignore:
--------------------------------------------------------------------------------
1 | dist/tests/
2 | src/
3 | tests/
4 | .travis.yml
5 | tsconfig.json
6 | tslint.json
7 | typings.d.ts
8 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apollo-link-state-fragment",
3 | "version": "0.1.8",
4 | "description": "A library to read fragments data in the apollo cache",
5 | "author": "Abhi Aiyer ",
6 | "license": "MIT",
7 | "main": "./lib/bundle.umd.js",
8 | "module": "./lib/index.js",
9 | "jsnext:main": "./lib/index.js",
10 | "typings": "./lib/index.d.ts",
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/abhiaiyer91/apollo-fragment.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/abhiaiyer91/apollo-fragment/issues"
17 | },
18 | "homepage": "https://github.com/abhiaiyer91/apollo-fragment#readme",
19 | "scripts": {
20 | "build:browser": "browserify ./lib/bundle.umd.js -o=./lib/bundle.js --i apollo-link --i apollo-utilities --i graphql-anywhere && npm run minify:browser",
21 | "build": "tsc -p .",
22 | "bundle": "rollup -c",
23 | "clean": "rimraf lib/* && rimraf coverage/*",
24 | "filesize": "npm run build && npm run build:browser && bundlesize",
25 | "prelint": "npm run lint-fix",
26 | "lint-fix": "prettier --trailing-comma all --single-quote --write \"src/**/*.{j,t}s*\"",
27 | "lint": "tslint --type-check -p tsconfig.json -c tslint.json src/*.ts",
28 | "lint-staged": "lint-staged",
29 | "minify:browser": "uglifyjs -c -m -o ./lib/bundle.min.js -- ./lib/bundle.js",
30 | "postbuild": "npm run bundle",
31 | "prebuild": "npm run clean",
32 | "prepublishOnly": "npm run clean && npm run build",
33 | "test": "jest",
34 | "coverage": "npm run lint && jest --coverage",
35 | "watch": "trap 'kill -9 %1' SIGINT; tsc -w -p . & rollup -w -c"
36 | },
37 | "bundlesize": [
38 | {
39 | "name": "apollo-link-state-fragment",
40 | "path": "./lib/bundle.min.js",
41 | "threshold": "1 Kb"
42 | }
43 | ],
44 | "peerDependencies": {
45 | "apollo-link-state": "0.4.1"
46 | },
47 | "devDependencies": {
48 | "@types/graphql": "0.11.5",
49 | "@types/jest": "22.1.x",
50 | "apollo-cache-inmemory": "^1.1.5",
51 | "apollo-client": "^2.2.0",
52 | "apollo-link": "^1.0.0",
53 | "apollo-link-state": "^0.4.1",
54 | "browserify": "14.5.0",
55 | "bundlesize": "0.15.3",
56 | "codecov": "3.0.0",
57 | "danger": "1.2.0",
58 | "graphql": "0.11.7",
59 | "graphql-tag": "2.5.0",
60 | "jest": "21.2.1",
61 | "lint-staged": "4.3.0",
62 | "pre-commit": "1.2.2",
63 | "prettier": "1.7.4",
64 | "rimraf": "2.6.1",
65 | "rollup": "0.56.x",
66 | "rollup-plugin-local-resolve": "1.0.x",
67 | "rollup-plugin-sourcemaps": "0.4.x",
68 | "ts-jest": "21.1.4",
69 | "tslint": "5.8.0",
70 | "typescript": "^4.1.2",
71 | "uglify-js": "3.1.5"
72 | },
73 | "jest": {
74 | "mapCoverage": true,
75 | "transform": {
76 | ".(ts|tsx)": "/node_modules/ts-jest/preprocessor.js"
77 | },
78 | "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
79 | "moduleFileExtensions": [
80 | "ts",
81 | "tsx",
82 | "js",
83 | "json"
84 | ]
85 | },
86 | "dependencies": {
87 | "apollo-utilities": "^1.0.12"
88 | },
89 | "lint-staged": {
90 | "*.ts*": [
91 | "prettier --trailing-comma all --single-quote --write",
92 | "git add"
93 | ],
94 | "*.js*": [
95 | "prettier --trailing-comma all --single-quote --write",
96 | "git add"
97 | ],
98 | "*.json*": [
99 | "prettier --write",
100 | "git add"
101 | ]
102 | },
103 | "pre-commit": "lint-staged"
104 | }
105 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/rollup.config.js:
--------------------------------------------------------------------------------
1 | import resolve from 'rollup-plugin-local-resolve';
2 | import sourcemaps from 'rollup-plugin-sourcemaps';
3 |
4 | const globals = {
5 | // Apollo
6 | 'apollo-client': 'apollo.core',
7 | 'apollo-cache': 'apolloCache.core',
8 | 'apollo-link': 'apolloLink.core',
9 | 'apollo-utilities': 'apollo.utilities',
10 |
11 | 'graphql-anywhere/lib/async': 'graphqlAnywhere.async',
12 | };
13 |
14 | export default {
15 | input: 'lib/index.js',
16 | output: {
17 | file: 'lib/bundle.umd.js',
18 | format: 'umd',
19 | name: 'apolloLinkStateFragment.state',
20 | exports: 'named',
21 | sourcemap: true,
22 | globals,
23 | },
24 | external: Object.keys(globals),
25 | onwarn,
26 | plugins: [resolve(), sourcemaps()],
27 | };
28 |
29 | function onwarn(message) {
30 | const suppressed = ['UNRESOLVED_IMPORT', 'THIS_IS_UNDEFINED'];
31 |
32 | if (!suppressed.find(code => message.code === code)) {
33 | return console.warn(message.message);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/src/__tests__/index.ts:
--------------------------------------------------------------------------------
1 | import gql from 'graphql-tag';
2 | import { ApolloLink, execute, Observable } from 'apollo-link';
3 | import { ApolloClient } from 'apollo-client';
4 | import { InMemoryCache } from 'apollo-cache-inmemory';
5 | import mockLink from '../mocks/mockLink';
6 | import { fragmentCacheRedirect, fragmentLinkState } from '../';
7 |
8 | describe('Basic Usage', () => {
9 | it('Will return null when fragment data is missing from cache', () => {
10 | const query = gql`
11 | {
12 | getFragment(id: 1, __typename: "Person") @client {
13 | id
14 | name
15 | }
16 | }
17 | `;
18 |
19 | const cache = new InMemoryCache({
20 | cacheRedirects: {
21 | Query: {
22 | ...fragmentCacheRedirect(cache),
23 | },
24 | },
25 | });
26 |
27 | const local = fragmentLinkState(cache);
28 |
29 | const client = new ApolloClient({
30 | cache,
31 | link: ApolloLink.from([local, mockLink]),
32 | });
33 |
34 | return client.query({ query }).then(({ data }) => {
35 | expect(data).toEqual(null);
36 | });
37 | });
38 |
39 | it('Will return fragment data once in cache', function() {
40 | const query = gql`
41 | {
42 | getFragment(id: 1, __typename: "Person") @client {
43 | id
44 | name
45 | }
46 | }
47 | `;
48 |
49 | const cache = new InMemoryCache({
50 | cacheRedirects: {
51 | Query: {
52 | ...fragmentCacheRedirect(),
53 | },
54 | },
55 | });
56 |
57 | const local = fragmentLinkState(cache);
58 |
59 | const client = new ApolloClient({
60 | cache,
61 | link: ApolloLink.from([local, mockLink]),
62 | });
63 |
64 | return client
65 | .query({
66 | query: gql`
67 | query peeps {
68 | people {
69 | id
70 | name
71 | }
72 | }
73 | `,
74 | })
75 | .then(result => {
76 | return client.query({ query }).then(({ data }) => {
77 | expect(data.getFragment.id).toEqual('1');
78 | });
79 | });
80 | });
81 | });
82 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/src/index.ts:
--------------------------------------------------------------------------------
1 | import { toIdValue, IdValue } from 'apollo-utilities';
2 | import { ApolloLink } from 'apollo-link';
3 | import { withClientState } from 'apollo-link-state';
4 | import { ApolloCache } from 'apollo-cache';
5 | import { defaultDataIdFromObject } from 'apollo-cache-inmemory';
6 |
7 | type GetFragmentType = {
8 | __typename: string;
9 | id: string;
10 | };
11 |
12 | export function fragmentCacheRedirect(
13 | dataIdFromObject = defaultDataIdFromObject,
14 | ) {
15 | return {
16 | getFragment: (_: any, { id, __typename }: GetFragmentType): IdValue => {
17 | return toIdValue(dataIdFromObject({ __typename, id }));
18 | },
19 | };
20 | }
21 |
22 | export function fragmentLinkState(apolloCache: ApolloCache): ApolloLink {
23 | return withClientState({
24 | cache: apolloCache,
25 | resolvers: {
26 | Query: {
27 | getFragment: (
28 | _: any,
29 | { __typename, id }: GetFragmentType,
30 | { cache }: { cache: any },
31 | ) => {
32 | const fragmentId = cache.config.dataIdFromObject({ __typename, id });
33 | return cache.data.data[fragmentId];
34 | },
35 | },
36 | },
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/src/mocks/mockLink.ts:
--------------------------------------------------------------------------------
1 | import { graphql, print } from 'graphql';
2 | import {
3 | Operation,
4 | GraphQLRequest,
5 | ApolloLink,
6 | FetchResult,
7 | Observable,
8 | // Observer,
9 | } from 'apollo-link';
10 | import { schema } from './mockSchema';
11 |
12 | export default new ApolloLink(operation => {
13 | return new Observable(observer => {
14 | const { query, operationName, variables } = operation;
15 | delay(300)
16 | .then(() =>
17 | graphql(schema, print(query), null, null, variables, operationName),
18 | )
19 | .then(result => {
20 | observer.next(result);
21 | observer.complete();
22 | })
23 | .catch(observer.error.bind(observer));
24 | });
25 | });
26 |
27 | function delay(ms: number) {
28 | return new Promise(resolve => {
29 | setTimeout(() => {
30 | resolve();
31 | }, ms);
32 | });
33 | }
34 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/src/mocks/mockSchema.ts:
--------------------------------------------------------------------------------
1 | import {
2 | GraphQLSchema,
3 | GraphQLObjectType,
4 | GraphQLID,
5 | GraphQLString,
6 | GraphQLList,
7 | } from 'graphql';
8 |
9 | const PersonType = new GraphQLObjectType({
10 | name: 'Person',
11 | fields: {
12 | id: { type: GraphQLID },
13 | name: { type: GraphQLString },
14 | },
15 | });
16 |
17 | const peopleData = [
18 | { id: 1, name: 'John Smith' },
19 | { id: 2, name: 'Sara Smith' },
20 | { id: 3, name: 'Budd Deey' },
21 | ];
22 |
23 | const QueryType = new GraphQLObjectType({
24 | name: 'Query',
25 | fields: {
26 | people: {
27 | type: new GraphQLList(PersonType),
28 | resolve: () => peopleData,
29 | },
30 | },
31 | });
32 |
33 | export const schema = new GraphQLSchema({ query: QueryType });
34 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig",
3 | "compilerOptions": {
4 | "declaration": true,
5 | "rootDir": "./src",
6 | "outDir": "lib"
7 | },
8 | "include": ["./src/index.ts"],
9 | "exclude": ["src/**/__tests__/*.ts", "./src/mocks"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/apollo-link-state-fragment/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "ban": false,
4 | "class-name": true,
5 | "eofline": true,
6 | "forin": true,
7 | "interface-name": [true, "never-prefix"],
8 | "jsdoc-format": true,
9 | "label-position": true,
10 | "member-access": true,
11 | "member-ordering": [
12 | true,
13 | {
14 | "order": [
15 | "static-field",
16 | "instance-field",
17 | "constructor",
18 | "public-instance-method",
19 | "protected-instance-method",
20 | "private-instance-method"
21 | ]
22 | }
23 | ],
24 | "no-any": false,
25 | "no-arg": true,
26 | "no-bitwise": true,
27 | "no-conditional-assignment": true,
28 | "no-consecutive-blank-lines": false,
29 | "no-console": [true, "log", "debug", "info", "time", "timeEnd", "trace"],
30 | "no-construct": true,
31 | "no-debugger": true,
32 | "no-duplicate-variable": true,
33 | "no-empty": true,
34 | "no-eval": true,
35 | "no-inferrable-types": false,
36 | "no-internal-module": true,
37 | "no-null-keyword": false,
38 | "no-require-imports": false,
39 | "no-shadowed-variable": true,
40 | "no-switch-case-fall-through": true,
41 | "no-trailing-whitespace": true,
42 | "no-unused-expression": true,
43 | "no-var-keyword": true,
44 | "no-var-requires": true,
45 | "object-literal-sort-keys": false,
46 | "radix": true,
47 | "switch-default": true,
48 | "triple-equals": [true, "allow-null-check"],
49 | "typedef": [
50 | false,
51 | "call-signature",
52 | "parameter",
53 | "arrow-parameter",
54 | "property-declaration",
55 | "variable-declaration",
56 | "member-variable-declaration"
57 | ],
58 | "variable-name": [
59 | true,
60 | "check-format",
61 | "allow-leading-underscore",
62 | "ban-keywords"
63 | ]
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["es6", "dom"],
5 | "module": "es2015",
6 | "moduleResolution": "node",
7 | "removeComments": true,
8 | "sourceMap": true,
9 | "declaration": false,
10 | "noImplicitAny": false,
11 | "noUnusedParameters": false,
12 | "noUnusedLocals": true,
13 | "skipLibCheck": true
14 | }
15 | }
16 |
--------------------------------------------------------------------------------