@tanstack/cta-ui 0.10.0-alpha.24 → 0.10.0-alpha.27

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 (80) hide show
  1. package/README.md +20 -0
  2. package/dist/assets/index-DSKioOfX.css +1 -0
  3. package/dist/assets/index-DWTDdndE.js +213 -0
  4. package/dist/assets/index-DWTDdndE.js.map +1 -0
  5. package/dist/favicon.ico +0 -0
  6. package/dist/index.html +19 -0
  7. package/dist/logo-color-100w.png +0 -0
  8. package/dist/logo192.png +0 -0
  9. package/dist/logo512.png +0 -0
  10. package/dist/manifest.json +25 -0
  11. package/dist/robots.txt +3 -0
  12. package/dist/tailwind.svg +1 -0
  13. package/dist/tanstack.png +0 -0
  14. package/dist/typescript.svg +1 -0
  15. package/index.html +18 -0
  16. package/lib/engine-handling/add-to-app-wrapper.ts +134 -0
  17. package/{src → lib}/engine-handling/create-app-wrapper.ts +48 -39
  18. package/{src → lib}/engine-handling/file-helpers.ts +4 -2
  19. package/{src → lib}/engine-handling/generate-initial-payload.ts +58 -51
  20. package/lib/engine-handling/server-environment.ts +37 -0
  21. package/lib/index.ts +150 -34
  22. package/lib/types.d.ts +20 -0
  23. package/lib-dist/engine-handling/add-to-app-wrapper.d.ts +14 -0
  24. package/lib-dist/engine-handling/add-to-app-wrapper.js +78 -0
  25. package/lib-dist/engine-handling/create-app-wrapper.d.ts +14 -0
  26. package/lib-dist/engine-handling/create-app-wrapper.js +70 -0
  27. package/lib-dist/engine-handling/file-helpers.d.ts +2 -0
  28. package/lib-dist/engine-handling/file-helpers.js +21 -0
  29. package/lib-dist/engine-handling/framework-registration.d.ts +1 -0
  30. package/lib-dist/engine-handling/framework-registration.js +10 -0
  31. package/lib-dist/engine-handling/generate-initial-payload.d.ts +32 -0
  32. package/lib-dist/engine-handling/generate-initial-payload.js +88 -0
  33. package/lib-dist/engine-handling/server-environment.d.ts +17 -0
  34. package/lib-dist/engine-handling/server-environment.js +18 -0
  35. package/lib-dist/index.d.ts +5 -7
  36. package/lib-dist/index.js +124 -18
  37. package/package.json +12 -12
  38. package/public/logo-color-100w.png +0 -0
  39. package/src/components/background-animation.tsx +229 -0
  40. package/src/components/cta-sidebar.tsx +28 -33
  41. package/src/components/file-navigator.tsx +72 -74
  42. package/src/components/header.tsx +31 -0
  43. package/src/components/sidebar-items/add-ons.tsx +48 -45
  44. package/src/components/sidebar-items/mode-selector.tsx +6 -4
  45. package/src/components/sidebar-items/project-name.tsx +4 -5
  46. package/src/components/sidebar-items/typescript-switch.tsx +3 -3
  47. package/src/components/startup-dialog.tsx +4 -6
  48. package/src/components/ui/switch.tsx +6 -6
  49. package/src/hooks/use-mounted.ts +9 -0
  50. package/src/hooks/use-preferred-reduced-motion.ts +27 -0
  51. package/src/index.tsx +48 -0
  52. package/src/lib/api.ts +10 -8
  53. package/src/main.tsx +12 -0
  54. package/src/store/project.ts +36 -20
  55. package/src/styles.css +90 -18
  56. package/src/types.d.ts +1 -1
  57. package/tailwind.config.cjs +47 -0
  58. package/vite.config.ts +16 -0
  59. package/app.config.js +0 -22
  60. package/src/api.ts +0 -6
  61. package/src/client.tsx +0 -8
  62. package/src/engine-handling/add-to-app-wrapper.ts +0 -114
  63. package/src/engine-handling/server-environment.ts +0 -30
  64. package/src/integrations/tanstack-query/layout.tsx +0 -5
  65. package/src/integrations/tanstack-query/root-provider.tsx +0 -15
  66. package/src/logo.svg +0 -44
  67. package/src/routeTree.gen.ts +0 -88
  68. package/src/router.tsx +0 -32
  69. package/src/routes/__root.tsx +0 -86
  70. package/src/routes/api/add-to-app.ts +0 -21
  71. package/src/routes/api/create-app.ts +0 -21
  72. package/src/routes/api/dry-run-add-to-app.ts +0 -16
  73. package/src/routes/api/dry-run-create-app.ts +0 -16
  74. package/src/routes/api/initial-payload.ts +0 -10
  75. package/src/routes/api/load-remote-add-on.ts +0 -42
  76. package/src/routes/api/load-starter.ts +0 -47
  77. package/src/routes/api/shutdown.ts +0 -11
  78. package/src/routes/index.tsx +0 -17
  79. package/src/ssr.tsx +0 -12
  80. /package/{src → lib}/engine-handling/framework-registration.ts +0 -0
