diff --git a/CHANGELOG.md b/CHANGELOG.md index 30d9faf85d8..0869745be6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,9 @@ - The `gql` template tag should now be imported from the `@apollo/client` package, rather than the `graphql-tag` package. Although the `graphql-tag` package still works for now, future versions of `@apollo/client` may change the implementation details of `gql` without a major version bump.
[@hwillson](https://github.com/hwillson) in [#5451](https://github.com/apollographql/apollo-client/pull/5451) +- `@apollo/client/core` can be used to import the Apollo Client core, which includes everything the main `@apollo/client` package does, except for all React related functionality.
+ [@kamilkisiela](https://github.com/kamilkisiela) in [#5541](https://github.com/apollographql/apollo-client/pull/5541) + ### Breaking Changes - Removed `graphql-anywhere` since it's no longer used by Apollo Client.
@@ -65,6 +68,8 @@ - The `ObservableQuery#getCurrentResult` method no longer falls back to reading from the cache, so calling it immediately after `client.watchQuery` will consistently return a `loading: true` result. When the `fetchPolicy` permits cached results, those results will be delivered via the `next` method of the `ObservableQuery`, and can be obtained by `getCurrentResult` after they have been delivered. This change prevents race conditions where the initial behavior of one query could depend on the timing of cache writes associated with other queries.
[@benjamn](https://github.com/benjamn) in [#5565](https://github.com/apollographql/apollo-client/pull/5565) +- The `QueryOptions`, `MutationOptions`, and `SubscriptionOptions` React Apollo interfaces have been renamed to `QueryDataOptions`, `MutationDataOptions`, and `SubscriptionDataOptions` (to avoid conflicting with similarly named and exported Apollo Client interfaces). + ## Apollo Client (2.6.4) ### Apollo Client (2.6.4) diff --git a/config/prepareDist.js b/config/prepareDist.js index 880b870e722..86e5f8a9c07 100644 --- a/config/prepareDist.js +++ b/config/prepareDist.js @@ -1,16 +1,23 @@ // The Apollo Client source that is published to npm is located in the -// "dist" directory. This utility script is called just before deploying -// Apollo Client, to make sure the "dist" directory is prepared for publishing. +// "dist" directory. This utility script is called when building Apollo Client, +// to make sure the "dist" directory is prepared for publishing. // // This script will: // // - Copy the current root package.json into "dist" after adjusting it for // publishing. // - Copy the supporting files from the root into "dist" (e.g. `README.MD`, -// `LICENSE`, etc.) +// `LICENSE`, etc.). +// - Create a new `package.json` for each sub-set bundle we support, and +// store it in the appropriate dist sub-directory. -const packageJson = require('../package.json'); const fs = require('fs'); +const recast = require('recast'); + + +/* @apollo/client */ + +const packageJson = require('../package.json'); // The root package.json is marked as private to prevent publishing // from happening in the root of the project. This sets the package back to @@ -25,13 +32,14 @@ delete packageJson.bundlesize; // on-going package development (e.g. running tests, supporting npm link, etc.). // When publishing from "dist" however, we need to update the package.json // to point to the files within the same directory. -const distPackageJson = JSON.stringify( - packageJson, - (_key, value) => ( - typeof value === 'string' ? value.replace(/\.\/dist\//, '') : value - ), - 2 -); +const distPackageJson = JSON.stringify(packageJson, (_key, value) => { + if (typeof value === 'string' && value.startsWith('./dist/')) { + const parts = value.split('/'); + parts.splice(1, 1); // remove dist + return parts.join('/'); + } + return value; +}, 2) + "\n"; // Save the modified package.json to "dist" fs.writeFileSync(`${__dirname}/../dist/package.json`, distPackageJson); @@ -41,3 +49,46 @@ const srcDir = `${__dirname}/..`; const destDir = `${srcDir}/dist`; fs.copyFileSync(`${srcDir}/README.md`, `${destDir}/README.md`); fs.copyFileSync(`${srcDir}/LICENSE`, `${destDir}/LICENSE`); + + +/* @apollo/client/core */ + +function buildPackageJson(bundleName) { + return JSON.stringify({ + name: `@apollo/client/${bundleName}`, + main: `${bundleName}.cjs.js`, + module: 'index.js', + types: 'index.d.ts', + }, null, 2) + "\n"; +} + +// Create a `core` bundle package.json, storing it in the dist core +// directory. This helps provide a way for Apollo Client to be used without +// React, via `@apollo/client/core`. +fs.writeFileSync( + `${__dirname}/../dist/core/package.json`, + buildPackageJson('core') +); + +// Build a new `core.cjs.js` entry point file, that includes everything +// except the exports listed in `src/react/index.ts`. Copy this file into +// the `dist/core` directory, to allow Apollo Client core only imports +// using `@apollo/client/core`. + +const reactIndexSrc = fs.readFileSync(`${__dirname}/../dist/react/index.js`); +const reactExports = []; +recast.visit(recast.parse(reactIndexSrc), { + visitExportSpecifier(path) { + reactExports.push(path.value.exported.name); + return false; + }, +}); + +fs.writeFileSync(`${__dirname}/../dist/core/core.cjs.js`, [ + "const allExports = require('../apollo-client.cjs');", + `const reactExportNames = new Set(${JSON.stringify(reactExports)});`, + "Object.keys(allExports).forEach(name => {", + " if (!reactExportNames.has(name)) exports[name] = allExports[name];", + "});", + "", +].join('\n')); diff --git a/config/rollup.config.js b/config/rollup.config.js index b1275cdf73f..db4419dc9b7 100644 --- a/config/rollup.config.js +++ b/config/rollup.config.js @@ -9,7 +9,7 @@ import packageJson from '../package.json'; const distDir = './dist'; const globals = { - 'tslib': 'tslib', + tslib: 'tslib', 'ts-invariant': 'invariant', 'symbol-observable': '$$observable', 'graphql/language/printer': 'print', @@ -21,7 +21,7 @@ const globals = { '@wry/equality': 'wryEquality', graphql: 'graphql', react: 'React', - 'zen-observable': 'Observable' + 'zen-observable': 'Observable', }; const hasOwn = Object.prototype.hasOwnProperty; @@ -30,12 +30,12 @@ function external(id) { return hasOwn.call(globals, id); } -function prepareESM() { +function prepareESM(input, outputDir) { return { - input: packageJson.module, + input, external, output: { - dir: distDir, + dir: outputDir, format: 'esm', sourcemap: true, }, @@ -58,39 +58,39 @@ function prepareESM() { }), cjs({ namedExports: { - 'graphql-tag': ['gql'] - } + 'graphql-tag': ['gql'], + }, }), - ] + ], }; } -function prepareCJS() { +function prepareCJS(input, output) { return { - input: packageJson.module, + input, external, output: { - file: packageJson.main, + file: output, format: 'cjs', sourcemap: true, - exports: 'named' + exports: 'named', }, plugins: [ nodeResolve(), cjs({ namedExports: { - 'graphql-tag': ['gql'] - } + 'graphql-tag': ['gql'], + }, }), - ] - } + ], + }; } -function prepareCJSMinified() { +function prepareCJSMinified(input) { return { - input: packageJson.main, + input, output: { - file: packageJson.main.replace('.js', '.min.js'), + file: input.replace('.js', '.min.js'), format: 'cjs', }, plugins: [ @@ -141,10 +141,10 @@ function prepareTesting() { function rollup() { return [ - prepareESM(), - prepareCJS(), - prepareCJSMinified(), - prepareTesting() + prepareESM(packageJson.module, distDir), + prepareCJS(packageJson.module, packageJson.main), + prepareCJSMinified(packageJson.main), + prepareTesting(), ]; } diff --git a/package-lock.json b/package-lock.json index a37ae957609..5476c365130 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6992,9 +6992,9 @@ } }, "recast": { - "version": "0.18.2", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.18.2.tgz", - "integrity": "sha512-MbuHc1lzIDIn7bpxaqIAGwwtyaokkzPqINf1Vm/LA0BSyVrTgXNVTTT7RzWC9kP+vqrUoYVpd6wHhI8x75ej8w==", + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.18.5.tgz", + "integrity": "sha512-sD1WJrpLQAkXGyQZyGzTM75WJvyAd98II5CHdK3IYbt/cZlU0UzCRVU11nUFNXX9fBVEt4E9ajkMjBlUlG+Oog==", "dev": true, "requires": { "ast-types": "0.13.2", diff --git a/package.json b/package.json index 50e3ebb6b19..b4f238d46c6 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "scripts": { "prebuild": "npm run clean", "build": "npx tsc", - "postbuild": "npm run bundle", + "postbuild": "npm run bundle && npm run prepdist", "watch": "npx tsc-watch --onSuccess \"npm run postbuild\"", "clean": "npx rimraf -r dist coverage lib", "test": "jest --config ./config/jest.config.js", @@ -41,7 +41,7 @@ "coverage:upload": "npx codecov", "bundlesize": "npm run build && bundlesize", "prepdist": "node ./config/prepareDist.js", - "predeploy": "npm run build && npm run prepdist", + "predeploy": "npm run build", "deploy": "cd dist && npm publish --tag beta" }, "bundlesize": [ @@ -89,6 +89,7 @@ "prop-types": "15.7.2", "react": "^16.11.0", "react-dom": "^16.11.0", + "recast": "^0.18.5", "rimraf": "^3.0.0", "rollup": "1.21.2", "rollup-plugin-commonjs": "^10.1.0", diff --git a/src/core/index.ts b/src/core/index.ts new file mode 100644 index 00000000000..c84426336e2 --- /dev/null +++ b/src/core/index.ts @@ -0,0 +1,85 @@ +/* Core */ + +export { + ApolloClient, + ApolloClientOptions, + DefaultOptions +} from '../ApolloClient'; +export { + ObservableQuery, + FetchMoreOptions, + UpdateQueryOptions, + ApolloCurrentQueryResult, +} from '../core/ObservableQuery'; +export { + QueryBaseOptions, + QueryOptions, + WatchQueryOptions, + MutationOptions, + SubscriptionOptions, + FetchPolicy, + WatchQueryFetchPolicy, + ErrorPolicy, + FetchMoreQueryOptions, + SubscribeToMoreOptions, + MutationUpdaterFn, +} from '../core/watchQueryOptions'; +export { NetworkStatus } from '../core/networkStatus'; +export * from '../core/types'; +export { + Resolver, + FragmentMatcher as LocalStateFragmentMatcher, +} from '../core/LocalState'; +export { isApolloError, ApolloError } from '../errors/ApolloError'; + +/* Cache */ + +export { Transaction, ApolloCache } from '../cache/core/cache'; +export { Cache } from '../cache/core/types/Cache'; +export { DataProxy } from '../cache/core/types/DataProxy'; +export { + InMemoryCache, + InMemoryCacheConfig, +} from '../cache/inmemory/inMemoryCache'; +export { defaultDataIdFromObject } from '../cache/inmemory/policies'; +export * from '../cache/inmemory/types'; + +/* Link */ + +export { empty } from '../link/core/empty'; +export { from } from '../link/core/from'; +export { split } from '../link/core/split'; +export { concat } from '../link/core/concat'; +export { execute } from '../link/core/execute'; +export { ApolloLink } from '../link/core/ApolloLink'; +export * from '../link/core/types'; +export { + parseAndCheckHttpResponse, + ServerParseError +} from '../link/http/parseAndCheckHttpResponse'; +export { + serializeFetchParameter, + ClientParseError +} from '../link/http/serializeFetchParameter'; +export { + HttpOptions, + fallbackHttpConfig, + selectHttpOptionsAndBody, + UriFunction +} from '../link/http/selectHttpOptionsAndBody'; +export { checkFetcher } from '../link/http/checkFetcher'; +export { createSignalIfSupported } from '../link/http/createSignalIfSupported'; +export { selectURI } from '../link/http/selectURI'; +export { createHttpLink } from '../link/http/createHttpLink'; +export { HttpLink } from '../link/http/HttpLink'; +export { fromError } from '../link/utils/fromError'; +export { ServerError, throwServerError } from '../link/utils/throwServerError'; + +/* Utilities */ + +export { Observable } from '../utilities/observables/Observable'; +export { getMainDefinition } from '../utilities/graphql/getFromAST'; + +/* Supporting */ + +export { default as gql } from 'graphql-tag'; diff --git a/src/index.ts b/src/index.ts index 4834c678247..78a29b8b5a3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,102 +1,2 @@ -/* Core */ - -export { - ApolloClient, - ApolloClientOptions, - DefaultOptions -} from './ApolloClient'; -export { - ObservableQuery, - FetchMoreOptions, - UpdateQueryOptions, - ApolloCurrentQueryResult, -} from './core/ObservableQuery'; -export { - QueryBaseOptions, - QueryOptions, - WatchQueryOptions, - MutationOptions, - SubscriptionOptions, - FetchPolicy, - WatchQueryFetchPolicy, - ErrorPolicy, - FetchMoreQueryOptions, - SubscribeToMoreOptions, - MutationUpdaterFn, -} from './core/watchQueryOptions'; -export { NetworkStatus } from './core/networkStatus'; -export * from './core/types'; -export { - Resolver, - FragmentMatcher as LocalStateFragmentMatcher, -} from './core/LocalState'; -export { isApolloError, ApolloError } from './errors/ApolloError'; - -/* Cache */ - -export { Transaction, ApolloCache } from './cache/core/cache'; -export { Cache } from './cache/core/types/Cache'; -export { DataProxy } from './cache/core/types/DataProxy'; -export { - InMemoryCache, - InMemoryCacheConfig, -} from './cache/inmemory/inMemoryCache'; -export { defaultDataIdFromObject } from './cache/inmemory/policies'; -export * from './cache/inmemory/types'; - -/* React */ - -export { ApolloProvider } from './react/context/ApolloProvider'; -export { ApolloConsumer } from './react/context/ApolloConsumer'; -export { - getApolloContext, - resetApolloContext, - ApolloContextValue -} from './react/context/ApolloContext'; -export { useQuery } from './react/hooks/useQuery'; -export { useLazyQuery } from './react/hooks/useLazyQuery'; -export { useMutation } from './react/hooks/useMutation'; -export { useSubscription } from './react/hooks/useSubscription'; -export { useApolloClient } from './react/hooks/useApolloClient'; -export { RenderPromises } from './react/ssr/RenderPromises'; -export * from './react/types/types'; -export * from './react/parser/parser'; - -/* Link */ - -export { empty } from './link/core/empty'; -export { from } from './link/core/from'; -export { split } from './link/core/split'; -export { concat } from './link/core/concat'; -export { execute } from './link/core/execute'; -export { ApolloLink } from './link/core/ApolloLink'; -export * from './link/core/types'; -export { - parseAndCheckHttpResponse, - ServerParseError -} from './link/http/parseAndCheckHttpResponse'; -export { - serializeFetchParameter, - ClientParseError -} from './link/http/serializeFetchParameter'; -export { - HttpOptions, - fallbackHttpConfig, - selectHttpOptionsAndBody, - UriFunction -} from './link/http/selectHttpOptionsAndBody'; -export { checkFetcher } from './link/http/checkFetcher'; -export { createSignalIfSupported } from './link/http/createSignalIfSupported'; -export { selectURI } from './link/http/selectURI'; -export { createHttpLink } from './link/http/createHttpLink'; -export { HttpLink } from './link/http/HttpLink'; -export { fromError } from './link/utils/fromError'; -export { ServerError, throwServerError } from './link/utils/throwServerError'; - -/* Utilities */ - -export { Observable } from './utilities/observables/Observable'; - -/* Supporting */ - -export { default as gql } from 'graphql-tag'; +export * from './core'; +export * from './react'; diff --git a/src/react/data/MutationData.ts b/src/react/data/MutationData.ts index 316ef21c13b..78d20e568a7 100644 --- a/src/react/data/MutationData.ts +++ b/src/react/data/MutationData.ts @@ -3,7 +3,7 @@ import { equal as isEqual } from '@wry/equality'; import { DocumentType } from '../parser/parser'; import { ApolloError } from '../../errors/ApolloError'; import { - MutationOptions, + MutationDataOptions, MutationTuple, MutationFunctionOptions, MutationResult @@ -27,7 +27,7 @@ export class MutationData< result, setResult }: { - options: MutationOptions; + options: MutationDataOptions; context: any; result: MutationResult; setResult: (result: MutationResult) => any; diff --git a/src/react/data/QueryData.ts b/src/react/data/QueryData.ts index c7f7b771191..853a9934ce4 100644 --- a/src/react/data/QueryData.ts +++ b/src/react/data/QueryData.ts @@ -15,7 +15,7 @@ import { DocumentType } from '../parser/parser'; import { QueryResult, QueryPreviousData, - QueryOptions, + QueryDataOptions, QueryCurrentObservable, QueryTuple, QueryLazyOptions, @@ -36,7 +36,7 @@ export class QueryData extends OperationData { context, forceUpdate }: { - options: QueryOptions; + options: QueryDataOptions; context: any; forceUpdate: any; }) { diff --git a/src/react/data/SubscriptionData.ts b/src/react/data/SubscriptionData.ts index 4ce09eebda4..9128899de3c 100644 --- a/src/react/data/SubscriptionData.ts +++ b/src/react/data/SubscriptionData.ts @@ -3,14 +3,14 @@ import { equal as isEqual } from '@wry/equality'; import { OperationData } from './OperationData'; import { SubscriptionCurrentObservable, - SubscriptionOptions, + SubscriptionDataOptions, SubscriptionResult } from '../types/types'; export class SubscriptionData< TData = any, TVariables = any -> extends OperationData> { +> extends OperationData> { private setResult: any; private currentObservable: SubscriptionCurrentObservable = {}; @@ -19,7 +19,7 @@ export class SubscriptionData< context, setResult }: { - options: SubscriptionOptions; + options: SubscriptionDataOptions; context: any; setResult: any; }) { @@ -77,7 +77,7 @@ export class SubscriptionData< delete this.currentObservable.query; } - private initialize(options: SubscriptionOptions) { + private initialize(options: SubscriptionDataOptions) { if (this.currentObservable.query || this.getOptions().skip === true) return; this.currentObservable.query = this.refreshClient().client.subscribe({ query: options.subscription, diff --git a/src/react/hooks/utils/useBaseQuery.ts b/src/react/hooks/utils/useBaseQuery.ts index 4e09bde168d..5810e55f2d5 100644 --- a/src/react/hooks/utils/useBaseQuery.ts +++ b/src/react/hooks/utils/useBaseQuery.ts @@ -3,7 +3,7 @@ import { DocumentNode } from 'graphql'; import { QueryHookOptions, - QueryOptions, + QueryDataOptions, QueryTuple, QueryResult, } from '../../types/types'; @@ -25,7 +25,7 @@ export function useBaseQuery( if (!queryDataRef.current) { queryDataRef.current = new QueryData({ - options: updatedOptions as QueryOptions, + options: updatedOptions as QueryDataOptions, context, forceUpdate }); diff --git a/src/react/index.ts b/src/react/index.ts new file mode 100644 index 00000000000..0cf189fadde --- /dev/null +++ b/src/react/index.ts @@ -0,0 +1,21 @@ +export { ApolloProvider } from './context/ApolloProvider'; +export { ApolloConsumer } from './context/ApolloConsumer'; +export { + getApolloContext, + resetApolloContext, + ApolloContextValue +} from './context/ApolloContext'; +export { useQuery } from './hooks/useQuery'; +export { useLazyQuery } from './hooks/useLazyQuery'; +export { useMutation } from './hooks/useMutation'; +export { useSubscription } from './hooks/useSubscription'; +export { useApolloClient } from './hooks/useApolloClient'; +export { RenderPromises } from './ssr/RenderPromises'; +export { + DocumentType, + IDocumentDefinition, + operationName, + parser +} from './parser/parser'; + +export * from './types/types'; diff --git a/src/react/ssr/RenderPromises.ts b/src/react/ssr/RenderPromises.ts index ae2849e6a69..734c7ef395c 100644 --- a/src/react/ssr/RenderPromises.ts +++ b/src/react/ssr/RenderPromises.ts @@ -1,7 +1,7 @@ import { DocumentNode } from 'graphql'; import { ObservableQuery } from '../../core/ObservableQuery'; -import { QueryOptions } from '../types/types'; +import { QueryDataOptions } from '../types/types'; import { QueryData } from '../data/QueryData'; type QueryInfo = { @@ -18,7 +18,7 @@ function makeDefaultQueryInfo(): QueryInfo { export class RenderPromises { // Map from Query component instances to pending fetchData promises. - private queryPromises = new Map, Promise>(); + private queryPromises = new Map, Promise>(); // Two-layered map from (query document, stringified variables) to QueryInfo // objects. These QueryInfo objects are intended to survive through the whole @@ -29,14 +29,14 @@ export class RenderPromises { // Registers the server side rendered observable. public registerSSRObservable( observable: ObservableQuery, - props: QueryOptions + props: QueryDataOptions ) { this.lookupQueryInfo(props).observable = observable; } // Get's the cached observable that matches the SSR Query instances query and variables. public getSSRObservable( - props: QueryOptions + props: QueryDataOptions ) { return this.lookupQueryInfo(props).observable; } @@ -84,7 +84,7 @@ export class RenderPromises { } private lookupQueryInfo( - props: QueryOptions + props: QueryDataOptions ): QueryInfo { const { queryInfoTrie } = this; const { query, variables } = props; diff --git a/src/react/types/types.ts b/src/react/types/types.ts index 3e082c5ed37..415efe694d8 100644 --- a/src/react/types/types.ts +++ b/src/react/types/types.ts @@ -85,7 +85,7 @@ export interface QueryResult called: boolean; } -export interface QueryOptions +export interface QueryDataOptions extends QueryFunctionOptions { children?: (result: QueryResult) => ReactNode; query: DocumentNode; @@ -109,7 +109,7 @@ export interface QueryPreviousData { observableQueryOptions?: {}; result?: ApolloQueryResult | null; loading?: boolean; - options?: QueryOptions; + options?: QueryDataOptions; error?: ApolloError; } @@ -188,7 +188,7 @@ export interface MutationHookOptions< mutation?: DocumentNode; } -export interface MutationOptions +export interface MutationDataOptions extends BaseMutationOptions { mutation: DocumentNode; } @@ -235,7 +235,7 @@ export interface SubscriptionHookOptions< subscription?: DocumentNode; } -export interface SubscriptionOptions< +export interface SubscriptionDataOptions< TData = any, TVariables = OperationVariables > extends BaseSubscriptionOptions {