Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/TanStack/router
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/start/src/client/createServerFn.ts
  • Loading branch information
tannerlinsley committed Dec 23, 2024
2 parents 3757958 + 405a60a commit 24c75bf
Show file tree
Hide file tree
Showing 120 changed files with 3,673 additions and 291 deletions.
2 changes: 1 addition & 1 deletion docs/framework/react/guide/code-based-routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ const routeTree = rootRoute.addChildren([
])
```

Now both `/layout-a` and `/layout-b` will render the their contents inside of the `LayoutComponent`:
Now both `/layout-a` and `/layout-b` will render their contents inside of the `LayoutComponent`:

```tsx
// URL: /layout-a
Expand Down
27 changes: 27 additions & 0 deletions docs/framework/react/guide/custom-link.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,30 @@ export const CustomLink: LinkComponent<typeof MUILinkComponent> = (props) => {
return <CreatedLinkComponent preload={'intent'} {...props} />
}
```

### Mantine example

```tsx
import * as React from 'react'
import { createLink, LinkComponent } from '@tanstack/react-router'
import { Anchor, AnchorProps } from '@mantine/core'

interface MantineAnchorProps extends Omit<AnchorProps, 'href'> {
// Add any additional props you want to pass to the anchor
}

const MantineLinkComponent = React.forwardRef<
HTMLAnchorElement,
MantineAnchorProps
>((props, ref) => {
return <Anchor ref={ref} {...props} />
})

const CreatedLinkComponent = createLink(MantineLinkComponent)

export const CustomLink: LinkComponent<typeof MantineLinkComponent> = (
props,
) => {
return <CreatedLinkComponent preload="intent" {...props} />
}
```
17 changes: 17 additions & 0 deletions docs/framework/react/guide/scroll-restoration.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,20 @@ function Component() {
)
}
```

## Scroll Behavior

To control the scroll behavior when navigating between pages, you can use the `scrollBehavior` option. This allows you to make the transition between pages instant instead of a smooth scroll. The global configuration of scroll restoration behavior has the same options as those supported by the browser, which are `smooth`, `instant`, and `auto` (see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView#behavior) for more information).

```tsx
import { ScrollRestoration } from '@tanstack/react-router'

function Root() {
return (
<>
<ScrollRestoration scrollBehavior="instant" />
<Outlet />
</>
)
}
```
2 changes: 1 addition & 1 deletion docs/framework/react/start/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: Middleware

## What is Middleware?

Middleware allows you to customized the behavior of server functions created with `createServerFn` with things like shared validation, context, and much more. Middleware can even depend on other middleware to create a chain of operations that are executed hierarchically and in order.
Middleware allows you to customize the behavior of server functions created with `createServerFn` with things like shared validation, context, and much more. Middleware can even depend on other middleware to create a chain of operations that are executed hierarchically and in order.

## What kinds of things can I do with Middleware?

Expand Down
10 changes: 10 additions & 0 deletions e2e/create-start/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules
.DS_Store
dist
dist-ssr
*.local

/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
16 changes: 16 additions & 0 deletions e2e/create-start/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "create-start-e2e",
"private": true,
"type": "module",
"scripts": {
"test:e2e": "playwright test --project=chromium"
},
"devDependencies": {
"@playwright/test": "^1.48.2",
"@tanstack/create-start": "workspace:^",
"get-port-please": "^3.1.2",
"tempy": "^3.1.0",
"terminate": "^2.8.0",
"wait-port": "^1.1.0"
}
}
34 changes: 34 additions & 0 deletions e2e/create-start/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { defineConfig, devices } from '@playwright/test'

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',

reporter: [['line']],
timeout: 60000,
use: {
trace: 'on-first-retry',
},
workers: 1,

// use: {
// /* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://localhost:3001/',
// },

// webServer: {
// command: 'pnpm run dev',
// url: 'http://localhost:3001',
// reuseExistingServer: !process.env.CI,
// stdout: 'pipe',
// },

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
})
38 changes: 38 additions & 0 deletions e2e/create-start/tests/templates/barebones.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { temporaryDirectory } from 'tempy'
import { getRandomPort } from 'get-port-please'
import { unstable_scaffoldTemplate } from '@tanstack/create-start'
import { test } from '../../utils/setup'

// Before running any tests - create the project in the temporary directory
const projectPath = temporaryDirectory()
await unstable_scaffoldTemplate({
cfg: {
packageManager: {
installDeps: true,
packageManager: 'pnpm',
},
git: {
setupGit: false,
},
packageJson: {
type: 'new',
name: 'barebones-test',
},
ide: {
ide: 'vscode',
},
},
targetPath: projectPath,
templateId: 'barebones',
})

const PORT = await getRandomPort()
test.use({ projectPath })
test.use({ port: PORT })
test.use({ baseURL: `http://localhost:${PORT}` })

test.describe('barebones template e2e', () => {
test('Navigating to index page', async ({ page }) => {
await page.goto('/')
})
})
10 changes: 10 additions & 0 deletions e2e/create-start/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"strict": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"target": "ESNext",
"moduleResolution": "Bundler",
"module": "ESNext"
}
}
72 changes: 72 additions & 0 deletions e2e/create-start/utils/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { exec, execSync } from 'node:child_process'
import { test as baseTest } from '@playwright/test'
import terminate from 'terminate/promise'
import waitPort from 'wait-port'

