-
Notifications
You must be signed in to change notification settings - Fork 48
Add TrailBase integration and example #228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: fc889b1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good!
BTW, thinking about this PR made me realize we really should have collection types be in their own packages so e.g. if you want to do a major release you can #235
We'll be migrating the other packages in the next day or two so you can just move this PR to create a new package.
Sounds good. I was thinking the same, let alone when adding the backend-specific dependency.
If I understood correctly, we'll table this review until the split has happened for me to rebase? Sounds good, just ping this PR and I'll get the train rolling. Did you think about the example, should we handle it in a follow-up? Thanks! |
The refactor is merged so you can now move your code to a |
Awesome! Moved to separate package. |
Great! I also refactored the example so you can easily add a trail base version. Could you look at doing that? The docker backend perhaps could have a trail base setup too? |
Sure can do. Quick questions:
|
Yeah same example. It's meant to be an omnibus example so easily see every collection type. And yes, one command to start all of them. And yes in this pr as that'll make it easier to test. |
I added TrailBase to the example. I tried to fumble my way through...
|
hmm interesting — you're using the zod schemas from drizzle it looks like? So you should use zod schemas consistent with the trailblaze schema? I suppose you can't have Date types w/ sqlite? |
That my understanding, at first I tried to make mine compatible because I didn't necessarily want to change the downstream code.
I guess so.
SQLite has a DATETIME type, which internally is just an INT64. That said, for type-safety reasons TrailBase requires STRICT mode (see migrations), which doesn't allow DATETIME. W/o STRICT, types are merely affinities and SQLite let's you stick any value into any column :) |
Ok — yeah the other collections serialize & deserialize to/from Date objects — I imagine most people might want that for Trailblaze? Perhaps you could add a |
That's an interesting proposal. I would certainly love not to to diverge the downstream code of the example. Could you elaborate a bit how this could look like, is there any precedent for me to look at? Thanks EDIT: Would this just be two functions: parser: (record: Record) -> TItem,
serialize: (item: TItem) -. Record, ? If so, yeah, yeah I'll do that. It will certainly be a good starting point. |
Ok, I found
INTEGER as opposed to PG TIMESTAMPZ .
Anyway, it works now 🎉 . Do you think this is a workable starting point? |
Nice! Yeah, parsing/serializing the whole row works — perhaps doing it per column would be better though as for big tables, it'd be tedious to have to pass through all the untouched stuff. Electric has a parser by pg type as you found. |
I like that, I'm just not sure my TS foo is strong enough. I'm aware that it can render Doom, but how would I define/infer a type type TItem = {
id: string;
created: Date;
}
type TRecord = {
id: string;
created: number;
}
type Parse = {
id?: (id: string) => string;
created: (id: number) => Date;
}
function parse(parse: Parse, record: Partial<TRecord> | Record) : Partial<TItem> | TItem; Instead I rewrote the serialize/parse implementations to only explicit set the relevant fields. Do you think this could be a workable starting point? {
parse: (record: Todo): SelectTodo => ({
...record,
created_at: new Date(record.created_at * 1000),
updated_at: new Date(record.updated_at * 1000),
}),
}
My bad. Fixed TrailBase-TanstackDB.mp4 |
…changing downstream example code.
No you have to test it in the same browser. Screen.Recording.2025-07-16.at.6.39.01.AM.mp4 |
I'm not very good at types either which is why I ask Claude 😆 This is what it came up with: // Parser type: takes input values and converts them to the target type
type Parser<T, InputType = unknown> = {
[K in keyof T]?: (value: InputType) => T[K];
};
// Serializer type: takes the typed values and converts them to output format
type Serializer<T, OutputType = string> = {
[K in keyof T]?: (value: T[K]) => OutputType;
}; |
Did you update and rebuild? I force-pushed an update that should fix your issue. In theory at least :hide: |
ah oops! I ran It's all working now :-D Let's get the parser/serializer slimmed down so you only specify what you actually want changed & then I think we're ready to go! |
…records and vice-versa on the per-key level. One downside of this approach is that you always have to specify serialize/parse because I cannot be bothered to make them optional only if no conversions are needed.
I should have been more clear about knowing types well enough that I suspect that it's not trivial. No offense to Claude, would still love to meet them over a beverage and talk about their outlook on humanity 🙃 (There might be a simpler way but that's the easiest I could come up with) I did do the gymnastics now. It's not pretty. They should be doing what you were asking for but now there's always a parse/serialize parameter needed. Otherwise the gymnastics get even worse. The more positive way to look at it is that previously it wasn't properly type-safe and now it is 🤷♀️ |
hmm why can't we make parse/serialize optional? |
Because they can only be optional when TItem and TRecord are fully
compatible.
…On Wed, 16 Jul 2025, 18:35 Kyle Mathews, ***@***.***> wrote:
*KyleAMathews* left a comment (TanStack/db#228)
<#228 (comment)>
hmm why can't we make parse/serialize optional?
—
Reply to this email directly, view it on GitHub
<#228 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAA3K4WJ6X6TTNRFATZJ7F33IZ5OTAVCNFSM6AAAAACA2DIAN6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTANZZGM4TOOJQG4>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
👍 works for me! Excited to get this out! Finishing up some other stuff but I'll get this merged and released a bit later today 🚀 |
Yay 🎉 - It was very fun working with you - looking forward to more. PS: We can make |
TypeScript always is haha. It was fun working with you too! Hopefully TanStack/DB is a super nice addition for your community. I'll tweet it out too — are you / trailbase on the various socials? |
I can lookup my Twitter handle in a bit, I don't think I've ever used it 😇.
Quick question, would you mind if I also update the example readme to
clarify Migrations and point out the admin dash?
Thanks again
…On Wed, 16 Jul 2025, 18:49 Kyle Mathews, ***@***.***> wrote:
*KyleAMathews* left a comment (TanStack/db#228)
<#228 (comment)>
It's just just more gymnastics
TypeScript always is haha.
It was fun working with you too! Hopefully TanStack/DB is a super nice
addition for your community. I'll tweet it out too — are you / trailbase on
the various socials?
—
Reply to this email directly, view it on GitHub
<#228 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAA3K4R7H2RFH27TEK4E6HD3IZ7BVAVCNFSM6AAAAACA2DIAN6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTANZZGQZTIOJRGM>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Yeah sure push away. Just lemme know when it's ready |
That turned out to be pretty minor 😅 . Feel free to change it as you see fit. All good from my side. My pristine twitter handle is @trailbase_io (in case that's what you were asking for otherwise no need to mention 🤷♀️ ). Last question, will you take care of publishing the npm package or would you rather have me do that? (not sure if there's some namespacing issue for the package) Thanks again. This was fun, I'm very excited 🙏 🥳 |
- Fix Promise resolver implementation in test setup - Remove unnecessary async keywords from mock functions without await - Ensure proper Promise return types for mock implementations - Fix third test function to not be async when no await is used 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
@tanstack/db-example-react-todo @tanstack/db
@tanstack/electric-db-collection
@tanstack/query-db-collection
@tanstack/react-db
@tanstack/trailbase-db-collection
@tanstack/vue-db
commit: |
trailbase-demo.mp4you need to rebuild your admin w/ db to get realtime updates 😆 |
You may be joking but the admin refresh does feel incredibly jarring 👀 😅 |
I've also started working on an example, as you suggested, but wanted to send out an RFC early.
Don't hold back. Let me know if this is going roughly the expected direction. If so, also let me know how you'd like to handle a potential example, e.g. should it be part of the same PR, should it be a full replica of the todo example?
Thanks!