@trpc/upgrade 11.3.1 → 11.3.2-canary.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -1,187 +1,172 @@
1
1
  #!/usr/bin/env node
2
- import { basename, extname } from 'node:path';
3
- import { parse } from '@bomb.sh/args';
4
- import * as p from '@clack/prompts';
5
- import { cancel, log, intro, multiselect, isCancel, outro } from '@clack/prompts';
6
- import * as ts from 'typescript';
7
- import { resolve } from 'path';
8
- import { exec } from 'node:child_process';
9
- import { promisify } from 'node:util';
10
- import __node_cjsModule from 'node:module';
2
+ import { createRequire } from "node:module";
3
+ import { basename, extname } from "node:path";
4
+ import { parse } from "@bomb.sh/args";
5
+ import * as p from "@clack/prompts";
6
+ import { cancel, intro, isCancel, log, multiselect, outro } from "@clack/prompts";
7
+ import * as ts from "typescript";
8
+ import { resolve } from "path";
9
+ import { exec } from "node:child_process";
10
+ import { promisify } from "node:util";
11
11
 
12
- var version = "11.3.1";
12
+ //#region rolldown:runtime
13
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
13
14
 
15
+ //#endregion
16
+ //#region package.json
17
+ var version = "11.3.2-canary.2+b0426132b";
18
+
19
+ //#endregion
20
+ //#region src/lib/ast/scanners.ts
14
21
  function getProgram() {
15
- const configFile = ts.findConfigFile(process.cwd(), (filepath)=>ts.sys.fileExists(filepath));
16
- if (!configFile) {
17
- p.log.error('No tsconfig found');
18
- process.exit(1);
19
- }
20
- if (process.env['VERBOSE']) {
21
- p.log.info(`Using tsconfig: ${configFile}`);
22
- }
23
- const { config } = ts.readConfigFile(configFile, (filepath)=>ts.sys.readFile(filepath));
24
- const parsedConfig = ts.parseJsonConfigFileContent(config, ts.sys, process.cwd());
25
- const program = ts.createProgram({
26
- options: parsedConfig.options,
27
- rootNames: parsedConfig.fileNames,
28
- configFileParsingDiagnostics: parsedConfig.errors
29
- });
30
- return program;
22
+ const configFile = ts.findConfigFile(process.cwd(), (filepath) => ts.sys.fileExists(filepath));
23
+ if (!configFile) {
24
+ p.log.error("No tsconfig found");
25
+ process.exit(1);
26
+ }
27
+ if (process.env["VERBOSE"]) p.log.info(`Using tsconfig: ${configFile}`);
28
+ const { config } = ts.readConfigFile(configFile, (filepath) => ts.sys.readFile(filepath));
29
+ const parsedConfig = ts.parseJsonConfigFileContent(config, ts.sys, process.cwd());
30
+ const program$1 = ts.createProgram({
31
+ options: parsedConfig.options,
32
+ rootNames: parsedConfig.fileNames,
33
+ configFileParsingDiagnostics: parsedConfig.errors
34
+ });
35
+ return program$1;
31
36
  }
32
- function findSourceAndImportName(program) {
33
- const files = program.getSourceFiles().filter((sourceFile)=>{
34
- if (sourceFile.isDeclarationFile) return false;
35
- let found = false;
36
- ts.forEachChild(sourceFile, (node)=>{
37
- if (!found && ts.isImportDeclaration(node)) {
38
- const { moduleSpecifier } = node;
39
- if (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.includes('@trpc/react-query')) {
40
- found = true;
41
- }
42
- }
43
- });
44
- return found;
45
- });
46
- let importName = 'trpc';
47
- files.forEach((sourceFile)=>{
48
- ts.forEachChild(sourceFile, (node)=>{
49
- if (ts.isVariableStatement(node) && node.modifiers?.some((mod)=>mod.getText(sourceFile) === 'export')) {
50
- node.declarationList.declarations.forEach((declaration)=>{
51
- if (ts.isVariableDeclaration(declaration) && declaration.initializer && ts.isCallExpression(declaration.initializer) && ts.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.getText(sourceFile) === 'createTRPCReact') {
52
- importName = declaration.name.getText(sourceFile);
53
- }
54
- });
55
- }
56
- });
57
- });
58
- return {
59
- files: files.map((d)=>d.fileName),
60
- importName
61
- };
37
+ function findSourceAndImportName(program$1) {
38
+ const files = program$1.getSourceFiles().filter((sourceFile) => {
39
+ if (sourceFile.isDeclarationFile) return false;
40
+ let found = false;
41
+ ts.forEachChild(sourceFile, (node) => {
42
+ if (!found && ts.isImportDeclaration(node)) {
43
+ const { moduleSpecifier } = node;
44
+ if (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.includes("@trpc/react-query")) found = true;
45
+ }
46
+ });
47
+ return found;
48
+ });
49
+ let importName = "trpc";
50
+ files.forEach((sourceFile) => {
51
+ ts.forEachChild(sourceFile, (node) => {
52
+ if (ts.isVariableStatement(node) && node.modifiers?.some((mod) => mod.getText(sourceFile) === "export")) node.declarationList.declarations.forEach((declaration) => {
53
+ if (ts.isVariableDeclaration(declaration) && declaration.initializer && ts.isCallExpression(declaration.initializer) && ts.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.getText(sourceFile) === "createTRPCReact") importName = declaration.name.getText(sourceFile);
54
+ });
55
+ });
56
+ });
57
+ return {
58
+ files: files.map((d) => d.fileName),
59
+ importName
60
+ };
62
61
  }
63
- function findTRPCImportReferences(program) {
64
- const { files: filesImportingTRPC, importName } = findSourceAndImportName(program);
65
- const trpcReferenceSpecifiers = new Map();
66
- program.getSourceFiles().forEach((sourceFile)=>{
67
- if (sourceFile.isDeclarationFile) return;
68
- ts.forEachChild(sourceFile, (node)=>{
69
- if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
70
- const resolved = ts.resolveModuleName(node.moduleSpecifier.text, sourceFile.fileName, program.getCompilerOptions(), ts.sys);
71
- if (resolved.resolvedModule && filesImportingTRPC.includes(resolved.resolvedModule.resolvedFileName)) {
72
- trpcReferenceSpecifiers.set(resolved.resolvedModule.resolvedFileName, node.moduleSpecifier.text);
73
- }
74
- }
75
- });
76
- });
77
- const counts = {};
78
- let currentMax = 0;
79
- const mostUsed = {
80
- file: ''
81
- };
82
- [
83
- ...trpcReferenceSpecifiers.values()
84
- ].forEach((specifier)=>{
85
- counts[specifier] = (counts[specifier] ?? 0) + 1;
86
- if (counts[specifier] > currentMax) {
87
- currentMax = counts[specifier];
88
- mostUsed.file = specifier;
89
- }
90
- });
91
- return {
92
- importName,
93
- mostUsed,
94
- all: Object.fromEntries(trpcReferenceSpecifiers.entries())
95
- };
62
+ function findTRPCImportReferences(program$1) {
63
+ const { files: filesImportingTRPC, importName } = findSourceAndImportName(program$1);
64
+ const trpcReferenceSpecifiers = /* @__PURE__ */ new Map();
65
+ program$1.getSourceFiles().forEach((sourceFile) => {
66
+ if (sourceFile.isDeclarationFile) return;
67
+ ts.forEachChild(sourceFile, (node) => {
68
+ if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
69
+ const resolved = ts.resolveModuleName(node.moduleSpecifier.text, sourceFile.fileName, program$1.getCompilerOptions(), ts.sys);
70
+ if (resolved.resolvedModule && filesImportingTRPC.includes(resolved.resolvedModule.resolvedFileName)) trpcReferenceSpecifiers.set(resolved.resolvedModule.resolvedFileName, node.moduleSpecifier.text);
71
+ }
72
+ });
73
+ });
74
+ const counts = {};
75
+ let currentMax = 0;
76
+ const mostUsed = { file: "" };
77
+ [...trpcReferenceSpecifiers.values()].forEach((specifier) => {
78
+ counts[specifier] = (counts[specifier] ?? 0) + 1;
79
+ if (counts[specifier] > currentMax) {
80
+ currentMax = counts[specifier];
81
+ mostUsed.file = specifier;
82
+ }
83
+ });
84
+ return {
85
+ importName,
86
+ mostUsed,
87
+ all: Object.fromEntries(trpcReferenceSpecifiers.entries())
88
+ };
96
89
  }
