@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
package/lib/index.ts CHANGED
@@ -1,43 +1,159 @@
1
1
  import { dirname, resolve } from 'node:path'
2
2
  import { fileURLToPath } from 'node:url'
3
+ import express from 'express'
4
+ import cors from 'cors'
5
+ import chalk from 'chalk'
3
6
 
4
- import type { Mode, SerializedOptions } from '@tanstack/cta-engine'
5
-
6
- export function launchUI({
7
- mode,
8
- addOns,
9
- options,
10
- forcedMode,
11
- forcedAddOns,
12
- }: {
13
- mode: 'add' | 'setup'
14
- addOns?: Array<string>
15
- options?: SerializedOptions
16
- forcedMode?: Mode
17
- forcedAddOns?: Array<string>
18
- }) {
19
- const projectPath = process.cwd()
20
-
21
- delete process.env.NODE_ENV
22
-
23
- process.env.CTA_ADD_ONS = addOns?.join(',') || ''
24
- process.env.CTA_PROJECT_PATH = projectPath
25
- process.env.CTA_OPTIONS = options ? JSON.stringify(options) : ''
26
- process.env.CTA_MODE = mode
27
- if (forcedMode) {
28
- process.env.CTA_FORCED_ROUTER_MODE = forcedMode
29
- }
30
- if (forcedAddOns) {
31
- process.env.CTA_FORCED_ADD_ONS = forcedAddOns.join(',')
7
+ import {
8
+ AddOnCompiledSchema,
9
+ StarterCompiledSchema,
10
+ } from '@tanstack/cta-engine'
11
+
12
+ import { addToAppWrapper } from './engine-handling/add-to-app-wrapper.js'
13
+ import { createAppWrapper } from './engine-handling/create-app-wrapper.js'
14
+ import { generateInitialPayload } from './engine-handling/generate-initial-payload.js'
15
+ import { setServerEnvironment } from './engine-handling/server-environment.js'
16
+
17
+ import type { ServerEnvironment } from './engine-handling/server-environment.js'
18
+ import type { Environment } from '@tanstack/cta-engine'
19
+
20
+ export function launchUI(
21
+ options: Partial<ServerEnvironment> & {
22
+ port?: number
23
+ environmentFactory?: () => Environment
24
+ },
25
+ ) {
26
+ const { port: requestedPort, ...rest } = options
27
+ setServerEnvironment(rest)
28
+
29
+ const app = express()
30
+
31
+ app.use(cors())
32
+ app.use(express.json())
33
+ app.use(express.urlencoded({ extended: true }))
34
+
35
+ const launchUI = !process.env.CTA_DISABLE_UI
36
+ if (launchUI) {
37
+ const packagePath = resolve(dirname(fileURLToPath(import.meta.url)), '..')
38
+ app.use(express.static(resolve(packagePath, 'dist')))
32
39
  }
33
40
 
34
- const developerPath = resolve(dirname(fileURLToPath(import.meta.url)), '..')
35
- const configPath = resolve(developerPath, './app.config.js')
41
+ app.post('/api/add-to-app', async (req, res) => {
42
+ await addToAppWrapper(req.body.addOns, {
43
+ response: res,
44
+ environmentFactory: options.environmentFactory,
45
+ })
46
+ })
36
47
 
37
- process.chdir(developerPath)
48
+ app.post('/api/create-app', async (req, res) => {
49
+ await createAppWrapper(req.body.options, {
50
+ response: res,
51
+ environmentFactory: options.environmentFactory,
52
+ })
53
+ })
54
+
55
+ app.post('/api/dry-run-add-to-app', async (req, res) => {
56
+ res.send(
57
+ await addToAppWrapper(req.body.addOns, {
58
+ dryRun: true,
59
+ environmentFactory: options.environmentFactory,
60
+ }),
61
+ )
62
+ })
63
+
64
+ app.post('/api/dry-run-create-app', async (req, res) => {
65
+ res.send(
66
+ await createAppWrapper(req.body.options, {
67
+ dryRun: true,
68
+ environmentFactory: options.environmentFactory,
69
+ }),
70
+ )
71
+ })
72
+
73
+ app.get('/api/initial-payload', async (_req, res) => {
74
+ res.send(await generateInitialPayload())
75
+ })
76
+
77
+ app.get('/api/load-remote-add-on', async (req, res) => {
78
+ const { url } = req.query
79
+ if (!url) {
80
+ res.status(400).send('URL is required')
81
+ return
82
+ }
83
+ try {
84
+ const response = await fetch(url as string)
85
+ const data = await response.json()
86
+ const parsed = AddOnCompiledSchema.safeParse(data)
87
+ if (!parsed.success) {
88
+ res.status(400).json({ error: 'Invalid add-on data' })
89
+ } else {
90
+ res.json({
91
+ id: url,
92
+ name: parsed.data.name,
93
+ description: parsed.data.description,
94
+ version: parsed.data.version,
95
+ author: parsed.data.author,
96
+ license: parsed.data.license,
97
+ link: parsed.data.link,
98
+ smallLogo: parsed.data.smallLogo,
99
+ logo: parsed.data.logo,
100
+ type: parsed.data.type,
101
+ modes: parsed.data.modes,
102
+ })
103
+ }
104
+ } catch {
105
+ res.status(500).send('Failed to load add-on')
106
+ }
107
+ })
108
+
109
+ app.get('/api/load-starter', async (req, res) => {
110
+ const { url } = req.query
111
+ if (!url) {
112
+ res.status(400).send('URL is required')
113
+ return
114
+ }
115
+ try {
116
+ const response = await fetch(url as string)
117
+ const data = await response.json()
118
+ const parsed = StarterCompiledSchema.safeParse(data)
119
+ if (!parsed.success) {
120
+ res.status(400).json({ error: 'Invalid starter data' })
121
+ } else {
122
+ res.json({
123
+ url,
124
+ id: parsed.data.id,
125
+ name: parsed.data.name,
126
+ description: parsed.data.description,
127
+ version: parsed.data.version,
128
+ author: parsed.data.author,
129
+ license: parsed.data.license,
130
+ dependsOn: parsed.data.dependsOn,
131
+ mode: parsed.data.mode,
132
+ typescript: parsed.data.typescript,
133
+ tailwind: parsed.data.tailwind,
134
+ banner: parsed.data.banner
135
+ ? (url as string).replace('starter.json', parsed.data.banner)
136
+ : undefined,
137
+ })
138
+ }
139
+ } catch {
140
+ res.status(500).send('Failed to load starter')
141
+ }
142
+ })
143
+
144
+ app.post('/api/shutdown', (_req, res) => {
145
+ setTimeout(() => {
146
+ process.exit(0)
147
+ }, 50)
148
+ res.send({ shutdown: true })
149
+ })
38
150
 
39
- import(configPath).then(async (config) => {
40
- const out = await config.default
41
- await out.dev()
151
+ const port = requestedPort || process.env.PORT || 8080
152
+ app.listen(port, () => {
153
+ console.log(
154
+ `🔥 ${chalk.blueBright(`Create TanStack ${launchUI ? 'App' : 'API'}`)} is running on ${chalk.underline(
155
+ `http://localhost:${port}`,
156
+ )}`,
157
+ )
42
158
  })
43
159
  }
package/lib/types.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ export type DryRunOutput = {
2
+ files: Record<string, string>
3
+ commands: Array<{
4
+ command: string
5
+ args: Array<string>
6
+ }>
7
+ deletedFiles: Array<string>
8
+ }
9
+
10
+ export type AddOnInfo = {
11
+ id: string
12
+ name: string
13
+ description: string
14
+ type: 'add-on' | 'example' | 'starter' | 'toolchain'
15
+ modes: Array<'code-router' | 'file-router'>
16
+ smallLogo?: string
17
+ logo?: string
18
+ link: string
19
+ dependsOn?: Array<string>
20
+ }
@@ -0,0 +1,14 @@
1
+ import type { Environment } from '@tanstack/cta-engine';
2
+ import type { Response } from 'express';
3
+ export declare function addToAppWrapper(addOns: Array<string>, opts: {
4
+ dryRun?: boolean;
5
+ response?: Response;
6
+ environmentFactory?: () => Environment;
7
+ }): Promise<{
8
+ files: Record<string, string>;
9
+ deletedFiles: Array<string>;
10
+ commands: Array<{
11
+ command: string;
12
+ args: Array<string>;
13
+ }>;
14
+ } | undefined>;
@@ -0,0 +1,78 @@
1
+ import { resolve } from 'node:path';
2
+ import { CONFIG_FILE, addToApp, createAppOptionsFromPersisted, createDefaultEnvironment, createMemoryEnvironment, createSerializedOptionsFromPersisted, readConfigFile, recursivelyGatherFiles, writeConfigFileToEnvironment, } from '@tanstack/cta-engine';
3
+ import { cleanUpFileArray, cleanUpFiles } from './file-helpers.js';
4
+ import { getProjectPath } from './server-environment.js';
5
+ import { createAppWrapper } from './create-app-wrapper.js';
6
+ export async function addToAppWrapper(addOns, opts) {
7
+ const projectPath = getProjectPath();
8
+ const persistedOptions = await readConfigFile(projectPath);
9
+ if (!persistedOptions) {
10
+ throw new Error('No config file found');
11
+ }
12
+ const options = await createAppOptionsFromPersisted(persistedOptions);
13
+ options.targetDir = projectPath;
14
+ const newAddons = [];
15
+ for (const addOn of addOns) {
16
+ if (!options.chosenAddOns.some((a) => a.id === addOn)) {
17
+ newAddons.push(addOn);
18
+ }
19
+ }
20
+ if (newAddons.length === 0) {
21
+ const serializedOptions = createSerializedOptionsFromPersisted(persistedOptions);
22
+ return await createAppWrapper(serializedOptions, opts);
23
+ }
24
+ async function createEnvironment() {
25
+ if (opts.dryRun) {
26
+ const { environment, output } = createMemoryEnvironment(projectPath);
27
+ const localFiles = await cleanUpFiles(await recursivelyGatherFiles(projectPath, false));
28
+ for (const file of Object.keys(localFiles)) {
29
+ environment.writeFile(resolve(projectPath, file), localFiles[file]);
30
+ }
31
+ return { environment, output };
32
+ }
33
+ return {
34
+ environment: opts.environmentFactory?.() ?? createDefaultEnvironment(),
35
+ output: { files: {}, deletedFiles: [], commands: [] },
36
+ };
37
+ }
38
+ const { environment, output } = await createEnvironment();
39
+ if (opts.response) {
40
+ opts.response.writeHead(200, {
41
+ 'Content-Type': 'text/plain',
42
+ 'Transfer-Encoding': 'chunked',
43
+ });
44
+ environment.startStep = ({ id, type, message, }) => {
45
+ opts.response.write(JSON.stringify({
46
+ msgType: 'start',
47
+ id,
48
+ type,
49
+ message,
50
+ }) + '\n');
51
+ };
52
+ environment.finishStep = (id, message) => {
53
+ opts.response.write(JSON.stringify({
54
+ msgType: 'finish',
55
+ id,
56
+ message,
57
+ }) + '\n');
58
+ };
59
+ environment.startRun();
60
+ await addToApp(environment, newAddons, projectPath, {
61
+ forced: true,
62
+ });
63
+ environment.finishRun();
64
+ opts.response.end();
65
+ }
66
+ else {
67
+ environment.startRun();
68
+ environment.writeFile(resolve(projectPath, CONFIG_FILE), JSON.stringify(persistedOptions, null, 2));
69
+ await addToApp(environment, newAddons, projectPath, {
70
+ forced: true,
71
+ });
72
+ writeConfigFileToEnvironment(environment, options);
73
+ environment.finishRun();
74
+ output.files = cleanUpFiles(output.files, projectPath);
75
+ output.deletedFiles = cleanUpFileArray(output.deletedFiles, projectPath);
76
+ return output;
77
+ }
78
+ }
@@ -0,0 +1,14 @@
1
+ import type { Environment, SerializedOptions } from '@tanstack/cta-engine';
2
+ import type { Response } from 'express';
3
+ export declare function createAppWrapper(projectOptions: SerializedOptions, opts: {
4
+ dryRun?: boolean;
5
+ response?: Response;
6
+ environmentFactory?: () => Environment;
7
+ }): Promise<{
8
+ files: Record<string, string>;
9
+ deletedFiles: Array<string>;
10
+ commands: Array<{
11
+ command: string;
12
+ args: Array<string>;
13
+ }>;
14
+ } | undefined>;
@@ -0,0 +1,70 @@
1
+ import { resolve } from 'node:path';
2
+ import { createApp, createDefaultEnvironment, createMemoryEnvironment, finalizeAddOns, getFrameworkById, loadStarter, } from '@tanstack/cta-engine';
3
+ import { registerFrameworks } from './framework-registration.js';
4
+ import { cleanUpFileArray, cleanUpFiles } from './file-helpers.js';
5
+ import { getApplicationMode, getProjectPath } from './server-environment.js';
6
+ export async function createAppWrapper(projectOptions, opts) {
7
+ registerFrameworks();
8
+ const framework = getFrameworkById(projectOptions.framework);
9
+ let starter;
10
+ const addOns = [...projectOptions.chosenAddOns];
11
+ if (projectOptions.starter) {
12
+ starter = await loadStarter(projectOptions.starter);
13
+ if (starter) {
14
+ for (const addOn of starter.dependsOn ?? []) {
15
+ addOns.push(addOn);
16
+ }
17
+ }
18
+ }
19
+ const chosenAddOns = await finalizeAddOns(framework, projectOptions.mode, addOns);
20
+ const projectPath = getProjectPath();
21
+ const targetDir = getApplicationMode() === 'add'
22
+ ? projectOptions.targetDir
23
+ : resolve(projectPath, projectOptions.projectName);
24
+ const options = {
25
+ ...projectOptions,
26
+ targetDir,
27
+ starter,
28
+ framework,
29
+ chosenAddOns,
30
+ };
31
+ function createEnvironment() {
32
+ if (opts.dryRun) {
33
+ return createMemoryEnvironment(targetDir);
34
+ }
35
+ return {
36
+ environment: opts.environmentFactory?.() ?? createDefaultEnvironment(),
37
+ output: { files: {}, deletedFiles: [], commands: [] },
38
+ };
39
+ }
40
+ const { environment, output } = createEnvironment();
41
+ if (opts.response) {
42
+ opts.response.writeHead(200, {
43
+ 'Content-Type': 'text/plain',
44
+ 'Transfer-Encoding': 'chunked',
45
+ });
46
+ environment.startStep = ({ id, type, message }) => {
47
+ opts.response.write(JSON.stringify({
48
+ msgType: 'start',
49
+ id,
50
+ type,
51
+ message,
52
+ }) + '\n');
53
+ };
54
+ environment.finishStep = (id, message) => {
55
+ opts.response.write(JSON.stringify({
56
+ msgType: 'finish',
57
+ id,
58
+ message,
59
+ }) + '\n');
60
+ };
61
+ await createApp(environment, options);
62
+ opts.response.end();
63
+ }
64
+ else {
65
+ await createApp(environment, options);
66
+ output.files = cleanUpFiles(output.files, targetDir);
67
+ output.deletedFiles = cleanUpFileArray(output.deletedFiles, targetDir);
68
+ return output;
69
+ }
70
+ }
@@ -0,0 +1,2 @@
1
+ export declare function cleanUpFiles(files: Record<string, string>, targetDir?: string): Record<string, string>;
2
+ export declare function cleanUpFileArray(files: Array<string>, targetDir?: string): string[];
@@ -0,0 +1,21 @@
1
+ import { basename } from 'node:path';
2
+ import { CONFIG_FILE } from '@tanstack/cta-engine';
3
+ export function cleanUpFiles(files, targetDir) {
4
+ return Object.keys(files).reduce((acc, file) => {
5
+ const content = files[file].startsWith('base64::')
6
+ ? '<binary file>'
7
+ : files[file];
8
+ if (basename(file) !== CONFIG_FILE) {
9
+ acc[targetDir ? file.replace(targetDir, '.') : file] = content;
10
+ }
11
+ return acc;
12
+ }, {});
13
+ }
14
+ export function cleanUpFileArray(files, targetDir) {
15
+ return files.reduce((acc, file) => {
16
+ if (basename(file) !== CONFIG_FILE) {
17
+ acc.push(targetDir ? file.replace(targetDir, '.') : file);
18
+ }
19
+ return acc;
20
+ }, []);
21
+ }
@@ -0,0 +1 @@
1
+ export declare function registerFrameworks(): void;
@@ -0,0 +1,10 @@
1
+ import { register as registerReactCra } from '@tanstack/cta-framework-react-cra';
2
+ import { register as registerSolid } from '@tanstack/cta-framework-solid';
3
+ let registered = false;
4
+ export function registerFrameworks() {
5
+ if (registered)
6
+ return;
7
+ registerReactCra();
8
+ registerSolid();
9
+ registered = true;
10
+ }
@@ -0,0 +1,32 @@
1
+ import type { SerializedOptions } from '@tanstack/cta-engine';
2
+ import type { AddOnInfo } from '../types.js';
3
+ export declare function generateInitialPayload(): Promise<{
4
+ applicationMode: "add" | "setup";
5
+ localFiles: Record<string, string>;
6
+ addOns: {
7
+ 'code-router': AddOnInfo[];
8
+ 'file-router': AddOnInfo[];
9
+ };
10
+ options: SerializedOptions;
11
+ output: {
12
+ files: Record<string, string>;
13
+ deletedFiles: Array<string>;
14
+ commands: Array<{
15
+ command: string;
16
+ args: Array<string>;
17
+ }>;
18
+ } | undefined;
19
+ forcedRouterMode: import("@tanstack/cta-engine").Mode | undefined;
20
+ forcedAddOns: string[];
21
+ registry: {
22
+ "add-ons": never[];
23
+ starters: {
24
+ name: string;
25
+ description: string;
26
+ url: string;
27
+ banner?: string;
28
+ mode: Mode;
29
+ framework: string;
30
+ }[];
31
+ };
32
+ }>;
@@ -0,0 +1,88 @@
1
+ import { basename, resolve } from 'node:path';
2
+ import { createSerializedOptionsFromPersisted, getAllAddOns, getFrameworkById, getRawRegistry, getRegistryAddOns, readConfigFile, recursivelyGatherFiles, } from '@tanstack/cta-engine';
3
+ import { cleanUpFiles } from './file-helpers.js';
4
+ import { createAppWrapper } from './create-app-wrapper.js';
5
+ import { registerFrameworks } from './framework-registration.js';
6
+ import { getApplicationMode, getForcedAddOns, getForcedRouterMode, getProjectOptions, getProjectPath, getRegistry as getRegistryURL, } from './server-environment.js';
7
+ function convertAddOnToAddOnInfo(addOn) {
8
+ return {
9
+ id: addOn.id,
10
+ name: addOn.name,
11
+ description: addOn.description,
12
+ modes: addOn.modes,
13
+ type: addOn.type,
14
+ smallLogo: addOn.smallLogo,
15
+ logo: addOn.logo,
16
+ link: addOn.link,
17
+ dependsOn: addOn.dependsOn,
18
+ };
19
+ }
20
+ export async function generateInitialPayload() {
21
+ registerFrameworks();
22
+ const projectPath = getProjectPath();
23
+ const applicationMode = getApplicationMode();
24
+ const localFiles = applicationMode === 'add'
25
+ ? await cleanUpFiles(await recursivelyGatherFiles(projectPath, false))
26
+ : {};
27
+ const forcedRouterMode = getForcedRouterMode();
28
+ async function getSerializedOptions() {
29
+ if (applicationMode === 'setup') {
30
+ const projectOptions = getProjectOptions();
31
+ return {
32
+ ...projectOptions,
33
+ framework: projectOptions.framework || 'react-cra',
34
+ projectName: projectOptions.projectName || basename(projectPath),
35
+ mode: forcedRouterMode || projectOptions.mode,
36
+ typescript: projectOptions.typescript || true,
37
+ tailwind: projectOptions.tailwind || true,
38
+ git: projectOptions.git || true,
39
+ targetDir: projectOptions.targetDir ||
40
+ resolve(projectPath, projectOptions.projectName),
41
+ };
42
+ }
43
+ else {
44
+ const persistedOptions = await readConfigFile(projectPath);
45
+ if (!persistedOptions) {
46
+ throw new Error('No config file found');
47
+ }
48
+ return createSerializedOptionsFromPersisted(persistedOptions);
49
+ }
50
+ }
51
+ const rawRegistry = await getRawRegistry(getRegistryURL());
52
+ const registryAddOns = await getRegistryAddOns(getRegistryURL());
53
+ const serializedOptions = await getSerializedOptions();
54
+ const output = await createAppWrapper(serializedOptions, {
55
+ dryRun: true,
56
+ });
57
+ const framework = await getFrameworkById(serializedOptions.framework);
58
+ const codeRouterAddOns = getAllAddOns(framework, 'code-router').map(convertAddOnToAddOnInfo);
59
+ const fileRouterAddOns = getAllAddOns(framework, 'file-router').map(convertAddOnToAddOnInfo);
60
+ for (const addOnInfo of registryAddOns || []) {
61
+ const addOnFramework = rawRegistry?.['add-ons'].find((addOn) => addOn.url === addOnInfo.id);
62
+ if (addOnFramework?.framework === serializedOptions.framework) {
63
+ if (addOnInfo.modes.includes('code-router')) {
64
+ codeRouterAddOns.push(convertAddOnToAddOnInfo(addOnInfo));
65
+ }
66
+ if (addOnInfo.modes.includes('file-router')) {
67
+ fileRouterAddOns.push(convertAddOnToAddOnInfo(addOnInfo));
68
+ }
69
+ }
70
+ }
71
+ const serializedRegistry = {
72
+ ['add-ons']: [],
73
+ starters: (rawRegistry?.starters || []).filter((starter) => starter.framework === serializedOptions.framework),
74
+ };
75
+ return {
76
+ applicationMode,
77
+ localFiles,
78
+ addOns: {
79
+ 'code-router': codeRouterAddOns,
80
+ 'file-router': fileRouterAddOns,
81
+ },
82
+ options: serializedOptions,
83
+ output,
84
+ forcedRouterMode,
85
+ forcedAddOns: getForcedAddOns(),
86
+ registry: serializedRegistry,
87
+ };
88
+ }
@@ -0,0 +1,17 @@
1
+ import type { Mode, SerializedOptions } from '@tanstack/cta-engine';
2
+ export type ServerEnvironment = {
3
+ projectPath: string;
4
+ mode: 'add' | 'setup';
5
+ options?: SerializedOptions;
6
+ addOns?: Array<string>;
7
+ forcedRouterMode?: Mode;
8
+ forcedAddOns?: Array<string>;
9
+ registry?: string;
10
+ };
11
+ export declare function setServerEnvironment(options: Partial<ServerEnvironment>): void;
12
+ export declare const getProjectPath: () => string;
13
+ export declare const getApplicationMode: () => "add" | "setup";
14
+ export declare const getProjectOptions: () => SerializedOptions;
15
+ export declare const getForcedRouterMode: () => Mode | undefined;
16
+ export declare const getForcedAddOns: () => string[];
17
+ export declare const getRegistry: () => string | undefined;
@@ -0,0 +1,18 @@
1
+ const serverEnvironment = {
2
+ projectPath: '',
3
+ mode: 'add',
4
+ options: {},
5
+ addOns: [],
6
+ forcedRouterMode: undefined,
7
+ forcedAddOns: undefined,
8
+ registry: undefined,
9
+ };
10
+ export function setServerEnvironment(options) {
11
+ Object.assign(serverEnvironment, options);
12
+ }
13
+ export const getProjectPath = () => serverEnvironment.projectPath;
14
+ export const getApplicationMode = () => serverEnvironment.mode;
15
+ export const getProjectOptions = () => serverEnvironment.options;
16
+ export const getForcedRouterMode = () => serverEnvironment.forcedRouterMode;
17
+ export const getForcedAddOns = () => serverEnvironment.forcedAddOns || [];
18
+ export const getRegistry = () => serverEnvironment.registry;
@@ -1,8 +1,6 @@
1
- import type { Mode, SerializedOptions } from '@tanstack/cta-engine';
2
- export declare function launchUI({ mode, addOns, options, forcedMode, forcedAddOns, }: {
3
- mode: 'add' | 'setup';
4
- addOns?: Array<string>;
5
- options?: SerializedOptions;
6
- forcedMode?: Mode;
7
- forcedAddOns?: Array<string>;
1
+ import type { ServerEnvironment } from './engine-handling/server-environment.js';
2
+ import type { Environment } from '@tanstack/cta-engine';
3
+ export declare function launchUI(options: Partial<ServerEnvironment> & {
4
+ port?: number;
5
+ environmentFactory?: () => Environment;
8
6
  }): void;