TypeORM with TanStack start
I have defined very simple code with TypeORM
Then i use it in loader of a component
import { User } from './User'
import { createServerOnlyFn } from '@tanstack/react-start'
import { AppDataSource } from './AppDataSource'
export const createNewUser = createServerOnlyFn(async () => {
const userRepository = AppDataSource.getRepository(User)
const user = new User()
user.firstName = 'Timber'
user.lastName = 'Saw'
user.age = 25
await userRepository.save(user)
const allUsers = await userRepository.find()
// find by id
const firstUser = await userRepository.findOneBy({
id: 1,
})
// find by firstName and lastName
const timber = await userRepository.findOneBy({
firstName: 'Timber',
lastName: 'Saw',
})
// await userRepository.remove(timber)
})
import { User } from './User'
import { createServerOnlyFn } from '@tanstack/react-start'
import { AppDataSource } from './AppDataSource'
export const createNewUser = createServerOnlyFn(async () => {
const userRepository = AppDataSource.getRepository(User)
const user = new User()
user.firstName = 'Timber'
user.lastName = 'Saw'
user.age = 25
await userRepository.save(user)
const allUsers = await userRepository.find()
// find by id
const firstUser = await userRepository.findOneBy({
id: 1,
})
// find by firstName and lastName
const timber = await userRepository.findOneBy({
firstName: 'Timber',
lastName: 'Saw',
})
// await userRepository.remove(timber)
})
export const Route = createFileRoute('/test-data-from-db')({
component: RouteComponent,
// Loaders run on server (unless defined otherwise with disabling SSR
// or SPA mode). Database connections (queries) should always run on server
// to not leak connection details to client.
loader: async () => {
const testData = await sql.query('select * from public.test_table')
await createNewUser()
return { dataFetchedWithNeonSdk: testData }
},
})
export const Route = createFileRoute('/test-data-from-db')({
component: RouteComponent,
// Loaders run on server (unless defined otherwise with disabling SSR
// or SPA mode). Database connections (queries) should always run on server
// to not leak connection details to client.
loader: async () => {
const testData = await sql.query('select * from public.test_table')
await createNewUser()
return { dataFetchedWithNeonSdk: testData }
},
})
5 Replies
equal-aquaOP•2mo ago
Then i get error
[ERROR] No matching export in "node_modules/unenv/dist/runtime/npm/debug.mjs" for import "debug"
node_modules/typeorm/browser/logger/DebugLogger.js:2:9:
2 │ import { debug } from "debug";
╵ ~~~~~
at failureErrorWithLog (C:\Users\MT\source\repos\react-samples\tanstack-start\node_modules\esbuild\lib\main.js:1467:15)
at C:\Users\MT\source\repos\react-samples\tanstack-start\node_modules\esbuild\lib\main.js:926:25
at C:\Users\MT\source\repos\react-samples\tanstack-start\node_modules\esbuild\lib\main.js:1345:9
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
errors: [Getter/Setter],
warnings: [Getter/Setter]
[ERROR] No matching export in "node_modules/unenv/dist/runtime/npm/debug.mjs" for import "debug"
node_modules/typeorm/browser/logger/DebugLogger.js:2:9:
2 │ import { debug } from "debug";
╵ ~~~~~
at failureErrorWithLog (C:\Users\MT\source\repos\react-samples\tanstack-start\node_modules\esbuild\lib\main.js:1467:15)
at C:\Users\MT\source\repos\react-samples\tanstack-start\node_modules\esbuild\lib\main.js:926:25
at C:\Users\MT\source\repos\react-samples\tanstack-start\node_modules\esbuild\lib\main.js:1345:9
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
errors: [Getter/Setter],
warnings: [Getter/Setter]
genetic-orange•2mo ago
loaders run not only on the server
they also run on the client after SSR
so they must be isomorphic
if you want it to always run on the server, wrap the logic in createServerFn
equal-aquaOP•2mo ago
This generated the same error
this also does not seem to work (with iseServerFn)
what is recommended SDK for databases in tanstack start?
Neon has own SDK, but it uses Postgres under the hood, so TypeORM could be used, but it's causing problems..
import { createServerFn } from '@tanstack/react-start'
import { AppDataSource } from './AppDataSource'
import { User } from './User'
export const createNewUser = createServerFn().handler(async () => {
const userRepository = AppDataSource.getRepository(User)
// example how to save DM entity
const user = new User()
user.firstName = 'Timber'
user.lastName = 'Saw'
user.isActive = true
await userRepository.save(user)
// example how to remove DM entity
// await userRepository.remove(user)
// example how to load DM entities
// const users = await userRepository.find({ skip: 2, take: 5 })
// const newUsers = await userRepository.findBy({ isActive: true })
// const timber = await userRepository.findOneBy({
// firstName: 'Timber',
// lastName: 'Saw',
// })
})
import { createServerFn } from '@tanstack/react-start'
import { AppDataSource } from './AppDataSource'
import { User } from './User'
export const createNewUser = createServerFn().handler(async () => {
const userRepository = AppDataSource.getRepository(User)
// example how to save DM entity
const user = new User()
user.firstName = 'Timber'
user.lastName = 'Saw'
user.isActive = true
await userRepository.save(user)
// example how to remove DM entity
// await userRepository.remove(user)
// example how to load DM entities
// const users = await userRepository.find({ skip: 2, take: 5 })
// const newUsers = await userRepository.findBy({ isActive: true })
// const timber = await userRepository.findOneBy({
// firstName: 'Timber',
// lastName: 'Saw',
// })
})
function RouteComponent() {
const createNewUserFn = useServerFn(createNewUser)
const data = Route.useLoaderData()
return (
<div className="[&_pre]:bg-gray-200 [&_h1]:text-3xl [&_h1]:font-bold [&_h1]:m-5 p-10 [&_*]:p-2 [&_button]:border [&_button]:border-black [&_button]:cursor-pointer [&_button]:p-2 [&_button]:rounded-2xl [&_button]:active:scale-95 [&_h2]:text-2xl">
<h1>Hello "/test-data-from-db"!</h1>
<p>
Below is example data from test table from database created with{' '}
<a
className="underline text-blue-600 hover:text-blue-800 transition-colors"
href="https://neon.com/"
>
Neon
</a>
</p>
{!data ? (
<p>No data in db or some other error</p>
) : (
<ul>
{data.map((x: any) => (
<li>
id = {x.id} | test_column = {x.test_column}
</li>
))}
</ul>
)}
<h1>TypeORM</h1>
<p>
For testing, TypeORM was used here. Click the below button to
create some data in DB.
</p>
<button onClick={() => createNewUserFn()}>Create User!</button>
</div>
)
}
function RouteComponent() {
const createNewUserFn = useServerFn(createNewUser)
const data = Route.useLoaderData()
return (
<div className="[&_pre]:bg-gray-200 [&_h1]:text-3xl [&_h1]:font-bold [&_h1]:m-5 p-10 [&_*]:p-2 [&_button]:border [&_button]:border-black [&_button]:cursor-pointer [&_button]:p-2 [&_button]:rounded-2xl [&_button]:active:scale-95 [&_h2]:text-2xl">
<h1>Hello "/test-data-from-db"!</h1>
<p>
Below is example data from test table from database created with{' '}
<a
className="underline text-blue-600 hover:text-blue-800 transition-colors"
href="https://neon.com/"
>
Neon
</a>
</p>
{!data ? (
<p>No data in db or some other error</p>
) : (
<ul>
{data.map((x: any) => (
<li>
id = {x.id} | test_column = {x.test_column}
</li>
))}
</ul>
)}
<h1>TypeORM</h1>
<p>
For testing, TypeORM was used here. Click the below button to
create some data in DB.
</p>
<button onClick={() => createNewUserFn()}>Create User!</button>
</div>
)
}
genetic-orange•2mo ago
what does not work here?
a minimal complete example would be helpful
equal-aquaOP•2mo ago
Of course, will work on it today
I could get it to work. The trick was to place crucial
import 'reflect-metadata' in server entry point. Now i got it working with server Fn, but will explore other possibilities.
Thanks for the support Martin, helpful as always
However, this i could achieve with new project, with the one that i am using neon SDK, it does not work. I get inconsistent errors either about serverFn failures or again about this "debug import" not found