97
90
 
91
+ //#endregion
92
+ //#region src/lib/execa.ts
98
93
  const execa = promisify(exec);
99
94
 
95
+ //#endregion
96
+ //#region src/lib/git.ts
100
97
  async function assertCleanGitTree() {
101
- const { stdout } = await execa('git status');
102
- if (!stdout.includes('nothing to commit')) {
103
- cancel('Git tree is not clean, please commit your changes and try again, or run with `--force`');
104
- process.exit(1);
105
- }
98
+ const { stdout } = await execa("git status");
99
+ if (!stdout.includes("nothing to commit")) {
100
+ cancel("Git tree is not clean, please commit your changes and try again, or run with `--force`");
101
+ process.exit(1);
102
+ }
106
103
  }
107
104
  async function filterIgnored(files) {
108
- let stdout = '';
109
- let stderr = '';
110
- try {
111
- const result = await execa('git check-ignore **/*');
112
- stdout = result.stdout;
113
- stderr = result.stderr;
114
- } catch (error) {
115
- log.error('Error executing git check-ignore:', error);
116
- stdout = '';
117
- }
118
- const ignores = stdout.split('\n');
119
- if (process.env['VERBOSE']) {
120
- log.info(`cwd: ${process.cwd()}`);
121
- log.info(`All files in program: ${files.map((file)=>file.fileName).join(', ')}`);
122
- log.info(`Ignored files: ${ignores.join(', ')}`);
123
- }
124
- // Ignore "common files"
125
- const filteredSourcePaths = files.filter((source)=>source.fileName.startsWith(resolve()) && // only look ahead of current directory
126
- !source.fileName.includes('/trpc/packages/') && // relative paths when running codemod locally
127
- !source.fileName.includes('/node_modules/') && // always ignore node_modules
128
- !ignores.includes(source.fileName)).map((source)=>source.fileName);
129
- if (process.env['VERBOSE']) {
130
- log.info(`Filtered files: ${filteredSourcePaths.join(', ')}`);
131
- }
132
- return filteredSourcePaths;
105
+ let stdout = "";
106
+ let stderr = "";
107
+ try {
108
+ const result = await execa("git check-ignore **/*");
109
+ stdout = result.stdout;
110
+ stderr = result.stderr;
111
+ } catch (error) {
112
+ log.error("Error executing git check-ignore:", error);
113
+ stdout = "";
114
+ }
115
+ const ignores = stdout.split("\n");
116
+ if (process.env["VERBOSE"]) {
117
+ log.info(`cwd: ${process.cwd()}`);
118
+ log.info(`All files in program: ${files.map((file) => file.fileName).join(", ")}`);
119
+ log.info(`Ignored files: ${ignores.join(", ")}`);
120
+ }
121
+ const filteredSourcePaths = files.filter((source) => source.fileName.startsWith(resolve()) && !source.fileName.includes("/trpc/packages/") && !source.fileName.includes("/node_modules/") && !ignores.includes(source.fileName)).map((source) => source.fileName);
122
+ if (process.env["VERBOSE"]) log.info(`Filtered files: ${filteredSourcePaths.join(", ")}`);
123
+ return filteredSourcePaths;
133
124
  }
134
125
 
126
+ //#endregion
127
+ //#region src/lib/pkgmgr.ts
135
128
  function getPackageManager() {
136
- const userAgent = process.env['npm_config_user_agent'];
137
- if (userAgent?.startsWith('pnpm')) return 'pnpm';
138
- if (userAgent?.startsWith('yarn')) return 'yarn';
139
- if (userAgent?.startsWith('bun')) return 'bun';
140
- return 'npm';
129
+ const userAgent = process.env["npm_config_user_agent"];
130
+ if (userAgent?.startsWith("pnpm")) return "pnpm";
131
+ if (userAgent?.startsWith("yarn")) return "yarn";
132
+ if (userAgent?.startsWith("bun")) return "bun";
133
+ return "npm";
141
134
  }
142
135
  async function installPackage(packageName) {
143
- const packageManager = getPackageManager();
144
- const installCmd = packageManager === 'yarn' ? 'add' : 'install';
145
- const { stdout, stderr } = await execa(`${packageManager} ${installCmd} ${packageName}`);
146
- if (stderr) {
147
- log.error(stderr);
148
- }
149
- if (process.env['VERBOSE']) {
150
- log.info(stdout);
151
- }
136
+ const packageManager = getPackageManager();
137
+ const installCmd = packageManager === "yarn" ? "add" : "install";
138
+ const { stdout, stderr } = await execa(`${packageManager} ${installCmd} ${packageName}`);
139
+ if (stderr) log.error(stderr);
140
+ if (process.env["VERBOSE"]) log.info(stdout);
152
141
  }
153
142
  async function uninstallPackage(packageName) {
154
- const packageManager = getPackageManager();
155
- const uninstallCmd = packageManager === 'yarn' ? 'remove' : 'uninstall';
156
- const { stdout, stderr } = await execa(`${packageManager} ${uninstallCmd} ${packageName}`);
157
- if (stderr) {
158
- log.error(stderr);
159
- }
160
- if (process.env['VERBOSE']) {
161
- log.info(stdout);
162
- }
143
+ const packageManager = getPackageManager();
144
+ const uninstallCmd = packageManager === "yarn" ? "remove" : "uninstall";
145
+ const { stdout, stderr } = await execa(`${packageManager} ${uninstallCmd} ${packageName}`);
146
+ if (stderr) log.error(stderr);
147
+ if (process.env["VERBOSE"]) log.info(stdout);
163
148
  }
164
149
 
