Skip to content

Commit 839cffd

Browse files
authored
Merge branch 'release-4.0' into jerel/get-started-doc
2 parents b2b37e6 + 4eac754 commit 839cffd

11 files changed

Lines changed: 275 additions & 32 deletions

.api-reports/api-report-utilities.api.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,26 +87,22 @@ type DeepPartialReadonlySet<T> = {} & ReadonlySet<DeepPartial<T>>;
8787
// @public (undocumented)
8888
type DeepPartialSet<T> = {} & Set<DeepPartial<T>>;
8989

90-
// @public (undocumented)
90+
// @public
9191
export class DocumentTransform {
9292
// Warning: (ae-forgotten-export) The symbol "TransformFn" needs to be exported by the entry point index.d.ts
9393
// Warning: (ae-forgotten-export) The symbol "DocumentTransformOptions" needs to be exported by the entry point index.d.ts
9494
constructor(transform: TransformFn, options?: DocumentTransformOptions);
95-
// (undocumented)
9695
concat(otherTransform: DocumentTransform): DocumentTransform;
97-
// (undocumented)
9896
static identity(): DocumentTransform;
9997
// @internal @deprecated
10098
readonly left?: DocumentTransform;
10199
resetCache(): void;
102100
// @internal @deprecated
103101
readonly right?: DocumentTransform;
104-
// (undocumented)
105102
static split(predicate: (document: DocumentNode) => boolean, left: DocumentTransform, right?: DocumentTransform): DocumentTransform & {
106103
left: DocumentTransform;
107104
right: DocumentTransform;
108105
};
109-
// (undocumented)
110106
transformDocument(document: DocumentNode): DocumentNode;
111107
}
112108

@@ -135,7 +131,7 @@ export interface HKT {
135131
return: unknown;
136132
}
137133

138-
// @public (undocumented)
134+
// @public
139135
export function isFormattedExecutionResult(result?: object): result is FormattedExecutionResult;
140136

141137
// @public

.api-reports/api-report-utilities_internal.api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ export const getInMemoryCacheMemoryInternals: (() => {
279279
};
280280
}) | undefined;
281281

282-
// @internal @deprecated
282+
// @public
283283
export function getMainDefinition(queryDoc: DocumentNode): OperationDefinitionNode | FragmentDefinitionNode;
284284

285285
// @internal @deprecated (undocumented)

.api-reports/api-report.api.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -948,26 +948,22 @@ type DistributedRequiredExclude<T, U> = T extends any ? Required<T> extends Requ
948948

949949
export { DocumentNode }
950950

951-
// @public (undocumented)
951+
// @public
952952
export class DocumentTransform {
953953
// Warning: (ae-forgotten-export) The symbol "TransformFn" needs to be exported by the entry point index.d.ts
954954
// Warning: (ae-forgotten-export) The symbol "DocumentTransformOptions" needs to be exported by the entry point index.d.ts
955955
constructor(transform: TransformFn, options?: DocumentTransformOptions);
956-
// (undocumented)
957956
concat(otherTransform: DocumentTransform): DocumentTransform;
958-
// (undocumented)
959957
static identity(): DocumentTransform;
960958
// @internal @deprecated
961959
readonly left?: DocumentTransform;
962960
resetCache(): void;
963961
// @internal @deprecated
964962
readonly right?: DocumentTransform;
965-
// (undocumented)
966963
static split(predicate: (document: DocumentNode) => boolean, left: DocumentTransform, right?: DocumentTransform): DocumentTransform & {
967964
left: DocumentTransform;
968965
right: DocumentTransform;
969966
};
970-
// (undocumented)
971967
transformDocument(document: DocumentNode): DocumentNode;
972968
}
973969

