Skip to content

Commit 6440e8b

Browse files
authored
last-minute codemod tweaks and corrections (#12858)
* also apply clientSetup codemod to integration packages * remove `TCacheShape` generic from `ApolloClient` constructor calls * ensure when moving types into the `Defer20220824Handler` they end up importing from the right module * add `Masked` and `MaskedDocumentNode` to removals * also remove `TCacheShape` parameter from `ApolloClient` type usage * update README * add test to ensure that aliases are followed * chore * changeset
1 parent 17b665e commit 6440e8b

File tree

8 files changed

+277
-8
lines changed

8 files changed

+277
-8
lines changed

.api-reports/api-report-v4-migration.api.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ export const itAsync: never;
196196
// @public @deprecated (undocumented)
197197
export const iterateObserversSafely: never;
198198

199+
// @public @deprecated (undocumented)
200+
export type Masked = never;
201+
202+
// @public @deprecated (undocumented)
203+
export type MaskedDocumentNode = never;
204+
199205
// @public @deprecated (undocumented)
200206
export const mergeIncrementalData: never;
201207

.changeset/sour-wasps-bathe.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@apollo/client-codemod-migrate-3-to-4": patch
3+
---
4+
5+
adjust the `clientSetup` codemod so that it removes the `TCacheShape` type argument from all `ApolloClient` usages (types and constructor calls).

scripts/codemods/ac3-to-ac4/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ In the order they will be applied per default if you don't manually specify a co
2929
- Renames `disableNetworkFetches` to `prioritizeCacheValues`
3030
- If `dataMasking` is enabled, adds a template for global type augmentation to re-enable data masking types
3131
- Adds the `incrementalHandler` option and adds a template for global type augmentation to accordingly type network responses in custom links
32+
- Removes the `TCacheShape` type argument from all `ApolloClient` usages (types and constructor calls)
3233

3334
### Usage against TypeScript/TSX
3435

scripts/codemods/ac3-to-ac4/src/__tests__/apolloClientInitialization.test.ts

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe("all transforms", () => {
2222
expect(transform()`
2323
import { ApolloClient, InMemoryCache } from "@apollo/client";
2424
25-
export const client = new ApolloClient({
25+
export const client = new ApolloClient<MyCacheShape>({
2626
uri: "/graphql",
2727
credentials: "include",
2828
headers: {
@@ -125,6 +125,177 @@ export const client = new ApolloClient({
125125
*/
126126
127127
128+
import "@apollo/client";
129+
import { Defer20220824Handler } from "@apollo/client/incremental";
130+
131+
declare module "@apollo/client" {
132+
export interface TypeOverrides extends Defer20220824Handler.TypeOverrides {}
133+
}
134+
135+
/*
136+
End: Inserted by Apollo Client 3->4 migration codemod.
137+
*/"
138+
`);
139+
});
140+
141+
test("Apollo Client renamed", () => {
142+
expect(transform()`
143+
import { ApolloClient as RenamedApolloClient, SomethingElse as ApolloClient, InMemoryCache } from "@apollo/client";
144+
145+
export const dontTouchThis: ApolloClient<MyCacheShape> = new ApolloClient<MyCacheShape>({
146+
uri: "/graphql",
147+
credentials: "include",
148+
headers: {
149+
"x-custom-header": "value",
150+
},
151+
cache: new InMemoryCache(),
152+
ssrForceFetchDelay: 50,
153+
ssrMode: true,
154+
connectToDevTools: true,
155+
queryDeduplication: true,
156+
defaultOptions: {},
157+
defaultContext: {},
158+
assumeImmutableResults: true,
159+
resolvers: myResolvers,
160+
typeDefs: mySchema,
161+
fragmentMatcher: () => true,
162+
name: "my-client",
163+
version: "1.0.0",
164+
documentTransform: myDocumentTransform,
165+
dataMasking: true
166+
})
167+
168+
export const transformThis: RenamedApolloClient<MyCacheShape> = new RenamedApolloClient<MyCacheShape>({
169+
uri: "/graphql",
170+
credentials: "include",
171+
headers: {
172+
"x-custom-header": "value",
173+
},
174+
cache: new InMemoryCache(),
175+
ssrForceFetchDelay: 50,
176+
ssrMode: true,
177+
connectToDevTools: true,
178+
queryDeduplication: true,
179+
defaultOptions: {},
180+
defaultContext: {},
181+
assumeImmutableResults: true,
182+
resolvers: myResolvers,
183+
typeDefs: mySchema,
184+
fragmentMatcher: () => true,
185+
name: "my-client",
186+
version: "1.0.0",
187+
documentTransform: myDocumentTransform,
188+
dataMasking: true
189+
})
190+
`).toMatchInlineSnapshot(`
191+
"import {
192+
ApolloClient as RenamedApolloClient,
193+
SomethingElse as ApolloClient,
194+
InMemoryCache,
195+
HttpLink,
196+
} from "@apollo/client";
197+
198+
import { Defer20220824Handler } from "@apollo/client/incremental";
199+
import { LocalState } from "@apollo/client/local-state";
200+
201+
export const dontTouchThis: ApolloClient<MyCacheShape> = new ApolloClient<MyCacheShape>({
202+
uri: "/graphql",
203+
credentials: "include",
204+
headers: {
205+
"x-custom-header": "value",
206+
},
207+
cache: new InMemoryCache(),
208+
ssrForceFetchDelay: 50,
209+
ssrMode: true,
210+
connectToDevTools: true,
211+
queryDeduplication: true,
212+
defaultOptions: {},
213+
defaultContext: {},
214+
assumeImmutableResults: true,
215+
resolvers: myResolvers,
216+
typeDefs: mySchema,
217+
fragmentMatcher: () => true,
218+
name: "my-client",
219+
version: "1.0.0",
220+
documentTransform: myDocumentTransform,
221+
dataMasking: true
222+
})
223+
224+
export const transformThis: RenamedApolloClient = new RenamedApolloClient({
225+
cache: new InMemoryCache(),
226+
ssrForceFetchDelay: 50,
227+
ssrMode: true,
228+
queryDeduplication: true,
229+
defaultOptions: {},
230+
defaultContext: {},
231+
assumeImmutableResults: true,
232+
documentTransform: myDocumentTransform,
233+
234+
/*
235+
Inserted by Apollo Client 3->4 migration codemod.
236+
Keep this comment here if you intend to run the codemod again,
237+
to avoid changes from being reapplied.
238+
Delete this comment once you are done with the migration.
239+
@apollo/client-codemod-migrate-3-to-4 applied
240+
*/
241+
dataMasking: true,
242+
243+
link: new HttpLink({
244+
uri: "/graphql",
245+
credentials: "include",
246+
247+
headers: {
248+
"x-custom-header": "value",
249+
}
250+
}),
251+
252+
clientAwareness: {
253+
name: "my-client",
254+
version: "1.0.0"
255+
},
256+
257+
localState: new LocalState({
258+
resolvers: myResolvers
259+
}),
260+
261+
devtools: {
262+
enabled: true
263+
},
264+
265+
/*
266+
Inserted by Apollo Client 3->4 migration codemod.
267+
If you are not using the \`@defer\` directive in your application,
268+
you can safely remove this option.
269+
*/
270+
incrementalHandler: new Defer20220824Handler()
271+
})
272+
273+
/*
274+
Start: Inserted by Apollo Client 3->4 migration codemod.
275+
Copy the contents of this block into a \`.d.ts\` file in your project
276+
to enable data masking types.
277+
*/
278+
279+
280+
import "@apollo/client";
281+
import { GraphQLCodegenDataMasking } from "@apollo/client/masking";
282+
283+
declare module "@apollo/client" {
284+
export interface TypeOverrides extends GraphQLCodegenDataMasking.TypeOverrides {}
285+
}
286+
287+
/*
288+
End: Inserted by Apollo Client 3->4 migration codemod.
289+
*/
290+
291+
292+
/*
293+
Start: Inserted by Apollo Client 3->4 migration codemod.
294+
Copy the contents of this block into a \`.d.ts\` file in your project to enable correct response types in your custom links.
295+
If you do not use the \`@defer\` directive in your application, you can safely remove this block.
296+
*/
297+
298+
128299
import "@apollo/client";
129300
import { Defer20220824Handler } from "@apollo/client/incremental";
130301
@@ -892,3 +1063,39 @@ new ApolloClient({
8921063
`).toMatchInlineSnapshot(`""`);
8931064
});
8941065
});
1066+
1067+
describe("removeTypeArguments", () => {
1068+
test("remove constructor type argument", () => {
1069+
expect(transform("removeTypeArguments")`
1070+
import { ApolloClient } from "@apollo/client";
1071+
1072+
new ApolloClient<CacheShape>({
1073+
cache: new InMemoryCache(),
1074+
link: someLink,
1075+
})
1076+
`).toMatchInlineSnapshot(`
1077+
"import { ApolloClient } from "@apollo/client";
1078+
1079+
new ApolloClient({
1080+
cache: new InMemoryCache(),
1081+
link: someLink,
1082+
})"
1083+
`);
1084+
});
1085+
1086+
test("removes type arguments for usages of `ApolloClient` as a type", () => {
1087+
expect(transform("removeTypeArguments")`
1088+
import { ApolloClient } from "@apollo/client";
1089+
1090+
function test(client: ApolloClient<unknown>): ApolloClient<any> {
1091+
return client;
1092+
}
1093+
`).toMatchInlineSnapshot(`
1094+
"import { ApolloClient } from "@apollo/client";
1095+
1096+
function test(client: ApolloClient): ApolloClient {
1097+
return client;
1098+
}"
1099+
`);
1100+
});
1101+
});

