Skip to content

ZenStack Release v3.9.0

Latest

Choose a tag to compare

@github-actions github-actions released this 03 Aug 14:18
8b4d280

New Features

Parameterized Computed Fields

Computed fields can now declare typed parameters, with arguments supplied at query time wherever the field is used. This makes computed fields vastly more flexible — e.g., you can let the client control how a dynamic value is calculated. Contributed by @evgenovalov 🎉. doc

model User {
    id    Int    @id @default(autoincrement())
    posts Post[]
    recentPostCount(since: DateTime) Int @computed
}
const db = new ZenStackClient(schema, {
    dialect,
    computedFields: {
        User: {
            // query-time arguments are passed as the 3rd parameter
            recentPostCount: (eb, ctx, args) =>
                eb
                    .selectFrom('Post')
                    .whereRef('Post.authorId', '=', sql.ref(`${ctx.modelAlias}.id`))
                    .where('Post.createdAt', '>=', args.since)
                    .select(({ fn }) => fn.countAll().as('count')),
        },
    },
});

// `args` is plain data, so it can come directly from a client request
await db.user.findMany({
    orderBy: { recentPostCount: { args: { since }, sort: 'desc' } },
});

Parameterized computed fields are supported in select, include, where, orderBy, aggregate, and groupBy.

Exact Query Argument Typing

TypeScript 6 & 7 changed how excessive properties are checked for function parameters inferred from generics. As a result, unknown keys passed to ZenStack queries are often silently allowed at type checking time, but later triggers runtime validation errors.

The new opt-in typing.exactQueryArgs client option rejects unknown properties recursively — across nested relations, where, select, include, orderBy, and nested mutation inputs. Contributed by @olup 🙏.

const db = new ZenStackClient(schema, {
    dialect,
    typing: { exactQueryArgs: true },
});

// ✗ compile-time error: unknown property `emial`
await db.user.findMany({ where: { activated: true, emial: 'a@b.com' } });

The option is off by default since the extra checking has a schema-dependent type-checking cost.

Bootstrapping Studio Without a Schema

zen studio now accepts an --introspect flag that introspects your database to generate a schema on the fly when no schema file is found — so you can point Studio at an existing database and start browsing right away.

npx zen studio --introspect

Fixes and Improvements

  • [orm] Fixed enum field filters inside typed JSON fields being incorrectly compared as raw JSON #2755
  • [orm] Fixed to-one relation filters missing the delegate base join for polymorphic models #2768
  • [policy] Implicit many-to-many join table deletes are now rejected when a participant side is not updatable #2752
  • [language] Added per-provider native type mapping diagnostics so invalid @db.* usages are caught at compile time by @sanny-io #2759
  • [language] Fixed @db.TinyInt not being allowed on Boolean fields #2758
  • [language] Native type mappings are now renamed to match the datasource during Prisma schema generation by @sanny-io
  • [language] Fixed unnamed relations resolving to the wrong opposite field #2757
  • [cli] Fixed db pull missing relation names when a model has both a to-one and a to-many relation to the same model
  • [cli] Fixed the CLI silently exiting with code zero when the version-check fetch stalls

Full Changelog: v3.8.3...v3.9.0