diff --git a/.github/labeler.yml b/.github/labeler.yml index 650e4e34d13..16ac3b06ef6 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,9 +1,5 @@ 'package: arktype-adapter': - 'packages/arktype-adapter/**/*' -'package: create-router': - - 'packages/create-router/**/*' -'package: create-start': - - 'packages/create-start/**/*' 'package: directive-functions-plugin': - 'packages/directive-functions-plugin/**/*' 'package: eslint-plugin-router': diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index edca1c876d3..73770db24a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,7 @@ concurrency: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + SERVER_PRESET: 'node-server' permissions: contents: write diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e031ae811fb..c6d20ead450 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -9,6 +9,7 @@ concurrency: env: NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + SERVER_PRESET: 'node-server' permissions: contents: read diff --git a/docs/router/framework/react/quick-start.md b/docs/router/framework/react/quick-start.md index 8e9f548bdda..b9264f87427 100644 --- a/docs/router/framework/react/quick-start.md +++ b/docs/router/framework/react/quick-start.md @@ -14,7 +14,7 @@ File based route generation (through Vite, and other supported bundlers) is the npx create-tsrouter-app@latest my-app --template file-router ``` -See [create-tsrouter-app](https://github.com/TanStack/create-tsrouter-app) for more options. +See [create-tsrouter-app](https://github.com/TanStack/create-tsrouter-app/tree/main/cli/create-tsrouter-app) for more options. ### Manual Setup diff --git a/docs/router/framework/react/routing/file-naming-conventions.md b/docs/router/framework/react/routing/file-naming-conventions.md index a789d82b418..300895addc6 100644 --- a/docs/router/framework/react/routing/file-naming-conventions.md +++ b/docs/router/framework/react/routing/file-naming-conventions.md @@ -11,6 +11,7 @@ File-based routing requires that you follow a few simple file naming conventions | **`$` Token** | Route segments with the `$` token are parameterized and will extract the value from the URL pathname as a route `param`. | | **`_` Prefix** | Route segments with the `_` prefix are considered to be pathless layout routes and will not be used when matching its child routes against the URL pathname. | | **`_` Suffix** | Route segments with the `_` suffix exclude the route from being nested under any parent routes. | +| **`-` Prefix** | Files and folders with the `-` prefix are excluded from the route tree. They will not be added to the `routeTree.gen.ts` file and can be used to colocate logic in route folders. | | **`(folder)` folder name pattern** | A folder that matches this pattern is treated as a **route group**, preventing the folder from being included in the route's URL path. | | **`index` Token** | Route segments ending with the `index` token (before any file extensions) will match the parent route when the URL pathname matches the parent route exactly. This can be configured via the `indexToken` configuration option, see [options](../../../api/file-based-routing.md#indextoken). | | **`.route.tsx` File Type** | When using directories to organise routes, the `route` suffix can be used to create a route file at the directory's path. For example, `blog.post.route.tsx` or `blog/post/route.tsx` can be used as the route file for the `/blog/post` route. This can be configured via the `routeToken` configuration option, see [options](../../../api/file-based-routing.md#routetoken). | diff --git a/docs/router/framework/react/routing/route-trees.md b/docs/router/framework/react/routing/route-trees.md index 3a0a23cadec..c2d97296668 100644 --- a/docs/router/framework/react/routing/route-trees.md +++ b/docs/router/framework/react/routing/route-trees.md @@ -4,15 +4,12 @@ title: Route Trees TanStack Router uses a nested route tree to match up the URL with the correct component tree to render. -To build a route tree, TanStack Router supports both: +To build a route tree, TanStack Router supports: -- File-Based Routing -- Code-Based Routing +- [File-Based Routing](./file-based-routing.md) +- [Code-Based Routing](./code-based-routing.md) -Both methods support the exact same core features and functionality, but **file-based routing requires less code for the same or better results**. For this reasons, **file-based routing is the preferred and recommended way to configure TanStack Router and most of the documentation is written from the perspective of file-based routing** - -For code-based routing documentation, please see -the [Code-Based Routing](./code-based-routing.md) guide. +Both methods support the exact same core features and functionality, but **file-based routing requires less code for the same or better results**. For this reason, **file-based routing is the preferred and recommended way** to configure TanStack Router. Most of the documentation is written from the perspective of file-based routing. ## Route Trees diff --git a/docs/router/framework/react/routing/routing-concepts.md b/docs/router/framework/react/routing/routing-concepts.md index f07bb658689..38d9ae5cd9b 100644 --- a/docs/router/framework/react/routing/routing-concepts.md +++ b/docs/router/framework/react/routing/routing-concepts.md @@ -318,6 +318,50 @@ The following table shows which component will be rendered based on the URL: - The `posts.$postId.tsx` route is nested as normal under the `posts.tsx` route and will render ``. - The `posts_.$postId.edit.tsx` route **does not share** the same `posts` prefix as the other routes and therefore will be treated as if it is a top-level route and will render ``. +## Excluding Files and Folders from Routes + +Files and folders can be excluded from route generation with a `-` prefix attached to the file name. This gives you the ability to colocate logic in the route directories. + +Consider the following route tree: + +``` +routes/ +├── posts.tsx +├── -posts-table.tsx // 👈🏼 ignored +├── -components/ // 👈🏼 ignored +│ ├── header.tsx // 👈🏼 ignored +│ ├── footer.tsx // 👈🏼 ignored +│ ├── ... +``` + +We can import from the excluded files into our posts route + +```tsx +import { createFileRoute } from '@tanstack/react-router' +import { PostsTable } from './-posts-table' +import { PostsHeader } from './-components/header' +import { PostsFooter } from './-components/footer' + +export const Route = createFileRoute('/posts')({ + loader: () => fetchPosts(), + component: PostComponent, +}) + +function PostComponent() { + const posts = Route.useLoaderData() + + return ( +
+ + + +
+ ) +} +``` + +The excluded files will not be added to `routeTree.gen.ts`. + ## Pathless Route Group Directories Pathless route group directories use `()` as a way to group routes files together regardless of their path. They are purely organizational and do not affect the route tree or component tree in any way. diff --git a/docs/router/framework/solid/quick-start.md b/docs/router/framework/solid/quick-start.md index b689dc01520..a831b6de1d0 100644 --- a/docs/router/framework/solid/quick-start.md +++ b/docs/router/framework/solid/quick-start.md @@ -14,7 +14,7 @@ File based route generation (through Vite, and other supported bundlers) is the npx create-tsrouter-app@latest my-app --framework solid --template file-router ``` -See [create-tsrouter-app](https://github.com/TanStack/create-tsrouter-app) for more options. +See [create-tsrouter-app](https://github.com/TanStack/create-tsrouter-app/tree/main/cli/create-tsrouter-app) for more options. ### Manual Setup diff --git a/docs/start/config.json b/docs/start/config.json index 5aa7af5324e..76cae14ab80 100644 --- a/docs/start/config.json +++ b/docs/start/config.json @@ -209,6 +209,21 @@ ] } ] + }, + { + "label": "Tutorials", + "children": [], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "Reading and Writing a File", + "to": "framework/react/reading-writing-file" + } + ] + } + ] } ] } diff --git a/docs/start/framework/react/api-routes.md b/docs/start/framework/react/api-routes.md index a1d1dd6d4c5..87032c5bcd7 100644 --- a/docs/start/framework/react/api-routes.md +++ b/docs/start/framework/react/api-routes.md @@ -7,7 +7,7 @@ API Routes are a powerful feature of TanStack Start that allow you to create ser By default, API Routes are defined in your `./app/routes/api` directory of your project and are automatically handled by the TanStack Start server. -> 🧠 This means that by default, your API Routes will be prefixed with `/api` and will be served from the same server as your application. You can customize this base path by changing the `server.apiBaseURL` in your TanStack Start config. +> 🧠 This means that by default, your API Routes will be prefixed with `/api` and will be served from the same server as your application. You can customize this base path by changing the `tsr.apiBase` in your TanStack Start config. ## File Route Conventions diff --git a/docs/start/framework/react/build-from-scratch.md b/docs/start/framework/react/build-from-scratch.md index 5cb2e8e4837..055526d7f81 100644 --- a/docs/start/framework/react/build-from-scratch.md +++ b/docs/start/framework/react/build-from-scratch.md @@ -30,7 +30,7 @@ npm init -y We highly recommend using TypeScript with TanStack Start. Create a `tsconfig.json` file with at least the following settings: -```jsonc +```json { "compilerOptions": { "jsx": "react-jsx", @@ -38,8 +38,8 @@ We highly recommend using TypeScript with TanStack Start. Create a `tsconfig.jso "module": "ESNext", "target": "ES2022", "skipLibCheck": true, - "strictNullChecks": true, - }, + "strictNullChecks": true + } } ``` diff --git a/docs/start/framework/react/hosting.md b/docs/start/framework/react/hosting.md index c7ef0d34851..5241494e80c 100644 --- a/docs/start/framework/react/hosting.md +++ b/docs/start/framework/react/hosting.md @@ -63,7 +63,7 @@ Or you can use the `--preset` flag with the `build` command to specify the deplo npm run build --preset netlify ``` -Deploy you application to Netlify using their one-click deployment process, and you're ready to go! +Deploy your application to Netlify using their one-click deployment process, and you're ready to go! ### Vercel @@ -86,7 +86,7 @@ Or you can use the `--preset` flag with the `build` command to specify the deplo npm run build --preset vercel ``` -Deploy you application to Vercel using their one-click deployment process, and you're ready to go! +Deploy your application to Vercel using their one-click deployment process, and you're ready to go! ### Cloudflare Pages @@ -127,7 +127,7 @@ compatibility_flags = ["nodejs_compat"] compatibility_date = "2024-11-13" ``` -Deploy you application to Cloudflare Pages using their one-click deployment process, and you're ready to go! +Deploy your application to Cloudflare Pages using their one-click deployment process, and you're ready to go! ### Node.js diff --git a/docs/start/framework/react/middleware.md b/docs/start/framework/react/middleware.md index c908f5b8956..7eb75ba032f 100644 --- a/docs/start/framework/react/middleware.md +++ b/docs/start/framework/react/middleware.md @@ -263,7 +263,7 @@ const requestLogger = createMiddleware() ## Reading/Modifying the Server Response -Middleware that uses the `server` method executes in the same context as server functions, so you can follow the exact same [Server Function Context Utilities](./server-functions#server-function-context) to read and modify anything about the request headers, status codes, etc. +Middleware that uses the `server` method executes in the same context as server functions, so you can follow the exact same [Server Function Context Utilities](../server-functions#server-function-context) to read and modify anything about the request headers, status codes, etc. ## Modifying the Client Request diff --git a/docs/start/framework/react/overview.md b/docs/start/framework/react/overview.md index 84e036c7b33..ca4bbac835b 100644 --- a/docs/start/framework/react/overview.md +++ b/docs/start/framework/react/overview.md @@ -68,6 +68,15 @@ TanStack Start is not for you if: TanStack works closely with our partners to provide the best possible developer experience while also providing solutions that work anywhere and are vetted by industry experts. Each of our partners plays a unique role in the TanStack ecosystem: +- **Clerk** + + + + + Clerk logo + + + The best possible authentication experience for modern web applications, including TanStack Start applications. Clerk provides TanStack Start users with first-class integrations and solutions to auth and collaborates closely with the TanStack team to ensure that TanStack Start provides APIs that are up to date with the latest in auth best practices. - **Netlify** @@ -77,15 +86,15 @@ TanStack works closely with our partners to provide the best possible developer The leading hosting platform for web applications that provides a fast, secure, and reliable environment for deploying your web applications. We work closely with Netlify to ensure that TanStack Start applications not only deploy seamlessly to their platform, but also implement best practices for performance, security, and reliability regardless of where you end up deploying. -- **Clerk** - +- **Neon** + - - - Convex logo + + + Neon logo - The best possible authentication experience for modern web applications, including TanStack Start applications. Clerk provides TanStack Start users with first-class integrations and solutions to auth and collaborates closely with the TanStack team to ensure that TanStack Start provides APIs that are up to date with the latest in auth best practices. + A serverless, autoscaling Postgres solution purpose-built for modern full-stack apps. Neon offers rich integration opportunities with TanStack Start, including server functions and database-backed routing. Together, we’re simplifying the database experience for developers using TanStack. - **Convex** @@ -100,7 +109,7 @@ TanStack works closely with our partners to provide the best possible developer - Convex logo + Sentry logo A powerful, full-featured observability platform that integrates seamlessly with TanStack Start. Sentry helps developers monitor and fix crashes in real-time and provides insights into your application's performance and error tracking. Sentry collaborates closely with the TanStack team to ensure that TanStack Start provides APIs that are up to date with the latest in observability best practices. diff --git a/docs/start/framework/react/reading-writing-file.md b/docs/start/framework/react/reading-writing-file.md new file mode 100644 index 00000000000..fb4d26f17bc --- /dev/null +++ b/docs/start/framework/react/reading-writing-file.md @@ -0,0 +1,557 @@ +--- +id: reading-and-writing-file +title: Building a Full Stack DevJokes App with TanStack Start +--- + +This tutorial will guide you through building a complete full-stack application using TanStack Start. You'll create a DevJokesapp where users can view and add developer-themed jokes, demonstrating key concepts of TanStack Start including server functions, file-based data storage, and React components. + +Here's a demo of the app in action: + + + +The complete code for this tutorial is available on [GitHub](https://github.com/shrutikapoor08/devjokes). + +## What You'll Learn + +1. Setting up a TanStack Start project +2. Implementing server functions +3. Reading and writing data to files +4. Building a complete UI with React components +5. Using TanStack Router for data fetching and navigation + +## Prerequisites + +- Basic knowledge of React and TypeScript. +- Node.js and `pnpm` installed on your machine + +## Nice to know + +- [Server Side Rendering (SSR)](https://tanstack.com/router/latest/docs/framework/react/guide/ssr) +- [TanStack Router concepts](https://tanstack.com/router/latest/docs/framework/react/routing/routing-concepts) +- [React Query concepts](https://tanstack.com/query/latest/docs/framework/react/overview) + +## Setting up a TanStack Start Project + +First, let's create a new TanStack Start project: + +```bash +pnpx create-start-app devjokes +cd devjokes +``` + +When this script runs, it will ask you a few setup questions. You can either pick choices that work for you or just press enter to accept the defaults. + +Optionally, you can pass in a `--add-on` flag to get options such as Shadcn, Clerk, Convex, TanStack Query, etc. + +Once setup is complete, install dependencies and start the development server: + +```bash +pnpm i +pnpm dev +``` + +For this project, we'll need a few additional packages: + +```bash +# Install uuid for generating unique IDs +pnpm add uuid +pnpm add -D @types/uuid +``` + +## Understanding the project structure + +At this point, the project structure should look like this - + +``` +/devjokes +├── src/ +│ ├── routes/ +│ │ ├── __root.tsx # Root layout +│ │ ├── index.tsx # Home page +│ │ ├── demo.start.server-funcs.tsx # Demo server functions +│ │ └── demo.start.api-request.tsx # Demo API request +│ ├── api/ # API endpoints +│ ├── components/ # React components +│ ├── api.ts # API handler. +│ ├── client.tsx # Client entry point +│ ├── router.tsx # Router configuration +│ ├── routeTree.gen.ts # Generated route tree +│ ├── ssr.tsx # Server-side rendering +│ └── styles.css # Global styles +├── public/ # Static assets +├── app.config.ts # TanStack Start configuration +├── package.json # Project dependencies +└── tsconfig.json # TypeScript configuration +``` + +This structure might seem overwhelming at first, but here are the key files you need to focus on: + +1. `router.tsx` - Sets up routing for your application +2. `src/routes/__root.tsx` - The root layout component where you can add global styles and components +3. `src/routes/index.tsx` - Your home page +4. `client.tsx` - Client-side entry point +5. `ssr.tsx` - Handles server-side rendering + +Once your project is set up, you can access your app at `localhost:3000`. You should see the default TanStack Start welcome page. + +At this point, your app will look like this - + +![TanStack Start Welcome Page After Setup](https://res.cloudinary.com/dubc3wnbv/image/upload/v1746312482/Photo-1_lpechn.png) + +## Step 1: Reading Data From a File + +Let's start by creating a file-based storage system for our jokes. + +### Step 1.1: Create a JSON File with Jokes + +Let's set up a list of jokes that we can use to render on the page. Create a `data` directory in your project root and a `jokes.json` file within it: + +```bash +mkdir -p src/data +touch src/data/jokes.json +``` + +Now, let's add some sample jokes to this file: + +```json +[ + { + "id": "1", + "question": "Why don't keyboards sleep?", + "answer": "Because they have two shifts" + }, + { + "id": "2", + "question": "Are you a RESTful API?", + "answer": "Because you GET my attention, PUT some love, POST the cutest smile, and DELETE my bad day" + }, + { + "id": "3", + "question": "I used to know a joke about Java", + "answer": "But I ran out of memory." + }, + { + "id": "4", + "question": "Why do Front-End Developers eat lunch alone?", + "answer": "Because, they don't know how to join tables." + }, + { + "id": "5", + "question": "I am declaring a war.", + "answer": "var war;" + } +] +``` + +### Step 1.2: Create Types for Our Data + +Let's create a file to define our data types. Create a new file at `src/types/index.ts`: + +```typescript +// src/types/index.ts +export interface Joke { + id: string + question: string + answer: string +} + +export type JokesData = Joke[] +``` + +### Step 1.3: Create Server Functions to Read the File + +Let's create a new file `src/serverActions/jokesActions.ts` to create a server function to perform a read-write operation. We will be creating a server function using [`createServerFn`](https://tanstack.com/start/latest/docs/framework/react/server-functions). + +```tsx +// src/serverActions/jokesActions.ts + +import { createServerFn } from '@tanstack/react-start' +import * as fs from 'node:fs' +import type { JokesData } from '../types' + +const JOKES_FILE = 'src/data/jokes.json' + +export const getJokes = createServerFn({ method: 'GET' }).handler(async () => { + const jokes = await fs.promises.readFile(JOKES_FILE, 'utf-8') + return JSON.parse(jokes) as JokesData +}) +``` + +In this code, we are using `createServerFn` to create a server function that reads the jokes from the JSON file. The `handler` function is where we are using the `fs` module to read the file. + +### Step 1.4: Consume Server Function on the Client Side + +Now to consume this server function, we can simply call it in our code using TanStack Router which already comes with TanStack Start! + +Now let's create a new component `JokesList` to render the jokes on the page with a little Tailwind styling sprinkle. + +```tsx +// src/components/JokesList.tsx +import { Joke } from '../types' + +interface JokesListProps { + jokes: Joke[] +} + +export function JokesList({ jokes }: JokesListProps) { + if (!jokes || jokes.length === 0) { + return

No jokes found. Add some!

+ } + + return ( +
+

Jokes Collection

+ {jokes.map((joke) => ( +
+

{joke.question}

+

{joke.answer}

+
+ ))} +
+ ) +} +``` + +Now let's call our server function inside `App.jsx` using TanStack Router which already comes with TanStack Start! + +```jsx +// App.jsx +import { createFileRoute } from '@tanstack/react-router' +import { getJokes } from './serverActions/jokesActions' +import { JokesList } from './JokesList' + +export const Route = createFileRoute('/')({ + loader: async () => { + // Load jokes data when the route is accessed + return getJokes() + }, + component: App, +}) + +const App = () => { + const jokes = Route.useLoaderData() || [] + + return ( +
+

DevJokes

