Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
fix typescript usage (#862)
Browse files Browse the repository at this point in the history
* fix typescript usage

* updated changelog

* add issue information to changelog

* Version bump

* update dangerfile
  • Loading branch information
James Baxley committed Jul 18, 2017
1 parent 4b048f5 commit 8ee56e9
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 198 deletions.
7 changes: 5 additions & 2 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Change log

### vNext
- Fix: Fix issue around hoisting non react statics for RN
- Fix: Fix issue where options was called even though skip was present

### 1.4.4
- Fix: Fix issue around hoisting non react statics for RN [#859](https://github.com/apollographql/react-apollo/pull/859)
- Fix: Fix issue where options was called even though skip was present [#859](https://github.com/apollographql/react-apollo/pull/859)
- Improvement: Allow for better typescript usage with improved types [#862](https://github.com/apollographql/react-apollo/pull/862)

### 1.4.3
- Feature: You can now supply a client in options object passed to the `graphql` high oder component. [PR #729](https://github.com/apollographql/react-apollo/pull/729)
Expand Down
13 changes: 6 additions & 7 deletions dangerfile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { danger, fail, warn, message } from 'danger';
// Removed import
import { includes } from 'lodash';
import * as fs from 'fs';

Expand All @@ -17,9 +17,11 @@ const filesOnly = (file: string) =>

// Custom subsets of known files
const modifiedAppFiles = modified
.filter(p => includes(p, 'src/') || includes(p, 'test/'))
.filter(p => includes(p, 'src/'))
.filter(p => filesOnly(p) && typescriptOnly(p));

const modifiedTestFiles = modified.filter(p => includes(p, 'test/'));

// Takes a list of file paths, and converts it into clickable links
const linkableFiles = paths => {
const repoURL = danger.github.pr.head.repo.html_url;
Expand Down Expand Up @@ -70,10 +72,7 @@ if (pr.body.length === 0) {

const hasAppChanges = modifiedAppFiles.length > 0;

const testChanges = modifiedAppFiles.filter(filepath =>
filepath.includes('test'),
);
const hasTestChanges = testChanges.length > 0;
const hasTestChanges = modifiedTestFiles.length > 0;

// Warn when there is a big PR
const bigPRThreshold = 500;
Expand All @@ -89,7 +88,7 @@ if (hasAppChanges && !hasTestChanges) {
}

// Be careful of leaving testing shortcuts in the codebase
const onlyTestFiles = testChanges.filter(x => {
const onlyTestFiles = modifiedTestFiles.filter(x => {
const content = fs.readFileSync(x).toString();
return (
content.includes('it.only') ||
Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-apollo",
"version": "1.4.3",
"version": "1.4.4",
"description": "React data container for Apollo Client",
"main": "lib/react-apollo.umd.js",
"module": "./lib/index.js",
Expand All @@ -15,7 +15,7 @@
"test-watch": "jest --watch",
"posttest": "npm run lint",
"filesize": "npm run compile:browser && bundlesize",
"flow-check": "flow check",
"type-check": "tsc ./test/typescript.ts --noEmit --jsx react --noEmitOnError --lib es6,dom --experimentalDecorators && flow check",
"compile": "tsc",
"bundle": "rollup -c && rollup -c rollup.browser.config.js && rollup -c rollup.test-utils.config.js && cp ./index.js.flow ./lib",
"compile:browser": "rm -rf ./dist && mkdir ./dist && browserify ./lib/react-apollo.browser.umd.js --i graphql-tag --i react --i apollo-client -o=./dist/index.js && npm run minify:browser && npm run compress:browser",
Expand Down Expand Up @@ -52,7 +52,7 @@
"npm",
"react"
],
"author": "James Baxley <james.baxley@newspring.cc>",
"author": "James Baxley <james@meteor.com>",
"babel": {
"presets": [
"react-native"
Expand All @@ -72,7 +72,8 @@
],
"modulePathIgnorePatterns": [
"<rootDir>/examples",
"<rootDir>/test/flow.js"
"<rootDir>/test/flow.js",
"<rootDir>/test/typescript.ts"
],
"testRegex": "(/test/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"collectCoverage": true
Expand Down
9 changes: 5 additions & 4 deletions src/browser.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
export { default as ApolloProvider } from './ApolloProvider';
export {
default as graphql,
export { default as graphql } from './graphql';
import {
MutationOpts,
QueryOpts,
QueryProps,
NamedProps,
MutationFunc,
OptionProps,
DefaultChildProps,
ChildProps,
OperationOption,
} from './graphql';
} from './types';
export { withApollo } from './withApollo';

// expose easy way to join queries from redux
Expand Down
194 changes: 14 additions & 180 deletions src/graphql.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
Component,
createElement,
ComponentClass,
StatelessComponent,
} from 'react';
import { Component, createElement } from 'react';
import * as PropTypes from 'prop-types';

const pick = require('lodash.pick');
Expand All @@ -16,98 +11,26 @@ const hoistNonReactStatics = require('hoist-non-react-statics');

import ApolloClient, {
ObservableQuery,
MutationQueryReducersMap,
Subscription,
ApolloStore,
ApolloQueryResult,
ApolloError,
FetchPolicy,
FetchMoreOptions,
UpdateQueryOptions,
FetchMoreQueryOptions,
SubscribeToMoreOptions,
} from 'apollo-client';
import { PureQueryOptions } from 'apollo-client/core/types';
import { MutationUpdaterFn } from 'apollo-client/core/watchQueryOptions';

import { ExecutionResult, DocumentNode } from 'graphql';

import { parser, DocumentType } from './parser';
import { ObservableQueryRecycler } from './queryRecycler';

export interface MutationOpts {
variables?: Object;
optimisticResponse?: Object;
updateQueries?: MutationQueryReducersMap;
refetchQueries?: string[] | PureQueryOptions[];
update?: MutationUpdaterFn;
client?: ApolloClient;
}

export interface QueryOpts {
ssr?: boolean;
variables?: { [key: string]: any };
fetchPolicy?: FetchPolicy;
pollInterval?: number;
client?: ApolloClient;
// deprecated
skip?: boolean;
}

export interface QueryProps {
error?: ApolloError;
networkStatus: number;
loading: boolean;
variables: {
[variable: string]: any;
};
fetchMore: (
fetchMoreOptions: FetchMoreQueryOptions & FetchMoreOptions,
) => Promise<ApolloQueryResult<any>>;
refetch: (variables?: any) => Promise<ApolloQueryResult<any>>;
startPolling: (pollInterval: number) => void;
stopPolling: () => void;
subscribeToMore: (options: SubscribeToMoreOptions) => () => void;
updateQuery: (
mapFn: (previousQueryResult: any, options: UpdateQueryOptions) => any,
) => void;
}

export type MutationFunc<TResult> = (
opts: MutationOpts,
) => Promise<ApolloQueryResult<TResult>>;

export interface OptionProps<TProps, TResult> {
ownProps: TProps;
data?: QueryProps & TResult;
mutate?: MutationFunc<TResult>;
}

export type DefaultChildProps<P, R> = P & {
data?: QueryProps & R;
mutate?: MutationFunc<R>;
};

export interface OperationOption<TProps, TResult> {
options?:
| QueryOpts
| MutationOpts
| ((props: TProps) => QueryOpts | MutationOpts);
props?: (props: OptionProps<TProps, TResult>) => any;
skip?: boolean | ((props: any) => boolean);
name?: string;
withRef?: boolean;
shouldResubscribe?: (props: TProps, nextProps: TProps) => boolean;
alias?: string;
}

export type CompositeComponent<P> = ComponentClass<P> | StatelessComponent<P>;
import { DocumentNode } from 'graphql';

export interface ComponentDecorator<TOwnProps, TMergedProps> {
(component: CompositeComponent<TMergedProps>): ComponentClass<TOwnProps>;
}
export interface InferableComponentDecorator<TOwnProps> {
<T extends CompositeComponent<TOwnProps>>(component: T): T;
}
import {
MutationOpts,
ChildProps,
OperationOption,
ComponentDecorator,
QueryOpts,
QueryProps,
MutationFunc,
OptionProps,
} from './types';

const defaultMapPropsToOptions = props => ({});
const defaultMapResultToProps = props => props;
Expand Down Expand Up @@ -145,7 +68,7 @@ let nextVersion = 0;
export default function graphql<
TResult = {},
TProps = {},
TChildProps = DefaultChildProps<TProps, TResult>
TChildProps = ChildProps<TProps, TResult>
>(
document: DocumentNode,
operationOptions: OperationOption<TProps, TResult> = {},
Expand Down Expand Up @@ -671,92 +594,3 @@ export default function graphql<

return wrapWithApolloComponent;
}

/**
* An observable query recycler stores some observable queries that are no
* longer in use, but that we may someday use again.
*
* Recycling observable queries avoids a few unexpected functionalities that
* may be hit when using the `react-apollo` API. Namely not updating queries
* when a component unmounts, and calling reducers/`updateQueries` more times
* then is necessary for old observable queries.
*
* We assume that the GraphQL document for every `ObservableQuery` is the same.
*
* For more context on why this was added and links to the issues recycling
* `ObservableQuery`s fixes see issue [#462][1].
*
* [1]: https://github.com/apollographql/react-apollo/pull/462
*/
class ObservableQueryRecycler {
/**
* The internal store for our observable queries and temporary subscriptions.
*/
private observableQueries: Array<{
observableQuery: ObservableQuery<any>;
subscription: Subscription;
}> = [];

/**
* Recycles an observable query that the recycler is finished with. It is
* stored in this class so that it may be used later on.
*
* A subscription is made to the observable query so that it continues to
* live even though the updates are noops.
*
* By recycling an observable query we keep the results fresh so that when it
* gets reused all of the mutations that have happened since recycle and
* reuse have been applied.
*/
public recycle(observableQuery: ObservableQuery<any>): void {
// Stop the query from polling when we recycle. Polling may resume when we
// reuse it and call `setOptions`.
observableQuery.setOptions({
fetchPolicy: 'standby',
pollInterval: 0,
fetchResults: false, // ensure we don't create another observer in AC
});

this.observableQueries.push({
observableQuery,
subscription: observableQuery.subscribe({}),
});
}

/**
* Reuses an observable query that was recycled earlier on in this class’s
* lifecycle. This observable was kept fresh by our recycler with a
* subscription that will be unsubscribed from before returning the
* observable query.
*
* All mutations that occured between the time of recycling and the time of
* reusing have been applied.
*/
public reuse(options: QueryOpts): ObservableQuery<any> {
if (this.observableQueries.length <= 0) {
return null;
}
const { observableQuery, subscription } = this.observableQueries.pop();
subscription.unsubscribe();

// strip off react-apollo specific options
const { ssr, skip, client, ...modifiableOpts } = options;

// When we reuse an `ObservableQuery` then the document and component
// GraphQL display name should be the same. Only the options may be
// different.
//
// Therefore we need to set the new options.
//
// If this observable query used to poll then polling will be restarted.
observableQuery.setOptions({
...modifiableOpts,
// Explicitly set options changed when recycling to make sure they
// are set to `undefined` if not provided in options.
pollInterval: options.pollInterval,
fetchPolicy: options.fetchPolicy,
});

return observableQuery;
}
}

0 comments on commit 8ee56e9

Please sign in to comment.