From 090485bff2823627b94a0ee961ffb56db32caba7 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Fri, 31 Jan 2025 00:58:20 +0100 Subject: [PATCH] refactor: router-utils for common utils (#3287) --- package.json | 3 +- .../src/modules/core/template/app/router.tsx | 1 + .../core/template/app/routes/__root.tsx | 6 +- .../directive-functions-plugin/package.json | 7 +- .../src/compilers.ts | 38 +---- .../directive-functions-plugin/src/index.ts | 2 +- packages/router-plugin/package.json | 9 +- .../src/core/code-splitter/ast.ts | 18 --- .../src/core/code-splitter/compilers.ts | 29 ++-- .../src/core/router-code-splitter-plugin.ts | 2 +- packages/router-plugin/src/logger.ts | 59 ------- packages/router-utils/eslint.config.js | 5 + packages/router-utils/package.json | 76 +++++++++ packages/router-utils/src/ast.ts | 34 ++++ packages/router-utils/src/index.ts | 4 + .../src/logger.ts | 18 +-- packages/router-utils/tsconfig.json | 5 + packages/router-utils/vite.config.ts | 20 +++ packages/server-functions-plugin/package.json | 6 - packages/start-plugin/package.json | 7 +- packages/start-plugin/src/ast.ts | 20 --- packages/start-plugin/src/compilers.ts | 32 ++-- packages/start-plugin/src/index.ts | 2 +- packages/start-plugin/src/logger.ts | 59 ------- pnpm-lock.yaml | 151 +++++++----------- scripts/publish.js | 4 + 26 files changed, 260 insertions(+), 357 deletions(-) delete mode 100644 packages/router-plugin/src/core/code-splitter/ast.ts delete mode 100644 packages/router-plugin/src/logger.ts create mode 100644 packages/router-utils/eslint.config.js create mode 100644 packages/router-utils/package.json create mode 100644 packages/router-utils/src/ast.ts create mode 100644 packages/router-utils/src/index.ts rename packages/{directive-functions-plugin => router-utils}/src/logger.ts (75%) create mode 100644 packages/router-utils/tsconfig.json create mode 100644 packages/router-utils/vite.config.ts delete mode 100644 packages/start-plugin/src/ast.ts delete mode 100644 packages/start-plugin/src/logger.ts diff --git a/package.json b/package.json index 8b7cc24427..cc8ad15517 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,8 @@ "@tanstack/start-plugin": "workspace:*", "@tanstack/eslint-plugin-router": "workspace:*", "@tanstack/server-functions-plugin": "workspace:*", - "@tanstack/directive-functions-plugin": "workspace:*" + "@tanstack/directive-functions-plugin": "workspace:*", + "@tanstack/router-utils": "workspace:*" } } } diff --git a/packages/create-start/src/modules/core/template/app/router.tsx b/packages/create-start/src/modules/core/template/app/router.tsx index 227f00e224..79fe23eab9 100644 --- a/packages/create-start/src/modules/core/template/app/router.tsx +++ b/packages/create-start/src/modules/core/template/app/router.tsx @@ -6,6 +6,7 @@ import { routeTree } from './routeTree.gen' export function createRouter() { const router = createTanStackRouter({ routeTree, + scrollRestoration: true, }) return router 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 index df8985a4b7..4483c0873c 100644 --- a/packages/create-start/src/modules/core/template/app/routes/__root.tsx +++ b/packages/create-start/src/modules/core/template/app/routes/__root.tsx @@ -1,10 +1,6 @@ // @ts-nocheck -import { - Outlet, - ScrollRestoration, - createRootRoute, -} from '@tanstack/react-router' +import { Outlet, createRootRoute } from '@tanstack/react-router' import { Meta, Scripts } from '@tanstack/start' import type { ReactNode } from 'react' diff --git a/packages/directive-functions-plugin/package.json b/packages/directive-functions-plugin/package.json index b16c2b8656..19067196c7 100644 --- a/packages/directive-functions-plugin/package.json +++ b/packages/directive-functions-plugin/package.json @@ -67,23 +67,18 @@ "dependencies": { "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.7", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.25.9", "@babel/traverse": "^7.26.7", "@babel/types": "^7.26.7", + "@tanstack/router-utils": "workspace:^", "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", - "@types/babel__generator": "^7.6.8", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", - "@types/diff": "^6.0.0", "babel-dead-code-elimination": "^1.0.8", - "chalk": "^5.4.1", "dedent": "^1.5.3", - "diff": "^7.0.0", "tiny-invariant": "^1.3.3" } } diff --git a/packages/directive-functions-plugin/src/compilers.ts b/packages/directive-functions-plugin/src/compilers.ts index 784d36232d..168d691bbd 100644 --- a/packages/directive-functions-plugin/src/compilers.ts +++ b/packages/directive-functions-plugin/src/compilers.ts @@ -1,16 +1,9 @@ import * as babel from '@babel/core' -import _generate from '@babel/generator' -import { parse } from '@babel/parser' import { isIdentifier, isVariableDeclarator } from '@babel/types' import { codeFrameColumns } from '@babel/code-frame' import { deadCodeElimination } from 'babel-dead-code-elimination' -import type { ParseResult } from '@babel/parser' - -let generate = _generate - -if ('default' in generate) { - generate = generate.default as typeof generate -} +import { generateFromAst, parseAst } from '@tanstack/router-utils' +import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils' export interface DirectiveFn { nodePath: SupportedFunctionPath @@ -46,29 +39,14 @@ export type CompileDirectivesOpts = ParseAstOptions & { // devSplitImporter: string } -export type ParseAstOptions = { - code: string - filename: string - root: string -} - -export function parseAst(opts: ParseAstOptions): ParseResult { - return parse(opts.code, { - plugins: ['jsx', 'typescript'], - sourceType: 'module', - ...{ - root: opts.root, - filename: opts.filename, - sourceMaps: true, - }, - }) -} - function buildDirectiveSplitParam(opts: CompileDirectivesOpts) { return `tsr-directive-${opts.directive.replace(/[^a-zA-Z0-9]/g, '-')}` } -export function compileDirectives(opts: CompileDirectivesOpts) { +export function compileDirectives(opts: CompileDirectivesOpts): { + compiledResult: GeneratorResult + directiveFnsById: Record +} { const directiveSplitParam = buildDirectiveSplitParam(opts) const isDirectiveSplitParam = opts.filename.includes(directiveSplitParam) @@ -123,7 +101,7 @@ export function compileDirectives(opts: CompileDirectivesOpts) { deadCodeElimination(ast) - const compiledResult = generate(ast, { + const compiledResult = generateFromAst(ast, { sourceMaps: true, sourceFileName: opts.filename, }) @@ -248,7 +226,7 @@ export function findDirectives( replacer?: ReplacerFn directiveSplitParam: string }, -) { +): Record { const directiveFnsById: Record = {} const functionNameSet: Set = new Set() diff --git a/packages/directive-functions-plugin/src/index.ts b/packages/directive-functions-plugin/src/index.ts index 583ac9b5d4..25ed1df746 100644 --- a/packages/directive-functions-plugin/src/index.ts +++ b/packages/directive-functions-plugin/src/index.ts @@ -1,7 +1,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url' +import { logDiff } from '@tanstack/router-utils' import { compileDirectives } from './compilers' -import { logDiff } from './logger' import type { CompileDirectivesOpts, DirectiveFn } from './compilers' import type { Plugin } from 'vite' diff --git a/packages/router-plugin/package.json b/packages/router-plugin/package.json index 6f61591db6..0e5e3ea9da 100644 --- a/packages/router-plugin/package.json +++ b/packages/router-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/router-plugin", - "version": "1.98.4", + "version": "1.98.3", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", @@ -104,24 +104,19 @@ }, "dependencies": { "@babel/core": "^7.26.7", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.25.9", "@babel/traverse": "^7.26.7", "@babel/types": "^7.26.7", "@tanstack/router-generator": "workspace:^", + "@tanstack/router-utils": "workspace:^", "@tanstack/virtual-file-routes": "workspace:^", "@types/babel__core": "^7.20.5", - "@types/babel__generator": "^7.6.8", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", - "@types/diff": "^6.0.0", "babel-dead-code-elimination": "^1.0.8", - "chalk": "^5.4.1", "chokidar": "^3.6.0", - "diff": "^7.0.0", "unplugin": "^2.1.2", "zod": "^3.24.1" }, diff --git a/packages/router-plugin/src/core/code-splitter/ast.ts b/packages/router-plugin/src/core/code-splitter/ast.ts deleted file mode 100644 index 7cb14cb239..0000000000 --- a/packages/router-plugin/src/core/code-splitter/ast.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { parse } from '@babel/parser' - -export type ParseAstOptions = { - code: string - filename: string - root: string -} - -export function parseAst(opts: ParseAstOptions) { - return parse(opts.code, { - plugins: ['jsx', 'typescript'], - sourceType: 'module', - ...{ - root: opts.root, - filename: opts.filename, - }, - }) -} diff --git a/packages/router-plugin/src/core/code-splitter/compilers.ts b/packages/router-plugin/src/core/code-splitter/compilers.ts index 34f34ca8f9..22eaf82d3a 100644 --- a/packages/router-plugin/src/core/code-splitter/compilers.ts +++ b/packages/router-plugin/src/core/code-splitter/compilers.ts @@ -1,24 +1,13 @@ import * as t from '@babel/types' import babel from '@babel/core' -import _generate from '@babel/generator' import * as template from '@babel/template' import { deadCodeElimination } from 'babel-dead-code-elimination' - +import { generateFromAst, parseAst } from '@tanstack/router-utils' import { splitPrefix } from '../constants' -import { parseAst } from './ast' -import type { ParseAstOptions } from './ast' +import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils' const debug = process.env.TSR_VITE_DEBUG -// Babel is a CJS package and uses `default` as named binding (`exports.default =`). -// https://github.com/babel/babel/issues/15269. -let generate = (_generate as any)['default'] as typeof _generate - -// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -if (!generate) { - generate = _generate -} - type SplitModulesById = Record< string, { id: string; node: t.FunctionExpression } @@ -79,7 +68,9 @@ const SPLIT_NOES_CONFIG = new Map([ ]) const SPLIT_ROUTE_IDENT_NODES = [...SPLIT_NOES_CONFIG.keys()] as const -export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) { +export function compileCodeSplitReferenceRoute( + opts: ParseAstOptions, +): GeneratorResult { const ast = parseAst(opts) babel.traverse(ast, { @@ -321,13 +312,15 @@ export function compileCodeSplitReferenceRoute(opts: ParseAstOptions) { deadCodeElimination(ast) - return generate(ast, { + return generateFromAst(ast, { sourceMaps: true, sourceFileName: opts.filename, }) } -export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) { +export function compileCodeSplitVirtualRoute( + opts: ParseAstOptions, +): GeneratorResult { const ast = parseAst(opts) const knownExportedIdents = new Set() @@ -483,7 +476,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) { ]), ) } else if (t.isCallExpression(splitNode)) { - const outputSplitNodeCode = generate(splitNode).code + const outputSplitNodeCode = generateFromAst(splitNode).code const splitNodeAst = babel.parse(outputSplitNodeCode) if (!splitNodeAst) { @@ -593,7 +586,7 @@ export function compileCodeSplitVirtualRoute(opts: ParseAstOptions) { } } - return generate(ast, { + return generateFromAst(ast, { sourceMaps: true, sourceFileName: opts.filename, }) diff --git a/packages/router-plugin/src/core/router-code-splitter-plugin.ts b/packages/router-plugin/src/core/router-code-splitter-plugin.ts index 1f4f9750bc..f07c4b36ee 100644 --- a/packages/router-plugin/src/core/router-code-splitter-plugin.ts +++ b/packages/router-plugin/src/core/router-code-splitter-plugin.ts @@ -1,7 +1,7 @@ import { isAbsolute, join, normalize } from 'node:path' import { fileURLToPath, pathToFileURL } from 'node:url' -import { logDiff } from '../logger' +import { logDiff } from '@tanstack/router-utils' import { getConfig } from './config' import { compileCodeSplitReferenceRoute, diff --git a/packages/router-plugin/src/logger.ts b/packages/router-plugin/src/logger.ts deleted file mode 100644 index 04574052b8..0000000000 --- a/packages/router-plugin/src/logger.ts +++ /dev/null @@ -1,59 +0,0 @@ -import chalk from 'chalk' -import { diffWords } from 'diff' - -export function logDiff(oldStr: string, newStr: string) { - const differences = diffWords(oldStr, newStr) - - let output = '' - let unchangedLines = '' - - function processUnchangedLines(lines: string): string { - const lineArray = lines.split('\n') - if (lineArray.length > 4) { - return [ - chalk.dim(lineArray[0]), - chalk.dim(lineArray[1]), - '', - chalk.dim.bold(`... (${lineArray.length - 4} lines) ...`), - '', - chalk.dim(lineArray[lineArray.length - 2]), - chalk.dim(lineArray[lineArray.length - 1]), - ].join('\n') - } - return chalk.dim(lines) - } - - differences.forEach((part, index) => { - const nextPart = differences[index + 1] - - if (part.added) { - if (unchangedLines) { - output += processUnchangedLines(unchangedLines) - unchangedLines = '' - } - output += chalk.green.bold(part.value) - if (nextPart?.removed) output += ' ' - } else if (part.removed) { - if (unchangedLines) { - output += processUnchangedLines(unchangedLines) - unchangedLines = '' - } - output += chalk.red.bold(part.value) - if (nextPart?.added) output += ' ' - } else { - unchangedLines += part.value - } - }) - - // Process any remaining unchanged lines at the end - if (unchangedLines) { - output += processUnchangedLines(unchangedLines) - } - - if (output) { - console.log('\nDiff:') - console.log(output + '\n') - } else { - console.log('No changes') - } -} diff --git a/packages/router-utils/eslint.config.js b/packages/router-utils/eslint.config.js new file mode 100644 index 0000000000..8ce6ad05fc --- /dev/null +++ b/packages/router-utils/eslint.config.js @@ -0,0 +1,5 @@ +// @ts-check + +import rootConfig from '../../eslint.config.js' + +export default [...rootConfig] diff --git a/packages/router-utils/package.json b/packages/router-utils/package.json new file mode 100644 index 0000000000..501a803441 --- /dev/null +++ b/packages/router-utils/package.json @@ -0,0 +1,76 @@ +{ + "name": "@tanstack/router-utils", + "version": "1.98.4", + "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/router-utils" + }, + "homepage": "https://tanstack.com/router", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "keywords": [ + "react", + "location", + "router", + "routing", + "async", + "async router", + "typescript" + ], + "scripts": { + "clean": "rimraf ./dist && rimraf ./coverage", + "test:eslint": "eslint ./src", + "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", + "test:types:ts52": "node ../../node_modules/typescript52/lib/tsc.js", + "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js", + "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", + "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", + "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", + "test:types:ts57": "tsc", + "test:unit": "exit 0; vitest --typecheck", + "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", + "build": "vite build" + }, + "type": "module", + "types": "dist/esm/index.d.ts", + "main": "dist/cjs/index.cjs", + "module": "dist/esm/index.js", + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.cts", + "default": "./dist/cjs/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "sideEffects": false, + "files": [ + "dist", + "src" + ], + "engines": { + "node": ">=12" + }, + "dependencies": { + "@babel/parser": "^7.26.7", + "@babel/generator": "^7.26.5", + "ansis": "^3.5.2", + "diff": "^7.0.0" + }, + "devDependencies": { + "@babel/types": "^7.26.7", + "@types/babel__generator": "^7.6.8", + "@types/diff": "^6.0.0" + } +} diff --git a/packages/router-utils/src/ast.ts b/packages/router-utils/src/ast.ts new file mode 100644 index 0000000000..795eff0f72 --- /dev/null +++ b/packages/router-utils/src/ast.ts @@ -0,0 +1,34 @@ +import { parse } from '@babel/parser' +import _generate from '@babel/generator' +import type { ParseResult } from '@babel/parser' +import type * as _babel_types from '@babel/types' + +export type ParseAstOptions = { + code: string + filename: string + root: string + env?: 'server' | 'client' | 'ssr' +} + +export function parseAst( + opts: ParseAstOptions, +): ParseResult<_babel_types.File> { + return parse(opts.code, { + plugins: ['jsx', 'typescript'], + sourceType: 'module', + ...{ + root: opts.root, + filename: opts.filename, + env: opts.env, + }, + }) +} + +let generate = _generate + +if ('default' in generate) { + generate = generate.default as typeof generate +} + +export { generate as generateFromAst } +export type { GeneratorResult } from '@babel/generator' diff --git a/packages/router-utils/src/index.ts b/packages/router-utils/src/index.ts new file mode 100644 index 0000000000..152cc3f550 --- /dev/null +++ b/packages/router-utils/src/index.ts @@ -0,0 +1,4 @@ +export { parseAst, generateFromAst } from './ast' +export type { ParseAstOptions, GeneratorResult } from './ast' + +export { logDiff } from './logger' diff --git a/packages/directive-functions-plugin/src/logger.ts b/packages/router-utils/src/logger.ts similarity index 75% rename from packages/directive-functions-plugin/src/logger.ts rename to packages/router-utils/src/logger.ts index d1273f9439..05439da8f0 100644 --- a/packages/directive-functions-plugin/src/logger.ts +++ b/packages/router-utils/src/logger.ts @@ -1,4 +1,4 @@ -import chalk from 'chalk' +import ansis from 'ansis' import { diffWords } from 'diff' export function logDiff(oldStr: string, newStr: string) { @@ -11,16 +11,16 @@ export function logDiff(oldStr: string, newStr: string) { const lineArray = lines.split('\n') if (lineArray.length > 4) { return [ - chalk.dim(lineArray[0]), - chalk.dim(lineArray[1]), + ansis.dim(lineArray[0]), + ansis.dim(lineArray[1]), '', - chalk.dim.bold(`... (${lineArray.length - 4} lines) ...`), + ansis.dim.bold(`... (${lineArray.length - 4} lines) ...`), '', - chalk.dim(lineArray[lineArray.length - 2]), - chalk.dim(lineArray[lineArray.length - 1]), + ansis.dim(lineArray[lineArray.length - 2]), + ansis.dim(lineArray[lineArray.length - 1]), ].join('\n') } - return chalk.dim(lines) + return ansis.dim(lines) } differences.forEach((part, index) => { @@ -31,14 +31,14 @@ export function logDiff(oldStr: string, newStr: string) { output += processUnchangedLines(unchangedLines) unchangedLines = '' } - output += chalk.green.bold(part.value) + output += ansis.green.bold(part.value) if (nextPart?.removed) output += ' ' } else if (part.removed) { if (unchangedLines) { output += processUnchangedLines(unchangedLines) unchangedLines = '' } - output += chalk.red.bold(part.value) + output += ansis.red.bold(part.value) if (nextPart?.added) output += ' ' } else { unchangedLines += part.value diff --git a/packages/router-utils/tsconfig.json b/packages/router-utils/tsconfig.json new file mode 100644 index 0000000000..604fde5556 --- /dev/null +++ b/packages/router-utils/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src", "vite.config.ts", "tests"], + "exclude": ["tests/generator/**/**"] +} diff --git a/packages/router-utils/vite.config.ts b/packages/router-utils/vite.config.ts new file mode 100644 index 0000000000..5389f0f739 --- /dev/null +++ b/packages/router-utils/vite.config.ts @@ -0,0 +1,20 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/config/vite' +import packageJson from './package.json' + +const config = defineConfig({ + test: { + name: packageJson.name, + dir: './tests', + watch: false, + typecheck: { enabled: true }, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ + entry: './src/index.ts', + srcDir: './src', + }), +) diff --git a/packages/server-functions-plugin/package.json b/packages/server-functions-plugin/package.json index acb87d27c4..9b0e8c97b7 100644 --- a/packages/server-functions-plugin/package.json +++ b/packages/server-functions-plugin/package.json @@ -68,8 +68,6 @@ "@tanstack/directive-functions-plugin": "workspace:*", "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.7", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.25.9", @@ -77,14 +75,10 @@ "@babel/types": "^7.26.7", "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", - "@types/babel__generator": "^7.6.8", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", - "@types/diff": "^6.0.0", "babel-dead-code-elimination": "^1.0.8", - "chalk": "^5.4.1", "dedent": "^1.5.3", - "diff": "^7.0.0", "tiny-invariant": "^1.3.3" } } diff --git a/packages/start-plugin/package.json b/packages/start-plugin/package.json index 63d7c75ef5..b1e36cac85 100644 --- a/packages/start-plugin/package.json +++ b/packages/start-plugin/package.json @@ -66,22 +66,17 @@ "dependencies": { "@babel/code-frame": "7.26.2", "@babel/core": "^7.26.7", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9", "@babel/template": "^7.25.9", "@babel/traverse": "^7.26.7", "@babel/types": "^7.26.7", + "@tanstack/router-utils": "workspace:^", "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", - "@types/babel__generator": "^7.6.8", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6", - "@types/diff": "^6.0.0", "babel-dead-code-elimination": "^1.0.8", - "chalk": "^5.4.1", - "diff": "^7.0.0", "tiny-invariant": "^1.3.3" } } diff --git a/packages/start-plugin/src/ast.ts b/packages/start-plugin/src/ast.ts deleted file mode 100644 index 99333fa6c4..0000000000 --- a/packages/start-plugin/src/ast.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { parse } from '@babel/parser' - -export type ParseAstOptions = { - code: string - filename: string - root: string - env: 'server' | 'client' | 'ssr' -} - -export function parseAst(opts: ParseAstOptions) { - return parse(opts.code, { - plugins: ['jsx', 'typescript'], - sourceType: 'module', - ...{ - root: opts.root, - filename: opts.filename, - env: opts.env, - }, - }) -} diff --git a/packages/start-plugin/src/compilers.ts b/packages/start-plugin/src/compilers.ts index ca2f60db21..edc214241b 100644 --- a/packages/start-plugin/src/compilers.ts +++ b/packages/start-plugin/src/compilers.ts @@ -1,25 +1,16 @@ import * as babel from '@babel/core' import * as t from '@babel/types' -import _generate from '@babel/generator' import { codeFrameColumns } from '@babel/code-frame' import { deadCodeElimination } from 'babel-dead-code-elimination' +import { generateFromAst, parseAst } from '@tanstack/router-utils' +import type { GeneratorResult, ParseAstOptions } from '@tanstack/router-utils' -import { parseAst } from './ast' -import type { ParseAstOptions } from './ast' - -// Babel is a CJS package and uses `default` as named binding (`exports.default =`). -// https://github.com/babel/babel/issues/15269. -let generate = (_generate as any)['default'] as typeof _generate - -// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -if (!generate) { - generate = _generate -} - -export function compileEliminateDeadCode(opts: ParseAstOptions) { +export function compileEliminateDeadCode( + opts: ParseAstOptions, +): GeneratorResult { const ast = parseAst(opts) deadCodeElimination(ast) - return generate(ast, { + return generateFromAst(ast, { sourceMaps: true, sourceFileName: opts.filename, filename: opts.filename, @@ -34,18 +25,21 @@ const handleServerOnlyCallExpression = const handleClientOnlyCallExpression = buildEnvOnlyCallExpressionHandler('client') +type CompileOptions = ParseAstOptions & { + env: 'server' | 'client' | 'ssr' +} type IdentifierConfig = { name: string type: 'ImportSpecifier' | 'ImportNamespaceSpecifier' namespaceId: string handleCallExpression: ( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) => void paths: Array } -export function compileStartOutput(opts: ParseAstOptions) { +export function compileStartOutput(opts: CompileOptions): GeneratorResult { const ast = parseAst(opts) babel.traverse(ast, { @@ -185,7 +179,7 @@ export function compileStartOutput(opts: ParseAstOptions) { }, }) - return generate(ast, { + return generateFromAst(ast, { sourceMaps: true, sourceFileName: opts.filename, filename: opts.filename, @@ -479,7 +473,7 @@ function buildEnvOnlyCallExpressionHandler(env: 'client' | 'server') { function handleCreateIsomorphicFnCallExpression( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { const rootCallExpression = getRootCallExpression(path) diff --git a/packages/start-plugin/src/index.ts b/packages/start-plugin/src/index.ts index 26c62bff78..ceec1f4b4a 100644 --- a/packages/start-plugin/src/index.ts +++ b/packages/start-plugin/src/index.ts @@ -1,8 +1,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url' +import { logDiff } from '@tanstack/router-utils' import { compileStartOutput } from './compilers' -import { logDiff } from './logger' import type { Plugin } from 'vite' const debug = diff --git a/packages/start-plugin/src/logger.ts b/packages/start-plugin/src/logger.ts deleted file mode 100644 index d1273f9439..0000000000 --- a/packages/start-plugin/src/logger.ts +++ /dev/null @@ -1,59 +0,0 @@ -import chalk from 'chalk' -import { diffWords } from 'diff' - -export function logDiff(oldStr: string, newStr: string) { - const differences = diffWords(oldStr, newStr) - - let output = '' - let unchangedLines = '' - - function processUnchangedLines(lines: string): string { - const lineArray = lines.split('\n') - if (lineArray.length > 4) { - return [ - chalk.dim(lineArray[0]), - chalk.dim(lineArray[1]), - '', - chalk.dim.bold(`... (${lineArray.length - 4} lines) ...`), - '', - chalk.dim(lineArray[lineArray.length - 2]), - chalk.dim(lineArray[lineArray.length - 1]), - ].join('\n') - } - return chalk.dim(lines) - } - - differences.forEach((part, index) => { - const nextPart = differences[index + 1] - - if (part.added) { - if (unchangedLines) { - output += processUnchangedLines(unchangedLines) - unchangedLines = '' - } - output += chalk.green.bold(part.value) - if (nextPart?.removed) output += ' ' - } else if (part.removed) { - if (unchangedLines) { - output += processUnchangedLines(unchangedLines) - unchangedLines = '' - } - output += chalk.red.bold(part.value) - if (nextPart?.added) output += ' ' - } else { - unchangedLines += part.value - } - }) - - // Process any remaining unchanged lines at the end - if (unchangedLines) { - output += processUnchangedLines(unchangedLines) - } - - if (output) { - console.log('\nDiff:') - console.log(output + '\n\n') - } else { - console.log('No changes') - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70a7beb79c..cf05331a4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,6 +42,7 @@ overrides: '@tanstack/eslint-plugin-router': workspace:* '@tanstack/server-functions-plugin': workspace:* '@tanstack/directive-functions-plugin': workspace:* + '@tanstack/router-utils': workspace:* importers: @@ -2379,10 +2380,10 @@ importers: version: 19.0.3(@types/react@19.0.8) html-webpack-plugin: specifier: ^5.6.3 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.9(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.9(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) typescript: specifier: ^5.7.2 version: 5.7.3 @@ -3847,7 +3848,7 @@ importers: 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) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) picocolors: specifier: ^1.1.1 version: 1.1.1 @@ -3859,7 +3860,7 @@ importers: version: 19.0.0(react@19.0.0) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.9(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.9(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) tinyglobby: specifier: ^0.2.10 version: 0.2.10 @@ -3991,12 +3992,6 @@ importers: '@babel/core': specifier: ^7.26.7 version: 7.26.7 - '@babel/generator': - specifier: ^7.26.5 - version: 7.26.5 - '@babel/parser': - specifier: ^7.26.7 - version: 7.26.7 '@babel/plugin-syntax-jsx': specifier: ^7.25.9 version: 7.25.9(@babel/core@7.26.7) @@ -4012,36 +4007,27 @@ importers: '@babel/types': specifier: ^7.26.7 version: 7.26.7 + '@tanstack/router-utils': + specifier: workspace:* + version: link:../router-utils '@types/babel__code-frame': specifier: ^7.0.6 version: 7.0.6 '@types/babel__core': specifier: ^7.20.5 version: 7.20.5 - '@types/babel__generator': - specifier: ^7.6.8 - version: 7.6.8 '@types/babel__template': specifier: ^7.4.4 version: 7.4.4 '@types/babel__traverse': specifier: ^7.20.6 version: 7.20.6 - '@types/diff': - specifier: ^6.0.0 - version: 6.0.0 babel-dead-code-elimination: specifier: ^1.0.8 version: 1.0.8 - chalk: - specifier: ^5.4.1 - version: 5.4.1 dedent: specifier: ^1.5.3 version: 1.5.3 - diff: - specifier: ^7.0.0 - version: 7.0.0 tiny-invariant: specifier: ^1.3.3 version: 1.3.3 @@ -4210,12 +4196,6 @@ importers: '@babel/core': specifier: ^7.26.7 version: 7.26.7 - '@babel/generator': - specifier: ^7.26.5 - version: 7.26.5 - '@babel/parser': - specifier: ^7.26.7 - version: 7.26.7 '@babel/plugin-syntax-jsx': specifier: ^7.25.9 version: 7.25.9(@babel/core@7.26.7) @@ -4237,36 +4217,27 @@ importers: '@tanstack/router-generator': specifier: workspace:* version: link:../router-generator + '@tanstack/router-utils': + specifier: workspace:* + version: link:../router-utils '@tanstack/virtual-file-routes': specifier: workspace:* version: link:../virtual-file-routes '@types/babel__core': specifier: ^7.20.5 version: 7.20.5 - '@types/babel__generator': - specifier: ^7.6.8 - version: 7.6.8 '@types/babel__template': specifier: ^7.4.4 version: 7.4.4 '@types/babel__traverse': specifier: ^7.20.6 version: 7.20.6 - '@types/diff': - specifier: ^6.0.0 - version: 6.0.0 babel-dead-code-elimination: specifier: ^1.0.8 version: 1.0.8 - chalk: - specifier: ^5.4.1 - version: 5.4.1 chokidar: specifier: ^3.6.0 version: 3.6.0 - diff: - specifier: ^7.0.0 - version: 7.0.0 unplugin: specifier: ^2.1.2 version: 2.1.2 @@ -4280,6 +4251,31 @@ importers: specifier: ^3.24.1 version: 3.24.1 + packages/router-utils: + dependencies: + '@babel/generator': + specifier: ^7.26.5 + version: 7.26.5 + '@babel/parser': + specifier: ^7.26.7 + version: 7.26.7 + ansis: + specifier: ^3.5.2 + version: 3.10.0 + diff: + specifier: ^7.0.0 + version: 7.0.0 + devDependencies: + '@babel/types': + specifier: ^7.26.7 + version: 7.26.7 + '@types/babel__generator': + specifier: ^7.6.8 + version: 7.6.8 + '@types/diff': + specifier: ^6.0.0 + version: 6.0.0 + packages/router-vite-plugin: dependencies: '@tanstack/router-plugin': @@ -4294,12 +4290,6 @@ importers: '@babel/core': specifier: ^7.26.7 version: 7.26.7 - '@babel/generator': - specifier: ^7.26.5 - version: 7.26.5 - '@babel/parser': - specifier: ^7.26.7 - version: 7.26.7 '@babel/plugin-syntax-jsx': specifier: ^7.25.9 version: 7.25.9(@babel/core@7.26.7) @@ -4324,30 +4314,18 @@ importers: '@types/babel__core': specifier: ^7.20.5 version: 7.20.5 - '@types/babel__generator': - specifier: ^7.6.8 - version: 7.6.8 '@types/babel__template': specifier: ^7.4.4 version: 7.4.4 '@types/babel__traverse': specifier: ^7.20.6 version: 7.20.6 - '@types/diff': - specifier: ^6.0.0 - version: 6.0.0 babel-dead-code-elimination: specifier: ^1.0.8 version: 1.0.8 - chalk: - specifier: ^5.4.1 - version: 5.4.1 dedent: specifier: ^1.5.3 version: 1.5.3 - diff: - specifier: ^7.0.0 - version: 7.0.0 tiny-invariant: specifier: ^1.3.3 version: 1.3.3 @@ -4501,12 +4479,6 @@ importers: '@babel/core': specifier: ^7.26.7 version: 7.26.7 - '@babel/generator': - specifier: ^7.26.5 - version: 7.26.5 - '@babel/parser': - specifier: ^7.26.7 - version: 7.26.7 '@babel/plugin-syntax-jsx': specifier: ^7.25.9 version: 7.25.9(@babel/core@7.26.7) @@ -4522,33 +4494,24 @@ importers: '@babel/types': specifier: ^7.26.7 version: 7.26.7 + '@tanstack/router-utils': + specifier: workspace:* + version: link:../router-utils '@types/babel__code-frame': specifier: ^7.0.6 version: 7.0.6 '@types/babel__core': specifier: ^7.20.5 version: 7.20.5 - '@types/babel__generator': - specifier: ^7.6.8 - version: 7.6.8 '@types/babel__template': specifier: ^7.4.4 version: 7.4.4 '@types/babel__traverse': specifier: ^7.20.6 version: 7.20.6 - '@types/diff': - specifier: ^6.0.0 - version: 6.0.0 babel-dead-code-elimination: specifier: ^1.0.8 version: 1.0.8 - chalk: - specifier: ^5.4.1 - version: 5.4.1 - diff: - specifier: ^7.0.0 - version: 7.0.0 tiny-invariant: specifier: ^1.3.3 version: 1.3.3 @@ -7346,6 +7309,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansis@3.10.0: + resolution: {integrity: sha512-hxDKLYT7hy3Y4sF3HxI926A3urzPxi73mZBB629m9bCVF+NyKNxbwCqqm+C/YrGPtxLwnl6d8/ZASCsz6SyvJA==} + engines: {node: '>=16'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -14221,17 +14188,17 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.97.1)': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.97.1)': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1)': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) @@ -14360,6 +14327,8 @@ snapshots: ansi-styles@6.2.1: {} + ansis@3.10.0: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -16078,7 +16047,7 @@ snapshots: relateurl: 0.2.7 terser: 5.37.0 - html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1): + html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -18145,7 +18114,7 @@ snapshots: csso: 5.0.5 picocolors: 1.1.1 - swc-loader@0.2.6(@swc/core@1.10.9(@swc/helpers@0.5.15))(webpack@5.97.1): + swc-loader@0.2.6(@swc/core@1.10.9(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)): dependencies: '@swc/core': 1.10.9(@swc/helpers@0.5.15) '@swc/counter': 0.1.3 @@ -18233,26 +18202,26 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)): + terser-webpack-plugin@5.3.11(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2) + webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.10.9(@swc/helpers@0.5.15) esbuild: 0.24.2 - terser-webpack-plugin@5.3.11(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack@5.97.1): + terser-webpack-plugin@5.3.11(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2) optionalDependencies: '@swc/core': 1.10.9(@swc/helpers@0.5.15) esbuild: 0.24.2 @@ -18990,9 +18959,9 @@ snapshots: webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.97.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.97.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.6 @@ -19006,7 +18975,7 @@ snapshots: optionalDependencies: webpack-dev-server: 5.2.0(webpack-cli@5.1.4)(webpack@5.97.1) - webpack-dev-middleware@7.4.2(webpack@5.97.1): + webpack-dev-middleware@7.4.2(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)): dependencies: colorette: 2.0.20 memfs: 4.17.0 @@ -19044,7 +19013,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.97.1) + webpack-dev-middleware: 7.4.2(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) ws: 8.18.0 optionalDependencies: webpack: 5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4) @@ -19117,7 +19086,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack@5.97.1) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.9(@swc/helpers@0.5.15))(esbuild@0.24.2)(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: diff --git a/scripts/publish.js b/scripts/publish.js index c56777bf8e..0b1fa2a1bd 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -132,6 +132,10 @@ await publish({ name: '@tanstack/start-router-manifest', packageDir: 'packages/start-router-manifest', }, + { + name: '@tanstack/router-utils', + packageDir: 'packages/router-utils', + }, ], branchConfigs: { main: {