@tanstack/cli 0.0.7 → 0.48.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.
Files changed (83) hide show
  1. package/dist/bin.js +7 -0
  2. package/dist/cli.js +481 -0
  3. package/dist/command-line.js +174 -0
  4. package/dist/dev-watch.js +290 -0
  5. package/dist/file-syncer.js +148 -0
  6. package/dist/index.js +1 -0
  7. package/dist/mcp/api.js +31 -0
  8. package/dist/mcp/tools.js +250 -0
  9. package/dist/mcp/types.js +37 -0
  10. package/dist/mcp.js +121 -0
  11. package/dist/options.js +162 -0
  12. package/dist/types/bin.d.ts +2 -0
  13. package/dist/types/cli.d.ts +16 -0
  14. package/dist/types/command-line.d.ts +10 -0
  15. package/dist/types/dev-watch.d.ts +27 -0
  16. package/dist/types/file-syncer.d.ts +18 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/mcp/api.d.ts +4 -0
  19. package/dist/types/mcp/tools.d.ts +2 -0
  20. package/dist/types/mcp/types.d.ts +217 -0
  21. package/dist/types/mcp.d.ts +6 -0
  22. package/dist/types/options.d.ts +8 -0
  23. package/dist/types/types.d.ts +25 -0
  24. package/dist/types/ui-environment.d.ts +2 -0
  25. package/dist/types/ui-prompts.d.ts +12 -0
  26. package/dist/types/utils.d.ts +8 -0
  27. package/dist/types.js +1 -0
  28. package/dist/ui-environment.js +52 -0
  29. package/dist/ui-prompts.js +244 -0
  30. package/dist/utils.js +30 -0
  31. package/package.json +46 -46
  32. package/src/bin.ts +6 -93
  33. package/src/cli.ts +692 -0
  34. package/src/command-line.ts +236 -0
  35. package/src/dev-watch.ts +430 -0
  36. package/src/file-syncer.ts +205 -0
  37. package/src/index.ts +1 -85
  38. package/src/mcp.ts +190 -0
  39. package/src/options.ts +260 -0
  40. package/src/types.ts +27 -0
  41. package/src/ui-environment.ts +74 -0
  42. package/src/ui-prompts.ts +322 -0
  43. package/src/utils.ts +38 -0
  44. package/tests/command-line.test.ts +304 -0
  45. package/tests/index.test.ts +9 -0
  46. package/tests/mcp.test.ts +225 -0
  47. package/tests/options.test.ts +304 -0
  48. package/tests/setupVitest.ts +6 -0
  49. package/tests/ui-environment.test.ts +97 -0
  50. package/tests/ui-prompts.test.ts +238 -0
  51. package/tsconfig.json +17 -0
  52. package/vitest.config.js +7 -0
  53. package/dist/bin.cjs +0 -761
  54. package/dist/bin.d.cts +0 -1
  55. package/dist/bin.d.mts +0 -1
  56. package/dist/bin.mjs +0 -760
  57. package/dist/index.cjs +0 -36
  58. package/dist/index.d.cts +0 -1172
  59. package/dist/index.d.mts +0 -1172
  60. package/dist/index.mjs +0 -3
  61. package/dist/template-CkAkdP8n.mjs +0 -2545
  62. package/dist/template-Cup47s9h.cjs +0 -2783
  63. package/src/api/fetch.test.ts +0 -114
  64. package/src/api/fetch.ts +0 -249
  65. package/src/cache/index.ts +0 -89
  66. package/src/commands/create.ts +0 -463
  67. package/src/commands/mcp.test.ts +0 -152
  68. package/src/commands/mcp.ts +0 -203
  69. package/src/engine/compile-with-addons.test.ts +0 -302
  70. package/src/engine/compile.test.ts +0 -404
  71. package/src/engine/compile.ts +0 -551
  72. package/src/engine/config-file.test.ts +0 -118
  73. package/src/engine/config-file.ts +0 -61
  74. package/src/engine/custom-addons/integration.ts +0 -323
  75. package/src/engine/custom-addons/shared.test.ts +0 -98
  76. package/src/engine/custom-addons/shared.ts +0 -281
  77. package/src/engine/custom-addons/template.test.ts +0 -288
  78. package/src/engine/custom-addons/template.ts +0 -124
  79. package/src/engine/template.test.ts +0 -256
  80. package/src/engine/template.ts +0 -269
  81. package/src/engine/types.ts +0 -336
  82. package/src/parse-gitignore.d.ts +0 -5
  83. package/src/templates/base.ts +0 -891
