Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ ZenStack is a TypeScript database toolkit for developing full-stack or backend N
- Automatic CRUD web APIs with adapters for popular frameworks (coming soon)
- Automatic [TanStack Query](https://github.com/TanStack/query) hooks for easy CRUD from the frontend (coming soon)

# What's new with V3
# What's New in V3

ZenStack V3 is a major rewrite of [V2](https://github.com/zenstackhq/zenstack). The biggest change is V3 doesn't have a runtime dependency to Prisma anymore. Instead of working as a big wrapper of Prisma as in V2, V3 made a bold move and implemented the entire ORM engine using [Kysely](https://github.com/kysely-org/kysely), while keeping the query API fully compatible with Prisma.

Expand All @@ -49,7 +49,7 @@ Even without using advanced features, ZenStack offers the following benefits as

> Although ZenStack v3's ORM runtime doesn't depend on Prisma anymore (specifically, `@prisma/client`), it still relies on Prisma to handle database migration. See [database migration](https://zenstack.dev/docs/3.x/orm/migration) for more details.

# Quick start
# Quick Start

- [ORM](./samples/orm): A simple example demonstrating ZenStack ORM usage.
- [Next.js + TanStack Query](./samples/next.js): A full-stack sample demonstrating using TanStack Query to consume ZenStack's automatic CRUD services in a Next.js app.
Expand All @@ -72,7 +72,7 @@ Or, if you have an existing project, use the CLI to initialize it:
npx @zenstackhq/cli@next init
```

### 3. Manual setup
### 3. Setting up manually

Alternatively, you can set it up manually:

Expand Down
6 changes: 4 additions & 2 deletions packages/language/res/stdlib.zmodel
Original file line number Diff line number Diff line change
Expand Up @@ -382,12 +382,14 @@ attribute @map(_ name: String) @@@prisma
attribute @@map(_ name: String) @@@prisma

/**
* Exclude a field from the Prisma Client (for example, a field that you do not want Prisma users to update).
* Exclude a field from the ORM Client (for example, a field that you do not want Prisma users to update).
* The field is still recognized by database schema migrations.
*/
attribute @ignore() @@@prisma

/**
* Exclude a model from the Prisma Client (for example, a model that you do not want Prisma users to update).
* Exclude a model from the ORM Client (for example, a model that you do not want Prisma users to update).
* The model is still recognized by database schema migrations.
*/
attribute @@ignore() @@@prisma

Expand Down
6 changes: 3 additions & 3 deletions packages/orm/src/client/client-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { FindOperationHandler } from './crud/operations/find';
import { GroupByOperationHandler } from './crud/operations/group-by';
import { UpdateOperationHandler } from './crud/operations/update';
import { InputValidator } from './crud/validator';
import { NotFoundError, QueryError } from './errors';
import { createConfigError, createNotFoundError } from './errors';
import { ZenStackDriver } from './executor/zenstack-driver';
import { ZenStackQueryExecutor } from './executor/zenstack-query-executor';
import * as BuiltinFunctions from './functions';
Expand Down Expand Up @@ -223,7 +223,7 @@ export class ClientImpl<Schema extends SchemaDef> {

private async handleProc(name: string, args: unknown[]) {
if (!('procedures' in this.$options) || !this.$options || typeof this.$options.procedures !== 'object') {
throw new QueryError('Procedures are not configured for the client.');
throw createConfigError('Procedures are not configured for the client.');
}

const procOptions = this.$options.procedures as ProceduresOptions<
Expand Down Expand Up @@ -389,7 +389,7 @@ function createModelCrudHandler<Schema extends SchemaDef, Model extends GetModel
const _handler = txClient ? handler.withClient(txClient) : handler;
const r = await _handler.handle(operation, _args);
if (!r && throwIfNoResult) {
throw new NotFoundError(model);
throw createNotFoundError(model);
}
let result: unknown;
if (r && postProcess) {
Expand Down
18 changes: 9 additions & 9 deletions packages/orm/src/client/crud/dialects/base-dialect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type {
SortOrder,
StringFilter,
} from '../../crud-types';
import { InternalError, QueryError } from '../../errors';
import { createConfigError, createInvalidInputError, createNotSupportedError } from '../../errors';
import type { ClientOptions } from '../../options';
import {
aggregate,
Expand Down Expand Up @@ -95,7 +95,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
if (this.supportsDistinctOn) {
result = result.distinctOn(distinct.map((f) => this.eb.ref(`${modelAlias}.${f}`)));
} else {
throw new QueryError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
throw createNotSupportedError(`"distinct" is not supported by "${this.schema.provider.type}" provider`);
}
}

Expand Down Expand Up @@ -482,7 +482,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
}

default: {
throw new InternalError(`Invalid array filter key: ${key}`);
throw createInvalidInputError(`Invalid array filter key: ${key}`);
}
}
}
Expand Down Expand Up @@ -510,10 +510,10 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
.with('Bytes', () => this.buildBytesFilter(fieldRef, payload))
// TODO: JSON filters
.with('Json', () => {
throw new InternalError('JSON filters are not supported yet');
throw createNotSupportedError('JSON filters are not supported yet');
})
.with('Unsupported', () => {
throw new QueryError(`Unsupported field cannot be used in filters`);
throw createInvalidInputError(`Unsupported field cannot be used in filters`);
})
.exhaustive()
);
Expand Down Expand Up @@ -589,7 +589,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
})
.otherwise(() => {
if (throwIfInvalid) {
throw new QueryError(`Invalid filter key: ${op}`);
throw createInvalidInputError(`Invalid filter key: ${op}`);
} else {
return undefined;
}
Expand Down Expand Up @@ -642,7 +642,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
: this.eb(fieldRef, 'like', sql.val(`%${value}`)),
)
.otherwise(() => {
throw new QueryError(`Invalid string filter key: ${key}`);
throw createInvalidInputError(`Invalid string filter key: ${key}`);
});

if (condition) {
Expand Down Expand Up @@ -815,7 +815,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
if (fieldDef.array) {
// order by to-many relation
if (typeof value !== 'object') {
throw new QueryError(`invalid orderBy value for field "${field}"`);
throw createInvalidInputError(`invalid orderBy value for field "${field}"`);
}
if ('_count' in value) {
invariant(
Expand Down Expand Up @@ -1084,7 +1084,7 @@ export abstract class BaseCrudDialect<Schema extends SchemaDef> {
computer = computedFields?.[fieldDef.originModel ?? model]?.[field];
}
if (!computer) {
throw new QueryError(`Computed field "${field}" implementation not provided for model "${model}"`);
throw createConfigError(`Computed field "${field}" implementation not provided for model "${model}"`);
}
return computer(this.eb, { modelAlias });
}
Expand Down
4 changes: 2 additions & 2 deletions packages/orm/src/client/crud/dialects/postgresql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { match } from 'ts-pattern';
import type { BuiltinType, FieldDef, GetModels, SchemaDef } from '../../../schema';
import { DELEGATE_JOINED_FIELD_PREFIX } from '../../constants';
import type { FindArgs } from '../../crud-types';
import { QueryError } from '../../errors';
import type { ClientOptions } from '../../options';
import {
buildJoinPairs,
Expand All @@ -24,6 +23,7 @@ import {
requireModel,
} from '../../query-utils';
import { BaseCrudDialect } from './base-dialect';
import { createInternalError } from '../../errors';

export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect<Schema> {
constructor(schema: Schema, options: ClientOptions<Schema>) {
Expand Down Expand Up @@ -438,7 +438,7 @@ export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDiale
override getFieldSqlType(fieldDef: FieldDef) {
// TODO: respect `@db.x` attributes
if (fieldDef.relation) {
throw new QueryError('Cannot get SQL type of a relation field');
throw createInternalError('Cannot get SQL type of a relation field');
}

let result: string;
Expand Down
8 changes: 4 additions & 4 deletions packages/orm/src/client/crud/dialects/sqlite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { match } from 'ts-pattern';
import type { BuiltinType, FieldDef, GetModels, SchemaDef } from '../../../schema';
import { DELEGATE_JOINED_FIELD_PREFIX } from '../../constants';
import type { FindArgs } from '../../crud-types';
import { QueryError } from '../../errors';
import { createInternalError } from '../../errors';
import {
getDelegateDescendantModels,
getManyToManyRelation,
Expand Down Expand Up @@ -121,7 +121,7 @@ export class SqliteCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect
try {
return JSON.parse(value);
} catch (e) {
throw new QueryError('Invalid JSON returned', e);
throw createInternalError('Invalid JSON returned', undefined, { cause: e });
}
}
return value;
Expand Down Expand Up @@ -376,10 +376,10 @@ export class SqliteCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect
override getFieldSqlType(fieldDef: FieldDef) {
// TODO: respect `@db.x` attributes
if (fieldDef.relation) {
throw new QueryError('Cannot get SQL type of a relation field');
throw createInternalError('Cannot get SQL type of a relation field');
}
if (fieldDef.array) {
throw new QueryError('SQLite does not support scalar list type');
throw createInternalError('SQLite does not support scalar list type');
}

if (this.schema.enums?.[fieldDef.type]) {
Expand Down
Loading
Loading