[How To?] Create a record in database on form submission...

I have an application using trpc, Cloudfare D1 database, and trpc. I am trying to use a tamagui form component to insert a record into the database. My trpc route:
export const carsRouter = router({
all: publicProcedure.query(async ({ ctx }) => {
const { db } = ctx
const allCars = await db.select().from(CarTable).all()
return allCars
}),
create: publicProcedure
.input((raw) => parse(CarSchema, raw))
.mutation(async ({ ctx, input }) => {
const { db } = ctx
await db.insert(CarTable).values(input).run()
}),
})
export const carsRouter = router({
all: publicProcedure.query(async ({ ctx }) => {
const { db } = ctx
const allCars = await db.select().from(CarTable).all()
return allCars
}),
create: publicProcedure
.input((raw) => parse(CarSchema, raw))
.mutation(async ({ ctx, input }) => {
const { db } = ctx
await db.insert(CarTable).values(input).run()
}),
})
My drizzle table schema:
export const CarTable = sqliteTable('Car', {
id: integer('id').primaryKey({ autoIncrement: true }),
uuid: binary('uuid', { length: 16 }).default('hex(randomblob(16))').unique(), // Generate a random 16-byte binary string
make: text('make'),
model: text('model'),
year: integer('year'),
color: text('color'),
price: real('price'),
mileage: integer('mileage'),
fuelType: text('fuelType'),
transmission: text('transmission'),
})
export const CarTable = sqliteTable('Car', {
id: integer('id').primaryKey({ autoIncrement: true }),
uuid: binary('uuid', { length: 16 }).default('hex(randomblob(16))').unique(), // Generate a random 16-byte binary string
make: text('make'),
model: text('model'),
year: integer('year'),
color: text('color'),
price: real('price'),
mileage: integer('mileage'),
fuelType: text('fuelType'),
transmission: text('transmission'),
})
My form component:
export const VirtualizedListScreen = (): React.ReactNode => {
const [make, setMake] = useState("");

const createCar = trpc.car.create.useMutation({
onSuccess: () => {
console.log("create post success")
/* router.refresh();
setName(""); */
},
onError: (e) => {
console.log("Error", e)
}
});

return (
<YStack fullscreen f={1}>

<Form
onSubmit={() => {
createCar.mutate({ make, uuid: 123456 });
}}
>
<Input
placeholder="Title"
value={make}
onChangeText={setMake}
/>
<Form.Trigger asChild>

<Button />
</Form.Trigger>
</Form>
{carsListLayout}
</YStack>
)
}
export const VirtualizedListScreen = (): React.ReactNode => {
const [make, setMake] = useState("");

const createCar = trpc.car.create.useMutation({
onSuccess: () => {
console.log("create post success")
/* router.refresh();
setName(""); */
},
onError: (e) => {
console.log("Error", e)
}
});

return (
<YStack fullscreen f={1}>

<Form
onSubmit={() => {
createCar.mutate({ make, uuid: 123456 });
}}
>
<Input
placeholder="Title"
value={make}
onChangeText={setMake}
/>
<Form.Trigger asChild>

<Button />
</Form.Trigger>
</Form>
{carsListLayout}
</YStack>
)
}
When i click the form button, i get a 500 internal error on api/trpc side. Can someone tell me what I am doing wrong, i feel like its obvious but im not getting it.
2 Replies
Trader Launchpad
Actually, looking now i can see an error:
uuid3.replace is not a function
uuid3.replace is not a function
on the trpc call. I have a uuid field I created that is supposed to work with sqlite. Ill remove it and try to insert a record just using basic id and report back. If anyone has an implementation of binary uuids in sqlite id love to see it. removed the uuid database column and all works as expected. Its some error im my implementation of uuids in sqlite, not a trpc issue. if anyone has a method for storing uuids in a cloudflare d1 database, sqlite, let me know
Dan
Dan7mo ago
Just searching through for something else but stumbled across your message. Example of sqlite table for cloudflare:
export const times = sqliteTable('times', {
id: text('id')
.notNull()
.primaryKey()
.$default(() => crypto.randomUUID()),
updatedAt: integer('updated_at', { mode: 'timestamp' })
.notNull()
.$default(() => new Date()),
createdAt: integer('created_at', { mode: 'timestamp' })
.notNull()
.$default(() => new Date()),
location: text('location').notNull(),
content: text('content', { mode: 'json' }).notNull().$type<TimeContent>(),
});
export const times = sqliteTable('times', {
id: text('id')
.notNull()
.primaryKey()
.$default(() => crypto.randomUUID()),
updatedAt: integer('updated_at', { mode: 'timestamp' })
.notNull()
.$default(() => new Date()),
createdAt: integer('created_at', { mode: 'timestamp' })
.notNull()
.$default(() => new Date()),
location: text('location').notNull(),
content: text('content', { mode: 'json' }).notNull().$type<TimeContent>(),
});
It's not as performant as uuid on postgres but the purpose to use uuid in my case is to avoid that people can guess a sequence. If there would be a need for a sortable id based on time, you could use uuidv7, there are some implementations, e.g. https://github.com/LiosK/uuidv7, but they are roughly 4x slower than uuid4.