@@ -1,2783 +0,0 @@
1
- //#region rolldown:runtime
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") {
10
- for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
- key = keys[i];
12
- if (!__hasOwnProp.call(to, key) && key !== except) {
13
- __defProp(to, key, {
14
- get: ((k) => from[k]).bind(null, key),
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- });
17
- }
18
- }
19
- }
20
- return to;
21
- };
22
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
- value: mod,
24
- enumerable: true
25
- }) : target, mod));
26
-
27
- //#endregion
28
- let ejs = require("ejs");
29
- let node_fs_promises = require("node:fs/promises");
30
- let node_fs = require("node:fs");
31
- let node_path = require("node:path");
32
- let zod = require("zod");
33
- let ignore = require("ignore");
34
- ignore = __toESM(ignore);
35
- let parse_gitignore = require("parse-gitignore");
36
- parse_gitignore = __toESM(parse_gitignore);
37
- let node_os = require("node:os");
38
-
39
- //#region src/engine/template.ts
40
- /**
41
- * Convert _dot_ prefixes to actual dots (for dotfiles)
42
- */
43
- function convertDotFiles(path) {
44
- return path.split("/").map((segment) => segment.replace(/^_dot_/, ".")).join("/");
45
- }
46
- /**
47
- * Strip option prefixes from filename
48
- * e.g., __postgres__schema.prisma -> schema.prisma
49
- */
50
- function stripOptionPrefix(path) {
51
- const match = path.match(/^(.+\/)?__([^_]+)__(.+)$/);
52
- if (match) {
53
- const [, directory, , filename] = match;
54
- return (directory || "") + filename;
55
- }
56
- return path;
57
- }
58
- /**
59
- * Calculate relative path between two file paths
60
- */
61
- function relativePath(from, to, stripExtension = false) {
62
- const fromParts = from.split("/").slice(0, -1);
63
- const toParts = to.split("/");
64
- let commonLength = 0;
65
- while (commonLength < fromParts.length && commonLength < toParts.length && fromParts[commonLength] === toParts[commonLength]) commonLength++;
66
- const upCount = fromParts.length - commonLength;
67
- const ups = Array(upCount).fill("..");
68
- const remainder = toParts.slice(commonLength);
69
- let result = [...ups, ...remainder].join("/");
70
- if (!result.startsWith(".")) result = "./" + result;
71
- if (stripExtension) result = result.replace(/\.[^/.]+$/, "");
72
- return result;
73
- }
74
- /**
75
- * Error thrown when ignoreFile() is called in a template
76
- */
77
- var IgnoreFileError = class extends Error {
78
- constructor() {
79
- super("ignoreFile");
80
- this.name = "IgnoreFileError";
81
- }
82
- };
83
- /**
84
- * Create template context from compile options
85
- */
86
- function createTemplateContext(options, currentFile) {
87
- const hooks = [];
88
- for (const integration of options.chosenIntegrations) if (integration.hooks) hooks.push(...integration.hooks);
89
- const routes = [];
90
- for (const integration of options.chosenIntegrations) if (integration.routes) routes.push(...integration.routes);
91
- const integrationEnabled = {};
92
- for (const integration of options.chosenIntegrations) integrationEnabled[integration.id] = true;
93
- const localRelativePath = (to, stripExt = false) => relativePath(currentFile, to, stripExt);
94
- const hookImportContent = (hook) => hook.import || `import ${hook.jsName} from '${localRelativePath(hook.path || "")}'`;
95
- const hookImportCode = (hook) => hook.code || hook.jsName || "";
96
- return {
97
- packageManager: options.packageManager,
98
- projectName: options.projectName,
99
- typescript: options.typescript,
100
- tailwind: options.tailwind,
101
- js: options.typescript ? "ts" : "js",
102
- jsx: options.typescript ? "tsx" : "jsx",
103
- fileRouter: options.mode === "file-router",
104
- codeRouter: options.mode === "code-router",
105
- integrationEnabled,
106
- integrationOption: options.integrationOptions,
107
- integrations: options.chosenIntegrations,
108
- hooks,
109
- routes,
110
- getPackageManagerAddScript: (pkg, isDev = false) => {
111
- const pm = options.packageManager;
112
- if (pm === "npm") return `npm install ${isDev ? "-D " : ""}${pkg}`;
113
- if (pm === "yarn") return `yarn add ${isDev ? "-D " : ""}${pkg}`;
114
- if (pm === "pnpm") return `pnpm add ${isDev ? "-D " : ""}${pkg}`;
115
- if (pm === "bun") return `bun add ${isDev ? "-d " : ""}${pkg}`;
116
- if (pm === "deno") return `deno add ${pkg}`;
117
- return `npm install ${isDev ? "-D " : ""}${pkg}`;
118
- },
119
- getPackageManagerRunScript: (script, args = []) => {
120
- const pm = options.packageManager;
121
- const argsStr = args.length ? " " + args.join(" ") : "";
122
- if (pm === "npm") return `npm run ${script}${argsStr}`;
123
- if (pm === "yarn") return `yarn ${script}${argsStr}`;
124
- if (pm === "pnpm") return `pnpm ${script}${argsStr}`;
125
- if (pm === "bun") return `bun run ${script}${argsStr}`;
126
- if (pm === "deno") return `deno task ${script}${argsStr}`;
127
- return `npm run ${script}${argsStr}`;
128
- },
129
- relativePath: localRelativePath,
130
- hookImportContent,
131
- hookImportCode,
132
- ignoreFile: () => {
133
- throw new IgnoreFileError();
134
- }
135
- };
136
- }
137
- /**
138
- * Process a template file with EJS
139
- */
140
- function processTemplateFile(filePath, content, options) {
141
- const context = createTemplateContext(options, filePath);
142
- let processedContent = content;
143
- let shouldIgnore = false;
144
- if (filePath.endsWith(".ejs")) try {
145
- processedContent = (0, ejs.render)(content, context);
146
- } catch (error) {
147
- if (error instanceof IgnoreFileError) shouldIgnore = true;
148
- else throw new Error(`EJS error in file ${filePath}: ${error}`);
149
- }
150
- if (shouldIgnore) return null;
151
- let outputPath = filePath;
152
- outputPath = outputPath.replace(/\.ejs$/, "");
153
- outputPath = convertDotFiles(outputPath);
154
- outputPath = stripOptionPrefix(outputPath);
155
- let append = false;
156
- if (outputPath.endsWith(".append")) {
157
- append = true;
158
- outputPath = outputPath.replace(/\.append$/, "");
159
- }
160
- if (!options.typescript) outputPath = outputPath.replace(/\.tsx$/, ".jsx").replace(/\.ts$/, ".js");
161
- return {
162
- path: outputPath,
163
- content: processedContent,
164
- append
165
- };
166
- }
167
-
168
- //#endregion
169
- //#region src/templates/base.ts
170
- /**
171
- * Base TanStack Start template files
172
- * These provide the foundation for every project
173
- */
174
- /**
175
- * Collect all hooks from integrations, grouped by type
176
- */
177
- function collectHooks(options) {
178
- const hooks = [];
179
- for (const integration of options.chosenIntegrations) if (integration.hooks) for (const hook of integration.hooks) hooks.push({
180
- ...hook,
181
- integrationId: integration.id
182
- });
183
- return {
184
- vitePlugins: hooks.filter((i) => i.type === "vite-plugin"),
185
- rootProviders: hooks.filter((i) => i.type === "root-provider"),
186
- devtoolsPlugins: hooks.filter((i) => i.type === "devtools"),
187
- entryClientInits: hooks.filter((i) => i.type === "entry-client")
188
- };
189
- }
190
- /**
191
- * Generate vite.config.ts content with line attribution
192
- */
193
- function generateViteConfig(options, vitePlugins) {
194
- const { tailwind } = options;
195
- const lines = [];
196
- lines.push({
197
- text: `import { defineConfig } from 'vite'`,
198
- integrationId: "base"
199
- });
200
- lines.push({
201
- text: `import { tanstackStart } from '@tanstack/react-start/plugin/vite'`,
202
- integrationId: "base"
203
- });
204
- lines.push({
205
- text: `import viteReact from '@vitejs/plugin-react'`,
206
- integrationId: "base"
207
- });
208
- lines.push({
209
- text: `import viteTsConfigPaths from 'vite-tsconfig-paths'`,
210
- integrationId: "base"
211
- });
212
- if (tailwind) lines.push({
213
- text: `import tailwindcss from '@tailwindcss/vite'`,
214
- integrationId: "base"
215
- });
216
- for (const plugin of vitePlugins) if (plugin.import) lines.push({
217
- text: plugin.import,
218
- integrationId: plugin.integrationId
219
- });
220
- else {
221
- const importPath = relativePath("vite.config.ts", plugin.path || `src/integrations/${plugin.integrationId}/vite-plugin.ts`, true);
222
- lines.push({
223
- text: `import ${plugin.jsName} from '${importPath}'`,
224
- integrationId: plugin.integrationId
225
- });
226
- }
227
- lines.push({
228
- text: "",
229
- integrationId: "base"
230
- });
231
- lines.push({
232
- text: `export default defineConfig({`,
233
- integrationId: "base"
234
- });
235
- lines.push({
236
- text: ` plugins: [`,
237
- integrationId: "base"
238
- });
239
- lines.push({
240
- text: ` viteTsConfigPaths({`,
241
- integrationId: "base"
242
- });
243
- lines.push({
244
- text: ` projects: ['./tsconfig.json'],`,
245
- integrationId: "base"
246
- });
247
- lines.push({
248
- text: ` }),`,
249
- integrationId: "base"
250
- });
251
- if (tailwind) lines.push({
252
- text: ` tailwindcss(),`,
253
- integrationId: "base"
254
- });
255
- lines.push({
256
- text: ` tanstackStart(),`,
257
- integrationId: "base"
258
- });
259
- lines.push({
260
- text: ` viteReact(),`,
261
- integrationId: "base"
262
- });
263
- for (const plugin of vitePlugins) {
264
- const pluginCall = plugin.code || `${plugin.jsName}()`;
265
- lines.push({
266
- text: ` ${pluginCall},`,
267
- integrationId: plugin.integrationId
268
- });
269
- }
270
- lines.push({
271
- text: ` ],`,
272
- integrationId: "base"
273
- });
274
- lines.push({
275
- text: `})`,
276
- integrationId: "base"
277
- });
278
- return {
279
- content: lines.map((l) => l.text).join("\n"),
280
- lineAttributions: lines.map((l, i) => ({
281
- line: i + 1,
282
- integrationId: l.integrationId
283
- }))
284
- };
285
- }
286
- /**
287
- * Generate entry-client.tsx content with line attribution
288
- */
289
- function generateEntryClient(_options, entryClientInits) {
290
- const lines = [];
291
- lines.push({
292
- text: `import { hydrateRoot } from 'react-dom/client'`,
293
- integrationId: "base"
294
- });
295
- lines.push({
296
- text: `import { StartClient } from '@tanstack/react-start'`,
297
- integrationId: "base"
298
- });
299
- lines.push({
300
- text: `import { getRouter } from './router'`,
301
- integrationId: "base"
302
- });
303
- for (const init of entryClientInits) {
304
- const importPath = relativePath("src/entry-client.tsx", init.path || `src/integrations/${init.integrationId}/client.ts`, true);
305
- lines.push({
306
- text: `import { ${init.jsName} } from '${importPath}'`,
307
- integrationId: init.integrationId
308
- });
309
- }
310
- lines.push({
311
- text: "",
312
- integrationId: "base"
313
- });
314
- if (entryClientInits.length > 0) {
315
- lines.push({
316
- text: `// Initialize integrations`,
317
- integrationId: "base"
318
- });
319
- for (const init of entryClientInits) lines.push({
320
- text: `${init.jsName}()`,
321
- integrationId: init.integrationId
322
- });
323
- lines.push({
324
- text: "",
325
- integrationId: "base"
326
- });
327
- }
328
- lines.push({
329
- text: `const router = getRouter()`,
330
- integrationId: "base"
331
- });
332
- lines.push({
333
- text: "",
334
- integrationId: "base"
335
- });
336
- lines.push({
337
- text: `hydrateRoot(document.getElementById('root')!, <StartClient router={router} />)`,
338
- integrationId: "base"
339
- });
340
- return {
341
- content: lines.map((l) => l.text).join("\n"),
342
- lineAttributions: lines.map((l, i) => ({
343
- line: i + 1,
344
- integrationId: l.integrationId
345
- }))
346
- };
347
- }
348
- /**
349
- * Generate __root.tsx content with line attribution
350
- * This generates a full document route with shellComponent for proper SSR
351
- */
352
- function generateRootRoute(options, rootProviders, devtoolsPlugins) {
353
- const lines = [];
354
- const hasHeader = options.chosenIntegrations.length > 0;
355
- if (devtoolsPlugins.length > 0) lines.push({
356
- text: `import React from 'react'`,
357
- integrationId: "base"
358
- });
359
- lines.push({
360
- text: `import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'`,
361
- integrationId: "base"
362
- });
363
- lines.push({
364
- text: `import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'`,
365
- integrationId: "base"
366
- });
367
- lines.push({
368
- text: `import appCss from '../styles.css?url'`,
369
- integrationId: "base"
370
- });
371
- if (hasHeader) lines.push({
372
- text: `import { Header } from '../components/Header'`,
373
- integrationId: "base"
374
- });
375
- for (const provider of rootProviders) {
376
- const importPath = relativePath("src/routes/__root.tsx", provider.path || `src/integrations/${provider.integrationId}/provider.tsx`, true);
377
- lines.push({
378
- text: `import { ${provider.jsName} } from '${importPath}'`,
379
- integrationId: provider.integrationId
380
- });
381
- }
382
- for (const devtools of devtoolsPlugins) {
383
- const importPath = relativePath("src/routes/__root.tsx", devtools.path || `src/integrations/${devtools.integrationId}/devtools.tsx`, true);
384
- lines.push({
385
- text: `import { ${devtools.jsName} } from '${importPath}'`,
386
- integrationId: devtools.integrationId
387
- });
388
- }
389
- if (devtoolsPlugins.length > 0) {
390
- lines.push({
391
- text: "",
392
- integrationId: "base"
393
- });
394
- lines.push({
395
- text: `const devtoolsPlugins = [`,
396
- integrationId: "base"
397
- });
398
- for (const devtools of devtoolsPlugins) lines.push({
399
- text: ` ${devtools.jsName},`,
400
- integrationId: devtools.integrationId
401
- });
402
- lines.push({
403
- text: `]`,
404
- integrationId: "base"
405
- });
406
- }
407
- lines.push({
408
- text: "",
409
- integrationId: "base"
410
- });
411
- lines.push({
412
- text: `export const Route = createRootRoute({`,
413
- integrationId: "base"
414
- });
415
- lines.push({
416
- text: ` head: () => ({`,
417
- integrationId: "base"
418
- });
419
- lines.push({
420
- text: ` meta: [`,
421
- integrationId: "base"
422
- });
423
- lines.push({
424
- text: ` { charSet: 'utf-8' },`,
425
- integrationId: "base"
426
- });
427
- lines.push({
428
- text: ` { name: 'viewport', content: 'width=device-width, initial-scale=1' },`,
429
- integrationId: "base"
430
- });
431
- lines.push({
432
- text: ` { title: 'TanStack Start Starter' },`,
433
- integrationId: "base"
434
- });
435
- lines.push({
436
- text: ` ],`,
437
- integrationId: "base"
438
- });
439
- lines.push({
440
- text: ` links: [{ rel: 'stylesheet', href: appCss }],`,
441
- integrationId: "base"
442
- });
443
- lines.push({
444
- text: ` }),`,
445
- integrationId: "base"
446
- });
447
- lines.push({
448
- text: ` shellComponent: RootDocument,`,
449
- integrationId: "base"
450
- });
451
- lines.push({
452
- text: `})`,
453
- integrationId: "base"
454
- });
455
- lines.push({
456
- text: "",
457
- integrationId: "base"
458
- });
459
- lines.push({
460
- text: `function RootDocument({ children }: { children: React.ReactNode }) {`,
461
- integrationId: "base"
462
- });
463
- lines.push({
464
- text: ` return (`,
465
- integrationId: "base"
466
- });
467
- lines.push({
468
- text: ` <html lang="en">`,
469
- integrationId: "base"
470
- });
471
- lines.push({
472
- text: ` <head>`,
473
- integrationId: "base"
474
- });
475
- lines.push({
476
- text: ` <HeadContent />`,
477
- integrationId: "base"
478
- });
479
- lines.push({
480
- text: ` </head>`,
481
- integrationId: "base"
482
- });
483
- lines.push({
484
- text: ` <body>`,
485
- integrationId: "base"
486
- });
487
- let currentIndent = " ";
488
- for (const provider of rootProviders) {
489
- lines.push({
490
- text: `${currentIndent}<${provider.jsName}>`,
491
- integrationId: provider.integrationId
492
- });
493
- currentIndent += " ";
494
- }
495
- if (hasHeader) lines.push({
496
- text: `${currentIndent}<Header />`,
497
- integrationId: "base"
498
- });
499
- lines.push({
500
- text: `${currentIndent}{children}`,
501
- integrationId: "base"
502
- });
503
- lines.push({
504
- text: `${currentIndent}<TanStackRouterDevtools />`,
505
- integrationId: "base"
506
- });
507
- if (devtoolsPlugins.length > 0) {
508
- lines.push({
509
- text: `${currentIndent}{devtoolsPlugins.map((plugin, i) => (`,
510
- integrationId: "base"
511
- });
512
- lines.push({
513
- text: `${currentIndent} <React.Fragment key={i}>{plugin.render}</React.Fragment>`,
514
- integrationId: "base"
515
- });
516
- lines.push({
517
- text: `${currentIndent}))}`,
518
- integrationId: "base"
519
- });
520
- }
521
- for (const provider of [...rootProviders].reverse()) {
522
- currentIndent = currentIndent.slice(0, -2);
523
- lines.push({
524
- text: `${currentIndent}</${provider.jsName}>`,
525
- integrationId: provider.integrationId
526
- });
527
- }
528
- lines.push({
529
- text: ` <Scripts />`,
530
- integrationId: "base"
531
- });
532
- lines.push({
533
- text: ` </body>`,
534
- integrationId: "base"
535
- });
536
- lines.push({
537
- text: ` </html>`,
538
- integrationId: "base"
539
- });
540
- lines.push({
541
- text: ` )`,
542
- integrationId: "base"
543
- });
544
- lines.push({
545
- text: `}`,
546
- integrationId: "base"
547
- });
548
- return {
549
- content: lines.map((l) => l.text).join("\n"),
550
- lineAttributions: lines.map((l, i) => ({
551
- line: i + 1,
552
- integrationId: l.integrationId
553
- }))
554
- };
555
- }
556
- /**
557
- * Collect routes from integrations for navigation
558
- */
559
- function collectRoutes(options) {
560
- const routes = [];
561
- for (const integration of options.chosenIntegrations) if (integration.routes) {
562
- for (const route of integration.routes) if (route.url && route.name) routes.push({
563
- url: route.url,
564
- name: route.name,
565
- icon: route.icon || "Globe"
566
- });
567
- }
568
- return routes;
569
- }
570
- /**
571
- * Generate Header component with slide-out drawer navigation
572
- */
573
- function generateHeader(options) {
574
- const lines = [];
575
- const routes = collectRoutes(options);
576
- const icons = new Set([
577
- "Menu",
578
- "X",
579
- "Home"
580
- ]);
581
- for (const route of routes) icons.add(route.icon);
582
- lines.push({
583
- text: `import { useState } from 'react'`,
584
- integrationId: "base"
585
- });
586
- lines.push({
587
- text: `import { Link } from '@tanstack/react-router'`,
588
- integrationId: "base"
589
- });
590
- lines.push({
591
- text: `import { ${Array.from(icons).sort().join(", ")} } from 'lucide-react'`,
592
- integrationId: "base"
593
- });
594
- lines.push({
595
- text: "",
596
- integrationId: "base"
597
- });
598
- lines.push({
599
- text: `export function Header() {`,
600
- integrationId: "base"
601
- });
602
- lines.push({
603
- text: ` const [isOpen, setIsOpen] = useState(false)`,
604
- integrationId: "base"
605
- });
606
- lines.push({
607
- text: "",
608
- integrationId: "base"
609
- });
610
- lines.push({
611
- text: ` return (`,
612
- integrationId: "base"
613
- });
614
- lines.push({
615
- text: ` <>`,
616
- integrationId: "base"
617
- });
618
- lines.push({
619
- text: ` <header className="p-4 flex items-center bg-gray-800 text-white shadow-lg">`,
620
- integrationId: "base"
621
- });
622
- lines.push({
623
- text: ` <button`,
624
- integrationId: "base"
625
- });
626
- lines.push({
627
- text: ` onClick={() => setIsOpen(true)}`,
628
- integrationId: "base"
629
- });
630
- lines.push({
631
- text: ` className="p-2 hover:bg-gray-700 rounded-lg transition-colors"`,
632
- integrationId: "base"
633
- });
634
- lines.push({
635
- text: ` aria-label="Open menu"`,
636
- integrationId: "base"
637
- });
638
- lines.push({
639
- text: ` >`,
640
- integrationId: "base"
641
- });
642
- lines.push({
643
- text: ` <Menu size={24} />`,
644
- integrationId: "base"
645
- });
646
- lines.push({
647
- text: ` </button>`,
648
- integrationId: "base"
649
- });
650
- lines.push({
651
- text: ` <h1 className="ml-4 text-xl font-semibold">`,
652
- integrationId: "base"
653
- });
654
- lines.push({
655
- text: ` <Link to="/">`,
656
- integrationId: "base"
657
- });
658
- lines.push({
659
- text: ` <img`,
660
- integrationId: "base"
661
- });
662
- lines.push({
663
- text: ` src="/tanstack-logo-light.svg"`,
664
- integrationId: "base"
665
- });
666
- lines.push({
667
- text: ` alt="TanStack Logo"`,
668
- integrationId: "base"
669
- });
670
- lines.push({
671
- text: ` className="h-10"`,
672
- integrationId: "base"
673
- });
674
- lines.push({
675
- text: ` />`,
676
- integrationId: "base"
677
- });
678
- lines.push({
679
- text: ` </Link>`,
680
- integrationId: "base"
681
- });
682
- lines.push({
683
- text: ` </h1>`,
684
- integrationId: "base"
685
- });
686
- lines.push({
687
- text: ` </header>`,
688
- integrationId: "base"
689
- });
690
- lines.push({
691
- text: "",
692
- integrationId: "base"
693
- });
694
- lines.push({
695
- text: ` <aside`,
696
- integrationId: "base"
697
- });
698
- lines.push({
699
- text: ` className={\`fixed top-0 left-0 h-full w-80 bg-gray-900 text-white shadow-2xl z-50 transform transition-transform duration-300 ease-in-out flex flex-col \${`,
700
- integrationId: "base"
701
- });
702
- lines.push({
703
- text: ` isOpen ? 'translate-x-0' : '-translate-x-full'`,
704
- integrationId: "base"
705
- });
706
- lines.push({
707
- text: ` }\`}`,
708
- integrationId: "base"
709
- });
710
- lines.push({
711
- text: ` >`,
712
- integrationId: "base"
713
- });
714
- lines.push({
715
- text: ` <div className="flex items-center justify-between p-4 border-b border-gray-700">`,
716
- integrationId: "base"
717
- });
718
- lines.push({
719
- text: ` <h2 className="text-xl font-bold">Navigation</h2>`,
720
- integrationId: "base"
721
- });
722
- lines.push({
723
- text: ` <button`,
724
- integrationId: "base"
725
- });
726
- lines.push({
727
- text: ` onClick={() => setIsOpen(false)}`,
728
- integrationId: "base"
729
- });
730
- lines.push({
731
- text: ` className="p-2 hover:bg-gray-800 rounded-lg transition-colors"`,
732
- integrationId: "base"
733
- });
734
- lines.push({
735
- text: ` aria-label="Close menu"`,
736
- integrationId: "base"
737
- });
738
- lines.push({
739
- text: ` >`,
740
- integrationId: "base"
741
- });
742
- lines.push({
743
- text: ` <X size={24} />`,
744
- integrationId: "base"
745
- });
746
- lines.push({
747
- text: ` </button>`,
748
- integrationId: "base"
749
- });
750
- lines.push({
751
- text: ` </div>`,
752
- integrationId: "base"
753
- });
754
- lines.push({
755
- text: "",
756
- integrationId: "base"
757
- });
758
- lines.push({
759
- text: ` <nav className="flex-1 p-4 overflow-y-auto">`,
760
- integrationId: "base"
761
- });
762
- lines.push({
763
- text: ` <Link`,
764
- integrationId: "base"
765
- });
766
- lines.push({
767
- text: ` to="/"`,
768
- integrationId: "base"
769
- });
770
- lines.push({
771
- text: ` onClick={() => setIsOpen(false)}`,
772
- integrationId: "base"
773
- });
774
- lines.push({
775
- text: ` className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2"`,
776
- integrationId: "base"
777
- });
778
- lines.push({
779
- text: ` activeProps={{`,
780
- integrationId: "base"
781
- });
782
- lines.push({
783
- text: ` className: 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',`,
784
- integrationId: "base"
785
- });
786
- lines.push({
787
- text: ` }}`,
788
- integrationId: "base"
789
- });
790
- lines.push({
791
- text: ` >`,
792
- integrationId: "base"
793
- });
794
- lines.push({
795
- text: ` <Home size={20} />`,
796
- integrationId: "base"
797
- });
798
- lines.push({
799
- text: ` <span className="font-medium">Home</span>`,
800
- integrationId: "base"
801
- });
802
- lines.push({
803
- text: ` </Link>`,
804
- integrationId: "base"
805
- });
806
- for (const route of routes) {
807
- const integrationId = options.chosenIntegrations.find((i) => i.routes?.some((r) => r.url === route.url))?.id || "base";
808
- lines.push({
809
- text: "",
810
- integrationId
811
- });
812
- lines.push({
813
- text: ` <Link`,
814
- integrationId
815
- });
816
- lines.push({
817
- text: ` to="${route.url}"`,
818
- integrationId
819
- });
820
- lines.push({
821
- text: ` onClick={() => setIsOpen(false)}`,
822
- integrationId
823
- });
824
- lines.push({
825
- text: ` className="flex items-center gap-3 p-3 rounded-lg hover:bg-gray-800 transition-colors mb-2"`,
826
- integrationId
827
- });
828
- lines.push({
829
- text: ` activeProps={{`,
830
- integrationId
831
- });
832
- lines.push({
833
- text: ` className: 'flex items-center gap-3 p-3 rounded-lg bg-cyan-600 hover:bg-cyan-700 transition-colors mb-2',`,
834
- integrationId
835
- });
836
- lines.push({
837
- text: ` }}`,
838
- integrationId
839
- });
840
- lines.push({
841
- text: ` >`,
842
- integrationId
843
- });
844
- lines.push({
845
- text: ` <${route.icon} size={20} />`,
846
- integrationId
847
- });
848
- lines.push({
849
- text: ` <span className="font-medium">${route.name}</span>`,
850
- integrationId
851
- });
852
- lines.push({
853
- text: ` </Link>`,
854
- integrationId
855
- });
856
- }
857
- lines.push({
858
- text: ` </nav>`,
859
- integrationId: "base"
860
- });
861
- lines.push({
862
- text: ` </aside>`,
863
- integrationId: "base"
864
- });
865
- lines.push({
866
- text: "",
867
- integrationId: "base"
868
- });
869
- lines.push({
870
- text: ` {isOpen && (`,
871
- integrationId: "base"
872
- });
873
- lines.push({
874
- text: ` <div`,
875
- integrationId: "base"
876
- });
877
- lines.push({
878
- text: ` className="fixed inset-0 bg-black/50 z-40"`,
879
- integrationId: "base"
880
- });
881
- lines.push({
882
- text: ` onClick={() => setIsOpen(false)}`,
883
- integrationId: "base"
884
- });
885
- lines.push({
886
- text: ` />`,
887
- integrationId: "base"
888
- });
889
- lines.push({
890
- text: ` )}`,
891
- integrationId: "base"
892
- });
893
- lines.push({
894
- text: ` </>`,
895
- integrationId: "base"
896
- });
897
- lines.push({
898
- text: ` )`,
899
- integrationId: "base"
900
- });
901
- lines.push({
902
- text: `}`,
903
- integrationId: "base"
904
- });
905
- return {
906
- content: lines.map((l) => l.text).join("\n"),
907
- lineAttributions: lines.map((l, i) => ({
908
- line: i + 1,
909
- integrationId: l.integrationId
910
- }))
911
- };
912
- }
913
- /**
914
- * Generate .gitignore content with line attribution
915
- */
916
- function generateGitignore(integrationPatterns) {
917
- const lines = [];
918
- lines.push({
919
- text: "# Dependencies",
920
- integrationId: "base"
921
- });
922
- lines.push({
923
- text: "node_modules/",
924
- integrationId: "base"
925
- });
926
- lines.push({
927
- text: ".pnpm-store/",
928
- integrationId: "base"
929
- });
930
- lines.push({
931
- text: "",
932
- integrationId: "base"
933
- });
934
- lines.push({
935
- text: "# Build outputs",
936
- integrationId: "base"
937
- });
938
- lines.push({
939
- text: "dist/",
940
- integrationId: "base"
941
- });
942
- lines.push({
943
- text: ".output/",
944
- integrationId: "base"
945
- });
946
- lines.push({
947
- text: ".vinxi/",
948
- integrationId: "base"
949
- });
950
- lines.push({
951
- text: ".vercel/",
952
- integrationId: "base"
953
- });
954
- lines.push({
955
- text: ".netlify/",
956
- integrationId: "base"
957
- });
958
- lines.push({
959
- text: "",
960
- integrationId: "base"
961
- });
962
- lines.push({
963
- text: "# Environment",
964
- integrationId: "base"
965
- });
966
- lines.push({
967
- text: ".env",
968
- integrationId: "base"
969
- });
970
- lines.push({
971
- text: ".env.*",
972
- integrationId: "base"
973
- });
974
- lines.push({
975
- text: "!.env.example",
976
- integrationId: "base"
977
- });
978
- lines.push({
979
- text: "",
980
- integrationId: "base"
981
- });
982
- lines.push({
983
- text: "# IDE",
984
- integrationId: "base"
985
- });
986
- lines.push({
987
- text: ".idea/",
988
- integrationId: "base"
989
- });
990
- lines.push({
991
- text: ".vscode/",
992
- integrationId: "base"
993
- });
994
- lines.push({
995
- text: "*.swp",
996
- integrationId: "base"
997
- });
998
- lines.push({
999
- text: "*.swo",
1000
- integrationId: "base"
1001
- });
1002
- lines.push({
1003
- text: "",
1004
- integrationId: "base"
1005
- });
1006
- lines.push({
1007
- text: "# OS",
1008
- integrationId: "base"
1009
- });
1010
- lines.push({
1011
- text: ".DS_Store",
1012
- integrationId: "base"
1013
- });
1014
- lines.push({
1015
- text: "Thumbs.db",
1016
- integrationId: "base"
1017
- });
1018
- lines.push({
1019
- text: "",
1020
- integrationId: "base"
1021
- });
1022
- lines.push({
1023
- text: "# Logs",
1024
- integrationId: "base"
1025
- });
1026
- lines.push({
1027
- text: "*.log",
1028
- integrationId: "base"
1029
- });
1030
- lines.push({
1031
- text: "npm-debug.log*",
1032
- integrationId: "base"
1033
- });
1034
- lines.push({
1035
- text: "pnpm-debug.log*",
1036
- integrationId: "base"
1037
- });
1038
- lines.push({
1039
- text: "",
1040
- integrationId: "base"
1041
- });
1042
- lines.push({
1043
- text: "# Generated",
1044
- integrationId: "base"
1045
- });
1046
- lines.push({
1047
- text: "src/routeTree.gen.ts",
1048
- integrationId: "base"
1049
- });
1050
- if (integrationPatterns.length > 0) {
1051
- lines.push({
1052
- text: "",
1053
- integrationId: "base"
1054
- });
1055
- lines.push({
1056
- text: "# Integration-specific",
1057
- integrationId: "base"
1058
- });
1059
- for (const { pattern, integrationId } of integrationPatterns) lines.push({
1060
- text: pattern,
1061
- integrationId
1062
- });
1063
- }
1064
- return {
1065
- content: lines.map((l) => l.text).join("\n"),
1066
- lineAttributions: lines.map((l, i) => ({
1067
- line: i + 1,
1068
- integrationId: l.integrationId
1069
- }))
1070
- };
1071
- }
1072
- /**
1073
- * Get base template files (static files without hook injection)
1074
- */
1075
- function getBaseFiles(options) {
1076
- const { projectName, typescript, tailwind, packageManager } = options;
1077
- const files = {};
1078
- const { vitePlugins, rootProviders, devtoolsPlugins, entryClientInits } = collectHooks(options);
1079
- if (typescript) files["tsconfig.json"] = JSON.stringify({
1080
- compilerOptions: {
1081
- target: "ES2022",
1082
- lib: [
1083
- "ES2022",
1084
- "DOM",
1085
- "DOM.Iterable"
1086
- ],
1087
- module: "ESNext",
1088
- skipLibCheck: true,
1089
- moduleResolution: "bundler",
1090
- allowImportingTsExtensions: true,
1091
- resolveJsonModule: true,
1092
- isolatedModules: true,
1093
- moduleDetection: "force",
1094
- noEmit: true,
1095
- jsx: "react-jsx",
1096
- strict: true,
1097
- noUnusedLocals: true,
1098
- noUnusedParameters: true,
1099
- noFallthroughCasesInSwitch: true,
1100
- noUncheckedIndexedAccess: true,
1101
- paths: { "~/*": ["./src/*"] }
1102
- },
1103
- include: ["src"]
1104
- }, null, 2);
1105
- files[typescript ? "vite.config.ts" : "vite.config.js"] = generateViteConfig(options, vitePlugins).content;
1106
- if (entryClientInits.length > 0) files[`src/entry-client.${typescript ? "tsx" : "jsx"}`] = generateEntryClient(options, entryClientInits).content;
1107
- files[`src/router.${typescript ? "tsx" : "jsx"}`] = `import { createRouter as createTanStackRouter } from '@tanstack/react-router'
1108
- import { routeTree } from './routeTree.gen'
1109
-
1110
- export function getRouter() {
1111
- const router = createTanStackRouter({
1112
- routeTree,
1113
- defaultPreload: 'intent',
1114
- scrollRestoration: true,
1115
- })
1116
-
1117
- return router
1118
- }
1119
-
1120
- declare module '@tanstack/react-router' {
1121
- interface Register {
1122
- router: ReturnType<typeof getRouter>
1123
- }
1124
- }
1125
- `;
1126
- files[`src/routes/__root.${typescript ? "tsx" : "jsx"}`] = generateRootRoute(options, rootProviders, devtoolsPlugins).content;
1127
- const hasHeader = options.chosenIntegrations.length > 0;
1128
- if (hasHeader && tailwind) files[`src/components/Header.${typescript ? "tsx" : "jsx"}`] = generateHeader(options).content;
1129
- const indexRouteWithHeader = `import { createFileRoute } from '@tanstack/react-router'
1130
-
1131
- export const Route = createFileRoute('/')({
1132
- component: Home,
1133
- })
1134
-
1135
- function Home() {
1136
- return (
1137
- <div className="min-h-[calc(100vh-72px)] bg-gradient-to-br from-gray-900 to-gray-800 flex items-center justify-center">
1138
- <div className="text-center px-4">
1139
- <img
1140
- src="/tanstack-logo-dark.svg"
1141
- alt="TanStack Logo"
1142
- className="h-24 mx-auto mb-8"
1143
- />
1144
- <h1 className="text-5xl font-bold text-white mb-4">
1145
- Welcome to TanStack Start
1146
- </h1>
1147
- <p className="text-xl text-gray-300 mb-8">
1148
- Full-stack React framework powered by TanStack Router
1149
- </p>
1150
- <div className="flex gap-4 justify-center flex-wrap">
1151
- <a
1152
- href="https://tanstack.com/start"
1153
- target="_blank"
1154
- rel="noopener noreferrer"
1155
- className="px-6 py-3 bg-cyan-500 text-white rounded-lg font-medium hover:bg-cyan-600 transition-colors"
1156
- >
1157
- Documentation
1158
- </a>
1159
- <a
1160
- href="https://github.com/tanstack/router"
1161
- target="_blank"
1162
- rel="noopener noreferrer"
1163
- className="px-6 py-3 bg-gray-700 text-white rounded-lg font-medium hover:bg-gray-600 transition-colors"
1164
- >
1165
- GitHub
1166
- </a>
1167
- </div>
1168
- </div>
1169
- </div>
1170
- )
1171
- }
1172
- `;
1173
- const indexRouteNoHeader = `import { createFileRoute } from '@tanstack/react-router'
1174
-
1175
- export const Route = createFileRoute('/')({
1176
- component: Home,
1177
- })
1178
-
1179
- function Home() {
1180
- return (
1181
- <div className="min-h-screen bg-gradient-to-br from-gray-900 to-gray-800 flex items-center justify-center">
1182
- <div className="text-center px-4">
1183
- <img
1184
- src="/tanstack-logo-dark.svg"
1185
- alt="TanStack Logo"
1186
- className="h-24 mx-auto mb-8"
1187
- />
1188
- <h1 className="text-5xl font-bold text-white mb-4">
1189
- Welcome to TanStack Start
1190
- </h1>
1191
- <p className="text-xl text-gray-300 mb-8">
1192
- Full-stack React framework powered by TanStack Router
1193
- </p>
1194
- <div className="flex gap-4 justify-center flex-wrap">
1195
- <a
1196
- href="https://tanstack.com/start"
1197
- target="_blank"
1198
- rel="noopener noreferrer"
1199
- className="px-6 py-3 bg-cyan-500 text-white rounded-lg font-medium hover:bg-cyan-600 transition-colors"
1200
- >
1201
- Documentation
1202
- </a>
1203
- <a
1204
- href="https://github.com/tanstack/router"
1205
- target="_blank"
1206
- rel="noopener noreferrer"
1207
- className="px-6 py-3 bg-gray-700 text-white rounded-lg font-medium hover:bg-gray-600 transition-colors"
1208
- >
1209
- GitHub
1210
- </a>
1211
- </div>
1212
- </div>
1213
- </div>
1214
- )
1215
- }
1216
- `;
1217
- const indexRouteNoTailwind = `import { createFileRoute } from '@tanstack/react-router'
1218
-
1219
- export const Route = createFileRoute('/')({
1220
- component: Home,
1221
- })
1222
-
1223
- function Home() {
1224
- return (
1225
- <div style={styles.container}>
1226
- <div style={styles.content}>
1227
- <img
1228
- src="/tanstack-logo-dark.svg"
1229
- alt="TanStack Logo"
1230
- style={styles.logo}
1231
- />
1232
- <h1 style={styles.title}>Welcome to TanStack Start</h1>
1233
- <p style={styles.subtitle}>
1234
- Full-stack React framework powered by TanStack Router
1235
- </p>
1236
- <div style={styles.buttons}>
1237
- <a
1238
- href="https://tanstack.com/start"
1239
- target="_blank"
1240
- rel="noopener noreferrer"
1241
- style={styles.primaryButton}
1242
- >
1243
- Documentation
1244
- </a>
1245
- <a
1246
- href="https://github.com/tanstack/router"
1247
- target="_blank"
1248
- rel="noopener noreferrer"
1249
- style={styles.secondaryButton}
1250
- >
1251
- GitHub
1252
- </a>
1253
- </div>
1254
- </div>
1255
- </div>
1256
- )
1257
- }
1258
-
1259
- const styles = {
1260
- container: {
1261
- minHeight: '100vh',
1262
- background: 'linear-gradient(to bottom right, #111827, #1f2937)',
1263
- display: 'flex',
1264
- alignItems: 'center',
1265
- justifyContent: 'center',
1266
- },
1267
- content: {
1268
- textAlign: 'center' as const,
1269
- padding: '0 1rem',
1270
- },
1271
- logo: {
1272
- height: '6rem',
1273
- marginBottom: '2rem',
1274
- },
1275
- title: {
1276
- fontSize: '3rem',
1277
- fontWeight: 'bold',
1278
- color: 'white',
1279
- marginBottom: '1rem',
1280
- },
1281
- subtitle: {
1282
- fontSize: '1.25rem',
1283
- color: '#d1d5db',
1284
- marginBottom: '2rem',
1285
- },
1286
- buttons: {
1287
- display: 'flex',
1288
- gap: '1rem',
1289
- justifyContent: 'center',
1290
- flexWrap: 'wrap' as const,
1291
- },
1292
- primaryButton: {
1293
- padding: '0.75rem 1.5rem',
1294
- backgroundColor: '#06b6d4',
1295
- color: 'white',
1296
- borderRadius: '0.5rem',
1297
- fontWeight: 500,
1298
- textDecoration: 'none',
1299
- },
1300
- secondaryButton: {
1301
- padding: '0.75rem 1.5rem',
1302
- backgroundColor: '#374151',
1303
- color: 'white',
1304
- borderRadius: '0.5rem',
1305
- fontWeight: 500,
1306
- textDecoration: 'none',
1307
- },
1308
- }
1309
- `;
1310
- if (tailwind) files[`src/routes/index.${typescript ? "tsx" : "jsx"}`] = hasHeader ? indexRouteWithHeader : indexRouteNoHeader;
1311
- else files[`src/routes/index.${typescript ? "tsx" : "jsx"}`] = indexRouteNoTailwind;
1312
- if (tailwind) files["src/styles.css"] = `@import 'tailwindcss';
1313
-
1314
- body {
1315
- @apply m-0;
1316
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
1317
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
1318
- sans-serif;
1319
- -webkit-font-smoothing: antialiased;
1320
- -moz-osx-font-smoothing: grayscale;
1321
- }
1322
-
1323
- code {
1324
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
1325
- monospace;
1326
- }
1327
- `;
1328
- else files["src/styles.css"] = `* {
1329
- box-sizing: border-box;
1330
- margin: 0;
1331
- padding: 0;
1332
- }
1333
-
1334
- body {
1335
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
1336
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
1337
- sans-serif;
1338
- -webkit-font-smoothing: antialiased;
1339
- -moz-osx-font-smoothing: grayscale;
1340
- line-height: 1.5;
1341
- }
1342
-
1343
- code {
1344
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
1345
- monospace;
1346
- }
1347
- `;
1348
- files["public/tanstack-logo-light.svg"] = `<svg height="660" viewBox="0 0 663 660" width="663" xmlns="http://www.w3.org/2000/svg"><path d="m305.114318.62443771c8.717817-1.14462121 17.926803-.36545135 26.712694-.36545135 32.548987 0 64.505987 5.05339923 95.64868 14.63098274 39.74418 12.2236582 76.762804 31.7666864 109.435876 57.477568 40.046637 31.5132839 73.228974 72.8472109 94.520714 119.2362609 39.836383 86.790386 39.544267 191.973146-1.268422 278.398081-26.388695 55.880442-68.724007 102.650458-119.964986 136.75724-41.808813 27.828603-90.706831 44.862601-140.45707 50.89341-63.325458 7.677926-131.784923-3.541603-188.712259-32.729444-106.868873-54.795293-179.52309291-165.076271-180.9604082-285.932068-.27660564-23.300971.08616998-46.74071 4.69884909-69.814998 7.51316071-37.57857 20.61272131-73.903917 40.28618971-106.877282 21.2814003-35.670293 48.7704861-67.1473767 81.6882804-92.5255597 38.602429-29.7610135 83.467691-51.1674988 130.978372-62.05777669 11.473831-2.62966514 22.9946-4.0869914 34.57273-5.4964306l3.658171-.44480576c3.050084-.37153079 6.104217-.74794222 9.162589-1.14972654zm-110.555861 549.44131429c-14.716752 1.577863-30.238964 4.25635-42.869928 12.522173 2.84343.683658 6.102369.004954 9.068638 0 7.124652-.011559 14.317732-.279903 21.434964.032202 17.817402.781913 36.381729 3.63214 53.58741 8.350042 22.029372 6.040631 41.432961 17.928687 62.656049 25.945156 22.389644 8.456554 44.67706 11.084675 68.427 11.084675 11.96813 0 23.845573-.035504 35.450133-3.302696-6.056202-3.225083-14.72582-2.619864-21.434964-3.963236-14.556814-2.915455-28.868774-6.474936-42.869928-11.470264-10.304996-3.676672-20.230803-8.214291-30.11097-12.848661l-6.348531-2.985046c-9.1705-4.309263-18.363277-8.560752-27.845391-12.142608-24.932161-9.418465-52.560181-14.071964-79.144482-11.221737zm22.259385-62.614168c-29.163917 0-58.660076 5.137344-84.915434 18.369597-6.361238 3.206092-12.407546 7.02566-18.137277 11.258891-1.746125 1.290529-4.841829 2.948483-5.487351 5.191839-.654591 2.275558 1.685942 4.182039 3.014086 5.637703 6.562396-3.497556 12.797498-7.199878 19.78612-9.855246 45.19892-17.169893 99.992458-13.570779 145.098218 2.172348 22.494346 7.851335 43.219483 19.592421 65.129314 28.800338 24.503461 10.297807 49.53043 16.975034 75.846795 20.399104 31.04195 4.037546 66.433549.7654 94.808495-13.242161 9.970556-4.921843 23.814245-12.422267 28.030337-23.320339-5.207047.454947-9.892236 2.685918-14.83959 4.224149-7.866632 2.445646-15.827248 4.51974-23.908229 6.138887-27.388113 5.486604-56.512458 6.619429-84.091013 1.639788-25.991939-4.693152-50.142596-14.119246-74.179513-24.03502l-3.068058-1.268177c-2.045137-.846788-4.089983-1.695816-6.135603-2.544467l-3.069142-1.272366c-12.279956-5.085721-24.606928-10.110797-37.210937-14.51024-24.485325-8.546552-50.726667-13.784628-76.671218-13.784628zm51.114145-447.9909432c-34.959602 7.7225298-66.276908 22.7605319-96.457338 41.7180089-17.521434 11.0054099-34.281927 22.2799893-49.465301 36.4444283-22.5792616 21.065423-39.8360564 46.668751-54.8866988 73.411509-15.507372 27.55357-25.4498976 59.665686-30.2554517 90.824149-4.7140432 30.568106-5.4906485 62.70747-.0906864 93.301172 6.7503648 38.248526 19.5989769 74.140579 39.8896436 107.337631 6.8187918-3.184625 11.659796-10.445603 17.3128555-15.336896 11.4149428-9.875888 23.3995608-19.029311 36.2745548-26.928535 4.765981-2.923712 9.662222-5.194315 14.83959-7.275014 1.953055-.785216 5.14604-1.502727 6.06527-3.647828 1.460876-3.406732-1.240754-9.335897-1.704904-12.865654-1.324845-10.095517-2.124534-20.362774-1.874735-30.549941.725492-29.668947 6.269727-59.751557 16.825623-87.521453 7.954845-20.924233 20.10682-39.922168 34.502872-56.971512 4.884699-5.785498 10.077731-11.170545 15.437296-16.512656 3.167428-3.157378 7.098271-5.858983 9.068639-9.908915-10.336599.006606-20.674847 2.987289-30.503603 6.013385-21.174447 6.519522-41.801477 16.19312-59.358362 29.841512-8.008432 6.226409-13.873368 14.387371-21.44733 20.939921-2.32322 2.010516-6.484901 4.704691-9.695199 3.187928-4.8500728-2.29042-4.1014979-11.835213-4.6571581-16.222019-2.1369011-16.873476 4.2548401-38.216325 12.3778671-52.843142 13.039878-23.479694 37.150915-43.528712 65.467327-42.82854 12.228647.302197 22.934587 4.551115 34.625711 7.324555-2.964621-4.211764-6.939158-7.28162-10.717482-10.733763-9.257431-8.459031-19.382979-16.184864-30.503603-22.028985-4.474136-2.350694-9.291232-3.77911-14.015169-5.506421-2.375159-.867783-5.36616-2.062533-6.259834-4.702213-1.654614-4.888817 7.148561-9.416813 10.381943-11.478522 12.499882-7.969406 27.826705-14.525258 42.869928-14.894334 23.509209-.577147 46.479246 12.467678 56.162903 34.665926 3.404469 7.803171 4.411273 16.054969 5.079109 24.382907l.121749 1.56229.174325 2.345587c.01913.260708.038244.521433.057403.782164l.11601 1.56437.120128 1.563971c7.38352-6.019164 12.576553-14.876995 19.78612-21.323859 16.861073-15.07846 39.936636-21.7722 61.831627-14.984333 19.786945 6.133107 36.984382 19.788105 47.105807 37.959541 2.648042 4.754231 10.035685 16.373942 4.698379 21.109183-4.177345 3.707277-9.475079.818243-13.880788-.719162-3.33605-1.16376-6.782939-1.90214-10.241828-2.585698l-1.887262-.369639c-.629089-.122886-1.257979-.246187-1.886079-.372129-11.980496-2.401886-25.91652-2.152533-37.923398-.041284-7.762754 1.364839-15.349083 4.127545-23.083807 5.271929v1.651348c21.149714.175043 41.608563 12.240618 52.043268 30.549941 4.323267 7.585468 6.482428 16.267431 8.138691 24.770223 2.047864 10.50918.608423 21.958802-2.263037 32.201289-.962925 3.433979-2.710699 9.255807-6.817143 10.046802-2.902789.558982-5.36781-2.330878-7.024898-4.279468-4.343878-5.10762-8.475879-9.96341-13.573278-14.374161-12.895604-11.157333-26.530715-21.449361-40.396663-31.373138-7.362086-5.269452-15.425755-12.12007-23.908229-15.340199 2.385052 5.745041 4.721463 11.086326 5.532694 17.339156 2.385876 18.392716-5.314223 35.704625-16.87179 49.540445-3.526876 4.222498-7.29943 8.475545-11.744712 11.755948-1.843407 1.360711-4.156734 3.137561-6.595373 2.752797-7.645687-1.207961-8.555849-12.73272-9.728176-18.637115-3.970415-19.998652-2.375984-39.861068 3.132802-59.448534-4.901187 2.485279-8.443727 7.923994-11.521293 12.385111-6.770975 9.816439-12.645804 20.199291-16.858599 31.375615-16.777806 44.519521-16.616219 96.664142 5.118834 139.523233 2.427098 4.786433 6.110614 4.144058 10.894733 4.144058.720854 0 1.44257-.004515 2.164851-.010924l2.168232-.022283c4.338648-.045438 8.686803-.064635 12.979772.508795 2.227588.297243 5.320818.032202 7.084256 1.673642 2.111344 1.966755.986008 5.338808.4996 7.758859-1.358647 6.765574-1.812904 12.914369-1.812904 19.816178 9.02412-1.398692 11.525415-15.866153 14.724172-23.118874 3.624982-8.216283 7.313444-16.440823 10.667192-24.770223 1.648843-4.093692 3.854171-8.671229 3.275427-13.210785-.649644-5.10184-4.335633-10.510831-6.904531-14.862134-4.86244-8.234447-10.389363-16.70834-13.969002-25.595896-2.861567-7.104926-.197036-15.983399 7.871579-18.521521 4.450228-1.400344 9.198073 1.345848 12.094266 4.562675 6.07269 6.74328 9.992815 16.777697 14.401823 24.692609l34.394873 61.925556c2.920926 5.243856 5.848447 10.481933 8.836976 15.687808 1.165732 2.031158 2.352075 5.167068 4.740424 6.0332 2.127008.77118 5.033095-.325315 7.148561-.748886 5.492297-1.099798 10.97635-2.287117 16.488434-3.28288 6.605266-1.193099 16.673928-.969342 21.434964-6.129805-6.963066-2.205375-15.011895-2.074919-22.259386-1.577863-4.352947.298894-9.178287 1.856116-13.178381-.686135-5.953149-3.783239-9.910373-12.522173-13.552668-18.377854-8.980425-14.439388-17.441465-29.095929-26.041008-43.760726l-1.376261-2.335014-2.765943-4.665258c-1.380597-2.334387-2.750786-4.67476-4.079753-7.036188-1.02723-1.826391-2.549937-4.233231-1.078344-6.24705 1.545791-2.114476 4.91472-2.239146 7.956473-2.243117l.603351.000261c1.195428.001526 2.315572.002427 3.222811-.11692 12.27399-1.615019 24.718635-2.952611 37.098976-2.952611-.963749-3.352237-3.719791-7.141255-2.838484-10.73046 1.972017-8.030506 13.526287-10.543033 18.899867-4.780653 3.60767 3.868283 5.704174 9.192229 8.051303 13.859765 3.097352 6.162006 6.624228 12.118418 9.940876 18.16483 5.805578 10.585967 12.146205 20.881297 18.116667 31.375615.49237.865561.999687 1.726685 1.512269 2.587098l.771613 1.290552c2.577138 4.303168 5.164895 8.635123 6.553094 13.461506-20.735854-.9487-36.30176-25.018751-45.343193-41.283704-.721369 2.604176.450959 4.928448 1.388326 7.431066 1.948109 5.197619 4.276275 10.147535 7.20627 14.862134 4.184765 6.732546 8.982075 13.665732 15.313633 18.553722 11.236043 8.673707 26.05255 8.721596 39.572241 7.794364 8.669619-.595311 19.50252-4.542034 28.030338-1.864372 8.513803 2.673532 11.940924 12.063098 6.884745 19.276187-3.787393 5.403211-8.842747 7.443452-15.128962 8.257566 4.445282 9.53571 10.268996 18.385285 14.490036 28.072919 1.758491 4.035895 3.59118 10.22102 7.8048 12.350433 2.805507 1.416857 6.824562.09743 9.85761.034678-3.043765-8.053625-8.742992-14.887729-11.541904-23.118874 8.533589.390544 16.786875 4.843404 24.732651 7.685374 15.630376 5.590144 31.063836 11.701854 46.475333 17.86913l7.112077 2.848685c6.338978 2.538947 12.71588 5.052299 18.961699 7.812528 2.285297 1.009799 5.449427 3.370401 7.975455 1.917215 2.061054-1.186494 3.394144-4.015253 4.665403-5.931643 3.55573-5.361927 6.775921-10.928622 9.965609-16.513481 12.774414-22.36586 22.143967-46.872692 28.402976-71.833646 20.645168-82.323009 2.934117-173.156241-46.677107-241.922507-19.061454-26.420745-43.033164-49.262193-69.46165-68.1783861-66.13923-47.336721-152.911262-66.294198-232.486917-48.7172481zm135.205158 410.5292842c-17.532977 4.570931-35.601827 8.714164-53.58741 11.040088 2.365265 8.052799 8.145286 15.885969 12.376218 23.118874 1.635653 2.796558 3.3859 6.541816 6.618457 7.755557 3.651364 1.370619 8.063669-.853747 11.508927-1.975838-1.595256-4.364513-4.279573-8.292245-6.476657-12.385112-.905215-1.687677-2.305907-3.685809-1.559805-5.68972 1.410585-3.786541 7.266452-3.563609 10.509727-4.221671 8.54678-1.733916 17.004522-3.898008 25.557073-5.611281 3.150939-.631641 7.538512-2.342438 10.705115-1.285575 2.371037.791232 3.800147 2.744743 5.152304 4.781948l.606196.918752c.80912 1.222827 1.637246 2.41754 2.671212 3.351165 3.457625 3.121874 8.628398 3.60159 13.017619 4.453686-2.678546-6.027421-7.130424-11.301001-9.984571-17.339156-1.659561-3.511592-3.023155-8.677834-6.656381-10.707341-5.005064-2.795733-15.341663 2.461334-20.458024 3.795624zm-110.472507-40.151706c-.825246 10.467897-4.036369 18.984725-9.068639 28.072919 5.76683.729896 11.649079.989984 17.312856 2.39363 4.244947 1.051908 8.156828 3.058296 12.366325 4.211763-2.250671-6.157877-6.426367-11.651913-9.661398-17.339156-3.266358-5.740912-6.189758-12.717032-10.949144-17.339156z" fill="#fff" transform="translate(.9778)"/></svg>`;
1349
- files["public/tanstack-logo-dark.svg"] = `<svg height="660" viewBox="0 0 663 660" width="663" xmlns="http://www.w3.org/2000/svg"><path d="m305.114318.62443771c8.717817-1.14462121 17.926803-.36545135 26.712694-.36545135 32.548987 0 64.505987 5.05339923 95.64868 14.63098274 39.74418 12.2236582 76.762804 31.7666864 109.435876 57.477568 40.046637 31.5132839 73.228974 72.8472109 94.520714 119.2362609 39.836383 86.790386 39.544267 191.973146-1.268422 278.398081-26.388695 55.880442-68.724007 102.650458-119.964986 136.75724-41.808813 27.828603-90.706831 44.862601-140.45707 50.89341-63.325458 7.677926-131.784923-3.541603-188.712259-32.729444-106.868873-54.795293-179.52309291-165.076271-180.9604082-285.932068-.27660564-23.300971.08616998-46.74071 4.69884909-69.814998 7.51316071-37.57857 20.61272131-73.903917 40.28618971-106.877282 21.2814003-35.670293 48.7704861-67.1473767 81.6882804-92.5255597 38.602429-29.7610135 83.467691-51.1674988 130.978372-62.05777669 11.473831-2.62966514 22.9946-4.0869914 34.57273-5.4964306l3.658171-.44480576c3.050084-.37153079 6.104217-.74794222 9.162589-1.14972654zm-110.555861 549.44131429c-14.716752 1.577863-30.238964 4.25635-42.869928 12.522173 2.84343.683658 6.102369.004954 9.068638 0 7.124652-.011559 14.317732-.279903 21.434964.032202 17.817402.781913 36.381729 3.63214 53.58741 8.350042 22.029372 6.040631 41.432961 17.928687 62.656049 25.945156 22.389644 8.456554 44.67706 11.084675 68.427 11.084675 11.96813 0 23.845573-.035504 35.450133-3.302696-6.056202-3.225083-14.72582-2.619864-21.434964-3.963236-14.556814-2.915455-28.868774-6.474936-42.869928-11.470264-10.304996-3.676672-20.230803-8.214291-30.11097-12.848661l-6.348531-2.985046c-9.1705-4.309263-18.363277-8.560752-27.845391-12.142608-24.932161-9.418465-52.560181-14.071964-79.144482-11.221737zm22.259385-62.614168c-29.163917 0-58.660076 5.137344-84.915434 18.369597-6.361238 3.206092-12.407546 7.02566-18.137277 11.258891-1.746125 1.290529-4.841829 2.948483-5.487351 5.191839-.654591 2.275558 1.685942 4.182039 3.014086 5.637703 6.562396-3.497556 12.797498-7.199878 19.78612-9.855246 45.19892-17.169893 99.992458-13.570779 145.098218 2.172348 22.494346 7.851335 43.219483 19.592421 65.129314 28.800338 24.503461 10.297807 49.53043 16.975034 75.846795 20.399104 31.04195 4.037546 66.433549.7654 94.808495-13.242161 9.970556-4.921843 23.814245-12.422267 28.030337-23.320339-5.207047.454947-9.892236 2.685918-14.83959 4.224149-7.866632 2.445646-15.827248 4.51974-23.908229 6.138887-27.388113 5.486604-56.512458 6.619429-84.091013 1.639788-25.991939-4.693152-50.142596-14.119246-74.179513-24.03502l-3.068058-1.268177c-2.045137-.846788-4.089983-1.695816-6.135603-2.544467l-3.069142-1.272366c-12.279956-5.085721-24.606928-10.110797-37.210937-14.51024-24.485325-8.546552-50.726667-13.784628-76.671218-13.784628zm51.114145-447.9909432c-34.959602 7.7225298-66.276908 22.7605319-96.457338 41.7180089-17.521434 11.0054099-34.281927 22.2799893-49.465301 36.4444283-22.5792616 21.065423-39.8360564 46.668751-54.8866988 73.411509-15.507372 27.55357-25.4498976 59.665686-30.2554517 90.824149-4.7140432 30.568106-5.4906485 62.70747-.0906864 93.301172 6.7503648 38.248526 19.5989769 74.140579 39.8896436 107.337631 6.8187918-3.184625 11.659796-10.445603 17.3128555-15.336896 11.4149428-9.875888 23.3995608-19.029311 36.2745548-26.928535 4.765981-2.923712 9.662222-5.194315 14.83959-7.275014 1.953055-.785216 5.14604-1.502727 6.06527-3.647828 1.460876-3.406732-1.240754-9.335897-1.704904-12.865654-1.324845-10.095517-2.124534-20.362774-1.874735-30.549941.725492-29.668947 6.269727-59.751557 16.825623-87.521453 7.954845-20.924233 20.10682-39.922168 34.502872-56.971512 4.884699-5.785498 10.077731-11.170545 15.437296-16.512656 3.167428-3.157378 7.098271-5.858983 9.068639-9.908915-10.336599.006606-20.674847 2.987289-30.503603 6.013385-21.174447 6.519522-41.801477 16.19312-59.358362 29.841512-8.008432 6.226409-13.873368 14.387371-21.44733 20.939921-2.32322 2.010516-6.484901 4.704691-9.695199 3.187928-4.8500728-2.29042-4.1014979-11.835213-4.6571581-16.222019-2.1369011-16.873476 4.2548401-38.216325 12.3778671-52.843142 13.039878-23.479694 37.150915-43.528712 65.467327-42.82854 12.228647.302197 22.934587 4.551115 34.625711 7.324555-2.964621-4.211764-6.939158-7.28162-10.717482-10.733763-9.257431-8.459031-19.382979-16.184864-30.503603-22.028985-4.474136-2.350694-9.291232-3.77911-14.015169-5.506421-2.375159-.867783-5.36616-2.062533-6.259834-4.702213-1.654614-4.888817 7.148561-9.416813 10.381943-11.478522 12.499882-7.969406 27.826705-14.525258 42.869928-14.894334 23.509209-.577147 46.479246 12.467678 56.162903 34.665926 3.404469 7.803171 4.411273 16.054969 5.079109 24.382907l.121749 1.56229.174325 2.345587c.01913.260708.038244.521433.057403.782164l.11601 1.56437.120128 1.563971c7.38352-6.019164 12.576553-14.876995 19.78612-21.323859 16.861073-15.07846 39.936636-21.7722 61.831627-14.984333 19.786945 6.133107 36.984382 19.788105 47.105807 37.959541 2.648042 4.754231 10.035685 16.373942 4.698379 21.109183-4.177345 3.707277-9.475079.818243-13.880788-.719162-3.33605-1.16376-6.782939-1.90214-10.241828-2.585698l-1.887262-.369639c-.629089-.122886-1.257979-.246187-1.886079-.372129-11.980496-2.401886-25.91652-2.152533-37.923398-.041284-7.762754 1.364839-15.349083 4.127545-23.083807 5.271929v1.651348c21.149714.175043 41.608563 12.240618 52.043268 30.549941 4.323267 7.585468 6.482428 16.267431 8.138691 24.770223 2.047864 10.50918.608423 21.958802-2.263037 32.201289-.962925 3.433979-2.710699 9.255807-6.817143 10.046802-2.902789.558982-5.36781-2.330878-7.024898-4.279468-4.343878-5.10762-8.475879-9.96341-13.573278-14.374161-12.895604-11.157333-26.530715-21.449361-40.396663-31.373138-7.362086-5.269452-15.425755-12.12007-23.908229-15.340199 2.385052 5.745041 4.721463 11.086326 5.532694 17.339156 2.385876 18.392716-5.314223 35.704625-16.87179 49.540445-3.526876 4.222498-7.29943 8.475545-11.744712 11.755948-1.843407 1.360711-4.156734 3.137561-6.595373 2.752797-7.645687-1.207961-8.555849-12.73272-9.728176-18.637115-3.970415-19.998652-2.375984-39.861068 3.132802-59.448534-4.901187 2.485279-8.443727 7.923994-11.521293 12.385111-6.770975 9.816439-12.645804 20.199291-16.858599 31.375615-16.777806 44.519521-16.616219 96.664142 5.118834 139.523233 2.427098 4.786433 6.110614 4.144058 10.894733 4.144058.720854 0 1.44257-.004515 2.164851-.010924l2.168232-.022283c4.338648-.045438 8.686803-.064635 12.979772.508795 2.227588.297243 5.320818.032202 7.084256 1.673642 2.111344 1.966755.986008 5.338808.4996 7.758859-1.358647 6.765574-1.812904 12.914369-1.812904 19.816178 9.02412-1.398692 11.525415-15.866153 14.724172-23.118874 3.624982-8.216283 7.313444-16.440823 10.667192-24.770223 1.648843-4.093692 3.854171-8.671229 3.275427-13.210785-.649644-5.10184-4.335633-10.510831-6.904531-14.862134-4.86244-8.234447-10.389363-16.70834-13.969002-25.595896-2.861567-7.104926-.197036-15.983399 7.871579-18.521521 4.450228-1.400344 9.198073 1.345848 12.094266 4.562675 6.07269 6.74328 9.992815 16.777697 14.401823 24.692609l34.394873 61.925556c2.920926 5.243856 5.848447 10.481933 8.836976 15.687808 1.165732 2.031158 2.352075 5.167068 4.740424 6.0332 2.127008.77118 5.033095-.325315 7.148561-.748886 5.492297-1.099798 10.97635-2.287117 16.488434-3.28288 6.605266-1.193099 16.673928-.969342 21.434964-6.129805-6.963066-2.205375-15.011895-2.074919-22.259386-1.577863-4.352947.298894-9.178287 1.856116-13.178381-.686135-5.953149-3.783239-9.910373-12.522173-13.552668-18.377854-8.980425-14.439388-17.441465-29.095929-26.041008-43.760726l-1.376261-2.335014-2.765943-4.665258c-1.380597-2.334387-2.750786-4.67476-4.079753-7.036188-1.02723-1.826391-2.549937-4.233231-1.078344-6.24705 1.545791-2.114476 4.91472-2.239146 7.956473-2.243117l.603351.000261c1.195428.001526 2.315572.002427 3.222811-.11692 12.27399-1.615019 24.718635-2.952611 37.098976-2.952611-.963749-3.352237-3.719791-7.141255-2.838484-10.73046 1.972017-8.030506 13.526287-10.543033 18.899867-4.780653 3.60767 3.868283 5.704174 9.192229 8.051303 13.859765 3.097352 6.162006 6.624228 12.118418 9.940876 18.16483 5.805578 10.585967 12.146205 20.881297 18.116667 31.375615.49237.865561.999687 1.726685 1.512269 2.587098l.771613 1.290552c2.577138 4.303168 5.164895 8.635123 6.553094 13.461506-20.735854-.9487-36.30176-25.018751-45.343193-41.283704-.721369 2.604176.450959 4.928448 1.388326 7.431066 1.948109 5.197619 4.276275 10.147535 7.20627 14.862134 4.184765 6.732546 8.982075 13.665732 15.313633 18.553722 11.236043 8.673707 26.05255 8.721596 39.572241 7.794364 8.669619-.595311 19.50252-4.542034 28.030338-1.864372 8.513803 2.673532 11.940924 12.063098 6.884745 19.276187-3.787393 5.403211-8.842747 7.443452-15.128962 8.257566 4.445282 9.53571 10.268996 18.385285 14.490036 28.072919 1.758491 4.035895 3.59118 10.22102 7.8048 12.350433 2.805507 1.416857 6.824562.09743 9.85761.034678-3.043765-8.053625-8.742992-14.887729-11.541904-23.118874 8.533589.390544 16.786875 4.843404 24.732651 7.685374 15.630376 5.590144 31.063836 11.701854 46.475333 17.86913l7.112077 2.848685c6.338978 2.538947 12.71588 5.052299 18.961699 7.812528 2.285297 1.009799 5.449427 3.370401 7.975455 1.917215 2.061054-1.186494 3.394144-4.015253 4.665403-5.931643 3.55573-5.361927 6.775921-10.928622 9.965609-16.513481 12.774414-22.36586 22.143967-46.872692 28.402976-71.833646 20.645168-82.323009 2.934117-173.156241-46.677107-241.922507-19.061454-26.420745-43.033164-49.262193-69.46165-68.1783861-66.13923-47.336721-152.911262-66.294198-232.486917-48.7172481zm135.205158 410.5292842c-17.532977 4.570931-35.601827 8.714164-53.58741 11.040088 2.365265 8.052799 8.145286 15.885969 12.376218 23.118874 1.635653 2.796558 3.3859 6.541816 6.618457 7.755557 3.651364 1.370619 8.063669-.853747 11.508927-1.975838-1.595256-4.364513-4.279573-8.292245-6.476657-12.385112-.905215-1.687677-2.305907-3.685809-1.559805-5.68972 1.410585-3.786541 7.266452-3.563609 10.509727-4.221671 8.54678-1.733916 17.004522-3.898008 25.557073-5.611281 3.150939-.631641 7.538512-2.342438 10.705115-1.285575 2.371037.791232 3.800147 2.744743 5.152304 4.781948l.606196.918752c.80912 1.222827 1.637246 2.41754 2.671212 3.351165 3.457625 3.121874 8.628398 3.60159 13.017619 4.453686-2.678546-6.027421-7.130424-11.301001-9.984571-17.339156-1.659561-3.511592-3.023155-8.677834-6.656381-10.707341-5.005064-2.795733-15.341663 2.461334-20.458024 3.795624zm-110.472507-40.151706c-.825246 10.467897-4.036369 18.984725-9.068639 28.072919 5.76683.729896 11.649079.989984 17.312856 2.39363 4.244947 1.051908 8.156828 3.058296 12.366325 4.211763-2.250671-6.157877-6.426367-11.651913-9.661398-17.339156-3.266358-5.740912-6.189758-12.717032-10.949144-17.339156z" fill="#1f2937" transform="translate(.9778)"/></svg>`;
1350
- const gitignorePatterns = [];
1351
- for (const integration of options.chosenIntegrations) if (integration.gitignorePatterns) for (const pattern of integration.gitignorePatterns) gitignorePatterns.push({
1352
- pattern,
1353
- integrationId: integration.id
1354
- });
1355
- files[".gitignore"] = generateGitignore(gitignorePatterns).content;
1356
- files[".env.example"] = `# Add your environment variables here
1357
- # Copy this file to .env.local and fill in your values
1358
-
1359
- # Example:
1360
- # DATABASE_URL=postgresql://user:password@localhost:5432/db
1361
- `;
1362
- files["README.md"] = `# ${projectName}
1363
-
1364
- A full-stack React application built with [TanStack Start](https://tanstack.com/start).
1365
-
1366
- ## Getting Started
1367
-
1368
- \`\`\`bash
1369
- # Install dependencies
1370
- ${packageManager} install
1371
-
1372
- # Start development server
1373
- ${packageManager}${packageManager === "npm" ? " run" : ""} dev
1374
- \`\`\`
1375
-
1376
- ## Scripts
1377
-
1378
- - \`dev\` - Start development server
1379
- - \`build\` - Build for production
1380
- - \`start\` - Start production server
1381
-
1382
- ## Learn More
1383
-
1384
- - [TanStack Start Documentation](https://tanstack.com/start)
1385
- - [TanStack Router Documentation](https://tanstack.com/router)
1386
- `;
1387
- files[".nvmrc"] = "22.12.0";
1388
- return files;
1389
- }
1390
- /**
1391
- * Get base files WITH line-by-line attribution for files that have hooks
1392
- */
1393
- function getBaseFilesWithAttribution(options) {
1394
- const { typescript } = options;
1395
- const files = getBaseFiles(options);
1396
- const attributions = {};
1397
- const { vitePlugins, rootProviders, devtoolsPlugins, entryClientInits } = collectHooks(options);
1398
- attributions[typescript ? "vite.config.ts" : "vite.config.js"] = generateViteConfig(options, vitePlugins).lineAttributions;
1399
- if (entryClientInits.length > 0) attributions[`src/entry-client.${typescript ? "tsx" : "jsx"}`] = generateEntryClient(options, entryClientInits).lineAttributions;
1400
- attributions[`src/routes/__root.${typescript ? "tsx" : "jsx"}`] = generateRootRoute(options, rootProviders, devtoolsPlugins).lineAttributions;
1401
- const gitignorePatterns = [];
1402
- for (const integration of options.chosenIntegrations) if (integration.gitignorePatterns) for (const pattern of integration.gitignorePatterns) gitignorePatterns.push({
1403
- pattern,
1404
- integrationId: integration.id
1405
- });
1406
- attributions[".gitignore"] = generateGitignore(gitignorePatterns).lineAttributions;
1407
- return {
1408
- files,
1409
- attributions
1410
- };
1411
- }
1412
-
1413
- //#endregion
1414
- //#region src/engine/compile.ts
1415
- /**
1416
- * Merge package contributions from integrations
1417
- */
1418
- function mergePackages(target, source) {
1419
- if (!source) return;
1420
- if (source.dependencies) target.dependencies = {
1421
- ...target.dependencies,
1422
- ...source.dependencies
1423
- };
1424
- if (source.devDependencies) target.devDependencies = {
1425
- ...target.devDependencies,
1426
- ...source.devDependencies
1427
- };
1428
- if (source.scripts) target.scripts = {
1429
- ...target.scripts,
1430
- ...source.scripts
1431
- };
1432
- }
1433
- function mergePackagesWithAttribution(target, source, integrationId, attribution) {
1434
- if (!source) return;
1435
- if (source.dependencies) {
1436
- for (const pkg of Object.keys(source.dependencies)) attribution.dependencies.set(pkg, integrationId);
1437
- target.dependencies = {
1438
- ...target.dependencies,
1439
- ...source.dependencies
1440
- };
1441
- }
1442
- if (source.devDependencies) {
1443
- for (const pkg of Object.keys(source.devDependencies)) attribution.devDependencies.set(pkg, integrationId);
1444
- target.devDependencies = {
1445
- ...target.devDependencies,
1446
- ...source.devDependencies
1447
- };
1448
- }
1449
- if (source.scripts) {
1450
- for (const script of Object.keys(source.scripts)) attribution.scripts.set(script, integrationId);
1451
- target.scripts = {
1452
- ...target.scripts,
1453
- ...source.scripts
1454
- };
1455
- }
1456
- }
1457
- /**
1458
- * Process all files from an integration
1459
- */
1460
- function processIntegrationFiles(integration, options, files, appendFiles) {
1461
- for (const [filePath, content] of Object.entries(integration.files)) {
1462
- const processed = processTemplateFile(filePath, content, options);
1463
- if (!processed) continue;
1464
- if (processed.append) {
1465
- if (!appendFiles.has(processed.path)) appendFiles.set(processed.path, []);
1466
- appendFiles.get(processed.path).push({
1467
- content: processed.content,
1468
- integrationId: integration.id
1469
- });
1470
- } else files.set(processed.path, {
1471
- content: processed.content,
1472
- integrationId: integration.id
1473
- });
1474
- }
1475
- }
1476
- /**
1477
- * Build the package.json content
1478
- */
1479
- function buildPackageJson(options, packages) {
1480
- const hasHeader = options.chosenIntegrations.length > 0 && options.tailwind;
1481
- const pkg = {
1482
- name: options.projectName,
1483
- private: true,
1484
- type: "module",
1485
- scripts: {
1486
- dev: "vite dev --port 3000",
1487
- build: "vite build",
1488
- start: "node .output/server/index.mjs",
1489
- ...packages.scripts
1490
- },
1491
- dependencies: {
1492
- "@tanstack/react-router": "^1.132.0",
1493
- "@tanstack/react-router-devtools": "^1.132.0",
1494
- "@tanstack/react-start": "^1.132.0",
1495
- react: "^19.2.0",
1496
- "react-dom": "^19.2.0",
1497
- "vite-tsconfig-paths": "^5.1.4",
1498
- ...hasHeader ? { "lucide-react": "^0.468.0" } : {},
1499
- ...packages.dependencies
1500
- },
1501
- devDependencies: {
1502
- "@vitejs/plugin-react": "^4.4.1",
1503
- vite: "^7.0.0",
1504
- ...options.typescript ? {
1505
- "@types/react": "^19.2.0",
1506
- "@types/react-dom": "^19.2.0",
1507
- typescript: "^5.7.0"
1508
- } : {},
1509
- ...options.tailwind ? {
1510
- "@tailwindcss/vite": "^4.0.0",
1511
- tailwindcss: "^4.0.0"
1512
- } : {},
1513
- ...packages.devDependencies
1514
- }
1515
- };
1516
- return JSON.stringify(pkg, null, 2);
1517
- }
1518
- /**
1519
- * Compile a project from options
1520
- */
1521
- function compile(options) {
1522
- const files = /* @__PURE__ */ new Map();
1523
- const appendFiles = /* @__PURE__ */ new Map();
1524
- const packages = {
1525
- dependencies: {},
1526
- devDependencies: {},
1527
- scripts: {}
1528
- };
1529
- const envVars = [];
1530
- const warnings = [];
1531
- const baseFiles = getBaseFiles(options);
1532
- for (const [path, content] of Object.entries(baseFiles)) files.set(path, {
1533
- content,
1534
- integrationId: "base"
1535
- });
1536
- const sortedIntegrations = [...options.chosenIntegrations].sort((a, b) => {
1537
- const phaseOrder = {
1538
- setup: 0,
1539
- integration: 1,
1540
- example: 2
1541
- };
1542
- const phaseA = phaseOrder[a.phase];
1543
- const phaseB = phaseOrder[b.phase];
1544
- if (phaseA !== phaseB) return phaseA - phaseB;
1545
- return (a.priority ?? 100) - (b.priority ?? 100);
1546
- });
1547
- for (const integration of sortedIntegrations) {
1548
- processIntegrationFiles(integration, options, files, appendFiles);
1549
- mergePackages(packages, integration.packageAdditions);
1550
- if (integration.envVars) envVars.push(...integration.envVars);
1551
- if (integration.warning) warnings.push(`${integration.name}: ${integration.warning}`);
1552
- }
1553
- for (const [path, appends] of appendFiles) {
1554
- const existing = files.get(path);
1555
- if (existing) {
1556
- const appendContent = appends.map((a) => a.content).join("\n");
1557
- existing.content = existing.content + "\n" + appendContent;
1558
- } else files.set(path, {
1559
- content: appends.map((a) => a.content).join("\n"),
1560
- integrationId: appends[0]?.integrationId ?? "base"
1561
- });
1562
- }
1563
- const outputFiles = {};
1564
- for (const [path, { content }] of files) outputFiles[path] = content;
1565
- outputFiles["package.json"] = buildPackageJson(options, packages);
1566
- const seenEnvVars = /* @__PURE__ */ new Set();
1567
- return {
1568
- files: outputFiles,
1569
- packages,
1570
- envVars: envVars.filter((v) => {
1571
- if (seenEnvVars.has(v.name)) return false;
1572
- seenEnvVars.add(v.name);
1573
- return true;
1574
- }),
1575
- warnings
1576
- };
1577
- }
1578
- /**
1579
- * Compile with line-by-line attribution tracking
1580
- */
1581
- function compileWithAttribution(options) {
1582
- const files = /* @__PURE__ */ new Map();
1583
- const appendFiles = /* @__PURE__ */ new Map();
1584
- const packages = {
1585
- dependencies: {},
1586
- devDependencies: {},
1587
- scripts: {}
1588
- };
1589
- const packageAttribution = {
1590
- dependencies: /* @__PURE__ */ new Map(),
1591
- devDependencies: /* @__PURE__ */ new Map(),
1592
- scripts: /* @__PURE__ */ new Map()
1593
- };
1594
- const envVars = [];
1595
- const warnings = [];
1596
- const fileOwnership = /* @__PURE__ */ new Map();
1597
- const { files: baseFiles, attributions: baseAttributions } = getBaseFilesWithAttribution(options);
1598
- for (const [path, content] of Object.entries(baseFiles)) {
1599
- files.set(path, {
1600
- content,
1601
- integrationId: "base"
1602
- });
1603
- fileOwnership.set(path, "base");
1604
- }
1605
- const hookAttributions = /* @__PURE__ */ new Map();
1606
- for (const [path, attrs] of Object.entries(baseAttributions)) hookAttributions.set(path, attrs);
1607
- const sortedIntegrations = [...options.chosenIntegrations].sort((a, b) => {
1608
- const phaseOrder = {
1609
- setup: 0,
1610
- integration: 1,
1611
- example: 2
1612
- };
1613
- const phaseA = phaseOrder[a.phase];
1614
- const phaseB = phaseOrder[b.phase];
1615
- if (phaseA !== phaseB) return phaseA - phaseB;
1616
- return (a.priority ?? 100) - (b.priority ?? 100);
1617
- });
1618
- const integrationNames = /* @__PURE__ */ new Map();
1619
- integrationNames.set("base", "Base Template");
1620
- if (options.customTemplate) integrationNames.set(options.customTemplate.id, options.customTemplate.name);
1621
- for (const integration of sortedIntegrations) integrationNames.set(integration.id, integration.name);
1622
- for (const integration of sortedIntegrations) {
1623
- for (const [filePath, content] of Object.entries(integration.files)) {
1624
- const processed = processTemplateFile(filePath, content, options);
1625
- if (!processed) continue;
1626
- if (processed.append) {
1627
- if (!appendFiles.has(processed.path)) appendFiles.set(processed.path, []);
1628
- appendFiles.get(processed.path).push({
1629
- content: processed.content,
1630
- integrationId: integration.id
1631
- });
1632
- } else {
1633
- files.set(processed.path, {
1634
- content: processed.content,
1635
- integrationId: integration.id
1636
- });
1637
- fileOwnership.set(processed.path, integration.id);
1638
- }
1639
- }
1640
- mergePackagesWithAttribution(packages, integration.packageAdditions, integration.id, packageAttribution);
1641
- if (integration.envVars) for (const envVar of integration.envVars) envVars.push({
1642
- ...envVar,
1643
- integrationId: integration.id
1644
- });
1645
- if (integration.warning) warnings.push(`${integration.name}: ${integration.warning}`);
1646
- }
1647
- const appendOwnership = /* @__PURE__ */ new Map();
1648
- for (const [path, appends] of appendFiles) {
1649
- const existing = files.get(path);
1650
- if (existing) {
1651
- const existingLines = existing.content.split("\n").length;
1652
- const lineMap = /* @__PURE__ */ new Map();
1653
- let currentLine = existingLines + 1;
1654
- for (const append of appends) {
1655
- const appendLines = append.content.split("\n").length;
1656
- for (let i = 0; i < appendLines; i++) lineMap.set(currentLine + i, append.integrationId);
1657
- currentLine += appendLines + 1;
1658
- }
1659
- appendOwnership.set(path, lineMap);
1660
- const appendContent = appends.map((a) => a.content).join("\n");
1661
- existing.content = existing.content + "\n" + appendContent;
1662
- } else {
1663
- files.set(path, {
1664
- content: appends.map((a) => a.content).join("\n"),
1665
- integrationId: appends[0]?.integrationId ?? "base"
1666
- });
1667
- fileOwnership.set(path, appends[0]?.integrationId ?? "base");
1668
- }
1669
- }
1670
- const outputFiles = {};
1671
- const attributedFiles = {};
1672
- for (const [path, { content, integrationId }] of files) {
1673
- outputFiles[path] = content;
1674
- const lines = content.split("\n");
1675
- const attributions = [];
1676
- const appendLineMap = appendOwnership.get(path);
1677
- const hookAttrMap = hookAttributions.get(path);
1678
- for (let i = 0; i < lines.length; i++) {
1679
- const lineNumber = i + 1;
1680
- let owningIntegrationId = integrationId;
1681
- const appendIntegrationId = appendLineMap?.get(lineNumber);
1682
- const hookAttr = hookAttrMap?.find((a) => a.line === lineNumber);
1683
- if (appendIntegrationId) owningIntegrationId = appendIntegrationId;
1684
- else if (hookAttr) owningIntegrationId = hookAttr.integrationId;
1685
- attributions.push({
1686
- lineNumber,
1687
- featureId: owningIntegrationId,
1688
- featureName: integrationNames.get(owningIntegrationId) || owningIntegrationId
1689
- });
1690
- }
1691
- attributedFiles[path] = {
1692
- path,
1693
- content,
1694
- attributions
1695
- };
1696
- }
1697
- outputFiles["package.json"] = buildPackageJson(options, packages);
1698
- const pkgJsonLines = outputFiles["package.json"].split("\n");
1699
- const pkgJsonAttributions = [];
1700
- for (let i = 0; i < pkgJsonLines.length; i++) {
1701
- const line = pkgJsonLines[i];
1702
- const lineNumber = i + 1;
1703
- let integrationId = "base";
1704
- const match = line.match(/^\s*"([^"]+)":\s*"[^"]+"/);
1705
- if (match) {
1706
- const pkgName = match[1];
1707
- const depIntegration = packageAttribution.dependencies.get(pkgName);
1708
- const devDepIntegration = packageAttribution.devDependencies.get(pkgName);
1709
- const scriptIntegration = packageAttribution.scripts.get(pkgName);
1710
- if (depIntegration) integrationId = depIntegration;
1711
- else if (devDepIntegration) integrationId = devDepIntegration;
1712
- else if (scriptIntegration) integrationId = scriptIntegration;
1713
- }
1714
- pkgJsonAttributions.push({
1715
- lineNumber,
1716
- featureId: integrationId,
1717
- featureName: integrationNames.get(integrationId) || integrationId
1718
- });
1719
- }
1720
- attributedFiles["package.json"] = {
1721
- path: "package.json",
1722
- content: outputFiles["package.json"],
1723
- attributions: pkgJsonAttributions
1724
- };
1725
- const seenEnvVars = /* @__PURE__ */ new Set();
1726
- const uniqueEnvVars = envVars.filter((v) => {
1727
- if (seenEnvVars.has(v.name)) return false;
1728
- seenEnvVars.add(v.name);
1729
- return true;
1730
- });
1731
- if (uniqueEnvVars.length > 0) {
1732
- const envLines = [];
1733
- envLines.push({
1734
- text: "# Environment Variables",
1735
- integrationId: "base"
1736
- });
1737
- envLines.push({
1738
- text: "# Copy this file to .env.local and fill in your values",
1739
- integrationId: "base"
1740
- });
1741
- envLines.push({
1742
- text: "",
1743
- integrationId: "base"
1744
- });
1745
- const envByIntegration = /* @__PURE__ */ new Map();
1746
- for (const envVar of uniqueEnvVars) {
1747
- const id = envVar.integrationId;
1748
- if (!envByIntegration.has(id)) envByIntegration.set(id, []);
1749
- envByIntegration.get(id).push(envVar);
1750
- }
1751
- for (const [integrationId, vars] of envByIntegration) {
1752
- const integrationName = integrationNames.get(integrationId) || integrationId;
1753
- envLines.push({
1754
- text: `# ${integrationName}`,
1755
- integrationId
1756
- });
1757
- for (const v of vars) {
1758
- envLines.push({
1759
- text: `# ${v.description}${v.required ? " (required)" : ""}`,
1760
- integrationId
1761
- });
1762
- envLines.push({
1763
- text: `${v.name}=${v.example || ""}`,
1764
- integrationId
1765
- });
1766
- }
1767
- envLines.push({
1768
- text: "",
1769
- integrationId: "base"
1770
- });
1771
- }
1772
- const envContent = envLines.map((l) => l.text).join("\n");
1773
- outputFiles[".env.example"] = envContent;
1774
- attributedFiles[".env.example"] = {
1775
- path: ".env.example",
1776
- content: envContent,
1777
- attributions: envLines.map((l, i) => ({
1778
- lineNumber: i + 1,
1779
- featureId: l.integrationId,
1780
- featureName: integrationNames.get(l.integrationId) || l.integrationId
1781
- }))
1782
- };
1783
- }
1784
- return {
1785
- files: outputFiles,
1786
- packages,
1787
- envVars: uniqueEnvVars.map(({ integrationId, ...rest }) => rest),
1788
- warnings,
1789
- attributedFiles
1790
- };
1791
- }
1792
-
1793
- //#endregion
1794
- //#region src/engine/config-file.ts
1795
- const CONFIG_FILE = ".tanstack.json";
1796
- function createPersistedOptions(options) {
1797
- return {
1798
- version: 1,
1799
- projectName: options.projectName,
1800
- framework: options.framework,
1801
- mode: options.mode,
1802
- typescript: options.typescript,
1803
- tailwind: options.tailwind,
1804
- packageManager: options.packageManager,
1805
- chosenIntegrations: options.chosenIntegrations.map((integration) => integration.id),
1806
- customTemplate: options.customTemplate?.id
1807
- };
1808
- }
1809
- async function writeConfigFile(targetDir, options) {
1810
- await (0, node_fs_promises.writeFile)((0, node_path.resolve)(targetDir, CONFIG_FILE), JSON.stringify(createPersistedOptions(options), null, 2));
1811
- }
1812
- async function readConfigFile(targetDir) {
1813
- const configPath = (0, node_path.resolve)(targetDir, CONFIG_FILE);
1814
- if (!(0, node_fs.existsSync)(configPath)) return null;
1815
- try {
1816
- const content = await (0, node_fs_promises.readFile)(configPath, "utf-8");
1817
- return JSON.parse(content);
1818
- } catch {
1819
- return null;
1820
- }
1821
- }
1822
-
1823
- //#endregion
1824
- //#region src/engine/types.ts
1825
- const CategorySchema = zod.z.enum([
1826
- "tanstack",
1827
- "database",
1828
- "orm",
1829
- "auth",
1830
- "deploy",
1831
- "tooling",
1832
- "monitoring",
1833
- "api",
1834
- "i18n",
1835
- "cms",
1836
- "other"
1837
- ]);
1838
- const IntegrationTypeSchema = zod.z.enum([
1839
- "integration",
1840
- "example",
1841
- "toolchain",
1842
- "deployment"
1843
- ]);
1844
- const IntegrationPhaseSchema = zod.z.enum([
1845
- "setup",
1846
- "integration",
1847
- "example"
1848
- ]);
1849
- const RouterModeSchema = zod.z.enum(["file-router", "code-router"]);
1850
- const SelectOptionSchema = zod.z.object({
1851
- type: zod.z.literal("select"),
1852
- label: zod.z.string(),
1853
- description: zod.z.string().optional(),
1854
- default: zod.z.string(),
1855
- options: zod.z.array(zod.z.object({
1856
- value: zod.z.string(),
1857
- label: zod.z.string()
1858
- }))
1859
- });
1860
- const BooleanOptionSchema = zod.z.object({
1861
- type: zod.z.literal("boolean"),
1862
- label: zod.z.string(),
1863
- description: zod.z.string().optional(),
1864
- default: zod.z.boolean()
1865
- });
1866
- const StringOptionSchema = zod.z.object({
1867
- type: zod.z.literal("string"),
1868
- label: zod.z.string(),
1869
- description: zod.z.string().optional(),
1870
- default: zod.z.string()
1871
- });
1872
- const IntegrationOptionSchema = zod.z.discriminatedUnion("type", [
1873
- SelectOptionSchema,
1874
- BooleanOptionSchema,
1875
- StringOptionSchema
1876
- ]);
1877
- const IntegrationOptionsSchema = zod.z.record(zod.z.string(), IntegrationOptionSchema);
1878
- const HookTypeSchema = zod.z.enum([
1879
- "header-user",
1880
- "provider",
1881
- "root-provider",
1882
- "layout",
1883
- "vite-plugin",
1884
- "devtools",
1885
- "entry-client"
1886
- ]);
1887
- const HookSchema = zod.z.object({
1888
- type: HookTypeSchema.optional(),
1889
- path: zod.z.string().optional(),
1890
- jsName: zod.z.string().optional(),
1891
- import: zod.z.string().optional(),
1892
- code: zod.z.string().optional()
1893
- });
1894
- const RouteSchema = zod.z.object({
1895
- url: zod.z.string().optional(),
1896
- name: zod.z.string().optional(),
1897
- icon: zod.z.string().optional(),
1898
- path: zod.z.string(),
1899
- jsName: zod.z.string(),
1900
- children: zod.z.array(zod.z.lazy(() => RouteSchema)).optional()
1901
- });
1902
- const EnvVarSchema = zod.z.object({
1903
- name: zod.z.string(),
1904
- description: zod.z.string(),
1905
- required: zod.z.boolean().optional(),
1906
- example: zod.z.string().optional()
1907
- });
1908
- const CommandSchema = zod.z.object({
1909
- command: zod.z.string(),
1910
- args: zod.z.array(zod.z.string()).optional()
1911
- });
1912
- const IntegrationInfoSchema = zod.z.object({
1913
- id: zod.z.string().optional(),
1914
- name: zod.z.string(),
1915
- description: zod.z.string(),
1916
- author: zod.z.string().optional(),
1917
- version: zod.z.string().optional(),
1918
- link: zod.z.string().optional(),
1919
- license: zod.z.string().optional(),
1920
- warning: zod.z.string().optional(),
1921
- type: IntegrationTypeSchema,
1922
- phase: IntegrationPhaseSchema,
1923
- category: CategorySchema.optional(),
1924
- modes: zod.z.array(RouterModeSchema),
1925
- priority: zod.z.number().optional(),
1926
- default: zod.z.boolean().optional(),
1927
- requiresTailwind: zod.z.boolean().optional(),
1928
- demoRequiresTailwind: zod.z.boolean().optional(),
1929
- dependsOn: zod.z.array(zod.z.string()).optional(),
1930
- exclusive: zod.z.array(zod.z.string()).optional(),
1931
- partnerId: zod.z.string().optional(),
1932
- options: IntegrationOptionsSchema.optional(),
1933
- hooks: zod.z.array(HookSchema).optional(),
1934
- routes: zod.z.array(RouteSchema).optional(),
1935
- packageAdditions: zod.z.object({
1936
- dependencies: zod.z.record(zod.z.string(), zod.z.string()).optional(),
1937
- devDependencies: zod.z.record(zod.z.string(), zod.z.string()).optional(),
1938
- scripts: zod.z.record(zod.z.string(), zod.z.string()).optional()
1939
- }).optional(),
1940
- shadcnComponents: zod.z.array(zod.z.string()).optional(),
1941
- gitignorePatterns: zod.z.array(zod.z.string()).optional(),
1942
- envVars: zod.z.array(EnvVarSchema).optional(),
1943
- command: CommandSchema.optional(),
1944
- integrationSpecialSteps: zod.z.array(zod.z.string()).optional(),
1945
- createSpecialSteps: zod.z.array(zod.z.string()).optional(),
1946
- postInitSpecialSteps: zod.z.array(zod.z.string()).optional(),
1947
- smallLogo: zod.z.string().optional(),
1948
- logo: zod.z.string().optional(),
1949
- readme: zod.z.string().optional()
1950
- });
1951
- const IntegrationCompiledSchema = IntegrationInfoSchema.extend({
1952
- id: zod.z.string(),
1953
- files: zod.z.record(zod.z.string(), zod.z.string()),
1954
- deletedFiles: zod.z.array(zod.z.string()).optional()
1955
- });
1956
- const CustomTemplateInfoSchema = zod.z.object({
1957
- id: zod.z.string().optional(),
1958
- name: zod.z.string(),
1959
- description: zod.z.string(),
1960
- framework: zod.z.string(),
1961
- mode: RouterModeSchema,
1962
- typescript: zod.z.boolean(),
1963
- tailwind: zod.z.boolean(),
1964
- integrations: zod.z.array(zod.z.string()),
1965
- integrationOptions: zod.z.record(zod.z.string(), zod.z.record(zod.z.string(), zod.z.unknown())).optional(),
1966
- banner: zod.z.string().optional()
1967
- });
1968
- const CustomTemplateCompiledSchema = CustomTemplateInfoSchema.extend({ id: zod.z.string() });
1969
- const ManifestIntegrationSchema = zod.z.object({
1970
- id: zod.z.string(),
1971
- name: zod.z.string(),
1972
- description: zod.z.string(),
1973
- type: IntegrationTypeSchema,
1974
- category: CategorySchema.optional(),
1975
- modes: zod.z.array(RouterModeSchema),
1976
- dependsOn: zod.z.array(zod.z.string()).optional(),
1977
- exclusive: zod.z.array(zod.z.string()).optional(),
1978
- partnerId: zod.z.string().optional(),
1979
- hasOptions: zod.z.boolean().optional(),
1980
- link: zod.z.string().optional(),
1981
- color: zod.z.string().optional(),
1982
- requiresTailwind: zod.z.boolean().optional(),
1983
- demoRequiresTailwind: zod.z.boolean().optional()
1984
- });
1985
- const ManifestCustomTemplateSchema = zod.z.object({
1986
- id: zod.z.string(),
1987
- name: zod.z.string(),
1988
- description: zod.z.string(),
1989
- banner: zod.z.string().optional(),
1990
- icon: zod.z.string().optional(),
1991
- features: zod.z.array(zod.z.string()).optional()
1992
- });
1993
- const ManifestSchema = zod.z.object({
1994
- version: zod.z.string(),
1995
- generated: zod.z.string(),
1996
- integrations: zod.z.array(ManifestIntegrationSchema),
1997
- customTemplates: zod.z.array(ManifestCustomTemplateSchema).optional()
1998
- });
1999
-
2000
- //#endregion
2001
- //#region src/cache/index.ts
2002
- const CACHE_DIR = (0, node_path.join)((0, node_os.homedir)(), ".tanstack", "cache");
2003
- const DEFAULT_TTL_MS = 1440 * 60 * 1e3;
2004
- function ensureCacheDir() {
2005
- if (!(0, node_fs.existsSync)(CACHE_DIR)) (0, node_fs.mkdirSync)(CACHE_DIR, { recursive: true });
2006
- }
2007
- function getCachePath(key) {
2008
- return (0, node_path.join)(CACHE_DIR, `${key.replace(/[^a-zA-Z0-9-_]/g, "_")}.json`);
2009
- }
2010
- function getCached(key) {
2011
- const cachePath = getCachePath(key);
2012
- if (!(0, node_fs.existsSync)(cachePath)) return null;
2013
- try {
2014
- const raw = (0, node_fs.readFileSync)(cachePath, "utf-8");
2015
- const entry = JSON.parse(raw);
2016
- if (Date.now() - entry.timestamp > entry.ttl) return null;
2017
- return entry.data;
2018
- } catch {
2019
- return null;
2020
- }
2021
- }
2022
- function setCache(key, data, ttlMs = DEFAULT_TTL_MS) {
2023
- ensureCacheDir();
2024
- const cachePath = getCachePath(key);
2025
- const entry = {
2026
- data,
2027
- timestamp: Date.now(),
2028
- ttl: ttlMs
2029
- };
2030
- (0, node_fs.writeFileSync)(cachePath, JSON.stringify(entry, null, 2), "utf-8");
2031
- }
2032
- async function fetchWithCache(key, fetcher, ttlMs = DEFAULT_TTL_MS) {
2033
- const cached = getCached(key);
2034
- if (cached !== null) return cached;
2035
- const data = await fetcher();
2036
- setCache(key, data, ttlMs);
2037
- return data;
2038
- }
2039
-
2040
- //#endregion
2041
- //#region src/api/fetch.ts
2042
- const GITHUB_RAW_BASE = "https://raw.githubusercontent.com/TanStack/cli/main/integrations";
2043
- const CACHE_TTL_MS = 3600 * 1e3;
2044
- /**
2045
- * Check if a path is a local directory
2046
- */
2047
- function isLocalPath(path) {
2048
- return path.startsWith("/") || path.startsWith("./") || path.startsWith("..");
2049
- }
2050
- /**
2051
- * Fetch the integration manifest from GitHub or local path (with caching for remote)
2052
- */
2053
- async function fetchManifest(baseUrl = GITHUB_RAW_BASE) {
2054
- if (isLocalPath(baseUrl)) {
2055
- const manifestPath = (0, node_path.join)(baseUrl, "manifest.json");
2056
- if (!(0, node_fs.existsSync)(manifestPath)) throw new Error(`Manifest not found at ${manifestPath}`);
2057
- const data = JSON.parse((0, node_fs.readFileSync)(manifestPath, "utf-8"));
2058
- return ManifestSchema.parse(data);
2059
- }
2060
- return fetchWithCache(`manifest_${baseUrl.replace(/[^a-zA-Z0-9]/g, "_")}`, async () => {
2061
- const url = `${baseUrl}/manifest.json`;
2062
- const response = await fetch(url);
2063
- if (!response.ok) throw new Error(`Failed to fetch manifest: ${response.statusText}`);
2064
- const data = await response.json();
2065
- return ManifestSchema.parse(data);
2066
- }, CACHE_TTL_MS);
2067
- }
2068
- /**
2069
- * Fetch integration info.json from GitHub or local path (with caching for remote)
2070
- */
2071
- async function fetchIntegrationInfo(integrationId, baseUrl = GITHUB_RAW_BASE) {
2072
- if (isLocalPath(baseUrl)) {
2073
- const infoPath = (0, node_path.join)(baseUrl, integrationId, "info.json");
2074
- if (!(0, node_fs.existsSync)(infoPath)) throw new Error(`Integration info not found at ${infoPath}`);
2075
- const data = JSON.parse((0, node_fs.readFileSync)(infoPath, "utf-8"));
2076
- return IntegrationInfoSchema.parse(data);
2077
- }
2078
- return fetchWithCache(`integration_info_${integrationId}_${baseUrl.replace(/[^a-zA-Z0-9]/g, "_")}`, async () => {
2079
- const url = `${baseUrl}/${integrationId}/info.json`;
2080
- const response = await fetch(url);
2081
- if (!response.ok) throw new Error(`Failed to fetch integration ${integrationId}: ${response.statusText}`);
2082
- const data = await response.json();
2083
- return IntegrationInfoSchema.parse(data);
2084
- }, CACHE_TTL_MS);
2085
- }
2086
- /**
2087
- * Recursively read all files from a directory
2088
- */
2089
- function readDirRecursive(dir, basePath = "") {
2090
- const files = {};
2091
- if (!(0, node_fs.existsSync)(dir)) return files;
2092
- for (const entry of (0, node_fs.readdirSync)(dir)) {
2093
- const fullPath = (0, node_path.join)(dir, entry);
2094
- const relativePath$1 = basePath ? `${basePath}/${entry}` : entry;
2095
- if ((0, node_fs.statSync)(fullPath).isDirectory()) Object.assign(files, readDirRecursive(fullPath, relativePath$1));
2096
- else files[relativePath$1] = (0, node_fs.readFileSync)(fullPath, "utf-8");
2097
- }
2098
- return files;
2099
- }
2100
- /**
2101
- * Fetch all files for an integration from GitHub or local path (with caching for remote)
2102
- */
2103
- async function fetchIntegrationFiles(integrationId, baseUrl = GITHUB_RAW_BASE) {
2104
- if (isLocalPath(baseUrl)) return readDirRecursive((0, node_path.join)(baseUrl, integrationId, "assets"));
2105
- return fetchWithCache(`integration_files_${integrationId}_${baseUrl.replace(/[^a-zA-Z0-9]/g, "_")}`, async () => {
2106
- const filesUrl = `${baseUrl}/${integrationId}/files.json`;
2107
- const response = await fetch(filesUrl);
2108
- if (!response.ok) return {};
2109
- const fileList = await response.json();
2110
- const files = {};
2111
- await Promise.all(fileList.map(async (filePath) => {
2112
- const fileUrl = `${baseUrl}/${integrationId}/assets/${filePath}`;
2113
- const fileResponse = await fetch(fileUrl);
2114
- if (fileResponse.ok) files[filePath] = await fileResponse.text();
2115
- }));
2116
- return files;
2117
- }, CACHE_TTL_MS);
2118
- }
2119
- /**
2120
- * Fetch integration package.json if it exists
2121
- */
2122
- async function fetchIntegrationPackageJson(integrationId, baseUrl) {
2123
- if (isLocalPath(baseUrl)) {
2124
- const pkgPath = (0, node_path.join)(baseUrl, integrationId, "package.json");
2125
- if ((0, node_fs.existsSync)(pkgPath)) return JSON.parse((0, node_fs.readFileSync)(pkgPath, "utf-8"));
2126
- return null;
2127
- }
2128
- const url = `${baseUrl}/${integrationId}/package.json`;
2129
- const response = await fetch(url);
2130
- if (!response.ok) return null;
2131
- return response.json();
2132
- }
2133
- /**
2134
- * Fetch a complete compiled integration from GitHub
2135
- */
2136
- async function fetchIntegration(integrationId, baseUrl = GITHUB_RAW_BASE) {
2137
- const [info, files, pkgJson] = await Promise.all([
2138
- fetchIntegrationInfo(integrationId, baseUrl),
2139
- fetchIntegrationFiles(integrationId, baseUrl),
2140
- fetchIntegrationPackageJson(integrationId, baseUrl)
2141
- ]);
2142
- const packageAdditions = info.packageAdditions ?? {};
2143
- if (pkgJson) {
2144
- if (pkgJson.dependencies) packageAdditions.dependencies = {
2145
- ...packageAdditions.dependencies,
2146
- ...pkgJson.dependencies
2147
- };
2148
- if (pkgJson.devDependencies) packageAdditions.devDependencies = {
2149
- ...packageAdditions.devDependencies,
2150
- ...pkgJson.devDependencies
2151
- };
2152
- if (pkgJson.scripts) packageAdditions.scripts = {
2153
- ...packageAdditions.scripts,
2154
- ...pkgJson.scripts
2155
- };
2156
- }
2157
- return IntegrationCompiledSchema.parse({
2158
- ...info,
2159
- id: integrationId,
2160
- files,
2161
- packageAdditions: Object.keys(packageAdditions).length > 0 ? packageAdditions : void 0,
2162
- deletedFiles: []
2163
- });
2164
- }
2165
- /**
2166
- * Fetch multiple integrations in parallel
2167
- */
2168
- async function fetchIntegrations(integrationIds, baseUrl = GITHUB_RAW_BASE) {
2169
- return Promise.all(integrationIds.map((id) => fetchIntegration(id, baseUrl)));
2170
- }
2171
-
2172
- //#endregion
2173
- //#region src/engine/custom-addons/shared.ts
2174
- /**
2175
- * Shared utilities for custom integration/template creation
2176
- * Based on Jack's implementation in create-tsrouter-app
2177
- */
2178
- const IGNORE_FILES = [
2179
- ".template",
2180
- ".integration",
2181
- ".tanstack.json",
2182
- ".git",
2183
- "integration-info.json",
2184
- "integration.json",
2185
- "build",
2186
- "bun.lock",
2187
- "bun.lockb",
2188
- "deno.lock",
2189
- "dist",
2190
- "node_modules",
2191
- "package-lock.json",
2192
- "pnpm-lock.yaml",
2193
- "template.json",
2194
- "template-info.json",
2195
- "yarn.lock"
2196
- ];
2197
- const PROJECT_FILES = ["package.json"];
2198
- const BINARY_EXTENSIONS = [
2199
- ".png",
2200
- ".jpg",
2201
- ".jpeg",
2202
- ".gif",
2203
- ".svg",
2204
- ".ico"
2205
- ];
2206
- /**
2207
- * Check if a file is binary based on extension
2208
- */
2209
- function isBinaryFile(path) {
2210
- return BINARY_EXTENSIONS.includes((0, node_path.extname)(path));
2211
- }
2212
- /**
2213
- * Read file contents, handling binary files with base64 encoding
2214
- */
2215
- function readFileHelper(path) {
2216
- if (isBinaryFile(path)) return `base64::${(0, node_fs.readFileSync)(path).toString("base64")}`;
2217
- return (0, node_fs.readFileSync)(path, "utf-8");
2218
- }
2219
- /**
2220
- * Create an ignore function that respects .gitignore and standard ignore patterns
2221
- * Ported from Jack's createIgnore in file-helpers.ts
2222
- */
2223
- function createIgnore(path, includeProjectFiles = true) {
2224
- const gitignorePath = (0, node_path.resolve)(path, ".gitignore");
2225
- const ignoreList = (0, node_fs.existsSync)(gitignorePath) ? (0, parse_gitignore.default)((0, node_fs.readFileSync)(gitignorePath)).patterns : [];
2226
- const ig = (0, ignore.default)().add(ignoreList);
2227
- return (filePath) => {
2228
- const fileName = (0, node_path.basename)(filePath);
2229
- if (IGNORE_FILES.includes(fileName) || includeProjectFiles && PROJECT_FILES.includes(fileName)) return true;
2230
- const nameWithoutDotSlash = fileName.replace(/^\.\//, "");
2231
- return ig.ignores(nameWithoutDotSlash);
2232
- };
2233
- }
2234
- /**
2235
- * Create package.json additions by comparing original and current
2236
- * Ported from Jack's createPackageAdditions
2237
- */
2238
- function createPackageAdditions(originalPackageJson, currentPackageJson) {
2239
- const packageAdditions = {};
2240
- const origScripts = originalPackageJson.scripts || {};
2241
- const currScripts = currentPackageJson.scripts || {};
2242
- const scripts = {};
2243
- for (const script of Object.keys(currScripts)) {
2244
- const currValue = currScripts[script];
2245
- if (currValue && origScripts[script] !== currValue) scripts[script] = currValue;
2246
- }
2247
- if (Object.keys(scripts).length) packageAdditions.scripts = scripts;
2248
- const origDeps = originalPackageJson.dependencies || {};
2249
- const currDeps = currentPackageJson.dependencies || {};
2250
- const dependencies = {};
2251
- for (const dep of Object.keys(currDeps)) {
2252
- const currValue = currDeps[dep];
2253
- if (currValue && origDeps[dep] !== currValue) dependencies[dep] = currValue;
2254
- }
2255
- if (Object.keys(dependencies).length) packageAdditions.dependencies = dependencies;
2256
- const origDevDeps = originalPackageJson.devDependencies || {};
2257
- const currDevDeps = currentPackageJson.devDependencies || {};
2258
- const devDependencies = {};
2259
- for (const dep of Object.keys(currDevDeps)) {
2260
- const currValue = currDevDeps[dep];
2261
- if (currValue && origDevDeps[dep] !== currValue) devDependencies[dep] = currValue;
2262
- }
2263
- if (Object.keys(devDependencies).length) packageAdditions.devDependencies = devDependencies;
2264
- return packageAdditions;
2265
- }
2266
- async function createCompileOptionsFromPersisted(persisted, integrationsPath) {
2267
- let chosenIntegrations = [];
2268
- if (persisted.chosenIntegrations.length > 0) chosenIntegrations = await fetchIntegrations(persisted.chosenIntegrations, integrationsPath);
2269
- return {
2270
- projectName: persisted.projectName,
2271
- framework: persisted.framework,
2272
- mode: persisted.mode,
2273
- typescript: persisted.typescript,
2274
- tailwind: persisted.tailwind,
2275
- packageManager: persisted.packageManager,
2276
- chosenIntegrations,
2277
- integrationOptions: {},
2278
- customTemplate: void 0
2279
- };
2280
- }
2281
- function runCompile(options) {
2282
- return compile(options);
2283
- }
2284
- /**
2285
- * Compare files recursively between current project and original output
2286
- * Ported from Jack's compareFilesRecursively
2287
- */
2288
- async function compareFilesRecursively(basePath, ignoreFn, original, changedFiles) {
2289
- await compareFilesRecursivelyHelper(basePath, ".", ignoreFn, original, changedFiles);
2290
- }
2291
- async function compareFilesRecursivelyHelper(basePath, relativePath$1, ignoreFn, original, changedFiles) {
2292
- const entries = await (0, node_fs_promises.readdir)((0, node_path.resolve)(basePath, relativePath$1), { withFileTypes: true });
2293
- for (const entry of entries) {
2294
- const entryRelativePath = relativePath$1 === "." ? entry.name : `${relativePath$1}/${entry.name}`;
2295
- const entryFullPath = (0, node_path.resolve)(basePath, entryRelativePath);
2296
- if (ignoreFn(entry.name)) continue;
2297
- if (entry.isDirectory()) await compareFilesRecursivelyHelper(basePath, entryRelativePath, ignoreFn, original, changedFiles);
2298
- else {
2299
- const contents = readFileHelper(entryFullPath);
2300
- const originalKey = entryRelativePath;
2301
- if (!original[originalKey] || original[originalKey] !== contents) changedFiles[entryRelativePath] = contents;
2302
- }
2303
- }
2304
- }
2305
- async function readCurrentProjectOptions(targetDir) {
2306
- const persisted = await readConfigFile(targetDir);
2307
- if (!persisted) throw new Error(`No .tanstack.json file found in ${targetDir}.\nThis project may have been created with an older version of the CLI, or was not created with the TanStack CLI.`);
2308
- return persisted;
2309
- }
2310
- /**
2311
- * Recursively gather files from a directory
2312
- * Ported from Jack's recursivelyGatherFiles
2313
- */
2314
- async function recursivelyGatherFiles(path, includeProjectFiles = true) {
2315
- const ignoreFn = createIgnore(path, includeProjectFiles);
2316
- const files = {};
2317
- if (!(0, node_fs.existsSync)(path)) return files;
2318
- await gatherFilesHelper(path, ".", files, ignoreFn);
2319
- return files;
2320
- }
2321
- async function gatherFilesHelper(basePath, relativePath$1, files, ignoreFn) {
2322
- const entries = await (0, node_fs_promises.readdir)((0, node_path.resolve)(basePath, relativePath$1), { withFileTypes: true });
2323
- for (const entry of entries) {
2324
- if (ignoreFn(entry.name)) continue;
2325
- const entryRelativePath = relativePath$1 === "." ? entry.name : `${relativePath$1}/${entry.name}`;
2326
- const entryFullPath = (0, node_path.resolve)(basePath, entryRelativePath);
2327
- if (entry.isDirectory()) await gatherFilesHelper(basePath, entryRelativePath, files, ignoreFn);
2328
- else files[entryRelativePath] = readFileHelper(entryFullPath);
2329
- }
2330
- }
2331
-
2332
- //#endregion
2333
- //#region src/engine/custom-addons/integration.ts
2334
- const INTEGRATION_DIR = ".integration";
2335
- const INFO_FILE$1 = ".integration/info.json";
2336
- const COMPILED_FILE$1 = "integration.json";
2337
- const ASSETS_DIR = "assets";
2338
- const INTEGRATION_IGNORE_FILES = [
2339
- "main.jsx",
2340
- "App.jsx",
2341
- "main.tsx",
2342
- "App.tsx",
2343
- "routeTree.gen.ts"
2344
- ];
2345
- function camelCase(str) {
2346
- return str.split(/(\.|-|\/)/).filter((part) => /^[a-zA-Z]+$/.test(part)).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
2347
- }
2348
- function templatize(routeCode, routeFile) {
2349
- let code = routeCode;
2350
- code = code.replace(/import { createFileRoute } from ['"]@tanstack\/react-router['"]/g, `import { <% if (fileRouter) { %>createFileRoute<% } else { %>createRoute<% } %> } from '@tanstack/react-router'`);
2351
- const routeMatch = code.match(/export\s+const\s+Route\s*=\s*createFileRoute\(['"]([^'"]+)['"]\)\s*\(\{([^}]+)\}\)/);
2352
- let path = "";
2353
- if (routeMatch) {
2354
- const fullMatch = routeMatch[0];
2355
- path = routeMatch[1];
2356
- const routeDefinition = routeMatch[2];
2357
- code = code.replace(fullMatch, `<% if (codeRouter) { %>
2358
- import type { RootRoute } from '@tanstack/react-router'
2359
- <% } else { %>
2360
- export const Route = createFileRoute('${path}')({${routeDefinition}})
2361
- <% } %>`);
2362
- code += `
2363
- <% if (codeRouter) { %>
2364
- export default (parentRoute: RootRoute) => createRoute({
2365
- path: '${path}',
2366
- ${routeDefinition}
2367
- getParentRoute: () => parentRoute,
2368
- })
2369
- <% } %>
2370
- `;
2371
- } else console.warn(`No route found in the file: ${routeFile}`);
2372
- const name = (0, node_path.basename)(path).replace(".tsx", "").replace(/^demo/, "").replace(".", " ").trim();
2373
- const jsName = camelCase((0, node_path.basename)(path));
2374
- return {
2375
- url: path,
2376
- code,
2377
- name,
2378
- jsName
2379
- };
2380
- }
2381
- async function validateIntegrationSetup(targetDir) {
2382
- const options = await readCurrentProjectOptions(targetDir);
2383
- if (options.mode === "code-router") throw new Error("This project is using code-router mode.\nTo create an integration, the project must use file-router mode.");
2384
- if (!options.tailwind) throw new Error("This project is not using Tailwind CSS.\nTo create an integration, the project must be created with Tailwind CSS.");
2385
- if (!options.typescript) throw new Error("This project is not using TypeScript.\nTo create an integration, the project must be created with TypeScript.");
2386
- }
2387
- async function readOrGenerateIntegrationInfo(options, targetDir) {
2388
- const infoPath = (0, node_path.resolve)(targetDir, INFO_FILE$1);
2389
- if ((0, node_fs.existsSync)(infoPath)) {
2390
- const content = await (0, node_fs_promises.readFile)(infoPath, "utf-8");
2391
- return JSON.parse(content);
2392
- }
2393
- return {
2394
- id: `${options.projectName}-integration`,
2395
- name: `${options.projectName} Integration`,
2396
- description: "Custom integration",
2397
- author: "Author <author@example.com>",
2398
- version: "0.0.1",
2399
- license: "MIT",
2400
- link: `https://github.com/example/${options.projectName}-integration`,
2401
- type: "integration",
2402
- phase: "integration",
2403
- modes: [options.mode],
2404
- requiresTailwind: options.tailwind || void 0,
2405
- dependsOn: options.chosenIntegrations.length > 0 ? options.chosenIntegrations : void 0,
2406
- routes: [],
2407
- packageAdditions: {
2408
- scripts: {},
2409
- dependencies: {},
2410
- devDependencies: {}
2411
- }
2412
- };
2413
- }
2414
- async function generateBaseProject(persistedOptions, targetDir, integrationsPath) {
2415
- return {
2416
- info: await readOrGenerateIntegrationInfo(persistedOptions, targetDir),
2417
- output: runCompile(await createCompileOptionsFromPersisted(persistedOptions, integrationsPath))
2418
- };
2419
- }
2420
- async function buildAssetsDirectory(targetDir, output, info) {
2421
- const assetsDir = (0, node_path.resolve)(targetDir, INTEGRATION_DIR, ASSETS_DIR);
2422
- if ((0, node_fs.existsSync)(assetsDir)) return;
2423
- const ignoreFn = createIgnore(targetDir);
2424
- const changedFiles = {};
2425
- await compareFilesRecursively(targetDir, ignoreFn, output.files, changedFiles);
2426
- for (const file of Object.keys(changedFiles)) {
2427
- if (INTEGRATION_IGNORE_FILES.includes((0, node_path.basename)(file))) continue;
2428
- const targetPath = (0, node_path.resolve)(assetsDir, file);
2429
- (0, node_fs.mkdirSync)((0, node_path.dirname)(targetPath), { recursive: true });
2430
- const fileContent = changedFiles[file];
2431
- if (file.includes("/routes/")) {
2432
- const { url, code, name, jsName } = templatize(fileContent, file);
2433
- info.routes ||= [];
2434
- if (!info.routes.find((r) => r.url === url)) info.routes.push({
2435
- url,
2436
- name,
2437
- jsName,
2438
- path: file
2439
- });
2440
- (0, node_fs.writeFileSync)(`${targetPath}.ejs`, code);
2441
- } else (0, node_fs.writeFileSync)(targetPath, fileContent);
2442
- }
2443
- }
2444
- async function updateIntegrationInfo(targetDir, integrationsPath) {
2445
- const { info, output } = await generateBaseProject(await readCurrentProjectOptions(targetDir), targetDir, integrationsPath);
2446
- info.packageAdditions = createPackageAdditions(JSON.parse(output.files["package.json"]), JSON.parse(await (0, node_fs_promises.readFile)((0, node_path.resolve)(targetDir, "package.json"), "utf-8")));
2447
- await buildAssetsDirectory(targetDir, output, info);
2448
- await (0, node_fs_promises.mkdir)((0, node_path.resolve)(targetDir, (0, node_path.dirname)(INFO_FILE$1)), { recursive: true });
2449
- await (0, node_fs_promises.writeFile)((0, node_path.resolve)(targetDir, INFO_FILE$1), JSON.stringify(info, null, 2));
2450
- }
2451
- async function compileIntegration(targetDir, _integrationsPath) {
2452
- const persistedOptions = await readCurrentProjectOptions(targetDir);
2453
- const info = await readOrGenerateIntegrationInfo(persistedOptions, targetDir);
2454
- const assetsDir = (0, node_path.resolve)(targetDir, INTEGRATION_DIR, ASSETS_DIR);
2455
- const compiledInfo = {
2456
- ...info,
2457
- id: info.id || `${persistedOptions.projectName}-integration`,
2458
- files: await recursivelyGatherFiles(assetsDir),
2459
- deletedFiles: []
2460
- };
2461
- await (0, node_fs_promises.writeFile)((0, node_path.resolve)(targetDir, COMPILED_FILE$1), JSON.stringify(compiledInfo, null, 2));
2462
- console.log(`Compiled integration written to ${COMPILED_FILE$1}`);
2463
- }
2464
- async function initIntegration(targetDir, integrationsPath) {
2465
- await validateIntegrationSetup(targetDir);
2466
- await updateIntegrationInfo(targetDir, integrationsPath);
2467
- await compileIntegration(targetDir, integrationsPath);
2468
- console.log(`
2469
- Integration initialized successfully!
2470
-
2471
- Files created:
2472
- ${INFO_FILE$1} - Integration metadata (edit this to customize)
2473
- ${INTEGRATION_DIR}/${ASSETS_DIR}/ - Integration asset files
2474
- ${COMPILED_FILE$1} - Compiled integration (distribute this)
2475
-
2476
- Next steps:
2477
- 1. Edit ${INFO_FILE$1} to customize your integration metadata
2478
- 2. Run 'tanstack integration compile' to rebuild after changes
2479
- 3. Share ${COMPILED_FILE$1} or host it publicly
2480
- `);
2481
- }
2482
- /**
2483
- * Load a remote integration from a URL
2484
- */
2485
- async function loadRemoteIntegration(url) {
2486
- const response = await fetch(url);
2487
- if (!response.ok) throw new Error(`Failed to fetch integration from ${url}: ${response.statusText}`);
2488
- const jsonContent = await response.json();
2489
- const result = IntegrationCompiledSchema.safeParse(jsonContent);
2490
- if (!result.success) throw new Error(`Invalid integration at ${url}: ${result.error.message}`);
2491
- const integration = result.data;
2492
- if (!integration.id) integration.id = url;
2493
- return integration;
2494
- }
2495
-
2496
- //#endregion
2497
- //#region src/engine/custom-addons/template.ts
2498
- const INFO_FILE = "template-info.json";
2499
- const COMPILED_FILE = "template.json";
2500
- /**
2501
- * Generate default template info from project options
2502
- * Custom templates are just integration presets - they capture which integrations are selected
2503
- */
2504
- async function readOrGenerateTemplateInfo(options, targetDir) {
2505
- const infoPath = (0, node_path.resolve)(targetDir, INFO_FILE);
2506
- if ((0, node_fs.existsSync)(infoPath)) {
2507
- const content = await (0, node_fs_promises.readFile)(infoPath, "utf-8");
2508
- return JSON.parse(content);
2509
- }
2510
- return {
2511
- id: `${options.projectName}-template`,
2512
- name: `${options.projectName} Template`,
2513
- description: "A curated project template",
2514
- framework: options.framework,
2515
- mode: options.mode,
2516
- typescript: options.typescript,
2517
- tailwind: options.tailwind,
2518
- integrations: options.chosenIntegrations
2519
- };
2520
- }
2521
- /**
2522
- * Compile a custom template from the current project
2523
- * Custom templates are just integration presets - they specify project defaults and which integrations to include
2524
- */
2525
- async function compileTemplate(targetDir) {
2526
- const persistedOptions = await readCurrentProjectOptions(targetDir);
2527
- const info = await readOrGenerateTemplateInfo(persistedOptions, targetDir);
2528
- const compiledInfo = {
2529
- ...info,
2530
- id: info.id || `${persistedOptions.projectName}-template`
2531
- };
2532
- await (0, node_fs_promises.writeFile)((0, node_path.resolve)(targetDir, COMPILED_FILE), JSON.stringify(compiledInfo, null, 2));
2533
- console.log(`Compiled template written to ${COMPILED_FILE}`);
2534
- console.log(`\nIncluded integrations: ${compiledInfo.integrations.length > 0 ? compiledInfo.integrations.join(", ") : "(none)"}`);
2535
- }
2536
- async function initTemplate(targetDir) {
2537
- const info = await readOrGenerateTemplateInfo(await readCurrentProjectOptions(targetDir), targetDir);
2538
- await (0, node_fs_promises.writeFile)((0, node_path.resolve)(targetDir, INFO_FILE), JSON.stringify(info, null, 2));
2539
- await compileTemplate(targetDir);
2540
- console.log(`
2541
- Custom template initialized successfully!
2542
-
2543
- Files created:
2544
- ${INFO_FILE} - Template metadata (edit this to customize)
2545
- ${COMPILED_FILE} - Compiled template (distribute this)
2546
-
2547
- Custom templates are integration presets. They capture:
2548
- - Project defaults (framework, mode, typescript, tailwind)
2549
- - Which integrations to include
2550
- - Preset integration options (if any)
2551
-
2552
- Next steps:
2553
- 1. Edit ${INFO_FILE} to customize name, description, and integrations
2554
- 2. Run 'tanstack template compile' to rebuild after changes
2555
- 3. Share ${COMPILED_FILE} or host it publicly
2556
- 4. Users can use: tanstack create --template <url-to-template.json>
2557
- `);
2558
- }
2559
- /**
2560
- * Load a remote custom template from a URL
2561
- */
2562
- async function loadTemplate(url) {
2563
- const response = await fetch(url);
2564
- if (!response.ok) throw new Error(`Failed to fetch template from ${url}: ${response.statusText}`);
2565
- const jsonContent = await response.json();
2566
- const result = CustomTemplateCompiledSchema.safeParse(jsonContent);
2567
- if (!result.success) throw new Error(`Invalid template at ${url}: ${result.error.message}`);
2568
- const template = result.data;
2569
- if (!template.id) template.id = url;
2570
- return template;
2571
- }
2572
-
2573
- //#endregion
2574
- Object.defineProperty(exports, 'CONFIG_FILE', {
2575
- enumerable: true,
2576
- get: function () {
2577
- return CONFIG_FILE;
2578
- }
2579
- });
2580
- Object.defineProperty(exports, 'CategorySchema', {
2581
- enumerable: true,
2582
- get: function () {
2583
- return CategorySchema;
2584
- }
2585
- });
2586
- Object.defineProperty(exports, 'CommandSchema', {
2587
- enumerable: true,
2588
- get: function () {
2589
- return CommandSchema;
2590
- }
2591
- });
2592
- Object.defineProperty(exports, 'CustomTemplateCompiledSchema', {
2593
- enumerable: true,
2594
- get: function () {
2595
- return CustomTemplateCompiledSchema;
2596
- }
2597
- });
2598
- Object.defineProperty(exports, 'CustomTemplateInfoSchema', {
2599
- enumerable: true,
2600
- get: function () {
2601
- return CustomTemplateInfoSchema;
2602
- }
2603
- });
2604
- Object.defineProperty(exports, 'EnvVarSchema', {
2605
- enumerable: true,
2606
- get: function () {
2607
- return EnvVarSchema;
2608
- }
2609
- });
2610
- Object.defineProperty(exports, 'HookSchema', {
2611
- enumerable: true,
2612
- get: function () {
2613
- return HookSchema;
2614
- }
2615
- });
2616
- Object.defineProperty(exports, 'IntegrationCompiledSchema', {
2617
- enumerable: true,
2618
- get: function () {
2619
- return IntegrationCompiledSchema;
2620
- }
2621
- });
2622
- Object.defineProperty(exports, 'IntegrationInfoSchema', {
2623
- enumerable: true,
2624
- get: function () {
2625
- return IntegrationInfoSchema;
2626
- }
2627
- });
2628
- Object.defineProperty(exports, 'IntegrationOptionSchema', {
2629
- enumerable: true,
2630
- get: function () {
2631
- return IntegrationOptionSchema;
2632
- }
2633
- });
2634
- Object.defineProperty(exports, 'IntegrationOptionsSchema', {
2635
- enumerable: true,
2636
- get: function () {
2637
- return IntegrationOptionsSchema;
2638
- }
2639
- });
2640
- Object.defineProperty(exports, 'IntegrationPhaseSchema', {
2641
- enumerable: true,
2642
- get: function () {
2643
- return IntegrationPhaseSchema;
2644
- }
2645
- });
2646
- Object.defineProperty(exports, 'IntegrationTypeSchema', {
2647
- enumerable: true,
2648
- get: function () {
2649
- return IntegrationTypeSchema;
2650
- }
2651
- });
2652
- Object.defineProperty(exports, 'ManifestIntegrationSchema', {
2653
- enumerable: true,
2654
- get: function () {
2655
- return ManifestIntegrationSchema;
2656
- }
2657
- });
2658
- Object.defineProperty(exports, 'ManifestSchema', {
2659
- enumerable: true,
2660
- get: function () {
2661
- return ManifestSchema;
2662
- }
2663
- });
2664
- Object.defineProperty(exports, 'RouteSchema', {
2665
- enumerable: true,
2666
- get: function () {
2667
- return RouteSchema;
2668
- }
2669
- });
2670
- Object.defineProperty(exports, 'RouterModeSchema', {
2671
- enumerable: true,
2672
- get: function () {
2673
- return RouterModeSchema;
2674
- }
2675
- });
2676
- Object.defineProperty(exports, '__toESM', {
2677
- enumerable: true,
2678
- get: function () {
2679
- return __toESM;
2680
- }
2681
- });
2682
- Object.defineProperty(exports, 'compile', {
2683
- enumerable: true,
2684
- get: function () {
2685
- return compile;
2686
- }
2687
- });
2688
- Object.defineProperty(exports, 'compileIntegration', {
2689
- enumerable: true,
2690
- get: function () {
2691
- return compileIntegration;
2692
- }
2693
- });
2694
- Object.defineProperty(exports, 'compileTemplate', {
2695
- enumerable: true,
2696
- get: function () {
2697
- return compileTemplate;
2698
- }
2699
- });
2700
- Object.defineProperty(exports, 'compileWithAttribution', {
2701
- enumerable: true,
2702
- get: function () {
2703
- return compileWithAttribution;
2704
- }
2705
- });
2706
- Object.defineProperty(exports, 'fetchIntegration', {
2707
- enumerable: true,
2708
- get: function () {
2709
- return fetchIntegration;
2710
- }
2711
- });
2712
- Object.defineProperty(exports, 'fetchIntegrationFiles', {
2713
- enumerable: true,
2714
- get: function () {
2715
- return fetchIntegrationFiles;
2716
- }
2717
- });
2718
- Object.defineProperty(exports, 'fetchIntegrationInfo', {
2719
- enumerable: true,
2720
- get: function () {
2721
- return fetchIntegrationInfo;
2722
- }
2723
- });
2724
- Object.defineProperty(exports, 'fetchIntegrations', {
2725
- enumerable: true,
2726
- get: function () {
2727
- return fetchIntegrations;
2728
- }
2729
- });
2730
- Object.defineProperty(exports, 'fetchManifest', {
2731
- enumerable: true,
2732
- get: function () {
2733
- return fetchManifest;
2734
- }
2735
- });
2736
- Object.defineProperty(exports, 'initIntegration', {
2737
- enumerable: true,
2738
- get: function () {
2739
- return initIntegration;
2740
- }
2741
- });
2742
- Object.defineProperty(exports, 'initTemplate', {
2743
- enumerable: true,
2744
- get: function () {
2745
- return initTemplate;
2746
- }
2747
- });
2748
- Object.defineProperty(exports, 'loadRemoteIntegration', {
2749
- enumerable: true,
2750
- get: function () {
2751
- return loadRemoteIntegration;
2752
- }
2753
- });
2754
- Object.defineProperty(exports, 'loadTemplate', {
2755
- enumerable: true,
2756
- get: function () {
2757
- return loadTemplate;
2758
- }
2759
- });
2760
- Object.defineProperty(exports, 'processTemplateFile', {
2761
- enumerable: true,
2762
- get: function () {
2763
- return processTemplateFile;
2764
- }
2765
- });
2766
- Object.defineProperty(exports, 'readConfigFile', {
2767
- enumerable: true,
2768
- get: function () {
2769
- return readConfigFile;
2770
- }
2771
- });
2772
- Object.defineProperty(exports, 'relativePath', {
2773
- enumerable: true,
2774
- get: function () {
2775
- return relativePath;
2776
- }
2777
- });
2778
- Object.defineProperty(exports, 'writeConfigFile', {
2779
- enumerable: true,
2780
- get: function () {
2781
- return writeConfigFile;
2782
- }
2783
- });