diff --git a/.changeset/light-coins-hear.md b/.changeset/light-coins-hear.md
new file mode 100644
index 00000000000..56212448572
--- /dev/null
+++ b/.changeset/light-coins-hear.md
@@ -0,0 +1,14 @@
+---
+'@tanstack/router-devtools-core': patch
+'@tanstack/react-start-client': patch
+'@tanstack/solid-start-client': patch
+'@tanstack/start-client-core': patch
+'@tanstack/start-server-core': patch
+'@tanstack/vue-start-client': patch
+'@tanstack/react-router': patch
+'@tanstack/solid-router': patch
+'@tanstack/router-core': patch
+'@tanstack/vue-router': patch
+---
+
+Replace tiny-invariant and tiny-warning with in-house solution for bundle-size
diff --git a/examples/react/start-convex-trellaux/convex/board.ts b/examples/react/start-convex-trellaux/convex/board.ts
index bae241a7734..f585a01cd33 100644
--- a/examples/react/start-convex-trellaux/convex/board.ts
+++ b/examples/react/start-convex-trellaux/convex/board.ts
@@ -1,4 +1,4 @@
-import invariant from 'tiny-invariant'
+import { invariant } from './invariant'
import { v } from 'convex/values'
import {
type QueryCtx,
diff --git a/examples/react/start-convex-trellaux/convex/invariant.ts b/examples/react/start-convex-trellaux/convex/invariant.ts
new file mode 100644
index 00000000000..41fcded35ef
--- /dev/null
+++ b/examples/react/start-convex-trellaux/convex/invariant.ts
@@ -0,0 +1,5 @@
+export function invariant(value: unknown, message?: string): asserts value {
+ if (!value) {
+ throw new Error(message ?? 'Invariant failed')
+ }
+}
diff --git a/examples/react/start-convex-trellaux/package.json b/examples/react/start-convex-trellaux/package.json
index 171c516d08a..355f8309c6f 100644
--- a/examples/react/start-convex-trellaux/package.json
+++ b/examples/react/start-convex-trellaux/package.json
@@ -28,7 +28,6 @@
"react-hot-toast": "^2.5.1",
"redaxios": "^0.5.1",
"tailwind-merge": "^2.6.0",
- "tiny-invariant": "^1.3.3",
"zod": "^3.24.2"
},
"devDependencies": {
diff --git a/examples/react/start-convex-trellaux/src/components/Board.tsx b/examples/react/start-convex-trellaux/src/components/Board.tsx
index 327603e2046..ac78c7baae5 100644
--- a/examples/react/start-convex-trellaux/src/components/Board.tsx
+++ b/examples/react/start-convex-trellaux/src/components/Board.tsx
@@ -1,5 +1,5 @@
import { useCallback, useMemo, useRef } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { useSuspenseQuery } from '@tanstack/react-query'
import { convexQuery } from '@convex-dev/react-query'
import { api } from '../../convex/_generated/api.js'
diff --git a/examples/react/start-convex-trellaux/src/components/Card.tsx b/examples/react/start-convex-trellaux/src/components/Card.tsx
index eacf87d7598..23f77ca2b2c 100644
--- a/examples/react/start-convex-trellaux/src/components/Card.tsx
+++ b/examples/react/start-convex-trellaux/src/components/Card.tsx
@@ -1,4 +1,4 @@
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { forwardRef, useState } from 'react'
import { CONTENT_TYPES } from '../types'
diff --git a/examples/react/start-convex-trellaux/src/components/Column.tsx b/examples/react/start-convex-trellaux/src/components/Column.tsx
index dd90e02ee71..fdf2916f6b1 100644
--- a/examples/react/start-convex-trellaux/src/components/Column.tsx
+++ b/examples/react/start-convex-trellaux/src/components/Column.tsx
@@ -1,8 +1,8 @@
import { forwardRef, useCallback, useMemo, useRef, useState } from 'react'
-import invariant from 'tiny-invariant'
import { twMerge } from 'tailwind-merge'
import { flushSync } from 'react-dom'
+import { invariant } from '../invariant'
import { CONTENT_TYPES } from '../types'
import { Icon } from '../icons/icons'
import {
diff --git a/examples/react/start-convex-trellaux/src/components/NewCard.tsx b/examples/react/start-convex-trellaux/src/components/NewCard.tsx
index 47cadcf5aee..99b0b148390 100644
--- a/examples/react/start-convex-trellaux/src/components/NewCard.tsx
+++ b/examples/react/start-convex-trellaux/src/components/NewCard.tsx
@@ -1,5 +1,5 @@
import { useRef } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { ItemMutationFields } from '../types'
import { useCreateItemMutation } from '../queries'
diff --git a/examples/react/start-convex-trellaux/src/components/NewColumn.tsx b/examples/react/start-convex-trellaux/src/components/NewColumn.tsx
index 50a7d608c55..0cd1f6aa532 100644
--- a/examples/react/start-convex-trellaux/src/components/NewColumn.tsx
+++ b/examples/react/start-convex-trellaux/src/components/NewColumn.tsx
@@ -1,5 +1,5 @@
import { useRef, useState } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { Icon } from '../icons/icons'
import { useCreateColumnMutation } from '../queries'
diff --git a/examples/react/start-convex-trellaux/src/invariant.ts b/examples/react/start-convex-trellaux/src/invariant.ts
new file mode 100644
index 00000000000..41fcded35ef
--- /dev/null
+++ b/examples/react/start-convex-trellaux/src/invariant.ts
@@ -0,0 +1,5 @@
+export function invariant(value: unknown, message?: string): asserts value {
+ if (!value) {
+ throw new Error(message ?? 'Invariant failed')
+ }
+}
diff --git a/examples/react/start-trellaux/package.json b/examples/react/start-trellaux/package.json
index 7a76758fe8d..7c4df69ed87 100644
--- a/examples/react/start-trellaux/package.json
+++ b/examples/react/start-trellaux/package.json
@@ -23,7 +23,6 @@
"react-hot-toast": "^2.5.1",
"redaxios": "^0.5.1",
"tailwind-merge": "^2.6.0",
- "tiny-invariant": "^1.3.3",
"zod": "^3.24.2"
},
"devDependencies": {
diff --git a/examples/react/start-trellaux/src/components/Board.tsx b/examples/react/start-trellaux/src/components/Board.tsx
index 0b43e1d9237..0ba9a3c288d 100644
--- a/examples/react/start-trellaux/src/components/Board.tsx
+++ b/examples/react/start-trellaux/src/components/Board.tsx
@@ -1,5 +1,5 @@
import { useCallback, useMemo, useRef } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { useSuspenseQuery } from '@tanstack/react-query'
import { boardQueries, useUpdateBoardMutation } from '../queries.js'
import { NewColumn } from './NewColumn.js'
diff --git a/examples/react/start-trellaux/src/components/Card.tsx b/examples/react/start-trellaux/src/components/Card.tsx
index 6c73ca079fb..729b93d2f85 100644
--- a/examples/react/start-trellaux/src/components/Card.tsx
+++ b/examples/react/start-trellaux/src/components/Card.tsx
@@ -1,4 +1,4 @@
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { forwardRef, useState } from 'react'
import { CONTENT_TYPES } from '../types'
diff --git a/examples/react/start-trellaux/src/components/Column.tsx b/examples/react/start-trellaux/src/components/Column.tsx
index f9fddaaf5f3..a95faedb54a 100644
--- a/examples/react/start-trellaux/src/components/Column.tsx
+++ b/examples/react/start-trellaux/src/components/Column.tsx
@@ -1,8 +1,8 @@
import { forwardRef, useCallback, useMemo, useRef, useState } from 'react'
-import invariant from 'tiny-invariant'
import { twMerge } from 'tailwind-merge'
import { flushSync } from 'react-dom'
+import { invariant } from '../invariant'
import { CONTENT_TYPES } from '../types'
import { Icon } from '../icons/icons'
import {
diff --git a/examples/react/start-trellaux/src/components/NewCard.tsx b/examples/react/start-trellaux/src/components/NewCard.tsx
index 8201083bb36..b46f965c8b5 100644
--- a/examples/react/start-trellaux/src/components/NewCard.tsx
+++ b/examples/react/start-trellaux/src/components/NewCard.tsx
@@ -1,5 +1,5 @@
import { useRef } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { ItemMutationFields } from '../types'
import { useCreateItemMutation } from '../queries'
diff --git a/examples/react/start-trellaux/src/components/NewColumn.tsx b/examples/react/start-trellaux/src/components/NewColumn.tsx
index acb6c82cfb9..655b380743c 100644
--- a/examples/react/start-trellaux/src/components/NewColumn.tsx
+++ b/examples/react/start-trellaux/src/components/NewColumn.tsx
@@ -1,5 +1,5 @@
import { useRef, useState } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { Icon } from '../icons/icons'
import { useCreateColumnMutation } from '../queries'
diff --git a/examples/react/start-trellaux/src/db/board.ts b/examples/react/start-trellaux/src/db/board.ts
index 92f94967e9c..ee80aeb9f7f 100644
--- a/examples/react/start-trellaux/src/db/board.ts
+++ b/examples/react/start-trellaux/src/db/board.ts
@@ -1,6 +1,6 @@
import crypto from 'node:crypto'
import { createServerFn } from '@tanstack/react-start'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import * as z from 'zod'
import {
deleteColumnSchema,
diff --git a/examples/react/start-trellaux/src/invariant.ts b/examples/react/start-trellaux/src/invariant.ts
new file mode 100644
index 00000000000..41fcded35ef
--- /dev/null
+++ b/examples/react/start-trellaux/src/invariant.ts
@@ -0,0 +1,5 @@
+export function invariant(value: unknown, message?: string): asserts value {
+ if (!value) {
+ throw new Error(message ?? 'Invariant failed')
+ }
+}
diff --git a/packages/react-router/package.json b/packages/react-router/package.json
index cfc57e0077f..ee7adffc7c1 100644
--- a/packages/react-router/package.json
+++ b/packages/react-router/package.json
@@ -99,9 +99,7 @@
"@tanstack/history": "workspace:*",
"@tanstack/react-store": "^0.9.2",
"@tanstack/router-core": "workspace:*",
- "isbot": "^5.1.22",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "isbot": "^5.1.22"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.6.3",
diff --git a/packages/react-router/src/Match.tsx b/packages/react-router/src/Match.tsx
index 36b41ef1240..ba21ee3896a 100644
--- a/packages/react-router/src/Match.tsx
+++ b/packages/react-router/src/Match.tsx
@@ -1,10 +1,9 @@
import * as React from 'react'
import { useStore } from '@tanstack/react-store'
-import invariant from 'tiny-invariant'
-import warning from 'tiny-warning'
import {
createControlledPromise,
getLocationChangeInfo,
+ invariant,
isNotFound,
isRedirect,
rootRouteId,
@@ -33,10 +32,15 @@ export const Match = React.memo(function MatchImpl({
if (isServer ?? router.isServer) {
const match = router.stores.activeMatchStoresById.get(matchId)?.state
- invariant(
- match,
- `Could not find match for matchId "${matchId}". Please file an issue!`,
- )
+ if (!match) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
+ )
+ }
+
+ invariant()
+ }
const routeId = match.routeId as string
const parentRouteId = (router.routesById[routeId] as AnyRoute).parentRoute
@@ -62,10 +66,15 @@ export const Match = React.memo(function MatchImpl({
// and reconcileMatchPool reuses stores for the same matchId.
// eslint-disable-next-line react-hooks/rules-of-hooks
const matchStore = router.stores.activeMatchStoresById.get(matchId)
- invariant(
- matchStore,
- `Could not find match for matchId "${matchId}". Please file an issue!`,
- )
+ if (!matchStore) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
+ )
+ }
+
+ invariant()
+ }
// eslint-disable-next-line react-hooks/rules-of-hooks
const resetKey = useStore(router.stores.loadedAt, (loadedAt) => loadedAt)
// eslint-disable-next-line react-hooks/rules-of-hooks
@@ -162,7 +171,9 @@ function MatchView({
onCatch={(error, errorInfo) => {
// Forward not found errors (we don't want to show the error component for these)
if (isNotFound(error)) throw error
- warning(false, `Error in route match: ${matchId}`)
+ if (process.env.NODE_ENV !== 'production') {
+ console.warn(`Warning: Error in route match: ${matchId}`)
+ }
routeOnCatch?.(error, errorInfo)
}}
>
@@ -249,10 +260,15 @@ export const MatchInner = React.memo(function MatchInnerImpl({
if (isServer ?? router.isServer) {
const match = router.stores.activeMatchStoresById.get(matchId)?.state
- invariant(
- match,
- `Could not find match for matchId "${matchId}". Please file an issue!`,
- )
+ if (!match) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
+ )
+ }
+
+ invariant()
+ }
const routeId = match.routeId as string
const route = router.routesById[routeId] as AnyRoute
@@ -282,12 +298,24 @@ export const MatchInner = React.memo(function MatchInnerImpl({
}
if (match.status === 'notFound') {
- invariant(isNotFound(match.error), 'Expected a notFound error')
+ if (!isNotFound(match.error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: Expected a notFound error')
+ }
+
+ invariant()
+ }
return renderRouteNotFound(router, route, match.error)
}
if (match.status === 'redirected') {
- invariant(isRedirect(match.error), 'Expected a redirect error')
+ if (!isRedirect(match.error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: Expected a redirect error')
+ }
+
+ invariant()
+ }
throw router.getMatch(match.id)?._nonReactive.loadPromise
}
@@ -312,10 +340,15 @@ export const MatchInner = React.memo(function MatchInnerImpl({
// eslint-disable-next-line react-hooks/rules-of-hooks
const matchStore = router.stores.activeMatchStoresById.get(matchId)
- invariant(
- matchStore,
- `Could not find match for matchId "${matchId}". Please file an issue!`,
- )
+ if (!matchStore) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`,
+ )
+ }
+
+ invariant()
+ }
// eslint-disable-next-line react-hooks/rules-of-hooks
const match = useStore(matchStore, (value) => value)
const routeId = match.routeId as string
@@ -384,14 +417,26 @@ export const MatchInner = React.memo(function MatchInnerImpl({
}
if (match.status === 'notFound') {
- invariant(isNotFound(match.error), 'Expected a notFound error')
+ if (!isNotFound(match.error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: Expected a notFound error')
+ }
+
+ invariant()
+ }
return renderRouteNotFound(router, route, match.error)
}
if (match.status === 'redirected') {
// Redirects should be handled by the router transition. If we happen to
// encounter a redirect here, it's a bug. Let's warn, but render nothing.
- invariant(isRedirect(match.error), 'Expected a redirect error')
+ if (!isRedirect(match.error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: Expected a redirect error')
+ }
+
+ invariant()
+ }
// warning(
// false,
@@ -479,7 +524,15 @@ export const Outlet = React.memo(function OutletImpl() {
) : null
if (parentGlobalNotFound) {
- invariant(route, 'Could not resolve route for Outlet render')
+ if (!route) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Could not resolve route for Outlet render',
+ )
+ }
+
+ invariant()
+ }
return renderRouteNotFound(router, route, undefined)
}
diff --git a/packages/react-router/src/Matches.tsx b/packages/react-router/src/Matches.tsx
index 953a49401bf..f7f61d6e9b3 100644
--- a/packages/react-router/src/Matches.tsx
+++ b/packages/react-router/src/Matches.tsx
@@ -1,5 +1,4 @@
import * as React from 'react'
-import warning from 'tiny-warning'
import { useStore } from '@tanstack/react-store'
import { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'
import { isServer } from '@tanstack/router-core/isServer'
@@ -100,11 +99,10 @@ function MatchesInner() {
onCatch={
process.env.NODE_ENV !== 'production'
? (error) => {
- warning(
- false,
- `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
+ console.warn(
+ `Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
)
- warning(false, error.message || error.toString())
+ console.warn(`Warning: ${error.message || error.toString()}`)
}
: undefined
}
diff --git a/packages/react-router/src/fileRoute.ts b/packages/react-router/src/fileRoute.ts
index c38c24485fb..aeccbc20443 100644
--- a/packages/react-router/src/fileRoute.ts
+++ b/packages/react-router/src/fileRoute.ts
@@ -1,4 +1,3 @@
-import warning from 'tiny-warning'
import { createRoute } from './route'
import { useMatch } from './useMatch'
@@ -151,10 +150,11 @@ export class FileRoute<
THandlers
> => {
if (process.env.NODE_ENV !== 'production') {
- warning(
- this.silent,
- 'FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
- )
+ if (!this.silent) {
+ console.warn(
+ 'Warning: FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
+ )
+ }
}
const route = createRoute(options as any)
;(route as any).isRoot = false
@@ -187,9 +187,8 @@ export function FileRouteLoader<
>,
) => TLoaderFn {
if (process.env.NODE_ENV !== 'production') {
- warning(
- false,
- `FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
+ console.warn(
+ `Warning: FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
)
}
return (loaderFn) => loaderFn as any
diff --git a/packages/react-router/src/renderRouteNotFound.tsx b/packages/react-router/src/renderRouteNotFound.tsx
index 225a013beae..f8374ebd7c2 100644
--- a/packages/react-router/src/renderRouteNotFound.tsx
+++ b/packages/react-router/src/renderRouteNotFound.tsx
@@ -1,5 +1,4 @@
import * as React from 'react'
-import warning from 'tiny-warning'
import { DefaultGlobalNotFound } from './not-found'
import type { AnyRoute, AnyRouter } from '@tanstack/router-core'
@@ -21,11 +20,12 @@ export function renderRouteNotFound(
return
}
- if (process.env.NODE_ENV === 'development') {
- warning(
- route.options.notFoundComponent,
- `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (
Not Found
)`,
- )
+ if (process.env.NODE_ENV !== 'production') {
+ if (!route.options.notFoundComponent) {
+ console.warn(
+ `Warning: A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (Not Found
)`,
+ )
+ }
}
return
diff --git a/packages/react-router/src/useMatch.tsx b/packages/react-router/src/useMatch.tsx
index 26dbc1082fe..8048e24521e 100644
--- a/packages/react-router/src/useMatch.tsx
+++ b/packages/react-router/src/useMatch.tsx
@@ -1,8 +1,7 @@
import * as React from 'react'
import { useStore } from '@tanstack/react-store'
-import { replaceEqualDeep } from '@tanstack/router-core'
+import { invariant, replaceEqualDeep } from '@tanstack/router-core'
import { isServer } from '@tanstack/router-core/isServer'
-import invariant from 'tiny-invariant'
import { dummyMatchContext, matchContext } from './matchContext'
import { useRouter } from './useRouter'
import type {
@@ -119,10 +118,15 @@ export function useMatch<
if (isServer ?? router.isServer) {
const match = matchStore?.state
- invariant(
- !((opts.shouldThrow ?? true) && !match),
- `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
- )
+ if ((opts.shouldThrow ?? true) && !match) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
+ )
+ }
+
+ invariant()
+ }
if (match === undefined) {
return undefined as any
@@ -139,10 +143,15 @@ export function useMatch<
// eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static
return useStore(matchStore ?? dummyStore, (match) => {
- invariant(
- !((opts.shouldThrow ?? true) && !match),
- `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
- )
+ if ((opts.shouldThrow ?? true) && !match) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
+ )
+ }
+
+ invariant()
+ }
if (match === undefined) {
return undefined
diff --git a/packages/react-router/src/useRouter.tsx b/packages/react-router/src/useRouter.tsx
index 1bc4220f383..51364f4e84e 100644
--- a/packages/react-router/src/useRouter.tsx
+++ b/packages/react-router/src/useRouter.tsx
@@ -1,5 +1,4 @@
import * as React from 'react'
-import warning from 'tiny-warning'
import { routerContext } from './routerContext'
import type { AnyRouter, RegisteredRouter } from '@tanstack/router-core'
@@ -17,9 +16,12 @@ export function useRouter(opts?: {
warn?: boolean
}): TRouter {
const value = React.useContext(routerContext)
- warning(
- !((opts?.warn ?? true) && !value),
- 'useRouter must be used inside a component!',
- )
+ if (process.env.NODE_ENV !== 'production') {
+ if ((opts?.warn ?? true) && !value) {
+ console.warn(
+ 'Warning: useRouter must be used inside a component!',
+ )
+ }
+ }
return value as any
}
diff --git a/packages/react-router/tests/redirect.test.tsx b/packages/react-router/tests/redirect.test.tsx
index b8b42d5e0e3..a391d02898f 100644
--- a/packages/react-router/tests/redirect.test.tsx
+++ b/packages/react-router/tests/redirect.test.tsx
@@ -8,7 +8,6 @@ import {
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
-import invariant from 'tiny-invariant'
import {
Link,
RouterProvider,
@@ -300,9 +299,9 @@ describe('redirect', () => {
expect(router.state.redirect).toBeDefined()
expect(router.state.redirect).toBeInstanceOf(Response)
- invariant(router.state.redirect)
+ const redirectResponse = router.state.redirect!
- expect(router.state.redirect.options).toEqual({
+ expect(redirectResponse.options).toEqual({
_fromLocation: expect.objectContaining({
hash: '',
href: '/',
@@ -352,10 +351,10 @@ describe('redirect', () => {
expect(currentRedirect).toBeDefined()
expect(currentRedirect).toBeInstanceOf(Response)
- invariant(currentRedirect)
- expect(currentRedirect.status).toEqual(307)
- expect(currentRedirect.headers.get('Location')).toEqual('/about')
- expect(currentRedirect.options).toEqual({
+ const redirectResponse = currentRedirect!
+ expect(redirectResponse.status).toEqual(307)
+ expect(redirectResponse.headers.get('Location')).toEqual('/about')
+ expect(redirectResponse.options).toEqual({
_fromLocation: {
external: false,
hash: '',
@@ -366,8 +365,8 @@ describe('redirect', () => {
searchStr: '',
state: {
__TSR_index: 0,
- __TSR_key: currentRedirect.options._fromLocation!.state.__TSR_key,
- key: currentRedirect.options._fromLocation!.state.key,
+ __TSR_key: redirectResponse.options._fromLocation!.state.__TSR_key,
+ key: redirectResponse.options._fromLocation!.state.key,
},
},
href: '/about',
diff --git a/packages/react-start-client/package.json b/packages/react-start-client/package.json
index d098b360a08..88dfa2f150d 100644
--- a/packages/react-start-client/package.json
+++ b/packages/react-start-client/package.json
@@ -61,9 +61,7 @@
"dependencies": {
"@tanstack/react-router": "workspace:*",
"@tanstack/router-core": "workspace:*",
- "@tanstack/start-client-core": "workspace:*",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "@tanstack/start-client-core": "workspace:*"
},
"devDependencies": {
"@testing-library/react": "^16.2.0",
diff --git a/packages/react-start-client/src/renderRSC.tsx b/packages/react-start-client/src/renderRSC.tsx
index 4832f074b61..bc8482fc538 100644
--- a/packages/react-start-client/src/renderRSC.tsx
+++ b/packages/react-start-client/src/renderRSC.tsx
@@ -1,6 +1,6 @@
// TODO: RSCs
import { isValidElement } from 'react'
-import invariant from 'tiny-invariant'
+import { invariant } from '@tanstack/router-core'
import type React from 'react'
export function renderRsc(input: any): React.JSX.Element {
@@ -68,7 +68,11 @@ export function renderRsc(input: any): React.JSX.Element {
// return element
- invariant(false, 'renderRSC() is coming soon!')
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: renderRSC() is coming soon!')
+ }
+
+ invariant()
})
.then((element) => {
input.state.value = element
diff --git a/packages/router-core/package.json b/packages/router-core/package.json
index 63c008514a1..cedab4baef8 100644
--- a/packages/router-core/package.json
+++ b/packages/router-core/package.json
@@ -165,9 +165,7 @@
"@tanstack/history": "workspace:*",
"cookie-es": "^2.0.0",
"seroval": "^1.4.2",
- "seroval-plugins": "^1.4.2",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "seroval-plugins": "^1.4.2"
},
"devDependencies": {
"@tanstack/store": "^0.9.2",
diff --git a/packages/router-core/src/index.ts b/packages/router-core/src/index.ts
index ad1389ff23b..649c4fac14e 100644
--- a/packages/router-core/src/index.ts
+++ b/packages/router-core/src/index.ts
@@ -2,6 +2,7 @@ export * from './global'
export { TSR_DEFERRED_PROMISE, defer } from './defer'
export type { DeferredPromiseState, DeferredPromise } from './defer'
+export { invariant } from './invariant'
export { preloadWarning } from './link'
export type {
IsRequiredParams,
diff --git a/packages/router-core/src/invariant.ts b/packages/router-core/src/invariant.ts
new file mode 100644
index 00000000000..926b8793a9b
--- /dev/null
+++ b/packages/router-core/src/invariant.ts
@@ -0,0 +1,3 @@
+export function invariant(): never {
+ throw new Error('Invariant failed')
+}
diff --git a/packages/router-core/src/load-matches.ts b/packages/router-core/src/load-matches.ts
index 84071950781..d212c72b926 100644
--- a/packages/router-core/src/load-matches.ts
+++ b/packages/router-core/src/load-matches.ts
@@ -1,5 +1,5 @@
-import invariant from 'tiny-invariant'
import { isServer } from '@tanstack/router-core/isServer'
+import { invariant } from './invariant'
import { createControlledPromise, isPromise } from './utils'
import { isNotFound } from './not-found'
import { rootRouteId } from './root'
@@ -1076,10 +1076,15 @@ export async function loadMatches(arg: {
notFoundToThrow,
)
- invariant(
- renderedBoundaryIndex !== undefined,
- 'Could not find match for notFound boundary',
- )
+ if (renderedBoundaryIndex === undefined) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Could not find match for notFound boundary',
+ )
+ }
+
+ invariant()
+ }
const boundaryMatch = inner.matches[renderedBoundaryIndex]!
const boundaryRoute = inner.router.looseRoutesById[boundaryMatch.routeId]!
diff --git a/packages/router-core/src/new-process-route-tree.ts b/packages/router-core/src/new-process-route-tree.ts
index 213f559f943..6ba6a45c870 100644
--- a/packages/router-core/src/new-process-route-tree.ts
+++ b/packages/router-core/src/new-process-route-tree.ts
@@ -1,4 +1,4 @@
-import invariant from 'tiny-invariant'
+import { invariant } from './invariant'
import { createLRUCache } from './lru-cache'
import { last } from './utils'
import type { LRUCache } from './lru-cache'
@@ -811,10 +811,15 @@ export function processRouteTree<
parseSegments(caseSensitive, data, routeTree, 1, segmentTree, 0, (route) => {
initRoute?.(route, index)
- invariant(
- !(route.id in routesById),
- `Duplicate routes found with id: ${String(route.id)}`,
- )
+ if (route.id in routesById) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Duplicate routes found with id: ${String(route.id)}`,
+ )
+ }
+
+ invariant()
+ }
routesById[route.id] = route
diff --git a/packages/router-core/src/route.ts b/packages/router-core/src/route.ts
index ef80228c8bc..7217f883ab6 100644
--- a/packages/router-core/src/route.ts
+++ b/packages/router-core/src/route.ts
@@ -1,4 +1,4 @@
-import invariant from 'tiny-invariant'
+import { invariant } from './invariant'
import { joinPaths, trimPathLeft, trimPathRight } from './path'
import { notFound } from './not-found'
import { redirect } from './redirect'
@@ -1808,10 +1808,13 @@ export class BaseRoute<
if (isRoot) {
this._path = rootRouteId as TPath
} else if (!this.parentRoute) {
- invariant(
- false,
- `Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
- )
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Child Route instances must pass a 'getParentRoute: () => ParentRoute' option that returns a Route instance.`,
+ )
+ }
+
+ invariant()
}
let path: undefined | string = isRoot ? rootRouteId : options?.path
diff --git a/packages/router-core/src/ssr/ssr-client.ts b/packages/router-core/src/ssr/ssr-client.ts
index 49c4627ad22..b2ea33e92bf 100644
--- a/packages/router-core/src/ssr/ssr-client.ts
+++ b/packages/router-core/src/ssr/ssr-client.ts
@@ -1,4 +1,4 @@
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { isNotFound } from '../not-found'
import { createControlledPromise } from '../utils'
import { hydrateSsrMatchId } from './ssr-match-id'
@@ -38,10 +38,15 @@ function hydrateMatch(
}
export async function hydrate(router: AnyRouter): Promise {
- invariant(
- window.$_TSR,
- 'Expected to find bootstrap data on window.$_TSR, but we did not. Please file an issue!',
- )
+ if (!window.$_TSR) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Expected to find bootstrap data on window.$_TSR, but we did not. Please file an issue!',
+ )
+ }
+
+ invariant()
+ }
const serializationAdapters = router.options.serializationAdapters as
| Array
@@ -57,10 +62,15 @@ export async function hydrate(router: AnyRouter): Promise {
}
window.$_TSR.initialized = true
- invariant(
- window.$_TSR.router,
- 'Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!',
- )
+ if (!window.$_TSR.router) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Expected to find a dehydrated data on window.$_TSR.router, but we did not. Please file an issue!',
+ )
+ }
+
+ invariant()
+ }
const dehydratedRouter = window.$_TSR.router
dehydratedRouter.matches.forEach((dehydratedMatch) => {
@@ -258,10 +268,15 @@ export async function hydrate(router: AnyRouter): Promise {
// this will prevent that other pending components are rendered but hydration is not blocked
if (isSpaMode) {
const match = matches[1]
- invariant(
- match,
- 'Expected to find a match below the root match in SPA mode.',
- )
+ if (!match) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Expected to find a match below the root match in SPA mode.',
+ )
+ }
+
+ invariant()
+ }
setMatchForcePending(match)
match._displayPending = true
diff --git a/packages/router-core/src/ssr/ssr-server.ts b/packages/router-core/src/ssr/ssr-server.ts
index 0d262ade8a3..3fdd8b24bc8 100644
--- a/packages/router-core/src/ssr/ssr-server.ts
+++ b/packages/router-core/src/ssr/ssr-server.ts
@@ -1,5 +1,5 @@
import { crossSerializeStream, getCrossReferenceHeader } from 'seroval'
-import invariant from 'tiny-invariant'
+import { invariant } from '../invariant'
import { decodePath } from '../utils'
import { createLRUCache } from '../lru-cache'
import minifiedTsrBootStrapScript from './tsrScript?script-string'
@@ -201,7 +201,13 @@ export function attachRouterServerSsrUtils({
router.serverSsr!.injectHtml(html)
},
dehydrate: async () => {
- invariant(!_dehydrated, 'router is already dehydrated!')
+ if (_dehydrated) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: router is already dehydrated!')
+ }
+
+ invariant()
+ }
let matchesToDehydrate = router.stores.activeMatchesSnapshot.state
if (router.isShell()) {
// In SPA mode we only want to dehydrate the root match
diff --git a/packages/router-devtools-core/package.json b/packages/router-devtools-core/package.json
index 9f8cef77380..5ab08258695 100644
--- a/packages/router-devtools-core/package.json
+++ b/packages/router-devtools-core/package.json
@@ -63,8 +63,7 @@
},
"dependencies": {
"clsx": "^2.1.1",
- "goober": "^2.1.16",
- "tiny-invariant": "^1.3.3"
+ "goober": "^2.1.16"
},
"devDependencies": {
"solid-js": "^1.9.10",
diff --git a/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx b/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
index 4ba50cf1cd0..883d07f6a65 100644
--- a/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
+++ b/packages/router-devtools-core/src/BaseTanStackRouterDevtoolsPanel.tsx
@@ -1,5 +1,4 @@
import { clsx as cx } from 'clsx'
-import { default as invariant } from 'tiny-invariant'
import { interpolatePath, rootRouteId, trimPath } from '@tanstack/router-core'
import {
For,
@@ -264,11 +263,6 @@ export const BaseTanStackRouterDevtoolsPanel =
const styles = useStyles()
const { className, style, ...otherPanelProps } = panelProps
- invariant(
- router,
- 'No router was found for the TanStack Router Devtools. Please place the devtools in the component tree or pass the router instance to the devtools manually.',
- )
-
// useStore(router.stores.__store)
const [currentTab, setCurrentTab] = useLocalStorage<
diff --git a/packages/solid-router/package.json b/packages/solid-router/package.json
index 585f140f8e5..0b618676917 100644
--- a/packages/solid-router/package.json
+++ b/packages/solid-router/package.json
@@ -109,9 +109,7 @@
"@solidjs/meta": "^0.29.4",
"@tanstack/history": "workspace:*",
"@tanstack/router-core": "workspace:*",
- "isbot": "^5.1.22",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "isbot": "^5.1.22"
},
"devDependencies": {
"@solidjs/testing-library": "^0.8.10",
diff --git a/packages/solid-router/src/Match.tsx b/packages/solid-router/src/Match.tsx
index 9ac0e485ea3..2f2320360df 100644
--- a/packages/solid-router/src/Match.tsx
+++ b/packages/solid-router/src/Match.tsx
@@ -1,9 +1,8 @@
import * as Solid from 'solid-js'
-import invariant from 'tiny-invariant'
-import warning from 'tiny-warning'
import {
createControlledPromise,
getLocationChangeInfo,
+ invariant,
isNotFound,
isRedirect,
rootRouteId,
@@ -119,10 +118,11 @@ export const Match = (props: { matchId: string }) => {
onCatch={(error: Error) => {
// Forward not found errors (we don't want to show the error component for these)
if (isNotFound(error)) throw error
- warning(
- false,
- `Error in route match: ${currentMatchState().routeId}`,
- )
+ if (process.env.NODE_ENV !== 'production') {
+ console.warn(
+ `Warning: Error in route match: ${currentMatchState().routeId}`,
+ )
+ }
routeOnCatch()?.(error)
}}
>
@@ -342,10 +342,15 @@ export const MatchInner = (): any => {
{(_) => {
- invariant(
- isNotFound(currentMatch().error),
- 'Expected a notFound error',
- )
+ if (!isNotFound(currentMatch().error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Expected a notFound error',
+ )
+ }
+
+ invariant()
+ }
// Use Show with keyed to ensure re-render when routeId changes
return (
@@ -359,10 +364,15 @@ export const MatchInner = (): any => {
{(_) => {
- invariant(
- isRedirect(currentMatch().error),
- 'Expected a redirect error',
- )
+ if (!isRedirect(currentMatch().error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: Expected a redirect error',
+ )
+ }
+
+ invariant()
+ }
const [loaderResult] = Solid.createResource(async () => {
await new Promise((r) => setTimeout(r, 0))
diff --git a/packages/solid-router/src/Matches.tsx b/packages/solid-router/src/Matches.tsx
index 636a9a73244..1a317693eb6 100644
--- a/packages/solid-router/src/Matches.tsx
+++ b/packages/solid-router/src/Matches.tsx
@@ -1,5 +1,4 @@
import * as Solid from 'solid-js'
-import warning from 'tiny-warning'
import { replaceEqualDeep, rootRouteId } from '@tanstack/router-core'
import { isServer } from '@tanstack/router-core/isServer'
import { CatchBoundary, ErrorComponent } from './CatchBoundary'
@@ -103,11 +102,10 @@ function MatchesInner() {
onCatch={
process.env.NODE_ENV !== 'production'
? (error) => {
- warning(
- false,
- `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
+ console.warn(
+ `Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
)
- warning(false, error.message || error.toString())
+ console.warn(`Warning: ${error.message || error.toString()}`)
}
: undefined
}
diff --git a/packages/solid-router/src/fileRoute.ts b/packages/solid-router/src/fileRoute.ts
index dbe12dd722d..5fbdc73d5f6 100644
--- a/packages/solid-router/src/fileRoute.ts
+++ b/packages/solid-router/src/fileRoute.ts
@@ -1,4 +1,3 @@
-import warning from 'tiny-warning'
import { createRoute } from './route'
import { useMatch } from './useMatch'
@@ -140,10 +139,11 @@ export class FileRoute<
THandlers
> => {
if (process.env.NODE_ENV !== 'production') {
- warning(
- this.silent,
- 'FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
- )
+ if (!this.silent) {
+ console.warn(
+ 'Warning: FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
+ )
+ }
}
const route = createRoute(options as any)
;(route as any).isRoot = false
@@ -177,9 +177,8 @@ export function FileRouteLoader<
>,
) => TLoaderFn {
if (process.env.NODE_ENV !== 'production') {
- warning(
- false,
- `FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
+ console.warn(
+ `Warning: FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
)
}
return (loaderFn) => loaderFn as any
diff --git a/packages/solid-router/src/renderRouteNotFound.tsx b/packages/solid-router/src/renderRouteNotFound.tsx
index 9160e624995..078a632e08c 100644
--- a/packages/solid-router/src/renderRouteNotFound.tsx
+++ b/packages/solid-router/src/renderRouteNotFound.tsx
@@ -1,4 +1,3 @@
-import warning from 'tiny-warning'
import { DefaultGlobalNotFound } from './not-found'
import type { AnyRoute, AnyRouter } from '@tanstack/router-core'
@@ -20,11 +19,12 @@ export function renderRouteNotFound(
return
}
- if (process.env.NODE_ENV === 'development') {
- warning(
- route.options.notFoundComponent,
- `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (Not Found
)`,
- )
+ if (process.env.NODE_ENV !== 'production') {
+ if (!route.options.notFoundComponent) {
+ console.warn(
+ `Warning: A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (Not Found
)`,
+ )
+ }
}
return
diff --git a/packages/solid-router/src/useMatch.tsx b/packages/solid-router/src/useMatch.tsx
index 7c8cae93a55..d8c6f8ec97e 100644
--- a/packages/solid-router/src/useMatch.tsx
+++ b/packages/solid-router/src/useMatch.tsx
@@ -1,6 +1,5 @@
import * as Solid from 'solid-js'
-import invariant from 'tiny-invariant'
-import { replaceEqualDeep } from '@tanstack/router-core'
+import { invariant, replaceEqualDeep } from '@tanstack/router-core'
import { nearestMatchContext } from './matchContext'
import { useRouter } from './useRouter'
import type {
@@ -92,14 +91,19 @@ export function useMatch<
? Boolean(router.stores.pendingRouteIds.state[opts.from!])
: (nearestMatch?.hasPending() ?? false)
- invariant(
- !(
- !hasPendingMatch &&
- !router.stores.isTransitioning.state &&
- (opts.shouldThrow ?? true)
- ),
- `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
- )
+ if (
+ !hasPendingMatch &&
+ !router.stores.isTransitioning.state &&
+ (opts.shouldThrow ?? true)
+ ) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
+ )
+ }
+
+ invariant()
+ }
})
return Solid.createMemo((prev: TSelected | undefined) => {
diff --git a/packages/solid-router/src/useRouter.tsx b/packages/solid-router/src/useRouter.tsx
index 33cd163cebf..89b53e9d57f 100644
--- a/packages/solid-router/src/useRouter.tsx
+++ b/packages/solid-router/src/useRouter.tsx
@@ -1,5 +1,4 @@
import * as Solid from 'solid-js'
-import warning from 'tiny-warning'
import { routerContext } from './routerContext'
import type { AnyRouter, RegisteredRouter } from '@tanstack/router-core'
@@ -7,9 +6,12 @@ export function useRouter(opts?: {
warn?: boolean
}): TRouter {
const value = Solid.useContext(routerContext as any)
- warning(
- !((opts?.warn ?? true) && !value),
- 'useRouter must be used inside a component!',
- )
+ if (process.env.NODE_ENV !== 'production') {
+ if ((opts?.warn ?? true) && !value) {
+ console.warn(
+ 'Warning: useRouter must be used inside a component!',
+ )
+ }
+ }
return value as any
}
diff --git a/packages/solid-router/tests/redirect.test.tsx b/packages/solid-router/tests/redirect.test.tsx
index df3326ada03..5d3ecc898ac 100644
--- a/packages/solid-router/tests/redirect.test.tsx
+++ b/packages/solid-router/tests/redirect.test.tsx
@@ -2,7 +2,6 @@ import { cleanup, fireEvent, render, screen } from '@solidjs/testing-library'
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
-import invariant from 'tiny-invariant'
import {
Link,
RouterProvider,
@@ -293,9 +292,9 @@ describe('redirect', () => {
expect(router.state.redirect).toBeDefined()
expect(router.state.redirect).toBeInstanceOf(Response)
- invariant(router.state.redirect)
+ const redirectResponse = router.state.redirect!
- expect(router.state.redirect.options).toEqual({
+ expect(redirectResponse.options).toEqual({
_fromLocation: expect.objectContaining({
hash: '',
href: '/',
@@ -346,10 +345,10 @@ describe('redirect', () => {
expect(currentRedirect).toBeDefined()
expect(currentRedirect).toBeInstanceOf(Response)
- invariant(currentRedirect)
- expect(currentRedirect.status).toEqual(307)
- expect(currentRedirect.headers.get('Location')).toEqual('/about')
- expect(currentRedirect.options).toEqual({
+ const redirectResponse = currentRedirect!
+ expect(redirectResponse.status).toEqual(307)
+ expect(redirectResponse.headers.get('Location')).toEqual('/about')
+ expect(redirectResponse.options).toEqual({
_fromLocation: {
external: false,
publicHref: '/',
@@ -360,8 +359,8 @@ describe('redirect', () => {
searchStr: '',
state: {
__TSR_index: 0,
- __TSR_key: currentRedirect.options._fromLocation!.state.__TSR_key,
- key: currentRedirect.options._fromLocation!.state.key,
+ __TSR_key: redirectResponse.options._fromLocation!.state.__TSR_key,
+ key: redirectResponse.options._fromLocation!.state.key,
},
},
href: '/about',
diff --git a/packages/solid-start-client/package.json b/packages/solid-start-client/package.json
index 21d835cac0e..8448041eb76 100644
--- a/packages/solid-start-client/package.json
+++ b/packages/solid-start-client/package.json
@@ -61,9 +61,7 @@
"dependencies": {
"@tanstack/router-core": "workspace:*",
"@tanstack/solid-router": "workspace:*",
- "@tanstack/start-client-core": "workspace:*",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "@tanstack/start-client-core": "workspace:*"
},
"devDependencies": {
"@solidjs/testing-library": "^0.8.10",
diff --git a/packages/start-client-core/package.json b/packages/start-client-core/package.json
index d33f3d260d8..37c39c6907d 100644
--- a/packages/start-client-core/package.json
+++ b/packages/start-client-core/package.json
@@ -85,9 +85,7 @@
"@tanstack/router-core": "workspace:*",
"@tanstack/start-fn-stubs": "workspace:*",
"@tanstack/start-storage-context": "workspace:*",
- "seroval": "^1.4.2",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "seroval": "^1.4.2"
},
"devDependencies": {
"@tanstack/intent": "^0.0.14",
diff --git a/packages/start-client-core/src/client-rpc/serverFnFetcher.ts b/packages/start-client-core/src/client-rpc/serverFnFetcher.ts
index 7d543b1df07..a260928a11f 100644
--- a/packages/start-client-core/src/client-rpc/serverFnFetcher.ts
+++ b/packages/start-client-core/src/client-rpc/serverFnFetcher.ts
@@ -1,11 +1,11 @@
import {
createRawStreamDeserializePlugin,
encode,
+ invariant,
isNotFound,
parseRedirect,
} from '@tanstack/router-core'
import { fromCrossJSON, toJSONAsync } from 'seroval'
-import invariant from 'tiny-invariant'
import { getDefaultSerovalPlugins } from '../getDefaultSerovalPlugins'
import {
TSS_CONTENT_TYPE_FRAMED,
@@ -185,7 +185,15 @@ async function getResponse(fn: () => Promise) {
}
const contentType = response.headers.get('content-type')
- invariant(contentType, 'expected content-type header to be set')
+ if (!contentType) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: expected content-type header to be set',
+ )
+ }
+
+ invariant()
+ }
const serializedByStart = !!response.headers.get(X_TSS_SERIALIZED)
// If the response is serialized by the start server, we need to process it
@@ -239,7 +247,13 @@ async function getResponse(fn: () => Promise) {
result = fromCrossJSON(jsonPayload, { plugins: serovalPlugins! })
}
- invariant(result, 'expected result to be resolved')
+ if (!result) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: expected result to be resolved')
+ }
+
+ invariant()
+ }
if (result instanceof Error) {
throw result
}
diff --git a/packages/start-server-core/package.json b/packages/start-server-core/package.json
index 65d0ac83906..25b4df51153 100644
--- a/packages/start-server-core/package.json
+++ b/packages/start-server-core/package.json
@@ -83,8 +83,7 @@
"@tanstack/start-client-core": "workspace:*",
"@tanstack/start-storage-context": "workspace:*",
"h3-v2": "npm:h3@2.0.1-rc.16",
- "seroval": "^1.4.2",
- "tiny-invariant": "^1.3.3"
+ "seroval": "^1.4.2"
},
"devDependencies": {
"@standard-schema/spec": "^1.0.0",
diff --git a/packages/start-server-core/src/server-functions-handler.ts b/packages/start-server-core/src/server-functions-handler.ts
index 4f5067a7ebd..7b3b34585be 100644
--- a/packages/start-server-core/src/server-functions-handler.ts
+++ b/packages/start-server-core/src/server-functions-handler.ts
@@ -1,9 +1,9 @@
import {
createRawStreamRPCPlugin,
+ invariant,
isNotFound,
isRedirect,
} from '@tanstack/router-core'
-import invariant from 'tiny-invariant'
import {
TSS_FORMDATA_CONTEXT,
X_TSS_RAW_RESPONSE,
@@ -88,10 +88,15 @@ export const handleServerAction = async ({
)
) {
// We don't support GET requests with FormData payloads... that seems impossible
- invariant(
- methodUpper !== 'GET',
- 'GET requests with FormData payloads are not supported',
- )
+ if (methodUpper === 'GET') {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ 'Invariant failed: GET requests with FormData payloads are not supported',
+ )
+ }
+
+ invariant()
+ }
const formData = await request.formData()
const serializedContext = formData.get(TSS_FORMDATA_CONTEXT)
formData.delete(TSS_FORMDATA_CONTEXT)
diff --git a/packages/vue-router/package.json b/packages/vue-router/package.json
index ce142fdfc48..7e98229837b 100644
--- a/packages/vue-router/package.json
+++ b/packages/vue-router/package.json
@@ -78,9 +78,7 @@
"@tanstack/vue-store": "^0.9.2",
"@vue/runtime-dom": "^3.5.25",
"isbot": "^5.1.22",
- "jsesc": "^3.0.2",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "jsesc": "^3.0.2"
},
"devDependencies": {
"@tanstack/intent": "^0.0.14",
diff --git a/packages/vue-router/src/Match.tsx b/packages/vue-router/src/Match.tsx
index ddc4cb83c25..104ec3a2908 100644
--- a/packages/vue-router/src/Match.tsx
+++ b/packages/vue-router/src/Match.tsx
@@ -1,9 +1,8 @@
import * as Vue from 'vue'
-import invariant from 'tiny-invariant'
-import warning from 'tiny-warning'
import {
createControlledPromise,
getLocationChangeInfo,
+ invariant,
isNotFound,
isRedirect,
rootRouteId,
@@ -42,10 +41,15 @@ export const Match = Vue.defineComponent({
props.matchId,
)?.routeId
- invariant(
- routeId,
- `Could not find routeId for matchId "${props.matchId}". Please file an issue!`,
- )
+ if (!routeId) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find routeId for matchId "${props.matchId}". Please file an issue!`,
+ )
+ }
+
+ invariant()
+ }
// Static route-tree check: is this route a direct child of the root?
// parentRoute is set at build time, so no reactive tracking needed.
@@ -187,7 +191,9 @@ export const Match = Vue.defineComponent({
onCatch: (error: Error) => {
// Forward not found errors (we don't want to show the error component for these)
if (isNotFound(error)) throw error
- warning(false, `Error in route match: ${actualMatchId}`)
+ if (process.env.NODE_ENV !== 'production') {
+ console.warn(`Warning: Error in route match: ${actualMatchId}`)
+ }
routeOnCatch.value?.(error)
},
children: content,
@@ -358,12 +364,24 @@ export const MatchInner = Vue.defineComponent({
}
if (match.value.status === 'notFound') {
- invariant(isNotFound(match.value.error), 'Expected a notFound error')
+ if (!isNotFound(match.value.error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: Expected a notFound error')
+ }
+
+ invariant()
+ }
return renderRouteNotFound(router, route.value, match.value.error)
}
if (match.value.status === 'redirected') {
- invariant(isRedirect(match.value.error), 'Expected a redirect error')
+ if (!isRedirect(match.value.error)) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error('Invariant failed: Expected a redirect error')
+ }
+
+ invariant()
+ }
throw router.getMatch(match.value.id)?._nonReactive.loadPromise
}
diff --git a/packages/vue-router/src/Matches.tsx b/packages/vue-router/src/Matches.tsx
index 88c1875550a..b3de324dbe9 100644
--- a/packages/vue-router/src/Matches.tsx
+++ b/packages/vue-router/src/Matches.tsx
@@ -1,5 +1,4 @@
import * as Vue from 'vue'
-import warning from 'tiny-warning'
import { isServer } from '@tanstack/router-core/isServer'
import { useStore } from '@tanstack/vue-store'
import { CatchBoundary } from './CatchBoundary'
@@ -129,11 +128,10 @@ const MatchesInner = Vue.defineComponent({
onCatch:
process.env.NODE_ENV !== 'production'
? (error: Error) => {
- warning(
- false,
- `The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
+ console.warn(
+ `Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,
)
- warning(false, error.message || error.toString())
+ console.warn(`Warning: ${error.message || error.toString()}`)
}
: undefined,
children: childElement,
diff --git a/packages/vue-router/src/fileRoute.ts b/packages/vue-router/src/fileRoute.ts
index 94ae9ccb9fa..e377665307c 100644
--- a/packages/vue-router/src/fileRoute.ts
+++ b/packages/vue-router/src/fileRoute.ts
@@ -1,4 +1,3 @@
-import warning from 'tiny-warning'
import { createRoute } from './route'
import { useMatch } from './useMatch'
@@ -140,10 +139,11 @@ export class FileRoute<
THandlers
> => {
if (process.env.NODE_ENV !== 'production') {
- warning(
- this.silent,
- 'FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
- )
+ if (!this.silent) {
+ console.warn(
+ 'Warning: FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
+ )
+ }
}
const route = createRoute(options as any)
;(route as any).isRoot = false
@@ -177,9 +177,8 @@ export function FileRouteLoader<
>,
) => TLoaderFn {
if (process.env.NODE_ENV !== 'production') {
- warning(
- false,
- `FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
+ console.warn(
+ `Warning: FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
)
}
return (loaderFn) => loaderFn as any
diff --git a/packages/vue-router/src/renderRouteNotFound.tsx b/packages/vue-router/src/renderRouteNotFound.tsx
index 63ec147f7e8..600a66a7f5f 100644
--- a/packages/vue-router/src/renderRouteNotFound.tsx
+++ b/packages/vue-router/src/renderRouteNotFound.tsx
@@ -1,5 +1,4 @@
import * as Vue from 'vue'
-import warning from 'tiny-warning'
import { DefaultGlobalNotFound } from './not-found'
import type { AnyRoute, AnyRouter } from '@tanstack/router-core'
@@ -21,11 +20,12 @@ export function renderRouteNotFound(
return Vue.h(router.options.defaultNotFoundComponent as any, data)
}
- if (process.env.NODE_ENV === 'development') {
- warning(
- route.options.notFoundComponent,
- `A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (Not Found
)`,
- )
+ if (process.env.NODE_ENV !== 'production') {
+ if (!route.options.notFoundComponent) {
+ console.warn(
+ `Warning: A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (Not Found
)`,
+ )
+ }
}
return Vue.h(DefaultGlobalNotFound)
diff --git a/packages/vue-router/src/useMatch.tsx b/packages/vue-router/src/useMatch.tsx
index c7ac0e96b7a..d4d54b02154 100644
--- a/packages/vue-router/src/useMatch.tsx
+++ b/packages/vue-router/src/useMatch.tsx
@@ -1,7 +1,7 @@
import * as Vue from 'vue'
+import { invariant } from '@tanstack/router-core'
import { useStore } from '@tanstack/vue-store'
import { isServer } from '@tanstack/router-core/isServer'
-import invariant from 'tiny-invariant'
import {
injectDummyPendingMatch,
injectPendingMatch,
@@ -87,10 +87,15 @@ export function useMatch<
: undefined
const match = matchStore?.state
- invariant(
- !((opts.shouldThrow ?? true) && !match),
- `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
- )
+ if ((opts.shouldThrow ?? true) && !match) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
+ )
+ }
+
+ invariant()
+ }
if (match === undefined) {
return Vue.ref(undefined) as Vue.Ref<
@@ -151,14 +156,19 @@ export function useMatch<
const hasPendingMatch = opts.from
? Boolean(hasPendingRouteMatch?.value[opts.from!])
: hasPendingNearestMatch.value
- invariant(
- !(
- !hasPendingMatch &&
- !isTransitioning.value &&
- (opts.shouldThrow ?? true)
- ),
- `Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
- )
+ if (
+ !hasPendingMatch &&
+ !isTransitioning.value &&
+ (opts.shouldThrow ?? true)
+ ) {
+ if (process.env.NODE_ENV !== 'production') {
+ throw new Error(
+ `Invariant failed: Could not find ${opts.from ? `an active match from "${opts.from}"` : 'a nearest match!'}`,
+ )
+ }
+
+ invariant()
+ }
return undefined
}
diff --git a/packages/vue-router/src/useRouter.tsx b/packages/vue-router/src/useRouter.tsx
index aa90b01a02f..e0fd91292bb 100644
--- a/packages/vue-router/src/useRouter.tsx
+++ b/packages/vue-router/src/useRouter.tsx
@@ -1,5 +1,4 @@
import * as Vue from 'vue'
-import warning from 'tiny-warning'
import { routerContext } from './routerContext'
import type { AnyRouter, RegisteredRouter } from '@tanstack/router-core'
@@ -7,9 +6,12 @@ export function useRouter(opts?: {
warn?: boolean
}): TRouter {
const value = Vue.inject(routerContext as any, null)
- warning(
- !((opts?.warn ?? true) && !value),
- 'useRouter must be used inside a component!',
- )
+ if (process.env.NODE_ENV !== 'production') {
+ if ((opts?.warn ?? true) && !value) {
+ console.warn(
+ 'Warning: useRouter must be used inside a component!',
+ )
+ }
+ }
return value as any
}
diff --git a/packages/vue-router/tests/redirect.test.tsx b/packages/vue-router/tests/redirect.test.tsx
index fc9a998157e..f198f8adf68 100644
--- a/packages/vue-router/tests/redirect.test.tsx
+++ b/packages/vue-router/tests/redirect.test.tsx
@@ -1,7 +1,6 @@
import { cleanup, fireEvent, render, screen } from '@testing-library/vue'
import { afterEach, describe, expect, test, vi } from 'vitest'
-import invariant from 'tiny-invariant'
import {
Link,
@@ -283,9 +282,9 @@ describe('redirect', () => {
expect(router.state.redirect).toBeDefined()
expect(router.state.redirect).toBeInstanceOf(Response)
- invariant(router.state.redirect)
+ const redirectResponse = router.state.redirect!
- expect(router.state.redirect.options).toEqual({
+ expect(redirectResponse.options).toEqual({
_fromLocation: expect.objectContaining({
hash: '',
href: '/',
@@ -335,9 +334,9 @@ describe('redirect', () => {
expect(currentRedirect).toBeDefined()
expect(currentRedirect).toBeInstanceOf(Response)
- invariant(currentRedirect)
+ const redirectResponse = currentRedirect!
- expect(currentRedirect.options).toEqual({
+ expect(redirectResponse.options).toEqual({
_fromLocation: expect.objectContaining({
hash: '',
href: '/',
diff --git a/packages/vue-start-client/package.json b/packages/vue-start-client/package.json
index c1a6ccab939..5a49f771e19 100644
--- a/packages/vue-start-client/package.json
+++ b/packages/vue-start-client/package.json
@@ -61,9 +61,7 @@
"dependencies": {
"@tanstack/router-core": "workspace:*",
"@tanstack/vue-router": "workspace:*",
- "@tanstack/start-client-core": "workspace:*",
- "tiny-invariant": "^1.3.3",
- "tiny-warning": "^1.0.3"
+ "@tanstack/start-client-core": "workspace:*"
},
"devDependencies": {
"@testing-library/vue": "^8.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 81b0857a537..78b11833717 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8765,9 +8765,6 @@ importers:
tailwind-merge:
specifier: ^2.6.0
version: 2.6.0
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
zod:
specifier: ^3.24.2
version: 3.25.57
@@ -9172,9 +9169,6 @@ importers:
tailwind-merge:
specifier: ^2.6.0
version: 2.6.0
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
zod:
specifier: ^3.24.2
version: 3.25.57
@@ -11762,12 +11756,6 @@ importers:
isbot:
specifier: ^5.1.22
version: 5.1.28
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@testing-library/jest-dom':
specifier: ^6.6.3
@@ -11907,12 +11895,6 @@ importers:
react-dom:
specifier: ^19.2.3
version: 19.2.3(react@19.2.3)
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@testing-library/react':
specifier: ^16.2.0
@@ -11991,12 +11973,6 @@ importers:
seroval-plugins:
specifier: ^1.4.2
version: 1.4.2(seroval@1.4.2)
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@tanstack/intent':
specifier: ^0.0.14
@@ -12056,9 +12032,6 @@ importers:
goober:
specifier: ^2.1.16
version: 2.1.16(csstype@3.1.3)
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
devDependencies:
solid-js:
specifier: 1.9.10
@@ -12259,12 +12232,6 @@ importers:
isbot:
specifier: ^5.1.22
version: 5.1.28
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@solidjs/testing-library':
specifier: ^0.8.10
@@ -12395,12 +12362,6 @@ importers:
solid-js:
specifier: 1.9.10
version: 1.9.10
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@solidjs/testing-library':
specifier: ^0.8.10
@@ -12463,12 +12424,6 @@ importers:
seroval:
specifier: ^1.4.2
version: 1.4.2
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@tanstack/intent':
specifier: ^0.0.14
@@ -12582,9 +12537,6 @@ importers:
seroval:
specifier: ^1.4.2
version: 1.4.2
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
devDependencies:
'@standard-schema/spec':
specifier: ^1.0.0
@@ -12684,12 +12636,6 @@ importers:
jsesc:
specifier: ^3.0.2
version: 3.1.0
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@tanstack/intent':
specifier: ^0.0.14
@@ -12820,12 +12766,6 @@ importers:
'@tanstack/vue-router':
specifier: workspace:*
version: link:../vue-router
- tiny-invariant:
- specifier: ^1.3.3
- version: 1.3.3
- tiny-warning:
- specifier: ^1.0.3
- version: 1.0.3
devDependencies:
'@testing-library/jest-dom':
specifier: ^6.6.3
@@ -24260,9 +24200,6 @@ packages:
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
- tiny-warning@1.0.3:
- resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
-
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@@ -38480,8 +38417,6 @@ snapshots:
tiny-invariant@1.3.3: {}
- tiny-warning@1.0.3: {}
-
tinybench@2.9.0: {}
tinyexec@0.3.2: {}