165
- const require = __node_cjsModule.createRequire(import.meta.url);
166
-
150
+ //#endregion
151
+ //#region src/bin/index.ts
167
152
  const args = parse(process.argv.slice(2), {
168
- default: {
169
- force: false,
170
- skipTanstackQuery: false,
171
- verbose: false
172
- },
173
- alias: {
174
- f: 'force',
175
- h: 'help',
176
- v: 'verbose',
177
- q: 'skipTanstackQuery'
178
- },
179
- boolean: true
153
+ default: {
154
+ force: false,
155
+ skipTanstackQuery: false,
156
+ verbose: false
157
+ },
158
+ alias: {
159
+ f: "force",
160
+ h: "help",
161
+ v: "verbose",
162
+ q: "skipTanstackQuery"
163
+ },
164
+ boolean: true
180
165
  });
181
- if (args.verbose) process.env['VERBOSE'] = '1';
166
+ if (args.verbose) process.env["VERBOSE"] = "1";
182
167
  intro(`tRPC Upgrade CLI v${version}`);
183
- if (args['help']) {
184
- log.info(`
168
+ if (args["help"]) {
169
+ log.info(`
185
170
  Usage: upgrade [options]
186
171
 
187
172
  Options:
@@ -190,52 +175,46 @@ Options:
190
175
  -v, --verbose Enable verbose logging
191
176
  -h, --help Show help
192
177
  `.trim());
193
- process.exit(0);
194
- }
195
- if (args.verbose) {
196
- log.info(`Running upgrade with args: ${JSON.stringify(args, null, 2)}`);
197
- }
198
- if (!args.force) {
199
- await assertCleanGitTree();
178
+ process.exit(0);
200
179
  }
180
+ if (args.verbose) log.info(`Running upgrade with args: ${JSON.stringify(args, null, 2)}`);
181
+ if (!args.force) await assertCleanGitTree();
201
182
  const transforms = await multiselect({
202
- message: 'Select transforms to run',
203
- options: [
204
- {
205
- value: require.resolve('@trpc/upgrade/transforms/hooksToOptions'),
206
- label: 'Migrate Hooks to xxxOptions API'
207
- },
208
- {
209
- value: require.resolve('@trpc/upgrade/transforms/provider'),
210
- label: 'Migrate context provider setup'
211
- }
212
- ]
183
+ message: "Select transforms to run",
184
+ options: [{
185
+ value: __require.resolve("@trpc/upgrade/transforms/hooksToOptions"),
186
+ label: "Migrate Hooks to xxxOptions API"
187
+ }, {
188
+ value: __require.resolve("@trpc/upgrade/transforms/provider"),
189
+ label: "Migrate context provider setup"
190
+ }]
213
191
  });
214
192
  if (isCancel(transforms)) process.exit(0);
215
- // Make sure provider transform runs first if it's selected
216
- const sortedTransforms = transforms.sort((a)=>a.includes('provider') ? -1 : 1);
193
+ const sortedTransforms = transforms.sort((a) => a.includes("provider") ? -1 : 1);
217
194
  const program = getProgram();
218
195
  const sourceFiles = program.getSourceFiles();
219
196
  const possibleReferences = findTRPCImportReferences(program);
220
197
  const trpcFile = possibleReferences.mostUsed.file;
221
198
  const trpcImportName = possibleReferences.importName;
222
199
  const commitedFiles = await filterIgnored(sourceFiles);
223
- for (const transform of sortedTransforms){
224
- log.step(`Running transform: ${basename(transform, extname(transform))}`);
225
- const { run } = await import('jscodeshift/src/Runner.js');
226
- await run(transform, commitedFiles, {
227
- ...args,
228
- trpcFile,
229
- trpcImportName
230
- });
231
- log.success(`Transform completed`);
200
+ for (const transform of sortedTransforms) {
201
+ log.step(`Running transform: ${basename(transform, extname(transform))}`);
202
+ const { run } = await import("jscodeshift/src/Runner.js");
203
+ await run(transform, commitedFiles, {
204
+ ...args,
205
+ trpcFile,
206
+ trpcImportName
207
+ });
208
+ log.success(`Transform completed`);
232
209
  }
233
210
  if (!args.skipTanstackQuery) {
234
- log.info('Installing @trpc/tanstack-react-query');
235
- await installPackage('@trpc/tanstack-react-query');
236
- log.success('@trpc/tanstack-react-query installed');
237
- log.info('Uninstalling @trpc/react-query');
238
- await uninstallPackage('@trpc/react-query');
239
- log.success('@trpc/react-query uninstalled');
211
+ log.info("Installing @trpc/tanstack-react-query");
212
+ await installPackage("@trpc/tanstack-react-query");
213
+ log.success("@trpc/tanstack-react-query installed");
214
+ log.info("Uninstalling @trpc/react-query");
215
+ await uninstallPackage("@trpc/react-query");
216
+ log.success("@trpc/react-query uninstalled");
240
217
  }
241
- outro('Upgrade complete! 🎉');
218
+ outro("Upgrade complete! 🎉");
219
+
220
+ //#endregion
@@ -1,365 +1,242 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
+ //#region src/lib/ast/modifiers.ts
3
4
  /**
4
- * Replaces the identifier for the root path key
5
- * of a member expression
6
- *
7
- * For dot notation like `rootKey.x.y.z` the AST
8
- * is constructed with the `rootKey` being nested deep
9
- * inside a wrapper MemberExpression holding `rootKey.x`
10
- * and so on
11
- *
12
- * This function helps replace the `rootKey` identifier with
13
- * the provided identifier node
14
- */ function replaceMemberExpressionRootIndentifier(j, expr, id) {
15
- if (j.Identifier.check(expr.object)) {
16
- expr.object = id;
17
- return true;
18
- }
19
- return !j.MemberExpression.check(expr.object) ? false : replaceMemberExpressionRootIndentifier(j, expr.object, id);
5
+ * Replaces the identifier for the root path key
6
+ * of a member expression
7
+ *
8
+ * For dot notation like `rootKey.x.y.z` the AST
9
+ * is constructed with the `rootKey` being nested deep
10
+ * inside a wrapper MemberExpression holding `rootKey.x`
11
+ * and so on
12
+ *
13
+ * This function helps replace the `rootKey` identifier with
14
+ * the provided identifier node
15
+ */
16
+ function replaceMemberExpressionRootIndentifier(j, expr, id) {
17
+ if (j.Identifier.check(expr.object)) {
18
+ expr.object = id;
19
+ return true;
20
+ }
21
+ return !j.MemberExpression.check(expr.object) ? false : replaceMemberExpressionRootIndentifier(j, expr.object, id);
20
22
  }
21
23
 
24
+ //#endregion
25
+ //#region src/lib/ast/walkers.ts
22
26
  /**
23
- * Walks the path upwards to look for the closest parent
24
- * of the mentioned type
25
- */ function findParentOfType(path, type) {
26
- if (!path.parent) {
27
- return false;
28
- }
29
- return type.check(path.node) ? path : findParentOfType(path.parentPath, type);
27
+ * Walks the path upwards to look for the closest parent
28
+ * of the mentioned type
29
+ */
30
+ function findParentOfType(path, type) {
31
+ if (!path.parent) return false;
32
+ return type.check(path.node) ? path : findParentOfType(path.parentPath, type);
30
33
  }
31
34
 
35
+ //#endregion
36
+ //#region src/transforms/hooksToOptions.ts
32
37
  const hookToOptions = {
33
- useQuery: {
34
- lib: '@tanstack/react-query',
35
- fn: 'queryOptions'
36
- },
37
- useSuspenseQuery: {
38
- lib: '@tanstack/react-query',
39
- fn: 'queryOptions'
40
- },
41
- useInfiniteQuery: {
42
- lib: '@tanstack/react-query',
43
- fn: 'infiniteQueryOptions'
44
- },
45
- useSuspenseInfiniteQuery: {
46
- lib: '@tanstack/react-query',
47
- fn: 'infiniteQueryOptions'
48
- },
49
- useMutation: {
50
- lib: '@tanstack/react-query',
51
- fn: 'mutationOptions'
52
- },
53
- useSubscription: {
54
- lib: '@trpc/tanstack-react-query',
55
- fn: 'subscriptionOptions'
56
- }
38
+ useQuery: {
39
+ lib: "@tanstack/react-query",
40
+ fn: "queryOptions"
41
+ },
42
+ useSuspenseQuery: {
43
+ lib: "@tanstack/react-query",
44
+ fn: "queryOptions"
45
+ },
46
+ useInfiniteQuery: {
47
+ lib: "@tanstack/react-query",
48
+ fn: "infiniteQueryOptions"
49
+ },
50
+ useSuspenseInfiniteQuery: {
51
+ lib: "@tanstack/react-query",
52
+ fn: "infiniteQueryOptions"
53
+ },
54
+ useMutation: {
55
+ lib: "@tanstack/react-query",
56
+ fn: "mutationOptions"
57
+ },
58
+ useSubscription: {
59
+ lib: "@trpc/tanstack-react-query",
60
+ fn: "subscriptionOptions"
61
+ }
57
62
  };
58
63
  /**
59
- * Map old proxy method to queryClient method
60
- * 1st item is the queryClient method, 2nd item is the filter/key method to use
61
- */ const utilMap = {
62
- fetch: [
63
- 'fetchQuery',
64
- 'queryOptions'
65
- ],
66
- fetchInfinite: [
67
- 'fetchInfiniteQuery',
68
- 'infiniteQueryOptions'
69
- ],
70
- prefetch: [
71
- 'prefetchQuery',
72
- 'queryOptions'
73
- ],
74
- prefetchInfinite: [
75
- 'prefetchInfiniteQuery',
76
- 'infiniteQueryOptions'
77
- ],
78
- ensureData: [
79
- 'ensureQueryData',
80
- 'queryOptions'
81
- ],
82
- invalidate: [
83
- 'invalidateQueries',
84
- 'DYNAMIC_FILTER'
85
- ],
86
- reset: [
87
- 'resetQueries',
88
- 'DYNAMIC_FILTER'
89
- ],
90
- refetch: [
91
- 'refetchQueries',
92
- 'DYNAMIC_FILTER'
93
- ],
94
- cancel: [
95
- 'cancelQueries',
96
- 'DYNAMIC_FILTER'
97
- ],
98
- setData: [
99
- 'setQueryData',
100
- 'queryKey'
101
- ],
102
- setInfiniteData: [
103
- 'setQueryData',
104
- 'infiniteQueryKey'
105
- ],
106
- getData: [
107
- 'getQueryData',
108
- 'queryKey'
109
- ],
110
- getInfiniteData: [
111
- 'getQueryData',
112
- 'infiniteQueryKey'
113
- ]
64
+ * Map old proxy method to queryClient method
65
+ * 1st item is the queryClient method, 2nd item is the filter/key method to use
66
+ */
67
+ const utilMap = {
68
+ fetch: ["fetchQuery", "queryOptions"],
69
+ fetchInfinite: ["fetchInfiniteQuery", "infiniteQueryOptions"],
70
+ prefetch: ["prefetchQuery", "queryOptions"],
71
+ prefetchInfinite: ["prefetchInfiniteQuery", "infiniteQueryOptions"],
72
+ ensureData: ["ensureQueryData", "queryOptions"],
73
+ invalidate: ["invalidateQueries", "DYNAMIC_FILTER"],
74
+ reset: ["resetQueries", "DYNAMIC_FILTER"],
75
+ refetch: ["refetchQueries", "DYNAMIC_FILTER"],
76
+ cancel: ["cancelQueries", "DYNAMIC_FILTER"],
77
+ setData: ["setQueryData", "queryKey"],
78
+ setInfiniteData: ["setQueryData", "infiniteQueryKey"],
79
+ getData: ["getQueryData", "queryKey"],
80
+ getInfiniteData: ["getQueryData", "infiniteQueryKey"]
114
81
  };
115
82
  function transform(file, api, options) {
116
- const { trpcImportName } = options;
117
- if (!trpcImportName) {
118
- throw new Error('trpcImportName is required');
119
- }
120
- const j = api.jscodeshift;
121
- const root = j(file.source);
122
- let dirtyFlag = false;
123
- // Traverse all functions, and _do stuff_
124
- root.find(j.FunctionDeclaration).forEach((path)=>{
125
- replaceHooksWithOptions(path);
126
- removeSuspenseDestructuring(path);
127
- migrateUseUtils(path);
128
- });
129
- root.find(j.ArrowFunctionExpression).forEach((path)=>{
130
- replaceHooksWithOptions(path);
131
- removeSuspenseDestructuring(path);
132
- migrateUseUtils(path);
133
- });
134
- if (dirtyFlag) {
135
- updateTRPCImport();
136
- }
137
- /**
138
- * === HELPER FUNCTIONS BELOW ===
139
- */ function isDeclarationInScope(path, name) {
140
- return j(path).find(j.VariableDeclarator, {
141
- id: {
142
- type: 'Identifier',
143
- name
144
- }
145
- }).size() > 0;
146
- }
147
- function ensureUseTRPCCall(path) {
148
- // Check if trpc is already declared in scope
149
- if (isDeclarationInScope(path, trpcImportName)) {
150
- return;
151
- }
152
- const variableDeclaration = j.variableDeclaration('const', [
153
- j.variableDeclarator(j.identifier(trpcImportName), j.callExpression(j.identifier('useTRPC'), []))
154
- ]);
155
- if (j.FunctionDeclaration.check(path.node)) {
156
- path.node.body.body.unshift(variableDeclaration);
157
- dirtyFlag = true;
158
- } else if (j.BlockStatement.check(path.node.body)) {
159
- path.node.body.body.unshift(variableDeclaration);
160
- dirtyFlag = true;
161
- }
162
- }
163
- function updateTRPCImport() {
164
- const specifier = root.find(j.ImportSpecifier, {
165
- imported: {
166
- name: trpcImportName
167
- }
168
- });
169
- if (specifier.size() > 0) {
170
- specifier.replaceWith(j.importSpecifier(j.identifier('useTRPC')));
171
- dirtyFlag = true;
172
- }
173
- }
174
- function ensureImported(lib, specifier) {
175
- if (root.find(j.ImportDeclaration, {
176
- source: {
177
- value: lib
178
- }
179
- }).find(j.ImportSpecifier, {
180
- imported: {
181
- name: specifier
182
- }
183
- }).size() === 0) {
184
- root.find(j.ImportDeclaration).at(-1).insertAfter(j.importDeclaration([
185
- j.importSpecifier(j.identifier(specifier))
186
- ], j.literal(lib)));
187
- dirtyFlag = true;
188
- }
189
- }
190
- function replaceHooksWithOptions(fnPath) {
191
- // REplace proxy-hooks with useX(options())
192
- for (const [hook, { fn, lib }] of Object.entries(hookToOptions)){
193
- j(fnPath).find(j.CallExpression, {
194
- callee: {
195
- property: {
196
- name: hook
197
- }
198
- }
199
- }).forEach((path)=>{
200
- const memberExpr = path.node.callee;
201
- if (!j.MemberExpression.check(memberExpr) || !j.Identifier.check(memberExpr.property)) {
202
- console.warn('Failed to identify hook call expression', path.node);
203
- return;
204
- }
205
- // Rename the hook to the options function
206
- memberExpr.property.name = fn;
207
- ensureUseTRPCCall(fnPath);
208
- // Wrap it in the hook call
209
- j(path).replaceWith(j.callExpression(j.identifier(hook), [
210
- path.node
211
- ]));
212
- ensureImported(lib, hook);
213
- dirtyFlag = true;
214
- });
215
- }
216
- }
217
- // Migrate trpc.useUtils() to useQueryClient()
218
- function migrateUseUtils(fnPath) {
219
- j(fnPath).find(j.CallExpression, {
220
- callee: {
221
- property: {
222
- name: (name)=>[
223
- 'useContext',
224
- 'useUtils'
225
- ].includes(name)
226
- }
227
- }
228
- }).forEach((path)=>{
229
- const isTRPCContextUtil = j.MemberExpression.check(path.value.callee) && j.Identifier.check(path.value.callee.object) && path.value.callee.object.name == trpcImportName;
230
- if (isTRPCContextUtil && j.VariableDeclarator.check(path.parentPath.node) && j.Identifier.check(path.parentPath.node.id)) {
231
- const oldIdentifier = path.parentPath.node.id;
232
- // Find all the references to `utils` and replace with `queryClient[helperMap](trpc.PATH.pathFilter())`
233
- root.find(j.Identifier, {
234
- name: oldIdentifier.name
235
- }).forEach((path)=>{
236
- if (j.MemberExpression.check(path.parent?.parent?.node) || j.CallExpression.check(path.parent?.parent?.node)) {
237
- const callExprPath = findParentOfType(path.parentPath, j.CallExpression);
238
- if (!callExprPath) {
239
- console.warn(`Failed to walk up the tree to find utilMethod call expression, on file: ${file.path}`, callExprPath, {
240
- start: path.node.loc?.start,
241
- end: path.node.loc?.end
242
- });
243
- return;
244
- }
245
- const callExpr = callExprPath.node;
246
- const memberExpr = callExpr.callee;
247
- if (!j.CallExpression.check(callExpr) || !j.MemberExpression.check(memberExpr)) {
248
- console.warn(`Failed to walk up the tree to find utilMethod with a \`trpc.PATH.<call>\`, on file: ${file.path}`, callExpr, {
249
- start: path.node.loc?.start,
250
- end: path.node.loc?.end
251
- });
252
- return;
253
- }
254
- if (!(j.Identifier.check(memberExpr.property) && memberExpr.property.name in utilMap)) {
255
- console.warn('Failed to identify utilMethod from proxy call expression', memberExpr);
256
- return;
257
- }
258
- // Replace util.PATH.proxyMethod()
259
- const proxyMethod = memberExpr.property.name;
260
- const replacedPath = replaceMemberExpressionRootIndentifier(j, memberExpr, j.identifier(trpcImportName));
261
- if (!replacedPath) {
262
- console.warn('Failed to wrap proxy call expression', memberExpr);
263
- }
264
- /**
265
- * If no input, use pathFilter
266
- * If input is undefined, use pathFilter
267
- * If input has cursor, use infiniteQueryFilter
268
- * Otherwise, use queryFilter
269
- */ const preferedFilter = utilMap[proxyMethod][1];
270
- const isNoArgs = !callExpr.arguments.length;
271
- const isUndefindInputArg = callExpr.arguments.length > 0 && j.Identifier.check(callExpr.arguments[0]) && callExpr.arguments[0].name === 'undefined';
272
- let argToForward = undefined;
273
- if (preferedFilter !== 'DYNAMIC_FILTER') {
274
- if (proxyMethod === 'setData' || proxyMethod === 'setInfiniteData') {
275
- // First arg goes into queryKey(), second is forwarded to the wrapped method
276
- // We can omit the first arg if it's undefined
277
- argToForward = callExpr.arguments[1];
278
- if (callExpr.arguments[0] && !isUndefindInputArg) {
279
- callExpr.arguments = [
280
- callExpr.arguments[0]
281
- ];
282
- } else {
283
- callExpr.arguments = [];
284
- }
285
- }
286
- memberExpr.property = j.identifier(preferedFilter);
287
- } else if (isNoArgs || isUndefindInputArg) {
288
- memberExpr.property = j.identifier('pathFilter');
289
- if (isUndefindInputArg) {
290
- callExpr.arguments.shift();
291
- }
292
- } else if (j.ObjectExpression.check(callExpr.arguments[0])) {
293
- if (callExpr.arguments[0].properties.find((p)=>j.ObjectProperty.check(p) && j.Identifier.check(p.key) && p.key.name === 'cursor')) {
294
- memberExpr.property = j.identifier('infiniteQueryFilter');
295
- } else {
296
- memberExpr.property = j.identifier('queryFilter');
297
- }
298
- }
299
- // Wrap it in queryClient.utilMethod()
300
- callExprPath.replace(j.memberExpression(j.identifier('queryClient'), j.callExpression(j.identifier(utilMap[proxyMethod][0]), [
301
- callExpr,
302
- ...argToForward ? [
303
- argToForward
304
- ] : []
305
- ])));
306
- ensureUseTRPCCall(fnPath);
307
- }
308
- });
309
- // Replace `const utils = trpc.useUtils()` with `const queryClient = useQueryClient()`
310
- // If `queryClient` is already declared, just remove the utils declaration
311
- if (isDeclarationInScope(fnPath, 'queryClient')) {
312
- j(path).remove();
313
- j(path.parentPath).remove();
314
- } else {
315
- j(path).replaceWith(j.callExpression(j.identifier('useQueryClient'), []));
316
- path.parentPath.node.id = j.identifier('queryClient');
317
- ensureImported('@tanstack/react-query', 'useQueryClient');
318
- }
319
- }
320
- dirtyFlag = true;
321
- });
322
- }
323
- function removeSuspenseDestructuring(path) {
324
- // Remove suspense query destructuring
325
- j(path).find(j.VariableDeclaration).forEach((path)=>{
326
- const declarator = j.VariableDeclarator.check(path.node.declarations[0]) ? path.node.declarations[0] : null;
327
- if (!j.CallExpression.check(declarator?.init) || !j.Identifier.check(declarator.init.callee) || ![
328
- 'useSuspenseQuery',
329
- 'useSuspenseInfiniteQuery'
330
- ].includes(declarator.init.callee.name)) {
331
- return;
332
- }
333
- const tuple = j.ArrayPattern.check(declarator?.id) ? declarator.id : null;
334
- const dataName = j.Identifier.check(tuple?.elements?.[0]) ? tuple.elements[0].name : null;
335
- const queryName = j.Identifier.check(tuple?.elements?.[1]) ? tuple.elements[1].name : null;
336
- const deepDestructure = j.ArrayPattern.check(declarator?.id) && j.ObjectPattern.check(tuple?.elements?.[0]) ? tuple?.elements?.[0] : null;
337
- if (queryName) {
338
- declarator.id = j.identifier(queryName);
339
- dirtyFlag = true;
340
- if (dataName) {
341
- j(path).insertAfter(j.variableDeclaration('const', [
342
- j.variableDeclarator(j.identifier(dataName), j.memberExpression(declarator.id, j.identifier('data')))
343
- ]));
344
- }
345
- } else if (dataName) {
346
- // const [dataName] = ... => const { data: dataName } = ...
347
- declarator.id = j.objectPattern([
348
- j.property('init', j.identifier('data'), j.identifier(dataName))
349
- ]);
350
- dirtyFlag = true;
351
- } else if (deepDestructure) {
352
- // const [{ dataName }] = ... => const { data: { dataName } } = ...
353
- declarator.id = j.objectPattern([
354
- j.property('init', j.identifier('data'), deepDestructure)
355
- ]);
356
- dirtyFlag = true;
357
- }
358
- });
359
- }
360
- return dirtyFlag ? root.toSource() : undefined;
83
+ const { trpcImportName } = options;
84
+ if (!trpcImportName) throw new Error("trpcImportName is required");
85
+ const j = api.jscodeshift;
86
+ const root = j(file.source);
87
+ let dirtyFlag = false;
88
+ root.find(j.FunctionDeclaration).forEach((path) => {
89
+ replaceHooksWithOptions(path);
90
+ removeSuspenseDestructuring(path);
91
+ migrateUseUtils(path);
92
+ });
93
+ root.find(j.ArrowFunctionExpression).forEach((path) => {
94
+ replaceHooksWithOptions(path);
95
+ removeSuspenseDestructuring(path);
96
+ migrateUseUtils(path);
97
+ });
98
+ if (dirtyFlag) updateTRPCImport();
99
+ /**
100
+ * === HELPER FUNCTIONS BELOW ===
101
+ */
102
+ function isDeclarationInScope(path, name) {
103
+ return j(path).find(j.VariableDeclarator, { id: {
104
+ type: "Identifier",
105
+ name
106
+ } }).size() > 0;
107
+ }
108
+ function ensureUseTRPCCall(path) {
109
+ if (isDeclarationInScope(path, trpcImportName)) return;
110
+ const variableDeclaration = j.variableDeclaration("const", [j.variableDeclarator(j.identifier(trpcImportName), j.callExpression(j.identifier("useTRPC"), []))]);
111
+ if (j.FunctionDeclaration.check(path.node)) {
112
+ path.node.body.body.unshift(variableDeclaration);
113
+ dirtyFlag = true;
114
+ } else if (j.BlockStatement.check(path.node.body)) {
115
+ path.node.body.body.unshift(variableDeclaration);
116
+ dirtyFlag = true;
117
+ }
118
+ }
119
+ function updateTRPCImport() {
120
+ const specifier = root.find(j.ImportSpecifier, { imported: { name: trpcImportName } });
121
+ if (specifier.size() > 0) {
122
+ specifier.replaceWith(j.importSpecifier(j.identifier("useTRPC")));
123
+ dirtyFlag = true;
124
+ }
125
+ }
126
+ function ensureImported(lib, specifier) {
127
+ if (root.find(j.ImportDeclaration, { source: { value: lib } }).find(j.ImportSpecifier, { imported: { name: specifier } }).size() === 0) {
128
+ root.find(j.ImportDeclaration).at(-1).insertAfter(j.importDeclaration([j.importSpecifier(j.identifier(specifier))], j.literal(lib)));
129
+ dirtyFlag = true;
130
+ }
131
+ }
132
+ function replaceHooksWithOptions(fnPath) {
133
+ for (const [hook, { fn, lib }] of Object.entries(hookToOptions)) j(fnPath).find(j.CallExpression, { callee: { property: { name: hook } } }).forEach((path) => {
134
+ const memberExpr = path.node.callee;
135
+ if (!j.MemberExpression.check(memberExpr) || !j.Identifier.check(memberExpr.property)) {
136
+ console.warn("Failed to identify hook call expression", path.node);
137
+ return;
138
+ }
139
+ memberExpr.property.name = fn;
140
+ ensureUseTRPCCall(fnPath);
141
+ j(path).replaceWith(j.callExpression(j.identifier(hook), [path.node]));
142
+ ensureImported(lib, hook);
143
+ dirtyFlag = true;
144
+ });
145
+ }
146
+ function migrateUseUtils(fnPath) {
147
+ j(fnPath).find(j.CallExpression, { callee: { property: { name: (name) => ["useContext", "useUtils"].includes(name) } } }).forEach((path) => {
148
+ const isTRPCContextUtil = j.MemberExpression.check(path.value.callee) && j.Identifier.check(path.value.callee.object) && path.value.callee.object.name == trpcImportName;
149
+ if (isTRPCContextUtil && j.VariableDeclarator.check(path.parentPath.node) && j.Identifier.check(path.parentPath.node.id)) {
150
+ const oldIdentifier = path.parentPath.node.id;
151
+ root.find(j.Identifier, { name: oldIdentifier.name }).forEach((path$1) => {
152
+ if (j.MemberExpression.check(path$1.parent?.parent?.node) || j.CallExpression.check(path$1.parent?.parent?.node)) {
153
+ const callExprPath = findParentOfType(path$1.parentPath, j.CallExpression);
154
+ if (!callExprPath) {
155
+ console.warn(`Failed to walk up the tree to find utilMethod call expression, on file: ${file.path}`, callExprPath, {
156
+ start: path$1.node.loc?.start,
157
+ end: path$1.node.loc?.end
158
+ });
159
+ return;
160
+ }
161
+ const callExpr = callExprPath.node;
162
+ const memberExpr = callExpr.callee;
163
+ if (!j.CallExpression.check(callExpr) || !j.MemberExpression.check(memberExpr)) {
164
+ console.warn(`Failed to walk up the tree to find utilMethod with a \`trpc.PATH.<call>\`, on file: ${file.path}`, callExpr, {
165
+ start: path$1.node.loc?.start,
166
+ end: path$1.node.loc?.end
167
+ });
168
+ return;
169
+ }
170
+ if (!(j.Identifier.check(memberExpr.property) && memberExpr.property.name in utilMap)) {
171
+ console.warn("Failed to identify utilMethod from proxy call expression", memberExpr);
172
+ return;
173
+ }
174
+ const proxyMethod = memberExpr.property.name;
175
+ const replacedPath = replaceMemberExpressionRootIndentifier(j, memberExpr, j.identifier(trpcImportName));
176
+ if (!replacedPath) console.warn("Failed to wrap proxy call expression", memberExpr);
177
+ /**
178
+ * If no input, use pathFilter
179
+ * If input is undefined, use pathFilter
180
+ * If input has cursor, use infiniteQueryFilter
181
+ * Otherwise, use queryFilter
182
+ */
183
+ const preferedFilter = utilMap[proxyMethod][1];
184
+ const isNoArgs = !callExpr.arguments.length;
185
+ const isUndefindInputArg = callExpr.arguments.length > 0 && j.Identifier.check(callExpr.arguments[0]) && callExpr.arguments[0].name === "undefined";
186
+ let argToForward = void 0;
187
+ if (preferedFilter !== "DYNAMIC_FILTER") {
188
+ if (proxyMethod === "setData" || proxyMethod === "setInfiniteData") {
189
+ argToForward = callExpr.arguments[1];
190
+ if (callExpr.arguments[0] && !isUndefindInputArg) callExpr.arguments = [callExpr.arguments[0]];
191
+ else callExpr.arguments = [];
192
+ }
193
+ memberExpr.property = j.identifier(preferedFilter);
194
+ } else if (isNoArgs || isUndefindInputArg) {
195
+ memberExpr.property = j.identifier("pathFilter");
196
+ if (isUndefindInputArg) callExpr.arguments.shift();
197
+ } else if (j.ObjectExpression.check(callExpr.arguments[0])) if (callExpr.arguments[0].properties.find((p) => j.ObjectProperty.check(p) && j.Identifier.check(p.key) && p.key.name === "cursor")) memberExpr.property = j.identifier("infiniteQueryFilter");
198
+ else memberExpr.property = j.identifier("queryFilter");
199
+ callExprPath.replace(j.memberExpression(j.identifier("queryClient"), j.callExpression(j.identifier(utilMap[proxyMethod][0]), [callExpr, ...argToForward ? [argToForward] : []])));
200
+ ensureUseTRPCCall(fnPath);
201
+ }
202
+ });
203
+ if (isDeclarationInScope(fnPath, "queryClient")) {
204
+ j(path).remove();
205
+ j(path.parentPath).remove();
206
+ } else {
207
+ j(path).replaceWith(j.callExpression(j.identifier("useQueryClient"), []));
208
+ path.parentPath.node.id = j.identifier("queryClient");
209
+ ensureImported("@tanstack/react-query", "useQueryClient");
210
+ }
211
+ }
212
+ dirtyFlag = true;
213
+ });
214
+ }
215
+ function removeSuspenseDestructuring(path) {
216
+ j(path).find(j.VariableDeclaration).forEach((path$1) => {
217
+ const declarator = j.VariableDeclarator.check(path$1.node.declarations[0]) ? path$1.node.declarations[0] : null;
218
+ if (!j.CallExpression.check(declarator?.init) || !j.Identifier.check(declarator.init.callee) || !["useSuspenseQuery", "useSuspenseInfiniteQuery"].includes(declarator.init.callee.name)) return;
219
+ const tuple = j.ArrayPattern.check(declarator?.id) ? declarator.id : null;
220
+ const dataName = j.Identifier.check(tuple?.elements?.[0]) ? tuple.elements[0].name : null;
221
+ const queryName = j.Identifier.check(tuple?.elements?.[1]) ? tuple.elements[1].name : null;
222
+ const deepDestructure = j.ArrayPattern.check(declarator?.id) && j.ObjectPattern.check(tuple?.elements?.[0]) ? tuple?.elements?.[0] : null;
223
+ if (queryName) {
224
+ declarator.id = j.identifier(queryName);
225
+ dirtyFlag = true;
226
+ if (dataName) j(path$1).insertAfter(j.variableDeclaration("const", [j.variableDeclarator(j.identifier(dataName), j.memberExpression(declarator.id, j.identifier("data")))]));
227
+ } else if (dataName) {
228
+ declarator.id = j.objectPattern([j.property("init", j.identifier("data"), j.identifier(dataName))]);
229
+ dirtyFlag = true;
230
+ } else if (deepDestructure) {
231
+ declarator.id = j.objectPattern([j.property("init", j.identifier("data"), deepDestructure)]);
232
+ dirtyFlag = true;
233
+ }
234
+ });
235
+ }
236
+ return dirtyFlag ? root.toSource() : void 0;
361
237
  }
