@tanstack/cta-engine 0.11.3 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -77,13 +77,13 @@ export function cli({ name, appName, forcedMode, forcedAddOns, }) {
77
77
  program.action(async (projectName, options) => {
78
78
  if (options.listAddOns) {
79
79
  await listAddOns(options, {
80
- forcedMode,
80
+ forcedMode: forcedMode,
81
81
  forcedAddOns,
82
82
  });
83
83
  }
84
84
  else if (options.mcp || options.mcpSse) {
85
85
  await runServer(!!options.mcpSse, {
86
- forcedMode,
86
+ forcedMode: forcedMode,
87
87
  forcedAddOns,
88
88
  appName,
89
89
  });
@@ -97,14 +97,14 @@ export function cli({ name, appName, forcedMode, forcedAddOns, }) {
97
97
  if (forcedMode) {
98
98
  cliOptions.template = forcedMode;
99
99
  }
100
- let finalOptions = await normalizeOptions(cliOptions, forcedAddOns);
100
+ let finalOptions = await normalizeOptions(cliOptions, forcedMode, forcedAddOns);
101
101
  if (finalOptions) {
102
102
  intro(`Creating a new ${appName} app in ${projectName}...`);
103
103
  }
104
104
  else {
105
105
  intro(`Let's configure your ${appName} application`);
106
106
  finalOptions = await promptForOptions(cliOptions, {
107
- forcedMode,
107
+ forcedMode: forcedMode,
108
108
  forcedAddOns,
109
109
  });
110
110
  }
@@ -492,6 +492,6 @@ Use the following commands to start your app:
492
492
  % cd ${options.projectName}
493
493
  % ${startCommand}
494
494
 
495
- Please read the README.md for more information on testing, styling, adding routes, react-query, etc.${errorStatement}`);
495
+ Please check the README.md for more information on testing, styling, adding routes, react-query, etc.${errorStatement}`);
496
496
  }
497
497
  }
package/dist/options.js CHANGED
@@ -4,7 +4,7 @@ import { DEFAULT_TOOLCHAIN, SUPPORTED_TOOLCHAINS } from './toolchain.js';
4
4
  import { CODE_ROUTER, DEFAULT_FRAMEWORK, FILE_ROUTER } from './constants.js';
5
5
  import { finalizeAddOns, getAllAddOns, loadRemoteAddOn } from './add-ons.js';
6
6
  // If all CLI options are provided, use them directly
7
- export async function normalizeOptions(cliOptions, forcedAddOns) {
7
+ export async function normalizeOptions(cliOptions, forcedMode, forcedAddOns) {
8
8
  // in some cases, if you use windows/powershell, the argument for addons
9
9
  // if sepparated by comma is not really passed as an array, but as a string
10
10
  // with spaces, We need to normalize this edge case.
@@ -46,7 +46,9 @@ export async function normalizeOptions(cliOptions, forcedAddOns) {
46
46
  ...cliOptions.addOns,
47
47
  ]));
48
48
  }
49
- chosenAddOns = await finalizeAddOns(cliOptions.framework || DEFAULT_FRAMEWORK, cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER, finalAddOns);
49
+ chosenAddOns = await finalizeAddOns(cliOptions.framework || DEFAULT_FRAMEWORK, forcedMode || cliOptions.template === 'file-router'
50
+ ? FILE_ROUTER
51
+ : CODE_ROUTER, finalAddOns);
50
52
  tailwind = true;
51
53
  typescript = true;
52
54
  }
@@ -1,6 +1,7 @@
1
+ import type { Mode } from './types.js';
1
2
  export declare function cli({ name, appName, forcedMode, forcedAddOns, }: {
2
3
  name: string;
3
4
  appName: string;
4
- forcedMode?: 'typescript' | 'javascript' | 'file-router';
5
+ forcedMode?: Mode;
5
6
  forcedAddOns?: Array<string>;
6
7
  }): void;
