@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 +174 -195
- package/dist/transforms/hooksToOptions.cjs +226 -349
- package/dist/transforms/provider.cjs +65 -114
- package/package.json +8 -8
package/dist/bin.js
CHANGED
|
@@ -1,187 +1,172 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
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
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
166
|
-
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/bin/index.ts
|
|
167
152
|
const args = parse(process.argv.slice(2), {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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[
|
|
166
|
+
if (args.verbose) process.env["VERBOSE"] = "1";
|
|
182
167
|
intro(`tRPC Upgrade CLI v${version}`);
|
|
183
|
-
if (args[
|
|
184
|
-
|
|
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
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
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
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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(
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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 =
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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 =
|
|
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.
|
|
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": "
|
|
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.
|
|
43
|
-
"@trpc/react-query": "11.3.
|
|
44
|
-
"@trpc/server": "11.3.
|
|
45
|
-
"@trpc/tanstack-react-query": "11.3.
|
|
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": "
|
|
59
|
+
"gitHead": "b0426132b53af5b3a679063522429e5842f577e4"
|
|
60
60
|
}
|