scripts/codemods/ac3-to-ac4/src/apolloClientInitialization.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { findImportSpecifiersFor } from "./util/findImportSpecifiersFor.js";
99
import { findOrInsertImport } from "./util/findOrInsertImport.js";
1010
import { findReferences } from "./util/findReferences.js";
1111
import { getProperty } from "./util/getProperty.js";
12+
import { monkeyPatchAstTypes } from "./util/monkeyPatchAstTypes.js";
1213

1314
const steps = {
1415
explicitLinkConstruction,
@@ -20,7 +21,7 @@ const steps = {
2021
incrementalHandler,
2122
} satisfies Record<string, (options: StepOptions) => void>;
2223

23-
export type Steps = keyof typeof steps;
24+
export type Steps = keyof typeof steps | "removeTypeArguments";
2425

2526
const apolloClientInitializationTransform: j.Transform = function transform(
2627
file,
@@ -31,14 +32,16 @@ const apolloClientInitializationTransform: j.Transform = function transform(
3132
const source = j(file.source);
3233
const context = { j, source };
3334

35+
monkeyPatchAstTypes(j);
36+
3437
let modified = false;
3538
function onModified() {
3639
modified = true;
3740
}
3841
const enabledStepNames =
3942
Array.isArray(options.apolloClientInitialization) ?
4043
options.apolloClientInitialization
41-
: Object.keys(steps);
44+
: Object.keys(steps).concat("removeTypeArguments");
4245
const enabledSteps = Object.fromEntries(
4346
Object.entries(steps).filter(([name]) => enabledStepNames.includes(name))
4447
);
@@ -61,6 +64,31 @@ const apolloClientInitializationTransform: j.Transform = function transform(
6164
}
6265
}
6366

67+
// removes `TCacheShape` parameter from all `ApolloClient` usages, not just constructor calls
68+
if (enabledStepNames.includes("removeTypeArguments")) {
69+
for (const specPath of findImportSpecifiersFor({
70+
description: apolloClientDescription,
71+
context,
72+
}).paths()) {
73+
for (const refParent of findReferences({
74+
context,
75+
identifier: (specPath.node.local || specPath.node.imported).name + "",
76+
scope: specPath.scope,
77+
})
78+
.map((refPath) => {
79+
const parentPath = refPath.parentPath;
80+
return j.ImportSpecifier.check(parentPath.node) ? null : parentPath;
81+
})
82+
.paths()) {
83+
const typeParameters = refParent.get("typeParameters");
84+
if (typeParameters?.node?.params?.length) {
85+
modified = true;
86+
typeParameters.prune();
87+
}
88+
}
89+
}
90+
}
91+
6492
return modified ? source.toSource() : undefined;
6593
};
6694
export default apolloClientInitializationTransform;
@@ -456,11 +484,7 @@ function* apolloClientConstructions({
456484
context: UtilContext;
457485
}): Generator<ConstructorCall> {
458486
for (const specPath of findImportSpecifiersFor({
459-
description: {
460-
module: "@apollo/client",
461-
identifier: "ApolloClient",
462-
alternativeModules: ["@apollo/client/core"],
463-
},
487+
description: apolloClientDescription,
464488
compatibleWith: "value",
465489
context,
466490
}).paths()) {
@@ -488,3 +512,16 @@ function* apolloClientConstructions({
488512
const CODEMOD_MARKER = `@apollo/client-codemod-migrate-3-to-4`;
489513
const CODEMOD_MARKER_REGEX = (keyword: string) =>
490514
new RegExp(`^\\s*(?:[*]?\\s*)${CODEMOD_MARKER} ${keyword}\\s*$`, "m");
515+
516+
const apolloClientDescription = {
517+
module: "@apollo/client",
518+
identifier: "ApolloClient",
519+
alternativeModules: [
520+
"@apollo/client/core",
521+
"@apollo/client-react-streaming",
522+
"@apollo/experimental-nextjs-app-support",
523+
"@apollo/client-integration-nextjs",
524+
"@apollo/client-integration-react-router",
525+
"@apollo/client-integration-tanstack-start",
526+
],
527+
};

scripts/codemods/ac3-to-ac4/src/removals.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ const removals = [
1818
{ importType: "type", module: "@apollo/client/errors", identifier: "NetworkError" },
1919
{ importType: "type", module: "@apollo/client/link/batch", identifier: "BatchableRequest" },
2020
{ importType: "type", module: "@apollo/client/link/http", identifier: "ClientParseError" },
21+
{ importType: "type", module: "@apollo/client/masking", identifier: "Masked" },
22+
{ importType: "type", module: "@apollo/client/masking", identifier: "MaskedDocumentNode" },
2123
{ importType: "type", module: "@apollo/client/react", identifier: "BaseMutationOptions" },
2224
{ importType: "type", module: "@apollo/client/react", identifier: "BaseQueryOptions" },
2325
{ importType: "type", module: "@apollo/client/react", identifier: "CommonOptions" },

scripts/codemods/ac3-to-ac4/src/renames.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ export const renames: Array<IdentifierRename | ModuleRename> = [
595595
},
596596
to: {
597597
module: "@apollo/client/incremental",
598+
alternativeModules: [],
598599
namespace: "Defer20220824Handler",
599600
},
600601
importType: "type",

src/v4-migration.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,16 @@ export type ChildProps = never;
510510
*/
511511
export type ClientParseError = never;
512512

513+
/**
514+
* {@inheritDoc @apollo/client/v4-migration!Removals.removedType:type {"name":"Masked"} }
515+
*/
516+
export type Masked = never;
517+
518+
/**
519+
* {@inheritDoc @apollo/client/v4-migration!Removals.removedType:type {"name":"MaskedDocumentNode"} }
520+
*/
521+
export type MaskedDocumentNode = never;
522+
513523
/**
514524
* {@inheritDoc @apollo/client/v4-migration!Removals.removedType:type {"name":"CommonOptions"} }
515525
*/

0 commit comments

Comments
 (0)