+ +
+ ) +} +``` + +When the page loads, `jokes` will have data from the `jokes.json` file already! + +With a little Tailwind styling, the app should look like this: + +![DevJoke App with 5 DevJokes](https://res.cloudinary.com/dubc3wnbv/image/upload/v1746313558/Screenshot_2025-05-03_at_4.04.50_PM_w0eern.png) + +## Step 2: Writing Data to a File + +So far, we have been able to read from the file successfully! We can use the same approach to write to the `jokes.json` file using `createServerFunction`. + +### Step 2.1: Create Server Function to Write to the File + +It's time to modify the `jokes.json` file so that we can add new jokes to it. Let's create another server function but this time with a `POST` method to write to the same file. + +```tsx +// src/serverActions/jokesActions.ts +import { createServerFn } from '@tanstack/react-start' +import * as fs from 'node:fs' +import { v4 as uuidv4 } from 'uuid' // Add this import +import type { Joke, JokesData } from '../types' + +export const addJoke = createServerFn({ method: 'POST' }) + .validator((data: { question: string; answer: string }) => { + // Validate input data + if (!data.question || !data.question.trim()) { + throw new Error('Joke question is required') + } + if (!data.answer || !data.answer.trim()) { + throw new Error('Joke answer is required') + } + return data + }) + .handler(async ({ data }) => { + try { + // Read the existing jokes from the file + const jokesData = await getJokes() + + // Create a new joke with a unique ID + const newJoke: Joke = { + id: uuidv4(), + question: data.question, + answer: data.answer, + } + + // Add the new joke to the list + const updatedJokes = [...jokesData, newJoke] + + // Write the updated jokes back to the file + await fs.promises.writeFile( + JOKES_FILE, + JSON.stringify(updatedJokes, null, 2), + 'utf-8', + ) + + return newJoke + } catch (error) { + console.error('Failed to add joke:', error) + throw new Error('Failed to add joke') + } + }) +``` + +In this code: + +- We are using `createServerFn` to create server functions that run on the server but can be called from the client. This server function is used to write data to the file. +- We are going to first use `validator` to validate the input data. This is a good practice to ensure that the data we are receiving is in the correct format. +- We are going to perform the actual write operation in the `handler` function. +- `getJokes` reads the jokes from our JSON file. +- `addJoke` validates the input data and adds a new joke to our file. +- We're using `uuidv4()` to generate unique IDs for our jokes. + +### Step 2.2: Adding a Form to Add Jokes to our JSON File + +Now, let's modify our home page to display jokes and provide a form to add new ones. Let's create a new component called `JokeForm.jsx` and add the following form to it: + +```tsx +// src/components/JokeForm.tsx +import { useState } from 'react' +import { useRouter } from '@tanstack/react-router' +import { addJoke } from '../serverActions/jokesActions' + +export function JokeForm() { + const router = useRouter() + const [question, setQuestion] = useState('') + const [answer, setAnswer] = useState('') + const [isSubmitting, setIsSubmitting] = useState(false) + const [error, setError] = useState(null) + + return ( +
+ {error && ( +
{error}
+ )} + +
+ setQuestion(e.target.value)} + required + /> + + setAnswer(e.target.value)} + required + /> + + +
+
+ ) +} +``` + +### Step 2.3: Wire Up the Form to the Server Function + +Now, let's wire the form up to our `addJoke` server function in the `handleSubmit` function. Calling a server action is simple! It's just a function call. + +```tsx +//JokeForm.tsx +import { useState } from 'react' +import { addJoke } from '../serverActions/jokesActions' +import { useRouter } from '@tanstack/react-router' + +export function JokeForm() { + const router = useRouter() + const [question, setQuestion] = useState('') + const [answer, setAnswer] = useState('') + const [isSubmitting, setIsSubmitting] = useState(false) + const [error, setError] = useState(null) + + const handleSubmit = async () => { + if (!question || !answer || isSubmitting) return + try { + setIsSubmitting(true) + await addJoke({ + data: { question, answer }, + }) + + // Clear form + setQuestion('') + setAnswer('') + + // Refresh data + router.invalidate() + } catch (error) { + console.error('Failed to add joke:', error) + setError('Failed to add joke') + } finally { + setIsSubmitting(false) + } + } + + return ( +
+ {error && ( +
{error}
+ )} + setQuestion(e.target.value)} + value={question} + /> + setAnswer(e.target.value)} + value={answer} + /> + +
+ ) +} +``` + +With this, our UI should look like this: +![DevJoke App with Form to Add Jokes](https://res.cloudinary.com/dubc3wnbv/image/upload/v1746356983/Screenshot_2025-05-04_at_4.06.57_AM_dkgvsm.png) + +## Understanding How It All Works Together + +Let's break down how the different parts of our application work together: + +1. **Server Functions**: These run on the server and handle data operations + + - `getJokes`: Reads the jokes from our JSON file + - `addJoke`: Adds a new joke to our JSON file + +2. **TanStack Router**: Handles routing and data loading + + - The loader function fetches jokes data when the route is accessed + - `useLoaderData` makes this data available in our component + - `router.invalidate()` refreshes the data when we add a new joke + +3. **React Components**: Build the UI of our application + + - `JokesList`: Displays the list of jokes + - `JokeForm`: Provides a form for adding new jokes + +4. **File-Based Storage**: Stores our jokes in a JSON file + - Reading and writing are handled by Node.js `fs` module + - Data is persisted between server restarts + +## How Data Flows Through the Application + +### Data Flow + +![Data Flow Diagram](https://res.cloudinary.com/dubc3wnbv/image/upload/v1746437057/Screenshot_2025-05-05_at_2.23.11_AM_wxfz2m.png) + +When a user visits the home page: + +1. The `loader` function in the route calls `getJokes()` server function +2. The server reads `jokes.json` and returns the jokes data +3. This data is passed to the `HomePage` component through `useLoaderData()` +4. The `HomePage` component passes the data to the `JokesList` component + +When a user adds a new joke: + +1. They fill out the form and submit it +2. The `handleSubmit` function calls the `addJoke()` server function +3. The server reads the current jokes, adds the new joke, and writes the updated data back to `jokes.json` +4. After the operation completes, we call `router.invalidate()` to refresh the data +5. This triggers the loader again, fetching the updated jokes +6. The UI updates to show the new joke in the list + +Here's a demo of the app in action: + + + +## Common Issues and Debugging + +Here are some common issues you might encounter when building your TanStack Start application and how to resolve them: + +### Server Functions Not Working + +If your server functions aren't working as expected: + +1. Check that you're using the correct HTTP method (`GET`, `POST`, etc.) +2. Ensure file paths are correct and accessible to the server +3. Check the server console for error messages +4. Make sure you're not using client-only APIs in server functions + +### Route Data Not Loading + +If route data isn't loading properly: + +1. Verify that your loader function is properly implemented +2. Check that you're using `useLoaderData()` correctly +3. Look for errors in the browser console +4. Make sure your server function is working correctly + +### Form Submission Issues + +If form submissions aren't working: + +1. Check for validation errors in your server function +2. Verify that form event prevention (`e.preventDefault()`) is working +3. Make sure state updates are happening correctly +4. Look for network errors in the browser's Developer Tools + +### File Reading/Writing Issues + +When working with file-based storage: + +1. Ensure file paths are correct +2. Check file permissions +3. Make sure you're handling async operations properly with `await` +4. Add proper error handling for file operations + +## Conclusion + +Congratulations! You've built a full-stack DevJokes app using TanStack Start. In this tutorial, you've learned: + +- How to set up a TanStack Start project +- How to implement server functions for data operations +- How to read and write data to files +- How to build React components for your UI +- How to use TanStack Router for routing and data fetching + +This simple application demonstrates the power of TanStack Start for building full-stack applications with a minimal amount of code. You can extend this app by adding features like: + +- Joke categories +- Ability to edit and delete jokes +- User authentication +- Voting for favorite jokes + +The complete code for this tutorial is available on [GitHub](https://github.com/shrutikapoor08/devjokes). diff --git a/docs/start/framework/solid/build-from-scratch.md b/docs/start/framework/solid/build-from-scratch.md index 6e00a653240..c5fcdb35632 100644 --- a/docs/start/framework/solid/build-from-scratch.md +++ b/docs/start/framework/solid/build-from-scratch.md @@ -30,7 +30,7 @@ npm init -y We highly recommend using TypeScript with TanStack Start. Create a `tsconfig.json` file with at least the following settings: -```jsonc +```json { "compilerOptions": { "jsx": "preserve", @@ -39,8 +39,8 @@ We highly recommend using TypeScript with TanStack Start. Create a `tsconfig.jso "module": "ESNext", "target": "ES2022", "skipLibCheck": true, - "strictNullChecks": true, - }, + "strictNullChecks": true + } } ``` diff --git a/e2e/react-start/server-functions/tests/server-functions.spec.ts b/e2e/react-start/server-functions/tests/server-functions.spec.ts index e0decd0ddff..56d66080773 100644 --- a/e2e/react-start/server-functions/tests/server-functions.spec.ts +++ b/e2e/react-start/server-functions/tests/server-functions.spec.ts @@ -187,7 +187,7 @@ test('server function can correctly send and receive headers', async ({ "connection": "keep-alive", "content-type": "application/json", "host": "localhost:${PORT}", - "sec-ch-ua": "\\"Not(A:Brand\\";v=\\"99\\", \\"HeadlessChrome\\";v=\\"133\\", \\"Chromium\\";v=\\"133\\"", + "sec-ch-ua": "\\"Chromium\\";v=\\"136\\", \\"HeadlessChrome\\";v=\\"136\\", \\"Not.A/Brand\\";v=\\"99\\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\\"Windows\\"", "sec-fetch-dest": "document", @@ -195,7 +195,7 @@ test('server function can correctly send and receive headers', async ({ "sec-fetch-site": "none", "sec-fetch-user": "?1", "upgrade-insecure-requests": "1", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36" + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.25 Safari/537.36" }`) await page.getByTestId('test-headers-btn').click() @@ -205,9 +205,9 @@ test('server function can correctly send and receive headers', async ({ "host": "localhost:${PORT}", "connection": "keep-alive", "sec-ch-ua-platform": "\\"Windows\\"", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.25 Safari/537.36", "accept": "application/json", - "sec-ch-ua": "\\"Not(A:Brand\\";v=\\"99\\", \\"HeadlessChrome\\";v=\\"133\\", \\"Chromium\\";v=\\"133\\"", + "sec-ch-ua": "\\"Chromium\\";v=\\"136\\", \\"HeadlessChrome\\";v=\\"136\\", \\"Not.A/Brand\\";v=\\"99\\"", "content-type": "application/json", "sec-ch-ua-mobile": "?0", "accept-language": "en-US", diff --git a/e2e/solid-start/server-functions/tests/server-functions.spec.ts b/e2e/solid-start/server-functions/tests/server-functions.spec.ts index e0decd0ddff..56d66080773 100644 --- a/e2e/solid-start/server-functions/tests/server-functions.spec.ts +++ b/e2e/solid-start/server-functions/tests/server-functions.spec.ts @@ -187,7 +187,7 @@ test('server function can correctly send and receive headers', async ({ "connection": "keep-alive", "content-type": "application/json", "host": "localhost:${PORT}", - "sec-ch-ua": "\\"Not(A:Brand\\";v=\\"99\\", \\"HeadlessChrome\\";v=\\"133\\", \\"Chromium\\";v=\\"133\\"", + "sec-ch-ua": "\\"Chromium\\";v=\\"136\\", \\"HeadlessChrome\\";v=\\"136\\", \\"Not.A/Brand\\";v=\\"99\\"", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "\\"Windows\\"", "sec-fetch-dest": "document", @@ -195,7 +195,7 @@ test('server function can correctly send and receive headers', async ({ "sec-fetch-site": "none", "sec-fetch-user": "?1", "upgrade-insecure-requests": "1", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36" + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.25 Safari/537.36" }`) await page.getByTestId('test-headers-btn').click() @@ -205,9 +205,9 @@ test('server function can correctly send and receive headers', async ({ "host": "localhost:${PORT}", "connection": "keep-alive", "sec-ch-ua-platform": "\\"Windows\\"", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.6943.16 Safari/537.36", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.7103.25 Safari/537.36", "accept": "application/json", - "sec-ch-ua": "\\"Not(A:Brand\\";v=\\"99\\", \\"HeadlessChrome\\";v=\\"133\\", \\"Chromium\\";v=\\"133\\"", + "sec-ch-ua": "\\"Chromium\\";v=\\"136\\", \\"HeadlessChrome\\";v=\\"136\\", \\"Not.A/Brand\\";v=\\"99\\"", "content-type": "application/json", "sec-ch-ua-mobile": "?0", "accept-language": "en-US", diff --git a/examples/react/authenticated-routes-firebase/.env.example b/examples/react/authenticated-routes-firebase/.env.example index 9ed8acffed2..e9b13d06f87 100644 --- a/examples/react/authenticated-routes-firebase/.env.example +++ b/examples/react/authenticated-routes-firebase/.env.example @@ -1,8 +1,8 @@ # Firebase Configuration: Copy this file to `.env.local` and add your Firebase credentials # Obtain these values from your Firebase Console (see README.md for detailed setup instructions) -VITE_FIREBASE_API_KEY= -VITE_FIREBASE_AUTH_DOMAIN= -VITE_FIREBASE_PROJECT_ID= -VITE_FIREBASE_STORAGE_BUCKET= -VITE_FIREBASE_MESSAGING_SENDER_ID= -VITE_FIREBASE_APP_ID= +VITE_PUBLIC_FIREBASE_API_KEY= +VITE_PUBLIC_FIREBASE_AUTH_DOMAIN= +VITE_PUBLIC_FIREBASE_PROJECT_ID= +VITE_PUBLIC_FIREBASE_STORAGE_BUCKET= +VITE_PUBLIC_FIREBASE_MESSAGING_SENDER_ID= +VITE_PUBLIC_FIREBASE_APP_ID= diff --git a/examples/react/authenticated-routes-firebase/package.json b/examples/react/authenticated-routes-firebase/package.json index 584d6b33c9e..1b1656e02bb 100644 --- a/examples/react/authenticated-routes-firebase/package.json +++ b/examples/react/authenticated-routes-firebase/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "autoprefixer": "^10.4.20", "firebase": "^11.4.0", "postcss": "^8.5.1", diff --git a/examples/react/authenticated-routes-firebase/src/vite.d.ts b/examples/react/authenticated-routes-firebase/src/vite.d.ts index f6c9d7f9051..775f54ec0fb 100644 --- a/examples/react/authenticated-routes-firebase/src/vite.d.ts +++ b/examples/react/authenticated-routes-firebase/src/vite.d.ts @@ -1,12 +1,12 @@ /// interface ImportMetaEnv { - readonly VITE_FIREBASE_API_KEY: string - readonly VITE_FIREBASE_AUTH_DOMAIN: string - readonly VITE_FIREBASE_PROJECT_ID: string - readonly VITE_FIREBASE_STORAGE_BUCKET: string - readonly VITE_FIREBASE_MESSAGING_SENDER_ID: string - readonly VITE_FIREBASE_APP_ID: string + readonly VITE_PUBLIC_FIREBASE_API_KEY: string + readonly VITE_PUBLIC_FIREBASE_AUTH_DOMAIN: string + readonly VITE_PUBLIC_FIREBASE_PROJECT_ID: string + readonly VITE_PUBLIC_FIREBASE_STORAGE_BUCKET: string + readonly VITE_PUBLIC_FIREBASE_MESSAGING_SENDER_ID: string + readonly VITE_PUBLIC_FIREBASE_APP_ID: string } interface ImportMeta { diff --git a/examples/react/authenticated-routes/package.json b/examples/react/authenticated-routes/package.json index 389e0905927..a362c7392c6 100644 --- a/examples/react/authenticated-routes/package.json +++ b/examples/react/authenticated-routes/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/basic-default-search-params/package.json b/examples/react/basic-default-search-params/package.json index 962aed096b7..4791165d3ec 100644 --- a/examples/react/basic-default-search-params/package.json +++ b/examples/react/basic-default-search-params/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/basic-devtools-panel/package.json b/examples/react/basic-devtools-panel/package.json index 4a6b823d071..dbc05652aea 100644 --- a/examples/react/basic-devtools-panel/package.json +++ b/examples/react/basic-devtools-panel/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "@tanstack/react-query-devtools": "^5.67.2", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/basic-file-based/package.json b/examples/react/basic-file-based/package.json index e7cd3eb8fc8..eeddd1e362f 100644 --- a/examples/react/basic-file-based/package.json +++ b/examples/react/basic-file-based/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/basic-non-nested-devtools/package.json b/examples/react/basic-non-nested-devtools/package.json index 33020a38892..8eb42da02d9 100644 --- a/examples/react/basic-non-nested-devtools/package.json +++ b/examples/react/basic-non-nested-devtools/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/basic-react-query-file-based/package.json b/examples/react/basic-react-query-file-based/package.json index 247b812c1e5..a817b29e205 100644 --- a/examples/react/basic-react-query-file-based/package.json +++ b/examples/react/basic-react-query-file-based/package.json @@ -11,9 +11,9 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/basic-react-query/package.json b/examples/react/basic-react-query/package.json index 5a7f29e37b9..193a7d0ffd8 100644 --- a/examples/react/basic-react-query/package.json +++ b/examples/react/basic-react-query/package.json @@ -11,8 +11,8 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/basic-ssr-file-based/package.json b/examples/react/basic-ssr-file-based/package.json index adb4dd57d2e..a08fae1ce20 100644 --- a/examples/react/basic-ssr-file-based/package.json +++ b/examples/react/basic-ssr-file-based/package.json @@ -11,10 +11,10 @@ "debug": "node --inspect-brk server" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "get-port": "^7.1.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/basic-ssr-streaming-file-based/package.json b/examples/react/basic-ssr-streaming-file-based/package.json index 4e09b12b6c9..2f1a96a1744 100644 --- a/examples/react/basic-ssr-streaming-file-based/package.json +++ b/examples/react/basic-ssr-streaming-file-based/package.json @@ -11,10 +11,10 @@ "debug": "node --inspect-brk server" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "get-port": "^7.1.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/basic-virtual-file-based/package.json b/examples/react/basic-virtual-file-based/package.json index bc3828c51aa..4084fe57c6c 100644 --- a/examples/react/basic-virtual-file-based/package.json +++ b/examples/react/basic-virtual-file-based/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "@tanstack/virtual-file-routes": "^1.115.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/basic-virtual-inside-file-based/package.json b/examples/react/basic-virtual-inside-file-based/package.json index 06db1c1e167..5eab54dae88 100644 --- a/examples/react/basic-virtual-inside-file-based/package.json +++ b/examples/react/basic-virtual-inside-file-based/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "@tanstack/virtual-file-routes": "^1.115.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/basic/package.json b/examples/react/basic/package.json index a00f9d49cd5..3ac260c81a5 100644 --- a/examples/react/basic/package.json +++ b/examples/react/basic/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/deferred-data/package.json b/examples/react/deferred-data/package.json index 392aa799146..67126a51817 100644 --- a/examples/react/deferred-data/package.json +++ b/examples/react/deferred-data/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/kitchen-sink-file-based/package.json b/examples/react/kitchen-sink-file-based/package.json index 3c9b8e3422e..574057946b5 100644 --- a/examples/react/kitchen-sink-file-based/package.json +++ b/examples/react/kitchen-sink-file-based/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/kitchen-sink-react-query-file-based/package.json b/examples/react/kitchen-sink-react-query-file-based/package.json index d646cc9cc72..e55d3e99dbc 100644 --- a/examples/react/kitchen-sink-react-query-file-based/package.json +++ b/examples/react/kitchen-sink-react-query-file-based/package.json @@ -11,9 +11,9 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/kitchen-sink-react-query/package.json b/examples/react/kitchen-sink-react-query/package.json index c6a940fd2b9..235b8bd571e 100644 --- a/examples/react/kitchen-sink-react-query/package.json +++ b/examples/react/kitchen-sink-react-query/package.json @@ -11,8 +11,8 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/kitchen-sink/package.json b/examples/react/kitchen-sink/package.json index 54cd956ace4..275d52ad2c6 100644 --- a/examples/react/kitchen-sink/package.json +++ b/examples/react/kitchen-sink/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/large-file-based/package.json b/examples/react/large-file-based/package.json index 4b95e6e9993..67aab63b142 100644 --- a/examples/react/large-file-based/package.json +++ b/examples/react/large-file-based/package.json @@ -12,9 +12,9 @@ }, "dependencies": { "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/location-masking/package.json b/examples/react/location-masking/package.json index 4f85c1c3485..43df52d6eac 100644 --- a/examples/react/location-masking/package.json +++ b/examples/react/location-masking/package.json @@ -11,8 +11,8 @@ "dependencies": { "@radix-ui/react-dialog": "^1.1.6", "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/navigation-blocking/package.json b/examples/react/navigation-blocking/package.json index 0b95f82bcb0..5491f8b5797 100644 --- a/examples/react/navigation-blocking/package.json +++ b/examples/react/navigation-blocking/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/quickstart-esbuild-file-based/package.json b/examples/react/quickstart-esbuild-file-based/package.json index 3fb55460088..824156e00cf 100644 --- a/examples/react/quickstart-esbuild-file-based/package.json +++ b/examples/react/quickstart-esbuild-file-based/package.json @@ -9,9 +9,9 @@ "start": "dev" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/quickstart-file-based/package.json b/examples/react/quickstart-file-based/package.json index c14ad11eced..cb048b2ee3a 100644 --- a/examples/react/quickstart-file-based/package.json +++ b/examples/react/quickstart-file-based/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/quickstart-rspack-file-based/package.json b/examples/react/quickstart-rspack-file-based/package.json index c23425e48ec..bea1276e5ba 100644 --- a/examples/react/quickstart-rspack-file-based/package.json +++ b/examples/react/quickstart-rspack-file-based/package.json @@ -8,8 +8,8 @@ "preview": "rsbuild preview" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "postcss": "^8.5.1", @@ -19,7 +19,7 @@ "devDependencies": { "@rsbuild/core": "1.2.4", "@rsbuild/plugin-react": "1.1.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "typescript": "^5.6.2" diff --git a/examples/react/quickstart-webpack-file-based/package.json b/examples/react/quickstart-webpack-file-based/package.json index 48e303f4a8d..4d8c37c3333 100644 --- a/examples/react/quickstart-webpack-file-based/package.json +++ b/examples/react/quickstart-webpack-file-based/package.json @@ -7,14 +7,14 @@ "build": "webpack build && tsc --noEmit" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@swc/core": "^1.10.15", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "html-webpack-plugin": "^5.6.3", diff --git a/examples/react/quickstart/package.json b/examples/react/quickstart/package.json index fe786d26b5b..13545b007d4 100644 --- a/examples/react/quickstart/package.json +++ b/examples/react/quickstart/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "postcss": "^8.5.1", diff --git a/examples/react/router-monorepo-react-query/package.json b/examples/react/router-monorepo-react-query/package.json index ff623faa35c..3d470f49cee 100644 --- a/examples/react/router-monorepo-react-query/package.json +++ b/examples/react/router-monorepo-react-query/package.json @@ -12,9 +12,9 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" diff --git a/examples/react/router-monorepo-react-query/packages/app/package.json b/examples/react/router-monorepo-react-query/packages/app/package.json index 1df369cc488..455096e1e94 100644 --- a/examples/react/router-monorepo-react-query/packages/app/package.json +++ b/examples/react/router-monorepo-react-query/packages/app/package.json @@ -20,7 +20,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5.7.2", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router-devtools": "^1.120.1", "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", diff --git a/examples/react/router-monorepo-react-query/packages/router/package.json b/examples/react/router-monorepo-react-query/packages/router/package.json index c67300b4239..37a043e0e3b 100644 --- a/examples/react/router-monorepo-react-query/packages/router/package.json +++ b/examples/react/router-monorepo-react-query/packages/router/package.json @@ -10,8 +10,8 @@ "dependencies": { "@tanstack/history": "^1.115.0", "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "@router-mono-react-query/post-query": "workspace:*", "redaxios": "^0.5.1", "zod": "^3.24.2", diff --git a/examples/react/router-monorepo-simple-lazy/package.json b/examples/react/router-monorepo-simple-lazy/package.json index abd862b9416..74de10881c1 100644 --- a/examples/react/router-monorepo-simple-lazy/package.json +++ b/examples/react/router-monorepo-simple-lazy/package.json @@ -8,9 +8,9 @@ "dev": "pnpm router build && pnpm post-feature build && pnpm app dev" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" diff --git a/examples/react/router-monorepo-simple-lazy/packages/app/package.json b/examples/react/router-monorepo-simple-lazy/packages/app/package.json index 539db44bd56..cc21f20a6b9 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/app/package.json +++ b/examples/react/router-monorepo-simple-lazy/packages/app/package.json @@ -19,7 +19,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5.7.2", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router-devtools": "^1.120.1", "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", diff --git a/examples/react/router-monorepo-simple-lazy/packages/router/package.json b/examples/react/router-monorepo-simple-lazy/packages/router/package.json index f5c18ffa6c7..d84f71d43dd 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/router/package.json +++ b/examples/react/router-monorepo-simple-lazy/packages/router/package.json @@ -9,8 +9,8 @@ "types": "./dist/index.d.ts", "dependencies": { "@tanstack/history": "^1.115.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "redaxios": "^0.5.1", "zod": "^3.24.2", "react": "^19.0.0", diff --git a/examples/react/router-monorepo-simple/package.json b/examples/react/router-monorepo-simple/package.json index da238d0a916..37918933986 100644 --- a/examples/react/router-monorepo-simple/package.json +++ b/examples/react/router-monorepo-simple/package.json @@ -8,9 +8,9 @@ "dev": "pnpm router build && pnpm post-feature build && pnpm app dev" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" diff --git a/examples/react/router-monorepo-simple/packages/app/package.json b/examples/react/router-monorepo-simple/packages/app/package.json index b95da79f9dc..844d312ab5a 100644 --- a/examples/react/router-monorepo-simple/packages/app/package.json +++ b/examples/react/router-monorepo-simple/packages/app/package.json @@ -19,7 +19,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", "typescript": "^5.7.2", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router-devtools": "^1.120.1", "vite": "^6.1.0", "postcss": "^8.5.1", "autoprefixer": "^10.4.20", diff --git a/examples/react/router-monorepo-simple/packages/router/package.json b/examples/react/router-monorepo-simple/packages/router/package.json index f9ca5e10378..a5c0d0ead6f 100644 --- a/examples/react/router-monorepo-simple/packages/router/package.json +++ b/examples/react/router-monorepo-simple/packages/router/package.json @@ -9,8 +9,8 @@ "types": "./dist/index.d.ts", "dependencies": { "@tanstack/history": "^1.115.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "redaxios": "^0.5.1", "zod": "^3.24.2", "react": "^19.0.0", diff --git a/examples/react/scroll-restoration/package.json b/examples/react/scroll-restoration/package.json index 7fa7a1c4b9d..c89284b7945 100644 --- a/examples/react/scroll-restoration/package.json +++ b/examples/react/scroll-restoration/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", + "@tanstack/react-router": "^1.120.1", "@tanstack/react-virtual": "^3.13.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "postcss": "^8.5.1", diff --git a/examples/react/search-validator-adapters/package.json b/examples/react/search-validator-adapters/package.json index 3fd0013d754..b33a32e22fd 100644 --- a/examples/react/search-validator-adapters/package.json +++ b/examples/react/search-validator-adapters/package.json @@ -10,13 +10,13 @@ "test:unit": "vitest" }, "dependencies": { - "@tanstack/arktype-adapter": "^1.116.0", + "@tanstack/arktype-adapter": "^1.120.1", "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", - "@tanstack/valibot-adapter": "^1.116.0", - "@tanstack/zod-adapter": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", + "@tanstack/valibot-adapter": "^1.120.1", + "@tanstack/zod-adapter": "^1.120.1", "arktype": "^2.1.7", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/start-bare/package.json b/examples/react/start-bare/package.json index 0198545c877..bc751526272 100644 --- a/examples/react/start-bare/package.json +++ b/examples/react/start-bare/package.json @@ -9,9 +9,9 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "vinxi": "0.5.3", diff --git a/examples/react/start-basic-auth/package.json b/examples/react/start-basic-auth/package.json index badba0d5cb6..78790f1b091 100644 --- a/examples/react/start-basic-auth/package.json +++ b/examples/react/start-basic-auth/package.json @@ -11,9 +11,9 @@ }, "dependencies": { "@prisma/client": "5.22.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "prisma": "^5.22.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/start-basic-react-query/package.json b/examples/react/start-basic-react-query/package.json index 3867697fe63..d981bd0dd7a 100644 --- a/examples/react/start-basic-react-query/package.json +++ b/examples/react/start-basic-react-query/package.json @@ -11,10 +11,10 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-with-query": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-with-query": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/start-basic-rsc/package.json b/examples/react/start-basic-rsc/package.json index 7dc50444be5..86e5ca47308 100644 --- a/examples/react/start-basic-rsc/package.json +++ b/examples/react/start-basic-rsc/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@babel/plugin-syntax-typescript": "^7.25.9", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/start-basic-static/package.json b/examples/react/start-basic-static/package.json index 127d3ea863a..6b35714546a 100644 --- a/examples/react/start-basic-static/package.json +++ b/examples/react/start-basic-static/package.json @@ -9,9 +9,9 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/start-basic/package.json b/examples/react/start-basic/package.json index 5c881a9495b..e972b401e22 100644 --- a/examples/react/start-basic/package.json +++ b/examples/react/start-basic/package.json @@ -9,9 +9,9 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "tailwind-merge": "^2.6.0", diff --git a/examples/react/start-clerk-basic/package.json b/examples/react/start-clerk-basic/package.json index 89d45c51803..6a850c81b84 100644 --- a/examples/react/start-clerk-basic/package.json +++ b/examples/react/start-clerk-basic/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@clerk/tanstack-react-start": "0.12.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/start-convex-trellaux/package.json b/examples/react/start-convex-trellaux/package.json index 04990cd0b6a..bd08bb42933 100644 --- a/examples/react/start-convex-trellaux/package.json +++ b/examples/react/start-convex-trellaux/package.json @@ -14,10 +14,10 @@ "@convex-dev/react-query": "0.0.0-alpha.8", "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-with-query": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-with-query": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "concurrently": "^8.2.2", "convex": "^1.19.0", "ky": "^1.7.4", diff --git a/examples/react/start-counter/package.json b/examples/react/start-counter/package.json index 99ca5458902..8a4de9f1a30 100644 --- a/examples/react/start-counter/package.json +++ b/examples/react/start-counter/package.json @@ -9,9 +9,9 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "vinxi": "0.5.3" diff --git a/examples/react/start-large/package.json b/examples/react/start-large/package.json index e92d2dcd7db..79bff0b1f99 100644 --- a/examples/react/start-large/package.json +++ b/examples/react/start-large/package.json @@ -12,9 +12,9 @@ }, "dependencies": { "@tanstack/react-query": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/start-material-ui/package.json b/examples/react/start-material-ui/package.json index 7ebb83d2d26..07f351f2553 100644 --- a/examples/react/start-material-ui/package.json +++ b/examples/react/start-material-ui/package.json @@ -14,9 +14,9 @@ "@emotion/styled": "11.14.0", "@fontsource-variable/roboto": "5.2.5", "@mui/material": "6.4.7", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-start": "^1.116.1", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-start": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "vinxi": "0.5.3", diff --git a/examples/react/start-supabase-basic/package.json b/examples/react/start-supabase-basic/package.json index fa3f0830065..015ee03923a 100644 --- a/examples/react/start-supabase-basic/package.json +++ b/examples/react/start-supabase-basic/package.json @@ -15,9 +15,9 @@ "dependencies": { "@supabase/ssr": "^0.5.2", "@supabase/supabase-js": "^2.48.1", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "vinxi": "0.5.3" diff --git a/examples/react/start-trellaux/package.json b/examples/react/start-trellaux/package.json index a4f24b23b81..ec1b7944026 100644 --- a/examples/react/start-trellaux/package.json +++ b/examples/react/start-trellaux/package.json @@ -11,10 +11,10 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-with-query": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-with-query": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "ky": "^1.7.4", "msw": "^2.7.0", "react": "^19.0.0", diff --git a/examples/react/start-workos/package.json b/examples/react/start-workos/package.json index 0411e0f7f7a..bcdbb6ab767 100644 --- a/examples/react/start-workos/package.json +++ b/examples/react/start-workos/package.json @@ -14,9 +14,9 @@ "license": "ISC", "dependencies": { "@radix-ui/themes": "^3.2.1", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "@workos-inc/node": "^7.45.0", "iron-session": "^8.0.4", "jose": "^6.0.10", diff --git a/examples/react/view-transitions/package.json b/examples/react/view-transitions/package.json index 80e0eec5431..dd28e17433a 100644 --- a/examples/react/view-transitions/package.json +++ b/examples/react/view-transitions/package.json @@ -9,9 +9,9 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/view-transitions/src/main.tsx b/examples/react/view-transitions/src/main.tsx index 0275c31e397..065d69a2cf8 100644 --- a/examples/react/view-transitions/src/main.tsx +++ b/examples/react/view-transitions/src/main.tsx @@ -12,9 +12,32 @@ const router = createRouter({ scrollRestoration: true, /* Using defaultViewTransition would prevent the need to - manually add `viewTransition: true` to every navigation + manually add `viewTransition: true` to every navigation. + + If defaultViewTransition.types is a function, it will be called with the + location change info and should return an array of view transition types. + This is useful if you want to have different view transitions depending on + the navigation's specifics. + + An example use case is sliding in a direction based on the index of the + previous and next routes when navigating via browser history back and forth. */ // defaultViewTransition: true + // OR + // defaultViewTransition: { + // types: ({ fromLocation, toLocation }) => { + // let direction = 'none' + + // if (fromLocation) { + // const fromIndex = fromLocation.state.__TSR_index + // const toIndex = toLocation.state.__TSR_index + + // direction = fromIndex > toIndex ? 'right' : 'left' + // } + + // return [`slide-${direction}`] + // }, + // }, }) // Register things for typesafety diff --git a/examples/react/with-framer-motion/package.json b/examples/react/with-framer-motion/package.json index 68201e26822..e543a73a2a9 100644 --- a/examples/react/with-framer-motion/package.json +++ b/examples/react/with-framer-motion/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", "framer-motion": "^11.18.2", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/examples/react/with-trpc-react-query/package.json b/examples/react/with-trpc-react-query/package.json index 3dfbd17f86e..b93bdbd65c0 100644 --- a/examples/react/with-trpc-react-query/package.json +++ b/examples/react/with-trpc-react-query/package.json @@ -10,10 +10,10 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "@tanstack/react-query-devtools": "^5.66.0", - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "@trpc/client": "11.0.0-rc.772", "@trpc/server": "11.0.0-rc.772", "@trpc/tanstack-react-query": "11.0.0-rc.772", diff --git a/examples/react/with-trpc/package.json b/examples/react/with-trpc/package.json index 87b4257c2a3..52714e560cc 100644 --- a/examples/react/with-trpc/package.json +++ b/examples/react/with-trpc/package.json @@ -8,10 +8,10 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/react-router": "^1.116.0", - "@tanstack/react-router-devtools": "^1.116.0", - "@tanstack/router-plugin": "^1.116.1", - "@tanstack/react-start": "^1.116.1", + "@tanstack/react-router": "^1.120.1", + "@tanstack/react-router-devtools": "^1.120.1", + "@tanstack/router-plugin": "^1.120.1", + "@tanstack/react-start": "^1.120.1", "@trpc/client": "11.0.0-rc.772", "@trpc/server": "11.0.0-rc.772", "react": "^19.0.0", diff --git a/examples/solid/basic-devtools-panel/package.json b/examples/solid/basic-devtools-panel/package.json index 573590a39ec..9f199efa6fe 100644 --- a/examples/solid/basic-devtools-panel/package.json +++ b/examples/solid/basic-devtools-panel/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "solid-js": "^1.9.5", "redaxios": "^0.5.1", "postcss": "^8.5.1", diff --git a/examples/solid/basic-file-based/package.json b/examples/solid/basic-file-based/package.json index 32a39f10fd5..3e8fecb8029 100644 --- a/examples/solid/basic-file-based/package.json +++ b/examples/solid/basic-file-based/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "autoprefixer": "^10.4.20", "postcss": "^8.5.1", "redaxios": "^0.5.1", @@ -19,7 +19,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "typescript": "^5.7.2", "vite": "^6.1.0", "vite-plugin-solid": "^2.11.2" diff --git a/examples/solid/basic-non-nested-devtools/package.json b/examples/solid/basic-non-nested-devtools/package.json index b1696e1e6d6..713a0ed9af7 100644 --- a/examples/solid/basic-non-nested-devtools/package.json +++ b/examples/solid/basic-non-nested-devtools/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "redaxios": "^0.5.1", "postcss": "^8.5.1", "solid-js": "^1.9.5", diff --git a/examples/solid/basic-solid-query-file-based/package.json b/examples/solid/basic-solid-query-file-based/package.json index 842638daf41..ce2dfd6cba0 100644 --- a/examples/solid/basic-solid-query-file-based/package.json +++ b/examples/solid/basic-solid-query-file-based/package.json @@ -12,8 +12,8 @@ "dependencies": { "@tanstack/solid-query": "^5.71.9", "@tanstack/solid-query-devtools": "^5.71.9", - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "solid-js": "^1.9.5", "redaxios": "^0.5.1", "postcss": "^8.5.1", @@ -22,7 +22,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "typescript": "^5.7.2", "vite": "^6.1.0", "vite-plugin-solid": "^2.11.2" diff --git a/examples/solid/basic-solid-query/package.json b/examples/solid/basic-solid-query/package.json index 3114511c579..20d22ed72c8 100644 --- a/examples/solid/basic-solid-query/package.json +++ b/examples/solid/basic-solid-query/package.json @@ -11,8 +11,8 @@ "dependencies": { "@tanstack/solid-query": "^5.71.9", "@tanstack/solid-query-devtools": "^5.71.9", - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "solid-js": "^1.9.5", "redaxios": "^0.5.1", "postcss": "^8.5.1", @@ -20,7 +20,7 @@ "tailwindcss": "^3.4.17" }, "devDependencies": { - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "typescript": "^5.7.2", "vite": "^6.1.0", "vite-plugin-solid": "^2.11.2" diff --git a/examples/solid/basic/package.json b/examples/solid/basic/package.json index 5fb59f2673e..6afc32d1b49 100644 --- a/examples/solid/basic/package.json +++ b/examples/solid/basic/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "redaxios": "^0.5.1", "postcss": "^8.5.1", "solid-js": "^1.9.5", diff --git a/examples/solid/kitchen-sink-file-based/package.json b/examples/solid/kitchen-sink-file-based/package.json index cf5c91a7416..63a8de1643b 100644 --- a/examples/solid/kitchen-sink-file-based/package.json +++ b/examples/solid/kitchen-sink-file-based/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "immer": "^10.1.1", "solid-js": "^1.9.5", "redaxios": "^0.5.1", @@ -20,7 +20,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "typescript": "^5.7.2", "vite": "^6.1.0", "vite-plugin-solid": "^2.11.2" diff --git a/examples/solid/quickstart-file-based/package.json b/examples/solid/quickstart-file-based/package.json index ee55ce5eddc..5909d691bdb 100644 --- a/examples/solid/quickstart-file-based/package.json +++ b/examples/solid/quickstart-file-based/package.json @@ -9,8 +9,8 @@ "start": "vite" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", "autoprefixer": "^10.4.20", "postcss": "^8.5.1", "redaxios": "^0.5.1", @@ -19,7 +19,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.116.1", + "@tanstack/router-plugin": "^1.120.1", "typescript": "^5.7.2", "vite": "^6.1.0", "vite-plugin-solid": "^2.11.2" diff --git a/examples/solid/start-bare/package.json b/examples/solid/start-bare/package.json index b713240e60b..cc62e82a45f 100644 --- a/examples/solid/start-bare/package.json +++ b/examples/solid/start-bare/package.json @@ -9,9 +9,9 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", - "@tanstack/solid-start": "^1.116.1", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", + "@tanstack/solid-start": "^1.120.1", "solid-js": "^1.9.5", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", diff --git a/examples/solid/start-basic/package.json b/examples/solid/start-basic/package.json index d04de861d82..af2f895b6c2 100644 --- a/examples/solid/start-basic/package.json +++ b/examples/solid/start-basic/package.json @@ -9,9 +9,9 @@ "start": "vinxi start" }, "dependencies": { - "@tanstack/solid-router": "^1.116.0", - "@tanstack/solid-router-devtools": "^1.116.0", - "@tanstack/solid-start": "^1.116.1", + "@tanstack/solid-router": "^1.120.1", + "@tanstack/solid-router-devtools": "^1.120.1", + "@tanstack/solid-start": "^1.120.1", "solid-js": "^1.9.5", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", diff --git a/package.json b/package.json index 2e7f0fc7bfa..9ac5606a3a0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "devDependencies": { "@arethetypeswrong/cli": "^0.17.3", "@eslint-react/eslint-plugin": "^1.26.2", - "@playwright/test": "^1.50.1", + "@playwright/test": "^1.52.0", "@tanstack/config": "^0.16.1", "@tanstack/react-query": "5.66.0", "@types/node": "^22.10.2", @@ -48,7 +48,7 @@ "eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-unused-imports": "^4.1.4", "jsdom": "^25.0.1", - "nx": "20.4.2", + "nx": "20.8.1", "prettier": "^3.5.0", "publint": "^0.3.4", "react": "^19.0.0", @@ -76,6 +76,7 @@ "@types/react-dom": "$@types/react-dom", "eslint": "$eslint", "vite": "$vite", + "@playwright/test": "$@playwright/test", "@tanstack/react-query": "5.66.0", "use-sync-external-store": "1.2.2", "@tanstack/history": "workspace:*", diff --git a/packages/arktype-adapter/package.json b/packages/arktype-adapter/package.json index b17e07f1e76..9ba618ece94 100644 --- a/packages/arktype-adapter/package.json +++ b/packages/arktype-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/arktype-adapter", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/create-router/build.config.ts b/packages/create-router/build.config.ts deleted file mode 100644 index e61c91fb608..00000000000 --- a/packages/create-router/build.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineBuildConfig } from 'unbuild' - -export default defineBuildConfig({ - entries: ['src/index'], - clean: true, - rollup: { - inlineDependencies: true, - esbuild: { - target: 'node18', - minify: true, - }, - }, -}) diff --git a/packages/create-router/eslint.config.js b/packages/create-router/eslint.config.js deleted file mode 100644 index 8ce6ad05fcd..00000000000 --- a/packages/create-router/eslint.config.js +++ /dev/null @@ -1,5 +0,0 @@ -// @ts-check - -import rootConfig from '../../eslint.config.js' - -export default [...rootConfig] diff --git a/packages/create-router/index.js b/packages/create-router/index.js deleted file mode 100755 index f5e8e064a68..00000000000 --- a/packages/create-router/index.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node - -import './dist/index.mjs' diff --git a/packages/create-router/package.json b/packages/create-router/package.json deleted file mode 100644 index 625021a2a14..00000000000 --- a/packages/create-router/package.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "name": "@tanstack/create-router", - "version": "1.116.1", - "description": "Modern and scalable routing for React applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/create-router" - }, - "homepage": "https://tanstack.com/router", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "bin": { - "create-router": "index.js" - }, - "scripts": { - "dev": "unbuild --stub", - "clean": "rimraf ./dist && rimraf ./coverage", - "test:eslint": "eslint ./src", - "build": "unbuild" - }, - "type": "module", - "files": [ - "index.js", - "templates", - "dist" - ], - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "dependencies": { - "which": "^5.0.0", - "@inquirer/prompts": "^5.5.0", - "commander": "^12.1.0", - "cross-spawn": "^7.0.6", - "tinyglobby": "^0.2.10", - "picocolors": "^1.1.1", - "validate-npm-package-name": "^6.0.0", - "yocto-spinner": "^0.2.0" - }, - "devDependencies": { - "@types/cross-spawn": "^6.0.6", - "@types/validate-npm-package-name": "^4.0.2", - "@types/which": "^3.0.4", - "unbuild": "^3.3.1" - }, - "peerDependencies": { - "@rsbuild/core": "^1.0.2", - "@rsbuild/plugin-react": "^1.0.1", - "@swc/core": "^1.7.25", - "@tanstack/react-router": "workspace:^", - "@tanstack/router-devtools": "workspace:^", - "@tanstack/router-plugin": "workspace:^", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "@vitejs/plugin-react": "^4.3.2", - "html-webpack-plugin": "^5.6.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "swc-loader": "^0.2.6", - "typescript": "^5.7.2", - "vite": "^6.0.3", - "webpack": "^5.94.0", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.1.0" - }, - "peerDependenciesMeta": { - "@tanstack/react-router": { - "optional": true - }, - "@tanstack/router-devtools": { - "optional": true - }, - "@tanstack/router-plugin": { - "optional": true - }, - "@vitejs/plugin-react": { - "optional": true - }, - "vite": { - "optional": true - }, - "@swc/core": { - "optional": true - }, - "html-webpack-plugin": { - "optional": true - }, - "swc-loader": { - "optional": true - }, - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - }, - "@rsbuild/core": { - "optional": true - }, - "@rsbuild/plugin-react": { - "optional": true - }, - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - }, - "typescript": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } -} diff --git a/packages/create-router/src/bundler/index.ts b/packages/create-router/src/bundler/index.ts deleted file mode 100644 index 78a0946fb4b..00000000000 --- a/packages/create-router/src/bundler/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { apply as applyVite } from './vite' -import { apply as applyRspack } from './rspack' -import { apply as applyWebpack } from './webpack' -import type { Bundler } from '../constants' -import type { ApplyParams } from '../types' - -export function apply(bundler: Bundler, params: ApplyParams) { - switch (bundler) { - case 'vite': - return applyVite(params) - case 'rspack': - return applyRspack(params) - case 'webpack': - return applyWebpack(params) - } -} diff --git a/packages/create-router/src/bundler/rspack.ts b/packages/create-router/src/bundler/rspack.ts deleted file mode 100644 index d596b9cf85b..00000000000 --- a/packages/create-router/src/bundler/rspack.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { copyTemplateFiles } from '../utils/copyTemplateFiles' -import type { ApplyParams, BundlerResult, PeerDependency } from '../types' - -export const scripts = { - dev: 'rsbuild dev --port 3001', - build: 'rsbuild build', - preview: 'rsbuild preview', -} as const - -export const devDependencies = [ - '@rsbuild/core', - '@rsbuild/plugin-react', -] as const satisfies Array - -export async function apply({ - targetFolder, -}: ApplyParams): Promise { - await copyTemplateFiles({ - file: '**/*', - sourceFolder: 'bundler/rspack', - targetFolder, - }) - return { - scripts, - devDependencies, - } -} diff --git a/packages/create-router/src/bundler/vite.ts b/packages/create-router/src/bundler/vite.ts deleted file mode 100644 index b0c4d042daa..00000000000 --- a/packages/create-router/src/bundler/vite.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { copyTemplateFiles } from '../utils/copyTemplateFiles' -import type { ApplyParams, BundlerResult, PeerDependency } from '../types' - -export const scripts = { - dev: 'vite --port=3001', - build: 'vite build', - serve: 'vite preview', - start: 'vite', -} as const - -export const devDependencies = [ - '@vitejs/plugin-react', - 'vite', -] as const satisfies Array - -export async function apply({ - targetFolder, -}: ApplyParams): Promise { - await copyTemplateFiles({ - file: '**/*', - sourceFolder: 'bundler/vite', - targetFolder, - }) - return { - scripts, - devDependencies, - } -} diff --git a/packages/create-router/src/bundler/webpack.ts b/packages/create-router/src/bundler/webpack.ts deleted file mode 100644 index 2e6d198e257..00000000000 --- a/packages/create-router/src/bundler/webpack.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { copyTemplateFiles } from '../utils/copyTemplateFiles' -import type { ApplyParams, BundlerResult, PeerDependency } from '../types' - -export const scripts = { - dev: 'webpack serve --port 3001 --no-open', - build: 'webpack build', -} as const - -export const devDependencies = [ - '@swc/core', - 'html-webpack-plugin', - 'swc-loader', - 'webpack', - 'webpack-cli', - 'webpack-dev-server', -] as const satisfies Array - -export async function apply({ - targetFolder, -}: ApplyParams): Promise { - await copyTemplateFiles({ - file: '**/*', - sourceFolder: 'bundler/webpack', - targetFolder, - }) - return { - scripts, - devDependencies, - } -} diff --git a/packages/create-router/src/cli.ts b/packages/create-router/src/cli.ts deleted file mode 100644 index 03c9be227f3..00000000000 --- a/packages/create-router/src/cli.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { basename, resolve } from 'node:path' -import { Command, InvalidArgumentError } from 'commander' -import { - NAME, - SUPPORTED_BUNDLERS, - SUPPORTED_IDES, - SUPPORTED_PACKAGE_MANAGERS, -} from './constants' -import { validateProjectName } from './utils/validateProjectName' -import { getPackageManager } from './utils/getPackageManager' -import { packageJson } from './utils/packageJson' -import type { Bundler, Ide, PackageManager } from './constants' - -let directory: string | undefined - -export const command = new Command(NAME) - .version( - packageJson.version, - '-v, --version', - `Output the current version of ${NAME}.`, - ) - .argument('[directory]') - .usage('[directory] [options]') - .helpOption('-h, --help', 'Display this help message.') - .option( - `--package-manager <${SUPPORTED_PACKAGE_MANAGERS.join('|')}>`, - `Explicitly tell the CLI to use this package manager`, - (value) => { - if (!SUPPORTED_PACKAGE_MANAGERS.includes(value as PackageManager)) { - throw new InvalidArgumentError( - `Invalid package manager: ${value}. Only the following are allowed: ${SUPPORTED_PACKAGE_MANAGERS.join(', ')}`, - ) - } - return value as PackageManager - }, - getPackageManager(), - ) - .option( - `--bundler <${SUPPORTED_BUNDLERS.join('|')}>`, - `use this bundler (${SUPPORTED_BUNDLERS.join(', ')})`, - (value) => { - if (!SUPPORTED_BUNDLERS.includes(value as Bundler)) { - throw new InvalidArgumentError( - `Invalid bundler: ${value}. Only the following are allowed: ${SUPPORTED_BUNDLERS.join(', ')}`, - ) - } - return value as Bundler - }, - ) - .option( - `--ide <${SUPPORTED_IDES.join('|')}>`, - `use this IDE (${SUPPORTED_IDES.join(', ')})`, - (value) => { - if (!SUPPORTED_IDES.includes(value as Ide)) { - throw new InvalidArgumentError( - `Invalid IDE: ${value}. Only the following are allowed: ${SUPPORTED_IDES.join(', ')}`, - ) - } - return value as Ide - }, - ) - .option( - '--open-project', - 'Open the generated project in the IDE after creation. This requires option --ide to be set.', - false, - ) - .option( - '--skip-install', - 'Explicitly tell the CLI to skip installing packages.', - false, - ) - .option( - '--skip-build', - 'Explicitly tell the CLI to skip building the newly generated project.', - false, - ) - .action((name) => { - if (typeof name === 'string') { - name = name.trim() - } - if (name) { - const validation = validateProjectName(basename(resolve(name))) - if (!validation.valid) { - throw new InvalidArgumentError( - `Invalid project name: ${validation.problems[0]}`, - ) - } - directory = name - } - }) - .parse() - -const options = command.opts<{ - packageManager: PackageManager | undefined - bundler: Bundler | undefined - ide: Ide | undefined - skipInstall: boolean - skipBuild: boolean - openProject: boolean -}>() - -export const cli = { options, args: command.args, directory } diff --git a/packages/create-router/src/constants.ts b/packages/create-router/src/constants.ts deleted file mode 100644 index 5691d33bdb5..00000000000 --- a/packages/create-router/src/constants.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { fileURLToPath } from 'node:url' -import { resolve } from 'node:path' - -export const TEMPLATES_FOLDER = resolve( - fileURLToPath(import.meta.url), - '../../templates', -) -export const NAME = 'create-router' - -export const SUPPORTED_PACKAGE_MANAGERS = [ - 'npm', - 'yarn', - 'pnpm', - 'bun', -] as const -export type PackageManager = (typeof SUPPORTED_PACKAGE_MANAGERS)[number] -export const DEFAULT_PACKAGE_MANAGER: PackageManager = 'npm' - -export const SUPPORTED_BUNDLERS = ['vite', 'webpack', 'rspack'] as const -export type Bundler = (typeof SUPPORTED_BUNDLERS)[number] -export const DEFAULT_BUNDLER: Bundler = 'vite' - -export const SUPPORTED_IDES = ['vscode', 'cursor', 'other'] as const -export type Ide = (typeof SUPPORTED_IDES)[number] -export const DEFAULT_IDE: Ide = 'vscode' diff --git a/packages/create-router/src/core.ts b/packages/create-router/src/core.ts deleted file mode 100644 index 2ac98d9c0f4..00000000000 --- a/packages/create-router/src/core.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { copyTemplateFiles } from './utils/copyTemplateFiles' -import type { ApplyParams, PeerDependency } from './types' - -export const dependencies = [ - '@tanstack/react-router', - '@tanstack/router-devtools', - 'react', - 'react-dom', -] as const satisfies Array -export const devDependencies = [ - '@types/react', - '@types/react-dom', - '@tanstack/router-plugin', -] as const satisfies Array - -export const scripts = { - typecheck: 'tsc --noEmit', -} - -export async function apply({ targetFolder }: ApplyParams) { - await copyTemplateFiles({ file: '**/*', sourceFolder: 'core', targetFolder }) - return { - dependencies, - devDependencies, - scripts, - } -} diff --git a/packages/create-router/src/create.ts b/packages/create-router/src/create.ts deleted file mode 100644 index f7b99f00eda..00000000000 --- a/packages/create-router/src/create.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { mkdir } from 'node:fs/promises' -import yoctoSpinner from 'yocto-spinner' -import colors from 'picocolors' -import { apply as applyCore } from './core' -import { apply as applyBundler } from './bundler' -import { apply as applyIde } from './ide' -import { openProject as openProjectImpl } from './ide/openProject' -import { getDependenciesWithVersion } from './utils/getPeerDependencyVersion' -import { writeTemplateFile } from './utils/writeTemplateFile' -import { build, install } from './utils/runPackageManagerCommand' -import type { Bundler, Ide, PackageManager } from './constants' -import type { PeerDependency } from './types' - -interface GeneratePackageJsonParams { - name: string - scripts: Record - devDependencies: Array - dependencies: Array - overrides?: Partial< - Record>> - > -} -function generatePackageJson({ - name, - scripts, - dependencies, - devDependencies, - overrides, -}: GeneratePackageJsonParams) { - return { - name, - version: '0.0.0', - private: true, - type: 'module', - scripts, - devDependencies: getDependenciesWithVersion(devDependencies), - dependencies: getDependenciesWithVersion(dependencies), - overrides, - } -} - -export interface CreateParams { - targetFolder: string - projectName: string - skipInstall: boolean - skipBuild: boolean - bundler: Bundler - packageManager: PackageManager - ide: Ide - openProject: boolean -} -export async function create({ - targetFolder, - projectName, - skipInstall, - skipBuild, - bundler, - packageManager, - ide, - openProject, -}: CreateParams) { - const originalCwd = process.cwd() - await mkdir(targetFolder, { recursive: true }) - process.chdir(targetFolder) - - const coreResult = await applyCore({ targetFolder }) - const bundlerResult = await applyBundler(bundler, { targetFolder }) - await applyIde(ide, { targetFolder }) - - const packageJson = generatePackageJson({ - name: projectName, - scripts: { ...coreResult.scripts, ...bundlerResult.scripts }, - dependencies: coreResult.dependencies, - devDependencies: [ - ...coreResult.devDependencies, - ...bundlerResult.devDependencies, - ], - overrides: bundlerResult.overrides, - }) - - await writeTemplateFile('package.json', targetFolder, packageJson) - - if (!skipInstall) { - const installSpinner = yoctoSpinner({ - text: 'installing dependencies', - }).start() - try { - await install(packageManager) - installSpinner.success('dependencies installed') - } catch (e) { - console.error(e) - installSpinner.error('failed to install dependencies') - process.exit(1) - } - } - - if (!skipInstall && !skipBuild) { - const buildSpinner = yoctoSpinner({ text: 'building project' }).start() - try { - await build(packageManager) - buildSpinner.success('project built') - console.log( - `${colors.green('Success')} Created ${projectName} at ${targetFolder}`, - ) - } catch (e) { - console.error(e) - buildSpinner.error('failed to build project') - process.exit(1) - } - } - - console.log() - if (openProject) { - console.log(`opening ${projectName} in ${ide}`) - console.log() - console.log(`start the development server in a terminal in ${ide} via:`) - console.log(colors.cyan(` ${packageManager} run dev`)) - console.log() - await openProjectImpl({ projectPath: targetFolder, ide }) - } else { - const needsCd = originalCwd !== targetFolder - if (needsCd) { - console.log('now go to your project using:') - console.log(colors.cyan(` cd ${targetFolder}`)) - console.log() - } - console.log(`${needsCd ? 'then ' : ''}start the development server via:`) - console.log(colors.cyan(` ${packageManager} run dev`)) - console.log() - } -} diff --git a/packages/create-router/src/ide/getIdeCommand.ts b/packages/create-router/src/ide/getIdeCommand.ts deleted file mode 100644 index bba018c6251..00000000000 --- a/packages/create-router/src/ide/getIdeCommand.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Ide } from '../constants' - -export function getIdeCommand(ide: Ide) { - switch (ide) { - case 'vscode': - return 'code' - case 'cursor': - return 'cursor' - case 'other': - return - } -} diff --git a/packages/create-router/src/ide/index.ts b/packages/create-router/src/ide/index.ts deleted file mode 100644 index 01cde1f507a..00000000000 --- a/packages/create-router/src/ide/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { apply as applyVsCode } from './vscode' -import type { Ide } from '../constants' -import type { ApplyParams } from '../types' - -export function apply(ide: Ide, params: ApplyParams) { - switch (ide) { - case 'vscode': - case 'cursor': - return applyVsCode(params) - case 'other': - return - } -} - -export function openProject(ide: Ide, params: ApplyParams) { - switch (ide) { - case 'vscode': - case 'cursor': // since cursor is a fork of vscode, we can use the same implementation - return applyVsCode(params) - case 'other': - return - } -} diff --git a/packages/create-router/src/ide/openProject.ts b/packages/create-router/src/ide/openProject.ts deleted file mode 100644 index 6df64c185cb..00000000000 --- a/packages/create-router/src/ide/openProject.ts +++ /dev/null @@ -1,23 +0,0 @@ -import which from 'which' -import spawn from 'cross-spawn' -import { getIdeCommand } from './getIdeCommand' -import type { Ide } from '../constants' - -export interface OpenProjectParams { - projectPath: string - ide: Ide -} -export async function openProject({ ide, projectPath }: OpenProjectParams) { - const command = getIdeCommand(ide) - if (command === undefined) { - return - } - try { - const resolved = await which(command) - spawn(resolved, [projectPath], { detached: true }) - } catch (error) { - console.error( - `Could not open project using ${ide}, since ${command} was not in your PATH`, - ) - } -} diff --git a/packages/create-router/src/ide/vscode.ts b/packages/create-router/src/ide/vscode.ts deleted file mode 100644 index cf16b003c42..00000000000 --- a/packages/create-router/src/ide/vscode.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { copyTemplateFiles } from '../utils/copyTemplateFiles' -import type { ApplyParams } from '../types' - -export async function apply({ targetFolder }: ApplyParams): Promise { - await copyTemplateFiles({ - file: '**/*', - sourceFolder: 'ide/vscode', - targetFolder, - }) -} diff --git a/packages/create-router/src/index.ts b/packages/create-router/src/index.ts deleted file mode 100644 index 2df759e44ff..00000000000 --- a/packages/create-router/src/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { basename, resolve } from 'node:path' -import { existsSync } from 'node:fs' - -import { confirm, input, select } from '@inquirer/prompts' -import { cli } from './cli' -import { - DEFAULT_BUNDLER, - DEFAULT_IDE, - DEFAULT_PACKAGE_MANAGER, - SUPPORTED_BUNDLERS, - SUPPORTED_IDES, - SUPPORTED_PACKAGE_MANAGERS, -} from './constants' -import { validateProjectName } from './utils/validateProjectName' -import { create } from './create' -import { isEmptyDirectory } from './utils/isEmptyDirectory' - -async function main() { - // project cannot be built if packages are not installed - if (cli.options.skipInstall === true) { - cli.options.skipInstall = true - } - - if (!cli.options.packageManager) { - cli.options.packageManager = await select({ - message: 'Select a package manager', - choices: SUPPORTED_PACKAGE_MANAGERS.map((pm) => ({ value: pm })), - default: DEFAULT_PACKAGE_MANAGER, - }) - } - - if (!cli.directory) { - cli.directory = await input({ - message: 'Enter the project name', - default: 'my-router-app', - validate: (name) => { - const validation = validateProjectName(basename(resolve(name))) - if (validation.valid) { - return true - } - return 'Invalid project name: ' + validation.problems[0] - }, - }) - } - - do { - if (!cli.options.bundler) { - cli.options.bundler = await select({ - message: 'Select a bundler', - choices: SUPPORTED_BUNDLERS.map((bundler) => ({ value: bundler })), - default: DEFAULT_BUNDLER, - }) - } - - if (cli.options.bundler !== 'vite') { - const bundlerConfirmed = await confirm({ - message: - 'Are you sure you want to use this bundler? If you ever choose to adopt full-stack features with Start, Vite is currently required. Proceed anyway?', - }) - if (!bundlerConfirmed) { - cli.options.bundler = undefined - } - } - } while (cli.options.bundler === undefined) - - if (!cli.options.ide) { - cli.options.ide = await select({ - message: 'Select an IDE', - choices: SUPPORTED_IDES.map((ide) => ({ value: ide })), - default: DEFAULT_IDE, - }) - } - - if (cli.options.ide === 'other') { - cli.options.openProject = false - } else { - cli.options.openProject = await confirm({ - message: `Open the generated project using ${cli.options.ide} after creation?`, - default: true, - }) - } - const targetFolder = resolve(cli.directory) - const projectName = basename(targetFolder) - - if (existsSync(targetFolder) && !(await isEmptyDirectory(targetFolder))) { - const dir = - cli.directory === '.' - ? 'Current directory' - : `Target directory "${targetFolder}"` - const message = `${dir} is not empty. Please choose how to proceed:` - const action = await select({ - message, - choices: [ - { name: 'Cancel', value: 'cancel' }, - { name: 'Ignore files and continue', value: 'ignore' }, - ], - }) - if (action === 'cancel') { - process.exit(1) - } - } - - await create({ - targetFolder, - projectName, - skipInstall: cli.options.skipInstall, - skipBuild: cli.options.skipBuild, - packageManager: cli.options.packageManager, - bundler: cli.options.bundler, - ide: cli.options.ide, - openProject: cli.options.openProject, - }) -} - -main().catch(console.error) diff --git a/packages/create-router/src/types.ts b/packages/create-router/src/types.ts deleted file mode 100644 index 5cc66170c85..00000000000 --- a/packages/create-router/src/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type packageJson from '../package.json' - -export interface ApplyParams { - targetFolder: string -} - -export type PeerDependency = keyof typeof packageJson.peerDependencies - -export interface BundlerResult { - scripts: Record - devDependencies: Array - dependencies?: Array - overrides?: Partial>>> -} diff --git a/packages/create-router/src/utils/copyTemplateFiles.ts b/packages/create-router/src/utils/copyTemplateFiles.ts deleted file mode 100644 index b557a034033..00000000000 --- a/packages/create-router/src/utils/copyTemplateFiles.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { copyFile, mkdir, readdir, stat } from 'node:fs/promises' -import { resolve } from 'node:path' -import { glob } from 'tinyglobby' -import { TEMPLATES_FOLDER } from '../constants' - -/** - * all files prefixed with `_dot_` will be copied over to the created project with a `.` instead of the `_dot_` - */ -const DOT_PREFIX = '_dot_' - -interface CopyTemplateFilesParams { - file: string - sourceFolder: string - targetFolder: string -} -export async function copyTemplateFiles({ - file, - sourceFolder, - targetFolder, -}: CopyTemplateFilesParams) { - const files = await glob(file, { - cwd: resolve(TEMPLATES_FOLDER, sourceFolder), - onlyFiles: false, - }) - - for (const file of files) { - await copy( - resolve(TEMPLATES_FOLDER, sourceFolder, file), - resolve(targetFolder, file), - ) - } -} - -async function copyDir(srcDir: string, destDir: string) { - await mkdir(destDir, { recursive: true }) - const files = await readdir(srcDir) - for (const file of files) { - const srcFile = resolve(srcDir, file) - const destFile = resolve(destDir, file) - await copy(srcFile, destFile) - } -} - -async function copy(src: string, dest: string) { - const statResult = await stat(src) - const replacedDest = dest.replace(DOT_PREFIX, '.') - if (statResult.isDirectory()) { - await copyDir(src, replacedDest) - } else { - await copyFile(src, replacedDest) - } -} diff --git a/packages/create-router/src/utils/getPackageManager.ts b/packages/create-router/src/utils/getPackageManager.ts deleted file mode 100644 index 4bcb7b8032c..00000000000 --- a/packages/create-router/src/utils/getPackageManager.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SUPPORTED_PACKAGE_MANAGERS } from '../constants' -import type { PackageManager } from '../constants' - -export function getPackageManager(): PackageManager | undefined { - const userAgent = process.env.npm_config_user_agent - - if (userAgent === undefined) { - return undefined - } - - const packageManager = SUPPORTED_PACKAGE_MANAGERS.find((manager) => - userAgent.startsWith(manager), - ) - - return packageManager -} diff --git a/packages/create-router/src/utils/getPeerDependencyVersion.ts b/packages/create-router/src/utils/getPeerDependencyVersion.ts deleted file mode 100644 index b215cdb4b90..00000000000 --- a/packages/create-router/src/utils/getPeerDependencyVersion.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { packageJson } from './packageJson' -import type { PeerDependency } from '../types' - -export function getDependenciesWithVersion(deps: Array) { - return deps.reduce( - (acc, dep) => { - acc[dep] = packageJson.peerDependencies[dep] - return acc - }, - {} as Record, - ) -} diff --git a/packages/create-router/src/utils/isEmptyDirectory.ts b/packages/create-router/src/utils/isEmptyDirectory.ts deleted file mode 100644 index b317f645b71..00000000000 --- a/packages/create-router/src/utils/isEmptyDirectory.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { readdir } from 'node:fs/promises' - -export async function isEmptyDirectory(path: string) { - const files = await readdir(path) - return files.length === 0 || (files.length === 1 && files[0] === '.git') -} diff --git a/packages/create-router/src/utils/packageJson.ts b/packages/create-router/src/utils/packageJson.ts deleted file mode 100644 index 4522a1edae8..00000000000 --- a/packages/create-router/src/utils/packageJson.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { readFile } from 'node:fs/promises' -import { resolve } from 'node:path' -import { fileURLToPath } from 'node:url' - -async function readPackageJson() { - const PACKAGE_JSON_FILE = resolve( - fileURLToPath(import.meta.url), - '../../package.json', - ) - const packageJson = await readFile(PACKAGE_JSON_FILE, 'utf-8') - return JSON.parse(packageJson) -} - -export const packageJson = await readPackageJson() diff --git a/packages/create-router/src/utils/runPackageManagerCommand.ts b/packages/create-router/src/utils/runPackageManagerCommand.ts deleted file mode 100644 index 89382fe99f7..00000000000 --- a/packages/create-router/src/utils/runPackageManagerCommand.ts +++ /dev/null @@ -1,48 +0,0 @@ -import spawn from 'cross-spawn' -import type { PackageManager } from '../constants' - -export async function runPackageManagerCommand( - packageManager: PackageManager, - args: Array, - env: NodeJS.ProcessEnv = {}, -) { - return new Promise((resolve, reject) => { - const child = spawn(packageManager, args, { - env: { - ...process.env, - ...env, - }, - stdio: ['pipe', 'pipe', 'pipe'], - }) - let stderrBuffer = '' - let stdoutBuffer = '' - - child.stderr?.on('data', (data) => { - stderrBuffer += data - }) - - child.stdout?.on('data', (data) => { - stdoutBuffer += data - }) - - child.on('close', (code) => { - if (code !== 0) { - reject( - `"${packageManager} ${args.join(' ')}" failed ${stdoutBuffer} ${stderrBuffer}`, - ) - return - } - resolve() - }) - }) -} - -export async function install(packageManager: PackageManager) { - return runPackageManagerCommand(packageManager, ['install'], { - NODE_ENV: 'development', - }) -} - -export async function build(packageManager: PackageManager) { - return runPackageManagerCommand(packageManager, ['run', 'build']) -} diff --git a/packages/create-router/src/utils/validateProjectName.ts b/packages/create-router/src/utils/validateProjectName.ts deleted file mode 100644 index dc1366ab4ac..00000000000 --- a/packages/create-router/src/utils/validateProjectName.ts +++ /dev/null @@ -1,25 +0,0 @@ -import validate from 'validate-npm-package-name' - -type ValidatationResult = - | { - valid: true - } - | { - valid: false - problems: Array - } - -export function validateProjectName(name: string): ValidatationResult { - const nameValidation = validate(name) - if (nameValidation.validForNewPackages) { - return { valid: true } - } - - return { - valid: false, - problems: [ - ...(nameValidation.errors || []), - ...(nameValidation.warnings || []), - ], - } -} diff --git a/packages/create-router/src/utils/writeTemplateFile.ts b/packages/create-router/src/utils/writeTemplateFile.ts deleted file mode 100644 index 44ab7840a31..00000000000 --- a/packages/create-router/src/utils/writeTemplateFile.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { resolve } from 'node:path' -import { writeFile } from 'node:fs/promises' - -export async function writeTemplateFile( - file: string, - targetFolder: string, - content: unknown, -) { - const targetPath = resolve(targetFolder, file) - let contentToWrite: string - if (typeof content === 'string') { - contentToWrite = content - } else { - contentToWrite = JSON.stringify(content, null, 2) - } - await writeFile(targetPath, contentToWrite) -} diff --git a/packages/create-router/templates/bundler/rspack/index.html b/packages/create-router/templates/bundler/rspack/index.html deleted file mode 100644 index f855293b649..00000000000 --- a/packages/create-router/templates/bundler/rspack/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - TanStack Router - - - - -
- - diff --git a/packages/create-router/templates/bundler/rspack/rsbuild.config.ts b/packages/create-router/templates/bundler/rspack/rsbuild.config.ts deleted file mode 100644 index 101af08a4ae..00000000000 --- a/packages/create-router/templates/bundler/rspack/rsbuild.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { defineConfig } from '@rsbuild/core' -import { pluginReact } from '@rsbuild/plugin-react' -import { TanStackRouterRspack } from '@tanstack/router-plugin/rspack' - -export default defineConfig({ - plugins: [pluginReact()], - source: { - entry: { index: './src/main.tsx' }, - }, - html: { - template: './index.html', - }, - tools: { - rspack: { - plugins: [ - TanStackRouterRspack({ - target: 'react', - autoCodeSplitting: true, - }), - ], - }, - }, -}) diff --git a/packages/create-router/templates/bundler/vite/index.html b/packages/create-router/templates/bundler/vite/index.html deleted file mode 100644 index 9367b8892a7..00000000000 --- a/packages/create-router/templates/bundler/vite/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - TanStack Router - - - - - -
- - - diff --git a/packages/create-router/templates/bundler/vite/vite.config.ts b/packages/create-router/templates/bundler/vite/vite.config.ts deleted file mode 100644 index f22a7fa76f3..00000000000 --- a/packages/create-router/templates/bundler/vite/vite.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' -import { TanStackRouterVite } from '@tanstack/router-plugin/vite' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [ - TanStackRouterVite({ - target: 'react', - autoCodeSplitting: true, - }), - react(), - ], -}) diff --git a/packages/create-router/templates/bundler/webpack/_dot_swcrc b/packages/create-router/templates/bundler/webpack/_dot_swcrc deleted file mode 100644 index 16ef25594c7..00000000000 --- a/packages/create-router/templates/bundler/webpack/_dot_swcrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://swc.rs/schema.json", - "jsc": { - "target": "es2015", - "parser": { - "syntax": "typescript", - "tsx": true - }, - "transform": { - "react": { - "runtime": "automatic" - } - } - } -} diff --git a/packages/create-router/templates/bundler/webpack/index.html b/packages/create-router/templates/bundler/webpack/index.html deleted file mode 100644 index f855293b649..00000000000 --- a/packages/create-router/templates/bundler/webpack/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - TanStack Router - - - - -
- - diff --git a/packages/create-router/templates/bundler/webpack/webpack.config.js b/packages/create-router/templates/bundler/webpack/webpack.config.js deleted file mode 100644 index 70f873b0cd5..00000000000 --- a/packages/create-router/templates/bundler/webpack/webpack.config.js +++ /dev/null @@ -1,48 +0,0 @@ -import path from 'path' -import { fileURLToPath } from 'url' -import HtmlWebpackPlugin from 'html-webpack-plugin' -import { TanStackRouterWebpack } from '@tanstack/router-plugin/webpack' - -const __dirname = fileURLToPath(new URL('.', import.meta.url)) - -/** @type import('webpack').Configuration */ -export default ({ WEBPACK_SERVE }) => ({ - target: 'web', - mode: WEBPACK_SERVE ? 'development' : 'production', - entry: path.resolve(__dirname, './src/main.tsx'), - output: { - path: path.resolve(__dirname, './dist'), - filename: '[name].bundle.js', - publicPath: '/', - }, - resolve: { - extensions: ['.ts', '.tsx', '.js', '.jsx'], - }, - plugins: [ - new HtmlWebpackPlugin({ - template: path.resolve(__dirname, './index.html'), - filename: 'index.html', - }), - TanStackRouterWebpack({ - target: 'react', - autoCodeSplitting: true, - }), - ], - module: { - rules: [ - { - test: /\.tsx?$/, - exclude: /(node_modules)/, - use: { loader: 'swc-loader' }, - }, - ], - }, - devServer: { - open: true, - hot: true, - historyApiFallback: { - rewrites: [{ from: /./, to: '/index.html' }], - }, - static: ['public'], - }, -}) diff --git a/packages/create-router/templates/core/_dot_gitignore b/packages/create-router/templates/core/_dot_gitignore deleted file mode 100644 index ed335a7bdc1..00000000000 --- a/packages/create-router/templates/core/_dot_gitignore +++ /dev/null @@ -1,18 +0,0 @@ -# Local -.DS_Store -*.local -*.log* - -# Dist -node_modules -dist/ -.vinxi -.output -.vercel -.netlify -.wrangler - -# IDE -.vscode/* -!.vscode/extensions.json -.idea diff --git a/packages/create-router/templates/core/src/main.tsx b/packages/create-router/templates/core/src/main.tsx deleted file mode 100644 index 489ebafacf4..00000000000 --- a/packages/create-router/templates/core/src/main.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import { RouterProvider, createRouter } from '@tanstack/react-router' -import { routeTree } from './routeTree.gen' - -// Set up a Router instance -const router = createRouter({ - routeTree, - defaultPreload: 'intent', -}) - -// Register things for typesafety -declare module '@tanstack/react-router' { - interface Register { - router: typeof router - } -} - -const rootElement = document.getElementById('app')! - -if (!rootElement.innerHTML) { - const root = ReactDOM.createRoot(rootElement) - root.render() -} diff --git a/packages/create-router/templates/core/src/routes/__root.tsx b/packages/create-router/templates/core/src/routes/__root.tsx deleted file mode 100644 index 8896176e24e..00000000000 --- a/packages/create-router/templates/core/src/routes/__root.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import * as React from 'react' -import { Link, Outlet, createRootRoute } from '@tanstack/react-router' -import { TanStackRouterDevtools } from '@tanstack/router-devtools' - -export const Route = createRootRoute({ - component: RootComponent, -}) - -function RootComponent() { - return ( - <> -
- - Home - {' '} - - About - -
-
- - - - ) -} diff --git a/packages/create-router/templates/core/src/routes/about.tsx b/packages/create-router/templates/core/src/routes/about.tsx deleted file mode 100644 index 492e6b85c25..00000000000 --- a/packages/create-router/templates/core/src/routes/about.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react' -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/about')({ - component: AboutComponent, -}) - -function AboutComponent() { - return ( -
-

About

-
- ) -} diff --git a/packages/create-router/templates/core/src/routes/index.tsx b/packages/create-router/templates/core/src/routes/index.tsx deleted file mode 100644 index c4588fb2c9c..00000000000 --- a/packages/create-router/templates/core/src/routes/index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import * as React from 'react' -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/')({ - component: HomeComponent, -}) - -function HomeComponent() { - return ( -
-

Welcome Home!

-
- ) -} diff --git a/packages/create-router/templates/core/tsconfig.json b/packages/create-router/templates/core/tsconfig.json deleted file mode 100644 index 2bb4932999a..00000000000 --- a/packages/create-router/templates/core/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "esModuleInterop": true, - "jsx": "react-jsx", - "target": "ESNext", - "module": "ESNext", - "moduleResolution": "Bundler", - "skipLibCheck": true - } -} diff --git a/packages/create-router/templates/ide/vscode/_dot_vscode/settings.json b/packages/create-router/templates/ide/vscode/_dot_vscode/settings.json deleted file mode 100644 index 00b5278e580..00000000000 --- a/packages/create-router/templates/ide/vscode/_dot_vscode/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "files.watcherExclude": { - "**/routeTree.gen.ts": true - }, - "search.exclude": { - "**/routeTree.gen.ts": true - }, - "files.readonlyInclude": { - "**/routeTree.gen.ts": true - } -} diff --git a/packages/create-router/tsconfig.json b/packages/create-router/tsconfig.json deleted file mode 100644 index aa15ad99251..00000000000 --- a/packages/create-router/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "jsx": "react-jsx", - "target": "ESNext", - "module": "ESNext" - }, - "moduleResolution": "Bundler", - "include": ["src", "tests", "build.config.ts"] -} diff --git a/packages/create-start/.gitignore b/packages/create-start/.gitignore deleted file mode 100644 index cab449e0176..00000000000 --- a/packages/create-start/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -test-results -dist -node_modules \ No newline at end of file diff --git a/packages/create-start/README.md b/packages/create-start/README.md deleted file mode 100644 index 8bf853f57fd..00000000000 --- a/packages/create-start/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# @tanstack/create-start - -CLI tool for creating and modifying TanStack Start projects. - -``` -pnpm create @tanstack/start -``` - -Run - -``` -pnpm create @tanstack/start --help -``` - -to see all options. - -Until peer dependency issues are worked out, `npm create @tanstack/start` doesn't work. - -Use pnpm or maybe a bundled version could be published instead. - -# Contributing - -## Modules - -Modules represent templates and functionality that can be added later to a TanStack Start project. A module is created using a chain of methods specifying callbacks which receives arguments from the previous step. - -- `createModule(schema)`: Set the schema of values that will be passed in from command line options. - -- `.init((configFromSchema) => { ... })`: Crawl the filesystem to infer configuration, for example detecting the current package manager - -- `.prompt((configFromInit) => { ... })`: Prompt the user for configuration, skipping config that has already been specified. - -- `.validateAndApply({ validate, apply })` - - - `validate({ cfg, targetPath })`: check if preconditions met (is there a package.json? is a library already installed?) and return an array of strings that are issues to address - - - `apply({ cfg, targetPath })`: modify the filesystem: install libraries, modify files diff --git a/packages/create-start/build.config.ts b/packages/create-start/build.config.ts deleted file mode 100644 index 1cf3d4a9594..00000000000 --- a/packages/create-start/build.config.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { defineBuildConfig } from 'unbuild' - -// Separeate config required for dev because mkdist + cli-entry doesn't work -// with stub. It will create a .d.ts and .mjs file in the src folder -const dev = defineBuildConfig({ - entries: ['src/cli-entry'], - outDir: 'dist', - clean: true, - declaration: true, - rollup: { - inlineDependencies: true, - esbuild: { - target: 'node18', - minify: false, - }, - }, -}) - -const prod = defineBuildConfig({ - entries: [ - { - builder: 'mkdist', - cleanDist: true, - input: './src/', - pattern: ['**/*.{ts,tsx}', '!**/template/**'], - }, - ], - outDir: 'dist', - clean: true, - declaration: true, - rollup: { - inlineDependencies: true, - esbuild: { - target: 'node18', - minify: false, - }, - }, -}) - -const config = process.env.BUILD_ENV === 'production' ? prod : dev -export default config diff --git a/packages/create-start/copyTemplates.mjs b/packages/create-start/copyTemplates.mjs deleted file mode 100644 index 1eb3915fade..00000000000 --- a/packages/create-start/copyTemplates.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import fs from 'node:fs/promises' -import path from 'node:path' -import fg from 'fast-glob' -import url from 'node:url' - -const __filename = url.fileURLToPath(import.meta.url) -const __dirname = path.dirname(__filename) - -async function copyTemplates() { - const templates = await fg('**/template/**', { - cwd: path.join(__dirname, 'src'), - onlyFiles: false, - }) - - for (const template of templates) { - const src = path.join(__dirname, 'src', template) - const dest = path.join(__dirname, 'dist', template) - - await fs.mkdir(path.dirname(dest), { recursive: true }) - await fs.cp(src, dest, { recursive: true }) - } -} - -copyTemplates().catch(console.error) diff --git a/packages/create-start/eslint.config.js b/packages/create-start/eslint.config.js deleted file mode 100644 index c12a3bebe03..00000000000 --- a/packages/create-start/eslint.config.js +++ /dev/null @@ -1,18 +0,0 @@ -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - files: ['src/templates/**/template/**/*', 'src/modules/**/template/**/*'], - rules: { - '@typescript-eslint/ban-ts-comment': [ - 'error', - { - 'ts-nocheck': false, - }, - ], - '@typescript-eslint/array-type': 'off', - '@typescript-eslint/require-await': 'off', - }, - }, -] diff --git a/packages/create-start/index.js b/packages/create-start/index.js deleted file mode 100755 index 9dd6223fc96..00000000000 --- a/packages/create-start/index.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node - -import './dist/cli-entry.mjs' diff --git a/packages/create-start/package.json b/packages/create-start/package.json deleted file mode 100644 index 4a2eaa0e7a3..00000000000 --- a/packages/create-start/package.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "name": "@tanstack/create-start", - "version": "1.116.1", - "description": "Modern and scalable routing for React applications", - "author": "Tim O'Connell", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/create-router" - }, - "homepage": "https://tanstack.com/router", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "bin": { - "create-start": "index.js" - }, - "scripts": { - "dev": "BUILD_ENV=development unbuild --stub --watch", - "clean": "rimraf ./dist && rimraf ./coverage", - "test:eslint": "eslint ./src", - "generate-templates": "node ./dist/generate-templates/index.mjs", - "build": "BUILD_ENV=production unbuild && node ./copyTemplates.mjs", - "test": "vitest run", - "test:watch": "vitest watch", - "test:coverage": "vitest run --coverage" - }, - "type": "module", - "files": [ - "index.js", - "templates", - "dist" - ], - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "exports": { - ".": { - "import": "./src/index.ts" - } - }, - "dependencies": { - "gradient-string": "^3.0.0", - "@commander-js/extra-typings": "^12.1.0", - "commander": "^12.1.0", - "@inquirer/prompts": "^5.5.0", - "cross-spawn": "^7.0.6", - "fast-glob": "^3.3.3", - "picocolors": "^1.1.1", - "rollup-plugin-copy": "^3.5.0", - "tempy": "^3.1.0", - "tiny-invariant": "^1.3.3", - "validate-npm-package-name": "^6.0.0", - "yocto-spinner": "^0.2.0", - "zod": "^3.24.2" - }, - "devDependencies": { - "@inquirer/type": "^3.0.4", - "@types/cross-spawn": "^6.0.6", - "@types/validate-npm-package-name": "^4.0.2", - "unbuild": "^3.3.1" - }, - "peerDependencies": { - "@tanstack/react-router": "workspace:^", - "@tanstack/router-devtools": "workspace:^", - "@tanstack/react-start": "workspace:^", - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "vinxi": "0.5.1", - "vite": "^6.0.3" - }, - "peerDependenciesMeta": { - "@tanstack/react-router": { - "optional": true - }, - "@tanstack/router-devtools": { - "optional": true - }, - "@tanstack/react-start": { - "optional": true - }, - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - }, - "typescript": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "vinxi": { - "optional": true - }, - "vite": { - "optional": true - } - } -} diff --git a/packages/create-start/src/cli-entry.ts b/packages/create-start/src/cli-entry.ts deleted file mode 100644 index 12e38723ebd..00000000000 --- a/packages/create-start/src/cli-entry.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { runCli } from './cli' - -runCli(process.argv).catch((error) => { - console.error(error) - process.exit(1) -}) diff --git a/packages/create-start/src/cli.ts b/packages/create-start/src/cli.ts deleted file mode 100644 index 000322ef2c7..00000000000 --- a/packages/create-start/src/cli.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Command, createOption } from '@commander-js/extra-typings' -import { packageManagerOption } from './modules/packageManager' -import { logo } from './logo' -import { - scaffoldTemplate, - templateCliOption, - templatePrompt, -} from './templates' -import { createDebugger, debugCliOption, initDebug } from './utils/debug' -import { getAbsolutePath, newProjectDirectoryPrompt } from './directory' -import { packageNameCliOption } from './modules/packageJson' -import { ideCliOption } from './modules/ide' -import type { TEMPLATE_NAME } from './templates' - -const logger = createDebugger('cli') - -const options = { - template: templateCliOption, - packageNameCliOption: packageNameCliOption, - packageManager: packageManagerOption, - directory: createOption('--directory ', 'The directory to use'), - installDeps: createOption( - '--install-deps', - 'Install dependencies after scaffolding', - ), - noInstallDeps: createOption( - '--no-install-deps', - 'Skip installing dependencies after scaffolding', - ), - initGit: createOption('--init-git', 'Initialise git'), - noInitGit: createOption('--no-init-git', 'Skip initialising git'), - hideLogo: createOption('--hide-logo', 'Hide the Tanstack Start logo'), - ide: ideCliOption, - debug: debugCliOption, -} - -const addNewProjectOptions = (command: Command) => { - return command - .addOption(options.template) - .addOption(options.packageNameCliOption) - .addOption(options.packageManager) - .addOption(options.directory) - .addOption(options.installDeps) - .addOption(options.noInstallDeps) - .addOption(options.initGit) - .addOption(options.noInitGit) - .addOption(options.hideLogo) - .addOption(options.ide) - .addOption(options.debug) -} - -// const addQueryCommand = addBaseOptions( -// new Command() -// .name('tanstack-query') -// .description('Add the Tanstack Query module'), -// ).action((options) => {}) - -// const addCommand = new Command() -// .name('add') -// .description('Add a module to your Tanstack Start project') - -const program = addNewProjectOptions( - new Command('create-start') - .name('create-start') - .description('Scaffold a Tanstack Start appliaction') - .command('default', { - isDefault: true, - hidden: true, - }), -) - // .addCommand(addCommand) - .action(async (options) => { - logger.info('Starting CLI action', { options }) - initDebug(options.debug) - - const templateId: TEMPLATE_NAME = - options.template ?? (await templatePrompt()) - logger.verbose('Template selected', { templateId }) - - const directory = options.directory ?? (await newProjectDirectoryPrompt()) - const targetPath = getAbsolutePath(directory) - logger.verbose('Target directory resolved', { directory, targetPath }) - - logger.info('Starting scaffold process', { - templateId, - targetPath, - packageManager: options.packageManager, - installDeps: options.installDeps, - packageName: options.packageName, - initGit: options.initGit, - ide: options.ide, - }) - - await scaffoldTemplate({ - cfg: { - packageManager: { - packageManager: options.packageManager, - installDeps: options.installDeps, - }, - packageJson: { - type: 'new', - name: options.packageName, - }, - git: { - setupGit: options.initGit, - }, - ide: { - ide: options.ide, - }, - }, - targetPath, - templateId, - }) - logger.info('Scaffold process complete') - }) - -export async function runCli(argv: Array) { - logger.info('CLI starting', { argv }) - if (!argv.includes('--hide-logo')) { - logo() - } - - return new Promise((resolve, reject) => { - logger.verbose('Parsing CLI arguments') - program - .parseAsync(argv) - .then(resolve) - .catch((error) => { - logger.error('CLI execution failed', error) - reject(error) - }) - }) -} diff --git a/packages/create-start/src/constants.ts b/packages/create-start/src/constants.ts deleted file mode 100644 index ef640a4203d..00000000000 --- a/packages/create-start/src/constants.ts +++ /dev/null @@ -1,8 +0,0 @@ -export const NAME = 'create-start' -export const SUPPORTED_PACKAGE_MANAGERS = [ - 'bun', - 'pnpm', - 'npm', - 'yarn', -] as const -export type PackageManager = (typeof SUPPORTED_PACKAGE_MANAGERS)[number] diff --git a/packages/create-start/src/directory.ts b/packages/create-start/src/directory.ts deleted file mode 100644 index 297b29358ef..00000000000 --- a/packages/create-start/src/directory.ts +++ /dev/null @@ -1,73 +0,0 @@ -import path from 'node:path' -import fs from 'node:fs/promises' -import { InvalidArgumentError, createOption } from '@commander-js/extra-typings' -import { input } from '@inquirer/prompts' - -export const getAbsolutePath = (relativePath: string) => { - return path.resolve(process.cwd(), relativePath) -} - -const doesPathExist = async (absolutePath: string) => { - try { - await fs.access(absolutePath) - return true - } catch { - return false - } -} - -const isFolderEmpty = async (absolutePath: string) => { - try { - const files = await fs.readdir(absolutePath) - return files.length === 0 - } catch { - return false - } -} - -const DEFAULT_NAME = 'my-tanstack-start-app' - -const generateDefaultName = async () => { - // Generate a unique default name e.g. my-tanstack-start-app, - // my-tanstack-start-app-1, my-tanstack-start-app-2 etc - - let folderName = DEFAULT_NAME - let absolutePath = getAbsolutePath(folderName) - let pathExists = await doesPathExist(absolutePath) - let counter = 1 - while (pathExists) { - folderName = `${DEFAULT_NAME}-${counter}` - absolutePath = getAbsolutePath(folderName) - pathExists = await doesPathExist(absolutePath) - counter++ - } - return `./${folderName}` -} - -const validateDirectory = async (directory: string) => { - const absolutePath = getAbsolutePath(directory) - const pathExists = await doesPathExist(absolutePath) - if (!pathExists) return true - const folderEmpty = await isFolderEmpty(absolutePath) - if (folderEmpty) return true - return 'The directory is not empty. New projects can only be scaffolded in empty directories' -} - -export const newProjectDirectoryCliOption = createOption( - '--directory ', - 'The directory to scaffold your app in', -).argParser(async (directory) => { - const validationResult = await validateDirectory(directory) - if (validationResult === true) return directory - throw new InvalidArgumentError(validationResult) -}) - -export const newProjectDirectoryPrompt = async () => { - return await input({ - message: 'Where should the project be created?', - default: await generateDefaultName(), - validate: async (path) => { - return await validateDirectory(path) - }, - }) -} diff --git a/packages/create-start/src/index.ts b/packages/create-start/src/index.ts deleted file mode 100644 index a73827cc6c5..00000000000 --- a/packages/create-start/src/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { createModule } from './module' -import { ideModule as unstable_ideModule } from './modules/ide' -import { gitModule as unstable_gitModule } from './modules/git' -import { coreModule as unstable_coreModule } from './modules/core' -import { packageJsonModule as unstable_packageJsonModule } from './modules/packageJson' -import { packageManagerModule as unstable_packageManagerModule } from './modules/packageManager' - -export { createModule as unstable_createModule } -export { scaffoldTemplate as unstable_scaffoldTemplate } from './templates' - -export const modules = { - unstable_ideModule, - unstable_gitModule, - unstable_coreModule, - unstable_packageJsonModule, - unstable_packageManagerModule, -} diff --git a/packages/create-start/src/logo.ts b/packages/create-start/src/logo.ts deleted file mode 100644 index 9de211427d1..00000000000 --- a/packages/create-start/src/logo.ts +++ /dev/null @@ -1,44 +0,0 @@ -import gradient from 'gradient-string' - -const LEFT_PADDING = 5 - -export const logo = () => { - const logoText = `|▗▄▄▄▖▗▄▖ ▗▖ ▗▖ ▗▄▄▖▗▄▄▄▖▗▄▖ ▗▄▄▖▗▖ ▗▖ - | █ ▐▌ ▐▌▐▛▚▖▐▌▐▌ █ ▐▌ ▐▌▐▌ ▐▌▗▞▘ - | █ ▐▛▀▜▌▐▌ ▝▜▌ ▝▀▚▖ █ ▐▛▀▜▌▐▌ ▐▛▚▖ - | █ ▐▌ ▐▌▐▌ ▐▌▗▄▄▞▘ █ ▐▌ ▐▌▝▚▄▄▖▐▌ ▐▌ - ` - - const startText = `| ▗▄▄▖▗▄▄▄▖▗▄▖ ▗▄▄▖▗▄▄▄▖ - | ▐▌ █ ▐▌ ▐▌▐▌ ▐▌ █ - | ▝▀▚▖ █ ▐▛▀▜▌▐▛▀▚▖ █ - | ▗▄▄▞▘ █ ▐▌ ▐▌▐▌ ▐▌ █ - ` - - const removeLeadngChars = (str: string) => { - return str - .split('\n') - .map((line) => line.replace(/^\s*\|/, '')) - .join('\n') - } - - const padLeft = (str: string) => { - return str - .split('\n') - .map((line) => ' '.repeat(LEFT_PADDING) + line) - .join('\n') - } - - // Create the gradients first - const logoGradient = gradient(['#00bba6', '#8a5eec']) - const startGradient = gradient(['#00bba6', '#00bba6']) - - // Then apply them to the processed text - const logo = logoGradient.multiline(padLeft(removeLeadngChars(logoText))) - const start = startGradient.multiline(padLeft(removeLeadngChars(startText))) - - console.log() - console.log(logo) - console.log(start) - console.log() -} diff --git a/packages/create-start/src/module.ts b/packages/create-start/src/module.ts deleted file mode 100644 index b6caf4154eb..00000000000 --- a/packages/create-start/src/module.ts +++ /dev/null @@ -1,286 +0,0 @@ -import yoctoSpinner from 'yocto-spinner' -import { checkFolderExists, checkFolderIsEmpty } from './utils/helpers' -import { createDebugger } from './utils/debug' -import type { - ParseReturnType, - SafeParseReturnType, - ZodType, - input, - output, - z, -} from 'zod' -import type { Spinner } from 'yocto-spinner' - -const debug = createDebugger('module') - -type Schema = ZodType - -class ModuleBase { - private _baseSchema: TSchema - - constructor(baseSchema: TSchema) { - this._baseSchema = baseSchema - debug.info('Creating new module') - } - - init( - fn: (baseSchema: TSchema) => TInitSchema, - ): InitModule { - debug.verbose('Initializing module with schema transformer') - const schema = fn(this._baseSchema) - return new InitModule(this._baseSchema, schema) - } -} - -class InitModule { - private _baseSchema: TSchema - private _initSchema: TInitSchema - - constructor(baseSchema: TSchema, initSchema: TInitSchema) { - this._baseSchema = baseSchema - this._initSchema = initSchema - debug.verbose('Created init module') - } - - prompt( - fn: (initSchema: TInitSchema) => TPromptSchema, - ): PromptModule { - debug.verbose('Creating prompt module with schema transformer') - const schema = fn(this._initSchema) - return new PromptModule( - this._baseSchema, - this._initSchema, - schema, - ) - } -} - -class PromptModule< - TSchema extends Schema, - TInitSchema extends Schema, - TPromptSchema extends Schema, -> { - private _baseSchema: TSchema - private _initSchema: TInitSchema - private _promptSchema: TPromptSchema - - constructor( - baseSchema: TSchema, - initSchema: TInitSchema, - promptSchema: TPromptSchema, - ) { - this._baseSchema = baseSchema - this._initSchema = initSchema - this._promptSchema = promptSchema - debug.verbose('Created prompt module') - } - - validateAndApply< - TApplyFn extends ApplyFn, - TValidateFn extends ValidateFn, - >({ - validate, - apply, - spinnerConfigFn, - }: { - validate?: TValidateFn - apply: TApplyFn - spinnerConfigFn?: SpinnerConfigFn - }): FinalModule { - debug.verbose('Creating final module with validate and apply functions') - return new FinalModule< - TSchema, - TInitSchema, - TPromptSchema, - TValidateFn, - TApplyFn - >( - this._baseSchema, - this._initSchema, - this._promptSchema, - apply, - validate, - spinnerConfigFn, - ) - } -} - -type ApplyFn = (opts: { - targetPath: string - cfg: z.output -}) => void | Promise - -type ValidateFn = (opts: { - targetPath: string - cfg: z.output -}) => Promise> | Array - -type SpinnerOptions = { - success: string - error: string - inProgress: string -} - -type SpinnerConfigFn = ( - cfg: z.infer, -) => SpinnerOptions | undefined - -class FinalModule< - TSchema extends Schema, - TInitSchema extends Schema, - TPromptSchema extends Schema, - TValidateFn extends ValidateFn, - TApplyFn extends ApplyFn, -> { - public _baseSchema: TSchema - public _initSchema: TInitSchema - public _promptSchema: TPromptSchema - public _applyFn: TApplyFn - public _validateFn: TValidateFn | undefined - public _spinnerConfigFn: SpinnerConfigFn | undefined - - constructor( - baseSchema: TSchema, - initSchema: TInitSchema, - promptSchema: TPromptSchema, - applyFn: TApplyFn, - validateFn?: TValidateFn, - spinnerConfigFn?: SpinnerConfigFn, - ) { - this._baseSchema = baseSchema - this._initSchema = initSchema - this._promptSchema = promptSchema - this._applyFn = applyFn - this._validateFn = validateFn - if (spinnerConfigFn) this._spinnerConfigFn = spinnerConfigFn - debug.verbose('Created final module') - } - - async init(cfg: input): Promise> { - debug.verbose('Running init', { cfg }) - return await this._initSchema.parseAsync(cfg) - } - - public async initSafe( - cfg: input, - ): Promise, output>> { - debug.verbose('Running safe init', { cfg }) - return await this._initSchema.safeParseAsync(cfg) - } - - public async prompt( - cfg: input, - ): Promise, output>> { - debug.verbose('Running prompt', { cfg }) - return await this._promptSchema.parseAsync(cfg) - } - - public async validate( - cfg: input, - ): Promise, output>> { - debug.verbose('Running validate', { cfg }) - return await this._promptSchema.safeParseAsync(cfg) - } - - public async apply({ - cfg, - targetPath, - }: { - cfg: output - targetPath: string - }) { - debug.verbose('Running apply', { cfg, targetPath }) - const spinnerOptions = this._spinnerConfigFn?.(cfg) - await runWithSpinner({ - fn: async () => { - return await this._applyFn({ cfg, targetPath }) - }, - spinnerOptions, - }) - } - - public async execute({ - cfg, - targetPath, - type, - applyingMessage, - }: { - cfg: input - targetPath: string - type: 'new-project' | 'update' - applyingMessage?: string - }) { - debug.info('Executing module', { type, targetPath }) - - const targetExists = await checkFolderExists(targetPath) - const targetIsEmpty = await checkFolderIsEmpty(targetPath) - - debug.verbose('Target directory status', { targetExists, targetIsEmpty }) - - if (type === 'new-project') { - if (targetExists && !targetIsEmpty) { - debug.error('Target directory is not empty for new project') - console.error("The target folder isn't empty") - process.exit(0) - } - } - - if (type === 'update') { - if (!targetExists) { - debug.error('Target directory does not exist for update') - console.error("The target folder doesn't exist") - process.exit(0) - } - } - - debug.verbose('Parsing init state') - const initState = await this._initSchema.parseAsync(cfg) - - debug.verbose('Parsing prompt state') - const promptState = await this._promptSchema.parseAsync(initState) - - if (applyingMessage) { - console.log() - console.log(applyingMessage) - } - - debug.verbose('Applying module') - await this.apply({ cfg: promptState, targetPath }) - debug.info('Module execution complete') - } -} - -export function createModule( - baseSchema: TSchema, -): ModuleBase { - return new ModuleBase(baseSchema) -} - -export const runWithSpinner = async ({ - spinnerOptions, - fn, -}: { - spinnerOptions: SpinnerOptions | undefined - fn: () => Promise -}) => { - let spinner: Spinner - - if (spinnerOptions != undefined) { - spinner = yoctoSpinner({ - text: spinnerOptions.inProgress, - }).start() - } - - try { - await fn() - if (spinnerOptions) { - spinner!.success(spinnerOptions.success) - } - } catch (e) { - if (spinnerOptions) { - spinner!.error(spinnerOptions.error) - } - debug.error('Error in spinner operation', e) - throw e - } -} diff --git a/packages/create-start/src/modules/core/index.ts b/packages/create-start/src/modules/core/index.ts deleted file mode 100644 index 79aaf2e8b1c..00000000000 --- a/packages/create-start/src/modules/core/index.ts +++ /dev/null @@ -1,279 +0,0 @@ -import { dirname, resolve } from 'node:path' -import { fileURLToPath } from 'node:url' -import { readFileSync } from 'node:fs' -import { z } from 'zod' -import { packageJsonModule } from '../packageJson' -import { createModule, runWithSpinner } from '../../module' -import { ideModule } from '../ide' -import { packageManagerModule } from '../packageManager' -import { initHelpers } from '../../utils/helpers' -import { gitModule } from '../git' -import { createDebugger } from '../../utils/debug' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - -const createStartPackageJson = JSON.parse( - readFileSync( - resolve(dirname(fileURLToPath(import.meta.url)), '../../../package.json'), - 'utf8', - ), -) - -const debug = createDebugger('core-module') - -export const coreModule = createModule( - z.object({ - packageJson: packageJsonModule._initSchema.optional(), - ide: ideModule._initSchema.optional(), - packageManager: packageManagerModule._initSchema.optional(), - git: gitModule._initSchema.optional(), - }), -) - .init((schema) => - schema.transform(async (vals, ctx) => { - debug.verbose('Initializing core module schema', { vals }) - - const gitignore: z.infer['gitIgnore'] = [ - { - sectionName: 'Dependencies', - lines: ['node_modules/'], - }, - { - sectionName: 'Env', - lines: [ - '.env', - '.env.local', - '.env.development', - '.env.test', - '.env.production', - '.env.staging', - ], - }, - { - sectionName: 'System Files', - lines: ['.DS_Store', 'Thumbs.db'], - }, - ] - - vals.git = { - ...vals.git, - gitIgnore: [...(vals.git?.gitIgnore ?? []), ...gitignore], - } - - const packageJson: z.infer = { - type: 'new', - dependencies: await deps([ - '@tanstack/react-router', - '@tanstack/react-start', - 'react', - 'react-dom', - 'vinxi', - ]), - devDependencies: await deps(['@types/react', '@types/react']), - scripts: [ - { - name: 'dev', - script: 'vinxi dev', - }, - { - name: 'build', - script: 'vinxi build', - }, - { - name: 'start', - script: 'vinxi start', - }, - ], - ...vals.packageJson, - } - - debug.verbose('Parsing package manager schema') - const packageManager = - await packageManagerModule._initSchema.safeParseAsync( - vals.packageManager, - { - path: ['packageManager'], - }, - ) - - debug.verbose('Parsing IDE schema') - const ide = await ideModule._initSchema.safeParseAsync(vals.ide, { - path: ['ide'], - }) - - debug.verbose('Parsing git schema') - const git = await gitModule._initSchema.safeParseAsync(vals.git, { - path: ['git'], - }) - - if (!ide.success || !packageManager.success || !git.success) { - debug.error('Schema validation failed', null, { - ide: ide.success, - packageManager: packageManager.success, - git: git.success, - }) - ide.error?.issues.forEach((i) => ctx.addIssue(i)) - packageManager.error?.issues.forEach((i) => ctx.addIssue(i)) - git.error?.issues.forEach((i) => ctx.addIssue(i)) - throw Error('Failed validation') - } - - debug.verbose('Schema transformation complete') - return { - ...vals, - packageManager: packageManager.data, - ide: ide.data, - git: git.data, - packageJson, - } - }), - ) - .prompt((schema) => - schema.transform(async (vals, ctx) => { - debug.verbose('Running prompt transformations', { vals }) - - debug.verbose('Parsing IDE prompt schema') - const ide = await ideModule._promptSchema.safeParseAsync(vals.ide, { - path: ['ide'], - }) - - debug.verbose('Parsing package manager prompt schema') - const packageManager = - await packageManagerModule._promptSchema.safeParseAsync( - vals.packageManager, - { path: ['packageManager'] }, - ) - - debug.verbose('Parsing git prompt schema') - const git = await gitModule._promptSchema.safeParseAsync(vals.git, { - path: ['git'], - }) - - debug.verbose('Parsing package.json prompt schema') - const packageJson = await packageJsonModule._promptSchema.safeParseAsync( - vals.packageJson, - { - path: ['packageJson'], - }, - ) - - if ( - !ide.success || - !packageManager.success || - !git.success || - !packageJson.success - ) { - debug.error('Prompt validation failed', null, { - ide: ide.success, - packageManager: packageManager.success, - git: git.success, - packageJson: packageJson.success, - }) - ide.error?.issues.forEach((i) => ctx.addIssue(i)) - packageManager.error?.issues.forEach((i) => ctx.addIssue(i)) - git.error?.issues.forEach((i) => ctx.addIssue(i)) - throw Error('Failed validation') - } - - debug.verbose('Prompt transformations complete') - return { - packageJson: packageJson.data, - ide: ide.data, - packageManager: packageManager.data, - git: git.data, - } - }), - ) - .validateAndApply({ - validate: async ({ cfg, targetPath }) => { - debug.verbose('Validating core module', { targetPath }) - const _ = initHelpers(__dirname, targetPath) - - const issues = await _.getTemplateFilesThatWouldBeOverwritten({ - file: '**/*', - templateFolder: './template', - targetFolder: targetPath, - overwrite: false, - }) - - if (ideModule._validateFn) { - debug.verbose('Running IDE validation') - const ideIssues = await ideModule._validateFn({ - cfg: cfg.ide, - targetPath, - }) - issues.push(...ideIssues) - } - - debug.info('Validation complete', { issueCount: issues.length }) - return issues - }, - apply: async ({ cfg, targetPath }) => { - debug.info('Applying core module', { targetPath }) - const _ = initHelpers(__dirname, targetPath) - - debug.verbose('Copying core template files') - await runWithSpinner({ - spinnerOptions: { - inProgress: 'Copying core template files', - error: 'Failed to copy core template files', - success: 'Copied core template files', - }, - fn: async () => - await _.copyTemplateFiles({ - file: '**/*', - templateFolder: './template', - targetFolder: '.', - overwrite: false, - }), - }) - - debug.verbose('Applying package.json module') - await packageJsonModule.apply({ cfg: cfg.packageJson, targetPath }) - - debug.verbose('Applying IDE module') - await ideModule.apply({ cfg: cfg.ide, targetPath }) - - debug.verbose('Applying git module') - await gitModule._applyFn({ cfg: cfg.git, targetPath }) - - debug.verbose('Applying package manager module') - await packageManagerModule.apply({ - cfg: cfg.packageManager, - targetPath, - }) - - debug.info('Core module application complete') - }, - }) - -type DepNames< - T extends - (typeof createStartPackageJson)['peerDependencies'] = (typeof createStartPackageJson)['peerDependencies'], -> = keyof T - -const deps = async ( - depsArray: Array, -): Promise< - Exclude< - z.infer['dependencies'], - undefined - > -> => { - debug.verbose('Resolving dependencies', { deps: depsArray }) - const result = await Promise.all( - depsArray.map((d) => { - const version = - createStartPackageJson['peerDependencies'][d] === 'workspace:^' - ? 'latest' // Use latest in development - : createStartPackageJson['peerDependencies'][d] - return { - name: d, - version: version, - } - }), - ) - - return result -} diff --git a/packages/create-start/src/modules/core/template/app.config.ts b/packages/create-start/src/modules/core/template/app.config.ts deleted file mode 100644 index b2c04b10631..00000000000 --- a/packages/create-start/src/modules/core/template/app.config.ts +++ /dev/null @@ -1,5 +0,0 @@ -// @ts-nocheck - -import { defineConfig } from '@tanstack/react-start/config' - -export default defineConfig({}) diff --git a/packages/create-start/src/modules/core/template/app/client.tsx b/packages/create-start/src/modules/core/template/app/client.tsx deleted file mode 100644 index 64f18c113f9..00000000000 --- a/packages/create-start/src/modules/core/template/app/client.tsx +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-nocheck - -/// -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/packages/create-start/src/modules/core/template/app/router.tsx b/packages/create-start/src/modules/core/template/app/router.tsx deleted file mode 100644 index 79fe23eab9a..00000000000 --- a/packages/create-start/src/modules/core/template/app/router.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-nocheck - -import { createRouter as createTanStackRouter } from '@tanstack/react-router' -import { routeTree } from './routeTree.gen' - -export function createRouter() { - const router = createTanStackRouter({ - routeTree, - scrollRestoration: true, - }) - - return router -} - -declare module '@tanstack/react-router' { - interface Register { - router: ReturnType - } -} diff --git a/packages/create-start/src/modules/core/template/app/routes/__root.tsx b/packages/create-start/src/modules/core/template/app/routes/__root.tsx deleted file mode 100644 index 046200b2323..00000000000 --- a/packages/create-start/src/modules/core/template/app/routes/__root.tsx +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-nocheck - -import { - HeadContent, - Outlet, - Scripts, - createRootRoute, -} from '@tanstack/react-router' -import type { ReactNode } from 'react' - -export const Route = createRootRoute({ - head: () => ({ - meta: [ - { - charSet: 'utf-8', - }, - { - name: 'viewport', - content: 'width=device-width, initial-scale=1', - }, - { - title: 'TanStack Start Starter', - }, - ], - }), - component: RootComponent, -}) - -function RootComponent() { - return ( - - - - ) -} - -function RootDocument({ children }: Readonly<{ children: ReactNode }>) { - return ( - - - - - - {children} - - - - ) -} diff --git a/packages/create-start/src/modules/core/template/app/ssr.tsx b/packages/create-start/src/modules/core/template/app/ssr.tsx deleted file mode 100644 index 4ab0e48d6f8..00000000000 --- a/packages/create-start/src/modules/core/template/app/ssr.tsx +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-nocheck - -/// -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/packages/create-start/src/modules/core/template/tsconfig.json b/packages/create-start/src/modules/core/template/tsconfig.json deleted file mode 100644 index edfdf0e8337..00000000000 --- a/packages/create-start/src/modules/core/template/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "jsx": "react-jsx", - "moduleResolution": "Bundler", - "module": "ESNext", - "target": "ES2022", - "skipLibCheck": true, - "strictNullChecks": true - } -} diff --git a/packages/create-start/src/modules/git.ts b/packages/create-start/src/modules/git.ts deleted file mode 100644 index cbf62f00a2e..00000000000 --- a/packages/create-start/src/modules/git.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { readFile, writeFile } from 'node:fs/promises' -import { fileURLToPath } from 'node:url' -import { dirname, resolve } from 'node:path' -import { z } from 'zod' -import { select } from '@inquirer/prompts' -import { createModule } from '../module' -import { runCmd } from '../utils/runCmd' -import { createDebugger } from '../utils/debug' -import { checkFileExists, initHelpers } from '../utils/helpers' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - -const debug = createDebugger('git-module') - -async function appendToGitignore( - targetPath: string, - newEntries: Array, - sectionName: string, -) { - const gitignorePath = resolve(targetPath, '.gitignore') - debug.verbose('Handling gitignore', { gitignorePath }) - - let existingContent = '' - const exists = await checkFileExists(gitignorePath) - - if (exists) { - existingContent = await readFile(gitignorePath, 'utf-8') - const lines = existingContent.split('\n') - - // Find existing section - const sectionStart = lines.findIndex( - (line) => line.trim() === `# ${sectionName}`, - ) - - if (sectionStart !== -1) { - // Section exists, find end (next comment or EOF) - let sectionEnd = lines.findIndex( - (line, i) => i > sectionStart && line.trim().startsWith('#'), - ) - if (sectionEnd === -1) sectionEnd = lines.length - - // Get existing entries in section - const sectionEntries = lines - .slice(sectionStart + 1, sectionEnd) - .map((line) => line.trim()) - .filter((line) => line !== '') - - // Filter out duplicates - newEntries = newEntries.filter( - (entry) => - !sectionEntries.some( - (existing) => existing.toLowerCase() === entry.trim().toLowerCase(), - ), - ) - - if (newEntries.length > 0) { - // Insert new entries at end of section - lines.splice(sectionEnd, 0, ...newEntries) - await writeFile(gitignorePath, lines.join('\n')) - debug.info('Updated existing section in gitignore file') - } - } else { - // Add new section at end - const newContent = `${existingContent}\n\n# ${sectionName}\n${newEntries.join('\n')}` - await writeFile(gitignorePath, newContent) - debug.info('Added new section to gitignore file') - } - } else { - // Create new file with section - const content = `# ${sectionName}\n${newEntries.join('\n')}` - await writeFile(gitignorePath, content) - debug.info('Created new gitignore file') - } -} - -export const gitModule = createModule( - z.object({ - setupGit: z.boolean().optional(), - gitIgnore: z - .object({ - sectionName: z.string(), - lines: z.string().array(), - }) - .array() - .optional(), - }), -) - .init((schema) => schema) // No init required - .prompt((schema) => - schema.transform(async (vals) => { - debug.verbose('Transforming git prompt schema', { vals }) - const setupGit = - vals.setupGit != undefined - ? vals.setupGit - : await select({ - message: 'Initialize git', - choices: [ - { name: 'yes', value: true }, - { name: 'no', value: false }, - ], - default: 'yes', - }) - debug.info('Git initialization choice made', { setupGit }) - return { - setupGit, - gitIgnore: vals.gitIgnore, - } - }), - ) - .validateAndApply({ - apply: async ({ cfg, targetPath }) => { - const _ = initHelpers(__dirname, targetPath) - debug.verbose('Applying git module', { cfg, targetPath }) - - if (cfg.gitIgnore && cfg.gitIgnore.length > 0) { - for (const gitIgnore of cfg.gitIgnore) { - await appendToGitignore( - _.getFullTargetPath(''), - gitIgnore.lines, - gitIgnore.sectionName, - ) - } - debug.info('Created / updated .gitignore') - } - - if (cfg.setupGit) { - debug.info('Initializing git repository') - try { - await runCmd('git', ['init'], {}, targetPath) - debug.info('Git repository initialized successfully') - } catch (error) { - debug.error('Failed to initialize git repository', error) - throw error - } - } else { - debug.info('Skipping git initialization') - } - }, - spinnerConfigFn: () => { - return { - success: 'Git initalized', - error: 'Failed to initialize git', - inProgress: 'Initializing git', - } - }, - }) diff --git a/packages/create-start/src/modules/ide.ts b/packages/create-start/src/modules/ide.ts deleted file mode 100644 index 4294e5d6ed0..00000000000 --- a/packages/create-start/src/modules/ide.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { InvalidArgumentError, createOption } from '@commander-js/extra-typings' -import { z } from 'zod' -import { select } from '@inquirer/prompts' -import { createModule } from '../module' -import { createDebugger } from '../utils/debug' -import { vsCodeModule } from './vscode' - -const debug = createDebugger('ide-module') - -const ide = z.enum(['vscode', 'cursor', 'other']) - -const schema = z.object({ - ide: ide.optional(), -}) - -const SUPPORTED_IDES = ide.options -type SupportedIDE = z.infer -const DEFAULT_IDE = 'vscode' - -export const ideCliOption = createOption( - `--ide <${SUPPORTED_IDES.join('|')}>`, - `use this IDE (${SUPPORTED_IDES.join(', ')})`, -).argParser((value) => { - debug.verbose('Parsing IDE CLI option', { value }) - if (!SUPPORTED_IDES.includes(value as SupportedIDE)) { - debug.error('Invalid IDE option provided', null, { value }) - throw new InvalidArgumentError( - `Invalid IDE: ${value}. Only the following are allowed: ${SUPPORTED_IDES.join(', ')}`, - ) - } - return value as SupportedIDE -}) - -export const ideModule = createModule(schema) - .init((schema) => schema) - .prompt((schema) => - schema.transform(async (vals) => { - debug.verbose('Prompting for IDE selection', { currentValue: vals.ide }) - const ide = vals.ide - ? vals.ide - : await select({ - message: 'Select an IDE', - choices: SUPPORTED_IDES.map((i) => ({ value: i })), - default: DEFAULT_IDE, - }) - - debug.info('IDE selected', { ide }) - return { - ide, - } - }), - ) - .validateAndApply({ - validate: async ({ cfg, targetPath }) => { - debug.verbose('Validating IDE configuration', { - ide: cfg.ide, - targetPath, - }) - const issues: Array = [] - - if (cfg.ide === 'vscode') { - debug.verbose('Validating VSCode configuration') - const issuesVsCode = - (await vsCodeModule._validateFn?.({ cfg, targetPath })) ?? [] - issues.push(...issuesVsCode) - } - - if (issues.length > 0) { - debug.warn('IDE validation issues found', { issues }) - } - return issues - }, - apply: async ({ cfg, targetPath }) => { - debug.info('Applying IDE configuration', { ide: cfg.ide, targetPath }) - await vsCodeModule._applyFn({ cfg, targetPath }) - debug.info('IDE configuration applied successfully') - }, - spinnerConfigFn: (cfg) => { - debug.verbose('Configuring spinner for IDE setup', { ide: cfg.ide }) - return ['vscode'].includes(cfg.ide) - ? { - error: `Failed to set up ${cfg.ide}`, - inProgress: `Setting up ${cfg.ide}`, - success: `${cfg.ide} set up`, - } - : undefined - }, - }) diff --git a/packages/create-start/src/modules/packageJson.ts b/packages/create-start/src/modules/packageJson.ts deleted file mode 100644 index 03642b3a326..00000000000 --- a/packages/create-start/src/modules/packageJson.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { dirname } from 'node:path' -import { fileURLToPath } from 'node:url' -import { z } from 'zod' -import { input } from '@inquirer/prompts' -import { InvalidArgumentError, createOption } from '@commander-js/extra-typings' -import { initHelpers } from '../utils/helpers' -import { createModule } from '../module' -import { validateProjectName } from '../utils/validateProjectName' -import { createDebugger } from '../utils/debug' - -const debug = createDebugger('package-json') - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - -export const packageNameCliOption = createOption( - '--package-name ', - 'The name to use in the package.json', -).argParser((name) => { - const validation = validateProjectName(name) - if (!validation.valid) { - debug.error('Invalid package name', { name, validation }) - throw new InvalidArgumentError(`The project name ${name} is invalid`) - } - debug.verbose('Validated package name', { name }) - return name -}) - -const dependencies = z.array( - z.object({ - name: z.string(), - version: z.string(), - }), -) - -const script = z.object({ - name: z.string(), - script: z.string(), -}) - -const schema = z.object({ - type: z.enum(['new', 'update']), - name: z.string().optional(), - dependencies: dependencies.optional(), - devDependencies: dependencies.optional(), - scripts: z.array(script).optional(), -}) - -export const packageJsonModule = createModule(schema) - .init((schema) => schema) - .prompt((schema) => { - return schema.transform(async (vals) => { - debug.verbose('Transforming prompt schema', vals) - if (vals.type === 'new') { - const name = vals.name - ? vals.name - : await input({ - message: 'Enter the project name', - default: 'tanstack-start', - validate: (name) => { - const validation = validateProjectName(name) - if (validation.valid) { - debug.verbose('Valid project name entered', { name }) - return true - } - debug.warn('Invalid project name entered', { - name, - problems: validation.problems, - }) - return 'Invalid project name: ' + validation.problems[0] - }, - }) - - return { - ...vals, - name, - } - } else { - return vals - } - }) - }) - .validateAndApply({ - validate: async ({ cfg, targetPath }) => { - debug.verbose('Validating package.json', { cfg, targetPath }) - const issues: Array = [] - const _ = initHelpers(__dirname, targetPath) - - const packageJsonExists = await _.targetFileExists('./package.json') - debug.verbose('Package.json exists check', { exists: packageJsonExists }) - - if (cfg.type === 'new') { - if (packageJsonExists) { - debug.warn('Package.json already exists for new project') - issues.push('Package.json already exists') - } - } else { - if (!packageJsonExists) { - debug.warn('Package.json missing for update') - issues.push("Package.json doesn't exist to update") - } - } - - return issues - }, - apply: async ({ cfg, targetPath }) => { - debug.verbose('Applying package.json changes', { cfg, targetPath }) - const _ = initHelpers(__dirname, targetPath) - if (cfg.type === 'new') { - const packageJson = { - name: cfg.name, - version: '0.0.0', - private: true, - type: 'module', - } - - debug.verbose('Creating new package.json', packageJson) - await _.writeTargetfile( - './package.json', - JSON.stringify(packageJson, null, 2), - false, - ) - } - - let packageJson = JSON.parse(await _.readTargetFile('./package.json')) - debug.verbose('Current package.json contents', packageJson) - - const dependenciesRecord = createDepsRecord(cfg.dependencies ?? []) - const devDependenciesRecord = createDepsRecord(cfg.devDependencies ?? []) - const scriptsRecord = createScriptsRecord(cfg.scripts ?? []) - - packageJson = { - ...packageJson, - scripts: { - ...packageJson.scripts, - ...scriptsRecord, - }, - dependencies: { - ...packageJson.dependencies, - ...dependenciesRecord, - }, - devDependencies: { - ...packageJson.devDependencies, - ...devDependenciesRecord, - }, - } - - debug.verbose('Updated package.json contents', packageJson) - await _.writeTargetfile( - './package.json', - JSON.stringify(packageJson, null, 2), - true, - ) - }, - spinnerConfigFn: (cfg) => ({ - success: `${cfg.type === 'new' ? 'Created' : 'Updated'} package.json`, - error: `Failed to ${cfg.type === 'new' ? 'create' : 'update'} package.json`, - inProgress: `${cfg.type === 'new' ? 'Creating' : 'Updating'} package.json`, - }), - }) - -const createDepsRecord = (deps: Array<{ name: string; version: string }>) => - deps.reduce( - (acc: Record, dep: { name: string; version: string }) => ({ - ...acc, - [dep.name]: dep.version, - }), - {}, - ) - -const createScriptsRecord = ( - scripts: Array<{ name: string; script: string }>, -) => - scripts.reduce( - ( - acc: Record, - script: { name: string; script: string }, - ) => ({ - ...acc, - [script.name]: script.script, - }), - {}, - ) diff --git a/packages/create-start/src/modules/packageManager.ts b/packages/create-start/src/modules/packageManager.ts deleted file mode 100644 index 2a0c2a52e40..00000000000 --- a/packages/create-start/src/modules/packageManager.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { z } from 'zod' -import { InvalidArgumentError, createOption } from '@commander-js/extra-typings' -import { select } from '@inquirer/prompts' -import { createModule } from '../module' -import { SUPPORTED_PACKAGE_MANAGERS } from '../constants' -import { getPackageManager } from '../utils/getPackageManager' -import { install } from '../utils/runPackageManagerCommand' -import { createDebugger } from '../utils/debug' - -const debug = createDebugger('packageManager') - -const schema = z.object({ - packageManager: z.enum(SUPPORTED_PACKAGE_MANAGERS), - installDeps: z.boolean(), -}) - -const DEFAULT_PACKAGE_MANAGER = 'npm' -const options = schema.shape.packageManager.options -type PackageManager = z.infer['packageManager'] - -export const packageManagerOption = createOption( - `--package-manager <${options.join('|')}>`, - `use this Package Manager (${options.join(', ')})`, -).argParser((value) => { - if (!options.includes(value as PackageManager)) { - debug.error('Invalid package manager provided', { value, allowed: options }) - throw new InvalidArgumentError( - `Invalid Package Manager: ${value}. Only the following are allowed: ${options.join(', ')}`, - ) - } - return value as PackageManager -}) - -export const packageManagerModule = createModule( - z.object({ - packageManager: z.enum(SUPPORTED_PACKAGE_MANAGERS).optional(), - installDeps: z.boolean().optional(), - }), -) - .init((schema) => - schema.transform((vals) => { - debug.verbose('Initializing package manager', vals) - const detectedPM = getPackageManager() - debug.verbose('Detected package manager', { detectedPM }) - return { - packageManager: vals.packageManager ?? detectedPM, - installDeps: vals.installDeps, - } - }), - ) - .prompt((schema) => - schema.transform(async (vals) => { - debug.verbose('Prompting for package manager options', vals) - const packageManager = - vals.packageManager != undefined - ? vals.packageManager - : await select({ - message: 'Select a package manager', - choices: options.map((pm) => ({ value: pm })), - default: getPackageManager() ?? DEFAULT_PACKAGE_MANAGER, - }) - - const installDeps = - vals.installDeps != undefined - ? vals.installDeps - : await select({ - message: 'Install dependencies', - choices: [ - { name: 'yes', value: true }, - { name: 'no', value: false }, - ], - default: 'yes', - }) - - debug.verbose('Package manager options selected', { - packageManager, - installDeps, - }) - return { - installDeps, - packageManager, - } - }), - ) - .validateAndApply({ - spinnerConfigFn: (cfg) => { - debug.verbose('Configuring spinner', cfg) - return cfg.installDeps - ? { - error: `Failed to install dependencies with ${cfg.packageManager}`, - inProgress: `Installing dependencies with ${cfg.packageManager}`, - success: `Installed dependencies with ${cfg.packageManager}`, - } - : undefined - }, - apply: async ({ cfg, targetPath }) => { - if (cfg.installDeps) { - debug.info('Installing dependencies', { - packageManager: cfg.packageManager, - targetPath, - }) - - await install(cfg.packageManager, targetPath) - debug.info('Dependencies installed successfully') - } else { - debug.info('Skipping dependency installation') - } - }, - }) diff --git a/packages/create-start/src/modules/vscode/index.ts b/packages/create-start/src/modules/vscode/index.ts deleted file mode 100644 index 52c448c3c24..00000000000 --- a/packages/create-start/src/modules/vscode/index.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { dirname } from 'node:path' -import { fileURLToPath } from 'node:url' -import { z } from 'zod' -import { initHelpers } from '../../utils/helpers' -import { createModule } from '../../module' -import { createDebugger } from '../../utils/debug' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - -const debug = createDebugger('vscode') - -export const vsCodeModule = createModule(z.object({})) - .init((schema) => schema) - .prompt((schema) => schema) - .validateAndApply({ - validate: async ({ targetPath }) => { - debug.verbose('Validating vscode module', { targetPath }) - const _ = initHelpers(__dirname, targetPath) - - const issues = await _.getTemplateFilesThatWouldBeOverwritten({ - file: '**/*', - templateFolder: './template', - targetFolder: targetPath, - overwrite: false, - }) - - debug.verbose('Validation complete', { issueCount: issues.length }) - return issues - }, - apply: async ({ targetPath }) => { - debug.info('Applying vscode module', { targetPath }) - // Copy the vscode template folders into the project - const _ = initHelpers(__dirname, targetPath) - - // TODO: Handle when the settings file already exists and merge settings - debug.verbose('Copying template files') - await _.copyTemplateFiles({ - file: '**/*', - templateFolder: './template', - targetFolder: '.', - overwrite: false, - }) - debug.info('VSCode module applied successfully') - }, - }) diff --git a/packages/create-start/src/modules/vscode/template/_dot_vscode/settings.json b/packages/create-start/src/modules/vscode/template/_dot_vscode/settings.json deleted file mode 100644 index 00b5278e580..00000000000 --- a/packages/create-start/src/modules/vscode/template/_dot_vscode/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "files.watcherExclude": { - "**/routeTree.gen.ts": true - }, - "search.exclude": { - "**/routeTree.gen.ts": true - }, - "files.readonlyInclude": { - "**/routeTree.gen.ts": true - } -} diff --git a/packages/create-start/src/templates/barebones/index.ts b/packages/create-start/src/templates/barebones/index.ts deleted file mode 100644 index 03dcb95fa51..00000000000 --- a/packages/create-start/src/templates/barebones/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { fileURLToPath } from 'node:url' -import { dirname } from 'node:path' -import { createModule, runWithSpinner } from '../../module' -import { coreModule } from '../../modules/core' -import { initHelpers } from '../../utils/helpers' -import { createDebugger } from '../../utils/debug' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = dirname(__filename) - -const debug = createDebugger('barebones-template') -const schema = coreModule._initSchema - -export const barebonesTemplate = createModule(schema) - .init((schema) => schema) - .prompt((schema) => - schema.transform(async (vals) => { - debug.verbose('Transforming prompt schema', { vals }) - const core = await coreModule._promptSchema.parseAsync(vals) - debug.verbose('Core module prompt complete') - - return { - ...core, - } - }), - ) - .validateAndApply({ - validate: async ({ cfg, targetPath }) => { - debug.verbose('Validating barebones template', { targetPath }) - const _ = initHelpers(__dirname, targetPath) - - const issues = await _.getTemplateFilesThatWouldBeOverwritten({ - file: '**/*', - templateFolder: './template', - targetFolder: targetPath, - overwrite: false, - }) - - debug.verbose('Template file conflicts found', { issues }) - - const coreIssues = - (await coreModule._validateFn?.({ cfg, targetPath })) ?? [] - debug.verbose('Core module validation issues', { coreIssues }) - - issues.push(...coreIssues) - - return issues - }, - apply: async ({ cfg, targetPath }) => { - debug.info('Applying barebones template', { targetPath }) - const _ = initHelpers(__dirname, targetPath) - - await runWithSpinner({ - spinnerOptions: { - inProgress: 'Copying barebones template files', - error: 'Failed to copy barebones template files', - success: 'Copied barebones template files', - }, - fn: async () => { - debug.verbose('Copying template files') - await _.copyTemplateFiles({ - file: '**/*', - templateFolder: './template', - targetFolder: '.', - overwrite: false, - }) - debug.verbose('Template files copied successfully') - }, - }) - - debug.verbose('Applying core module') - await coreModule._applyFn({ cfg, targetPath }) - debug.info('Barebones template applied successfully') - }, - }) diff --git a/packages/create-start/src/templates/barebones/template/app/routes/index.tsx b/packages/create-start/src/templates/barebones/template/app/routes/index.tsx deleted file mode 100644 index bf75abe4995..00000000000 --- a/packages/create-start/src/templates/barebones/template/app/routes/index.tsx +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-nocheck - -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/')({ - component: RouteComponent, -}) - -function RouteComponent() { - return
Hello "/"!
-} diff --git a/packages/create-start/src/templates/index.ts b/packages/create-start/src/templates/index.ts deleted file mode 100644 index 3fcbb7b5eca..00000000000 --- a/packages/create-start/src/templates/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { select } from '@inquirer/prompts' -import { InvalidArgumentError, createOption } from '@commander-js/extra-typings' -import invariant from 'tiny-invariant' -import { createDebugger } from '../utils/debug' -import { barebonesTemplate } from './barebones' -import type { coreModule } from '../modules/core' -import type { z } from 'zod' - -const debug = createDebugger('templates') - -const templates = [ - { - id: 'barebones', - name: 'Barebones', - module: barebonesTemplate, - description: 'The bare minimum', - }, -] as const - -const templateIds = templates.map((t) => t.id) -export type TEMPLATE_NAME = (typeof templateIds)[number] -export const DEFAULT_TEMPLATE: TEMPLATE_NAME = 'barebones' - -export const templateCliOption = createOption( - '--template ', - 'Choose the template to use', -).argParser((value) => { - if (!templateIds.includes(value as TEMPLATE_NAME)) { - debug.error(`Invalid template specified: ${value}`) - throw new InvalidArgumentError( - `Invalid Template: ${value}. Only the following are allowed: ${templateIds.join(', ')}`, - ) - } - debug.verbose('Template validated from CLI', { template: value }) - return value as TEMPLATE_NAME -}) - -export const templatePrompt = async () => { - debug.info('Prompting for template selection') - const selection = await select({ - message: 'Which template would you like to use?', - choices: templates.map((t) => ({ - name: t.name, - value: t.id, - description: t.description, - })), - default: DEFAULT_TEMPLATE, - }) - debug.verbose('Template selected', { template: selection }) - return selection -} - -export const scaffoldTemplate = async ({ - templateId, - cfg, - targetPath, -}: { - templateId: TEMPLATE_NAME - cfg: z.input - targetPath: string -}) => { - debug.info('Starting template scaffolding', { templateId, targetPath }) - // const template = templates.find((f) => f.id === templateId) - const template = templates[0] // Remove this when we add more templates - invariant(template, `The template with ${templateId} is not valid`) - - debug.verbose('Executing template module', { template: template.id }) - await template.module.execute({ - cfg, - targetPath, - type: 'new-project', - applyingMessage: `Scaffolding the ${template.name} template`, - }) - debug.info('Template scaffolding complete') -} diff --git a/packages/create-start/src/types.ts b/packages/create-start/src/types.ts deleted file mode 100644 index b66c077f64b..00000000000 --- a/packages/create-start/src/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type packageJson from '../package.json' - -export type PeerDependency = keyof typeof packageJson.peerDependencies diff --git a/packages/create-start/src/utils/debug.ts b/packages/create-start/src/utils/debug.ts deleted file mode 100644 index 81d7bfe1590..00000000000 --- a/packages/create-start/src/utils/debug.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { InvalidArgumentError, createOption } from '@commander-js/extra-typings' - -type Context = string -type LogLevel = 'info' | 'warn' | 'error' - -interface LogOptions { - context: Context - data?: Record -} - -let isDebugMode = false -let debugLevel = 0 // 1 = basic, 2 = verbose, 3 = trace - -const DEBUG_LEVELS = ['debug', 'trace', 'verbose'] as const -type DebugLevels = (typeof DEBUG_LEVELS)[number] - -export const debugCliOption = createOption( - `--debug <${DEBUG_LEVELS.join('|')}>`, - `Set a debug level (${DEBUG_LEVELS.join(', ')})`, -).argParser((value) => { - if (!DEBUG_LEVELS.includes(value as DebugLevels)) { - throw new InvalidArgumentError( - `Invalid debug level: ${value}. Only the following are allowed: ${DEBUG_LEVELS.join(', ')}`, - ) - } - return value as DebugLevels -}) - -export const initDebug = (level: undefined | 'debug' | 'trace' | 'verbose') => { - if (level === undefined) return - isDebugMode = true - if (level === 'debug') debugLevel = 1 - if (level === 'trace') debugLevel = 2 - if (level === 'verbose') debugLevel = 3 -} - -const formatData = (data?: Record): string => { - if (!data) return '' - return Object.entries(data) - .map(([key, value]) => `${key}=${JSON.stringify(value)}`) - .join(' ') -} - -const log = (level: LogLevel, message: string, options: LogOptions) => { - if (!isDebugMode) return - - const timestamp = new Date().toISOString() - const dataStr = formatData(options.data) - const logMessage = `[${timestamp}] [${level}] [${options.context}] ${message} ${dataStr}` - - switch (level) { - case 'error': - console.error(logMessage) - break - case 'warn': - console.warn(logMessage) - break - case 'info': - console.log(logMessage) - break - } -} - -export const createDebugger = (context: Context) => ({ - info: (message: string, data?: Record) => { - if (debugLevel < 1) return - log('info', message, { context, data }) - }, - warn: (message: string, data?: Record) => { - if (debugLevel < 2) return - log('warn', message, { context, data }) - }, - error: ( - message: string, - error?: Error | unknown, - data?: Record, - ) => { - if (debugLevel < 1) return - log('error', message, { - context, - data: { - ...data, - error: error instanceof Error ? error.message : error, - }, - }) - }, - verbose: (message: string, data?: Record) => { - if (debugLevel < 2) return - log('info', message, { context, data }) - }, - trace: (message: string, data?: Record) => { - if (debugLevel < 3) return - log('info', message, { context, data }) - }, -}) diff --git a/packages/create-start/src/utils/getPackageManager.ts b/packages/create-start/src/utils/getPackageManager.ts deleted file mode 100644 index 4bcb7b8032c..00000000000 --- a/packages/create-start/src/utils/getPackageManager.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SUPPORTED_PACKAGE_MANAGERS } from '../constants' -import type { PackageManager } from '../constants' - -export function getPackageManager(): PackageManager | undefined { - const userAgent = process.env.npm_config_user_agent - - if (userAgent === undefined) { - return undefined - } - - const packageManager = SUPPORTED_PACKAGE_MANAGERS.find((manager) => - userAgent.startsWith(manager), - ) - - return packageManager -} diff --git a/packages/create-start/src/utils/helpers/helperFactory.ts b/packages/create-start/src/utils/helpers/helperFactory.ts deleted file mode 100644 index 1f0fa6afb89..00000000000 --- a/packages/create-start/src/utils/helpers/helperFactory.ts +++ /dev/null @@ -1,20 +0,0 @@ -export type Ctx = { - getFullModulePath: (relativePath: string) => string - getFullTargetPath: (relativePath: string) => string - targetFileExists: (relativePath: string) => Promise - moduleFileExists: (relativePath: string) => Promise - absoluteTargetFolder: string - absoluteModuleFolder: string -} - -type HelperFn any> = (args: { - modulePath: string - targetPath: string - ctx: Ctx -}) => T - -export const helperFactory = any>( - fn: HelperFn, -) => { - return fn -} diff --git a/packages/create-start/src/utils/helpers/index.ts b/packages/create-start/src/utils/helpers/index.ts deleted file mode 100644 index 051bdf7a2cf..00000000000 --- a/packages/create-start/src/utils/helpers/index.ts +++ /dev/null @@ -1,284 +0,0 @@ -import path, { resolve } from 'node:path' -import fs, { - access, - copyFile, - mkdir, - readFile, - readdir, - stat, - writeFile, -} from 'node:fs/promises' -import invariant from 'tiny-invariant' -import fastGlob from 'fast-glob' -import { createDebugger } from '../debug' - -import { helperFactory } from './helperFactory' -import type { Ctx } from './helperFactory' - -const debug = createDebugger('helpers') - -export const initHelpers = (modulePath: string, targetPath: string) => { - debug.info('Initializing helpers', { modulePath, targetPath }) - - const getFullModulePath = (relativePath: string) => { - const fullPath = path.join(modulePath, relativePath) - debug.trace('Getting full module path', { relativePath, fullPath }) - return fullPath - } - - const getFullTargetPath = (relativePath: string) => { - const fullPath = path.join(targetPath, relativePath) - debug.trace('Getting full target path', { relativePath, fullPath }) - return fullPath - } - - const targetFileExists = async (relativePath: string) => { - const path = resolve(targetPath, relativePath) - debug.trace('Checking if target file exists', { path }) - return await checkFileExists(path) - } - - const moduleFileExists = async (relativePath: string) => { - const path = resolve(modulePath, relativePath) - debug.trace('Checking if module file exists', { path }) - return await checkFileExists(path) - } - - const ctx: Ctx = { - targetFileExists, - moduleFileExists, - absoluteModuleFolder: getFullModulePath(modulePath), - absoluteTargetFolder: getFullTargetPath(targetPath), - getFullModulePath, - getFullTargetPath, - } - - debug.verbose('Created helper context', ctx) - - return { - ...ctx, - readTargetFile: createReadTargetFile({ - ctx, - modulePath, - targetPath, - }), - writeTargetfile: createWriteTargetFile({ - ctx, - modulePath, - targetPath, - }), - copyTemplateFiles: createCopyTemplateFiles({ - ctx, - modulePath, - targetPath, - }), - getTemplateFilesThatWouldBeOverwritten: - createGetTemplateFilesThatWouldBeOverwritten({ - ctx, - modulePath, - targetPath, - }), - } -} - -export const checkFileExists = async (path: string): Promise => { - debug.trace('Checking if file exists', { path }) - try { - await access(path, fs.constants.F_OK) - return true - } catch { - return false - } -} - -export const checkFolderExists = async (path: string): Promise => { - debug.trace('Checking if folder exists', { path }) - try { - await access(path, fs.constants.R_OK) - return true - } catch { - return false - } -} - -export const checkFolderIsEmpty = async (path: string): Promise => { - debug.trace('Checking if folder is empty', { path }) - try { - const files = await readdir(path) - return files.length === 0 - } catch { - return false - } -} - -const createReadTargetFile = helperFactory( - ({ ctx, targetPath }) => - async (relativePath: string) => { - debug.trace('Reading target file', { relativePath, targetPath }) - invariant( - await ctx.targetFileExists(relativePath), - `The file ${relativePath} doesn't exist`, - ) - const path = resolve(targetPath, relativePath) - return await readFile(path, 'utf-8') - }, -) - -export const createWriteTargetFile = helperFactory( - ({ targetPath }) => - async ( - relativePath: string, - content: string, - overwrite: boolean = false, - ) => { - debug.trace('Writing target file', { - relativePath, - targetPath, - overwrite, - }) - const path = resolve(targetPath, relativePath) - invariant( - !(!overwrite && (await checkFileExists(path))), - `File ${relativePath} already exists and overwrite is false`, - ) - await writeFile(path, content) - }, -) - -const DOT_PREFIX = '_dot_' - -const removeTsNoCheckHeader = async (filePath: string) => { - debug.trace('Removing ts-nocheck header', { filePath }) - // Template files will sometimes include // @ts-nocheck in the header of the file - // This is to avoid type checking in the template folders - // This function removes that header - - const content = await readFile(filePath, 'utf-8') - const lines = content.split('\n') - - let newContent = content - - if (lines[0]?.trim() === '// @ts-nocheck') { - newContent = lines.slice(1).join('\n').trimStart() - } - - await writeFile(filePath, newContent) -} - -async function copyDir(srcDir: string, destDir: string) { - debug.trace('Copying directory', { srcDir, destDir }) - await mkdir(destDir, { recursive: true }) - const files = await readdir(srcDir) - for (const file of files) { - const srcFile = resolve(srcDir, file) - const destFile = resolve(destDir, file) - await copy(srcFile, destFile) - } -} - -async function copy(src: string, dest: string) { - debug.trace('Copying file', { src, dest }) - const statResult = await stat(src) - const replacedDest = dest.replaceAll(DOT_PREFIX, '.') - if (statResult.isDirectory()) { - await copyDir(src, replacedDest) - } else { - await copyFile(src, replacedDest) - await removeTsNoCheckHeader(replacedDest) - } -} - -export const createGetTemplateFilesThatWouldBeOverwritten = helperFactory( - ({ ctx }) => - async ({ - file, - templateFolder, - targetFolder, - overwrite, - }: { - file: string - templateFolder: string - targetFolder: string - overwrite: boolean - }) => { - debug.verbose('Checking for files that would be overwritten', { - file, - templateFolder, - targetFolder, - overwrite, - }) - const overwrittenFiles: Array = [] - - if (overwrite) [] - - const absoluteTemplateFolder = ctx.getFullModulePath(templateFolder) - const absoluteTargetFolder = ctx.getFullTargetPath(targetFolder) - - const files = await fastGlob.glob(file, { - cwd: absoluteTemplateFolder, - onlyFiles: false, - }) - - for (const file of files) { - const exists = await checkFileExists( - resolve(absoluteTargetFolder, file), - ) - if (exists) { - debug.verbose('Found file that would be overwritten', { file }) - overwrittenFiles.push(file) - } - } - - return overwrittenFiles - }, -) - -export const createCopyTemplateFiles = helperFactory( - ({ ctx }) => - async ({ - file, - templateFolder, - targetFolder, - overwrite, - }: { - file: string - templateFolder: string - targetFolder: string - overwrite: boolean - }) => { - debug.verbose('Copying template files', { - file, - templateFolder, - targetFolder, - overwrite, - }) - const absoluteTemplateFolder = ctx.getFullModulePath(templateFolder) - const absoluteTargetFolder = ctx.getFullTargetPath(targetFolder) - - const templateFolderExists = checkFolderExists(absoluteTemplateFolder) - invariant( - templateFolderExists, - `The template folder ${templateFolder} doesn't exist`, - ) - - const files = await fastGlob.glob(file, { - cwd: absoluteTemplateFolder, - onlyFiles: false, - }) - - for (const file of files) { - if (overwrite) { - invariant( - await checkFileExists(resolve(absoluteTargetFolder, file)), - `The file ${file} couldn't be created because it would overwrite an existing file`, - ) - } - - debug.trace('Copying template file', { file }) - await copy( - resolve(absoluteTemplateFolder, file), - resolve(absoluteTargetFolder, file), - ) - } - }, -) diff --git a/packages/create-start/src/utils/runCmd.ts b/packages/create-start/src/utils/runCmd.ts deleted file mode 100644 index 0b3634a2945..00000000000 --- a/packages/create-start/src/utils/runCmd.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { spawnCommand } from './spawnCmd' - -export async function runCmd( - command: string, - args: Array, - env: NodeJS.ProcessEnv = {}, - cwd?: string, -) { - return spawnCommand(command, args, env, cwd) -} diff --git a/packages/create-start/src/utils/runPackageManagerCommand.ts b/packages/create-start/src/utils/runPackageManagerCommand.ts deleted file mode 100644 index 9e7d054f200..00000000000 --- a/packages/create-start/src/utils/runPackageManagerCommand.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { spawnCommand } from './spawnCmd' -import type { PackageManager } from '../constants' - -export async function runPackageManagerCommand( - packageManager: PackageManager, - args: Array, - env: NodeJS.ProcessEnv = {}, - cwd?: string, -) { - return spawnCommand(packageManager, args, env, cwd) -} - -export async function install(packageManager: PackageManager, cwd?: string) { - return runPackageManagerCommand( - packageManager, - ['install'], - { - NODE_ENV: 'development', - }, - cwd, - ) -} - -export async function build(packageManager: PackageManager, cwd?: string) { - return runPackageManagerCommand(packageManager, ['run', 'build'], {}, cwd) -} diff --git a/packages/create-start/src/utils/spawnCmd.ts b/packages/create-start/src/utils/spawnCmd.ts deleted file mode 100644 index 0525e2ae7b4..00000000000 --- a/packages/create-start/src/utils/spawnCmd.ts +++ /dev/null @@ -1,39 +0,0 @@ -import spawn from 'cross-spawn' - -export async function spawnCommand( - command: string, - args: Array, - env: NodeJS.ProcessEnv = {}, - cwd?: string, -) { - return new Promise((resolve, reject) => { - const child = spawn(command, args, { - env: { - ...process.env, - ...env, - }, - stdio: ['pipe', 'pipe', 'pipe'], - cwd, - }) - let stderrBuffer = '' - let stdoutBuffer = '' - - child.stderr?.on('data', (data) => { - stderrBuffer += data - }) - - child.stdout?.on('data', (data) => { - stdoutBuffer += data - }) - - child.on('close', (code) => { - if (code !== 0) { - reject( - `"${command} ${args.join(' ')}" failed ${stdoutBuffer} ${stderrBuffer}`, - ) - return - } - resolve() - }) - }) -} diff --git a/packages/create-start/src/utils/validateProjectName.ts b/packages/create-start/src/utils/validateProjectName.ts deleted file mode 100644 index dc1366ab4ac..00000000000 --- a/packages/create-start/src/utils/validateProjectName.ts +++ /dev/null @@ -1,25 +0,0 @@ -import validate from 'validate-npm-package-name' - -type ValidatationResult = - | { - valid: true - } - | { - valid: false - problems: Array - } - -export function validateProjectName(name: string): ValidatationResult { - const nameValidation = validate(name) - if (nameValidation.validForNewPackages) { - return { valid: true } - } - - return { - valid: false, - problems: [ - ...(nameValidation.errors || []), - ...(nameValidation.warnings || []), - ], - } -} diff --git a/packages/create-start/tests/e2e/cli.test.ts b/packages/create-start/tests/e2e/cli.test.ts deleted file mode 100644 index c03a4fc767b..00000000000 --- a/packages/create-start/tests/e2e/cli.test.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { readFile } from 'node:fs/promises' -import { join } from 'node:path' -import { describe, expect, it } from 'vitest' -import { temporaryDirectoryTask } from 'tempy' -import { runCli } from '../../src/cli' - -const constructCliArgs = ({ - template, - directory, - packageName, - packageManager, - installDeps, - initGit, - hideLogo, - ide, -}: { - template?: string - directory?: string - packageName?: string - packageManager?: string - installDeps?: boolean - initGit?: boolean - hideLogo?: boolean - ide?: string -}) => { - return [ - 'node', - 'cli.js', - '--template', - template ?? 'barebones', - '--directory', - directory ?? '', - '--package-name', - packageName ?? '', - '--package-manager', - packageManager ?? 'npm', - ...(installDeps === false ? ['--no-install-deps'] : []), - ...(initGit === false ? ['--no-init-git'] : []), - ...(hideLogo ? ['--hide-logo'] : []), - ...(ide ? ['--ide', ide] : []), - ] -} - -describe('cli e2e', () => { - it('should create a basic project structure using CLI', async () => { - await temporaryDirectoryTask(async (tempDir) => { - const args = constructCliArgs({ - template: 'barebones', - directory: tempDir, - packageName: 'test-package', - packageManager: 'npm', - installDeps: false, - hideLogo: true, - ide: 'vscode', - initGit: false, - }) - - await runCli(args) - - // Check core files exist - const expectedFiles = [ - '.gitignore', - 'package.json', - 'tsconfig.json', - 'app.config.ts', - 'app/client.tsx', - 'app/router.tsx', - 'app/routes/__root.tsx', - 'app/routes/index.tsx', - '.vscode/settings.json', - ] - - for (const file of expectedFiles) { - const filePath = join(tempDir, file) - const exists = await readFile(filePath) - expect(exists).toBeDefined() - } - }) - }) - - it('should create project in current directory when using "." as directory', async () => { - await temporaryDirectoryTask(async (tempDir) => { - const args = constructCliArgs({ - template: 'barebones', - directory: '.', - packageName: 'test-package', - packageManager: 'npm', - installDeps: false, - hideLogo: true, - ide: 'vscode', - initGit: false, - }) - - // Run CLI from the temporary directory - process.chdir(tempDir) - await runCli(args) - - // Check core files exist in current directory - const expectedFiles = [ - 'package.json', - 'tsconfig.json', - 'app.config.ts', - 'app/client.tsx', - 'app/router.tsx', - 'app/routes/__root.tsx', - 'app/routes/index.tsx', - '.vscode/settings.json', - ] - - for (const file of expectedFiles) { - const filePath = join(tempDir, file) - const exists = await readFile(filePath) - expect(exists).toBeDefined() - } - - // Reset working directory - process.chdir('..') - }) - }) - - it('should fail when using an incorrect directory name', async () => { - const args = constructCliArgs({ - template: 'barebones', - directory: '/invalid/directory/path', - packageName: 'test-package', - packageManager: 'npm', - installDeps: false, - hideLogo: true, - ide: 'vscode', - initGit: false, - }) - - await expect(runCli(args)).rejects.toThrow() - }) -}) diff --git a/packages/create-start/tests/e2e/templates/barebones.test.ts b/packages/create-start/tests/e2e/templates/barebones.test.ts deleted file mode 100644 index f509937d329..00000000000 --- a/packages/create-start/tests/e2e/templates/barebones.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { join } from 'node:path' -import { readFile } from 'node:fs/promises' -import { describe, expect, it } from 'vitest' -import { temporaryDirectoryTask } from 'tempy' -import { barebonesTemplate } from '../../../src/templates/barebones' - -const base = (tmpDir: string) => ({ - cfg: { - packageManager: { - installDeps: false, - packageManager: 'npm' as const, - }, - git: { - setupGit: false, - }, - packageJson: { - type: 'new' as const, - name: 'test', - }, - ide: { - ide: 'vscode' as const, - }, - }, - targetPath: tmpDir, - type: 'new-project' as const, -}) - -describe('barebones template e2e', () => { - it('should create a basic project structure', async () => { - await temporaryDirectoryTask(async (tempDir) => { - await barebonesTemplate.execute(base(tempDir)) - - // Check core files exist - const expectedFiles = [ - 'package.json', - 'tsconfig.json', - 'app.config.ts', - 'app/client.tsx', - 'app/router.tsx', - 'app/routes/__root.tsx', - 'app/routes/index.tsx', - '.vscode/settings.json', - ] - - for (const file of expectedFiles) { - const filePath = join(tempDir, file) - const exists = await readFile(filePath) - expect(exists).toBeDefined() - } - }) - }) - - it('should have valid package.json contents', async () => { - await temporaryDirectoryTask(async (tempDir) => { - await barebonesTemplate.execute(base(tempDir)) - - const pkgJsonPath = join(tempDir, 'package.json') - const pkgJson = JSON.parse(await readFile(pkgJsonPath, 'utf-8')) - - expect(pkgJson.name).toBe('test') - expect(pkgJson.private).toBe(true) - expect(pkgJson.type).toBe('module') - expect(pkgJson.dependencies).toBeDefined() - expect(pkgJson.dependencies['@tanstack/react-router']).toBeDefined() - expect(pkgJson.dependencies['@tanstack/react-start']).toBeDefined() - expect(pkgJson.dependencies['react']).toBeDefined() - expect(pkgJson.dependencies['react-dom']).toBeDefined() - expect(pkgJson.dependencies['vinxi']).toBeDefined() - - expect(pkgJson.devDependencies).toBeDefined() - expect(pkgJson.devDependencies['@types/react']).toBeDefined() - - expect(pkgJson.scripts).toBeDefined() - expect(pkgJson.scripts.dev).toBe('vinxi dev') - expect(pkgJson.scripts.build).toBe('vinxi build') - expect(pkgJson.scripts.start).toBe('vinxi start') - }) - }) -}) diff --git a/packages/create-start/tsconfig.json b/packages/create-start/tsconfig.json deleted file mode 100644 index 747f8933df2..00000000000 --- a/packages/create-start/tsconfig.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "module": "ESNext" - }, - "moduleResolution": "Bundler", - "include": ["src", "tests", "build.config.ts"] -} diff --git a/packages/create-start/vitest.config.ts b/packages/create-start/vitest.config.ts deleted file mode 100644 index f5b965c618d..00000000000 --- a/packages/create-start/vitest.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from 'vitest/config' -import packageJson from './package.json' - -const config = defineConfig({ - test: { - name: packageJson.name, - dir: './tests', - watch: false, - environment: 'node', - typecheck: { enabled: true }, - }, -}) - -export default config diff --git a/packages/directive-functions-plugin/package.json b/packages/directive-functions-plugin/package.json index 8f0cee2cd5c..7b07f0e0d47 100644 --- a/packages/directive-functions-plugin/package.json +++ b/packages/directive-functions-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/directive-functions-plugin", - "version": "1.115.0", + "version": "1.119.2", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/directive-functions-plugin/src/compilers.ts b/packages/directive-functions-plugin/src/compilers.ts index da0fe941bce..463f5e879e8 100644 --- a/packages/directive-functions-plugin/src/compilers.ts +++ b/packages/directive-functions-plugin/src/compilers.ts @@ -288,24 +288,19 @@ export function findDirectives( babel.traverse(ast, { DirectiveLiteral(nodePath) { if (nodePath.node.value === opts.directive) { - const directiveFn = nodePath.findParent((p) => p.isFunction()) as - | SupportedFunctionPath - | undefined + const directiveFn = nodePath.findParent((p) => p.isFunction()) if (!directiveFn) return // Handle class and object methods which are not supported - const isGenerator = - directiveFn.isFunction() && directiveFn.node.generator - const isClassMethod = directiveFn.isClassMethod() const isObjectMethod = directiveFn.isObjectMethod() - if (isClassMethod || isObjectMethod || isGenerator) { + if (isClassMethod || isObjectMethod) { throw codeFrameError( opts.code, directiveFn.node.loc, - `"${opts.directive}" in ${isClassMethod ? 'class' : isObjectMethod ? 'object method' : 'generator function'} not supported`, + `"${opts.directive}" in ${isClassMethod ? 'class' : isObjectMethod ? 'object method' : ''} not supported`, ) } diff --git a/packages/directive-functions-plugin/tests/compiler.test.ts b/packages/directive-functions-plugin/tests/compiler.test.ts index a7ff05be977..a2c7fd3fc57 100644 --- a/packages/directive-functions-plugin/tests/compiler.test.ts +++ b/packages/directive-functions-plugin/tests/compiler.test.ts @@ -38,75 +38,91 @@ const serverConfig: Omit = { } describe('server function compilation', () => { - const code = ` - export const namedFunction = createServerFn(function namedFunction() { - 'use server' - return 'hello' - }) - - export const arrowFunction = createServerFn(() => { - 'use server' - return 'hello' - }) - - export const anonymousFunction = createServerFn(function () { - 'use server' - return 'hello' - }) - - export const multipleDirectives = function multipleDirectives() { - 'use server' - 'use strict' - return 'hello' - } - - export const iife = (function () { - 'use server' - return 'hello' - })() - - export default function defaultExportFn() { - 'use server' - return 'hello' - } - - export function namedExportFn() { - 'use server' - return 'hello' - } - - export const exportedArrowFunction = wrapper(() => { - 'use server' - return 'hello' - }) - - export const namedExportConst = () => { - 'use server' - return usedFn() - } - - function usedFn() { - return 'hello' - } - - function unusedFn() { - return 'hello' - } - - const namedDefaultExport = 'namedDefaultExport' - export default namedDefaultExport - - const usedButNotExported = 'usedButNotExported' - - const namedExport = 'namedExport' - - export { - namedExport - } + test('basic function declaration nested in other variable', () => { + const code = ` + export const namedFunction = createServerFn(function namedFunction() { + 'use server' + return 'hello' + }) + + export const namedGeneratorFunction = createServerFn(function* namedGeneratorFunction () { + 'use server' + yield 'hello' + return 'hello world' + }) + + export const arrowFunction = createServerFn(() => { + 'use server' + return 'hello' + }) + + export const anonymousFunction = createServerFn(function () { + 'use server' + return 'hello' + }) - ` + export const anonymousGeneratorFunction = createServerFn(function* () { + 'use server' + yield 'hello' + return 'hello world' + }) + + export const multipleDirectives = function multipleDirectives() { + 'use server' + 'use strict' + return 'hello' + } + + export const iife = (function () { + 'use server' + return 'hello' + })() + + export default function defaultExportFn() { + 'use server' + return 'hello' + } + + export function namedExportFn() { + 'use server' + return 'hello' + } + + export const exportedArrowFunction = wrapper(() => { + 'use server' + return 'hello' + }) + + export const namedExportConst = () => { + 'use server' + return usedFn() + } - test('basic function declaration nested in other variable', () => { + export const namedExportConstGenerator = function* () { + 'use server' + yield 'hello' + return usedFn() + } + + function usedFn() { + return 'hello' + } + + function unusedFn() { + return 'hello' + } + + const namedDefaultExport = 'namedDefaultExport' + export default namedDefaultExport + + const usedButNotExported = 'usedButNotExported' + + const namedExport = 'namedExport' + + export { + namedExport + } + ` const client = compileDirectives({ ...clientConfig, code, @@ -123,10 +139,14 @@ describe('server function compilation', () => { "import { createClientRpc } from "my-rpc-lib-client"; const namedFunction_createServerFn_namedFunction = createClientRpc("test_ts--namedFunction_createServerFn_namedFunction"); export const namedFunction = createServerFn(namedFunction_createServerFn_namedFunction); + const namedGeneratorFunction_createServerFn_namedGeneratorFunction = createClientRpc("test_ts--namedGeneratorFunction_createServerFn_namedGeneratorFunction"); + export const namedGeneratorFunction = createServerFn(namedGeneratorFunction_createServerFn_namedGeneratorFunction); const arrowFunction_createServerFn = createClientRpc("test_ts--arrowFunction_createServerFn"); export const arrowFunction = createServerFn(arrowFunction_createServerFn); const anonymousFunction_createServerFn = createClientRpc("test_ts--anonymousFunction_createServerFn"); export const anonymousFunction = createServerFn(anonymousFunction_createServerFn); + const anonymousGeneratorFunction_createServerFn = createClientRpc("test_ts--anonymousGeneratorFunction_createServerFn"); + export const anonymousGeneratorFunction = createServerFn(anonymousGeneratorFunction_createServerFn); const multipleDirectives_multipleDirectives = createClientRpc("test_ts--multipleDirectives_multipleDirectives"); export const multipleDirectives = multipleDirectives_multipleDirectives; const iife_1 = createClientRpc("test_ts--iife_1"); @@ -139,6 +159,8 @@ describe('server function compilation', () => { export const exportedArrowFunction = wrapper(exportedArrowFunction_wrapper); const namedExportConst_1 = createClientRpc("test_ts--namedExportConst_1"); export const namedExportConst = namedExportConst_1; + const namedExportConstGenerator_1 = createClientRpc("test_ts--namedExportConstGenerator_1"); + export const namedExportConstGenerator = namedExportConstGenerator_1; function unusedFn() { return 'hello'; } @@ -153,10 +175,14 @@ describe('server function compilation', () => { "import { createSsrRpc } from "my-rpc-lib-server"; const namedFunction_createServerFn_namedFunction = createSsrRpc("test_ts--namedFunction_createServerFn_namedFunction"); export const namedFunction = createServerFn(namedFunction_createServerFn_namedFunction); + const namedGeneratorFunction_createServerFn_namedGeneratorFunction = createSsrRpc("test_ts--namedGeneratorFunction_createServerFn_namedGeneratorFunction"); + export const namedGeneratorFunction = createServerFn(namedGeneratorFunction_createServerFn_namedGeneratorFunction); const arrowFunction_createServerFn = createSsrRpc("test_ts--arrowFunction_createServerFn"); export const arrowFunction = createServerFn(arrowFunction_createServerFn); const anonymousFunction_createServerFn = createSsrRpc("test_ts--anonymousFunction_createServerFn"); export const anonymousFunction = createServerFn(anonymousFunction_createServerFn); + const anonymousGeneratorFunction_createServerFn = createSsrRpc("test_ts--anonymousGeneratorFunction_createServerFn"); + export const anonymousGeneratorFunction = createServerFn(anonymousGeneratorFunction_createServerFn); const multipleDirectives_multipleDirectives = createSsrRpc("test_ts--multipleDirectives_multipleDirectives"); export const multipleDirectives = multipleDirectives_multipleDirectives; const iife_1 = createSsrRpc("test_ts--iife_1"); @@ -169,6 +195,8 @@ describe('server function compilation', () => { export const exportedArrowFunction = wrapper(exportedArrowFunction_wrapper); const namedExportConst_1 = createSsrRpc("test_ts--namedExportConst_1"); export const namedExportConst = namedExportConst_1; + const namedExportConstGenerator_1 = createSsrRpc("test_ts--namedExportConstGenerator_1"); + export const namedExportConstGenerator = namedExportConstGenerator_1; function unusedFn() { return 'hello'; } @@ -185,12 +213,20 @@ describe('server function compilation', () => { const namedFunction_createServerFn_namedFunction = createServerRpc("test_ts--namedFunction_createServerFn_namedFunction", function namedFunction() { return 'hello'; }); + const namedGeneratorFunction_createServerFn_namedGeneratorFunction = createServerRpc("test_ts--namedGeneratorFunction_createServerFn_namedGeneratorFunction", function* namedGeneratorFunction() { + yield 'hello'; + return 'hello world'; + }); const arrowFunction_createServerFn = createServerRpc("test_ts--arrowFunction_createServerFn", () => { return 'hello'; }); const anonymousFunction_createServerFn = createServerRpc("test_ts--anonymousFunction_createServerFn", function () { return 'hello'; }); + const anonymousGeneratorFunction_createServerFn = createServerRpc("test_ts--anonymousGeneratorFunction_createServerFn", function* () { + yield 'hello'; + return 'hello world'; + }); const multipleDirectives_multipleDirectives = createServerRpc("test_ts--multipleDirectives_multipleDirectives", function multipleDirectives() { 'use strict'; @@ -211,6 +247,10 @@ describe('server function compilation', () => { const namedExportConst_1 = createServerRpc("test_ts--namedExportConst_1", () => { return usedFn(); }); + const namedExportConstGenerator_1 = createServerRpc("test_ts--namedExportConstGenerator_1", function* () { + yield 'hello'; + return usedFn(); + }); function usedFn() { return 'hello'; } @@ -219,7 +259,7 @@ describe('server function compilation', () => { } const usedButNotExported = 'usedButNotExported'; const namedExportFn = namedExportFn_1; - export { namedFunction_createServerFn_namedFunction, arrowFunction_createServerFn, anonymousFunction_createServerFn, multipleDirectives_multipleDirectives, iife_1, defaultExportFn_1, namedExportFn_1, exportedArrowFunction_wrapper, namedExportConst_1 };" + export { namedFunction_createServerFn_namedFunction, namedGeneratorFunction_createServerFn_namedGeneratorFunction, arrowFunction_createServerFn, anonymousFunction_createServerFn, anonymousGeneratorFunction_createServerFn, multipleDirectives_multipleDirectives, iife_1, defaultExportFn_1, namedExportFn_1, exportedArrowFunction_wrapper, namedExportConst_1, namedExportConstGenerator_1 };" `, ) }) @@ -292,30 +332,6 @@ describe('server function compilation', () => { ).toThrow() }) - test('does not support generator functions', () => { - const code = ` - function* generatorServer() { - 'use server' - yield 'hello' - } - - async function* asyncGeneratorServer() { - 'use server' - yield 'hello' - } - ` - - expect(() => compileDirectives({ ...clientConfig, code })).toThrow() - expect(() => compileDirectives({ ...serverConfig, code })).toThrow() - expect(() => - compileDirectives({ - ...serverConfig, - code, - filename: serverConfig.filename + `?tsr-serverfn-split=temp`, - }), - ).toThrow() - }) - test('multiple directiveFnsById', () => { const code = ` function multiDirective() { @@ -787,4 +803,83 @@ describe('server function compilation', () => { export { bytesSignupServerFn_1 };" `) }) + + test('generator function', () => { + const code = ` + function* generator() { + 'use server' + yield 'hello' + return 'hello world' + } + ` + const client = compileDirectives({ + ...clientConfig, + code, + }) + const ssr = compileDirectives({ ...ssrConfig, code }) + + const server = compileDirectives({ + ...serverConfig, + code, + filename: `${ssr.directiveFnsById[Object.keys(ssr.directiveFnsById)[0]!]!.extractedFilename}`, + }) + + expect(client.compiledResult.code).toMatchInlineSnapshot(` + "import { createClientRpc } from "my-rpc-lib-client"; + const generator_1 = createClientRpc("test_ts--generator_1"); + const generator = generator_1;"`) + + expect(ssr.compiledResult.code).toMatchInlineSnapshot(` + "import { createSsrRpc } from "my-rpc-lib-server"; + const generator_1 = createSsrRpc("test_ts--generator_1"); + const generator = generator_1;"`) + + expect(server.compiledResult.code).toMatchInlineSnapshot(` + "import { createServerRpc } from "my-rpc-lib-server"; + const generator_1 = createServerRpc("test_ts--generator_1", function* () { + yield 'hello'; + return 'hello world'; + }); + const generator = generator_1; + export { generator_1 };"`) + }) + test('async generator function', () => { + const code = ` + async function* asyncGenerator() { + 'use server' + yield 'hello' + return 'hello world' + } + ` + const client = compileDirectives({ + ...clientConfig, + code, + }) + const ssr = compileDirectives({ ...ssrConfig, code }) + + const server = compileDirectives({ + ...serverConfig, + code, + filename: `${ssr.directiveFnsById[Object.keys(ssr.directiveFnsById)[0]!]!.extractedFilename}`, + }) + + expect(client.compiledResult.code).toMatchInlineSnapshot(` + "import { createClientRpc } from "my-rpc-lib-client"; + const asyncGenerator_1 = createClientRpc("test_ts--asyncGenerator_1"); + const asyncGenerator = asyncGenerator_1;"`) + + expect(ssr.compiledResult.code).toMatchInlineSnapshot(` + "import { createSsrRpc } from "my-rpc-lib-server"; + const asyncGenerator_1 = createSsrRpc("test_ts--asyncGenerator_1"); + const asyncGenerator = asyncGenerator_1;"`) + + expect(server.compiledResult.code).toMatchInlineSnapshot(` + "import { createServerRpc } from "my-rpc-lib-server"; + const asyncGenerator_1 = createServerRpc("test_ts--asyncGenerator_1", async function* () { + yield 'hello'; + return 'hello world'; + }); + const asyncGenerator = asyncGenerator_1; + export { asyncGenerator_1 };"`) + }) }) diff --git a/packages/react-router-devtools/package.json b/packages/react-router-devtools/package.json index 2aa10fcaa1d..ef2a483c58a 100644 --- a/packages/react-router-devtools/package.json +++ b/packages/react-router-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-router-devtools", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx b/packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx index 2940f4e4f74..fc401606fe0 100644 --- a/packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx +++ b/packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx @@ -38,7 +38,7 @@ export const TanStackRouterDevtoolsPanel: React.FC = ( props, ): React.ReactElement | null => { const { router: propsRouter, ...rest } = props - const hookRouter = useRouter({ warn: propsRouter !== undefined }) + const hookRouter = useRouter({ warn: false }) const activeRouter = propsRouter ?? hookRouter const activeRouterState = useRouterState({ router: activeRouter }) diff --git a/packages/react-router-with-query/package.json b/packages/react-router-with-query/package.json index e5ab2496d7f..3667ef06c1c 100644 --- a/packages/react-router-with-query/package.json +++ b/packages/react-router-with-query/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-router-with-query", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 520358cda13..203e368ada2 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-router", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index ae4fd238741..56fba11d386 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -452,9 +452,12 @@ export type CreateLinkProps = LinkProps< string > -export type LinkComponent = < +export type LinkComponent< + in out TComp, + in out TDefaultFrom extends string = string, +> = < TRouter extends AnyRouter = RegisteredRouter, - const TFrom extends string = string, + const TFrom extends string = TDefaultFrom, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = '', diff --git a/packages/react-router/src/route.ts b/packages/react-router/src/route.tsx similarity index 92% rename from packages/react-router/src/route.ts rename to packages/react-router/src/route.tsx index f9c8898cfe8..105341feb22 100644 --- a/packages/react-router/src/route.ts +++ b/packages/react-router/src/route.tsx @@ -4,6 +4,7 @@ import { BaseRouteApi, notFound, } from '@tanstack/router-core' +import React from 'react' import { useLoaderData } from './useLoaderData' import { useLoaderDeps } from './useLoaderDeps' import { useParams } from './useParams' @@ -11,6 +12,7 @@ import { useSearch } from './useSearch' import { useNavigate } from './useNavigate' import { useMatch } from './useMatch' import { useRouter } from './useRouter' +import { Link } from './link' import type { AnyContext, AnyRoute, @@ -39,8 +41,8 @@ import type { UseMatchRoute } from './useMatch' import type { UseLoaderDepsRoute } from './useLoaderDeps' import type { UseParamsRoute } from './useParams' import type { UseSearchRoute } from './useSearch' -import type * as React from 'react' import type { UseRouteContextRoute } from './useRouteContext' +import type { LinkComponent } from './link' declare module '@tanstack/router-core' { export interface UpdatableRouteOptionsExtensions { @@ -61,6 +63,7 @@ declare module '@tanstack/router-core' { useLoaderDeps: UseLoaderDepsRoute useLoaderData: UseLoaderDataRoute useNavigate: () => UseNavigateResult + Link: LinkComponent<'a', TFullPath> } } @@ -133,6 +136,16 @@ export class RouteApi< notFound = (opts?: NotFoundError) => { return notFound({ routeId: this.id as string, ...opts }) } + + Link: LinkComponent<'a', RouteTypesById['fullPath']> = + React.forwardRef((props, ref: React.ForwardedRef) => { + const router = useRouter() + const fullPath = router.routesById[this.id as string].fullPath + return + }) as unknown as LinkComponent< + 'a', + RouteTypesById['fullPath'] + > } export class Route< @@ -241,6 +254,12 @@ export class Route< useNavigate = (): UseNavigateResult => { return useNavigate({ from: this.fullPath }) } + + Link: LinkComponent<'a', TFullPath> = React.forwardRef( + (props, ref: React.ForwardedRef) => { + return + }, + ) as unknown as LinkComponent<'a', TFullPath> } export function createRoute< @@ -426,6 +445,12 @@ export class RootRoute< useNavigate = (): UseNavigateResult<'/'> => { return useNavigate({ from: this.fullPath }) } + + Link: LinkComponent<'a', '/'> = React.forwardRef( + (props, ref: React.ForwardedRef) => { + return + }, + ) as unknown as LinkComponent<'a', '/'> } export function createRootRoute< diff --git a/packages/react-router/tests/routeApi.test-d.tsx b/packages/react-router/tests/routeApi.test-d.tsx index 972be17b5e9..de7ff81ca36 100644 --- a/packages/react-router/tests/routeApi.test-d.tsx +++ b/packages/react-router/tests/routeApi.test-d.tsx @@ -1,6 +1,6 @@ import { describe, expectTypeOf, test } from 'vitest' import { createRootRoute, createRoute, createRouter, getRouteApi } from '../src' -import type { MakeRouteMatch, UseNavigateResult } from '../src' +import type { LinkComponent, MakeRouteMatch, UseNavigateResult } from '../src' const rootRoute = createRootRoute() @@ -87,6 +87,12 @@ describe('getRouteApi', () => { MakeRouteMatch >() }) + test('Link', () => { + const Link = invoiceRouteApi.Link + expectTypeOf(Link).toEqualTypeOf< + LinkComponent<'a', '/invoices/$invoiceId'> + >() + }) }) describe('createRoute', () => { diff --git a/packages/react-start-client/package.json b/packages/react-start-client/package.json index edadd908711..0eacdcd9c81 100644 --- a/packages/react-start-client/package.json +++ b/packages/react-start-client/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-start-client", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-start-config/package.json b/packages/react-start-config/package.json index 928e7f01563..29cdd967c57 100644 --- a/packages/react-start-config/package.json +++ b/packages/react-start-config/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-start-config", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-start-config/src/index.ts b/packages/react-start-config/src/index.ts index 7d8c8475df9..ac30bf21406 100644 --- a/packages/react-start-config/src/index.ts +++ b/packages/react-start-config/src/index.ts @@ -87,9 +87,7 @@ export async function defineConfig( const { preset: configDeploymentPreset, ...serverOptions } = serverSchema.parse(opts.server || {}) - const deploymentPreset = checkDeploymentPresetInput( - configDeploymentPreset || 'node-server', - ) + const deploymentPreset = checkDeploymentPresetInput(configDeploymentPreset) const tsr = setTsrDefaults(opts.tsr) const tsrConfig = getConfig(tsr) diff --git a/packages/react-start-config/src/schema.ts b/packages/react-start-config/src/schema.ts index 516e4e86fa5..45294837939 100644 --- a/packages/react-start-config/src/schema.ts +++ b/packages/react-start-config/src/schema.ts @@ -80,19 +80,23 @@ const testedDeploymentPresets: Array = [ 'node-server', ] -export function checkDeploymentPresetInput(preset: string): DeploymentPreset { - if (!vinxiDeploymentPresets.includes(preset as any)) { - console.warn( - `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets - .map((p) => `"${p}"`) - .join(', ')}.`, - ) - } - - if (!testedDeploymentPresets.includes(preset as any)) { - console.warn( - `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, - ) +export function checkDeploymentPresetInput( + preset?: string, +): DeploymentPreset | undefined { + if (preset) { + if (!vinxiDeploymentPresets.includes(preset as any)) { + console.warn( + `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets + .map((p) => `"${p}"`) + .join(', ')}.`, + ) + } + + if (!testedDeploymentPresets.includes(preset as any)) { + console.warn( + `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, + ) + } } return preset diff --git a/packages/react-start-router-manifest/package.json b/packages/react-start-router-manifest/package.json index be7c7ddec48..09d5ea55fee 100644 --- a/packages/react-start-router-manifest/package.json +++ b/packages/react-start-router-manifest/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-start-router-manifest", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-start-server/package.json b/packages/react-start-server/package.json index 57f14f8d3f3..c8ca486ef80 100644 --- a/packages/react-start-server/package.json +++ b/packages/react-start-server/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-start-server", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/react-start/package.json b/packages/react-start/package.json index c113f852c92..a08d2c78daa 100644 --- a/packages/react-start/package.json +++ b/packages/react-start/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-start", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-cli/package.json b/packages/router-cli/package.json index c7c57695917..59f061b5e9c 100644 --- a/packages/router-cli/package.json +++ b/packages/router-cli/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-cli", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-core/package.json b/packages/router-core/package.json index f0fc92d4c10..3daafd8a957 100644 --- a/packages/router-core/package.json +++ b/packages/router-core/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-core", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-core/src/path.ts b/packages/router-core/src/path.ts index f2daff5104f..4d002673cdb 100644 --- a/packages/router-core/src/path.ts +++ b/packages/router-core/src/path.ts @@ -216,6 +216,7 @@ interface InterpolatePathOptions { type InterPolatePathResult = { interpolatedPath: string usedParams: Record + isMissingParams: boolean // true if any params were not available when being looked up in the params object } export function interpolatePath({ path, @@ -238,6 +239,10 @@ export function interpolatePath({ } } + // Tracking if any params are missing in the `params` object + // when interpolating the path + let isMissingParams = false + const usedParams: Record = {} const interpolatedPath = joinPaths( interpolatedPathSegments.map((segment) => { @@ -250,6 +255,9 @@ export function interpolatePath({ if (segment.type === 'param') { const key = segment.value.substring(1) + if (!isMissingParams && !(key in params)) { + isMissingParams = true + } usedParams[key] = params[key] if (leaveParams) { const value = encodeParam(segment.value) @@ -261,7 +269,7 @@ export function interpolatePath({ return segment.value }), ) - return { usedParams, interpolatedPath } + return { usedParams, interpolatedPath, isMissingParams } } function encodePathParam(value: string, decodeCharMap?: Map) { diff --git a/packages/router-core/src/router.ts b/packages/router-core/src/router.ts index e458e3e9311..f41b47fe2f9 100644 --- a/packages/router-core/src/router.ts +++ b/packages/router-core/src/router.ts @@ -670,7 +670,15 @@ export type AnyRouterWithContext = RouterCore< export type AnyRouter = RouterCore export interface ViewTransitionOptions { - types: Array + types: + | Array + | ((locationChangeInfo: { + fromLocation?: ParsedLocation + toLocation: ParsedLocation + pathChanged: boolean + hrefChanged: boolean + hashChanged: boolean + }) => Array) } export function defaultSerializeError(err: unknown) { @@ -2172,9 +2180,22 @@ export class RouterCore< typeof shouldViewTransition === 'object' && this.isViewTransitionTypesSupported ) { + const next = this.latestLocation + const prevLocation = this.state.resolvedLocation + + const resolvedViewTransitionTypes = + typeof shouldViewTransition.types === 'function' + ? shouldViewTransition.types( + getLocationChangeInfo({ + resolvedLocation: prevLocation, + location: next, + }), + ) + : shouldViewTransition.types + startViewTransitionParams = { update: fn, - types: shouldViewTransition.types, + types: resolvedViewTransitionTypes, } } else { startViewTransitionParams = fn @@ -2253,10 +2274,6 @@ export class RouterCore< return !!(allPreload && !this.state.matches.find((d) => d.id === matchId)) } - if (!this.isServer && !this.state.matches.length) { - triggerOnReady() - } - const handleRedirectAndNotFound = (match: AnyRouteMatch, err: any) => { if (isResolvedRedirect(err)) { if (!err.reloadDocument) { @@ -2362,7 +2379,9 @@ export class RouterCore< onReady && !this.isServer && !resolvePreload(matchId) && - (route.options.loader || route.options.beforeLoad) && + (route.options.loader || + route.options.beforeLoad || + routeNeedsPreload(route)) && typeof pendingMs === 'number' && pendingMs !== Infinity && (route.options.pendingComponent ?? @@ -2647,6 +2666,10 @@ export class RouterCore< loaderData, }) + // Last but not least, wait for the the components + // to be preloaded before we resolve the match + await route._componentsPromise + updateMatch(matchId, (prev) => ({ ...prev, error: undefined, @@ -2689,10 +2712,6 @@ export class RouterCore< router: this, match: this.getMatch(matchId)!, }) - - // Last but not least, wait for the the components - // to be preloaded before we resolve the match - await route._componentsPromise } catch (err) { updateMatch(matchId, (prev) => ({ ...prev, diff --git a/packages/router-core/tests/path.test.ts b/packages/router-core/tests/path.test.ts index 8c86975b1d0..0b709d24539 100644 --- a/packages/router-core/tests/path.test.ts +++ b/packages/router-core/tests/path.test.ts @@ -266,7 +266,7 @@ describe('resolvePath', () => { }) describe('interpolatePath', () => { - ;[ + it.each([ { name: 'should interpolate the path', path: '/users/$id', @@ -324,68 +324,177 @@ describe('interpolatePath', () => { ['@', '+'].map((char) => [encodeURIComponent(char), char]), ), }, - ].forEach((exp) => { - it(exp.name, () => { - const result = interpolatePath({ - path: exp.path, - params: exp.params, - decodeCharMap: exp.decodeCharMap, - }).interpolatedPath - expect(result).toBe(exp.result) - }) - }) -}) - -describe('matchPathname', () => { - it.each([ { - name: 'should match the root path that start with the basepath', - basepath: '/basepath', - pathname: '/basepath', - matchLocation: { - to: '/', - }, - expected: {}, + name: 'should interpolate the path with the splat param at the end', + path: '/users/$', + params: { _splat: '123' }, + result: '/users/123', }, { - name: 'should match the path that start with the basepath', - basepath: '/basepath', - pathname: '/basepath/abc', - matchLocation: { - to: '/abc', - }, - expected: {}, + name: 'should interpolate the path with a single named path param and the splat param at the end', + path: '/users/$username/$', + params: { username: 'seancassiere', _splat: '123' }, + result: '/users/seancassiere/123', }, { - name: 'should not match the root path that does not start with the basepath', - basepath: '/basepath', - pathname: '/', - matchLocation: { - to: '/', - }, - expected: undefined, + name: 'should interpolate the path with 2 named path params with the splat param at the end', + path: '/users/$username/$id/$', + params: { username: 'seancassiere', id: '123', _splat: '456' }, + result: '/users/seancassiere/123/456', }, { - name: 'should not match the path that does not start with the basepath', - basepath: '/basepath', - pathname: '/abc', - matchLocation: { - to: '/abc', + name: 'should interpolate the path with multiple named path params with the splat param at the end', + path: '/$username/settings/$repo/$id/$', + params: { + username: 'sean-cassiere', + repo: 'my-repo', + id: '123', + _splat: '456', }, - expected: undefined, + result: '/sean-cassiere/settings/my-repo/123/456', }, { - name: 'should not match the path that match partial of the basepath', - basepath: '/base', - pathname: '/basepath/abc', - matchLocation: { - to: '/abc', - }, - expected: undefined, + name: 'should interpolate the path with the splat param containing slashes', + path: '/users/$', + params: { _splat: 'sean/cassiere' }, + result: '/users/sean/cassiere', }, - ])('$name', ({ basepath, pathname, matchLocation, expected }) => { - expect(matchPathname(basepath, pathname, matchLocation)).toStrictEqual( - expected, + ])('$name', ({ path, params, decodeCharMap, result }) => { + expect( + interpolatePath({ + path, + params, + decodeCharMap, + }).interpolatedPath, + ).toBe(result) + }) +}) + +describe('matchPathname', () => { + describe('basepath matching', () => { + it.each([ + { + name: 'should match when the input is the same as the basepath', + basepath: '/basepath', + input: '/basepath', + matchingOptions: { + to: '/', + }, + expectedMatchedParams: {}, + }, + { + name: 'should match when the input starts with the basepath and `to` is set to the remaining', + basepath: '/basepath', + input: '/basepath/abc', + matchingOptions: { + to: '/abc', + }, + expectedMatchedParams: {}, + }, + { + name: 'should not match when the input is `/` and does not start with the basepath', + basepath: '/basepath', + input: '/', + matchingOptions: { + to: '/', + }, + expectedMatchedParams: undefined, + }, + { + name: 'should not match when the input completely does not start with the basepath', + basepath: '/basepath', + input: '/abc', + matchingOptions: { + to: '/abc', + }, + expectedMatchedParams: undefined, + }, + { + name: 'should not match when the input only partially matches the basepath', + basepath: '/base', + input: '/basepath/abc', + matchingOptions: { + to: '/abc', + }, + expectedMatchedParams: undefined, + }, + ])( + '$name', + ({ basepath, input, matchingOptions, expectedMatchedParams }) => { + expect(matchPathname(basepath, input, matchingOptions)).toStrictEqual( + expectedMatchedParams, + ) + }, ) }) + + describe('path param(s) matching', () => { + it.each([ + { + name: 'should not match since `to` does not match the input', + input: '/', + matchingOptions: { + to: '/users', + }, + expectedMatchedParams: undefined, + }, + { + name: 'should match since `to` matches the input', + input: '/users', + matchingOptions: { + to: '/users', + }, + expectedMatchedParams: {}, + }, + { + name: 'should match and return the named path params', + input: '/users/123', + matchingOptions: { + to: '/users/$id', + }, + expectedMatchedParams: { id: '123' }, + }, + { + name: 'should match and return the the splat param', + input: '/users/123', + matchingOptions: { + to: '/users/$', + }, + expectedMatchedParams: { + '*': '123', + _splat: '123', + }, + }, + { + name: 'should match and return the named path and splat params', + input: '/users/123/456', + matchingOptions: { + to: '/users/$id/$', + }, + expectedMatchedParams: { + id: '123', + '*': '456', + _splat: '456', + }, + }, + { + name: 'should match and return the multiple named path params and splat param', + input: '/sean-cassiere/settings/my-repo/123/456', + matchingOptions: { + to: '/$username/settings/$repo/$id/$', + }, + expectedMatchedParams: { + username: 'sean-cassiere', + repo: 'my-repo', + id: '123', + '*': '456', + _splat: '456', + }, + }, + ])('$name', ({ input, matchingOptions, expectedMatchedParams }) => { + expect(matchPathname('/', input, matchingOptions)).toStrictEqual( + expectedMatchedParams, + ) + }) + }) }) diff --git a/packages/router-devtools-core/package.json b/packages/router-devtools-core/package.json index b0b8fb822af..fe715ab3428 100644 --- a/packages/router-devtools-core/package.json +++ b/packages/router-devtools-core/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-devtools-core", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for Web applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx b/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx index b05428c9260..a84f318bc6e 100644 --- a/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx +++ b/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx @@ -1,7 +1,7 @@ import { clsx as cx } from 'clsx' import { default as invariant } from 'tiny-invariant' -import { rootRouteId, trimPath } from '@tanstack/router-core' -import { createMemo } from 'solid-js' +import { interpolatePath, rootRouteId, trimPath } from '@tanstack/router-core' +import { Show, createMemo } from 'solid-js' import { useDevtoolsOnClose } from './context' import { useStyles } from './useStyles' import useLocalStorage from './useLocalStorage' @@ -10,6 +10,7 @@ import { getRouteStatusColor, getStatusColor, multiSortBy } from './utils' import { AgeTicker } from './AgeTicker' // import type { DevtoolsPanelOptions } from './TanStackRouterDevtoolsPanel' +import { NavigateButton } from './NavigateButton' import type { AnyContext, AnyRoute, @@ -64,6 +65,28 @@ function Logo(props: any) { ) } +function NavigateLink(props: { + class?: string + left?: JSX.Element + children?: JSX.Element + right?: JSX.Element +}) { + return ( +
+ {props.left} +
{props.children}
+ {props.right} +
+ ) +} + function RouteComp({ routerState, router, @@ -126,6 +149,30 @@ function RouteComp({ } }) + const navigationTarget = createMemo(() => { + if (isRoot) return undefined // rootRouteId has no path + if (!route.path) return undefined // no path to navigate to + + // flatten all params in the router state, into a single object + const allParams = Object.assign({}, ...matches().map((m) => m.params)) + + // interpolatePath is used by router-core to generate the `to` + // path for the navigate function in the router + const interpolated = interpolatePath({ + path: route.fullPath, + params: allParams, + leaveWildcards: false, + leaveParams: false, + decodeCharMap: router().pathParamsDecodeCharMap, + }) + + // only if `interpolated` is not missing params, return the path since this + // means that all the params are present for a successful navigation + return !interpolated.isMissingParams + ? interpolated.interpolatedPath + : undefined + }) + return (
-
-
- - {isRoot ? rootRouteId : route.path || trimPath(route.id)}{' '} - - {param()} -
- -
+ + {(navigate) => } + + } + right={} + > + + {isRoot ? rootRouteId : route.path || trimPath(route.id)}{' '} + + {param()} +
{route.children?.length ? (
@@ -406,7 +458,7 @@ export const BaseTanStackRouterDevtoolsPanel = {(routerState().pendingMatches?.length ? routerState().pendingMatches : routerState().matches - )?.map((match: any, i: any) => { + )?.map((match: any, _i: any) => { return (
- - {`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`} - + + } + right={} + > + + {`${match.routeId === rootRouteId ? rootRouteId : match.pathname}`} + +
) })} @@ -457,10 +519,19 @@ export const BaseTanStackRouterDevtoolsPanel = styles().matchIndicator(getStatusColor(match)), )} /> - - {`${match.id}`} - - + + } + right={} + > + {`${match.id}`} +
) })} diff --git a/packages/router-devtools-core/src/NavigateButton.tsx b/packages/router-devtools-core/src/NavigateButton.tsx new file mode 100644 index 00000000000..8f9e5161fc5 --- /dev/null +++ b/packages/router-devtools-core/src/NavigateButton.tsx @@ -0,0 +1,25 @@ +import { useStyles } from './useStyles' +import type { AnyRouter, NavigateOptions } from '@tanstack/router-core' +import type { Accessor } from 'solid-js' + +interface Props extends NavigateOptions { + router: Accessor +} + +export function NavigateButton({ to, params, search, router }: Props) { + const styles = useStyles() + + return ( + + ) +} diff --git a/packages/router-devtools-core/src/useStyles.tsx b/packages/router-devtools-core/src/useStyles.tsx index 3ba7a9785dc..d1a12ad5753 100644 --- a/packages/router-devtools-core/src/useStyles.tsx +++ b/packages/router-devtools-core/src/useStyles.tsx @@ -370,6 +370,12 @@ const stylesFactory = (shadowDOMTarget?: ShadowRoot) => { return classes }, + routesRowInner: css` + display: 'flex'; + align-items: 'center'; + flex-grow: 1; + min-width: 0; + `, routeParamInfo: css` color: ${colors.gray[400]}; font-size: ${fontSize.xs}; @@ -385,6 +391,9 @@ const stylesFactory = (shadowDOMTarget?: ShadowRoot) => { code: css` font-size: ${fontSize.xs}; line-height: ${lineHeight['xs']}; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; `, matchesContainer: css` flex: 1 1 auto; @@ -579,6 +588,22 @@ const stylesFactory = (shadowDOMTarget?: ShadowRoot) => { width: ${size[2]}; height: ${size[2]}; `, + navigateButton: css` + background: none; + border: none; + padding: 0 0 0 4px; + margin: 0; + color: ${colors.gray[400]}; + font-size: ${fontSize.md}; + cursor: pointer; + line-height: 1; + vertical-align: middle; + margin-right: 0.5ch; + flex-shrink: 0; + &:hover { + color: ${colors.blue[300]}; + } + `, } } diff --git a/packages/router-devtools/package.json b/packages/router-devtools/package.json index 8bbe6ab4323..add03651ea1 100644 --- a/packages/router-devtools/package.json +++ b/packages/router-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-devtools", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-generator/package.json b/packages/router-generator/package.json index 28794a8b57e..24fa2c93cae 100644 --- a/packages/router-generator/package.json +++ b/packages/router-generator/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-generator", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-plugin/package.json b/packages/router-plugin/package.json index 4698be35361..df0d7ea1367 100644 --- a/packages/router-plugin/package.json +++ b/packages/router-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-plugin", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/router-plugin/src/core/constants.ts b/packages/router-plugin/src/core/constants.ts index 690c079888c..b4d4bb940f1 100644 --- a/packages/router-plugin/src/core/constants.ts +++ b/packages/router-plugin/src/core/constants.ts @@ -12,7 +12,6 @@ export type CodeSplitGroupings = Array> export const defaultCodeSplitGroupings: CodeSplitGroupings = [ ['component'], - ['pendingComponent'], ['errorComponent'], ['notFoundComponent'], ] diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/arrow-function@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/arrow-function@pendingComponent.tsx deleted file mode 100644 index b75acfb436c..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/arrow-function@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import * as React from 'react'; -import { Route } from "arrow-function.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/chinese@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/chinese@pendingComponent.tsx deleted file mode 100644 index 3cf6f4a7d61..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/chinese@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "chinese.tsx"; -interface DemoProps { - title: string; -} \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/conditional-properties@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/conditional-properties@pendingComponent.tsx deleted file mode 100644 index bf6f4765048..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/conditional-properties@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "conditional-properties.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/destructured-react-memo-imported-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/destructured-react-memo-imported-component@pendingComponent.tsx deleted file mode 100644 index ddd3c054455..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/destructured-react-memo-imported-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "destructured-react-memo-imported-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/destructuring@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/destructuring@pendingComponent.tsx deleted file mode 100644 index 858c5c0e051..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/destructuring@pendingComponent.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import thing from 'thing'; -export function test() { - const { - foo: { - bar: { - destructured - } - } - } = thing; - return destructured; -} \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/export-default-component-and-normal-notFound@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/export-default-component-and-normal-notFound@pendingComponent.tsx deleted file mode 100644 index 327bc4b8695..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/export-default-component-and-normal-notFound@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import React from 'react'; -import { Route } from "export-default-component-and-normal-notFound.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/export-default-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/export-default-component@pendingComponent.tsx deleted file mode 100644 index 5f691824e7c..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/export-default-component@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import React from 'react'; -import { Route } from "export-default-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/function-as-parameter@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/function-as-parameter@pendingComponent.tsx deleted file mode 100644 index 23e2cd0f036..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/function-as-parameter@pendingComponent.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; -// @ts-expect-error -import { useMemo } from 'tan-react'; -const useUsedVar = 'i-am-unused'; -const ReactUseMemoCall1 = React.useMemo(function performAction() { - return 'true'; -}, []); -console.info(ReactUseMemoCall1); -const ReactUseMemoCall2 = React.useMemo(() => { - return 'true'; -}, []); -console.info(ReactUseMemoCall2); -const UseMemoCall1 = useMemo(function performAction() { - return 'true'; -}, []); -console.info(UseMemoCall1); -const UseMemoCall2 = useMemo(() => { - return 'true'; -}, []); -console.info(UseMemoCall2); \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/function-declaration@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/function-declaration@pendingComponent.tsx deleted file mode 100644 index 3eda0a9227d..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/function-declaration@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import * as React from 'react'; -import { Route } from "function-declaration.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/importAttribute@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/importAttribute@pendingComponent.tsx deleted file mode 100644 index 2745b8a2d31..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/importAttribute@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "importAttribute.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-default-component-destructured-loader@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-default-component-destructured-loader@pendingComponent.tsx deleted file mode 100644 index ec634683a4b..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-default-component-destructured-loader@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-default-component-destructured-loader.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-default-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-default-component@pendingComponent.tsx deleted file mode 100644 index 0619586a44d..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-default-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-default-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-errorComponent@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-errorComponent@pendingComponent.tsx deleted file mode 100644 index 42ae8aeafe9..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-errorComponent@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-errorComponent.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-notFoundComponent@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-notFoundComponent@pendingComponent.tsx deleted file mode 100644 index 8aae85019bc..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-notFoundComponent@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-notFoundComponent.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent.tsx index 143fe9c5e30..13cfc22f7b2 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent.tsx @@ -1,10 +1,10 @@ -const $$splitPendingComponentImporter = () => import('imported-pendingComponent.tsx?tsr-split=pendingComponent'); const $$splitComponentImporter = () => import('imported-pendingComponent.tsx?tsr-split=component'); import { lazyRouteComponent } from '@tanstack/react-router'; import { createFileRoute } from '@tanstack/react-router'; +import { importedPendingComponent } from '../../shared/imported'; export const Route = createFileRoute('/')({ component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr), - pendingComponent: lazyRouteComponent($$splitPendingComponentImporter, 'pendingComponent') + pendingComponent: importedPendingComponent }); export function TSRDummyComponent() { return null; diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent@pendingComponent.tsx deleted file mode 100644 index 8075e421dca..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported-pendingComponent@pendingComponent.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { importedPendingComponent } from '../../shared/imported'; -import { Route } from "imported-pendingComponent.tsx"; -const SplitPendingComponent = importedPendingComponent; -export { SplitPendingComponent as pendingComponent }; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported@pendingComponent.tsx deleted file mode 100644 index 3918e275fd9..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/imported@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/inline@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/inline@pendingComponent.tsx deleted file mode 100644 index c7b20c31278..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/inline@pendingComponent.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import * as React from 'react'; -import { Route } from "inline.tsx"; -Route.addChildren([]); -import { test } from "inline.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/random-number@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/random-number@pendingComponent.tsx deleted file mode 100644 index e1a0daed5be..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/random-number@pendingComponent.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Await, Link } from '@tanstack/react-router'; -import { Carbon } from '~/components/Carbon'; -import { twMerge } from 'tailwind-merge'; -import { FaDiscord, FaGithub, FaTshirt } from 'react-icons/fa'; -import { CgMusicSpeaker, CgSpinner } from 'react-icons/cg'; -import { Footer } from '~/components/Footer'; -import SponsorPack from '~/components/SponsorPack'; -import { LogoColor } from '~/components/LogoColor'; -import agGridImage from '~/images/ag-grid.png'; -import nozzleImage from '~/images/nozzle.png'; -import bytesImage from '~/images/bytes.svg'; -import bytesUidotdevImage from '~/images/bytes-uidotdev.png'; -import { textColors } from "random-number.tsx"; -import { gradients } from "random-number.tsx"; -const courses = [{ - name: 'The Official TanStack React Query Course', - cardStyles: `border-t-4 border-red-500 hover:(border-green-500)`, - href: 'https://query.gg/?s=tanstack', - description: `Learn how to build enterprise quality apps with TanStack's React Query the easy way with our brand new course.` -}]; -import { Route } from "random-number.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/react-memo-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/react-memo-component@pendingComponent.tsx deleted file mode 100644 index e7e5dfc08d3..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/react-memo-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "react-memo-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/react-memo-imported-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/react-memo-imported-component@pendingComponent.tsx deleted file mode 100644 index d88b8022178..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/react-memo-imported-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "react-memo-imported-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-export-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-export-component@pendingComponent.tsx deleted file mode 100644 index 912181bd1a4..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-export-component@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-export-component.tsx"; -import { SIDEBAR_WIDTH } from "retain-export-component.tsx"; -const SIDEBAR_MINI_WIDTH = '80px'; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-const@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-const@pendingComponent.tsx deleted file mode 100644 index 1d00e8f2631..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-const@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-exports-const.tsx"; -import { SIDEBAR_WIDTH } from "retain-exports-const.tsx"; -import { SIDEBAR_MINI_WIDTH } from "retain-exports-const.tsx"; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-function@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-function@pendingComponent.tsx deleted file mode 100644 index 74c5d64313e..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-function@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-exports-function.tsx"; -import { SIDEBAR_WIDTH } from "retain-exports-function.tsx"; -import { SIDEBAR_MINI_WIDTH } from "retain-exports-function.tsx"; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-loader@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-loader@pendingComponent.tsx deleted file mode 100644 index 988a358b5d7..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/retain-exports-loader@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-exports-loader.tsx"; -import { SIDEBAR_WIDTH } from "retain-exports-loader.tsx"; -import { SIDEBAR_MINI_WIDTH } from "retain-exports-loader.tsx"; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx deleted file mode 100644 index f4b72ad2a09..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { FaBolt, FaBook, FaCheckCircle, FaCogs } from 'react-icons/fa'; -import { VscPreview, VscWand } from 'react-icons/vsc'; -import { Route } from "useStateDestructure.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/arrow-function@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/arrow-function@pendingComponent.tsx deleted file mode 100644 index b75acfb436c..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/arrow-function@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import * as React from 'react'; -import { Route } from "arrow-function.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/chinese@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/chinese@pendingComponent.tsx deleted file mode 100644 index 3cf6f4a7d61..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/chinese@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "chinese.tsx"; -interface DemoProps { - title: string; -} \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/conditional-properties@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/conditional-properties@pendingComponent.tsx deleted file mode 100644 index bf6f4765048..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/conditional-properties@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "conditional-properties.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/destructured-react-memo-imported-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/destructured-react-memo-imported-component@pendingComponent.tsx deleted file mode 100644 index ddd3c054455..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/destructured-react-memo-imported-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "destructured-react-memo-imported-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/destructuring@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/destructuring@pendingComponent.tsx deleted file mode 100644 index 858c5c0e051..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/destructuring@pendingComponent.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import thing from 'thing'; -export function test() { - const { - foo: { - bar: { - destructured - } - } - } = thing; - return destructured; -} \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/export-default-component-and-normal-notFound@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/export-default-component-and-normal-notFound@pendingComponent.tsx deleted file mode 100644 index 327bc4b8695..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/export-default-component-and-normal-notFound@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import React from 'react'; -import { Route } from "export-default-component-and-normal-notFound.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/export-default-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/export-default-component@pendingComponent.tsx deleted file mode 100644 index 5f691824e7c..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/export-default-component@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import React from 'react'; -import { Route } from "export-default-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/function-as-parameter@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/function-as-parameter@pendingComponent.tsx deleted file mode 100644 index 23e2cd0f036..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/function-as-parameter@pendingComponent.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import * as React from 'react'; -// @ts-expect-error -import { useMemo } from 'tan-react'; -const useUsedVar = 'i-am-unused'; -const ReactUseMemoCall1 = React.useMemo(function performAction() { - return 'true'; -}, []); -console.info(ReactUseMemoCall1); -const ReactUseMemoCall2 = React.useMemo(() => { - return 'true'; -}, []); -console.info(ReactUseMemoCall2); -const UseMemoCall1 = useMemo(function performAction() { - return 'true'; -}, []); -console.info(UseMemoCall1); -const UseMemoCall2 = useMemo(() => { - return 'true'; -}, []); -console.info(UseMemoCall2); \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/function-declaration@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/function-declaration@pendingComponent.tsx deleted file mode 100644 index 3eda0a9227d..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/function-declaration@pendingComponent.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import * as React from 'react'; -import { Route } from "function-declaration.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/importAttribute@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/importAttribute@pendingComponent.tsx deleted file mode 100644 index 2745b8a2d31..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/importAttribute@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "importAttribute.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-default-component-destructured-loader@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-default-component-destructured-loader@pendingComponent.tsx deleted file mode 100644 index ec634683a4b..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-default-component-destructured-loader@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-default-component-destructured-loader.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-default-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-default-component@pendingComponent.tsx deleted file mode 100644 index 0619586a44d..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-default-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-default-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-errorComponent@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-errorComponent@pendingComponent.tsx deleted file mode 100644 index 42ae8aeafe9..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-errorComponent@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-errorComponent.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-notFoundComponent@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-notFoundComponent@pendingComponent.tsx deleted file mode 100644 index 8aae85019bc..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-notFoundComponent@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported-notFoundComponent.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent.tsx index 4b0c7bd790b..fc542f708a3 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent.tsx @@ -1,8 +1,8 @@ -const $$splitPendingComponentImporter = () => import('imported-pendingComponent.tsx?tsr-split=pendingComponent'); const $$splitComponentImporter = () => import('imported-pendingComponent.tsx?tsr-split=component'); import { lazyRouteComponent } from '@tanstack/react-router'; import { createFileRoute } from '@tanstack/react-router'; +import { importedPendingComponent } from '../../shared/imported'; export const Route = createFileRoute('/')({ component: lazyRouteComponent($$splitComponentImporter, 'component', () => Route.ssr), - pendingComponent: lazyRouteComponent($$splitPendingComponentImporter, 'pendingComponent') + pendingComponent: importedPendingComponent }); \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent@pendingComponent.tsx deleted file mode 100644 index 8075e421dca..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported-pendingComponent@pendingComponent.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { importedPendingComponent } from '../../shared/imported'; -import { Route } from "imported-pendingComponent.tsx"; -const SplitPendingComponent = importedPendingComponent; -export { SplitPendingComponent as pendingComponent }; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported@pendingComponent.tsx deleted file mode 100644 index 3918e275fd9..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/imported@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "imported.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/inline@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/inline@pendingComponent.tsx deleted file mode 100644 index c7b20c31278..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/inline@pendingComponent.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import * as React from 'react'; -import { Route } from "inline.tsx"; -Route.addChildren([]); -import { test } from "inline.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/random-number@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/random-number@pendingComponent.tsx deleted file mode 100644 index e1a0daed5be..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/random-number@pendingComponent.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Await, Link } from '@tanstack/react-router'; -import { Carbon } from '~/components/Carbon'; -import { twMerge } from 'tailwind-merge'; -import { FaDiscord, FaGithub, FaTshirt } from 'react-icons/fa'; -import { CgMusicSpeaker, CgSpinner } from 'react-icons/cg'; -import { Footer } from '~/components/Footer'; -import SponsorPack from '~/components/SponsorPack'; -import { LogoColor } from '~/components/LogoColor'; -import agGridImage from '~/images/ag-grid.png'; -import nozzleImage from '~/images/nozzle.png'; -import bytesImage from '~/images/bytes.svg'; -import bytesUidotdevImage from '~/images/bytes-uidotdev.png'; -import { textColors } from "random-number.tsx"; -import { gradients } from "random-number.tsx"; -const courses = [{ - name: 'The Official TanStack React Query Course', - cardStyles: `border-t-4 border-red-500 hover:(border-green-500)`, - href: 'https://query.gg/?s=tanstack', - description: `Learn how to build enterprise quality apps with TanStack's React Query the easy way with our brand new course.` -}]; -import { Route } from "random-number.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/react-memo-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/react-memo-component@pendingComponent.tsx deleted file mode 100644 index e7e5dfc08d3..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/react-memo-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "react-memo-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/react-memo-imported-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/react-memo-imported-component@pendingComponent.tsx deleted file mode 100644 index d88b8022178..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/react-memo-imported-component@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "react-memo-imported-component.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-export-component@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-export-component@pendingComponent.tsx deleted file mode 100644 index 912181bd1a4..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-export-component@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-export-component.tsx"; -import { SIDEBAR_WIDTH } from "retain-export-component.tsx"; -const SIDEBAR_MINI_WIDTH = '80px'; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-const@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-const@pendingComponent.tsx deleted file mode 100644 index 1d00e8f2631..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-const@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-exports-const.tsx"; -import { SIDEBAR_WIDTH } from "retain-exports-const.tsx"; -import { SIDEBAR_MINI_WIDTH } from "retain-exports-const.tsx"; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-function@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-function@pendingComponent.tsx deleted file mode 100644 index 74c5d64313e..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-function@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-exports-function.tsx"; -import { SIDEBAR_WIDTH } from "retain-exports-function.tsx"; -import { SIDEBAR_MINI_WIDTH } from "retain-exports-function.tsx"; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-loader@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-loader@pendingComponent.tsx deleted file mode 100644 index 988a358b5d7..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/retain-exports-loader@pendingComponent.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react'; -import { Route } from "retain-exports-loader.tsx"; -import { SIDEBAR_WIDTH } from "retain-exports-loader.tsx"; -import { SIDEBAR_MINI_WIDTH } from "retain-exports-loader.tsx"; -const ASIDE_WIDTH = '250px'; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx deleted file mode 100644 index f4b72ad2a09..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { FaBolt, FaBook, FaCheckCircle, FaCogs } from 'react-icons/fa'; -import { VscPreview, VscWand } from 'react-icons/vsc'; -import { Route } from "useStateDestructure.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/solid/1-default/development/arrow-function@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/solid/1-default/development/arrow-function@pendingComponent.tsx deleted file mode 100644 index 32dee4a059f..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/solid/1-default/development/arrow-function@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "arrow-function.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/code-splitter/snapshots/solid/1-default/production/arrow-function@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/solid/1-default/production/arrow-function@pendingComponent.tsx deleted file mode 100644 index 32dee4a059f..00000000000 --- a/packages/router-plugin/tests/code-splitter/snapshots/solid/1-default/production/arrow-function@pendingComponent.tsx +++ /dev/null @@ -1 +0,0 @@ -import { Route } from "arrow-function.tsx"; \ No newline at end of file diff --git a/packages/router-plugin/tests/detect-route-codesplit-groupings.test.ts b/packages/router-plugin/tests/detect-route-codesplit-groupings.test.ts index 69fec8ce118..49b6b40c0a0 100644 --- a/packages/router-plugin/tests/detect-route-codesplit-groupings.test.ts +++ b/packages/router-plugin/tests/detect-route-codesplit-groupings.test.ts @@ -10,13 +10,13 @@ const successCases: Array<{ expectedRouteId: string }> = [ { + // This test should be updated whenever the `defaultCodeSplitGroupings` changes name: 'defaults', code: ` import {createFileRoute} from '@tanstack/react-router' export const Route = createFileRoute('/posts')({ codeSplitGroupings: [ ['component'], - ['pendingComponent'], ['errorComponent'], ['notFoundComponent'] ] diff --git a/packages/router-vite-plugin/README.md b/packages/router-vite-plugin/README.md index efd08180d32..b0494d9f48f 100644 --- a/packages/router-vite-plugin/README.md +++ b/packages/router-vite-plugin/README.md @@ -2,4 +2,4 @@ # TanStack Router Vite Plugin -See https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing +See https://tanstack.com/router/latest/docs/framework/react/routing/file-based-routing diff --git a/packages/router-vite-plugin/package.json b/packages/router-vite-plugin/package.json index 0e5f4ac4bac..c03b95efd2c 100644 --- a/packages/router-vite-plugin/package.json +++ b/packages/router-vite-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-vite-plugin", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/server-functions-plugin/package.json b/packages/server-functions-plugin/package.json index 2fae541436d..289b909ea68 100644 --- a/packages/server-functions-plugin/package.json +++ b/packages/server-functions-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/server-functions-plugin", - "version": "1.115.0", + "version": "1.119.2", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-router-devtools/package.json b/packages/solid-router-devtools/package.json index a174ab0c286..c933c241823 100644 --- a/packages/solid-router-devtools/package.json +++ b/packages/solid-router-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-router-devtools", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-router/package.json b/packages/solid-router/package.json index 930884b8841..602a805be11 100644 --- a/packages/solid-router/package.json +++ b/packages/solid-router/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-router", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-router/src/Transitioner.tsx b/packages/solid-router/src/Transitioner.tsx index 385ed736cd1..51112e3bbc5 100644 --- a/packages/solid-router/src/Transitioner.tsx +++ b/packages/solid-router/src/Transitioner.tsx @@ -31,9 +31,9 @@ export function Transitioner() { const previousIsPagePending = usePrevious(isPagePending) if (!router.isServer) { - router.startTransition = (fn: () => void) => { + router.startTransition = async (fn: () => void | Promise) => { setIsTransitioning(true) - fn() + await fn() setIsTransitioning(false) } } diff --git a/packages/solid-router/src/link.tsx b/packages/solid-router/src/link.tsx index 79e58b30a34..bc9e3f23030 100644 --- a/packages/solid-router/src/link.tsx +++ b/packages/solid-router/src/link.tsx @@ -509,9 +509,12 @@ export type CreateLinkProps = LinkProps< string > -export type LinkComponent = < +export type LinkComponent< + in out TComp, + in out TDefaultFrom extends string = string, +> = < TRouter extends AnyRouter = RegisteredRouter, - const TFrom extends string = string, + const TFrom extends string = TDefaultFrom, const TTo extends string | undefined = undefined, const TMaskFrom extends string = TFrom, const TMaskTo extends string = '', diff --git a/packages/solid-router/src/route.ts b/packages/solid-router/src/route.tsx similarity index 95% rename from packages/solid-router/src/route.ts rename to packages/solid-router/src/route.tsx index c56dc4ef8fa..2d89232acc2 100644 --- a/packages/solid-router/src/route.ts +++ b/packages/solid-router/src/route.tsx @@ -4,6 +4,7 @@ import { BaseRouteApi, notFound, } from '@tanstack/router-core' +import { Link } from './link' import { useLoaderData } from './useLoaderData' import { useLoaderDeps } from './useLoaderDeps' import { useParams } from './useParams' @@ -41,6 +42,7 @@ import type { UseParamsRoute } from './useParams' import type { UseSearchRoute } from './useSearch' import type * as Solid from 'solid-js' import type { UseRouteContextRoute } from './useRouteContext' +import type { LinkComponent } from './link' declare module '@tanstack/router-core' { export interface UpdatableRouteOptionsExtensions { @@ -61,6 +63,7 @@ declare module '@tanstack/router-core' { useLoaderDeps: UseLoaderDepsRoute useLoaderData: UseLoaderDataRoute useNavigate: () => UseNavigateResult + Link: LinkComponent<'a', TFullPath> } } @@ -128,6 +131,14 @@ export class RouteApi< notFound = (opts?: NotFoundError) => { return notFound({ routeId: this.id as string, ...opts }) } + + Link: LinkComponent<'a', RouteTypesById['fullPath']> = ( + props, + ) => { + const router = useRouter() + const fullPath = router.routesById[this.id as string].fullPath + return + } } export class Route< @@ -230,6 +241,10 @@ export class Route< useNavigate = (): UseNavigateResult => { return useNavigate({ from: this.fullPath }) } + + Link: LinkComponent<'a', TFullPath> = (props) => { + return + } } export function createRoute< @@ -411,6 +426,10 @@ export class RootRoute< useNavigate = (): UseNavigateResult<'/'> => { return useNavigate({ from: this.fullPath }) } + + Link: LinkComponent<'a', '/'> = (props) => { + return + } } export function createRouteMask< diff --git a/packages/solid-router/tests/routeApi.test-d.tsx b/packages/solid-router/tests/routeApi.test-d.tsx index 99908a3d7a4..805eec55658 100644 --- a/packages/solid-router/tests/routeApi.test-d.tsx +++ b/packages/solid-router/tests/routeApi.test-d.tsx @@ -1,5 +1,6 @@ import { describe, expectTypeOf, test } from 'vitest' import { createRootRoute, createRoute, createRouter, getRouteApi } from '../src' +import type { LinkComponent } from '../src' import type { Accessor } from 'solid-js' import type { MakeRouteMatch, UseNavigateResult } from '@tanstack/router-core' @@ -96,6 +97,12 @@ describe('getRouteApi', () => { Accessor> >() }) + test('Link', () => { + const Link = invoiceRouteApi.Link + expectTypeOf(Link).toEqualTypeOf< + LinkComponent<'a', '/invoices/$invoiceId'> + >() + }) }) describe('createRoute', () => { diff --git a/packages/solid-start-client/package.json b/packages/solid-start-client/package.json index 87c027ab787..9c3853128d0 100644 --- a/packages/solid-start-client/package.json +++ b/packages/solid-start-client/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-start-client", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-start-config/package.json b/packages/solid-start-config/package.json index 5ceea9f853a..3ae1f93823d 100644 --- a/packages/solid-start-config/package.json +++ b/packages/solid-start-config/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-start-config", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-start-config/src/index.ts b/packages/solid-start-config/src/index.ts index b148a4470c7..3a5c597f0d6 100644 --- a/packages/solid-start-config/src/index.ts +++ b/packages/solid-start-config/src/index.ts @@ -87,9 +87,7 @@ export async function defineConfig( const { preset: configDeploymentPreset, ...serverOptions } = serverSchema.parse(opts.server || {}) - const deploymentPreset = checkDeploymentPresetInput( - configDeploymentPreset || 'node-server', - ) + const deploymentPreset = checkDeploymentPresetInput(configDeploymentPreset) const tsr = setTsrDefaults(opts.tsr) const tsrConfig = getConfig(tsr) diff --git a/packages/solid-start-config/src/schema.ts b/packages/solid-start-config/src/schema.ts index caa4ecbc41b..9c8a6dc8106 100644 --- a/packages/solid-start-config/src/schema.ts +++ b/packages/solid-start-config/src/schema.ts @@ -80,19 +80,23 @@ const testedDeploymentPresets: Array = [ 'node-server', ] -export function checkDeploymentPresetInput(preset: string): DeploymentPreset { - if (!vinxiDeploymentPresets.includes(preset as any)) { - console.warn( - `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets - .map((p) => `"${p}"`) - .join(', ')}.`, - ) - } - - if (!testedDeploymentPresets.includes(preset as any)) { - console.warn( - `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, - ) +export function checkDeploymentPresetInput( + preset?: string, +): DeploymentPreset | undefined { + if (preset) { + if (!vinxiDeploymentPresets.includes(preset as any)) { + console.warn( + `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets + .map((p) => `"${p}"`) + .join(', ')}.`, + ) + } + + if (!testedDeploymentPresets.includes(preset as any)) { + console.warn( + `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, + ) + } } return preset diff --git a/packages/solid-start-router-manifest/package.json b/packages/solid-start-router-manifest/package.json index 230bf5565be..097417e4879 100644 --- a/packages/solid-start-router-manifest/package.json +++ b/packages/solid-start-router-manifest/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-start-router-manifest", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-start-server/package.json b/packages/solid-start-server/package.json index 8a67c1049d3..65e46e4f90f 100644 --- a/packages/solid-start-server/package.json +++ b/packages/solid-start-server/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-start-server", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/solid-start/package.json b/packages/solid-start/package.json index b9733757a0b..bb3a4c32003 100644 --- a/packages/solid-start/package.json +++ b/packages/solid-start/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-start", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-api-routes/package.json b/packages/start-api-routes/package.json index e7b698bb3f1..c1443f001a1 100644 --- a/packages/start-api-routes/package.json +++ b/packages/start-api-routes/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-api-routes", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-client-core/package.json b/packages/start-client-core/package.json index 6a5f00cd8e3..2e902b2b70f 100644 --- a/packages/start-client-core/package.json +++ b/packages/start-client-core/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-client-core", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-client-core/src/createServerFn.ts b/packages/start-client-core/src/createServerFn.ts index 890345f2dfd..a84995097e1 100644 --- a/packages/start-client-core/src/createServerFn.ts +++ b/packages/start-client-core/src/createServerFn.ts @@ -461,17 +461,23 @@ export type ServerFnBaseOptions< > } -export type ValidatorSerializerStringify = Validator< - SerializerStringifyBy< - ResolveValidatorInput, - Date | undefined | FormData - >, - any +export type ValidatorInputStringify = SerializerStringifyBy< + ResolveValidatorInput, + Date | undefined | FormData > -export type ConstrainValidator = unknown extends TValidator - ? TValidator - : Constrain> +export type ValidatorSerializerStringify = + ValidatorInputStringify extends infer TInput + ? Validator + : never + +export type ConstrainValidator = + | (unknown extends TValidator + ? TValidator + : ResolveValidatorInput extends ValidatorInputStringify + ? TValidator + : never) + | ValidatorSerializerStringify export interface ServerFnMiddleware< TMethod extends Method, diff --git a/packages/start-client-core/src/index.tsx b/packages/start-client-core/src/index.tsx index 5be7fcc4e41..fb50145deeb 100644 --- a/packages/start-client-core/src/index.tsx +++ b/packages/start-client-core/src/index.tsx @@ -75,6 +75,7 @@ export type { NextFn, Method, StaticCachedResult, + OptionalFetcher, } from './createServerFn' export { applyMiddleware, diff --git a/packages/start-client-core/src/tests/createServerFn.test-d.ts b/packages/start-client-core/src/tests/createServerFn.test-d.ts index 5963d9f9a9f..5cb1305ebe6 100644 --- a/packages/start-client-core/src/tests/createServerFn.test-d.ts +++ b/packages/start-client-core/src/tests/createServerFn.test-d.ts @@ -2,6 +2,7 @@ import { describe, expectTypeOf, test } from 'vitest' import { createMiddleware } from '../createMiddleware' import { createServerFn } from '../createServerFn' import type { Constrain, Validator } from '@tanstack/router-core' +import type { ConstrainValidator } from '../createServerFn' test('createServerFn method with autocomplete', () => { createServerFn().handler((options) => { @@ -395,9 +396,7 @@ test('createServerFn can validate Date', () => { expectTypeOf(validator) .parameter(0) - .toEqualTypeOf< - Constrain<(input: Date) => { output: 'string' }, Validator> - >() + .toEqualTypeOf { output: 'string' }>>() }) test('createServerFn can validate FormData', () => { @@ -408,10 +407,7 @@ test('createServerFn can validate FormData', () => { expectTypeOf(validator) .parameter(0) .toEqualTypeOf< - Constrain< - (input: FormData) => { output: 'string' }, - Validator - > + ConstrainValidator<(input: FormData) => { output: 'string' }> >() }) @@ -486,3 +482,31 @@ test('createServerFn can be used as a mutation function', () => { useMutation(serverFn) }) + +test('createServerFn validator infers unknown for default input type', () => { + const fn = createServerFn() + .validator((input) => { + expectTypeOf(input).toEqualTypeOf() + + if (typeof input === 'number') return 'success' as const + + return 'failed' as const + }) + .handler(({ data }) => { + expectTypeOf(data).toEqualTypeOf<'success' | 'failed'>() + + return data + }) + + expectTypeOf(fn).parameter(0).toEqualTypeOf< + | { + data?: unknown | undefined + headers?: HeadersInit + type?: 'static' | 'dynamic' + signal?: AbortSignal + } + | undefined + >() + + expectTypeOf(fn()).toEqualTypeOf>() +}) diff --git a/packages/start-client-core/src/tests/createServerMiddleware.test-d.ts b/packages/start-client-core/src/tests/createServerMiddleware.test-d.ts index 22caa76e3d9..8ca1eaca36f 100644 --- a/packages/start-client-core/src/tests/createServerMiddleware.test-d.ts +++ b/packages/start-client-core/src/tests/createServerMiddleware.test-d.ts @@ -1,6 +1,7 @@ import { expectTypeOf, test } from 'vitest' import { createMiddleware } from '../createMiddleware' import type { Constrain, Validator } from '@tanstack/router-core' +import type { ConstrainValidator } from '../createServerFn' test('createServeMiddleware removes middleware after middleware,', () => { const middleware = createMiddleware() @@ -590,9 +591,7 @@ test('createMiddleware can validate Date', () => { expectTypeOf(validator) .parameter(0) - .toEqualTypeOf< - Constrain<(input: Date) => { output: 'string' }, Validator> - >() + .toEqualTypeOf { output: 'string' }>>() }) test('createMiddleware can validate FormData', () => { @@ -603,9 +602,22 @@ test('createMiddleware can validate FormData', () => { expectTypeOf(validator) .parameter(0) .toEqualTypeOf< - Constrain< - (input: FormData) => { output: 'string' }, - Validator - > + ConstrainValidator<(input: FormData) => { output: 'string' }> >() }) + +test('createMiddleware validator infers unknown for default input type', () => { + createMiddleware() + .validator((input) => { + expectTypeOf(input).toEqualTypeOf() + + if (typeof input === 'number') return 'success' as const + + return 'failed' as const + }) + .server(({ data, next }) => { + expectTypeOf(data).toEqualTypeOf<'success' | 'failed'>() + + return next() + }) +}) diff --git a/packages/start-config/package.json b/packages/start-config/package.json index d35faeae25f..671ebf7d55c 100644 --- a/packages/start-config/package.json +++ b/packages/start-config/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-config", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-config/src/index.ts b/packages/start-config/src/index.ts index 60043bfa9c3..4f676105046 100644 --- a/packages/start-config/src/index.ts +++ b/packages/start-config/src/index.ts @@ -87,9 +87,7 @@ export async function defineConfig( const { preset: configDeploymentPreset, ...serverOptions } = serverSchema.parse(opts.server || {}) - const deploymentPreset = checkDeploymentPresetInput( - configDeploymentPreset || 'node-server', - ) + const deploymentPreset = checkDeploymentPresetInput(configDeploymentPreset) const tsr = setTsrDefaults(opts.tsr) const tsrConfig = getConfig(tsr) diff --git a/packages/start-config/src/schema.ts b/packages/start-config/src/schema.ts index 516e4e86fa5..45294837939 100644 --- a/packages/start-config/src/schema.ts +++ b/packages/start-config/src/schema.ts @@ -80,19 +80,23 @@ const testedDeploymentPresets: Array = [ 'node-server', ] -export function checkDeploymentPresetInput(preset: string): DeploymentPreset { - if (!vinxiDeploymentPresets.includes(preset as any)) { - console.warn( - `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets - .map((p) => `"${p}"`) - .join(', ')}.`, - ) - } - - if (!testedDeploymentPresets.includes(preset as any)) { - console.warn( - `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, - ) +export function checkDeploymentPresetInput( + preset?: string, +): DeploymentPreset | undefined { + if (preset) { + if (!vinxiDeploymentPresets.includes(preset as any)) { + console.warn( + `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets + .map((p) => `"${p}"`) + .join(', ')}.`, + ) + } + + if (!testedDeploymentPresets.includes(preset as any)) { + console.warn( + `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, + ) + } } return preset diff --git a/packages/start-server-core/package.json b/packages/start-server-core/package.json index 71b42ba2bab..8d2b81d030b 100644 --- a/packages/start-server-core/package.json +++ b/packages/start-server-core/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-server-core", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-server-functions-client/package.json b/packages/start-server-functions-client/package.json index 1f1d93d7927..79444509568 100644 --- a/packages/start-server-functions-client/package.json +++ b/packages/start-server-functions-client/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-server-functions-client", - "version": "1.115.3", + "version": "1.119.2", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-server-functions-fetcher/package.json b/packages/start-server-functions-fetcher/package.json index f69a7812e50..2c65dd1e175 100644 --- a/packages/start-server-functions-fetcher/package.json +++ b/packages/start-server-functions-fetcher/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-server-functions-fetcher", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-server-functions-handler/package.json b/packages/start-server-functions-handler/package.json index 57a4c950402..9a6c43c3169 100644 --- a/packages/start-server-functions-handler/package.json +++ b/packages/start-server-functions-handler/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-server-functions-handler", - "version": "1.115.3", + "version": "1.119.0", "description": "Modern and scalable routing for applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-server-functions-server/package.json b/packages/start-server-functions-server/package.json index 4700c48e1f3..d7011d4a02d 100644 --- a/packages/start-server-functions-server/package.json +++ b/packages/start-server-functions-server/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-server-functions-server", - "version": "1.115.0", + "version": "1.119.2", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start-server-functions-ssr/package.json b/packages/start-server-functions-ssr/package.json index 19d4241b5f5..02fda3ff2a5 100644 --- a/packages/start-server-functions-ssr/package.json +++ b/packages/start-server-functions-ssr/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start-server-functions-ssr", - "version": "1.115.3", + "version": "1.119.2", "description": "Modern and scalable routing for applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/start/package.json b/packages/start/package.json index eb12162d608..b831cdbe323 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/start", - "version": "1.116.1", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/valibot-adapter/package.json b/packages/valibot-adapter/package.json index ab6967dc614..0c1710d105e 100644 --- a/packages/valibot-adapter/package.json +++ b/packages/valibot-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/valibot-adapter", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/zod-adapter/package.json b/packages/zod-adapter/package.json index b64a21c6dc8..07441549458 100644 --- a/packages/zod-adapter/package.json +++ b/packages/zod-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/zod-adapter", - "version": "1.116.0", + "version": "1.120.1", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aa18d466ae9..898732a3cfb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,7 @@ overrides: '@types/react-dom': ^19.0.3 eslint: ^9.22.0 vite: 6.1.4 + '@playwright/test': ^1.52.0 '@tanstack/react-query': 5.66.0 '@tanstack/history': workspace:* '@tanstack/router-core': workspace:* @@ -65,8 +66,8 @@ importers: specifier: ^1.26.2 version: 1.26.2(eslint@9.22.0(jiti@2.4.2))(ts-api-utils@2.0.1(typescript@5.8.2))(typescript@5.8.2) '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/config': specifier: ^0.16.1 version: 0.16.1(@types/node@22.13.4)(esbuild@0.25.0)(eslint@9.22.0(jiti@2.4.2))(rollup@4.39.0)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) @@ -84,7 +85,7 @@ importers: version: 19.0.3(@types/react@19.0.8) '@vitest/browser': specifier: ^3.0.6 - version: 3.0.6(@types/node@22.13.4)(playwright@1.50.1)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))(vitest@3.0.6) + version: 3.0.6(@types/node@22.13.4)(playwright@1.52.0)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))(vitest@3.0.6) '@vitest/ui': specifier: ^3.0.6 version: 3.0.6(vitest@3.0.6) @@ -101,8 +102,8 @@ importers: specifier: ^25.0.1 version: 25.0.1 nx: - specifier: 20.4.2 - version: 20.4.2(@swc/core@1.10.15(@swc/helpers@0.5.15)) + specifier: 20.8.1 + version: 20.8.1(@swc/core@1.10.15(@swc/helpers@0.5.15)) prettier: specifier: ^3.5.0 version: 3.5.0 @@ -179,8 +180,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -225,8 +226,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -277,8 +278,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -329,8 +330,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -381,8 +382,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -439,8 +440,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -488,8 +489,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -543,8 +544,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -598,8 +599,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -647,8 +648,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -693,8 +694,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -733,8 +734,8 @@ importers: version: 0.5.1 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@rsbuild/core': specifier: ^1.2.4 version: 1.2.4 @@ -785,8 +786,8 @@ importers: version: 0.5.1 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@rsbuild/core': specifier: ^1.2.4 version: 1.2.4 @@ -858,8 +859,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -913,8 +914,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -962,8 +963,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1032,8 +1033,8 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1102,8 +1103,8 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1255,8 +1256,8 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1322,8 +1323,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1392,8 +1393,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1462,8 +1463,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1520,8 +1521,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1557,8 +1558,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1603,8 +1604,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1646,8 +1647,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1686,8 +1687,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1729,8 +1730,8 @@ importers: version: 3.4.17 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1778,8 +1779,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1824,8 +1825,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1870,8 +1871,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -1898,8 +1899,8 @@ importers: version: 1.9.5 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@rsbuild/core': specifier: ^1.2.4 version: 1.2.4 @@ -1944,8 +1945,8 @@ importers: version: 1.9.5 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@rsbuild/core': specifier: ^1.2.4 version: 1.2.4 @@ -2011,8 +2012,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -2051,8 +2052,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -2140,8 +2141,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -2201,8 +2202,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -2262,8 +2263,8 @@ importers: version: 3.24.2 devDependencies: '@playwright/test': - specifier: ^1.50.1 - version: 1.50.1 + specifier: ^1.52.0 + version: 1.52.0 '@tanstack/router-e2e-utils': specifier: workspace:^ version: link:../../e2e-utils @@ -5243,7 +5244,7 @@ importers: examples/solid/basic: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5283,7 +5284,7 @@ importers: examples/solid/basic-devtools-panel: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5317,7 +5318,7 @@ importers: examples/solid/basic-file-based: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5357,7 +5358,7 @@ importers: examples/solid/basic-non-nested-devtools: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5403,7 +5404,7 @@ importers: specifier: ^5.71.9 version: 5.71.9(@tanstack/solid-query@5.71.9(solid-js@1.9.5))(solid-js@1.9.5) '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5446,7 +5447,7 @@ importers: specifier: ^5.71.9 version: 5.71.9(@tanstack/solid-query@5.71.9(solid-js@1.9.5))(solid-js@1.9.5) '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5486,7 +5487,7 @@ importers: examples/solid/kitchen-sink-file-based: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5529,7 +5530,7 @@ importers: examples/solid/quickstart-file-based: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5569,7 +5570,7 @@ importers: examples/solid/start-bare: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5618,7 +5619,7 @@ importers: examples/solid/start-basic: dependencies: '@tanstack/solid-router': - specifier: ^1.116.0 + specifier: ^1.120.1 version: link:../../../packages/solid-router '@tanstack/solid-router-devtools': specifier: workspace:^ @@ -5682,182 +5683,6 @@ importers: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) - packages/create-router: - dependencies: - '@inquirer/prompts': - specifier: ^5.5.0 - version: 5.5.0 - '@rsbuild/core': - specifier: ^1.0.2 - version: 1.2.4 - '@rsbuild/plugin-react': - specifier: ^1.0.1 - version: 1.1.0(@rsbuild/core@1.2.4) - '@swc/core': - specifier: ^1.7.25 - version: 1.10.15(@swc/helpers@0.5.15) - '@tanstack/react-router': - specifier: workspace:* - version: link:../react-router - '@tanstack/router-devtools': - specifier: workspace:* - version: link:../router-devtools - '@tanstack/router-plugin': - specifier: workspace:* - version: link:../router-plugin - '@types/react': - specifier: ^19.0.8 - version: 19.0.8 - '@types/react-dom': - specifier: ^19.0.3 - version: 19.0.3(@types/react@19.0.8) - '@vitejs/plugin-react': - specifier: ^4.3.2 - version: 4.3.4(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) - commander: - specifier: ^12.1.0 - version: 12.1.0 - cross-spawn: - specifier: ^7.0.6 - version: 7.0.6 - html-webpack-plugin: - specifier: ^5.6.0 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) - picocolors: - specifier: ^1.1.1 - version: 1.1.1 - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - swc-loader: - specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1) - tinyglobby: - specifier: ^0.2.10 - version: 0.2.12 - typescript: - specifier: ^5.7.2 - version: 5.8.2 - validate-npm-package-name: - specifier: ^6.0.0 - version: 6.0.0 - vite: - specifier: 6.1.4 - version: 6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - webpack: - specifier: ^5.94.0 - version: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) - webpack-cli: - specifier: ^5.1.4 - version: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - webpack-dev-server: - specifier: ^5.1.0 - version: 5.2.0(webpack-cli@5.1.4)(webpack@5.97.1) - which: - specifier: ^5.0.0 - version: 5.0.0 - yocto-spinner: - specifier: ^0.2.0 - version: 0.2.0 - devDependencies: - '@types/cross-spawn': - specifier: ^6.0.6 - version: 6.0.6 - '@types/validate-npm-package-name': - specifier: ^4.0.2 - version: 4.0.2 - '@types/which': - specifier: ^3.0.4 - version: 3.0.4 - unbuild: - specifier: ^3.3.1 - version: 3.3.1(typescript@5.8.2)(vue-tsc@2.0.29(typescript@5.8.2)) - - packages/create-start: - dependencies: - '@commander-js/extra-typings': - specifier: ^12.1.0 - version: 12.1.0(commander@12.1.0) - '@inquirer/prompts': - specifier: ^5.5.0 - version: 5.5.0 - '@tanstack/react-router': - specifier: workspace:* - version: link:../react-router - '@tanstack/react-start': - specifier: workspace:* - version: link:../react-start - '@tanstack/router-devtools': - specifier: workspace:* - version: link:../router-devtools - '@types/react': - specifier: ^19.0.8 - version: 19.0.8 - '@types/react-dom': - specifier: ^19.0.3 - version: 19.0.3(@types/react@19.0.8) - commander: - specifier: ^12.1.0 - version: 12.1.0 - cross-spawn: - specifier: ^7.0.6 - version: 7.0.6 - fast-glob: - specifier: ^3.3.3 - version: 3.3.3 - gradient-string: - specifier: ^3.0.0 - version: 3.0.0 - picocolors: - specifier: ^1.1.1 - version: 1.1.1 - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - rollup-plugin-copy: - specifier: ^3.5.0 - version: 3.5.0 - tempy: - specifier: ^3.1.0 - version: 3.1.0 - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - validate-npm-package-name: - specifier: ^6.0.0 - version: 6.0.0 - vinxi: - specifier: 0.5.1 - version: 0.5.1(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) - vite: - specifier: 6.1.4 - version: 6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - yocto-spinner: - specifier: ^0.2.0 - version: 0.2.0 - zod: - specifier: ^3.24.2 - version: 3.24.2 - devDependencies: - '@inquirer/type': - specifier: ^3.0.4 - version: 3.0.4(@types/node@22.13.4) - '@types/cross-spawn': - specifier: ^6.0.6 - version: 6.0.6 - '@types/validate-npm-package-name': - specifier: ^4.0.2 - version: 4.0.2 - unbuild: - specifier: ^3.3.1 - version: 3.3.1(typescript@5.8.2)(vue-tsc@2.0.29(typescript@5.8.2)) - packages/directive-functions-plugin: dependencies: '@babel/code-frame': @@ -7356,11 +7181,6 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@commander-js/extra-typings@12.1.0': - resolution: {integrity: sha512-wf/lwQvWAA0goIghcb91dQYpkLBcyhOhQNqG/VgWhnKzgt+UOMvra7EX/2fv70arm5RW+PUHoQHHDa6/p77Eqg==} - peerDependencies: - commander: ~12.1.0 - '@commitlint/parse@19.5.0': resolution: {integrity: sha512-cZ/IxfAlfWYhAQV0TwcbdR1Oc0/r0Ik1GEessDJ3Lbuma/MRO8FRQX76eurcXtmhJC//rj52ZSZuXUg0oIX0Fw==} engines: {node: '>=v18'} @@ -8534,14 +8354,6 @@ packages: resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} engines: {node: '>=18.18'} - '@inquirer/checkbox@2.5.0': - resolution: {integrity: sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==} - engines: {node: '>=18'} - - '@inquirer/confirm@3.2.0': - resolution: {integrity: sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==} - engines: {node: '>=18'} - '@inquirer/confirm@5.1.4': resolution: {integrity: sha512-EsiT7K4beM5fN5Mz6j866EFA9+v9d5o9VUra3hrg8zY4GHmCS8b616FErbdo5eyKoVotBQkHzMIeeKYsKDStDw==} engines: {node: '>=18'} @@ -8552,58 +8364,10 @@ packages: resolution: {integrity: sha512-/vyCWhET0ktav/mUeBqJRYTwmjFPIKPRYb3COAw7qORULgipGSUO2vL32lQKki3UxDKJ8BvuEbokaoyCA6YlWw==} engines: {node: '>=18'} - '@inquirer/core@9.2.1': - resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} - engines: {node: '>=18'} - - '@inquirer/editor@2.2.0': - resolution: {integrity: sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==} - engines: {node: '>=18'} - - '@inquirer/expand@2.3.0': - resolution: {integrity: sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==} - engines: {node: '>=18'} - '@inquirer/figures@1.0.10': resolution: {integrity: sha512-Ey6176gZmeqZuY/W/nZiUyvmb1/qInjcpiZjXWi6nON+nxJpD1bxtSoBxNliGISae32n6OwbY+TSXPZ1CfS4bw==} engines: {node: '>=18'} - '@inquirer/input@2.3.0': - resolution: {integrity: sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==} - engines: {node: '>=18'} - - '@inquirer/number@1.1.0': - resolution: {integrity: sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==} - engines: {node: '>=18'} - - '@inquirer/password@2.2.0': - resolution: {integrity: sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==} - engines: {node: '>=18'} - - '@inquirer/prompts@5.5.0': - resolution: {integrity: sha512-BHDeL0catgHdcHbSFFUddNzvx/imzJMft+tWDPwTm3hfu8/tApk1HrooNngB2Mb4qY+KaRWF+iZqoVUPeslEog==} - engines: {node: '>=18'} - - '@inquirer/rawlist@2.3.0': - resolution: {integrity: sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==} - engines: {node: '>=18'} - - '@inquirer/search@1.1.0': - resolution: {integrity: sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ==} - engines: {node: '>=18'} - - '@inquirer/select@2.5.0': - resolution: {integrity: sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==} - engines: {node: '>=18'} - - '@inquirer/type@1.5.5': - resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} - engines: {node: '>=18'} - - '@inquirer/type@2.0.0': - resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} - engines: {node: '>=18'} - '@inquirer/type@3.0.4': resolution: {integrity: sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA==} engines: {node: '>=18'} @@ -8830,62 +8594,62 @@ packages: '@nothing-but/utils@0.17.0': resolution: {integrity: sha512-TuCHcHLOqDL0SnaAxACfuRHBNRgNJcNn9X0GiH5H3YSDBVquCr3qEIG3FOQAuMyZCbu9w8nk2CHhOsn7IvhIwQ==} - '@nx/nx-darwin-arm64@20.4.2': - resolution: {integrity: sha512-djXV3rZcDdps2TUo7bMNiB6IkxFlLIZfub5cxPhxSbnrKiMGqmISZNn9n0AmchpNNL6auRWZPAPtDfowtR5GqA==} + '@nx/nx-darwin-arm64@20.8.1': + resolution: {integrity: sha512-Gat4Io66cV70Oa1CjrMJPsEx5ICpAGayv9hejOtBUEDb6XjR12L2e4wV+4EHliF0UbEcuZAr8/lTROEPk0RGWQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@nx/nx-darwin-x64@20.4.2': - resolution: {integrity: sha512-3PsiO4zEGgco/pSkYnHIB2j/IEnxsaoME+WdRYa8nRfewASAqCqf7e8DyOCftR7CBsXRosiUQWDcICu3cIfBgw==} + '@nx/nx-darwin-x64@20.8.1': + resolution: {integrity: sha512-TB9mZk7neGFKgBr2wSBgY6c4kFF9vvChNSp3TrEeXR3FppFcYG5eK4AaKfzWCpYb0wMtseAm7NMX1Lu74utClQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@nx/nx-freebsd-x64@20.4.2': - resolution: {integrity: sha512-FXaQqn67KDGF6b735GCjFVyWVFWYrVxftvmaM/V4pCmJXjhO3K9NV3jhPVj2MNmrpdYwUtfTP1JMpr/iUBYCQA==} + '@nx/nx-freebsd-x64@20.8.1': + resolution: {integrity: sha512-7UQu0/Afna5Af2GagEQ6rbKfUh75NfUn+g66wsoQoUGBvDW0U7B8P3Ph5Bk4Urub0BSfMVcNg2X7CgfypLFN/g==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@nx/nx-linux-arm-gnueabihf@20.4.2': - resolution: {integrity: sha512-RcVr6VN7lWJybr0bjs2zaK9mQ0OMFmuILx/8IDniLjAQK8JB+1qQhHLgunAAUJtWv+o0sVb6WXlN/F7PTegmEA==} + '@nx/nx-linux-arm-gnueabihf@20.8.1': + resolution: {integrity: sha512-Tjh8JkTP+x1jSrzx+ofx1pKpkhIbXd7bi0bPdpYt6NI1lZz2HB/dv8vtdzP80jXEDztHf0AeGnEJVgJKsgI6yg==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@nx/nx-linux-arm64-gnu@20.4.2': - resolution: {integrity: sha512-Gt38hdU615g+pUAUHe5Z9ingLgpDKNumbJfqe6Y65N9XDHMGvi3YpUwFio2t/8DNZDYY7FH46CBYydDCJjDNyw==} + '@nx/nx-linux-arm64-gnu@20.8.1': + resolution: {integrity: sha512-2+qPIwav2vrytH6pe7fukBe8+yN5JGbEDCnDO8wKQsHeeZMLAQJiZ7EJH/+vynRkI7oWf87mihIKNQME19+w6A==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@nx/nx-linux-arm64-musl@20.4.2': - resolution: {integrity: sha512-Kp658KNoRfhi4a/1eoXrxxBiw2kkXqR745iuytVn1f/BL3L2tUHCp6+OyFF7sLx8TnlU9yZAxO62k4DPqS+Ffw==} + '@nx/nx-linux-arm64-musl@20.8.1': + resolution: {integrity: sha512-DsKc+DiMsuHqpBWchUUUg6zv4OaexRqpFXys6auZlrpFpn80kSqLQ3S4zZ5AUu+26wxZqEVJs+uxHGwFbhEssQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@nx/nx-linux-x64-gnu@20.4.2': - resolution: {integrity: sha512-v+qOF2tmFFPX3fYYCqcdLIgATqlaQcBSHDs8EbwZjdncWk6RQAI/hq6+06+oZQc71RnyhBq5zBE12P0Bj1qTbw==} + '@nx/nx-linux-x64-gnu@20.8.1': + resolution: {integrity: sha512-Kzru44beVKAmSG84ShuMIIfyu2Uu5r8gsHdtiQPBIOGkZa0Z/e6YtUxcN3w1UZ7yvvzoQ4pQLvqU6UZRSWZtEg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@nx/nx-linux-x64-musl@20.4.2': - resolution: {integrity: sha512-MxlAqNItkSyiVcB91pOpYWX2Mj6PL9+GzPa63TA0v4PcpZTsFmToYlbKno/1e2T6AKI/0R1ZkAo1XxurUc++nw==} + '@nx/nx-linux-x64-musl@20.8.1': + resolution: {integrity: sha512-cSVVb7DVMhrxCaj/n55okBZS6lZoP5a5vynOBGIV4z3/OJLev+xI9A+3imn/aXnBl8iS69HogYyrW0YTXv4Xaw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@nx/nx-win32-arm64-msvc@20.4.2': - resolution: {integrity: sha512-0FkvctI4lXFK0BEhQjM5If9RC0ja16oVjSacyLY893gBhbSI56Ud/XSA75uF6aplA4AvBe97NPQg5l5btJSxYw==} + '@nx/nx-win32-arm64-msvc@20.8.1': + resolution: {integrity: sha512-gte5HcvI24CN6b9I6IYTXh/A0CtRfnlAFaJomPpfT8Wcq637aOZzS0arAEZVoU8QZty1350hj6sfu+wSIjoP7A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@nx/nx-win32-x64-msvc@20.4.2': - resolution: {integrity: sha512-J7Nh/3hfdlbEXvvIYJI+tAnvupYaeDwSU8ZRlDV7VU5Ee9VLT3hDLhmtXcDjEZnFHNPyaIYgFZXXDppU3a04Xg==} + '@nx/nx-win32-x64-msvc@20.8.1': + resolution: {integrity: sha512-6c2fVEPdPwJdnRbckBatRDF/g6JAp6p3Mfl90DpuaEF2DZC5pmCXKOsXE0aSIZ+gODom2JIchM++2KmDZPJUoA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -9008,8 +8772,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@playwright/test@1.50.1': - resolution: {integrity: sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==} + '@playwright/test@1.52.0': + resolution: {integrity: sha512-uh6W7sb55hl7D6vsAeA+V2p5JnlAqzhqFyF0VcJkKZXkgnFcVG9PziERRHQfPLfNGx1C292a4JqbWzhR8L4R1g==} engines: {node: '>=18'} hasBin: true @@ -9969,15 +9733,6 @@ packages: rollup: optional: true - '@rollup/plugin-node-resolve@16.0.0': - resolution: {integrity: sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^2.78.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - '@rollup/plugin-replace@6.0.2': resolution: {integrity: sha512-7QaYCf8bqF04dOy7w/eHmJeNExxTYwvKAmlSAH/EaWWUzbT0h5sbF6bktFoX/0F/0qwng5/dWFMyf3gzaM8DsQ==} engines: {node: '>=14.0.0'} @@ -10772,10 +10527,6 @@ packages: react-dom: ^19.0.0 typescript: '>=5.7.2' - '@trysound/sax@0.2.0': - resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} - engines: {node: '>=10.13.0'} - '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -10833,9 +10584,6 @@ packages: '@types/cookies@0.9.0': resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} - '@types/cross-spawn@6.0.6': - resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} - '@types/diff@6.0.0': resolution: {integrity: sha512-dhVCYGv3ZSbzmQaBSagrv1WJ6rXCdkyTcDyoNu1MD8JohI7pR7k8wdZEm+mvdxRKXyHVwckFzWU1vJc+Z29MlA==} @@ -10860,15 +10608,9 @@ packages: '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - '@types/fs-extra@8.1.5': - resolution: {integrity: sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ==} - '@types/gensync@1.0.4': resolution: {integrity: sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==} - '@types/glob@7.2.0': - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} @@ -10908,12 +10650,6 @@ packages: '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/minimatch@5.1.2': - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - - '@types/mute-stream@0.0.4': - resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} - '@types/node-forge@1.3.11': resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} @@ -10972,24 +10708,12 @@ packages: '@types/statuses@2.0.5': resolution: {integrity: sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A==} - '@types/tinycolor2@1.4.6': - resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} - '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/validate-npm-package-name@4.0.2': - resolution: {integrity: sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw==} - - '@types/which@3.0.4': - resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==} - - '@types/wrap-ansi@3.0.0': - resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} - '@types/ws@8.5.14': resolution: {integrity: sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==} @@ -11460,10 +11184,6 @@ packages: resolution: {integrity: sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==} engines: {node: '>=0.10.0'} - array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - asn1js@3.0.6: resolution: {integrity: sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==} engines: {node: '>=12.0.0'} @@ -11488,8 +11208,8 @@ packages: peerDependencies: postcss: ^8.1.0 - axios@1.7.9: - resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} + axios@1.9.0: + resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} @@ -11621,9 +11341,6 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} - caniuse-api@3.0.0: - resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001696: resolution: {integrity: sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==} @@ -11650,9 +11367,6 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} - chardet@0.7.0: - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} - check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -11749,9 +11463,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - colord@2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} @@ -11769,10 +11480,6 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} - commander@13.1.0: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} @@ -11784,10 +11491,6 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} @@ -11936,30 +11639,9 @@ packages: crossws@0.3.3: resolution: {integrity: sha512-/71DJT3xJlqSnBr83uGJesmVHSzZEvgxHt/fIKxBAAngqMHmnBWQNxCphVxxJ2XL3xleu5+hJD6IQ3TglBedcw==} - crypto-random-string@4.0.0: - resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} - engines: {node: '>=12'} - - css-declaration-sorter@7.2.0: - resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==} - engines: {node: ^14 || ^16 || >=18} - peerDependencies: - postcss: ^8.0.9 - css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - css-select@5.1.0: - resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} - - css-tree@2.2.1: - resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - - css-tree@2.3.1: - resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} - css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -11972,28 +11654,6 @@ packages: engines: {node: '>=4'} hasBin: true - cssnano-preset-default@7.0.6: - resolution: {integrity: sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - cssnano-utils@5.0.0: - resolution: {integrity: sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - cssnano@7.0.6: - resolution: {integrity: sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - csso@5.0.5: - resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} - engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} - cssstyle@4.2.1: resolution: {integrity: sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==} engines: {node: '>=18'} @@ -12168,10 +11828,6 @@ packages: resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} engines: {node: '>=0.3.1'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} @@ -12198,9 +11854,6 @@ packages: dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dom-serializer@2.0.0: - resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} - domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} @@ -12208,16 +11861,9 @@ packages: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} - domhandler@5.0.3: - resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} - engines: {node: '>= 4'} - domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - domutils@3.2.2: - resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} - dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -12588,10 +12234,6 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - external-editor@3.1.0: - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} - engines: {node: '>=4'} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -12761,10 +12403,6 @@ packages: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} - fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} @@ -12871,10 +12509,6 @@ packages: resolution: {integrity: sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==} engines: {node: '>=18'} - globby@10.0.1: - resolution: {integrity: sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==} - engines: {node: '>=8'} - globby@14.0.2: resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} engines: {node: '>=18'} @@ -12894,10 +12528,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - gradient-string@3.0.0: - resolution: {integrity: sha512-frdKI4Qi8Ihp4C6wZNB565de/THpIaw3DjP5ku87M+N9rNSGmPTjfkq61SdRXB7eCaL8O1hkKDvf6CDMtOzIAg==} - engines: {node: '>=14'} - graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -13225,10 +12855,6 @@ packages: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} - is-plain-object@3.0.1: - resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} - engines: {node: '>=0.10.0'} - is-plain-object@5.0.0: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} @@ -13569,15 +13195,9 @@ packages: lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -13656,12 +13276,6 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - mdn-data@2.0.28: - resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} - - mdn-data@2.0.30: - resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} - mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} @@ -13804,24 +13418,6 @@ packages: engines: {node: '>=10'} hasBin: true - mkdist@2.2.0: - resolution: {integrity: sha512-GfKwu4A2grXfhj2TZm4ydfzP515NaALqKaPq4WqaZ6NhEnD47BiIQPySoCTTvVqHxYcuqVkNdCXjYf9Bz1Y04Q==} - hasBin: true - peerDependencies: - sass: ^1.83.0 - typescript: '>=5.7.2' - vue: ^3.5.13 - vue-tsc: ^1.8.27 || ^2.0.21 - peerDependenciesMeta: - sass: - optional: true - typescript: - optional: true - vue: - optional: true - vue-tsc: - optional: true - mlly@1.7.4: resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==} @@ -13862,10 +13458,6 @@ packages: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} hasBin: true - mute-stream@1.0.0: - resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - mute-stream@2.0.0: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} @@ -13973,8 +13565,8 @@ packages: nwsapi@2.2.16: resolution: {integrity: sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==} - nx@20.4.2: - resolution: {integrity: sha512-WXbKqk8looDo9zAISfmWtGyGm5RlOvr0G/THAa1WGSU4qHAZDsUtMAtwnxXje9s+R5rrwMmhbXCVvZELyeJP9Q==} + nx@20.8.1: + resolution: {integrity: sha512-73Uw8YXpsjeLqHSl7NMCmGdCs+8ynPzoNJFWAqVanPETEY9zPd5wevVQmeyzYtNNQU35uj6Os4iUzYunmwnFaA==} hasBin: true peerDependencies: '@swc-node/register': ^1.8.0 @@ -14060,10 +13652,6 @@ packages: resolution: {integrity: sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==} engines: {node: '>=10'} - os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} @@ -14230,13 +13818,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - playwright-core@1.50.1: - resolution: {integrity: sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==} + playwright-core@1.52.0: + resolution: {integrity: sha512-l2osTgLXSMeuLZOML9qYODUQoPPnUsKsb5/P6LJ2e6uPKXUdPK5WYhN4z03G+YNbWmGDY4YENauNu4ZKczreHg==} engines: {node: '>=18'} hasBin: true - playwright@1.50.1: - resolution: {integrity: sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==} + playwright@1.52.0: + resolution: {integrity: sha512-JAwMNMBlxJ2oD1kce4KPtMkDeKGHQstdpFPcPH3maElAXon/QZeTvtsfXmTMRyO9TslfoYOXkSsvao2nE1ilTw==} engines: {node: '>=18'} hasBin: true @@ -14244,48 +13832,6 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - postcss-calc@10.1.1: - resolution: {integrity: sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==} - engines: {node: ^18.12 || ^20.9 || >=22.0} - peerDependencies: - postcss: ^8.4.38 - - postcss-colormin@7.0.2: - resolution: {integrity: sha512-YntRXNngcvEvDbEjTdRWGU606eZvB5prmHG4BF0yLmVpamXbpsRJzevyy6MZVyuecgzI2AWAlvFi8DAeCqwpvA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-convert-values@7.0.4: - resolution: {integrity: sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-discard-comments@7.0.3: - resolution: {integrity: sha512-q6fjd4WU4afNhWOA2WltHgCbkRhZPgQe7cXF74fuVB/ge4QbM9HEaOIzGSiMvM+g/cOsNAUGdf2JDzqA2F8iLA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-discard-duplicates@7.0.1: - resolution: {integrity: sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-discard-empty@7.0.0: - resolution: {integrity: sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-discard-overridden@7.0.0: - resolution: {integrity: sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - postcss-import@15.1.0: resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} engines: {node: '>=14.0.0'} @@ -14310,166 +13856,36 @@ packages: ts-node: optional: true - postcss-merge-longhand@7.0.4: - resolution: {integrity: sha512-zer1KoZA54Q8RVHKOY5vMke0cCdNxMP3KBfDerjH/BYHh4nCIh+1Yy0t1pAEQF18ac/4z3OFclO+ZVH8azjR4A==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-merge-rules@7.0.4: - resolution: {integrity: sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-minify-font-values@7.0.0: - resolution: {integrity: sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-minify-gradients@7.0.0: - resolution: {integrity: sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-minify-params@7.0.2: - resolution: {integrity: sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-minify-selectors@7.0.4: - resolution: {integrity: sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - postcss-nested@6.2.0: resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 - postcss-nested@7.0.2: - resolution: {integrity: sha512-5osppouFc0VR9/VYzYxO03VaDa3e8F23Kfd6/9qcZTUI8P58GIYlArOET2Wq0ywSl2o2PjELhYOFI4W7l5QHKw==} - engines: {node: '>=18.0'} - peerDependencies: - postcss: ^8.2.14 + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} - postcss-normalize-charset@7.0.0: - resolution: {integrity: sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss-normalize-display-values@7.0.0: - resolution: {integrity: sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} - postcss-normalize-positions@7.0.0: - resolution: {integrity: sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} - postcss-normalize-repeat-style@7.0.0: - resolution: {integrity: sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 + prettier@3.4.2: + resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} + engines: {node: '>=14'} + hasBin: true - postcss-normalize-string@7.0.0: - resolution: {integrity: sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-normalize-timing-functions@7.0.0: - resolution: {integrity: sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-normalize-unicode@7.0.2: - resolution: {integrity: sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-normalize-url@7.0.0: - resolution: {integrity: sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-normalize-whitespace@7.0.0: - resolution: {integrity: sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-ordered-values@7.0.1: - resolution: {integrity: sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-reduce-initial@7.0.2: - resolution: {integrity: sha512-pOnu9zqQww7dEKf62Nuju6JgsW2V0KRNBHxeKohU+JkHd/GAH5uvoObqFLqkeB2n20mr6yrlWDvo5UBU5GnkfA==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-reduce-transforms@7.0.0: - resolution: {integrity: sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} - engines: {node: '>=4'} - - postcss-selector-parser@7.0.0: - resolution: {integrity: sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==} - engines: {node: '>=4'} - - postcss-svgo@7.0.1: - resolution: {integrity: sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA==} - engines: {node: ^18.12.0 || ^20.9.0 || >= 18} - peerDependencies: - postcss: ^8.4.31 - - postcss-unique-selectors@7.0.3: - resolution: {integrity: sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - - postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - - postcss@8.5.3: - resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} - engines: {node: ^10 || ^12 || >=14} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier@3.4.2: - resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==} - engines: {node: '>=14'} - hasBin: true - - prettier@3.5.0: - resolution: {integrity: sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA==} - engines: {node: '>=14'} - hasBin: true + prettier@3.5.0: + resolution: {integrity: sha512-quyMrVt6svPS7CjQ9gKb3GLEX/rl3BCL2oa/QkNcXv4YNVBC9olt3s+H7ukto06q7B1Qz46PbrKLO34PR6vXcA==} + engines: {node: '>=14'} + hasBin: true pretty-bytes@6.1.1: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} @@ -14768,17 +14184,6 @@ packages: engines: {node: 20 || >=22} hasBin: true - rollup-plugin-copy@3.5.0: - resolution: {integrity: sha512-wI8D5dvYovRMx/YYKtUNt3Yxaw4ORC9xo6Gt9t22kveWz1enG9QrhVlagzwrxSC455xD1dHMKhIJkbsQ7d48BA==} - engines: {node: '>=8.3'} - - rollup-plugin-dts@6.1.1: - resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} - engines: {node: '>=16'} - peerDependencies: - rollup: ^3.29.4 || ^4 - typescript: ^4.5 || ^5.0 - rollup-plugin-preserve-directives@0.4.0: resolution: {integrity: sha512-gx4nBxYm5BysmEQS+e2tAMrtFxrGvk+Pe5ppafRibQi0zlW7VYAbEGk6IKDw9sJGPdFWgVTE0o4BU4cdG0Fylg==} peerDependencies: @@ -14961,10 +14366,6 @@ packages: resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} engines: {node: '>=8'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - slash@5.1.0: resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} engines: {node: '>=14.16'} @@ -15106,12 +14507,6 @@ packages: style-to-object@1.0.8: resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} - stylehacks@7.0.4: - resolution: {integrity: sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==} - engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} - peerDependencies: - postcss: ^8.4.31 - stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} @@ -15144,11 +14539,6 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - svgo@3.3.2: - resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} - engines: {node: '>=14.0.0'} - hasBin: true - swc-loader@0.2.6: resolution: {integrity: sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==} peerDependencies: @@ -15197,14 +14587,6 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} - temp-dir@3.0.0: - resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} - engines: {node: '>=14.16'} - - tempy@3.1.0: - resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} - engines: {node: '>=14.16'} - terser-webpack-plugin@5.3.11: resolution: {integrity: sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==} engines: {node: '>= 10.13.0'} @@ -15261,9 +14643,6 @@ packages: tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinycolor2@1.6.0: - resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} - tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} @@ -15271,9 +14650,6 @@ packages: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} - tinygradient@1.1.5: - resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==} - tinypool@1.0.2: resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -15293,10 +14669,6 @@ packages: resolution: {integrity: sha512-6U2ti64/nppsDxQs9hw8ephA3nO6nSQvVVfxwRw8wLQPFtLI1cFI1a1eP22g+LUP+1TA2pKKjUTwWB+K2coqmQ==} hasBin: true - tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - tmp@0.2.3: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} @@ -15385,10 +14757,6 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@1.4.0: - resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} - engines: {node: '>=10'} - type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} @@ -15477,15 +14845,6 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - unbuild@3.3.1: - resolution: {integrity: sha512-/5OeeHmW1JlWEyQw3SPkB9BV16lzr6C5i8D+O17NLx6ETgvCZ3ZlyXfWkVVfG2YCsv8xAVQCqJNJtbEAGwHg7A==} - hasBin: true - peerDependencies: - typescript: ^5.7.3 - peerDependenciesMeta: - typescript: - optional: true - unc-path-regex@0.1.2: resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} engines: {node: '>=0.10.0'} @@ -15516,10 +14875,6 @@ packages: unimport@3.14.6: resolution: {integrity: sha512-CYvbDaTT04Rh8bmD8jz3WPmHYZRG/NnvYVzwD6V1YAlvvKROlAeNDUBhkBGzNav2RKaeuXvlWYaa1V4Lfi/O0g==} - unique-string@3.0.0: - resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} - engines: {node: '>=12'} - universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -15700,10 +15055,6 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - validate-npm-package-name@6.0.0: - resolution: {integrity: sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==} - engines: {node: ^18.17.0 || >=20.5.0} - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -15985,11 +15336,6 @@ packages: engines: {node: ^16.13.0 || >=18.0.0} hasBin: true - which@5.0.0: - resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} - engines: {node: ^18.17.0 || >=20.5.0} - hasBin: true - why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} engines: {node: '>=8'} @@ -16086,18 +15432,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - yocto-spinner@0.2.0: - resolution: {integrity: sha512-Qu6WAqNLGleB687CCGcmgHIo8l+J19MX/32UrSMfbf/4L8gLoxjpOYoiHT1asiWyqvjRZbgvOhLlvne6E5Tbdw==} - engines: {node: '>=18.19'} - yoctocolors-cjs@2.1.2: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} - yoctocolors@2.1.1: - resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} - engines: {node: '>=18'} - zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} @@ -16446,10 +15784,6 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@commander-js/extra-typings@12.1.0(commander@12.1.0)': - dependencies: - commander: 12.1.0 - '@commitlint/parse@19.5.0': dependencies: '@commitlint/types': 19.5.0 @@ -17459,19 +16793,6 @@ snapshots: '@humanwhocodes/retry@0.4.2': {} - '@inquirer/checkbox@2.5.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/figures': 1.0.10 - '@inquirer/type': 1.5.5 - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 - - '@inquirer/confirm@3.2.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - '@inquirer/confirm@5.1.4(@types/node@22.13.4)': dependencies: '@inquirer/core': 10.1.5(@types/node@22.13.4) @@ -17491,93 +16812,8 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@inquirer/core@9.2.1': - dependencies: - '@inquirer/figures': 1.0.10 - '@inquirer/type': 2.0.0 - '@types/mute-stream': 0.0.4 - '@types/node': 22.13.4 - '@types/wrap-ansi': 3.0.0 - ansi-escapes: 4.3.2 - cli-width: 4.1.0 - mute-stream: 1.0.0 - signal-exit: 4.1.0 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - yoctocolors-cjs: 2.1.2 - - '@inquirer/editor@2.2.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - external-editor: 3.1.0 - - '@inquirer/expand@2.3.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - yoctocolors-cjs: 2.1.2 - '@inquirer/figures@1.0.10': {} - '@inquirer/input@2.3.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - - '@inquirer/number@1.1.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - - '@inquirer/password@2.2.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - ansi-escapes: 4.3.2 - - '@inquirer/prompts@5.5.0': - dependencies: - '@inquirer/checkbox': 2.5.0 - '@inquirer/confirm': 3.2.0 - '@inquirer/editor': 2.2.0 - '@inquirer/expand': 2.3.0 - '@inquirer/input': 2.3.0 - '@inquirer/number': 1.1.0 - '@inquirer/password': 2.2.0 - '@inquirer/rawlist': 2.3.0 - '@inquirer/search': 1.1.0 - '@inquirer/select': 2.5.0 - - '@inquirer/rawlist@2.3.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/type': 1.5.5 - yoctocolors-cjs: 2.1.2 - - '@inquirer/search@1.1.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/figures': 1.0.10 - '@inquirer/type': 1.5.5 - yoctocolors-cjs: 2.1.2 - - '@inquirer/select@2.5.0': - dependencies: - '@inquirer/core': 9.2.1 - '@inquirer/figures': 1.0.10 - '@inquirer/type': 1.5.5 - ansi-escapes: 4.3.2 - yoctocolors-cjs: 2.1.2 - - '@inquirer/type@1.5.5': - dependencies: - mute-stream: 1.0.0 - - '@inquirer/type@2.0.0': - dependencies: - mute-stream: 1.0.0 - '@inquirer/type@3.0.4(@types/node@22.13.4)': optionalDependencies: '@types/node': 22.13.4 @@ -17861,34 +17097,34 @@ snapshots: '@nothing-but/utils@0.17.0': {} - '@nx/nx-darwin-arm64@20.4.2': + '@nx/nx-darwin-arm64@20.8.1': optional: true - '@nx/nx-darwin-x64@20.4.2': + '@nx/nx-darwin-x64@20.8.1': optional: true - '@nx/nx-freebsd-x64@20.4.2': + '@nx/nx-freebsd-x64@20.8.1': optional: true - '@nx/nx-linux-arm-gnueabihf@20.4.2': + '@nx/nx-linux-arm-gnueabihf@20.8.1': optional: true - '@nx/nx-linux-arm64-gnu@20.4.2': + '@nx/nx-linux-arm64-gnu@20.8.1': optional: true - '@nx/nx-linux-arm64-musl@20.4.2': + '@nx/nx-linux-arm64-musl@20.8.1': optional: true - '@nx/nx-linux-x64-gnu@20.4.2': + '@nx/nx-linux-x64-gnu@20.8.1': optional: true - '@nx/nx-linux-x64-musl@20.4.2': + '@nx/nx-linux-x64-musl@20.8.1': optional: true - '@nx/nx-win32-arm64-msvc@20.4.2': + '@nx/nx-win32-arm64-msvc@20.8.1': optional: true - '@nx/nx-win32-x64-msvc@20.4.2': + '@nx/nx-win32-x64-msvc@20.8.1': optional: true '@open-draft/deferred-promise@2.2.0': {} @@ -17991,9 +17227,9 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@playwright/test@1.50.1': + '@playwright/test@1.52.0': dependencies: - playwright: 1.50.1 + playwright: 1.52.0 '@polka/url@1.0.0-next.28': {} @@ -18967,16 +18203,6 @@ snapshots: optionalDependencies: rollup: 4.39.0 - '@rollup/plugin-node-resolve@16.0.0(rollup@4.39.0)': - dependencies: - '@rollup/pluginutils': 5.1.4(rollup@4.39.0) - '@types/resolve': 1.20.2 - deepmerge: 4.3.1 - is-module: 1.0.0 - resolve: 1.22.10 - optionalDependencies: - rollup: 4.39.0 - '@rollup/plugin-replace@6.0.2(rollup@4.39.0)': dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.39.0) @@ -19799,8 +19025,6 @@ snapshots: react-dom: 19.0.0(react@19.0.0) typescript: 5.8.2 - '@trysound/sax@0.2.0': {} - '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 @@ -19873,10 +19097,6 @@ snapshots: '@types/keygrip': 1.0.6 '@types/node': 22.13.4 - '@types/cross-spawn@6.0.6': - dependencies: - '@types/node': 22.13.4 - '@types/diff@6.0.0': {} '@types/doctrine@0.0.9': {} @@ -19914,17 +19134,8 @@ snapshots: '@types/qs': 6.9.18 '@types/serve-static': 1.15.7 - '@types/fs-extra@8.1.5': - dependencies: - '@types/node': 22.13.4 - '@types/gensync@1.0.4': {} - '@types/glob@7.2.0': - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 22.13.4 - '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 @@ -19968,12 +19179,6 @@ snapshots: '@types/mime@1.3.5': {} - '@types/minimatch@5.1.2': {} - - '@types/mute-stream@0.0.4': - dependencies: - '@types/node': 22.13.4 - '@types/node-forge@1.3.11': dependencies: '@types/node': 22.13.4 @@ -20031,18 +19236,10 @@ snapshots: '@types/statuses@2.0.5': {} - '@types/tinycolor2@1.4.6': {} - '@types/tough-cookie@4.0.5': {} '@types/unist@3.0.3': {} - '@types/validate-npm-package-name@4.0.2': {} - - '@types/which@3.0.4': {} - - '@types/wrap-ansi@3.0.0': {} - '@types/ws@8.5.14': dependencies: '@types/node': 22.13.4 @@ -20241,7 +19438,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/browser@3.0.6(@types/node@22.13.4)(playwright@1.50.1)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))(vitest@3.0.6)': + '@vitest/browser@3.0.6(@types/node@22.13.4)(playwright@1.52.0)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))(vitest@3.0.6)': dependencies: '@testing-library/dom': 10.4.0 '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) @@ -20254,7 +19451,7 @@ snapshots: vitest: 3.0.6(@types/node@22.13.4)(@vitest/browser@3.0.6)(@vitest/ui@3.0.6)(jiti@2.4.2)(jsdom@25.0.1)(lightningcss@1.29.1)(msw@2.7.0(@types/node@22.13.4)(typescript@5.8.2))(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) ws: 8.18.0 optionalDependencies: - playwright: 1.50.1 + playwright: 1.52.0 transitivePeerDependencies: - '@types/node' - bufferutil @@ -20664,8 +19861,6 @@ snapshots: array-slice@1.1.0: {} - array-union@2.1.0: {} - asn1js@3.0.6: dependencies: pvtsutils: 1.3.6 @@ -20690,7 +19885,7 @@ snapshots: postcss: 8.5.3 postcss-value-parser: 4.2.0 - axios@1.7.9: + axios@1.9.0: dependencies: follow-redirects: 1.15.9 form-data: 4.0.1 @@ -20868,13 +20063,6 @@ snapshots: camelcase@7.0.1: {} - caniuse-api@3.0.0: - dependencies: - browserslist: 4.24.4 - caniuse-lite: 1.0.30001696 - lodash.memoize: 4.1.2 - lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001696: {} chai@5.2.0: @@ -20901,8 +20089,6 @@ snapshots: char-regex@1.0.2: {} - chardet@0.7.0: {} - check-error@2.1.1: {} chokidar@3.6.0: @@ -21000,8 +20186,6 @@ snapshots: color-name@1.1.4: {} - colord@2.9.3: {} - colorette@1.4.0: {} colorette@2.0.20: {} @@ -21014,16 +20198,12 @@ snapshots: commander@10.0.1: {} - commander@12.1.0: {} - commander@13.1.0: {} commander@2.20.3: {} commander@4.1.1: {} - commander@7.2.0: {} - commander@8.3.0: {} commondir@1.0.1: {} @@ -21161,14 +20341,6 @@ snapshots: dependencies: uncrypto: 0.1.3 - crypto-random-string@4.0.0: - dependencies: - type-fest: 1.4.0 - - css-declaration-sorter@7.2.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - css-select@4.3.0: dependencies: boolbase: 1.0.0 @@ -21177,78 +20349,12 @@ snapshots: domutils: 2.8.0 nth-check: 2.1.1 - css-select@5.1.0: - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 5.0.3 - domutils: 3.2.2 - nth-check: 2.1.1 - - css-tree@2.2.1: - dependencies: - mdn-data: 2.0.28 - source-map-js: 1.2.1 - - css-tree@2.3.1: - dependencies: - mdn-data: 2.0.30 - source-map-js: 1.2.1 - css-what@6.1.0: {} css.escape@1.5.1: {} cssesc@3.0.0: {} - cssnano-preset-default@7.0.6(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - css-declaration-sorter: 7.2.0(postcss@8.5.3) - cssnano-utils: 5.0.0(postcss@8.5.3) - postcss: 8.5.3 - postcss-calc: 10.1.1(postcss@8.5.3) - postcss-colormin: 7.0.2(postcss@8.5.3) - postcss-convert-values: 7.0.4(postcss@8.5.3) - postcss-discard-comments: 7.0.3(postcss@8.5.3) - postcss-discard-duplicates: 7.0.1(postcss@8.5.3) - postcss-discard-empty: 7.0.0(postcss@8.5.3) - postcss-discard-overridden: 7.0.0(postcss@8.5.3) - postcss-merge-longhand: 7.0.4(postcss@8.5.3) - postcss-merge-rules: 7.0.4(postcss@8.5.3) - postcss-minify-font-values: 7.0.0(postcss@8.5.3) - postcss-minify-gradients: 7.0.0(postcss@8.5.3) - postcss-minify-params: 7.0.2(postcss@8.5.3) - postcss-minify-selectors: 7.0.4(postcss@8.5.3) - postcss-normalize-charset: 7.0.0(postcss@8.5.3) - postcss-normalize-display-values: 7.0.0(postcss@8.5.3) - postcss-normalize-positions: 7.0.0(postcss@8.5.3) - postcss-normalize-repeat-style: 7.0.0(postcss@8.5.3) - postcss-normalize-string: 7.0.0(postcss@8.5.3) - postcss-normalize-timing-functions: 7.0.0(postcss@8.5.3) - postcss-normalize-unicode: 7.0.2(postcss@8.5.3) - postcss-normalize-url: 7.0.0(postcss@8.5.3) - postcss-normalize-whitespace: 7.0.0(postcss@8.5.3) - postcss-ordered-values: 7.0.1(postcss@8.5.3) - postcss-reduce-initial: 7.0.2(postcss@8.5.3) - postcss-reduce-transforms: 7.0.0(postcss@8.5.3) - postcss-svgo: 7.0.1(postcss@8.5.3) - postcss-unique-selectors: 7.0.3(postcss@8.5.3) - - cssnano-utils@5.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - - cssnano@7.0.6(postcss@8.5.3): - dependencies: - cssnano-preset-default: 7.0.6(postcss@8.5.3) - lilconfig: 3.1.3 - postcss: 8.5.3 - - csso@5.0.5: - dependencies: - css-tree: 2.2.1 - cssstyle@4.2.1: dependencies: '@asamuzakjp/css-color': 2.8.3 @@ -21349,10 +20455,6 @@ snapshots: diff@7.0.0: {} - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - dlv@1.1.3: {} dns-packet@5.6.1: @@ -21382,34 +20484,18 @@ snapshots: domhandler: 4.3.1 entities: 2.2.0 - dom-serializer@2.0.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 5.0.3 - entities: 4.5.0 - domelementtype@2.3.0: {} domhandler@4.3.1: dependencies: domelementtype: 2.3.0 - domhandler@5.0.3: - dependencies: - domelementtype: 2.3.0 - domutils@2.8.0: dependencies: dom-serializer: 1.4.1 domelementtype: 2.3.0 domhandler: 4.3.1 - domutils@3.2.2: - dependencies: - dom-serializer: 2.0.0 - domelementtype: 2.3.0 - domhandler: 5.0.3 - dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -22010,12 +21096,6 @@ snapshots: extend@3.0.2: {} - external-editor@3.1.0: - dependencies: - chardet: 0.7.0 - iconv-lite: 0.4.24 - tmp: 0.0.33 - fast-deep-equal@3.1.3: {} fast-fifo@1.3.2: {} @@ -22209,12 +21289,6 @@ snapshots: jsonfile: 4.0.0 universalify: 0.1.2 - fs-extra@8.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - fs-minipass@2.1.0: dependencies: minipass: 3.3.6 @@ -22338,17 +21412,6 @@ snapshots: globals@15.14.0: {} - globby@10.0.1: - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.3 - glob: 7.2.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - globby@14.0.2: dependencies: '@sindresorhus/merge-streams': 2.3.0 @@ -22368,11 +21431,6 @@ snapshots: graceful-fs@4.2.11: {} - gradient-string@3.0.0: - dependencies: - chalk: 5.4.1 - tinygradient: 1.1.5 - graphemer@1.4.0: {} graphql@16.10.0: {} @@ -22689,8 +21747,6 @@ snapshots: dependencies: isobject: 3.0.1 - is-plain-object@3.0.1: {} - is-plain-object@5.0.0: {} is-potential-custom-element-name@1.0.1: {} @@ -23001,12 +22057,8 @@ snapshots: lodash.isarguments@3.1.0: {} - lodash.memoize@4.1.2: {} - lodash.merge@4.6.2: {} - lodash.uniq@4.5.0: {} - lodash@4.17.21: {} log-symbols@4.1.0: @@ -23084,10 +22136,6 @@ snapshots: math-intrinsics@1.1.0: {} - mdn-data@2.0.28: {} - - mdn-data@2.0.30: {} - mdurl@2.0.0: {} media-typer@0.3.0: {} @@ -23194,25 +22242,6 @@ snapshots: mkdirp@3.0.1: {} - mkdist@2.2.0(typescript@5.8.2)(vue-tsc@2.0.29(typescript@5.8.2)): - dependencies: - autoprefixer: 10.4.20(postcss@8.5.3) - citty: 0.1.6 - cssnano: 7.0.6(postcss@8.5.3) - defu: 6.1.4 - esbuild: 0.24.2 - jiti: 1.21.7 - mlly: 1.7.4 - pathe: 1.1.2 - pkg-types: 1.3.1 - postcss: 8.5.3 - postcss-nested: 7.0.2(postcss@8.5.3) - semver: 7.7.0 - tinyglobby: 0.2.12 - optionalDependencies: - typescript: 5.8.2 - vue-tsc: 2.0.29(typescript@5.8.2) - mlly@1.7.4: dependencies: acorn: 8.14.0 @@ -23266,8 +22295,6 @@ snapshots: dns-packet: 5.6.1 thunky: 1.1.0 - mute-stream@1.0.0: {} - mute-stream@2.0.0: {} mz@2.7.0: @@ -23442,13 +22469,13 @@ snapshots: nwsapi@2.2.16: {} - nx@20.4.2(@swc/core@1.10.15(@swc/helpers@0.5.15)): + nx@20.8.1(@swc/core@1.10.15(@swc/helpers@0.5.15)): dependencies: '@napi-rs/wasm-runtime': 0.2.4 '@yarnpkg/lockfile': 1.1.0 '@yarnpkg/parsers': 3.0.2 '@zkochan/js-yaml': 0.0.7 - axios: 1.7.9 + axios: 1.9.0 chalk: 4.1.2 cli-cursor: 3.1.0 cli-spinners: 2.6.1 @@ -23479,16 +22506,16 @@ snapshots: yargs: 17.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@nx/nx-darwin-arm64': 20.4.2 - '@nx/nx-darwin-x64': 20.4.2 - '@nx/nx-freebsd-x64': 20.4.2 - '@nx/nx-linux-arm-gnueabihf': 20.4.2 - '@nx/nx-linux-arm64-gnu': 20.4.2 - '@nx/nx-linux-arm64-musl': 20.4.2 - '@nx/nx-linux-x64-gnu': 20.4.2 - '@nx/nx-linux-x64-musl': 20.4.2 - '@nx/nx-win32-arm64-msvc': 20.4.2 - '@nx/nx-win32-x64-msvc': 20.4.2 + '@nx/nx-darwin-arm64': 20.8.1 + '@nx/nx-darwin-x64': 20.8.1 + '@nx/nx-freebsd-x64': 20.8.1 + '@nx/nx-linux-arm-gnueabihf': 20.8.1 + '@nx/nx-linux-arm64-gnu': 20.8.1 + '@nx/nx-linux-arm64-musl': 20.8.1 + '@nx/nx-linux-x64-gnu': 20.8.1 + '@nx/nx-linux-x64-musl': 20.8.1 + '@nx/nx-win32-arm64-msvc': 20.8.1 + '@nx/nx-win32-x64-msvc': 20.8.1 '@swc/core': 1.10.15(@swc/helpers@0.5.15) transitivePeerDependencies: - debug @@ -23590,8 +22617,6 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 - os-tmpdir@1.0.2: {} - outvariant@1.4.3: {} p-limit@2.3.0: @@ -23735,53 +22760,16 @@ snapshots: mlly: 1.7.4 pathe: 2.0.3 - playwright-core@1.50.1: {} + playwright-core@1.52.0: {} - playwright@1.50.1: + playwright@1.52.0: dependencies: - playwright-core: 1.50.1 + playwright-core: 1.52.0 optionalDependencies: fsevents: 2.3.2 pluralize@8.0.0: {} - postcss-calc@10.1.1(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-selector-parser: 7.0.0 - postcss-value-parser: 4.2.0 - - postcss-colormin@7.0.2(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - caniuse-api: 3.0.0 - colord: 2.9.3 - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-convert-values@7.0.4(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-discard-comments@7.0.3(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - - postcss-discard-duplicates@7.0.1(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - - postcss-discard-empty@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - - postcss-discard-overridden@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-import@15.1.0(postcss@8.5.3): dependencies: postcss: 8.5.3 @@ -23801,138 +22789,16 @@ snapshots: optionalDependencies: postcss: 8.5.3 - postcss-merge-longhand@7.0.4(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - stylehacks: 7.0.4(postcss@8.5.3) - - postcss-merge-rules@7.0.4(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - caniuse-api: 3.0.0 - cssnano-utils: 5.0.0(postcss@8.5.3) - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - - postcss-minify-font-values@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-minify-gradients@7.0.0(postcss@8.5.3): - dependencies: - colord: 2.9.3 - cssnano-utils: 5.0.0(postcss@8.5.3) - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-minify-params@7.0.2(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - cssnano-utils: 5.0.0(postcss@8.5.3) - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-minify-selectors@7.0.4(postcss@8.5.3): - dependencies: - cssesc: 3.0.0 - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - postcss-nested@6.2.0(postcss@8.5.3): dependencies: postcss: 8.5.3 postcss-selector-parser: 6.1.2 - postcss-nested@7.0.2(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-selector-parser: 7.0.0 - - postcss-normalize-charset@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - - postcss-normalize-display-values@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-positions@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-repeat-style@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-string@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-timing-functions@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-unicode@7.0.2(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-url@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-normalize-whitespace@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-ordered-values@7.0.1(postcss@8.5.3): - dependencies: - cssnano-utils: 5.0.0(postcss@8.5.3) - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - - postcss-reduce-initial@7.0.2(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - caniuse-api: 3.0.0 - postcss: 8.5.3 - - postcss-reduce-transforms@7.0.0(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-selector-parser@7.0.0: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss-svgo@7.0.1(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-value-parser: 4.2.0 - svgo: 3.3.2 - - postcss-unique-selectors@7.0.3(postcss@8.5.3): - dependencies: - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - postcss-value-parser@4.2.0: {} postcss@8.5.3: @@ -24291,22 +23157,6 @@ snapshots: glob: 11.0.1 package-json-from-dist: 1.0.1 - rollup-plugin-copy@3.5.0: - dependencies: - '@types/fs-extra': 8.1.5 - colorette: 1.4.0 - fs-extra: 8.1.0 - globby: 10.0.1 - is-plain-object: 3.0.1 - - rollup-plugin-dts@6.1.1(rollup@4.39.0)(typescript@5.8.2): - dependencies: - magic-string: 0.30.17 - rollup: 4.39.0 - typescript: 5.8.2 - optionalDependencies: - '@babel/code-frame': 7.26.2 - rollup-plugin-preserve-directives@0.4.0(rollup@4.39.0): dependencies: '@rollup/pluginutils': 5.1.4(rollup@4.39.0) @@ -24531,8 +23381,6 @@ snapshots: dependencies: unicode-emoji-modifier-base: 1.0.0 - slash@3.0.0: {} - slash@5.1.0: {} smob@1.5.0: {} @@ -24682,12 +23530,6 @@ snapshots: dependencies: inline-style-parser: 0.2.4 - stylehacks@7.0.4(postcss@8.5.3): - dependencies: - browserslist: 4.24.4 - postcss: 8.5.3 - postcss-selector-parser: 6.1.2 - stylis@4.2.0: {} sucrase@3.35.0: @@ -24721,16 +23563,6 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svgo@3.3.2: - dependencies: - '@trysound/sax': 0.2.0 - commander: 7.2.0 - css-select: 5.1.0 - css-tree: 2.3.1 - css-what: 6.1.0 - csso: 5.0.5 - picocolors: 1.1.1 - swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1): dependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) @@ -24812,15 +23644,6 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 - temp-dir@3.0.0: {} - - tempy@3.1.0: - dependencies: - is-stream: 3.0.0 - temp-dir: 3.0.0 - type-fest: 2.19.0 - unique-string: 3.0.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)): dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -24880,8 +23703,6 @@ snapshots: tinybench@2.9.0: {} - tinycolor2@1.6.0: {} - tinyexec@0.3.2: {} tinyglobby@0.2.12: @@ -24889,11 +23710,6 @@ snapshots: fdir: 6.4.3(picomatch@4.0.2) picomatch: 4.0.2 - tinygradient@1.1.5: - dependencies: - '@types/tinycolor2': 1.4.6 - tinycolor2: 1.6.0 - tinypool@1.0.2: {} tinyrainbow@2.0.0: {} @@ -24906,10 +23722,6 @@ snapshots: dependencies: tldts-core: 6.1.76 - tmp@0.0.33: - dependencies: - os-tmpdir: 1.0.2 - tmp@0.2.3: {} to-regex-range@5.0.1: @@ -24981,8 +23793,6 @@ snapshots: type-fest@0.21.3: {} - type-fest@1.4.0: {} - type-fest@2.19.0: {} type-fest@4.33.0: {} @@ -25042,39 +23852,6 @@ snapshots: ufo@1.5.4: {} - unbuild@3.3.1(typescript@5.8.2)(vue-tsc@2.0.29(typescript@5.8.2)): - dependencies: - '@rollup/plugin-alias': 5.1.1(rollup@4.39.0) - '@rollup/plugin-commonjs': 28.0.2(rollup@4.39.0) - '@rollup/plugin-json': 6.1.0(rollup@4.39.0) - '@rollup/plugin-node-resolve': 16.0.0(rollup@4.39.0) - '@rollup/plugin-replace': 6.0.2(rollup@4.39.0) - '@rollup/pluginutils': 5.1.4(rollup@4.39.0) - citty: 0.1.6 - consola: 3.4.0 - defu: 6.1.4 - esbuild: 0.24.2 - hookable: 5.5.3 - jiti: 2.4.2 - magic-string: 0.30.17 - mkdist: 2.2.0(typescript@5.8.2)(vue-tsc@2.0.29(typescript@5.8.2)) - mlly: 1.7.4 - pathe: 2.0.3 - pkg-types: 1.3.1 - pretty-bytes: 6.1.1 - rollup: 4.39.0 - rollup-plugin-dts: 6.1.1(rollup@4.39.0)(typescript@5.8.2) - scule: 1.3.0 - tinyglobby: 0.2.12 - untyped: 1.5.2 - optionalDependencies: - typescript: 5.8.2 - transitivePeerDependencies: - - sass - - supports-color - - vue - - vue-tsc - unc-path-regex@0.1.2: {} uncrypto@0.1.3: {} @@ -25121,10 +23898,6 @@ snapshots: transitivePeerDependencies: - rollup - unique-string@3.0.0: - dependencies: - crypto-random-string: 4.0.0 - universalify@0.1.2: {} universalify@0.2.0: {} @@ -25252,8 +24025,6 @@ snapshots: validate-npm-package-name@5.0.1: {} - validate-npm-package-name@6.0.0: {} - vary@1.1.2: {} vinxi@0.5.1(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0): @@ -25546,7 +24317,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.13.4 - '@vitest/browser': 3.0.6(@types/node@22.13.4)(playwright@1.50.1)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))(vitest@3.0.6) + '@vitest/browser': 3.0.6(@types/node@22.13.4)(playwright@1.52.0)(typescript@5.8.2)(vite@6.1.4(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))(vitest@3.0.6) '@vitest/ui': 3.0.6(vitest@3.0.6) jsdom: 25.0.1 transitivePeerDependencies: @@ -25796,10 +24567,6 @@ snapshots: dependencies: isexe: 3.1.1 - which@5.0.0: - dependencies: - isexe: 3.1.1 - why-is-node-running@2.3.0: dependencies: siginfo: 2.0.0 @@ -25879,14 +24646,8 @@ snapshots: yocto-queue@0.1.0: {} - yocto-spinner@0.2.0: - dependencies: - yoctocolors: 2.1.1 - yoctocolors-cjs@2.1.2: {} - yoctocolors@2.1.1: {} - zip-stream@6.0.1: dependencies: archiver-utils: 5.0.2 diff --git a/scripts/publish.js b/scripts/publish.js index 1d55ca6ddcd..430c3a3c41b 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -84,18 +84,10 @@ await publish({ name: '@tanstack/server-functions-plugin', packageDir: 'packages/server-functions-plugin', }, - { - name: '@tanstack/create-router', - packageDir: 'packages/create-router', - }, { name: '@tanstack/eslint-plugin-router', packageDir: 'packages/eslint-plugin-router', }, - { - name: '@tanstack/create-start', - packageDir: 'packages/create-start', - }, { name: '@tanstack/solid-start', packageDir: 'packages/solid-start',