Binary file
@@ -0,0 +1,19 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>TanStack CTA</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
9
+ <link
10
+ rel="stylesheet"
11
+ href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
12
+ />
13
+ <script type="module" crossorigin src="/assets/index-DWTDdndE.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-DSKioOfX.css">
15
+ </head>
16
+ <body class="dark">
17
+ <div id="root"></div>
18
+ </body>
19
+ </html>
Binary file
Binary file
Binary file
@@ -0,0 +1,25 @@
1
+ {
2
+ "short_name": "TanStack App",
3
+ "name": "Create TanStack App Sample",
4
+ "icons": [
5
+ {
6
+ "src": "favicon.ico",
7
+ "sizes": "64x64 32x32 24x24 16x16",
8
+ "type": "image/x-icon"
9
+ },
10
+ {
11
+ "src": "logo192.png",
12
+ "type": "image/png",
13
+ "sizes": "192x192"
14
+ },
15
+ {
16
+ "src": "logo512.png",
17
+ "type": "image/png",
18
+ "sizes": "512x512"
19
+ }
20
+ ],
21
+ "start_url": ".",
22
+ "display": "standalone",
23
+ "theme_color": "#000000",
24
+ "background_color": "#ffffff"
25
+ }
@@ -0,0 +1,3 @@
1
+ # https://www.robotstxt.org/robotstxt.html
2
+ User-agent: *
3
+ Disallow:
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 54 33"><g clip-path="url(#a)"><path fill="#38bdf8" fill-rule="evenodd" d="M27 0c-7.2 0-11.7 3.6-13.5 10.8 2.7-3.6 5.85-4.95 9.45-4.05 2.054.513 3.522 2.004 5.147 3.653C30.744 13.09 33.808 16.2 40.5 16.2c7.2 0 11.7-3.6 13.5-10.8-2.7 3.6-5.85 4.95-9.45 4.05-2.054-.513-3.522-2.004-5.147-3.653C36.756 3.11 33.692 0 27 0zM13.5 16.2C6.3 16.2 1.8 19.8 0 27c2.7-3.6 5.85-4.95 9.45-4.05 2.054.514 3.522 2.004 5.147 3.653C17.244 29.29 20.308 32.4 27 32.4c7.2 0 11.7-3.6 13.5-10.8-2.7 3.6-5.85 4.95-9.45 4.05-2.054-.513-3.522-2.004-5.147-3.653C23.256 19.31 20.192 16.2 13.5 16.2z" clip-rule="evenodd"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h54v32.4H0z"/></clipPath></defs></svg>
Binary file
@@ -0,0 +1 @@
1
+ <svg viewBox="0 0 256 256" width="256" height="256" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M20 0h216c11.046 0 20 8.954 20 20v216c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20V20C0 8.954 8.954 0 20 0Z" fill="#3178C6"/><path d="M150.518 200.475v27.62c4.492 2.302 9.805 4.028 15.938 5.179 6.133 1.151 12.597 1.726 19.393 1.726 6.622 0 12.914-.633 18.874-1.899 5.96-1.266 11.187-3.352 15.678-6.257 4.492-2.906 8.048-6.704 10.669-11.394 2.62-4.689 3.93-10.486 3.93-17.391 0-5.006-.749-9.394-2.246-13.163a30.748 30.748 0 0 0-6.479-10.055c-2.821-2.935-6.205-5.567-10.149-7.898-3.945-2.33-8.394-4.531-13.347-6.602-3.628-1.497-6.881-2.949-9.761-4.359-2.879-1.41-5.327-2.848-7.342-4.316-2.016-1.467-3.571-3.021-4.665-4.661-1.094-1.64-1.641-3.495-1.641-5.567 0-1.899.489-3.61 1.468-5.135s2.362-2.834 4.147-3.927c1.785-1.094 3.973-1.942 6.565-2.547 2.591-.604 5.471-.906 8.638-.906 2.304 0 4.737.173 7.299.518 2.563.345 5.14.877 7.732 1.597a53.669 53.669 0 0 1 7.558 2.719 41.7 41.7 0 0 1 6.781 3.797v-25.807c-4.204-1.611-8.797-2.805-13.778-3.582-4.981-.777-10.697-1.165-17.147-1.165-6.565 0-12.784.705-18.658 2.115-5.874 1.409-11.043 3.61-15.506 6.602-4.463 2.993-7.99 6.805-10.582 11.437-2.591 4.632-3.887 10.17-3.887 16.615 0 8.228 2.375 15.248 7.127 21.06 4.751 5.811 11.963 10.731 21.638 14.759a291.458 291.458 0 0 1 10.625 4.575c3.283 1.496 6.119 3.049 8.509 4.66 2.39 1.611 4.276 3.366 5.658 5.265 1.382 1.899 2.073 4.057 2.073 6.474a9.901 9.901 0 0 1-1.296 4.963c-.863 1.524-2.174 2.848-3.93 3.97-1.756 1.122-3.945 1.999-6.565 2.632-2.62.633-5.687.95-9.2.95-5.989 0-11.92-1.05-17.794-3.151-5.875-2.1-11.317-5.25-16.327-9.451Zm-46.036-68.733H140V109H41v22.742h35.345V233h28.137V131.742Z" fill="#FFF"/></svg>
package/index.html ADDED
@@ -0,0 +1,18 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>TanStack CTA</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="" />
9
+ <link
10
+ rel="stylesheet"
11
+ href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"
12
+ />
13
+ </head>
14
+ <body class="dark">
15
+ <div id="root"></div>
16
+ <script type="module" src="/src/main.tsx"></script>
17
+ </body>
18
+ </html>
@@ -0,0 +1,134 @@
1
+ import { resolve } from 'node:path'
2
+
3
+ import {
4
+ CONFIG_FILE,
5
+ addToApp,
6
+ createAppOptionsFromPersisted,
7
+ createDefaultEnvironment,
8
+ createMemoryEnvironment,
9
+ createSerializedOptionsFromPersisted,
10
+ readConfigFile,
11
+ recursivelyGatherFiles,
12
+ writeConfigFileToEnvironment,
13
+ } from '@tanstack/cta-engine'
14
+
15
+ import { cleanUpFileArray, cleanUpFiles } from './file-helpers.js'
16
+ import { getProjectPath } from './server-environment.js'
17
+ import { createAppWrapper } from './create-app-wrapper.js'
18
+
19
+ import type { Environment } from '@tanstack/cta-engine'
20
+ import type { Response } from 'express'
21
+ import type { DryRunOutput } from '../types.js'
22
+
23
+ export async function addToAppWrapper(
24
+ addOns: Array<string>,
25
+ opts: {
26
+ dryRun?: boolean
27
+ response?: Response
28
+ environmentFactory?: () => Environment
29
+ },
30
+ ) {
31
+ const projectPath = getProjectPath()
32
+
33
+ const persistedOptions = await readConfigFile(projectPath)
34
+
35
+ if (!persistedOptions) {
36
+ throw new Error('No config file found')
37
+ }
38
+
39
+ const options = await createAppOptionsFromPersisted(persistedOptions)
40
+ options.targetDir = projectPath
41
+
42
+ const newAddons: Array<string> = []
43
+ for (const addOn of addOns) {
44
+ if (!options.chosenAddOns.some((a) => a.id === addOn)) {
45
+ newAddons.push(addOn)
46
+ }
47
+ }
48
+
49
+ if (newAddons.length === 0) {
50
+ const serializedOptions =
51
+ createSerializedOptionsFromPersisted(persistedOptions)
52
+ return await createAppWrapper(serializedOptions, opts)
53
+ }
54
+
55
+ async function createEnvironment(): Promise<{
56
+ environment: Environment
57
+ output: DryRunOutput
58
+ }> {
59
+ if (opts.dryRun) {
60
+ const { environment, output } = createMemoryEnvironment(projectPath)
61
+
62
+ const localFiles = await cleanUpFiles(
63
+ await recursivelyGatherFiles(projectPath, false),
64
+ )
65
+ for (const file of Object.keys(localFiles)) {
66
+ environment.writeFile(resolve(projectPath, file), localFiles[file])
67
+ }
68
+ return { environment, output }
69
+ }
70
+ return {
71
+ environment: opts.environmentFactory?.() ?? createDefaultEnvironment(),
72
+ output: { files: {}, deletedFiles: [], commands: [] },
73
+ }
74
+ }
75
+
76
+ const { environment, output } = await createEnvironment()
77
+
78
+ if (opts.response) {
79
+ opts.response.writeHead(200, {
80
+ 'Content-Type': 'text/plain',
81
+ 'Transfer-Encoding': 'chunked',
82
+ })
83
+
84
+ environment.startStep = ({
85
+ id,
86
+ type,
87
+ message,
88
+ }: {
89
+ id: string
90
+ type: string
91
+ message: string
92
+ }) => {
93
+ opts.response!.write(
94
+ JSON.stringify({
95
+ msgType: 'start',
96
+ id,
97
+ type,
98
+ message,
99
+ }) + '\n',
100
+ )
101
+ }
102
+ environment.finishStep = (id: string, message: string) => {
103
+ opts.response!.write(
104
+ JSON.stringify({
105
+ msgType: 'finish',
106
+ id,
107
+ message,
108
+ }) + '\n',
109
+ )
110
+ }
111
+
112
+ environment.startRun()
113
+ await addToApp(environment, newAddons, projectPath, {
114
+ forced: true,
115
+ })
116
+ environment.finishRun()
117
+ opts.response.end()
118
+ } else {
119
+ environment.startRun()
120
+ environment.writeFile(
121
+ resolve(projectPath, CONFIG_FILE),
122
+ JSON.stringify(persistedOptions, null, 2),
123
+ )
124
+ await addToApp(environment, newAddons, projectPath, {
125
+ forced: true,
126
+ })
127
+ writeConfigFileToEnvironment(environment, options)
128
+ environment.finishRun()
129
+
130
+ output.files = cleanUpFiles(output.files, projectPath)
131
+ output.deletedFiles = cleanUpFileArray(output.deletedFiles, projectPath)
132
+ return output
133
+ }
134
+ }
@@ -9,16 +9,27 @@ import {
9
9
  loadStarter,
10
10
  } from '@tanstack/cta-engine'
11
11
 
12
- import { registerFrameworks } from './framework-registration'
12
+ import { registerFrameworks } from './framework-registration.js'
13
13
 
14
- import { cleanUpFileArray, cleanUpFiles } from './file-helpers'
15
- import { getApplicationMode, getProjectPath } from './server-environment'
14
+ import { cleanUpFileArray, cleanUpFiles } from './file-helpers.js'
15
+ import { getApplicationMode, getProjectPath } from './server-environment.js'
16
16
 
17
- import type { Options, SerializedOptions, Starter } from '@tanstack/cta-engine'
17
+ import type {
18
+ Environment,
19
+ Options,
20
+ SerializedOptions,
21
+ Starter,
22
+ } from '@tanstack/cta-engine'
23
+
24
+ import type { Response } from 'express'
18
25
 
19
26
  export async function createAppWrapper(
20
27
  projectOptions: SerializedOptions,
21
- opts: { dryRun?: boolean; stream?: boolean },
28
+ opts: {
29
+ dryRun?: boolean
30
+ response?: Response
31
+ environmentFactory?: () => Environment
32
+ },
22
33
  ) {
23
34
  registerFrameworks()
24
35
 
@@ -28,8 +39,10 @@ export async function createAppWrapper(
28
39
  const addOns: Array<string> = [...projectOptions.chosenAddOns]
29
40
  if (projectOptions.starter) {
30
41
  starter = await loadStarter(projectOptions.starter)
31
- for (const addOn of starter.dependsOn ?? []) {
32
- addOns.push(addOn)
42
+ if (starter) {
43
+ for (const addOn of starter.dependsOn ?? []) {
44
+ addOns.push(addOn)
45
+ }
33
46
  }
34
47
  }
35
48
  const chosenAddOns = await finalizeAddOns(
@@ -57,45 +70,41 @@ export async function createAppWrapper(
57
70
  return createMemoryEnvironment(targetDir)
58
71
  }
59
72
  return {
60
- environment: createDefaultEnvironment(),
73
+ environment: opts.environmentFactory?.() ?? createDefaultEnvironment(),
61
74
  output: { files: {}, deletedFiles: [], commands: [] },
62
75
  }
63
76
  }
64
77
 
65
78
  const { environment, output } = createEnvironment()
66
79
 
67
- if (opts.stream) {
68
- return new ReadableStream({
69
- start(controller) {
70
- environment.startStep = ({ id, type, message }) => {
71
- controller.enqueue(
72
- new TextEncoder().encode(
73
- JSON.stringify({
74
- msgType: 'start',
75
- id,
76
- type,
77
- message,
78
- }) + '\n',
79
- ),
80
- )
81
- }
82
- environment.finishStep = (id, message) => {
83
- controller.enqueue(
84
- new TextEncoder().encode(
85
- JSON.stringify({
86
- msgType: 'finish',
87
- id,
88
- message,
89
- }) + '\n',
90
- ),
91
- )
92
- }
93
-
94
- createApp(environment, options).then(() => {
95
- controller.close()
96
- })
97
- },
80
+ if (opts.response) {
81
+ opts.response.writeHead(200, {
82
+ 'Content-Type': 'text/plain',
83
+ 'Transfer-Encoding': 'chunked',
98
84
  })
85
+
86
+ environment.startStep = ({ id, type, message }) => {
87
+ opts.response!.write(
88
+ JSON.stringify({
89
+ msgType: 'start',
90
+ id,
91
+ type,
92
+ message,
93
+ }) + '\n',
94
+ )
95
+ }
96
+ environment.finishStep = (id, message) => {
97
+ opts.response!.write(
98
+ JSON.stringify({
99
+ msgType: 'finish',
100
+ id,
101
+ message,
102
+ }) + '\n',
103
+ )
104
+ }
105
+
106
+ await createApp(environment, options)
107
+ opts.response.end()
99
108
  } else {
100
109
  await createApp(environment, options)
101
110
 
@@ -1,5 +1,7 @@
1
1
  import { basename } from 'node:path'
2
2
 
3
+ import { CONFIG_FILE } from '@tanstack/cta-engine'
4
+
3
5
  export function cleanUpFiles(
4
6
  files: Record<string, string>,
5
7
  targetDir?: string,
@@ -8,7 +10,7 @@ export function cleanUpFiles(
8
10
  const content = files[file].startsWith('base64::')
9
11
  ? '<binary file>'
10
12
  : files[file]
11
- if (basename(file) !== '.cta.json') {
13
+ if (basename(file) !== CONFIG_FILE) {
12
14
  acc[targetDir ? file.replace(targetDir, '.') : file] = content
13
15
  }
14
16
  return acc
@@ -17,7 +19,7 @@ export function cleanUpFiles(
17
19
 
18
20
  export function cleanUpFileArray(files: Array<string>, targetDir?: string) {
19
21
  return files.reduce<Array<string>>((acc, file) => {
20
- if (basename(file) !== '.cta.json') {
22
+ if (basename(file) !== CONFIG_FILE) {
21
23
  acc.push(targetDir ? file.replace(targetDir, '.') : file)
22
24
  }
23
25
  return acc
@@ -1,10 +1,12 @@
1
- import { readFileSync } from 'node:fs'
2
1
  import { basename, resolve } from 'node:path'
3
2
 
4
3
  import {
5
4
  createSerializedOptionsFromPersisted,
6
5
  getAllAddOns,
7
6
  getFrameworkById,
7
+ getRawRegistry,
8
+ getRegistryAddOns,
9
+ readConfigFile,
8
10
  recursivelyGatherFiles,
9
11
  } from '@tanstack/cta-engine'
10
12
 
@@ -17,18 +19,24 @@ import {
17
19
  getForcedRouterMode,
18
20
  getProjectOptions,
19
21
  getProjectPath,
20
- getRegistry,
22
+ getRegistry as getRegistryURL,
21
23
  } from './server-environment.js'
22
24
 
23
- import type { SerializedOptions } from '@tanstack/cta-engine'
24
- import type { Registry } from '@/types.js'
25
+ import type { AddOn, SerializedOptions } from '@tanstack/cta-engine'
26
+ import type { AddOnInfo } from '../types.js'
25
27
 
26
- function absolutizeUrl(originalUrl: string, relativeUrl: string) {
27
- if (relativeUrl.startsWith('http') || relativeUrl.startsWith('https')) {
28
- return relativeUrl
28
+ function convertAddOnToAddOnInfo(addOn: AddOn): AddOnInfo {
29
+ return {
30
+ id: addOn.id,
31
+ name: addOn.name,
32
+ description: addOn.description,
33
+ modes: addOn.modes as Array<'code-router' | 'file-router'>,
34
+ type: addOn.type,
35
+ smallLogo: addOn.smallLogo,
36
+ logo: addOn.logo,
37
+ link: addOn.link!,
38
+ dependsOn: addOn.dependsOn,
29
39
  }
30
- const baseUrl = originalUrl.replace(/registry.json$/, '')
31
- return `${baseUrl}${relativeUrl.replace(/^\.\//, '')}`
32
40
  }
33
41
 
34
42
  export async function generateInitialPayload() {
@@ -44,7 +52,7 @@ export async function generateInitialPayload() {
44
52
 
45
53
  const forcedRouterMode = getForcedRouterMode()
46
54
 
47
- function getSerializedOptions() {
55
+ async function getSerializedOptions() {
48
56
  if (applicationMode === 'setup') {
49
57
  const projectOptions = getProjectOptions()
50
58
  return {
@@ -55,31 +63,23 @@ export async function generateInitialPayload() {
55
63
  typescript: projectOptions.typescript || true,
56
64
  tailwind: projectOptions.tailwind || true,
57
65
  git: projectOptions.git || true,
66
+ targetDir:
67
+ projectOptions.targetDir ||
68
+ resolve(projectPath, projectOptions.projectName),
58
69
  } as SerializedOptions
59
70
  } else {
60
- const persistedOptions = JSON.parse(
61
- readFileSync(resolve(projectPath, '.cta.json')),
62
- )
71
+ const persistedOptions = await readConfigFile(projectPath)
72
+ if (!persistedOptions) {
73
+ throw new Error('No config file found')
74
+ }
63
75
  return createSerializedOptionsFromPersisted(persistedOptions)
64
76
  }
65
77
  }
66
78
 
67
- const registryUrl = getRegistry()
68
- let registry: Registry | undefined
69
- if (registryUrl) {
70
- registry = (await fetch(registryUrl).then((res) => res.json())) as Registry
71
- for (const addOn of registry['add-ons']) {
72
- addOn.url = absolutizeUrl(registryUrl, addOn.url)
73
- }
74
- for (const starter of registry.starters) {
75
- starter.url = absolutizeUrl(registryUrl, starter.url)
76
- if (starter.banner) {
77
- starter.banner = absolutizeUrl(registryUrl, starter.banner)
78
- }
79
- }
80
- }
79
+ const rawRegistry = await getRawRegistry(getRegistryURL())
80
+ const registryAddOns = await getRegistryAddOns(getRegistryURL())
81
81
 
82
- const serializedOptions = getSerializedOptions()
82
+ const serializedOptions = await getSerializedOptions()
83
83
 
84
84
  const output = await createAppWrapper(serializedOptions, {
85
85
  dryRun: true,
@@ -87,39 +87,46 @@ export async function generateInitialPayload() {
87
87
 
88
88
  const framework = await getFrameworkById(serializedOptions.framework)
89
89
 
90
- const codeRouter = getAllAddOns(framework!, 'code-router').map((addOn) => ({
91
- id: addOn.id,
92
- name: addOn.name,
93
- description: addOn.description,
94
- type: addOn.type,
95
- smallLogo: addOn.smallLogo,
96
- logo: addOn.logo,
97
- link: addOn.link,
98
- dependsOn: addOn.dependsOn,
99
- }))
90
+ const codeRouterAddOns = getAllAddOns(framework!, 'code-router').map(
91
+ convertAddOnToAddOnInfo,
92
+ )
93
+
94
+ const fileRouterAddOns = getAllAddOns(framework!, 'file-router').map(
95
+ convertAddOnToAddOnInfo,
96
+ )
97
+
98
+ for (const addOnInfo of registryAddOns || []) {
99
+ const addOnFramework = rawRegistry?.['add-ons'].find(
100
+ (addOn) => addOn.url === addOnInfo.id,
101
+ )
102
+ if (addOnFramework?.framework === serializedOptions.framework) {
103
+ if (addOnInfo.modes.includes('code-router')) {
104
+ codeRouterAddOns.push(convertAddOnToAddOnInfo(addOnInfo))
105
+ }
106
+ if (addOnInfo.modes.includes('file-router')) {
107
+ fileRouterAddOns.push(convertAddOnToAddOnInfo(addOnInfo))
108
+ }
109
+ }
110
+ }
100
111
 
101
- const fileRouter = getAllAddOns(framework!, 'file-router').map((addOn) => ({
102
- id: addOn.id,
103
- name: addOn.name,
104
- description: addOn.description,
105
- type: addOn.type,
106
- smallLogo: addOn.smallLogo,
107
- logo: addOn.logo,
108
- link: addOn.link,
109
- dependsOn: addOn.dependsOn,
110
- }))
112
+ const serializedRegistry = {
113
+ ['add-ons']: [],
114
+ starters: (rawRegistry?.starters || []).filter(
115
+ (starter) => starter.framework === serializedOptions.framework,
116
+ ),
117
+ }
111
118
 
112
119
  return {
113
120
  applicationMode,
114
121
  localFiles,
115
122
  addOns: {
116
- 'code-router': codeRouter,
117
- 'file-router': fileRouter,
123
+ 'code-router': codeRouterAddOns,
124
+ 'file-router': fileRouterAddOns,
118
125
  },
119
126
  options: serializedOptions,
120
127
  output,
121
128
  forcedRouterMode,
122
129
  forcedAddOns: getForcedAddOns(),
123
- registry,
130
+ registry: serializedRegistry,
124
131
  }
125
132
  }
@@ -0,0 +1,37 @@
1
+ import type { Mode, SerializedOptions } from '@tanstack/cta-engine'
2
+
3
+ export type ServerEnvironment = {
4
+ projectPath: string
5
+ mode: 'add' | 'setup'
6
+ options?: SerializedOptions
7
+ addOns?: Array<string>
8
+ forcedRouterMode?: Mode
9
+ forcedAddOns?: Array<string>
10
+ registry?: string
11
+ }
12
+
13
+ const serverEnvironment: ServerEnvironment = {
14
+ projectPath: '',
15
+ mode: 'add',
16
+ options: {} as SerializedOptions,
17
+ addOns: [],
18
+ forcedRouterMode: undefined,
19
+ forcedAddOns: undefined,
20
+ registry: undefined,
21
+ }
22
+
23
+ export function setServerEnvironment(options: Partial<ServerEnvironment>) {
24
+ Object.assign(serverEnvironment, options)
25
+ }
26
+
27
+ export const getProjectPath = () => serverEnvironment.projectPath
28
+
29
+ export const getApplicationMode = () => serverEnvironment.mode
30
+
31
+ export const getProjectOptions = () => serverEnvironment.options!
32
+
33
+ export const getForcedRouterMode = () => serverEnvironment.forcedRouterMode
34
+
35
+ export const getForcedAddOns = () => serverEnvironment.forcedAddOns || []
36
+
37
+ export const getRegistry = () => serverEnvironment.registry