async function _setup(
projectPath: string,
port: number,
): Promise<{
PID: number
ADDR: string
killProcess: () => Promise<void>
deleteTempDir: () => void
}> {
const ADDR = `http://localhost:${port}`

const childProcess = exec(
`VITE_SERVER_PORT=${port} pnpm vinxi dev --port ${port}`,
{
cwd: projectPath,
},
)

childProcess.stdout?.on('data', (data) => {
const message = data.toString()
console.log('Stdout:', message)
})

childProcess.stderr?.on('data', (data) => {
console.error('Stderr:', data.toString())
})

try {
await waitPort({ port, timeout: 30000 }) // Added timeout
} catch (err) {
console.error('Failed to start server:', err)
throw err
}

const PID = childProcess.pid!
const killProcess = async () => {
console.log('Killing process')
try {
await terminate(PID)
} catch (err) {
console.error('Failed to kill process:', err)
}
}
const deleteTempDir = () => execSync(`rm -rf ${projectPath}`)

return { PID, ADDR, killProcess, deleteTempDir }
}

type SetupApp = Awaited<ReturnType<typeof _setup>>

export const test = baseTest.extend<{
setupApp: SetupApp
projectPath: string
port: number
ensureServer: void
}>({
projectPath: ['', { option: true }],
port: [0, { option: true }],
ensureServer: [
async ({ projectPath, port }, use) => {
const setup = await _setup(projectPath, port)
await use()
await setup.killProcess()
},
{ auto: true },
],
})
63 changes: 63 additions & 0 deletions e2e/start/basic/app/routes/-server-fns/allow-fn-return-null.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* This exported component checks whether the server function can
* return null without throwing an error or returning something else.
* @link https://github.com/TanStack/router/issues/2776
*/

import * as React from 'react'
import { createServerFn } from '@tanstack/start'

const $allow_return_null_getFn = createServerFn().handler(async () => {
return null
})
const $allow_return_null_postFn = createServerFn({ method: 'POST' }).handler(
async () => {
return null
},
)

export function AllowServerFnReturnNull() {
const [getServerResult, setGetServerResult] = React.useState<any>('-')
const [postServerResult, setPostServerResult] = React.useState<any>('-')

return (
<div className="p-2 border m-2 grid gap-2">
<h3>Allow ServerFn to return `null`</h3>
<p>
This component checks whether the server function can return null
without throwing an error.
</p>
<div>
It should return{' '}
<code>
<pre>{JSON.stringify(null)}</pre>
</code>
</div>
<p>
{`GET: $allow_return_null_getFn returns`}
<br />
<span data-testid="allow_return_null_getFn-response">
{JSON.stringify(getServerResult)}
</span>
</p>
<p>
{`POST: $allow_return_null_postFn returns`}
<br />
<span data-testid="allow_return_null_postFn-response">
{JSON.stringify(postServerResult)}
</span>
</p>
<button
data-testid="test-allow-server-fn-return-null-btn"
type="button"
className="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
onClick={() => {
$allow_return_null_getFn().then(setGetServerResult)
$allow_return_null_postFn().then(setPostServerResult)
}}
>
Test Allow Server Fn Return Null
</button>
</div>
)
}
2 changes: 2 additions & 0 deletions e2e/start/basic/app/routes/server-fns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createFileRoute } from '@tanstack/react-router'

import { ConsistentServerFnCalls } from './-server-fns/consistent-fn-calls'
import { MultipartServerFnCall } from './-server-fns/multipart-formdata-fn-call'
import { AllowServerFnReturnNull } from './-server-fns/allow-fn-return-null'

export const Route = createFileRoute('/server-fns')({
component: RouteComponent,
Expand All @@ -13,6 +14,7 @@ function RouteComponent() {
<>
<ConsistentServerFnCalls />
<MultipartServerFnCall />
<AllowServerFnReturnNull />
</>
)
}
4 changes: 4 additions & 0 deletions e2e/start/basic/app/styles/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
@tailwind utilities;

@layer base {
html {
color-scheme: light dark;
}

html,
body {
@apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200;
Expand Down
20 changes: 20 additions & 0 deletions e2e/start/basic/tests/base.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,3 +192,23 @@ test('env-only functions can only be called on the server or client respectively
'client got: hello',
)
})

test.only('Server function can return null for GET and POST calls', async ({
page,
}) => {
await page.goto('/server-fns')

await page.waitForLoadState('networkidle')
await page.getByTestId('test-allow-server-fn-return-null-btn').click()
await page.waitForLoadState('networkidle')

// GET call
await expect(
page.getByTestId('allow_return_null_getFn-response'),
).toContainText(JSON.stringify(null))

// POST call
await expect(
page.getByTestId('allow_return_null_postFn-response'),
).toContainText(JSON.stringify(null))
})
4 changes: 2 additions & 2 deletions examples/react/authenticated-routes/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"start": "vite"
},
"dependencies": {
"@tanstack/react-router": "^1.91.2",
"@tanstack/router-devtools": "^1.91.2",
"@tanstack/react-router": "^1.92.3",
"@tanstack/router-devtools": "^1.92.3",
"@tanstack/router-plugin": "^1.91.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
4 changes: 2 additions & 2 deletions examples/react/basic-default-search-params/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
},
"dependencies": {
"@tanstack/react-query": "^5.62.3",
"@tanstack/react-router": "^1.91.2",
"@tanstack/router-devtools": "^1.91.2",
"@tanstack/react-router": "^1.92.3",
"@tanstack/router-devtools": "^1.92.3",
"redaxios": "^0.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
Loading

0 comments on commit 24c75bf

Please sign in to comment.