Persist extention hydration
Hi! First of all, thank you for releasing the new version of the library. I have two questions about how to properly use the persist extension.
Schema example
import { Collection } from '@msw/data'
import { persist } from '@msw/data/extensions/persist'
import { sync } from '@msw/data/extensions/sync'
import { z } from 'zod'
const userSchema = z.object({
id: z.number(),
email: z.email(),
password: z.string(),
})
const wishlistSchema = z.object({
id: z.number(),
get user() {
return userSchema
},
productIds: z.array(z.number()),
})
export async function createDb() {
const users = new Collection({
schema: userSchema,
extensions: [
persist(),
sync(),
],
})
const wishlists = new Collection({
schema: wishlistSchema,
extensions: [persist(), sync()],
})
wishlists.defineRelations(({ one }) => ({
user: one(users),
}))
return {
users,
wishlists,
}
}
////
createDb().then(
db => startDatabaseMigration(db)
)
1 – Asynchronous hydration
If I call a function to seed fixtures from the global scope, queries against the collections always return empty results, since the data is hydrated asynchronously.
export async function startDatabaseMigration() {
const users = db.users.findMany(q => q.where({ id: value => Boolean(value) }))
// users is always an empty array
To work around this, I can add a small delay — but this isn’t obvious from the docs and feels a bit hacky (it might also break logic that expects the collections to be ready synchronously):
export async function startDatabaseMigration() {
+ await new Promise(resolve => setTimeout(resolve, 10))
const users = db.users.findMany(q => q.where({ id: value => Boolean(value) }))
// users is correctly restored from localStorage
Is this the correct approach to handle the issue, or am I misusing the extension?
2 – Hydrating related entities
When I am trying to hydrate a related entity, I get an error saying that the user entity doesn’t exist yet at the time of hydration:
collection-BJduKbwC-….js?v=aa5ed28a:2330 Uncaught (in promise) OperationError$1: Failed to create a new record with initial values: does not match the schema. Please see the schema validation errors above.
at async Promise.all (:5174/index 0)
await in create
(anonymous) @ db.ts:28
With errors like this:
What I’ve discovered is that when closing the browser tab, the user inside wishlists record is not saved. So during the next hydration, the errors above occur:
You can see in the screenshot that there’s no user field.
Here’s how I create the entities:
const user = await db.users.create({ ...userData, id: generateId('user') })
await wait(10)
await db.wishlists.create({
id: generateId('wishlist'),
user,
productIds: [3, 4, 5, 6, 7],
})
On the first run (without reloading the page), everything works correctly:
Is this a bug, or am I doing something wrong?
If needed, I can create a CodePen reproduction for both issues.