@@ -1,6 +1,6 @@
1
- import type { CliOptions, Options } from './types.js';
2
- export declare function normalizeOptions(cliOptions: CliOptions, forcedAddOns?: Array<string>): Promise<Options | undefined>;
1
+ import type { CliOptions, Mode, Options, TemplateOptions } from './types.js';
2
+ export declare function normalizeOptions(cliOptions: CliOptions, forcedMode?: Mode, forcedAddOns?: Array<string>): Promise<Options | undefined>;
3
3
  export declare function promptForOptions(cliOptions: CliOptions, { forcedAddOns, forcedMode, }: {
4
4
  forcedAddOns?: Array<string>;
5
- forcedMode?: 'typescript' | 'javascript' | 'file-router';
5
+ forcedMode?: TemplateOptions;
6
6
  }): Promise<Required<Options>>;
@@ -3,6 +3,7 @@ import type { PackageManager } from './package-manager.js';
3
3
  import type { ToolChain } from './toolchain.js';
4
4
  export type Framework = 'solid' | 'react';
5
5
  export type TemplateOptions = 'typescript' | 'javascript' | 'file-router';
6
+ export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER;
6
7
  export interface Options {
7
8
  framework: Framework;
8
9
  projectName: string;
@@ -10,7 +11,7 @@ export interface Options {
10
11
  tailwind: boolean;
11
12
  packageManager: PackageManager;
12
13
  toolchain: ToolChain;
13
- mode: typeof CODE_ROUTER | typeof FILE_ROUTER;
14
+ mode: Mode;
14
15
  addOns: boolean;
15
16
  chosenAddOns: Array<AddOn>;
16
17
  git: boolean;
@@ -100,7 +101,7 @@ export type Overlay = AddOn & {
100
101
  author: string;
101
102
  link: string;
102
103
  license: string;
103
- mode: typeof CODE_ROUTER | typeof FILE_ROUTER;
104
+ mode: Mode;
104
105
  framework: Framework;
105
106
  typescript: boolean;
106
107
  tailwind: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-engine",
3
- "version": "0.11.3",
3
+ "version": "0.12.0",
4
4
  "description": "Tanstack Application Builder Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/cli.ts CHANGED
@@ -16,7 +16,7 @@ import { createDefaultEnvironment } from './environment.js'
16
16
 
17
17
  import type { PackageManager } from './package-manager.js'
18
18
  import type { ToolChain } from './toolchain.js'
19
- import type { CliOptions, Framework } from './types.js'
19
+ import type { CliOptions, Framework, Mode, TemplateOptions } from './types.js'
20
20
 
21
21
  export function cli({
22
22
  name,
@@ -26,7 +26,7 @@ export function cli({
26
26
  }: {
27
27
  name: string
28
28
  appName: string
29
- forcedMode?: 'typescript' | 'javascript' | 'file-router'
29
+ forcedMode?: Mode
30
30
  forcedAddOns?: Array<string>
31
31
  }) {
32
32
  const program = new Command()
@@ -143,12 +143,12 @@ export function cli({
143
143
  program.action(async (projectName: string, options: CliOptions) => {
144
144
  if (options.listAddOns) {
145
145
  await listAddOns(options, {
146
- forcedMode,
146
+ forcedMode: forcedMode as TemplateOptions,
147
147
  forcedAddOns,
148
148
  })
149
149
  } else if (options.mcp || options.mcpSse) {
150
150
  await runServer(!!options.mcpSse, {
151
- forcedMode,
151
+ forcedMode: forcedMode as TemplateOptions,
152
152
  forcedAddOns,
153
153
  appName,
154
154
  })
@@ -160,16 +160,20 @@ export function cli({
160
160
  } as CliOptions
161
161
 
162
162
  if (forcedMode) {
163
- cliOptions.template = forcedMode
163
+ cliOptions.template = forcedMode as TemplateOptions
164
164
  }
165
165
 
166
- let finalOptions = await normalizeOptions(cliOptions, forcedAddOns)
166
+ let finalOptions = await normalizeOptions(
167
+ cliOptions,
168
+ forcedMode,
169
+ forcedAddOns,
170
+ )
167
171
  if (finalOptions) {
168
172
  intro(`Creating a new ${appName} app in ${projectName}...`)
169
173
  } else {
170
174
  intro(`Let's configure your ${appName} application`)
171
175
  finalOptions = await promptForOptions(cliOptions, {
172
- forcedMode,
176
+ forcedMode: forcedMode as TemplateOptions,
173
177
  forcedAddOns,
174
178
  })
175
179
  }
package/src/create-app.ts CHANGED
@@ -799,6 +799,6 @@ Use the following commands to start your app:
799
799
  % cd ${options.projectName}
800
800
  % ${startCommand}
801
801
 
802
- Please read the README.md for more information on testing, styling, adding routes, react-query, etc.${errorStatement}`)
802
+ Please check the README.md for more information on testing, styling, adding routes, react-query, etc.${errorStatement}`)
803
803
  }
804
804
  }
package/src/options.ts CHANGED
@@ -16,11 +16,20 @@ import { DEFAULT_TOOLCHAIN, SUPPORTED_TOOLCHAINS } from './toolchain.js'
16
16
  import { CODE_ROUTER, DEFAULT_FRAMEWORK, FILE_ROUTER } from './constants.js'
17
17
  import { finalizeAddOns, getAllAddOns, loadRemoteAddOn } from './add-ons.js'
18
18
 
19
- import type { AddOn, CliOptions, Options, Overlay, Variable } from './types.js'
19
+ import type {
20
+ AddOn,
21
+ CliOptions,
22
+ Mode,
23
+ Options,
24
+ Overlay,
25
+ TemplateOptions,
26
+ Variable,
27
+ } from './types.js'
20
28
 
21
29
  // If all CLI options are provided, use them directly
22
30
  export async function normalizeOptions(
23
31
  cliOptions: CliOptions,
32
+ forcedMode?: Mode,
24
33
  forcedAddOns?: Array<string>,
25
34
  ): Promise<Options | undefined> {
26
35
  // in some cases, if you use windows/powershell, the argument for addons
@@ -80,7 +89,9 @@ export async function normalizeOptions(
80
89
  }
81
90
  chosenAddOns = await finalizeAddOns(
82
91
  cliOptions.framework || DEFAULT_FRAMEWORK,
83
- cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER,
92
+ forcedMode || cliOptions.template === 'file-router'
93
+ ? FILE_ROUTER
94
+ : CODE_ROUTER,
84
95
  finalAddOns,
85
96
  )
86
97
  tailwind = true
@@ -154,7 +165,7 @@ export async function promptForOptions(
154
165
  forcedMode,
155
166
  }: {
156
167
  forcedAddOns?: Array<string>
157
- forcedMode?: 'typescript' | 'javascript' | 'file-router'
168
+ forcedMode?: TemplateOptions
158
169
  },
159
170
  ): Promise<Required<Options>> {
160
171
  const options = {} as Required<Options>
package/src/types.ts CHANGED
@@ -6,6 +6,8 @@ export type Framework = 'solid' | 'react'
6
6
 
7
7
  export type TemplateOptions = 'typescript' | 'javascript' | 'file-router'
8
8
 
9
+ export type Mode = typeof CODE_ROUTER | typeof FILE_ROUTER
10
+
9
11
  export interface Options {
10
12
  framework: Framework
11
13
  projectName: string
@@ -13,7 +15,7 @@ export interface Options {
13
15
  tailwind: boolean
14
16
  packageManager: PackageManager
15
17
  toolchain: ToolChain
16
- mode: typeof CODE_ROUTER | typeof FILE_ROUTER
18
+ mode: Mode
17
19
  addOns: boolean
18
20
  chosenAddOns: Array<AddOn>
19
21
  git: boolean
@@ -114,7 +116,7 @@ export type Overlay = AddOn & {
114
116
  author: string
115
117
  link: string
116
118
  license: string
117
- mode: typeof CODE_ROUTER | typeof FILE_ROUTER
119
+ mode: Mode
118
120
  framework: Framework
119
121
  typescript: boolean
120
122
  tailwind: boolean
@@ -1,2 +1,2 @@
1
- # Clerk configuration, get this key from your [Dashboard](https://clerk.com/dashboard).
1
+ # Clerk configuration, get this key from your [Dashboard](dashboard.clerk.com)
2
2
  VITE_CLERK_PUBLISHABLE_KEY=
@@ -1,3 +1,3 @@
1
- # Convex configuration, get this URL from your [Dashboard](https://convex.dev/dashboard).
1
+ # Convex configuration, get this URL from your [Dashboard](dashboard.convex.dev)
2
2
  CONVEX_DEPLOYMENT=
3
- VITE_CONVEX_URL=
3
+ VITE_CONVEX_URL=
@@ -0,0 +1,16 @@
1
+ ## T3Env
2
+
3
+ - You can use T3Env to add type safety to your environment variables.
4
+ - Add Environment variables to the `src/env.mjs` file.
5
+ - Use the environment variables in your code.
6
+
7
+ ### Usage
8
+
9
+ ```ts
10
+ import { env } from "@/env";
11
+
12
+ console.log(env.VITE_APP_TITLE);
13
+ ```
14
+
15
+
16
+
@@ -0,0 +1,39 @@
1
+ import { createEnv } from "@t3-oss/env-core";
2
+ import { z } from "zod";
3
+
4
+ export const env = createEnv({
5
+ server: {
6
+ SERVER_URL: z.string().url().optional(),
7
+ },
8
+
9
+ /**
10
+ * The prefix that client-side variables must have. This is enforced both at
11
+ * a type-level and at runtime.
12
+ */
13
+ clientPrefix: "VITE_",
14
+
15
+ client: {
16
+ VITE_APP_TITLE: z.string().min(1).optional(),
17
+ },
18
+
19
+ /**
20
+ * What object holds the environment variables at runtime. This is usually
21
+ * `process.env` or `import.meta.env`.
22
+ */
23
+ runtimeEnv: import.meta.env,
24
+
25
+ /**
26
+ * By default, this library will feed the environment variables directly to
27
+ * the Zod validator.
28
+ *
29
+ * This means that if you have an empty string for a value that is supposed
30
+ * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
31
+ * it as a type mismatch violation. Additionally, if you have an empty string
32
+ * for a value that is supposed to be a string with a default value (e.g.
33
+ * `DOMAIN=` in an ".env" file), the default value will never be applied.
34
+ *
35
+ * In order to solve these issues, we recommend that all new projects
36
+ * explicitly specify this option as true.
37
+ */
38
+ emptyStringAsUndefined: true,
39
+ });
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "T3Env",
3
+ "description": "Add type safety to your environment variables",
4
+ "phase": "add-on",
5
+ "link": "https://github.com/t3-oss/t3-env",
6
+ "templates": [
7
+ "file-router",
8
+ "code-router"
9
+ ]
10
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "zod": "^3.24.2",
4
+ "@t3-oss/env-core": "^0.12.0"
5
+ }
6
+ }
@@ -0,0 +1,24 @@
1
+ import { createAPIFileRoute } from "@tanstack/react-start/api";
2
+ import { getEvent } from "vinxi/http";
3
+
4
+ import { transports } from "@/utils/demo.sse";
5
+
6
+ export const APIRoute = createAPIFileRoute("/api/messages")({
7
+ // @ts-ignore
8
+ POST: async ({ request, params }) => {
9
+ const body = await request.json();
10
+ const url = new URL(request.url);
11
+ const sessionId = url.searchParams.get("sessionId") as string;
12
+ const transport = transports[sessionId];
13
+ if (transport) {
14
+ try {
15
+ getEvent().node.res.statusCode = 200;
16
+ await transport.handleMessage(body);
17
+ } catch (error) {
18
+ getEvent().node.res.send("Error handling message");
19
+ }
20
+ } else {
21
+ getEvent().node.res.send("No transport found for sessionId");
22
+ }
23
+ },
24
+ });
@@ -0,0 +1,23 @@
1
+ import { createAPIFileRoute } from '@tanstack/react-start/api'
2
+ import { getEvent } from 'vinxi/http'
3
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'
4
+
5
+ import { transports, server } from '@/utils/demo.sse'
6
+
7
+ export const APIRoute = createAPIFileRoute('/api/sse')({
8
+ // @ts-ignore
9
+ GET: async ({}) => {
10
+ const transport = new SSEServerTransport(
11
+ '/api/messages',
12
+ getEvent().node.res,
13
+ )
14
+ transports[transport.sessionId] = transport
15
+ transport.onerror = (error) => {
16
+ console.error(error)
17
+ }
18
+ getEvent().node.res.on('close', () => {
19
+ delete transports[transport.sessionId]
20
+ })
21
+ await server.connect(transport)
22
+ },
23
+ })
@@ -0,0 +1,31 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
3
+ import { getWebRequest } from "vinxi/http";
4
+
5
+ import guitars from "@/data/example-guitars";
6
+
7
+ export const server = new McpServer({
8
+ name: "guitar-server",
9
+ version: "1.0.0",
10
+ });
11
+ export const transports: { [sessionId: string]: SSEServerTransport } = {};
12
+
13
+ server.tool("getGuitars", {}, async ({}) => {
14
+ const port = new URL(getWebRequest().url).port;
15
+ return {
16
+ content: [
17
+ {
18
+ type: "text",
19
+ text: JSON.stringify(
20
+ guitars.map((guitar) => ({
21
+ id: guitar.id,
22
+ name: guitar.name,
23
+ description: guitar.description,
24
+ price: guitar.price,
25
+ image: `http://localhost:${port}${guitar.image}`,
26
+ }))
27
+ ),
28
+ },
29
+ ],
30
+ };
31
+ });
@@ -2,6 +2,7 @@
2
2
  "dependencies": {
3
3
  "@ai-sdk/anthropic": "^1.1.17",
4
4
  "@ai-sdk/react": "^1.1.23",
5
+ "@modelcontextprotocol/sdk": "^1.8.0",
5
6
  "ai": "^4.1.65",
6
7
  "highlight.js": "^11.11.1",
7
8
  "react-markdown": "^9.0.1",
@@ -0,0 +1,16 @@
1
+ ## T3Env
2
+
3
+ - You can use T3Env to add type safety to your environment variables.
4
+ - Add Environment variables to the `src/env.mjs` file.
5
+ - Use the environment variables in your code.
6
+
7
+ ### Usage
8
+
9
+ ```ts
10
+ import { env } from "@/env";
11
+
12
+ console.log(env.VITE_APP_TITLE);
13
+ ```
14
+
15
+
16
+
@@ -0,0 +1,39 @@
1
+ import { createEnv } from "@t3-oss/env-core";
2
+ import { z } from "zod";
3
+
4
+ export const env = createEnv({
5
+ server: {
6
+ SERVER_URL: z.string().url().optional(),
7
+ },
8
+
9
+ /**
10
+ * The prefix that client-side variables must have. This is enforced both at
11
+ * a type-level and at runtime.
12
+ */
13
+ clientPrefix: "VITE_",
14
+
15
+ client: {
16
+ VITE_APP_TITLE: z.string().min(1).optional(),
17
+ },
18
+
19
+ /**
20
+ * What object holds the environment variables at runtime. This is usually
21
+ * `process.env` or `import.meta.env`.
22
+ */
23
+ runtimeEnv: import.meta.env,
24
+
25
+ /**
26
+ * By default, this library will feed the environment variables directly to
27
+ * the Zod validator.
28
+ *
29
+ * This means that if you have an empty string for a value that is supposed
30
+ * to be a number (e.g. `PORT=` in a ".env" file), Zod will incorrectly flag
31
+ * it as a type mismatch violation. Additionally, if you have an empty string
32
+ * for a value that is supposed to be a string with a default value (e.g.
33
+ * `DOMAIN=` in an ".env" file), the default value will never be applied.
34
+ *
35
+ * In order to solve these issues, we recommend that all new projects
36
+ * explicitly specify this option as true.
37
+ */
38
+ emptyStringAsUndefined: true,
39
+ });
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "T3Env",
3
+ "description": "Add type safety to your environment variables",
4
+ "phase": "add-on",
5
+ "link": "https://github.com/t3-oss/t3-env",
6
+ "templates": [
7
+ "file-router",
8
+ "code-router"
9
+ ]
10
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "dependencies": {
3
+ "zod": "^3.24.2",
4
+ "@t3-oss/env-core": "^0.12.0"
5
+ }
6
+ }