362
- const parser = 'tsx';
238
+ const parser = "tsx";
363
239
 
240
+ //#endregion
364
241
  exports.default = transform;
365
- exports.parser = parser;
242
+ exports.parser = parser;
@@ -1,120 +1,71 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
2
 
3
+ //#region src/transforms/provider.ts
3
4
  function transform(file, api, options) {
4
- const { trpcImportName } = options;
5
- let routerName = undefined;
6
- const j = api.jscodeshift;
7
- const root = j(file.source);
8
- let dirtyFlag = false;
9
- // Find the variable declaration for `trpc`
10
- root.find(j.VariableDeclaration).forEach((path)=>{
11
- const declaration = path.node.declarations[0];
12
- if (j.Identifier.check(declaration.id) && declaration.id.name === trpcImportName) {
13
- if (j.CallExpression.check(declaration.init) && j.Identifier.check(declaration.init.callee) && declaration.init.callee.name === 'createTRPCReact') {
14
- // Get router name ( TODO : should probably get this from the TS compiler along with the import path)
15
- routerName = declaration.init.original?.typeParameters?.params?.[0]?.typeName?.name;
16
- // Replace the `createTRPCReact` call with `createTRPCContext`
17
- declaration.init.callee.name = 'createTRPCContext';
18
- // Destructure the result into `TRPCProvider` and `useTRPC`
19
- declaration.id = j.objectPattern([
20
- j.property.from({
21
- kind: 'init',
22
- key: j.identifier('TRPCProvider'),
23
- value: j.identifier('TRPCProvider'),
24
- shorthand: true
25
- }),
26
- j.property.from({
27
- kind: 'init',
28
- key: j.identifier('useTRPC'),
29
- value: j.identifier('useTRPC'),
30
- shorthand: true
31
- })
32
- ]);
33
- dirtyFlag = true;
34
- }
35
- }
36
- });
37
- // Update the import statement if transformation was successful
38
- if (dirtyFlag) {
39
- root.find(j.ImportDeclaration, {
40
- source: {
41
- value: '@trpc/react-query'
42
- }
43
- }).forEach((path)=>{
44
- path.node.source.value = '@trpc/tanstack-react-query';
45
- path.node.specifiers?.forEach((specifier)=>{
46
- if (j.ImportSpecifier.check(specifier) && specifier.imported.name === 'createTRPCReact') {
47
- specifier.imported.name = 'createTRPCContext';
48
- }
49
- });
50
- });
51
- }
52
- // Replace trpc.createClient with createTRPCClient<TRouter>
53
- root.find(j.CallExpression, {
54
- callee: {
55
- object: {
56
- name: trpcImportName
57
- },
58
- property: {
59
- name: 'createClient'
60
- }
61
- }
62
- }).forEach((path)=>{
63
- path.node.callee = j.identifier('createTRPCClient');
64
- dirtyFlag = true;
65
- if (routerName) {
66
- path.node.typeParameters = j.tsTypeParameterInstantiation([
67
- j.tsTypeReference(j.identifier(routerName))
68
- ]);
69
- }
70
- });
71
- // Replace <trpc.Provider client={...} with <TRPCProvider trpcClient={...}
72
- root.find(j.JSXElement, {
73
- openingElement: {
74
- name: {
75
- object: {
76
- name: trpcImportName
77
- },
78
- property: {
79
- name: 'Provider'
80
- }
81
- }
82
- }
83
- }).forEach((path)=>{
84
- path.node.openingElement.name = j.jsxIdentifier('TRPCProvider');
85
- if (path.node.closingElement) {
86
- path.node.closingElement.name = j.jsxIdentifier('TRPCProvider');
87
- }
88
- path.node.openingElement.attributes?.forEach((attr)=>{
89
- if (j.JSXAttribute.check(attr) && attr.name.name === 'client') {
90
- attr.name.name = 'trpcClient';
91
- }
92
- });
93
- dirtyFlag = true;
94
- });
95
- // Update imports if transformations were applied
96
- if (dirtyFlag) {
97
- // Add createTRPCClient to the import from '@trpc/client'
98
- root.find(j.ImportDeclaration, {
99
- source: {
100
- value: '@trpc/client'
101
- }
102
- }).forEach((path)=>{
103
- const createTRPCClientImport = j.importSpecifier(j.identifier('createTRPCClient'));
104
- path.node.specifiers?.push(createTRPCClientImport);
105
- });
106
- // Replace trpc import with TRPCProvider
107
- root.find(j.ImportSpecifier, {
108
- imported: {
109
- name: trpcImportName
110
- }
111
- }).forEach((path)=>{
112
- path.node.name = j.identifier('TRPCProvider');
113
- });
114
- }
115
- return dirtyFlag ? root.toSource() : undefined;
5
+ const { trpcImportName } = options;
6
+ let routerName = void 0;
7
+ const j = api.jscodeshift;
8
+ const root = j(file.source);
9
+ let dirtyFlag = false;
10
+ root.find(j.VariableDeclaration).forEach((path) => {
11
+ const declaration = path.node.declarations[0];
12
+ if (j.Identifier.check(declaration.id) && declaration.id.name === trpcImportName) {
13
+ if (j.CallExpression.check(declaration.init) && j.Identifier.check(declaration.init.callee) && declaration.init.callee.name === "createTRPCReact") {
14
+ routerName = declaration.init.original?.typeParameters?.params?.[0]?.typeName?.name;
15
+ declaration.init.callee.name = "createTRPCContext";
16
+ declaration.id = j.objectPattern([j.property.from({
17
+ kind: "init",
18
+ key: j.identifier("TRPCProvider"),
19
+ value: j.identifier("TRPCProvider"),
20
+ shorthand: true
21
+ }), j.property.from({
22
+ kind: "init",
23
+ key: j.identifier("useTRPC"),
24
+ value: j.identifier("useTRPC"),
25
+ shorthand: true
26
+ })]);
27
+ dirtyFlag = true;
28
+ }
29
+ }
30
+ });
31
+ if (dirtyFlag) root.find(j.ImportDeclaration, { source: { value: "@trpc/react-query" } }).forEach((path) => {
32
+ path.node.source.value = "@trpc/tanstack-react-query";
33
+ path.node.specifiers?.forEach((specifier) => {
34
+ if (j.ImportSpecifier.check(specifier) && specifier.imported.name === "createTRPCReact") specifier.imported.name = "createTRPCContext";
35
+ });
36
+ });
37
+ root.find(j.CallExpression, { callee: {
38
+ object: { name: trpcImportName },
39
+ property: { name: "createClient" }
40
+ } }).forEach((path) => {
41
+ path.node.callee = j.identifier("createTRPCClient");
42
+ dirtyFlag = true;
43
+ if (routerName) path.node.typeParameters = j.tsTypeParameterInstantiation([j.tsTypeReference(j.identifier(routerName))]);
44
+ });
45
+ root.find(j.JSXElement, { openingElement: { name: {
46
+ object: { name: trpcImportName },
47
+ property: { name: "Provider" }
48
+ } } }).forEach((path) => {
49
+ path.node.openingElement.name = j.jsxIdentifier("TRPCProvider");
50
+ if (path.node.closingElement) path.node.closingElement.name = j.jsxIdentifier("TRPCProvider");
51
+ path.node.openingElement.attributes?.forEach((attr) => {
52
+ if (j.JSXAttribute.check(attr) && attr.name.name === "client") attr.name.name = "trpcClient";
53
+ });
54
+ dirtyFlag = true;
55
+ });
56
+ if (dirtyFlag) {
57
+ root.find(j.ImportDeclaration, { source: { value: "@trpc/client" } }).forEach((path) => {
58
+ const createTRPCClientImport = j.importSpecifier(j.identifier("createTRPCClient"));
59
+ path.node.specifiers?.push(createTRPCClientImport);
60
+ });
61
+ root.find(j.ImportSpecifier, { imported: { name: trpcImportName } }).forEach((path) => {
62
+ path.node.name = j.identifier("TRPCProvider");
63
+ });
64
+ }
65
+ return dirtyFlag ? root.toSource() : void 0;
116
66
  }
