diff --git a/packages/README.md b/packages/README.md index 177623bc..67d1e54d 100644 --- a/packages/README.md +++ b/packages/README.md @@ -1,3 +1,5 @@ # Tuono packages -- `vite-fs-router`: Handles the bundling +- `tuono-vite`: Handles the bundling (with chunk splitting) +- `tuono-routes-generator`: Handles the creation of the `routeGen.tree.ts` file +- `tuono-router`: Expose all the Functions and Component related to the routing diff --git a/packages/router-generator/src/_index.ts b/packages/router-generator/src/_index.ts deleted file mode 100644 index b735b750..00000000 --- a/packages/router-generator/src/_index.ts +++ /dev/null @@ -1,532 +0,0 @@ -/** - * Overview: - * - * src/routes = Routes entry point - * src/routes/layout.tsx = Shared layout - * src/routes/index.tsx = xyz.com - * src/routes/about.tsx = xyz.com/about - * src/routes/about-loading.tsx = xyz.com/about - while loading data - * src/routes/about/index.tsx = xyz.com/about - * src/routes/posts/[slug].tsx = xyz.com/posts/my-lovely-post - * src/routes/posts/[...params].tsx = xyz.com/posts/my-lovely-post/commend-id-304 - * src/routes/404.tsx = Not found - * - * public/ = Public files - * - * All the routes are lazy loaded! - */ - -import * as fs from 'fs' -import * as fsp from 'fs/promises' -import { format } from 'prettier' -import path from 'path' - -const ROUTES_FOLDER = './src/routes/' -const ROOT_PATH_ID = '__root' -const GENERATED_ROUTE_TREE = './src/routeTree.gen.ts' - -let latestTask = 0 -const routeGroupPatternRegex = /\(.+\)/g - -interface RouteNode { - filePath: string - fullPath: string - routePath: string - path?: string - cleanedPath?: string - isLayout?: boolean - isLoader: boolean - children?: RouteNode[] - parent?: RouteNode - variableName?: string -} - -let isFirst = false -let skipMessage = false - -export function removeExt(d: string, keepExtension: boolean = false): string { - return keepExtension ? d : d.substring(0, d.lastIndexOf('.')) || d -} - -function replaceBackslash(s: string): string { - return s.replaceAll(/\\/gi, '/') -} - -export function cleanPath(pathToClean: string): string { - // remove double slashes - return pathToClean.replace(/\/{2,}/g, '/') -} - -function removeUnderscores(s?: string): string | undefined { - return s?.replaceAll(/(^_|_$)/gi, '').replaceAll(/(\/_|_\/)/gi, '/') -} - -function routePathToVariable(routePath: string): string { - return ( - removeUnderscores(routePath) - ?.replace(/\/\$\//g, '/splat/') - .replace(/\$$/g, 'splat') - .replace(/\$/g, '') - .split(/[/-]/g) - .map((d, i) => (i > 0 ? capitalize(d) : d)) - .join('') - .replace(/([^a-zA-Z0-9]|[.])/gm, '') - .replace(/^(\d)/g, 'R$1') ?? '' - ) -} - -function capitalize(s: string): string { - if (typeof s !== 'string') return '' - return s.charAt(0).toUpperCase() + s.slice(1) -} - -async function getRouteNodes(config = defaultConfig): Promise { - const routeNodes: RouteNode[] = [] - - async function recurse(dir: string): Promise { - const fullDir = path.resolve(config.folderName, dir) - const dirList = await fsp.readdir(fullDir, { withFileTypes: true }) - - await Promise.all( - dirList.map(async (dirent) => { - const fullPath = path.join(fullDir, dirent.name) - const relativePath = path.join(dir, dirent.name) - - if (dirent.isDirectory()) { - await recurse(relativePath) - } else if (fullPath.match(/\.(tsx|ts|jsx|js)$/)) { - const filePath = replaceBackslash(path.join(dir, dirent.name)) - const filePathNoExt = removeExt(filePath) - let routePath = - cleanPath(`/${filePathNoExt.split('.').join('/')}`) || '' - - const variableName = routePathToVariable(routePath) - - // Remove the index from the route path and - // if the route path is empty, use `/' - - const isLoader = routePath.includes('-loading') - - if (routePath === 'index') { - routePath = '/' - } - - routePath = routePath.replace(/\/index$/, '/') || '/' - - routeNodes.push({ - filePath, - fullPath, - routePath, - isLoader, - variableName, - }) - } - }), - ) - } - - await recurse('./') - - return routeNodes -} - -export function multiSortBy( - arr: T[], - accessors: ((item: T) => any)[] = [(d): any => d], -): T[] { - return arr - .map((d, i) => [d, i] as const) - .sort(([a, ai], [b, bi]) => { - for (const accessor of accessors) { - const ao = accessor(a) - const bo = accessor(b) - - if (typeof ao === 'undefined') { - if (typeof bo === 'undefined') { - continue - } - return 1 - } - - if (ao === bo) { - continue - } - - return ao > bo ? 1 : -1 - } - - return ai - bi - }) - .map(([d]) => d) -} - -/** - * @deprecated - */ -interface RouteSubNode { - component?: RouteNode - errorComponent?: RouteNode - pendingComponent?: RouteNode - loader?: RouteNode - lazy?: RouteNode -} - -export function hasParentRoute( - routes: RouteNode[], - node: RouteNode, - routePathToCheck: string | undefined, -): RouteNode | null { - if (!routePathToCheck || routePathToCheck === '/') { - return null - } - - const sortedNodes = multiSortBy(routes, [ - (d): number => d.routePath.length * -1, - (d): string | undefined => d.variableName, - ]).filter((d) => d.routePath !== `/${ROOT_PATH_ID}`) - - for (const route of sortedNodes) { - if (route.routePath === '/') continue - - if ( - routePathToCheck.startsWith(`${route.routePath}/`) && - route.routePath !== routePathToCheck - ) { - return route - } - } - - const segments = routePathToCheck.split('/') - segments.pop() // Remove the last segment - const parentRoutePath = segments.join('/') - - return hasParentRoute(routes, node, parentRoutePath) -} - -interface Config { - folderName: string - generatedRouteTree: string -} - -const defaultConfig: Config = { - folderName: ROUTES_FOLDER, - generatedRouteTree: GENERATED_ROUTE_TREE, -} - -export async function routeGenerator(config = defaultConfig): Promise { - if (!isFirst) { - console.log('Generating routes...') - isFirst = true - } else if (skipMessage) { - skipMessage = false - } else { - console.log('Regenerating routes') - } - - const checkLatest = (): boolean => { - if (latestTask !== taskId) { - skipMessage = true - return false - } - - return true - } - - const taskId = latestTask + 1 - latestTask = taskId - - const start = Date.now() - const beforeRouteNodes = await getRouteNodes(config) - - const preRouteNodes = multiSortBy(beforeRouteNodes, [ - (d): number => (d.routePath === '/' ? -1 : 1), - (d): number => d.routePath.split('/').length, - (d): number => (d.filePath.match(/[./]index[.]/) ? 1 : -1), - (d): number => - d.filePath.match( - /[./](component|errorComponent|pendingComponent|loader|lazy)[.]/, - ) - ? 1 - : -1, - (d): number => (d.filePath.match(/[./]route[.]/) ? -1 : 1), - (d): number => (d.routePath.endsWith('/') ? -1 : 1), - (d): string => d.routePath, - ]).filter((d) => ![`/${ROOT_PATH_ID}`].includes(d.routePath || '')) - - const routeTree: RouteNode[] = [] - const routePiecesByPath: Record = {} - - // Loop over the flat list of routeNodes and - // build up a tree based on the routeNodes' routePath - const routeNodes: RouteNode[] = [] - - const handleNode = async (node: RouteNode): Promise => { - const parentRoute = hasParentRoute(routeNodes, node, node.routePath) - - if (parentRoute) node.parent = parentRoute - - node.path = determineNodePath(node) - - const trimmedPath = trimPathLeft(node.path ?? '') - const split = trimmedPath.split('/') - const first = split[0] ?? trimmedPath - const lastRouteSegment = split[split.length - 1] ?? trimmedPath - - // TODO: check these two - node.isNonPath = lastRouteSegment.startsWith('_') - node.isNonLayout = first.endsWith('_') - - node.cleanedPath = removeGroups( - removeUnderscores(removeLayoutSegments(node.path)) ?? '', - ) - - const routeCode = fs.readFileSync(node.fullPath, 'utf-8') - - const escapedRoutePath = removeTrailingUnderscores( - node.routePath.replaceAll('$', '$$') ?? '', - ) - - let replaced = routeCode - - if (!routeCode) { - replaced = [ - `import { createFileRoute } from '@tanstack/react-router'`, - `export const Route = createFileRoute('${escapedRoutePath}')({ - component: () =>
Hello ${escapedRoutePath}!
-})`, - ].join('\n\n') - - if (replaced !== routeCode) { - console.log(`[emoticon] Updating ${node.fullPath}`) - await fsp.writeFile(node.fullPath, replaced) - } - } - - if (node.parent) { - node.parent.children = node.parent.children ?? [] - node.parent.children.push(node) - } - routeNodes.push(node) - } - - for (const node of preRouteNodes) { - await handleNode(node) - } - - function buildRouteConfig(nodes: RouteNode[], depth = 1): string { - const children = nodes.map((node) => { - if (node.isLayout) { - return - } - - if (node.isLayout && !node.children?.length) { - return - } - - const route = `${node.variableName}Route` - - if (node.children?.length) { - const childConfigs = buildRouteConfig(node.children, depth + 1) - return `${route}.addChildren([${spaces(depth * 4)}${childConfigs}])` - } - - return route - }) - - return children.filter(Boolean).join(`,`) - } - - const routeConfigChildrenText = buildRouteConfig(routeTree) - - const sortedRouteNodes = multiSortBy(routeNodes, [ - (d): number => (d.routePath.includes(`/${ROOT_PATH_ID}`) ? -1 : 1), - (d): number => d.routePath.split('/').length, - (d): number => (d.routePath.endsWith("index'") ? -1 : 1), - (d): any => d, - ]) - - const imports = Object.entries({ - createFileRoute: false, - lazyFn: sortedRouteNodes.some( - (node) => routePiecesByPath[node.routePath]?.loader, - ), - lazyRouteComponent: sortedRouteNodes.some( - (node) => - routePiecesByPath[node.routePath]?.component || - routePiecesByPath[node.routePath]?.errorComponent || - routePiecesByPath[node.routePath]?.pendingComponent, - ), - }) - .filter((d) => d[1]) - .map((d) => d[0]) - - const routeImports = [ - '// This file is auto-generated by Tuono', - imports.length - ? `import { ${imports.join(', ')} } from '@tanstack/react-router'\n` - : '', - '// Import Routes', - [ - `import { Route as rootRoute } from './${replaceBackslash( - path.relative( - path.dirname(config.generatedRouteTree), - path.resolve(config.folderName, ROOT_PATH_ID), - ), - )}'`, - ...sortedRouteNodes.map((node) => { - return `import { Route as ${ - node.variableName - }Import } from './${replaceBackslash( - removeExt( - path.relative( - path.dirname(config.generatedRouteTree), - path.resolve(config.folderName, node.filePath), - ), - false, - ), - )}'` - }), - ].join('\n'), - '// Create/Update Routes', - sortedRouteNodes - .map((node) => { - const loaderNode = routePiecesByPath[node.routePath]?.loader - const lazyComponentNode = routePiecesByPath[node.routePath]?.lazy - - return [ - `const ${node.variableName}Route = ${node.variableName}Import.update({ - ${[ - `path: '${node.cleanedPath}'`, - `getParentRoute: () => ${node.parent?.variableName ?? 'root'}Route`, - ] - .filter(Boolean) - .join(',')} - } as any)`, - loaderNode - ? `.updateLoader({ loader: lazyFn(() => import('./${replaceBackslash( - removeExt( - path.relative( - path.dirname(config.generatedRouteTree), - path.resolve(config.folderName, loaderNode.filePath), - ), - false, - ), - )}'), 'loader') })` - : '', - lazyComponentNode - ? `.lazy(() => import('./${replaceBackslash( - removeExt( - path.relative( - path.dirname(config.generatedRouteTree), - path.resolve(config.folderName, lazyComponentNode.filePath), - ), - false, - ), - )}').then((d) => d.Route))` - : '', - ].join('') - }) - .join('\n\n'), - ...[ - '// Populate the FileRoutesByPath interface', - `declare module '@tanstack/react-router' { - interface FileRoutesByPath { - ${routeNodes - .map((routeNode) => { - return `'${removeTrailingUnderscores(routeNode.routePath)}': { - preLoaderRoute: typeof ${routeNode.variableName}Import - parentRoute: typeof ${ - routeNode.parent?.variableName - ? `${routeNode.parent.variableName}Import` - : 'rootRoute' - } - }` - }) - .join('\n')} - } -}`, - ], - '// Create and export the route tree', - `export const routeTree = rootRoute.addChildren([${routeConfigChildrenText}])`, - ] - .filter(Boolean) - .join('\n\n') - - console.log(routeImports) - - const routeConfigFileContent = await format(routeImports, { - semi: false, - singleQuote: true, - parser: 'typescript', - }) - - const routeTreeContent = await fsp - .readFile(path.resolve(config.generatedRouteTree), 'utf-8') - .catch((err: any) => { - if (err.code === 'ENOENT') { - return undefined - } - throw err - }) - - if (!checkLatest()) return - - if (routeTreeContent !== routeConfigFileContent) { - await fsp.mkdir(path.dirname(path.resolve(config.generatedRouteTree)), { - recursive: true, - }) - if (!checkLatest()) return - await fsp.writeFile( - path.resolve(config.generatedRouteTree), - routeConfigFileContent, - ) - } - - console.log( - `[emoticon] Processed ${routeNodes.length === 1 ? 'route' : 'routes'} in ${ - Date.now() - start - }ms`, - ) -} - -function spaces(d: number): string { - return Array.from({ length: d }) - .map(() => ' ') - .join('') -} - -function removeTrailingUnderscores(s?: string): string | undefined { - return s?.replaceAll(/(_$)/gi, '').replaceAll(/(_\/)/gi, '/') -} -/** - * Removes all segments from a given path that start with an underscore ('_'). - * - * @param {string} routePath - The path from which to remove segments. Defaults to '/'. - * @returns {string} The path with all underscore-prefixed segments removed. - * @example - * removeLayoutSegments('/workspace/_auth/foo') // '/workspace/foo' - */ -function removeLayoutSegments(routePath: string = '/'): string { - const segments = routePath.split('/') - const newSegments = segments.filter((segment) => !segment.startsWith('_')) - return newSegments.join('/') -} - -function removeGroups(s: string): string { - return s.replaceAll(routeGroupPatternRegex, '').replaceAll('//', '/') -} -export function trimPathLeft(pathToTrim: string): string { - return pathToTrim === '/' ? pathToTrim : pathToTrim.replace(/^\/{1,}/, '') -} - -/** - * The `node.path` is used as the `id` in the route definition. - * This function checks if the given node has a parent and if so, it determines the correct path for the given node. - * @param node - The node to determine the path for. - * @returns The correct path for the given node. - */ -function determineNodePath(node: RouteNode): string { - return (node.path = node.parent - ? node.routePath.replace(node.parent.routePath, '') || '/' - : node.routePath) -} diff --git a/packages/router-generator/.prettierignore b/packages/tuono-routes-generator/.prettierignore similarity index 100% rename from packages/router-generator/.prettierignore rename to packages/tuono-routes-generator/.prettierignore diff --git a/packages/router-generator/README.md b/packages/tuono-routes-generator/README.md similarity index 100% rename from packages/router-generator/README.md rename to packages/tuono-routes-generator/README.md diff --git a/packages/router-generator/package.json b/packages/tuono-routes-generator/package.json similarity index 91% rename from packages/router-generator/package.json rename to packages/tuono-routes-generator/package.json index 384ded55..09fd2a39 100644 --- a/packages/router-generator/package.json +++ b/packages/tuono-routes-generator/package.json @@ -1,5 +1,5 @@ { - "name": "router-generator", + "name": "tuono-routes-generator", "version": "0.1.0", "description": "", "scripts": { @@ -28,9 +28,7 @@ "dist", "src" ], - "dependencies": { - "prettier": "^3.2.4" - }, + "dependencies": {}, "type": "module", "types": "dist/esm/index.d.ts", "main": "dist/cjs/index.cjs", diff --git a/packages/router-generator/src/generator.ts b/packages/tuono-routes-generator/src/generator.ts similarity index 95% rename from packages/router-generator/src/generator.ts rename to packages/tuono-routes-generator/src/generator.ts index a72965ee..4a3f7d74 100644 --- a/packages/router-generator/src/generator.ts +++ b/packages/tuono-routes-generator/src/generator.ts @@ -156,7 +156,6 @@ export async function routeGenerator(config = defaultConfig): Promise { (d): string => d.routePath, ]).filter((d) => ![`/${ROOT_PATH_ID}`].includes(d.routePath || '')) - const routeTree: RouteNode[] = [] const routePiecesByPath: Record = {} // Loop over the flat list of routeNodes and @@ -240,21 +239,6 @@ export async function routeGenerator(config = defaultConfig): Promise { (d): any => d, ]) - const imports = Object.entries({ - createFileRoute: false, - lazyFn: sortedRouteNodes.some( - (node) => routePiecesByPath[node.routePath]?.loader, - ), - lazyRouteComponent: sortedRouteNodes.some( - (node) => - routePiecesByPath[node.routePath]?.component || - routePiecesByPath[node.routePath]?.errorComponent || - routePiecesByPath[node.routePath]?.pendingComponent, - ), - }) - .filter((d) => d[1]) - .map((d) => d[0]) - const routeImports = [ '// This file is auto-generated by Tuono', [ diff --git a/packages/router-generator/src/index.ts b/packages/tuono-routes-generator/src/index.ts similarity index 100% rename from packages/router-generator/src/index.ts rename to packages/tuono-routes-generator/src/index.ts diff --git a/packages/router-generator/src/types.ts b/packages/tuono-routes-generator/src/types.ts similarity index 100% rename from packages/router-generator/src/types.ts rename to packages/tuono-routes-generator/src/types.ts diff --git a/packages/router-generator/src/utils.ts b/packages/tuono-routes-generator/src/utils.ts similarity index 100% rename from packages/router-generator/src/utils.ts rename to packages/tuono-routes-generator/src/utils.ts diff --git a/packages/router-generator/tests/generator.test.ts b/packages/tuono-routes-generator/tests/generator.test.ts similarity index 100% rename from packages/router-generator/tests/generator.test.ts rename to packages/tuono-routes-generator/tests/generator.test.ts diff --git a/packages/router-generator/tests/generator/multi-level/routeTree.expected.ts b/packages/tuono-routes-generator/tests/generator/multi-level/routeTree.expected.ts similarity index 100% rename from packages/router-generator/tests/generator/multi-level/routeTree.expected.ts rename to packages/tuono-routes-generator/tests/generator/multi-level/routeTree.expected.ts diff --git a/packages/router-generator/tests/generator/multi-level/routes/__root.tsx b/packages/tuono-routes-generator/tests/generator/multi-level/routes/__root.tsx similarity index 100% rename from packages/router-generator/tests/generator/multi-level/routes/__root.tsx rename to packages/tuono-routes-generator/tests/generator/multi-level/routes/__root.tsx diff --git a/packages/router-generator/tests/generator/multi-level/routes/about.tsx b/packages/tuono-routes-generator/tests/generator/multi-level/routes/about.tsx similarity index 69% rename from packages/router-generator/tests/generator/multi-level/routes/about.tsx rename to packages/tuono-routes-generator/tests/generator/multi-level/routes/about.tsx index c1bb0410..7c83ec8c 100644 --- a/packages/router-generator/tests/generator/multi-level/routes/about.tsx +++ b/packages/tuono-routes-generator/tests/generator/multi-level/routes/about.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/about')({ - component: () =>
Hello /about!
-}) \ No newline at end of file + component: () =>
Hello /about!
, +}) diff --git a/packages/router-generator/tests/generator/multi-level/routes/index.tsx b/packages/tuono-routes-generator/tests/generator/multi-level/routes/index.tsx similarity index 100% rename from packages/router-generator/tests/generator/multi-level/routes/index.tsx rename to packages/tuono-routes-generator/tests/generator/multi-level/routes/index.tsx diff --git a/packages/router-generator/tests/generator/multi-level/routes/posts/index.tsx b/packages/tuono-routes-generator/tests/generator/multi-level/routes/posts/index.tsx similarity index 100% rename from packages/router-generator/tests/generator/multi-level/routes/posts/index.tsx rename to packages/tuono-routes-generator/tests/generator/multi-level/routes/posts/index.tsx diff --git a/packages/router-generator/tests/generator/multi-level/routes/posts/post-slug.tsx b/packages/tuono-routes-generator/tests/generator/multi-level/routes/posts/post-slug.tsx similarity index 100% rename from packages/router-generator/tests/generator/multi-level/routes/posts/post-slug.tsx rename to packages/tuono-routes-generator/tests/generator/multi-level/routes/posts/post-slug.tsx diff --git a/packages/router-generator/tests/generator/single-level/routeTree.expected.ts b/packages/tuono-routes-generator/tests/generator/single-level/routeTree.expected.ts similarity index 100% rename from packages/router-generator/tests/generator/single-level/routeTree.expected.ts rename to packages/tuono-routes-generator/tests/generator/single-level/routeTree.expected.ts diff --git a/packages/router-generator/tests/generator/single-level/routes/__root.tsx b/packages/tuono-routes-generator/tests/generator/single-level/routes/__root.tsx similarity index 100% rename from packages/router-generator/tests/generator/single-level/routes/__root.tsx rename to packages/tuono-routes-generator/tests/generator/single-level/routes/__root.tsx diff --git a/packages/router-generator/tests/generator/single-level/routes/about.tsx b/packages/tuono-routes-generator/tests/generator/single-level/routes/about.tsx similarity index 100% rename from packages/router-generator/tests/generator/single-level/routes/about.tsx rename to packages/tuono-routes-generator/tests/generator/single-level/routes/about.tsx diff --git a/packages/router-generator/tests/generator/single-level/routes/index.tsx b/packages/tuono-routes-generator/tests/generator/single-level/routes/index.tsx similarity index 100% rename from packages/router-generator/tests/generator/single-level/routes/index.tsx rename to packages/tuono-routes-generator/tests/generator/single-level/routes/index.tsx diff --git a/packages/router-generator/tsconfig.json b/packages/tuono-routes-generator/tsconfig.json similarity index 100% rename from packages/router-generator/tsconfig.json rename to packages/tuono-routes-generator/tsconfig.json diff --git a/packages/router-generator/vite.config.ts b/packages/tuono-routes-generator/vite.config.ts similarity index 100% rename from packages/router-generator/vite.config.ts rename to packages/tuono-routes-generator/vite.config.ts diff --git a/packages/vite-fs-router/.prettierignore b/packages/tuono-vite/.prettierignore similarity index 100% rename from packages/vite-fs-router/.prettierignore rename to packages/tuono-vite/.prettierignore diff --git a/packages/vite-fs-router/README.md b/packages/tuono-vite/README.md similarity index 100% rename from packages/vite-fs-router/README.md rename to packages/tuono-vite/README.md diff --git a/packages/vite-fs-router/package.json b/packages/tuono-vite/package.json similarity index 97% rename from packages/vite-fs-router/package.json rename to packages/tuono-vite/package.json index 1a7124d5..15f22622 100644 --- a/packages/vite-fs-router/package.json +++ b/packages/tuono-vite/package.json @@ -1,5 +1,5 @@ { - "name": "vite-plugin-fs-router", + "name": "tuono-vite", "version": "0.1.0", "description": "", "main": "src/index.ts", diff --git a/packages/vite-fs-router/src/compiler.ts b/packages/tuono-vite/src/compiler.ts similarity index 100% rename from packages/vite-fs-router/src/compiler.ts rename to packages/tuono-vite/src/compiler.ts diff --git a/packages/vite-fs-router/src/constants.ts b/packages/tuono-vite/src/constants.ts similarity index 100% rename from packages/vite-fs-router/src/constants.ts rename to packages/tuono-vite/src/constants.ts diff --git a/packages/vite-fs-router/src/eliminateUnreferencedIdentifiers.ts b/packages/tuono-vite/src/eliminateUnreferencedIdentifiers.ts similarity index 100% rename from packages/vite-fs-router/src/eliminateUnreferencedIdentifiers.ts rename to packages/tuono-vite/src/eliminateUnreferencedIdentifiers.ts diff --git a/packages/vite-fs-router/src/index.ts b/packages/tuono-vite/src/index.ts similarity index 100% rename from packages/vite-fs-router/src/index.ts rename to packages/tuono-vite/src/index.ts diff --git a/packages/vite-fs-router/tests/index.test.ts b/packages/tuono-vite/tests/index.test.ts similarity index 100% rename from packages/vite-fs-router/tests/index.test.ts rename to packages/tuono-vite/tests/index.test.ts diff --git a/packages/vite-fs-router/tests/shared/imported.tsx b/packages/tuono-vite/tests/shared/imported.tsx similarity index 100% rename from packages/vite-fs-router/tests/shared/imported.tsx rename to packages/tuono-vite/tests/shared/imported.tsx diff --git a/packages/vite-fs-router/tests/snapshots/default-exported?split.tsx b/packages/tuono-vite/tests/snapshots/default-exported?split.tsx similarity index 100% rename from packages/vite-fs-router/tests/snapshots/default-exported?split.tsx rename to packages/tuono-vite/tests/snapshots/default-exported?split.tsx diff --git a/packages/vite-fs-router/tests/snapshots/function-export?split.tsx b/packages/tuono-vite/tests/snapshots/function-export?split.tsx similarity index 100% rename from packages/vite-fs-router/tests/snapshots/function-export?split.tsx rename to packages/tuono-vite/tests/snapshots/function-export?split.tsx diff --git a/packages/vite-fs-router/tests/snapshots/imported?split.tsx b/packages/tuono-vite/tests/snapshots/imported?split.tsx similarity index 100% rename from packages/vite-fs-router/tests/snapshots/imported?split.tsx rename to packages/tuono-vite/tests/snapshots/imported?split.tsx diff --git a/packages/vite-fs-router/tests/test-files/default-exported.tsx b/packages/tuono-vite/tests/test-files/default-exported.tsx similarity index 100% rename from packages/vite-fs-router/tests/test-files/default-exported.tsx rename to packages/tuono-vite/tests/test-files/default-exported.tsx diff --git a/packages/vite-fs-router/tests/test-files/function-export.tsx b/packages/tuono-vite/tests/test-files/function-export.tsx similarity index 100% rename from packages/vite-fs-router/tests/test-files/function-export.tsx rename to packages/tuono-vite/tests/test-files/function-export.tsx diff --git a/packages/vite-fs-router/tests/test-files/imported.tsx b/packages/tuono-vite/tests/test-files/imported.tsx similarity index 100% rename from packages/vite-fs-router/tests/test-files/imported.tsx rename to packages/tuono-vite/tests/test-files/imported.tsx diff --git a/packages/vite-fs-router/tsconfig.json b/packages/tuono-vite/tsconfig.json similarity index 100% rename from packages/vite-fs-router/tsconfig.json rename to packages/tuono-vite/tsconfig.json diff --git a/packages/vite-fs-router/vite.config.ts b/packages/tuono-vite/vite.config.ts similarity index 100% rename from packages/vite-fs-router/vite.config.ts rename to packages/tuono-vite/vite.config.ts