@trpc/upgrade 0.0.0-alpha.28 → 0.0.0-alpha.29

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.
Files changed (2) hide show
  1. package/dist/bin.js +137 -151
  2. package/package.json +1 -1
package/dist/bin.js CHANGED
@@ -1,23 +1,41 @@
1
1
  #!/usr/bin/env node
2
- import * as CP from 'node:child_process';
3
- import * as Path from 'node:path';
4
- import * as Util from 'node:util';
5
- import * as Args from '@bomb.sh/args';
2
+ import { parse } from '@bomb.sh/args';
6
3
  import * as p from '@clack/prompts';
4
+ import { intro, log, multiselect, isCancel, outro } from '@clack/prompts';
7
5
  import * as ts from 'typescript';
8
- import { forEachChild, isImportDeclaration, isStringLiteral, resolveModuleName, sys, isVariableStatement, isVariableDeclaration, isCallExpression, isIdentifier } from 'typescript';
6
+ import * as Path from 'path';
7
+ import * as CP from 'node:child_process';
8
+ import * as Util from 'node:util';
9
9
  import __node_cjsModule from 'node:module';
10
10
 
11
- var version = "0.0.0-alpha.27";
11
+ var version = "0.0.0-alpha.28";
12
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
+ }
13
31
  function findSourceAndImportName(program) {
14
32
  const files = program.getSourceFiles().filter((sourceFile)=>{
15
33
  if (sourceFile.isDeclarationFile) return false;
16
34
  let found = false;
17
- forEachChild(sourceFile, (node)=>{
18
- if (!found && isImportDeclaration(node)) {
35
+ ts.forEachChild(sourceFile, (node)=>{
36
+ if (!found && ts.isImportDeclaration(node)) {
19
37
  const { moduleSpecifier } = node;
20
- if (isStringLiteral(moduleSpecifier) && moduleSpecifier.text.includes('@trpc/react-query')) {
38
+ if (ts.isStringLiteral(moduleSpecifier) && moduleSpecifier.text.includes('@trpc/react-query')) {
21
39
  found = true;
22
40
  }
23
41
  }
@@ -26,10 +44,10 @@ function findSourceAndImportName(program) {
26
44
  });
27
45
  let importName = 'trpc';
28
46
  files.forEach((sourceFile)=>{
29
- forEachChild(sourceFile, (node)=>{
30
- if (isVariableStatement(node) && node.modifiers?.some((mod)=>mod.getText(sourceFile) === 'export')) {
47
+ ts.forEachChild(sourceFile, (node)=>{
48
+ if (ts.isVariableStatement(node) && node.modifiers?.some((mod)=>mod.getText(sourceFile) === 'export')) {
31
49
  node.declarationList.declarations.forEach((declaration)=>{
32
- if (isVariableDeclaration(declaration) && declaration.initializer && isCallExpression(declaration.initializer) && isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.getText(sourceFile) === 'createTRPCReact') {
50
+ if (ts.isVariableDeclaration(declaration) && declaration.initializer && ts.isCallExpression(declaration.initializer) && ts.isIdentifier(declaration.initializer.expression) && declaration.initializer.expression.getText(sourceFile) === 'createTRPCReact') {
33
51
  importName = declaration.name.getText(sourceFile);
34
52
  }
35
53
  });
@@ -46,9 +64,9 @@ function findTRPCImportReferences(program) {
46
64
  const trpcReferenceSpecifiers = new Map();
47
65
  program.getSourceFiles().forEach((sourceFile)=>{
48
66
  if (sourceFile.isDeclarationFile) return;
49
- forEachChild(sourceFile, (node)=>{
50
- if (isImportDeclaration(node) && isStringLiteral(node.moduleSpecifier)) {
51
- const resolved = resolveModuleName(node.moduleSpecifier.text, sourceFile.fileName, program.getCompilerOptions(), sys);
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);
52
70
  if (resolved.resolvedModule && filesImportingTRPC.includes(resolved.resolvedModule.resolvedFileName)) {
53
71
  trpcReferenceSpecifiers.set(resolved.resolvedModule.resolvedFileName, node.moduleSpecifier.text);
54
72
  }
@@ -76,45 +94,22 @@ function findTRPCImportReferences(program) {
76
94
  };
77
95
  }
78
96
 
79
- const require = __node_cjsModule.createRequire(import.meta.url);
80
-
81
97
  const execa = Util.promisify(CP.exec);
82
- function exitOnCancel(value) {
83
- if (p.isCancel(value)) {
84
- process.exit(0);
85
- }
86
- }
87
- async function getPackageManager() {
88
- const userAgent = process.env.npm_config_user_agent;
89
- if (userAgent?.startsWith('pnpm')) return 'pnpm';
90
- if (userAgent?.startsWith('yarn')) return 'yarn';
91
- if (userAgent?.startsWith('bun')) return 'bun';
92
- return 'npm';
93
- }
98
+
94
99
  async function assertCleanGitTree() {
95
100
  const { stdout } = await execa('git status');
96
101
  if (!stdout.includes('nothing to commit')) {
97
- throw new Error('Git tree is not clean, please commit your changes and try again, or run with `--force`');
102
+ p.cancel('Git tree is not clean, please commit your changes and try again, or run with `--force`');
103
+ process.exit(1);
98
104
  }
99
105
  }
100
- async function installPackage(packageName) {
101
- const packageManager = await getPackageManager();
102
- const { stdout } = await execa(`${packageManager} install ${packageName}`);
103
- console.log(stdout);
104
- }
105
- async function uninstallPackage(packageName) {
106
- const packageManager = await getPackageManager();
107
- const uninstallCmd = packageManager === 'yarn' ? 'remove' : 'uninstall';
108
- const { stdout } = await execa(`${packageManager} ${uninstallCmd} ${packageName}`);
109
- console.log(stdout);
110
- }
111
106
  async function filterIgnored(files) {
112
107
  const { stdout } = await execa('git check-ignore **/*');
113
108
  const ignores = stdout.split('\n');
114
109
  if (process.env.VERBOSE) {
115
- console.debug('cwd:', process.cwd());
116
- console.debug('All files in program:', files.map((file)=>file.fileName));
117
- console.debug('Ignored files:', ignores);
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(', ')}`);
118
113
  }
119
114
  // Ignore "common files"
120
115
  const filteredSourcePaths = files.filter((source)=>source.fileName.startsWith(Path.resolve()) && // only look ahead of current directory
@@ -122,119 +117,110 @@ async function filterIgnored(files) {
122
117
  !source.fileName.includes('/node_modules/') && // always ignore node_modules
123
118
  !ignores.includes(source.fileName)).map((source)=>source.fileName);
124
119
  if (process.env.VERBOSE) {
125
- console.debug('Filtered files:', filteredSourcePaths);
120
+ p.log.info(`Filtered files: ${filteredSourcePaths.join(', ')}`);
126
121
  }
127
122
  return filteredSourcePaths;
128
123
  }
129
- // FIXME :: hacky
130
- const transformPath = (path)=>process.env.DEV ? path : path.replace('../', './').replace('.ts', '.cjs');
131
- async function main() {
132
- const args = Args.parse(process.argv.slice(2), {
133
- default: {
134
- force: false,
135
- skipTanstackQuery: false,
136
- verbose: false,
137
- version: false
138
- },
139
- alias: {
140
- f: 'force',
141
- h: 'help',
142
- v: 'verbose',
143
- q: 'skipTanstackQuery'
144
- },
145
- boolean: true
146
- });
147
- if (args.version) {
148
- console.log(`v${version}`);
149
- process.exit(0);
150
- }
151
- if (args.help) {
152
- console.log(`
153
- Usage: upgrade [options]
154
124
 
155
- Options:
156
- -f, --force Skip git status check, use with caution
157
- -q, --skipTanstackQuery Skip installing @trpc/tanstack-react-query package
158
- -v, --verbose Enable verbose logging
159
- -h, --help Show help
160
- `.trim());
161
- process.exit(0);
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);
162
138
  }
163
- if (args.verbose) {
164
- console.log('Running upgrade with args:', args);
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);
165
147
  }
166
- p.intro('tRPC Upgrade CLI');
167
- if (!args.force) {
168
- try {
169
- await assertCleanGitTree();
170
- } catch (error) {
171
- console.error(error);
172
- process.exit(1);
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'
173
196
  }
174
- }
175
- const transforms = await p.multiselect({
176
- message: 'Select transforms to run',
177
- options: [
178
- {
179
- value: require.resolve(transformPath('../transforms/hooksToOptions.ts')),
180
- label: 'Migrate Hooks to xxxOptions API'
181
- },
182
- {
183
- value: require.resolve(transformPath('../transforms/provider.ts')),
184
- label: 'Migrate context provider setup'
185
- }
186
- ]
187
- });
188
- exitOnCancel(transforms);
189
- if (!transforms || transforms.length === 0) {
190
- console.error('Please select at least one transform to run');
191
- process.exit(1);
192
- }
193
- // Make sure provider transform runs first if it's selected
194
- const sortedTransforms = transforms.sort((a)=>a.includes('provider.ts') ? -1 : 1);
195
- const configFile = ts.findConfigFile(process.cwd(), ts.sys.fileExists);
196
- if (!configFile) {
197
- console.error('No tsconfig found');
198
- process.exit(1);
199
- }
200
- if (process.env.VERBOSE) {
201
- console.debug('Using tsconfig', configFile);
202
- }
203
- const { config } = ts.readConfigFile(configFile, ts.sys.readFile);
204
- const parsedConfig = ts.parseJsonConfigFileContent(config, ts.sys, process.cwd());
205
- const program = ts.createProgram({
206
- options: parsedConfig.options,
207
- rootNames: parsedConfig.fileNames,
208
- configFileParsingDiagnostics: parsedConfig.errors
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
209
215
  });
210
- const sourceFiles = program.getSourceFiles();
211
- const possibleReferences = findTRPCImportReferences(program);
212
- const trpcFile = possibleReferences.mostUsed.file;
213
- const trpcImportName = possibleReferences.importName;
214
- const commitedFiles = await filterIgnored(sourceFiles);
215
- for (const transform of sortedTransforms){
216
- console.log('Running transform', transform);
217
- const { run } = await import('jscodeshift/src/Runner.js');
218
- const result = await run(transform, commitedFiles, {
219
- ...args,
220
- trpcFile,
221
- trpcImportName
222
- });
223
- console.log('Transform result', result);
224
- }
225
- if (!args.skipTanstackQuery) {
226
- console.log('Installing @trpc/tanstack-react-query');
227
- await installPackage('@trpc/tanstack-react-query');
228
- console.log('Uninstalling @trpc/react-query');
229
- await uninstallPackage('@trpc/react-query');
230
- }
231
- p.outro('Upgrade complete! 🎉');
216
+ log.info(`Transform ${transform} completed`);
232
217
  }
233
- main().catch((error)=>{
234
- if (error instanceof Error) {
235
- console.error(error.message);
236
- } else {
237
- console.error('An unknown error occurred:', error);
238
- }
239
- process.exit(1);
240
- });
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! 🎉');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trpc/upgrade",
3
- "version": "0.0.0-alpha.28",
3
+ "version": "0.0.0-alpha.29",
4
4
  "description": "Upgrade scripts for tRPC",
5
5
  "author": "juliusmarminge",
6
6
  "license": "MIT",