src/utilities/common/stripTypename.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ import { omitDeep } from "@apollo/client/utilities/internal";
55
*
66
* @param value - The object or array that should have `__typename` removed.
77
* @returns The object with all `__typename` properties removed.
8+
*
9+
* @example
10+
*
11+
* ```ts
12+
* stripTypename({
13+
* __typename: "User",
14+
* id: 1,
15+
* profile: { __typename: "Profile", name: "John Doe" },
16+
* });
17+
* // => { id: 1, profile: { name: "John Doe"}}
18+
* ```
819
*/
920
export function stripTypename<T>(value: T) {
1021
return omitDeep(value, "__typename");

src/utilities/graphql/DocumentTransform.ts

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,23 @@ type TransformFn = (document: DocumentNode) => DocumentNode;
1414

1515
interface DocumentTransformOptions {
1616
/**
17-
* Determines whether to cache the transformed GraphQL document. Caching can speed up repeated calls to the document transform for the same input document. Set to `false` to completely disable caching for the document transform. When disabled, this option takes precedence over the [`getCacheKey`](#getcachekey) option.
17+
* Determines whether to cache the transformed GraphQL document. Caching can
18+
* speed up repeated calls to the document transform for the same input
19+
* document. Set to `false` to completely disable caching for the document
20+
* transform. When disabled, this option takes precedence over the [`getCacheKey`](#getcachekey)
21+
* option.
1822
*
19-
* The default value is `true`.
23+
* @defaultValue `true`
2024
*/
2125
cache?: boolean;
2226
/**
2327
* Defines a custom cache key for a GraphQL document that will determine whether to re-run the document transform when given the same input GraphQL document. Returns an array that defines the cache key. Return `undefined` to disable caching for that GraphQL document.
2428
*
25-
* > **Note:** The items in the array may be any type, but also need to be referentially stable to guarantee a stable cache key.
29+
* > [!NOTE]
30+
* > The items in the array can be any type, but each item needs to be
31+
* > referentially stable to guarantee a stable cache key.
2632
*
27-
* The default implementation of this function returns the `document` as the cache key.
33+
* @defaultValue `(document) => [document]`
2834
*/
2935
getCacheKey?: (
3036
document: DocumentNode
@@ -35,6 +41,25 @@ function identity(document: DocumentNode) {
3541
return document;
3642
}
3743

44+
/**
45+
* A class for transforming GraphQL documents. See the [Document transforms
46+
* documentation](https://www.apollographql.com/docs/react/data/document-transforms) for more details on using them.
47+
*
48+
* @example
49+
*
50+
* ```ts
51+
* import { DocumentTransform } from "@apollo/client/utilities";
52+
* import { visit } from "graphql";
53+
*
54+
* const documentTransform = new DocumentTransform((doc) => {
55+
* return visit(doc, {
56+
* // ...
57+
* });
58+
* });
59+
*
60+
* const transformedDoc = documentTransform.transformDocument(myDocument);
61+
* ```
62+
*/
3863
export class DocumentTransform {
3964
private readonly transform: TransformFn;
4065
private cached: boolean;
@@ -52,13 +77,38 @@ export class DocumentTransform {
5277
return [document];
5378
}
5479

80+
/**
81+
* Creates a DocumentTransform that returns the input document unchanged.
82+
*
83+
* @returns The input document
84+
*/
5585
static identity() {
5686
// No need to cache this transform since it just returns the document
5787
// unchanged. This should save a bit of memory that would otherwise be
5888
// needed to populate the `documentCache` of this transform.
5989
return new DocumentTransform(identity, { cache: false });
6090
}
6191

92+
/**
93+
* Creates a DocumentTransform that conditionally applies one of two transforms.
94+
*
95+
* @param predicate - Function that determines which transform to apply
96+
* @param left - Transform to apply when `predicate` returns `true`
97+
* @param right - Transform to apply when `predicate` returns `false`. If not provided, it defaults to `DocumentTransform.identity()`.
98+
* @returns A DocumentTransform that conditionally applies a document transform based on the predicate
99+
*
100+
* @example
101+
*
102+
* ```ts
103+
* import { isQueryOperation } from "@apollo/client/utilities";
104+
*
105+
* const conditionalTransform = DocumentTransform.split(
106+
* (document) => isQueryOperation(document),
107+
* queryTransform,
108+
* mutationTransform
109+
* );
110+
* ```
111+
*/
62112
static split(
63113
predicate: (document: DocumentNode) => boolean,
64114
left: DocumentTransform,
@@ -91,7 +141,7 @@ export class DocumentTransform {
91141
}
92142

93143
/**
94-
* Resets the internal cache of this transform, if it has one.
144+
* Resets the internal cache of this transform, if it is cached.
95145
*/
96146
resetCache() {
97147
if (this.cached) {
@@ -121,6 +171,29 @@ export class DocumentTransform {
121171
return this.transform(document);
122172
}
123173

174+
/**
175+
* Transforms a GraphQL document using the configured transform function.
176+
*
177+
* @remarks
178+
*
179+
* Note that `transformDocument` caches the transformed document. Calling
180+
* `transformDocument` again with the already-transformed document will
181+
* immediately return it.
182+
*
183+
* @param document - The GraphQL document to transform
184+
* @returns The transformed document
185+
*
186+
* @example
187+
*
188+
* ```ts
189+
* const document = gql`
190+
* # ...
191+
* `;
192+
*
193+
* const documentTransform = new DocumentTransform(transformFn);
194+
* const transformedDocument = documentTransform.transformDocument(document);
195+
* ```
196+
*/
124197
transformDocument(document: DocumentNode) {
125198
// If a user passes an already transformed result back to this function,
126199
// immediately return it.
@@ -135,6 +208,22 @@ export class DocumentTransform {
135208
return transformedDocument;
136209
}
137210

211+
/**
212+
* Combines this document transform with another document transform. The
213+
* returned document transform first applies the current document transform,
214+
* then applies the other document transform.
215+
*
216+
* @param otherTransform - The transform to apply after this one
217+
* @returns A new DocumentTransform that applies both transforms in sequence
218+
*
219+
* @example
220+
*
221+
* ```ts
222+
* const combinedTransform = addTypenameTransform.concat(
223+
* removeDirectivesTransform
224+
* );
225+
* ```
226+
*/
138227
concat(otherTransform: DocumentTransform): DocumentTransform {
139228
return Object.assign(
140229
new DocumentTransform(

src/utilities/graphql/isFormattedExecutionResult.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
import type { FormattedExecutionResult } from "graphql";
22

3+
/**
4+
* Determines whether the given object is a valid GraphQL execution result
5+
* according to the GraphQL specification.
6+
*
7+
* @remarks
8+
*
9+
* A valid execution result must be an object that contains only `data`,
10+
* `errors`, and/or `extensions` properties. At least one of `data` or `errors`
11+
* must be present.
12+
*
13+
* @param result - The object to test
14+
* @returns `true` if the object conforms to the GraphQL execution result format
15+
*
16+
* @example
17+
*
18+
* ```ts
19+
* import { isFormattedExecutionResult } from "@apollo/client/utilities";
20+
*
21+
* // Valid execution result
22+
* const validResult = { data: { user: { name: "John" } } };
23+
* console.log(isFormattedExecutionResult(validResult)); // true
24+
*
25+
* // Invalid - contains non-standard properties
26+
* const invalidResult = { data: {}, customField: "value" };
27+
* console.log(isFormattedExecutionResult(invalidResult)); // false
28+
* ```
29+
*/
330
export function isFormattedExecutionResult(
431
result?: object
532
): result is FormattedExecutionResult {

src/utilities/graphql/operations.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,26 @@ function isOperation(
1111
/**
1212
* Determine if a document is a mutation document.
1313
*
14+
* @remarks
15+
* If you are authoring an Apollo link, you might not need this utility.
16+
* Prefer using the `operationType` property the `operation` object instead.
17+
*
1418
* @param document - The GraphQL document to check
19+
* @returns A boolean indicating if the document is a mutation operation
20+
*
21+
* @example
22+
*
23+
* ```ts
24+
* import { isMutationOperation } from "@apollo/client/utilities";
1525
*
16-
* @since 3.8.0
26+
* const mutation = gql`
27+
* mutation MyMutation {
28+
* # ...
29+
* }
30+
* `;
31+
*
32+
* isMutationOperation(mutation); // true
33+
* ```
1734
*/
1835
export function isMutationOperation(document: DocumentNode) {
1936
return isOperation(document, "mutation");
@@ -22,9 +39,26 @@ export function isMutationOperation(document: DocumentNode) {
2239
/**
2340
* Determine if a document is a query document.
2441
*
42+
* @remarks
43+
* If you are authoring an Apollo link, you might not need this utility.
44+
* Prefer using the `operationType` property the `operation` object instead.
45+
*
2546
* @param document - The GraphQL document to check
47+
* @returns A boolean indicating if the document is a query operation
48+
*
49+
* @example
2650
*
27-
* @since 3.8.0
51+
* ```ts
52+
* import { isQueryOperation } from "@apollo/client/utilities";
53+
*
54+
* const query = gql`
55+
* query MyQuery {
56+
* # ...
57+
* }
58+
* `;
59+
*
60+
* isQueryOperation(query); // true
61+
* ```
2862
*/
2963
export function isQueryOperation(document: DocumentNode) {
3064
return isOperation(document, "query");
@@ -33,9 +67,26 @@ export function isQueryOperation(document: DocumentNode) {
3367
/**
3468
* Determine if a document is a subscription document.
3569
*
70+
* @remarks
71+
* If you are authoring an Apollo link, you might not need this utility.
72+
* Prefer using the `operationType` property the `operation` object instead.
73+
*
3674
* @param document - The GraphQL document to check
75+
* @returns A boolean indicating if the document is a subscription operation
76+
*
77+
* @example
78+
*
79+
* ```ts
80+
* import { isSubscriptionOperation } from "@apollo/client/utilities";
81+
*
82+
* const subscription = gql`
83+
* subscription MySubscription {
84+
* # ...
85+
* }
86+
* `;
3787
*
38-
* @since 3.8.0
88+
* isSubscriptionOperation(subscription); // true
89+
* ```
3990
*/
4091
export function isSubscriptionOperation(document: DocumentNode) {
4192
return isOperation(document, "subscription");

src/utilities/graphql/storeUtils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ export interface Reference {
99
* Determines if a given object is a reference object.
1010
*
1111
* @param obj - The object to check if its a reference object
12+
*
13+
* @example
14+
*
15+
* ```ts
16+
* import { isReference } from "@apollo/client/utilities";
17+
*
18+
* isReference({ __ref: "User:1" }); // true
19+
* isReference({ __typename: "User", id: 1 }); // false
20+
* ```
1221
*/
1322
export function isReference(obj: any): obj is Reference {
1423
return Boolean(

0 commit comments

Comments
 (0)