@trpc/upgrade 0.0.0-alpha.29 → 0.0.0-alpha.30
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.cjs
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var args = require('@bomb.sh/args');
|
|
3
|
+
var p = require('@clack/prompts');
|
|
4
|
+
var ts = require('typescript');
|
|
5
|
+
var Path = require('path');
|
|
6
|
+
var CP = require('node:child_process');
|
|
7
|
+
var Util = require('node:util');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n.default = e;
|
|
24
|
+
return n;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var p__namespace = /*#__PURE__*/_interopNamespace(p);
|
|
28
|
+
var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
|
|
29
|
+
var Path__namespace = /*#__PURE__*/_interopNamespace(Path);
|
|
30
|
+
var CP__namespace = /*#__PURE__*/_interopNamespace(CP);
|
|
31
|
+
var Util__namespace = /*#__PURE__*/_interopNamespace(Util);
|
|
32
|
+
|
|
33
|
+
var version = "0.0.0-alpha.29";
|
|
34
|
+
|
|
35
|
+
function getProgram(args) {
|
|
36
|
+
const configFile = ts__namespace.findConfigFile(process.cwd(), (filepath)=>ts__namespace.sys.fileExists(filepath));
|
|
37
|
+
if (!configFile) {
|
|
38
|
+
p__namespace.log.error('No tsconfig found');
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
if (args.verbose) {
|
|
42
|
+
p__namespace.log.info(`Using tsconfig: ${configFile}`);
|
|
43
|
+
}
|
|
44
|
+
const { config } = ts__namespace.readConfigFile(configFile, (filepath)=>ts__namespace.sys.readFile(filepath));
|
|
45
|
+
const parsedConfig = ts__namespace.parseJsonConfigFileContent(config, ts__namespace.sys, process.cwd());
|
|
46
|
+
const program = ts__namespace.createProgram({
|
|
47
|
+
options: parsedConfig.options,
|
|
48
|
+
rootNames: parsedConfig.fileNames,
|
|
49
|
+
configFileParsingDiagnostics: parsedConfig.errors
|
|
50
|
+
});
|
|
51
|
+
return program;
|
|
52
|
+
}
|
|
53
|
+
function findSourceAndImportName(program) {
|
|
54
|
+
const files = program.getSourceFiles().filter((sourceFile)=>{
|
|
55
|
+
if (sourceFile.isDeclarationFile) return false;
|
|
56
|
+
let found = false;
|
|
57
|
+
ts__namespace.forEachChild(sourceFile, (node)=>{
|
|
58
|
+
if (!found && ts__namespace.isImportDeclaration(node)) {
|
|
59
|
+
const { moduleSpecifier } = node;
|
|
60
|
+
if (ts__namespace.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.includes('@trpc/react-query')) {
|
|
61
|
+
found = true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return found;
|
|
66
|
+
});
|
|
67
|
+
let importName = 'trpc';
|
|
68
|
+
files.forEach((sourceFile)=>{
|
|
69
|
+
ts__namespace.forEachChild(sourceFile, (node)=>{
|
|
70
|
+
if (ts__namespace.isVariableStatement(node) && node.modifiers?.some((mod)=>mod.getText(sourceFile) === 'export')) {
|
|
71
|
+
node.declarationList.declarations.forEach((declaration)=>{
|
|
72
|
+
if (ts__namespace.isVariableDeclaration(declaration) && declaration.initializer && ts__namespace.isCallExpression(declaration.initializer) && ts__namespace.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.getText(sourceFile) === 'createTRPCReact') {
|
|
73
|
+
importName = declaration.name.getText(sourceFile);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
files: files.map((d)=>d.fileName),
|
|
81
|
+
importName
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function findTRPCImportReferences(program) {
|
|
85
|
+
const { files: filesImportingTRPC, importName } = findSourceAndImportName(program);
|
|
86
|
+
const trpcReferenceSpecifiers = new Map();
|
|
87
|
+
program.getSourceFiles().forEach((sourceFile)=>{
|
|
88
|
+
if (sourceFile.isDeclarationFile) return;
|
|
89
|
+
ts__namespace.forEachChild(sourceFile, (node)=>{
|
|
90
|
+
if (ts__namespace.isImportDeclaration(node) && ts__namespace.isStringLiteral(node.moduleSpecifier)) {
|
|
91
|
+
const resolved = ts__namespace.resolveModuleName(node.moduleSpecifier.text, sourceFile.fileName, program.getCompilerOptions(), ts__namespace.sys);
|
|
92
|
+
if (resolved.resolvedModule && filesImportingTRPC.includes(resolved.resolvedModule.resolvedFileName)) {
|
|
93
|
+
trpcReferenceSpecifiers.set(resolved.resolvedModule.resolvedFileName, node.moduleSpecifier.text);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
const counts = {};
|
|
99
|
+
let currentMax = 0;
|
|
100
|
+
const mostUsed = {
|
|
101
|
+
file: ''
|
|
102
|
+
};
|
|
103
|
+
[
|
|
104
|
+
...trpcReferenceSpecifiers.values()
|
|
105
|
+
].forEach((specifier)=>{
|
|
106
|
+
counts[specifier] = (counts[specifier] || 0) + 1;
|
|
107
|
+
if (counts[specifier] > currentMax) {
|
|
108
|
+
currentMax = counts[specifier];
|
|
109
|
+
mostUsed.file = specifier;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
return {
|
|
113
|
+
importName,
|
|
114
|
+
mostUsed,
|
|
115
|
+
all: Object.fromEntries(trpcReferenceSpecifiers.entries())
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const execa = Util__namespace.promisify(CP__namespace.exec);
|
|
120
|
+
|
|
121
|
+
async function assertCleanGitTree() {
|
|
122
|
+
const { stdout } = await execa('git status');
|
|
123
|
+
if (!stdout.includes('nothing to commit')) {
|
|
124
|
+
p__namespace.cancel('Git tree is not clean, please commit your changes and try again, or run with `--force`');
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function filterIgnored(files) {
|
|
129
|
+
const { stdout } = await execa('git check-ignore **/*');
|
|
130
|
+
const ignores = stdout.split('\n');
|
|
131
|
+
if (process.env.VERBOSE) {
|
|
132
|
+
p__namespace.log.info(`cwd: ${process.cwd()}`);
|
|
133
|
+
p__namespace.log.info(`All files in program: ${files.map((file)=>file.fileName).join(', ')}`);
|
|
134
|
+
p__namespace.log.info(`Ignored files: ${ignores.join(', ')}`);
|
|
135
|
+
}
|
|
136
|
+
// Ignore "common files"
|
|
137
|
+
const filteredSourcePaths = files.filter((source)=>source.fileName.startsWith(Path__namespace.resolve()) && // only look ahead of current directory
|
|
138
|
+
!source.fileName.includes('/trpc/packages/') && // relative paths when running codemod locally
|
|
139
|
+
!source.fileName.includes('/node_modules/') && // always ignore node_modules
|
|
140
|
+
!ignores.includes(source.fileName)).map((source)=>source.fileName);
|
|
141
|
+
if (process.env.VERBOSE) {
|
|
142
|
+
p__namespace.log.info(`Filtered files: ${filteredSourcePaths.join(', ')}`);
|
|
143
|
+
}
|
|
144
|
+
return filteredSourcePaths;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function getPackageManager() {
|
|
148
|
+
const userAgent = process.env.npm_config_user_agent;
|
|
149
|
+
if (userAgent?.startsWith('pnpm')) return 'pnpm';
|
|
150
|
+
if (userAgent?.startsWith('yarn')) return 'yarn';
|
|
151
|
+
if (userAgent?.startsWith('bun')) return 'bun';
|
|
152
|
+
return 'npm';
|
|
153
|
+
}
|
|
154
|
+
async function installPackage(packageName) {
|
|
155
|
+
const packageManager = getPackageManager();
|
|
156
|
+
const installCmd = packageManager === 'yarn' ? 'add' : 'install';
|
|
157
|
+
const { stdout, stderr } = await execa(`${packageManager} ${installCmd} ${packageName}`);
|
|
158
|
+
if (stderr) {
|
|
159
|
+
p__namespace.log.error(stderr);
|
|
160
|
+
}
|
|
161
|
+
p__namespace.log.info(stdout);
|
|
162
|
+
}
|
|
163
|
+
async function uninstallPackage(packageName) {
|
|
164
|
+
const packageManager = getPackageManager();
|
|
165
|
+
const uninstallCmd = packageManager === 'yarn' ? 'remove' : 'uninstall';
|
|
166
|
+
const { stdout, stderr } = await execa(`${packageManager} ${uninstallCmd} ${packageName}`);
|
|
167
|
+
if (stderr) {
|
|
168
|
+
p__namespace.log.error(stderr);
|
|
169
|
+
}
|
|
170
|
+
p__namespace.log.info(stdout);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
void (async ()=>{
|
|
174
|
+
const args$1 = args.parse(process.argv.slice(2), {
|
|
175
|
+
default: {
|
|
176
|
+
force: false,
|
|
177
|
+
skipTanstackQuery: false,
|
|
178
|
+
verbose: false
|
|
179
|
+
},
|
|
180
|
+
alias: {
|
|
181
|
+
f: 'force',
|
|
182
|
+
h: 'help',
|
|
183
|
+
v: 'verbose',
|
|
184
|
+
q: 'skipTanstackQuery'
|
|
185
|
+
},
|
|
186
|
+
boolean: true
|
|
187
|
+
});
|
|
188
|
+
p.intro(`tRPC Upgrade CLI v${version}`);
|
|
189
|
+
if (args$1.help) {
|
|
190
|
+
p.log.info(`
|
|
191
|
+
Usage: upgrade [options]
|
|
192
|
+
|
|
193
|
+
Options:
|
|
194
|
+
-f, --force Skip git status check, use with caution
|
|
195
|
+
-q, --skipTanstackQuery Skip installing @trpc/tanstack-react-query package
|
|
196
|
+
-v, --verbose Enable verbose logging
|
|
197
|
+
-h, --help Show help
|
|
198
|
+
`.trim());
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
if (args$1.verbose) {
|
|
202
|
+
p.log.info(`Running upgrade with args: ${JSON.stringify(args$1, null, 2)}`);
|
|
203
|
+
}
|
|
204
|
+
if (!args$1.force) {
|
|
205
|
+
await assertCleanGitTree();
|
|
206
|
+
}
|
|
207
|
+
const transforms = await p.multiselect({
|
|
208
|
+
message: 'Select transforms to run',
|
|
209
|
+
options: [
|
|
210
|
+
{
|
|
211
|
+
value: require.resolve('@trpc/upgrade/transforms/hooksToOptions'),
|
|
212
|
+
label: 'Migrate Hooks to xxxOptions API'
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
value: require.resolve('@trpc/upgrade/transforms/provider'),
|
|
216
|
+
label: 'Migrate context provider setup'
|
|
217
|
+
}
|
|
218
|
+
]
|
|
219
|
+
});
|
|
220
|
+
if (p.isCancel(transforms)) process.exit(0);
|
|
221
|
+
// Make sure provider transform runs first if it's selected
|
|
222
|
+
const sortedTransforms = transforms.sort((a)=>a.includes('provider') ? -1 : 1);
|
|
223
|
+
const program = getProgram(args$1);
|
|
224
|
+
const sourceFiles = program.getSourceFiles();
|
|
225
|
+
const possibleReferences = findTRPCImportReferences(program);
|
|
226
|
+
const trpcFile = possibleReferences.mostUsed.file;
|
|
227
|
+
const trpcImportName = possibleReferences.importName;
|
|
228
|
+
const commitedFiles = await filterIgnored(sourceFiles);
|
|
229
|
+
for (const transform of sortedTransforms){
|
|
230
|
+
p.log.info(`Running transform: ${transform}`);
|
|
231
|
+
const { run } = await import('jscodeshift/src/Runner.js');
|
|
232
|
+
await run(transform, commitedFiles, {
|
|
233
|
+
...args$1,
|
|
234
|
+
trpcFile,
|
|
235
|
+
trpcImportName
|
|
236
|
+
});
|
|
237
|
+
p.log.info(`Transform ${transform} completed`);
|
|
238
|
+
}
|
|
239
|
+
if (!args$1.skipTanstackQuery) {
|
|
240
|
+
p.log.info('Installing @trpc/tanstack-react-query');
|
|
241
|
+
await installPackage('@trpc/tanstack-react-query');
|
|
242
|
+
p.log.success('@trpc/tanstack-react-query installed');
|
|
243
|
+
p.log.info('Uninstalling @trpc/react-query');
|
|
244
|
+
await uninstallPackage('@trpc/react-query');
|
|
245
|
+
p.log.success('@trpc/react-query uninstalled');
|
|
246
|
+
}
|
|
247
|
+
p.outro('Upgrade complete! 🎉');
|
|
248
|
+
})();
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Replaces the identifier for the root path key
|
|
3
5
|
* of a member expression
|
|
@@ -259,4 +261,5 @@ function transform(file, api, options) {
|
|
|
259
261
|
}
|
|
260
262
|
const parser = 'tsx';
|
|
261
263
|
|
|
262
|
-
|
|
264
|
+
exports.default = transform;
|
|
265
|
+
exports.parser = parser;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
1
3
|
function transform(file, api, options) {
|
|
2
4
|
const { trpcImportName } = options;
|
|
3
5
|
let routerName = undefined;
|
|
@@ -114,4 +116,5 @@ function transform(file, api, options) {
|
|
|
114
116
|
}
|
|
115
117
|
const parser = 'tsx';
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
exports.default = transform;
|
|
120
|
+
exports.parser = parser;
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trpc/upgrade",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.30",
|
|
4
4
|
"description": "Upgrade scripts for tRPC",
|
|
5
5
|
"author": "juliusmarminge",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"
|
|
8
|
-
"bin": "./dist/bin.js",
|
|
7
|
+
"bin": "./dist/bin.cjs",
|
|
9
8
|
"homepage": "https://trpc.io",
|
|
10
9
|
"repository": {
|
|
11
10
|
"type": "git",
|
|
@@ -14,10 +13,10 @@
|
|
|
14
13
|
},
|
|
15
14
|
"exports": {
|
|
16
15
|
"./transforms/hooksToOptions": {
|
|
17
|
-
"default": "./dist/transforms/hooksToOptions.
|
|
16
|
+
"default": "./dist/transforms/hooksToOptions.cjs"
|
|
18
17
|
},
|
|
19
18
|
"./transforms/provider": {
|
|
20
|
-
"default": "./dist/transforms/provider.
|
|
19
|
+
"default": "./dist/transforms/provider.cjs"
|
|
21
20
|
}
|
|
22
21
|
},
|
|
23
22
|
"files": [
|
package/src/bin/index.ts
CHANGED
|
@@ -6,26 +6,27 @@ import { findTRPCImportReferences, getProgram } from '../lib/ast/scanners';
|
|
|
6
6
|
import { assertCleanGitTree, filterIgnored } from '../lib/git';
|
|
7
7
|
import { installPackage, uninstallPackage } from '../lib/pkgmgr';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
void (async () => {
|
|
10
|
+
const args = parse(process.argv.slice(2), {
|
|
11
|
+
default: {
|
|
12
|
+
force: false,
|
|
13
|
+
skipTanstackQuery: false,
|
|
14
|
+
verbose: false,
|
|
15
|
+
},
|
|
16
|
+
alias: {
|
|
17
|
+
f: 'force',
|
|
18
|
+
h: 'help',
|
|
19
|
+
v: 'verbose',
|
|
20
|
+
q: 'skipTanstackQuery',
|
|
21
|
+
},
|
|
22
|
+
boolean: true,
|
|
23
|
+
});
|
|
23
24
|
|
|
24
|
-
intro(`tRPC Upgrade CLI v${version}`);
|
|
25
|
+
intro(`tRPC Upgrade CLI v${version}`);
|
|
25
26
|
|
|
26
|
-
if (args.help) {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
if (args.help) {
|
|
28
|
+
log.info(
|
|
29
|
+
`
|
|
29
30
|
Usage: upgrade [options]
|
|
30
31
|
|
|
31
32
|
Options:
|
|
@@ -34,65 +35,66 @@ Options:
|
|
|
34
35
|
-v, --verbose Enable verbose logging
|
|
35
36
|
-h, --help Show help
|
|
36
37
|
`.trim(),
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
38
|
+
);
|
|
39
|
+
process.exit(0);
|
|
40
|
+
}
|
|
40
41
|
|
|
41
|
-
if (args.verbose) {
|
|
42
|
-
|
|
43
|
-
}
|
|
42
|
+
if (args.verbose) {
|
|
43
|
+
log.info(`Running upgrade with args: ${JSON.stringify(args, null, 2)}`);
|
|
44
|
+
}
|
|
44
45
|
|
|
45
|
-
if (!args.force) {
|
|
46
|
-
|
|
47
|
-
}
|
|
46
|
+
if (!args.force) {
|
|
47
|
+
await assertCleanGitTree();
|
|
48
|
+
}
|
|
48
49
|
|
|
49
|
-
const transforms = await multiselect({
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
});
|
|
62
|
-
if (isCancel(transforms)) process.exit(0);
|
|
50
|
+
const transforms = await multiselect({
|
|
51
|
+
message: 'Select transforms to run',
|
|
52
|
+
options: [
|
|
53
|
+
{
|
|
54
|
+
value: require.resolve('@trpc/upgrade/transforms/hooksToOptions'),
|
|
55
|
+
label: 'Migrate Hooks to xxxOptions API',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: require.resolve('@trpc/upgrade/transforms/provider'),
|
|
59
|
+
label: 'Migrate context provider setup',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
if (isCancel(transforms)) process.exit(0);
|
|
63
64
|
|
|
64
|
-
// Make sure provider transform runs first if it's selected
|
|
65
|
-
const sortedTransforms = transforms.sort((a) =>
|
|
66
|
-
|
|
67
|
-
);
|
|
65
|
+
// Make sure provider transform runs first if it's selected
|
|
66
|
+
const sortedTransforms = transforms.sort((a) =>
|
|
67
|
+
a.includes('provider') ? -1 : 1,
|
|
68
|
+
);
|
|
68
69
|
|
|
69
|
-
const program = getProgram(args);
|
|
70
|
-
const sourceFiles = program.getSourceFiles();
|
|
71
|
-
const possibleReferences = findTRPCImportReferences(program);
|
|
72
|
-
const trpcFile = possibleReferences.mostUsed.file;
|
|
73
|
-
const trpcImportName = possibleReferences.importName;
|
|
70
|
+
const program = getProgram(args);
|
|
71
|
+
const sourceFiles = program.getSourceFiles();
|
|
72
|
+
const possibleReferences = findTRPCImportReferences(program);
|
|
73
|
+
const trpcFile = possibleReferences.mostUsed.file;
|
|
74
|
+
const trpcImportName = possibleReferences.importName;
|
|
74
75
|
|
|
75
|
-
const commitedFiles = await filterIgnored(sourceFiles);
|
|
76
|
+
const commitedFiles = await filterIgnored(sourceFiles);
|
|
76
77
|
|
|
77
|
-
for (const transform of sortedTransforms) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
78
|
+
for (const transform of sortedTransforms) {
|
|
79
|
+
log.info(`Running transform: ${transform}`);
|
|
80
|
+
const { run } = await import('jscodeshift/src/Runner.js');
|
|
81
|
+
await run(transform, commitedFiles, {
|
|
82
|
+
...args,
|
|
83
|
+
trpcFile,
|
|
84
|
+
trpcImportName,
|
|
85
|
+
});
|
|
86
|
+
log.info(`Transform ${transform} completed`);
|
|
87
|
+
}
|
|
87
88
|
|
|
88
|
-
if (!args.skipTanstackQuery) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
if (!args.skipTanstackQuery) {
|
|
90
|
+
log.info('Installing @trpc/tanstack-react-query');
|
|
91
|
+
await installPackage('@trpc/tanstack-react-query');
|
|
92
|
+
log.success('@trpc/tanstack-react-query installed');
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
94
|
+
log.info('Uninstalling @trpc/react-query');
|
|
95
|
+
await uninstallPackage('@trpc/react-query');
|
|
96
|
+
log.success('@trpc/react-query uninstalled');
|
|
97
|
+
}
|
|
97
98
|
|
|
98
|
-
outro('Upgrade complete! 🎉');
|
|
99
|
+
outro('Upgrade complete! 🎉');
|
|
100
|
+
})();
|
package/dist/bin.js
DELETED
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { parse } from '@bomb.sh/args';
|
|
3
|
-
import * as p from '@clack/prompts';
|
|
4
|
-
import { intro, log, multiselect, isCancel, outro } from '@clack/prompts';
|
|
5
|
-
import * as ts from 'typescript';
|
|
6
|
-
import * as Path from 'path';
|
|
7
|
-
import * as CP from 'node:child_process';
|
|
8
|
-
import * as Util from 'node:util';
|
|
9
|
-
import __node_cjsModule from 'node:module';
|
|
10
|
-
|
|
11
|
-
var version = "0.0.0-alpha.28";
|
|
12
|
-
|
|
13
|
-
function getProgram(args) {
|
|
14
|
-
const configFile = ts.findConfigFile(process.cwd(), (filepath)=>ts.sys.fileExists(filepath));
|
|
15
|
-
if (!configFile) {
|
|
16
|
-
p.log.error('No tsconfig found');
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
if (args.verbose) {
|
|
20
|
-
p.log.info(`Using tsconfig: ${configFile}`);
|
|
21
|
-
}
|
|
22
|
-
const { config } = ts.readConfigFile(configFile, (filepath)=>ts.sys.readFile(filepath));
|
|
23
|
-
const parsedConfig = ts.parseJsonConfigFileContent(config, ts.sys, process.cwd());
|
|
24
|
-
const program = ts.createProgram({
|
|
25
|
-
options: parsedConfig.options,
|
|
26
|
-
rootNames: parsedConfig.fileNames,
|
|
27
|
-
configFileParsingDiagnostics: parsedConfig.errors
|
|
28
|
-
});
|
|
29
|
-
return program;
|
|
30
|
-
}
|
|
31
|
-
function findSourceAndImportName(program) {
|
|
32
|
-
const files = program.getSourceFiles().filter((sourceFile)=>{
|
|
33
|
-
if (sourceFile.isDeclarationFile) return false;
|
|
34
|
-
let found = false;
|
|
35
|
-
ts.forEachChild(sourceFile, (node)=>{
|
|
36
|
-
if (!found && ts.isImportDeclaration(node)) {
|
|
37
|
-
const { moduleSpecifier } = node;
|
|
38
|
-
if (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.includes('@trpc/react-query')) {
|
|
39
|
-
found = true;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
return found;
|
|
44
|
-
});
|
|
45
|
-
let importName = 'trpc';
|
|
46
|
-
files.forEach((sourceFile)=>{
|
|
47
|
-
ts.forEachChild(sourceFile, (node)=>{
|
|
48
|
-
if (ts.isVariableStatement(node) && node.modifiers?.some((mod)=>mod.getText(sourceFile) === 'export')) {
|
|
49
|
-
node.declarationList.declarations.forEach((declaration)=>{
|
|
50
|
-
if (ts.isVariableDeclaration(declaration) && declaration.initializer && ts.isCallExpression(declaration.initializer) && ts.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.getText(sourceFile) === 'createTRPCReact') {
|
|
51
|
-
importName = declaration.name.getText(sourceFile);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
return {
|
|
58
|
-
files: files.map((d)=>d.fileName),
|
|
59
|
-
importName
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
function findTRPCImportReferences(program) {
|
|
63
|
-
const { files: filesImportingTRPC, importName } = findSourceAndImportName(program);
|
|
64
|
-
const trpcReferenceSpecifiers = new Map();
|
|
65
|
-
program.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.getCompilerOptions(), ts.sys);
|
|
70
|
-
if (resolved.resolvedModule && filesImportingTRPC.includes(resolved.resolvedModule.resolvedFileName)) {
|
|
71
|
-
trpcReferenceSpecifiers.set(resolved.resolvedModule.resolvedFileName, node.moduleSpecifier.text);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
const counts = {};
|
|
77
|
-
let currentMax = 0;
|
|
78
|
-
const mostUsed = {
|
|
79
|
-
file: ''
|
|
80
|
-
};
|
|
81
|
-
[
|
|
82
|
-
...trpcReferenceSpecifiers.values()
|
|
83
|
-
].forEach((specifier)=>{
|
|
84
|
-
counts[specifier] = (counts[specifier] || 0) + 1;
|
|
85
|
-
if (counts[specifier] > currentMax) {
|
|
86
|
-
currentMax = counts[specifier];
|
|
87
|
-
mostUsed.file = specifier;
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
return {
|
|
91
|
-
importName,
|
|
92
|
-
mostUsed,
|
|
93
|
-
all: Object.fromEntries(trpcReferenceSpecifiers.entries())
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const execa = Util.promisify(CP.exec);
|
|
98
|
-
|
|
99
|
-
async function assertCleanGitTree() {
|
|
100
|
-
const { stdout } = await execa('git status');
|
|
101
|
-
if (!stdout.includes('nothing to commit')) {
|
|
102
|
-
p.cancel('Git tree is not clean, please commit your changes and try again, or run with `--force`');
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
async function filterIgnored(files) {
|
|
107
|
-
const { stdout } = await execa('git check-ignore **/*');
|
|
108
|
-
const ignores = stdout.split('\n');
|
|
109
|
-
if (process.env.VERBOSE) {
|
|
110
|
-
p.log.info(`cwd: ${process.cwd()}`);
|
|
111
|
-
p.log.info(`All files in program: ${files.map((file)=>file.fileName).join(', ')}`);
|
|
112
|
-
p.log.info(`Ignored files: ${ignores.join(', ')}`);
|
|
113
|
-
}
|
|
114
|
-
// Ignore "common files"
|
|
115
|
-
const filteredSourcePaths = files.filter((source)=>source.fileName.startsWith(Path.resolve()) && // only look ahead of current directory
|
|
116
|
-
!source.fileName.includes('/trpc/packages/') && // relative paths when running codemod locally
|
|
117
|
-
!source.fileName.includes('/node_modules/') && // always ignore node_modules
|
|
118
|
-
!ignores.includes(source.fileName)).map((source)=>source.fileName);
|
|
119
|
-
if (process.env.VERBOSE) {
|
|
120
|
-
p.log.info(`Filtered files: ${filteredSourcePaths.join(', ')}`);
|
|
121
|
-
}
|
|
122
|
-
return filteredSourcePaths;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function getPackageManager() {
|
|
126
|
-
const userAgent = process.env.npm_config_user_agent;
|
|
127
|
-
if (userAgent?.startsWith('pnpm')) return 'pnpm';
|
|
128
|
-
if (userAgent?.startsWith('yarn')) return 'yarn';
|
|
129
|
-
if (userAgent?.startsWith('bun')) return 'bun';
|
|
130
|
-
return 'npm';
|
|
131
|
-
}
|
|
132
|
-
async function installPackage(packageName) {
|
|
133
|
-
const packageManager = getPackageManager();
|
|
134
|
-
const installCmd = packageManager === 'yarn' ? 'add' : 'install';
|
|
135
|
-
const { stdout, stderr } = await execa(`${packageManager} ${installCmd} ${packageName}`);
|
|
136
|
-
if (stderr) {
|
|
137
|
-
p.log.error(stderr);
|
|
138
|
-
}
|
|
139
|
-
p.log.info(stdout);
|
|
140
|
-
}
|
|
141
|
-
async function uninstallPackage(packageName) {
|
|
142
|
-
const packageManager = getPackageManager();
|
|
143
|
-
const uninstallCmd = packageManager === 'yarn' ? 'remove' : 'uninstall';
|
|
144
|
-
const { stdout, stderr } = await execa(`${packageManager} ${uninstallCmd} ${packageName}`);
|
|
145
|
-
if (stderr) {
|
|
146
|
-
p.log.error(stderr);
|
|
147
|
-
}
|
|
148
|
-
p.log.info(stdout);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const require = __node_cjsModule.createRequire(import.meta.url);
|
|
152
|
-
|
|
153
|
-
const args = parse(process.argv.slice(2), {
|
|
154
|
-
default: {
|
|
155
|
-
force: false,
|
|
156
|
-
skipTanstackQuery: false,
|
|
157
|
-
verbose: false
|
|
158
|
-
},
|
|
159
|
-
alias: {
|
|
160
|
-
f: 'force',
|
|
161
|
-
h: 'help',
|
|
162
|
-
v: 'verbose',
|
|
163
|
-
q: 'skipTanstackQuery'
|
|
164
|
-
},
|
|
165
|
-
boolean: true
|
|
166
|
-
});
|
|
167
|
-
intro(`tRPC Upgrade CLI v${version}`);
|
|
168
|
-
if (args.help) {
|
|
169
|
-
log.info(`
|
|
170
|
-
Usage: upgrade [options]
|
|
171
|
-
|
|
172
|
-
Options:
|
|
173
|
-
-f, --force Skip git status check, use with caution
|
|
174
|
-
-q, --skipTanstackQuery Skip installing @trpc/tanstack-react-query package
|
|
175
|
-
-v, --verbose Enable verbose logging
|
|
176
|
-
-h, --help Show help
|
|
177
|
-
`.trim());
|
|
178
|
-
process.exit(0);
|
|
179
|
-
}
|
|
180
|
-
if (args.verbose) {
|
|
181
|
-
log.info(`Running upgrade with args: ${JSON.stringify(args, null, 2)}`);
|
|
182
|
-
}
|
|
183
|
-
if (!args.force) {
|
|
184
|
-
await assertCleanGitTree();
|
|
185
|
-
}
|
|
186
|
-
const transforms = await multiselect({
|
|
187
|
-
message: 'Select transforms to run',
|
|
188
|
-
options: [
|
|
189
|
-
{
|
|
190
|
-
value: require.resolve('@trpc/upgrade/transforms/hooksToOptions'),
|
|
191
|
-
label: 'Migrate Hooks to xxxOptions API'
|
|
192
|
-
},
|
|
193
|
-
{
|
|
194
|
-
value: require.resolve('@trpc/upgrade/transforms/provider'),
|
|
195
|
-
label: 'Migrate context provider setup'
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
});
|
|
199
|
-
if (isCancel(transforms)) process.exit(0);
|
|
200
|
-
// Make sure provider transform runs first if it's selected
|
|
201
|
-
const sortedTransforms = transforms.sort((a)=>a.includes('provider') ? -1 : 1);
|
|
202
|
-
const program = getProgram(args);
|
|
203
|
-
const sourceFiles = program.getSourceFiles();
|
|
204
|
-
const possibleReferences = findTRPCImportReferences(program);
|
|
205
|
-
const trpcFile = possibleReferences.mostUsed.file;
|
|
206
|
-
const trpcImportName = possibleReferences.importName;
|
|
207
|
-
const commitedFiles = await filterIgnored(sourceFiles);
|
|
208
|
-
for (const transform of sortedTransforms){
|
|
209
|
-
log.info(`Running transform: ${transform}`);
|
|
210
|
-
const { run } = await import('jscodeshift/src/Runner.js');
|
|
211
|
-
await run(transform, commitedFiles, {
|
|
212
|
-
...args,
|
|
213
|
-
trpcFile,
|
|
214
|
-
trpcImportName
|
|
215
|
-
});
|
|
216
|
-
log.info(`Transform ${transform} completed`);
|
|
217
|
-
}
|
|
218
|
-
if (!args.skipTanstackQuery) {
|
|
219
|
-
log.info('Installing @trpc/tanstack-react-query');
|
|
220
|
-
await installPackage('@trpc/tanstack-react-query');
|
|
221
|
-
log.success('@trpc/tanstack-react-query installed');
|
|
222
|
-
log.info('Uninstalling @trpc/react-query');
|
|
223
|
-
await uninstallPackage('@trpc/react-query');
|
|
224
|
-
log.success('@trpc/react-query uninstalled');
|
|
225
|
-
}
|
|
226
|
-
outro('Upgrade complete! 🎉');
|