Skip to content

[Feature Request] Split schema into selectSchema, insertSchema, updateSchema for granular control #1115

@kvnwolf

Description

@kvnwolf

Problem

Currently, the schema property is used for both validation (on mutations) and type inference, but transformations are not applied to data coming from sync (e.g., ElectricSQL).

This was previously reported in #396 - the schema transforms work for insert/update but not for data received from the sync stream.

Example:

const schema = z.object({
  id: z.string(),
  createdAt: z.string().transform(val => new Date(val)), // Transform string → Date
});

// Expected: createdAt is Date
// Actual: createdAt is still string (from Electric sync)

Proposal

Replace the single schema property with granular schemas:

electricCollectionOptions({
  // Schema for transforming/validating data FROM sync (select/read)
  selectSchema: z.object({
    id: z.string(),
    message: z.string(),
    createdAt: z.string().transform(val => new Date(val)),
  }),
  
  // Schema for validating data on insert (with defaults)
  insertSchema: z.object({
    id: z.string().default(() => crypto.randomUUID()),
    message: z.string().min(1),
    createdAt: z.date().default(() => new Date()),
  }),
  
  // Schema for validating data on update (optional, falls back to insertSchema)
  updateSchema: z.object({
    message: z.string().min(1).optional(),
  }),
})

Benefits

  1. selectSchema would actually transform sync data (solving Types are incorrect for schema, where input & output are different #396)
  2. insertSchema can have stricter validation (required fields, defaults)
  3. updateSchema can have partial/optional fields for updates
  4. Clear separation of concerns
  5. Similar pattern to PowerSync's deserializationSchema

Alternative

If splitting into 3 schemas is too complex, at minimum add deserializationSchema (like PowerSync has) to transform data from the sync stream.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions