create-tsrouter-app 0.3.0-alpha.6 → 0.3.0

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 (155) hide show
  1. package/dist/index.js +347 -2
  2. package/package.json +3 -4
  3. package/src/index.ts +507 -2
  4. package/templates/{react/base → base}/README.md.ejs +0 -9
  5. package/templates/{react/base/tsconfig.json.ejs → base/tsconfig.json} +1 -5
  6. package/templates/base/vite.config.js.ejs +15 -0
  7. package/templates/file-router/src/routes/__root.tsx +11 -0
  8. package/dist/add-ons.js +0 -60
  9. package/dist/cli.js +0 -58
  10. package/dist/constants.js +0 -4
  11. package/dist/create-app.js +0 -293
  12. package/dist/options.js +0 -245
  13. package/dist/types.js +0 -1
  14. package/src/add-ons.ts +0 -158
  15. package/src/cli.ts +0 -90
  16. package/src/constants.ts +0 -7
  17. package/src/create-app.ts +0 -460
  18. package/src/options.ts +0 -284
  19. package/src/types.ts +0 -28
  20. package/templates/react/add-on/clerk/README.md +0 -3
  21. package/templates/react/add-on/clerk/assets/.env.local.append +0 -2
  22. package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
  23. package/templates/react/add-on/clerk/info.json +0 -29
  24. package/templates/react/add-on/clerk/package.json +0 -5
  25. package/templates/react/add-on/convex/README.md +0 -4
  26. package/templates/react/add-on/convex/assets/.cursorrules.append +0 -93
  27. package/templates/react/add-on/convex/assets/.env.local.append +0 -3
  28. package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
  29. package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
  30. package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
  31. package/templates/react/add-on/convex/info.json +0 -28
  32. package/templates/react/add-on/convex/package.json +0 -6
  33. package/templates/react/add-on/form/assets/src/routes/demo.form.tsx +0 -50
  34. package/templates/react/add-on/form/info.json +0 -13
  35. package/templates/react/add-on/form/package.json +0 -5
  36. package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
  37. package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  38. package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
  39. package/templates/react/add-on/module-federation/info.json +0 -7
  40. package/templates/react/add-on/module-federation/package.json +0 -5
  41. package/templates/react/add-on/netlify/README.md +0 -11
  42. package/templates/react/add-on/netlify/info.json +0 -7
  43. package/templates/react/add-on/sentry/assets/.cursorrules +0 -22
  44. package/templates/react/add-on/sentry/assets/.env.local.append +0 -2
  45. package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.bad-server-func.tsx +0 -29
  46. package/templates/react/add-on/sentry/info.json +0 -14
  47. package/templates/react/add-on/sentry/package.json +0 -5
  48. package/templates/react/add-on/shadcn/README.md +0 -7
  49. package/templates/react/add-on/shadcn/info.json +0 -11
  50. package/templates/react/add-on/start/assets/app.config.ts +0 -16
  51. package/templates/react/add-on/start/assets/postcss.config.ts +0 -5
  52. package/templates/react/add-on/start/assets/src/api.ts +0 -6
  53. package/templates/react/add-on/start/assets/src/client.tsx +0 -10
  54. package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -34
  55. package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
  56. package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
  57. package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
  58. package/templates/react/add-on/start/assets/src/ssr.tsx +0 -12
  59. package/templates/react/add-on/start/info.json +0 -19
  60. package/templates/react/add-on/start/package.json +0 -14
  61. package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -5
  62. package/templates/react/add-on/store/assets/src/routes/demo.store.page1.tsx +0 -30
  63. package/templates/react/add-on/store/assets/src/routes/demo.store.page2.tsx +0 -30
  64. package/templates/react/add-on/store/info.json +0 -17
  65. package/templates/react/add-on/store/package.json +0 -6
  66. package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  67. package/templates/react/add-on/tanstack-query/info.json +0 -31
  68. package/templates/react/add-on/tanstack-query/package.json +0 -6
  69. package/templates/react/base/.vscode/settings.json +0 -11
  70. package/templates/react/base/vite.config.js.ejs +0 -24
  71. package/templates/react/example/tanchat/README.md +0 -37
  72. package/templates/react/example/tanchat/assets/.env.local.append +0 -2
  73. package/templates/react/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -148
  74. package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
  75. package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx.ejs +0 -375
  76. package/templates/react/example/tanchat/assets/src/store/demo.hooks.ts +0 -21
  77. package/templates/react/example/tanchat/assets/src/store/demo.store.ts +0 -133
  78. package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -108
  79. package/templates/react/example/tanchat/info.json +0 -15
  80. package/templates/react/example/tanchat/package.json +0 -10
  81. package/templates/react/file-router/src/components/Header.tsx.ejs +0 -27
  82. package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -80
  83. package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx +0 -136
  84. package/templates/solid/add-on/form/info.json +0 -13
  85. package/templates/solid/add-on/form/package.json +0 -5
  86. package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
  87. package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
  88. package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
  89. package/templates/solid/add-on/module-federation/info.json +0 -7
  90. package/templates/solid/add-on/module-federation/package.json +0 -5
  91. package/templates/solid/add-on/sentry/assets/.cursorrules.append +0 -22
  92. package/templates/solid/add-on/sentry/assets/.env.local.append +0 -2
  93. package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
  94. package/templates/solid/add-on/sentry/info.json +0 -13
  95. package/templates/solid/add-on/sentry/package.json +0 -5
  96. package/templates/solid/add-on/solid-ui/README.md +0 -9
  97. package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
  98. package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
  99. package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
  100. package/templates/solid/add-on/solid-ui/info.json +0 -11
  101. package/templates/solid/add-on/solid-ui/package.json +0 -9
  102. package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -5
  103. package/templates/solid/add-on/store/assets/src/routes/demo.store.page1.tsx +0 -30
  104. package/templates/solid/add-on/store/assets/src/routes/demo.store.page2.tsx +0 -30
  105. package/templates/solid/add-on/store/info.json +0 -17
  106. package/templates/solid/add-on/store/package.json +0 -6
  107. package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
  108. package/templates/solid/add-on/tanstack-query/info.json +0 -31
  109. package/templates/solid/add-on/tanstack-query/package.json +0 -6
  110. package/templates/solid/base/.cursorrules +0 -35
  111. package/templates/solid/base/.vscode/settings.json +0 -11
  112. package/templates/solid/base/README.md.ejs +0 -200
  113. package/templates/solid/base/gitignore +0 -5
  114. package/templates/solid/base/index.html.ejs +0 -20
  115. package/templates/solid/base/package.json +0 -22
  116. package/templates/solid/base/package.ts.json +0 -5
  117. package/templates/solid/base/package.tw.json +0 -6
  118. package/templates/solid/base/public/favicon.ico +0 -0
  119. package/templates/solid/base/public/logo192.png +0 -0
  120. package/templates/solid/base/public/logo512.png +0 -0
  121. package/templates/solid/base/public/manifest.json +0 -25
  122. package/templates/solid/base/public/robots.txt +0 -3
  123. package/templates/solid/base/src/App.css +0 -0
  124. package/templates/solid/base/src/App.tsx.ejs +0 -47
  125. package/templates/solid/base/src/logo.svg +0 -120
  126. package/templates/solid/base/src/styles.css.ejs +0 -15
  127. package/templates/solid/base/tsconfig.json.ejs +0 -30
  128. package/templates/solid/base/vite.config.js.ejs +0 -22
  129. package/templates/solid/code-router/src/main.tsx.ejs +0 -53
  130. package/templates/solid/file-router/package.fr.json +0 -5
  131. package/templates/solid/file-router/src/components/Header.tsx.ejs +0 -24
  132. package/templates/solid/file-router/src/main.tsx.ejs +0 -44
  133. package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -47
  134. package/templates/solid/file-router/src/routes/index.tsx +0 -43
  135. /package/dist/{package-manager.js → utils/getPackageManager.js} +0 -0
  136. /package/src/{package-manager.ts → utils/getPackageManager.ts} +0 -0
  137. /package/templates/{react/base → base}/gitignore +0 -0
  138. /package/templates/{react/base → base}/index.html.ejs +0 -0
  139. /package/templates/{react/base → base}/package.json +0 -0
  140. /package/templates/{react/base → base}/package.ts.json +0 -0
  141. /package/templates/{react/base → base}/package.tw.json +0 -0
  142. /package/templates/{react/base → base}/public/favicon.ico +0 -0
  143. /package/templates/{react/base → base}/public/logo192.png +0 -0
  144. /package/templates/{react/base → base}/public/logo512.png +0 -0
  145. /package/templates/{react/base → base}/public/manifest.json +0 -0
  146. /package/templates/{react/base → base}/public/robots.txt +0 -0
  147. /package/templates/{react/base → base}/src/App.css +0 -0
  148. /package/templates/{react/base → base}/src/App.test.tsx.ejs +0 -0
  149. /package/templates/{react/base → base}/src/App.tsx.ejs +0 -0
  150. /package/templates/{react/base → base}/src/logo.svg +0 -0
  151. /package/templates/{react/base → base}/src/reportWebVitals.ts.ejs +0 -0
  152. /package/templates/{react/base → base}/src/styles.css.ejs +0 -0
  153. /package/templates/{react/code-router → code-router}/src/main.tsx.ejs +0 -0
  154. /package/templates/{react/file-router → file-router}/package.fr.json +0 -0
  155. /package/templates/{react/file-router → file-router}/src/main.tsx.ejs +0 -0
package/dist/index.js CHANGED
@@ -1,3 +1,348 @@
1
1
  #!/usr/bin/env node
2
- import { cli } from './cli.js';
3
- cli();
2
+ import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import { existsSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { Command, InvalidArgumentError } from 'commander';
7
+ import { cancel, confirm, intro, isCancel, log, outro, select, spinner, text, } from '@clack/prompts';
8
+ import { execa } from 'execa';
9
+ import { render } from 'ejs';
10
+ import { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getPackageManager, } from './utils/getPackageManager.js';
11
+ const program = new Command();
12
+ const CODE_ROUTER = 'code-router';
13
+ const FILE_ROUTER = 'file-router';
14
+ function sortObject(obj) {
15
+ return Object.keys(obj)
16
+ .sort()
17
+ .reduce((acc, key) => {
18
+ acc[key] = obj[key];
19
+ return acc;
20
+ }, {});
21
+ }
22
+ function createCopyFile(targetDir) {
23
+ return async function copyFiles(templateDir, files) {
24
+ for (const file of files) {
25
+ const targetFileName = file.replace('.tw', '');
26
+ await copyFile(resolve(templateDir, file), resolve(targetDir, targetFileName));
27
+ }
28
+ };
29
+ }
30
+ function createTemplateFile(projectName, options, targetDir) {
31
+ return async function templateFile(templateDir, file, targetFileName) {
32
+ const templateValues = {
33
+ packageManager: options.packageManager,
34
+ projectName: projectName,
35
+ typescript: options.typescript,
36
+ tailwind: options.tailwind,
37
+ js: options.typescript ? 'ts' : 'js',
38
+ jsx: options.typescript ? 'tsx' : 'jsx',
39
+ fileRouter: options.mode === FILE_ROUTER,
40
+ codeRouter: options.mode === CODE_ROUTER,
41
+ };
42
+ const template = await readFile(resolve(templateDir, file), 'utf-8');
43
+ const content = render(template, templateValues);
44
+ const target = targetFileName ?? file.replace('.ejs', '');
45
+ await writeFile(resolve(targetDir, target), content);
46
+ };
47
+ }
48
+ async function createPackageJSON(projectName, options, templateDir, routerDir, targetDir) {
49
+ let packageJSON = JSON.parse(await readFile(resolve(templateDir, 'package.json'), 'utf8'));
50
+ packageJSON.name = projectName;
51
+ if (options.typescript) {
52
+ const tsPackageJSON = JSON.parse(await readFile(resolve(templateDir, 'package.ts.json'), 'utf8'));
53
+ packageJSON = {
54
+ ...packageJSON,
55
+ devDependencies: {
56
+ ...packageJSON.devDependencies,
57
+ ...tsPackageJSON.devDependencies,
58
+ },
59
+ };
60
+ }
61
+ if (options.tailwind) {
62
+ const twPackageJSON = JSON.parse(await readFile(resolve(templateDir, 'package.tw.json'), 'utf8'));
63
+ packageJSON = {
64
+ ...packageJSON,
65
+ dependencies: {
66
+ ...packageJSON.dependencies,
67
+ ...twPackageJSON.dependencies,
68
+ },
69
+ };
70
+ }
71
+ if (options.mode === FILE_ROUTER) {
72
+ const frPackageJSON = JSON.parse(await readFile(resolve(routerDir, 'package.fr.json'), 'utf8'));
73
+ packageJSON = {
74
+ ...packageJSON,
75
+ dependencies: {
76
+ ...packageJSON.dependencies,
77
+ ...frPackageJSON.dependencies,
78
+ },
79
+ };
80
+ }
81
+ packageJSON.dependencies = sortObject(packageJSON.dependencies);
82
+ packageJSON.devDependencies = sortObject(packageJSON.devDependencies);
83
+ await writeFile(resolve(targetDir, 'package.json'), JSON.stringify(packageJSON, null, 2));
84
+ }
85
+ async function createApp(options) {
86
+ const templateDirBase = fileURLToPath(new URL('../templates/base', import.meta.url));
87
+ const templateDirRouter = fileURLToPath(new URL(`../templates/${options.mode}`, import.meta.url));
88
+ const targetDir = resolve(process.cwd(), options.projectName);
89
+ if (existsSync(targetDir)) {
90
+ log.error(`Directory "${options.projectName}" already exists`);
91
+ return;
92
+ }
93
+ const copyFiles = createCopyFile(targetDir);
94
+ const templateFile = createTemplateFile(options.projectName, options, targetDir);
95
+ intro(`Creating a new TanStack app in ${targetDir}...`);
96
+ // Make the root directory
97
+ await mkdir(targetDir, { recursive: true });
98
+ // Setup the .vscode directory
99
+ await mkdir(resolve(targetDir, '.vscode'), { recursive: true });
100
+ await copyFile(resolve(templateDirBase, '.vscode/settings.json'), resolve(targetDir, '.vscode/settings.json'));
101
+ // Fill the public directory
102
+ await mkdir(resolve(targetDir, 'public'), { recursive: true });
103
+ copyFiles(templateDirBase, [
104
+ './public/robots.txt',
105
+ './public/favicon.ico',
106
+ './public/manifest.json',
107
+ './public/logo192.png',
108
+ './public/logo512.png',
109
+ ]);
110
+ // Make the src directory
111
+ await mkdir(resolve(targetDir, 'src'), { recursive: true });
112
+ if (options.mode === FILE_ROUTER) {
113
+ await mkdir(resolve(targetDir, 'src/routes'), { recursive: true });
114
+ }
115
+ // Copy in Vite and Tailwind config and CSS
116
+ if (!options.tailwind) {
117
+ await copyFiles(templateDirBase, ['./src/App.css']);
118
+ }
119
+ await templateFile(templateDirBase, './vite.config.js.ejs');
120
+ await templateFile(templateDirBase, './src/styles.css.ejs');
121
+ copyFiles(templateDirBase, ['./src/logo.svg']);
122
+ // Setup the app component. There are four variations, typescript/javascript and tailwind/non-tailwind.
123
+ if (options.mode === FILE_ROUTER) {
124
+ copyFiles(templateDirRouter, ['./src/routes/__root.tsx']);
125
+ await templateFile(templateDirBase, './src/App.tsx.ejs', './src/routes/index.tsx');
126
+ }
127
+ else {
128
+ await templateFile(templateDirBase, './src/App.tsx.ejs', options.typescript ? undefined : './src/App.jsx');
129
+ await templateFile(templateDirBase, './src/App.test.tsx.ejs', options.typescript ? undefined : './src/App.test.jsx');
130
+ }
131
+ // Create the main entry point
132
+ if (options.typescript) {
133
+ await templateFile(templateDirRouter, './src/main.tsx.ejs');
134
+ }
135
+ else {
136
+ await templateFile(templateDirRouter, './src/main.tsx.ejs', './src/main.jsx');
137
+ }
138
+ // Setup the main, reportWebVitals and index.html files
139
+ if (options.typescript) {
140
+ await templateFile(templateDirBase, './src/reportWebVitals.ts.ejs');
141
+ }
142
+ else {
143
+ await templateFile(templateDirBase, './src/reportWebVitals.ts.ejs', './src/reportWebVitals.js');
144
+ }
145
+ await templateFile(templateDirBase, './index.html.ejs');
146
+ // Setup tsconfig
147
+ if (options.typescript) {
148
+ await copyFiles(templateDirBase, ['./tsconfig.json']);
149
+ }
150
+ // Setup the package.json file, optionally with typescript and tailwind
151
+ await createPackageJSON(options.projectName, options, templateDirBase, templateDirRouter, targetDir);
152
+ // Add .gitignore
153
+ await copyFile(resolve(templateDirBase, 'gitignore'), resolve(targetDir, '.gitignore'));
154
+ // Create the README.md
155
+ await templateFile(templateDirBase, 'README.md.ejs');
156
+ // Install dependencies
157
+ const s = spinner();
158
+ s.start(`Installing dependencies via ${options.packageManager}...`);
159
+ await execa(options.packageManager, ['install'], { cwd: targetDir });
160
+ s.stop(`Installed dependencies`);
161
+ if (options.git) {
162
+ s.start(`Initializing git repository...`);
163
+ await execa('git', ['init'], { cwd: targetDir });
164
+ s.stop(`Initialized git repository`);
165
+ }
166
+ outro(`Created your new TanStack app in ${targetDir}.
167
+
168
+ Use the following commands to start your app:
169
+
170
+ % cd ${options.projectName}
171
+ % ${options.packageManager} start
172
+
173
+ Please read README.md for more information on testing, styling, adding routes, react-query, etc.
174
+ `);
175
+ }
176
+ // If all CLI options are provided, use them directly
177
+ function normalizeOptions(cliOptions) {
178
+ if (cliOptions.projectName) {
179
+ const typescript = cliOptions.template === 'typescript' ||
180
+ cliOptions.template === 'file-router';
181
+ return {
182
+ projectName: cliOptions.projectName,
183
+ typescript,
184
+ tailwind: !!cliOptions.tailwind,
185
+ packageManager: cliOptions.packageManager || DEFAULT_PACKAGE_MANAGER,
186
+ mode: cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER,
187
+ git: !!cliOptions.git,
188
+ };
189
+ }
190
+ }
191
+ async function promptForOptions(cliOptions) {
192
+ const options = {};
193
+ if (!cliOptions.projectName) {
194
+ const value = await text({
195
+ message: 'What would you like to name your project?',
196
+ defaultValue: 'my-app',
197
+ validate(value) {
198
+ if (!value) {
199
+ return 'Please enter a name';
200
+ }
201
+ },
202
+ });
203
+ if (isCancel(value)) {
204
+ cancel('Operation cancelled.');
205
+ process.exit(0);
206
+ }
207
+ options.projectName = value;
208
+ }
209
+ // Router type selection
210
+ if (!cliOptions.template) {
211
+ const routerType = await select({
212
+ message: 'Select the router type:',
213
+ options: [
214
+ {
215
+ value: FILE_ROUTER,
216
+ label: 'File Router - File-based routing structure',
217
+ },
218
+ {
219
+ value: CODE_ROUTER,
220
+ label: 'Code Router - Traditional code-based routing',
221
+ },
222
+ ],
223
+ initialValue: FILE_ROUTER,
224
+ });
225
+ if (isCancel(routerType)) {
226
+ cancel('Operation cancelled.');
227
+ process.exit(0);
228
+ }
229
+ options.mode = routerType;
230
+ }
231
+ else {
232
+ options.mode = cliOptions.template;
233
+ if (options.mode === FILE_ROUTER) {
234
+ options.typescript = true;
235
+ }
236
+ }
237
+ // TypeScript selection (if using Code Router)
238
+ if (!options.typescript) {
239
+ if (options.mode === CODE_ROUTER) {
240
+ const typescriptEnable = await confirm({
241
+ message: 'Would you like to use TypeScript?',
242
+ initialValue: true,
243
+ });
244
+ if (isCancel(typescriptEnable)) {
245
+ cancel('Operation cancelled.');
246
+ process.exit(0);
247
+ }
248
+ options.typescript = typescriptEnable;
249
+ }
250
+ else {
251
+ options.typescript = true;
252
+ }
253
+ }
254
+ // Tailwind selection
255
+ if (cliOptions.tailwind === undefined) {
256
+ const tailwind = await confirm({
257
+ message: 'Would you like to use Tailwind CSS?',
258
+ initialValue: true,
259
+ });
260
+ if (isCancel(tailwind)) {
261
+ cancel('Operation cancelled.');
262
+ process.exit(0);
263
+ }
264
+ options.tailwind = tailwind;
265
+ }
266
+ else {
267
+ options.tailwind = cliOptions.tailwind;
268
+ }
269
+ // Package manager selection
270
+ if (cliOptions.packageManager === undefined) {
271
+ const detectedPackageManager = getPackageManager();
272
+ if (!detectedPackageManager) {
273
+ const pm = await select({
274
+ message: 'Select package manager:',
275
+ options: SUPPORTED_PACKAGE_MANAGERS.map((pm) => ({
276
+ value: pm,
277
+ label: pm,
278
+ })),
279
+ initialValue: DEFAULT_PACKAGE_MANAGER,
280
+ });
281
+ if (isCancel(pm)) {
282
+ cancel('Operation cancelled.');
283
+ process.exit(0);
284
+ }
285
+ options.packageManager = pm;
286
+ }
287
+ else {
288
+ options.packageManager = detectedPackageManager;
289
+ }
290
+ }
291
+ else {
292
+ options.packageManager = cliOptions.packageManager;
293
+ }
294
+ // Git selection
295
+ if (cliOptions.git === undefined) {
296
+ const git = await confirm({
297
+ message: 'Would you like to initialize a new git repository?',
298
+ initialValue: true,
299
+ });
300
+ if (isCancel(git)) {
301
+ cancel('Operation cancelled.');
302
+ process.exit(0);
303
+ }
304
+ options.git = git;
305
+ }
306
+ else {
307
+ options.git = !!cliOptions.git;
308
+ }
309
+ return options;
310
+ }
311
+ program
312
+ .name('create-tsrouter-app')
313
+ .description('CLI to create a new TanStack application')
314
+ .argument('[project-name]', 'name of the project')
315
+ .option('--no-git', 'do not create a git repository')
316
+ .option('--template <type>', 'project template (typescript, javascript, file-router)', (value) => {
317
+ if (value !== 'typescript' &&
318
+ value !== 'javascript' &&
319
+ value !== 'file-router') {
320
+ throw new InvalidArgumentError(`Invalid template: ${value}. Only the following are allowed: typescript, javascript, file-router`);
321
+ }
322
+ return value;
323
+ })
324
+ .option(`--package-manager <${SUPPORTED_PACKAGE_MANAGERS.join('|')}>`, `Explicitly tell the CLI to use this package manager`, (value) => {
325
+ if (!SUPPORTED_PACKAGE_MANAGERS.includes(value)) {
326
+ throw new InvalidArgumentError(`Invalid package manager: ${value}. Only the following are allowed: ${SUPPORTED_PACKAGE_MANAGERS.join(', ')}`);
327
+ }
328
+ return value;
329
+ })
330
+ .option('--tailwind', 'add Tailwind CSS')
331
+ .action(async (projectName, options) => {
332
+ try {
333
+ const cliOptions = {
334
+ projectName,
335
+ ...options,
336
+ };
337
+ let finalOptions = normalizeOptions(cliOptions);
338
+ if (!finalOptions) {
339
+ finalOptions = await promptForOptions(cliOptions);
340
+ }
341
+ await createApp(finalOptions);
342
+ }
343
+ catch (error) {
344
+ log.error(error instanceof Error ? error.message : 'An unknown error occurred');
345
+ process.exit(1);
346
+ }
347
+ });
348
+ program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tsrouter-app",
3
- "version": "0.3.0-alpha.6",
3
+ "version": "0.3.0",
4
4
  "description": "Tanstack Application Builder",
5
5
  "bin": "./dist/index.js",
6
6
  "type": "module",
@@ -23,11 +23,9 @@
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
25
  "@clack/prompts": "^0.10.0",
26
- "chalk": "^5.4.1",
27
26
  "commander": "^13.1.0",
28
27
  "ejs": "^3.1.10",
29
- "execa": "^9.5.2",
30
- "prettier": "^3.5.0"
28
+ "execa": "^9.5.2"
31
29
  },
32
30
  "devDependencies": {
33
31
  "@tanstack/config": "^0.16.2",
@@ -36,6 +34,7 @@
36
34
  "eslint": "^9.20.0",
37
35
  "eslint-plugin-react-hooks": "^5.1.0",
38
36
  "eslint-plugin-unused-imports": "^4.1.4",
37
+ "prettier": "^3.5.0",
39
38
  "typescript": "^5.6.3"
40
39
  },
41
40
  "scripts": {}