117
- const parser = 'tsx';
67
+ const parser = "tsx";
118
68
 
69
+ //#endregion
119
70
  exports.default = transform;
120
- exports.parser = parser;
71
+ exports.parser = parser;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/upgrade",
3
- "version": "11.3.1",
3
+ "version": "11.3.2-canary.2+b0426132b",
4
4
  "description": "Upgrade scripts for tRPC",
5
5
  "author": "juliusmarminge",
6
6
  "license": "MIT",
@@ -21,7 +21,7 @@
21
21
  }
22
22
  },
23
23
  "scripts": {
24
- "build": "bunchee"
24
+ "build": "tsdown"
25
25
  },
26
26
  "files": [
27
27
  "dist",
@@ -39,15 +39,15 @@
39
39
  },
40
40
  "devDependencies": {
41
41
  "@tanstack/react-query": "^5.80.3",
42
- "@trpc/client": "11.3.1",
43
- "@trpc/react-query": "11.3.1",
44
- "@trpc/server": "11.3.1",
45
- "@trpc/tanstack-react-query": "11.3.1",
42
+ "@trpc/client": "11.3.2-canary.2+b0426132b",
43
+ "@trpc/react-query": "11.3.2-canary.2+b0426132b",
44
+ "@trpc/server": "11.3.2-canary.2+b0426132b",
45
+ "@trpc/tanstack-react-query": "11.3.2-canary.2+b0426132b",
46
46
  "@types/jscodeshift": "0.12.0",
47
47
  "@types/node": "^22.13.5",
48
- "bunchee": "6.5.1",
49
48
  "react": "^19.1.0",
50
49
  "react-dom": "^19.1.0",
50
+ "tsdown": "0.12.7",
51
51
  "zod": "^3.25.51"
52
52
  },
53
53
  "publishConfig": {
@@ -56,5 +56,5 @@
56
56
  "funding": [
57
57
  "https://trpc.io/sponsor"
58
58
  ],
59
- "gitHead": "c97573dd72086529c3f26dcc5e96d8152337b7f7"
59
+ "gitHead": "b0426132b53af5b3a679063522429e5842f577e4"
60
60
  }