From 9cb60375c3e5e79e6fa7090a7cf32d90e6333f06 Mon Sep 17 00:00:00 2001 From: Jonas Helfer Date: Fri, 2 Dec 2016 21:53:09 +0100 Subject: [PATCH 1/3] deprecate fragments everywhere --- src/ApolloClient.ts | 62 +++++++++++++++++++++++++++++++++++++++++++-- src/fragments.ts | 23 ++++++++++++++++- test/client.ts | 8 ++++-- test/tests.ts | 2 +- 4 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/ApolloClient.ts b/src/ApolloClient.ts index 6ab9008ad07..025cfaafc69 100644 --- a/src/ApolloClient.ts +++ b/src/ApolloClient.ts @@ -82,6 +82,12 @@ function defaultReduxRootSelector(state: any) { return state[DEFAULT_REDUX_ROOT_KEY]; } +// deprecation warning flags +let haveWarnedQuery = false; +let haveWarnedWatchQuery = false; +let haveWarnedMutation = false; +let haveWarnedSubscription = false; + /** * This is the primary Apollo Client class. It is used to send GraphQL documents (i.e. queries * and mutations) to a GraphQL spec-compliant server over a {@link NetworkInterface} instance, @@ -249,10 +255,23 @@ export default class ApolloClient { }) as DeprecatedWatchQueryOptions; } + if (options.fragments && !haveWarnedWatchQuery && process.env.NODE_ENV !== 'production') { + console.warn( + '"fragments" option is deprecated and will be removed in the upcoming versions, ' + + 'please refer to the documentation for how to define fragments: ' + + 'http://dev.apollodata.com/react/fragments.html.' + ); + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'test') { + // When running tests, we want to print the warning every time + haveWarnedWatchQuery = true; + } + } + // Register each of the fragments present in the query document. The point // is to prevent fragment name collisions with fragments that are in the query // document itself. - createFragment(options.query); + createFragment(options.query, undefined, true); // We add the fragments to the document to pass only the document around internally. const fullDocument = addFragmentsToDocument(options.query, options.fragments); @@ -286,10 +305,23 @@ export default class ApolloClient { }) as DeprecatedWatchQueryOptions; } + if (options.fragments && !haveWarnedQuery && process.env.NODE_ENV !== 'production') { + console.warn( + '"fragments" option is deprecated and will be removed in the upcoming versions, ' + + 'please refer to the documentation for how to define fragments: ' + + 'http://dev.apollodata.com/react/fragments.html.' + ); + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'test') { + // When running tests, we want to print the warning every time + haveWarnedQuery = true; + } + } + // Register each of the fragments present in the query document. The point // is to prevent fragment name collisions with fragments that are in the query // document itself. - createFragment(options.query); + createFragment(options.query, undefined, true); // We add the fragments to the document to pass only the document around internally. const fullDocument = addFragmentsToDocument(options.query, options.fragments); @@ -336,6 +368,19 @@ export default class ApolloClient { public mutate(options: MutationOptions): Promise { this.initStore(); + if (options.fragments && !haveWarnedMutation && process.env.NODE_ENV !== 'production') { + console.warn( + '"fragments" option is deprecated and will be removed in the upcoming versions, ' + + 'please refer to the documentation for how to define fragments: ' + + 'http://dev.apollodata.com/react/fragments.html.' + ); + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'test') { + // When running tests, we want to print the warning every time + haveWarnedMutation = true; + } + } + // We add the fragments to the document to pass only the document around internally. const fullDocument = addFragmentsToDocument(options.mutation, options.fragments); @@ -350,6 +395,19 @@ export default class ApolloClient { public subscribe(options: DeprecatedSubscriptionOptions): Observable { this.initStore(); + if (options.fragments && !haveWarnedSubscription && process.env.NODE_ENV !== 'production') { + console.warn( + '"fragments" option is deprecated and will be removed in the upcoming versions, ' + + 'please refer to the documentation for how to define fragments: ' + + 'http://dev.apollodata.com/react/fragments.html.' + ); + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'test') { + // When running tests, we want to print the warning every time + haveWarnedSubscription = true; + } + } + // We add the fragments to the document to pass only the document around internally. const fullDocument = addFragmentsToDocument(options.query, options.fragments); diff --git a/src/fragments.ts b/src/fragments.ts index c9d72d0d13f..b05aeb1b32d 100644 --- a/src/fragments.ts +++ b/src/fragments.ts @@ -24,10 +24,31 @@ let printFragmentWarnings = true; // that the fragment in the document depends on. The fragment definition array from the document // is concatenated with the fragment definition array passed as the second argument and this // concatenated array is returned. +let haveWarned = false; + export function createFragment( doc: Document, - fragments: (FragmentDefinition[] | FragmentDefinition[][]) = [] + fragments: (FragmentDefinition[] | FragmentDefinition[][]) = [], + internalUse = false, ): FragmentDefinition[] { + + if (!internalUse) { + if (! haveWarned) { + if (process.env.NODE_ENV !== 'production') { + console.warn( + '"createFragment" is deprecated and will be removed in the upcoming versions, ' + + 'please refer to the documentation for how to define fragments: ' + + 'http://dev.apollodata.com/react/fragments.html.' + ); + } + /* istanbul ignore if */ + if (process.env.NODE_ENV !== 'test') { + // When running tests, we want to print the warning every time + haveWarned = true; + } + } + } + fragments = flatten(fragments) as FragmentDefinition[] ; const fragmentDefinitions = getFragmentDefinitions(doc); fragmentDefinitions.forEach((fragmentDefinition: FragmentDefinition) => { diff --git a/test/client.ts b/test/client.ts index e76cf8a111e..1c72c8e95ac 100644 --- a/test/client.ts +++ b/test/client.ts @@ -1358,7 +1358,9 @@ it('should not let errors in observer.next reach the store', (done) => { // hacky solution that allows us to test whether the warning is printed const oldWarn = console.warn; console.warn = (str: string) => { - assert.include(str, 'Warning: fragment with name'); + if (!str.match(/deprecated/)) { + assert.include(str, 'Warning: fragment with name'); + } }; createFragment(fragmentDoc); @@ -1622,7 +1624,9 @@ it('should not let errors in observer.next reach the store', (done) => { it('should not print a warning if we call disableFragmentWarnings', (done) => { const oldWarn = console.warn; console.warn = (str: string) => { - done(new Error('Returned a warning despite calling disableFragmentWarnings')); + if (!str.match(/deprecated/)) { + done(new Error('Returned a warning despite calling disableFragmentWarnings')); + } }; disableFragmentWarnings(); createFragment(gql` diff --git a/test/tests.ts b/test/tests.ts index aa4485df78e..457be0d6639 100644 --- a/test/tests.ts +++ b/test/tests.ts @@ -18,7 +18,7 @@ require('source-map-support').install(); console.warn = console.error = (...messages: string[]) => { console.log(`==> Error in test: Tried to log warning or error with message: `, ...messages); - if (!process.env.CI) { + if (!process.env.CI && !messages[0].match(/deprecated/)) { process.exit(1); } }; From 74ff109c9dba2fcdeda70cebb3b21ccd2fc71fcf Mon Sep 17 00:00:00 2001 From: Jonas Helfer Date: Fri, 2 Dec 2016 21:56:23 +0100 Subject: [PATCH 2/3] update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 627e74ab99e..5a7b640e281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Expect active development and potentially significant breaking changes in the `0.x` track. We'll try to be diligent about releasing a `1.0` version in a timely fashion (ideally within 3 to 6 months), to signal the start of a more stable API. ### vNEXT +- Deprecate usage of fragment option and createFragment function [PR #984](https://github.com/apollostack/apollo-client/pull/984) ### 0.5.9 - Prevent Redux from crashing when an uncaught ApolloError is raised in an Apollo reducer. [PR #874](https://github.com/apollostack/apollo-client/pull/874) From 78ccf53595d69bc839b7ecbc940ccbe64ea27c40 Mon Sep 17 00:00:00 2001 From: Jonas Helfer Date: Sat, 3 Dec 2016 13:24:15 +0100 Subject: [PATCH 3/3] change deprecation message --- src/fragments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fragments.ts b/src/fragments.ts index b05aeb1b32d..02b7e6410b2 100644 --- a/src/fragments.ts +++ b/src/fragments.ts @@ -36,7 +36,7 @@ export function createFragment( if (! haveWarned) { if (process.env.NODE_ENV !== 'production') { console.warn( - '"createFragment" is deprecated and will be removed in the upcoming versions, ' + + '"createFragment" is deprecated and will be removed in version 0.6, ' + 'please refer to the documentation for how to define fragments: ' + 'http://dev.apollodata.com/react/fragments.html.' );