@zenstackhq/orm 3.5.2 → 3.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _zenstackhq_schema from '@zenstackhq/schema';
2
- import { SchemaDef, GetModels, ScalarFields, ForeignKeyFields, GetModelFields, FieldHasDefault, GetModelFieldType, ModelFieldIsOptional, GetModelField, NonRelationFields, GetModel, ProcedureDef, BuiltinType, FieldDef, ModelDef, DataSourceProviderType, IsDelegateModel, RelationFields, FieldIsArray, RelationFieldType, FieldIsRelation, GetEnums, GetEnum, GetTypeDefs, GetTypeDefFields, GetTypeDefField, TypeDefFieldIsOptional, GetTypeDefFieldType, TypeDefFieldIsArray, UpdatedAtInfo, FieldIsDelegateDiscriminator, FieldType, RelationInfo, Expression as Expression$1, LiteralExpression, ArrayExpression, FieldExpression, MemberExpression, BinaryExpression, UnaryExpression, CallExpression, BindingExpression, ThisExpression, NullExpression } from '@zenstackhq/schema';
2
+ import { SchemaDef, GetModels, ScalarFields, ForeignKeyFields, GetModelFields, FieldHasDefault, GetModelFieldType, ModelFieldIsOptional, GetModelField, NonRelationFields, GetModel, ProcedureDef, BuiltinType, FieldDef, ModelDef, DataSourceProviderType, IsDelegateModel, RelationFields, FieldIsArray, RelationFieldType, FieldIsRelation, GetEnums, GetEnum, GetTypeDefs, GetTypeDefFields, GetTypeDefField, TypeDefFieldIsOptional, GetTypeDefFieldType, TypeDefFieldIsArray, GetModelDiscriminator, GetSubModels, UpdatedAtInfo, FieldIsDelegateDiscriminator, FieldType, RelationInfo, Expression as Expression$1, LiteralExpression, ArrayExpression, FieldExpression, MemberExpression, BinaryExpression, UnaryExpression, CallExpression, BindingExpression, ThisExpression, NullExpression } from '@zenstackhq/schema';
3
3
  import * as kysely from 'kysely';
4
4
  import { Kysely, OperationNodeVisitor, OperationNode, SelectQueryNode, SelectionNode, ColumnNode, AliasNode, TableNode, FromNode, ReferenceNode, AndNode, OrNode, ValueListNode, ParensNode, JoinNode, RawNode, WhereNode, InsertQueryNode, DeleteQueryNode, ReturningNode, CreateTableNode, AddColumnNode, ColumnDefinitionNode, DropTableNode, OrderByNode, OrderByItemNode, GroupByNode, GroupByItemNode, UpdateQueryNode, ColumnUpdateNode, LimitNode, OffsetNode, OnConflictNode, OnDuplicateKeyNode, CheckConstraintNode, DataTypeNode, SelectAllNode, IdentifierNode, SchemableIdentifierNode, ValueNode, PrimitiveValueListNode, OperatorNode, CreateIndexNode, DropIndexNode, ListNode, PrimaryKeyConstraintNode, UniqueConstraintNode, ReferencesNode, WithNode, CommonTableExpressionNode, CommonTableExpressionNameNode, HavingNode, CreateSchemaNode, DropSchemaNode, AlterTableNode, DropColumnNode, RenameColumnNode, AlterColumnNode, ModifyColumnNode, AddConstraintNode, DropConstraintNode, ForeignKeyConstraintNode, CreateViewNode, DropViewNode, GeneratedNode, DefaultValueNode, OnNode, ValuesNode, SelectModifierNode, CreateTypeNode, DropTypeNode, ExplainNode, DefaultInsertValueNode, AggregateFunctionNode, OverNode, PartitionByNode, PartitionByItemNode, SetOperationNode, BinaryOperationNode, UnaryOperationNode, UsingNode, FunctionNode, CaseNode, WhenNode, JSONReferenceNode, JSONPathNode, JSONPathLegNode, JSONOperatorChainNode, TupleNode, MergeQueryNode, MatchedNode, AddIndexNode, CastNode, FetchNode, TopNode, OutputNode, RenameConstraintNode, RefreshMaterializedViewNode, OrActionNode, CollateNode, Generated, QueryId, RootOperationNode, QueryResult, UnknownRow, Dialect, ExpressionBuilder, Expression, KyselyConfig, OperandExpression, SelectQueryBuilder, SqlBool, AliasableExpression, ExpressionWrapper } from 'kysely';
5
5
  import Decimal from 'decimal.js';
@@ -908,6 +908,10 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
908
908
  * Builds a VALUES table and select all fields from it.
909
909
  */
910
910
  abstract buildValuesTableSelect(fields: FieldDef[], rows: unknown[][]): SelectQueryBuilder<any, any, any>;
911
+ /**
912
+ * Builds a binary comparison expression between two operands.
913
+ */
914
+ buildComparison(left: Expression<unknown>, _leftFieldDef: FieldDef | undefined, op: string, right: Expression<unknown>, _rightFieldDef: FieldDef | undefined): Expression<SqlBool>;
911
915
  /**
912
916
  * Builds a JSON path selection expression.
913
917
  */
@@ -1099,13 +1103,26 @@ type GetAllFieldsExcludedFilterKinds<FieldsConfig> = '$all' extends keyof Fields
1099
1103
  excludedFilterKinds: readonly (infer EFK)[];
1100
1104
  } ? EFK : never : never;
1101
1105
 
1102
- type DefaultModelResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Omit = undefined, Options extends QueryOptions<Schema> = QueryOptions<Schema>, Optional = false, Array = false> = WrapType<{
1103
- [Key in NonRelationFields<Schema, Model> as ShouldOmitField<Schema, Model, Options, Key, Omit> extends true ? never : Key]: MapModelFieldType<Schema, Model, Key>;
1104
- }, Optional, Array>;
1106
+ type DefaultModelResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Omit = undefined, Options extends QueryOptions<Schema> = QueryOptions<Schema>, Optional = false, Array = false, IsGenericModel = [string] extends [Model] ? true : false> = WrapType<IsGenericModel extends true ? FlatModelResult<Schema, Model, Omit, Options> : IsDelegateModel<Schema, Model> extends true ? DelegateUnionResult<Schema, Model, Options, GetSubModels<Schema, Model>, Omit> : FlatModelResult<Schema, Model, Omit, Options>, Optional, Array>;
1105
1107
  type ShouldOmitField<Schema extends SchemaDef, Model extends GetModels<Schema>, Options extends QueryOptions<Schema>, Field extends GetModelFields<Schema, Model>, Omit> = QueryLevelOmit<Schema, Model, Field, Omit> extends boolean ? QueryLevelOmit<Schema, Model, Field, Omit> : OptionsLevelOmit<Schema, Model, Field, Options> extends boolean ? OptionsLevelOmit<Schema, Model, Field, Options> : SchemaLevelOmit<Schema, Model, Field>;
1106
1108
  type QueryLevelOmit<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetModelFields<Schema, Model>, Omit> = Field extends keyof Omit ? (Omit[Field] extends boolean ? Omit[Field] : undefined) : undefined;
1107
1109
  type OptionsLevelOmit<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetModelFields<Schema, Model>, Options extends QueryOptions<Schema>> = Uncapitalize<Model> extends keyof Options['omit'] ? Field extends keyof Options['omit'][Uncapitalize<Model>] ? Options['omit'][Uncapitalize<Model>][Field] extends boolean ? Options['omit'][Uncapitalize<Model>][Field] : undefined : undefined : undefined;
1108
1110
  type SchemaLevelOmit<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetModelFields<Schema, Model>> = GetModelField<Schema, Model, Field>['omit'] extends true ? true : false;
1111
+ type FlatModelResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Omit, Options extends QueryOptions<Schema>> = {
1112
+ [Key in NonRelationFields<Schema, Model> as ShouldOmitField<Schema, Model, Options, Key, Omit> extends true ? never : Key]: MapModelFieldType<Schema, Model, Key>;
1113
+ };
1114
+ type DelegateUnionResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Options extends QueryOptions<Schema>, SubModel extends GetModels<Schema>, Omit = undefined, Depth extends readonly 0[] = []> = Depth['length'] extends 10 ? SubModel extends string ? FlatModelResult<Schema, SubModel, Omit, Options> & {
1115
+ [K in GetModelDiscriminator<Schema, Model>]: SubModel;
1116
+ } : never : SubModel extends string ? IsDelegateModel<Schema, SubModel> extends true ? // sub-model is itself a delegate — recurse into its own sub-models so all
1117
+ DelegateUnionResult<Schema, SubModel, Options, GetSubModels<Schema, SubModel>, Omit, [
1118
+ ...Depth,
1119
+ 0
1120
+ ]> & {
1121
+ [K in GetModelDiscriminator<Schema, Model>]: SubModel;
1122
+ } : // leaf model — produce a flat scalar result and fix the discriminator
1123
+ FlatModelResult<Schema, SubModel, Omit, Options> & {
1124
+ [K in GetModelDiscriminator<Schema, Model>]: SubModel;
1125
+ } : never;
1109
1126
  type ModelSelectResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Select, Omit, Options extends QueryOptions<Schema>, ExtResult extends ExtResultBase<Schema> = {}> = {
1110
1127
  [Key in keyof Select as Select[Key] extends false | undefined ? never : Key extends keyof ExtractExtResult<ExtResult, Model & string> ? never : Key extends '_count' ? Select[Key] extends SelectCount<Schema, Model, Options> ? Key : never : Key extends keyof Omit ? Omit[Key] extends true ? never : Key : Key]: Key extends '_count' ? SelectCountResult<Schema, Model, Select[Key]> : Key extends NonRelationFields<Schema, Model> ? MapModelFieldType<Schema, Model, Key> : Key extends RelationFields<Schema, Model> ? ModelResult<Schema, RelationFieldType<Schema, Model, Key>, Select[Key], Options, ModelFieldIsOptional<Schema, Model, Key>, FieldIsArray<Schema, Model, Key>, ExtResult> : never;
1111
1128
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _zenstackhq_schema from '@zenstackhq/schema';
2
- import { SchemaDef, GetModels, ScalarFields, ForeignKeyFields, GetModelFields, FieldHasDefault, GetModelFieldType, ModelFieldIsOptional, GetModelField, NonRelationFields, GetModel, ProcedureDef, BuiltinType, FieldDef, ModelDef, DataSourceProviderType, IsDelegateModel, RelationFields, FieldIsArray, RelationFieldType, FieldIsRelation, GetEnums, GetEnum, GetTypeDefs, GetTypeDefFields, GetTypeDefField, TypeDefFieldIsOptional, GetTypeDefFieldType, TypeDefFieldIsArray, UpdatedAtInfo, FieldIsDelegateDiscriminator, FieldType, RelationInfo, Expression as Expression$1, LiteralExpression, ArrayExpression, FieldExpression, MemberExpression, BinaryExpression, UnaryExpression, CallExpression, BindingExpression, ThisExpression, NullExpression } from '@zenstackhq/schema';
2
+ import { SchemaDef, GetModels, ScalarFields, ForeignKeyFields, GetModelFields, FieldHasDefault, GetModelFieldType, ModelFieldIsOptional, GetModelField, NonRelationFields, GetModel, ProcedureDef, BuiltinType, FieldDef, ModelDef, DataSourceProviderType, IsDelegateModel, RelationFields, FieldIsArray, RelationFieldType, FieldIsRelation, GetEnums, GetEnum, GetTypeDefs, GetTypeDefFields, GetTypeDefField, TypeDefFieldIsOptional, GetTypeDefFieldType, TypeDefFieldIsArray, GetModelDiscriminator, GetSubModels, UpdatedAtInfo, FieldIsDelegateDiscriminator, FieldType, RelationInfo, Expression as Expression$1, LiteralExpression, ArrayExpression, FieldExpression, MemberExpression, BinaryExpression, UnaryExpression, CallExpression, BindingExpression, ThisExpression, NullExpression } from '@zenstackhq/schema';
3
3
  import * as kysely from 'kysely';
4
4
  import { Kysely, OperationNodeVisitor, OperationNode, SelectQueryNode, SelectionNode, ColumnNode, AliasNode, TableNode, FromNode, ReferenceNode, AndNode, OrNode, ValueListNode, ParensNode, JoinNode, RawNode, WhereNode, InsertQueryNode, DeleteQueryNode, ReturningNode, CreateTableNode, AddColumnNode, ColumnDefinitionNode, DropTableNode, OrderByNode, OrderByItemNode, GroupByNode, GroupByItemNode, UpdateQueryNode, ColumnUpdateNode, LimitNode, OffsetNode, OnConflictNode, OnDuplicateKeyNode, CheckConstraintNode, DataTypeNode, SelectAllNode, IdentifierNode, SchemableIdentifierNode, ValueNode, PrimitiveValueListNode, OperatorNode, CreateIndexNode, DropIndexNode, ListNode, PrimaryKeyConstraintNode, UniqueConstraintNode, ReferencesNode, WithNode, CommonTableExpressionNode, CommonTableExpressionNameNode, HavingNode, CreateSchemaNode, DropSchemaNode, AlterTableNode, DropColumnNode, RenameColumnNode, AlterColumnNode, ModifyColumnNode, AddConstraintNode, DropConstraintNode, ForeignKeyConstraintNode, CreateViewNode, DropViewNode, GeneratedNode, DefaultValueNode, OnNode, ValuesNode, SelectModifierNode, CreateTypeNode, DropTypeNode, ExplainNode, DefaultInsertValueNode, AggregateFunctionNode, OverNode, PartitionByNode, PartitionByItemNode, SetOperationNode, BinaryOperationNode, UnaryOperationNode, UsingNode, FunctionNode, CaseNode, WhenNode, JSONReferenceNode, JSONPathNode, JSONPathLegNode, JSONOperatorChainNode, TupleNode, MergeQueryNode, MatchedNode, AddIndexNode, CastNode, FetchNode, TopNode, OutputNode, RenameConstraintNode, RefreshMaterializedViewNode, OrActionNode, CollateNode, Generated, QueryId, RootOperationNode, QueryResult, UnknownRow, Dialect, ExpressionBuilder, Expression, KyselyConfig, OperandExpression, SelectQueryBuilder, SqlBool, AliasableExpression, ExpressionWrapper } from 'kysely';
5
5
  import Decimal from 'decimal.js';
@@ -908,6 +908,10 @@ declare abstract class BaseCrudDialect<Schema extends SchemaDef> {
908
908
  * Builds a VALUES table and select all fields from it.
909
909
  */
910
910
  abstract buildValuesTableSelect(fields: FieldDef[], rows: unknown[][]): SelectQueryBuilder<any, any, any>;
911
+ /**
912
+ * Builds a binary comparison expression between two operands.
913
+ */
914
+ buildComparison(left: Expression<unknown>, _leftFieldDef: FieldDef | undefined, op: string, right: Expression<unknown>, _rightFieldDef: FieldDef | undefined): Expression<SqlBool>;
911
915
  /**
912
916
  * Builds a JSON path selection expression.
913
917
  */
@@ -1099,13 +1103,26 @@ type GetAllFieldsExcludedFilterKinds<FieldsConfig> = '$all' extends keyof Fields
1099
1103
  excludedFilterKinds: readonly (infer EFK)[];
1100
1104
  } ? EFK : never : never;
1101
1105
 
1102
- type DefaultModelResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Omit = undefined, Options extends QueryOptions<Schema> = QueryOptions<Schema>, Optional = false, Array = false> = WrapType<{
1103
- [Key in NonRelationFields<Schema, Model> as ShouldOmitField<Schema, Model, Options, Key, Omit> extends true ? never : Key]: MapModelFieldType<Schema, Model, Key>;
1104
- }, Optional, Array>;
1106
+ type DefaultModelResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Omit = undefined, Options extends QueryOptions<Schema> = QueryOptions<Schema>, Optional = false, Array = false, IsGenericModel = [string] extends [Model] ? true : false> = WrapType<IsGenericModel extends true ? FlatModelResult<Schema, Model, Omit, Options> : IsDelegateModel<Schema, Model> extends true ? DelegateUnionResult<Schema, Model, Options, GetSubModels<Schema, Model>, Omit> : FlatModelResult<Schema, Model, Omit, Options>, Optional, Array>;
1105
1107
  type ShouldOmitField<Schema extends SchemaDef, Model extends GetModels<Schema>, Options extends QueryOptions<Schema>, Field extends GetModelFields<Schema, Model>, Omit> = QueryLevelOmit<Schema, Model, Field, Omit> extends boolean ? QueryLevelOmit<Schema, Model, Field, Omit> : OptionsLevelOmit<Schema, Model, Field, Options> extends boolean ? OptionsLevelOmit<Schema, Model, Field, Options> : SchemaLevelOmit<Schema, Model, Field>;
1106
1108
  type QueryLevelOmit<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetModelFields<Schema, Model>, Omit> = Field extends keyof Omit ? (Omit[Field] extends boolean ? Omit[Field] : undefined) : undefined;
1107
1109
  type OptionsLevelOmit<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetModelFields<Schema, Model>, Options extends QueryOptions<Schema>> = Uncapitalize<Model> extends keyof Options['omit'] ? Field extends keyof Options['omit'][Uncapitalize<Model>] ? Options['omit'][Uncapitalize<Model>][Field] extends boolean ? Options['omit'][Uncapitalize<Model>][Field] : undefined : undefined : undefined;
1108
1110
  type SchemaLevelOmit<Schema extends SchemaDef, Model extends GetModels<Schema>, Field extends GetModelFields<Schema, Model>> = GetModelField<Schema, Model, Field>['omit'] extends true ? true : false;
1111
+ type FlatModelResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Omit, Options extends QueryOptions<Schema>> = {
1112
+ [Key in NonRelationFields<Schema, Model> as ShouldOmitField<Schema, Model, Options, Key, Omit> extends true ? never : Key]: MapModelFieldType<Schema, Model, Key>;
1113
+ };
1114
+ type DelegateUnionResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Options extends QueryOptions<Schema>, SubModel extends GetModels<Schema>, Omit = undefined, Depth extends readonly 0[] = []> = Depth['length'] extends 10 ? SubModel extends string ? FlatModelResult<Schema, SubModel, Omit, Options> & {
1115
+ [K in GetModelDiscriminator<Schema, Model>]: SubModel;
1116
+ } : never : SubModel extends string ? IsDelegateModel<Schema, SubModel> extends true ? // sub-model is itself a delegate — recurse into its own sub-models so all
1117
+ DelegateUnionResult<Schema, SubModel, Options, GetSubModels<Schema, SubModel>, Omit, [
1118
+ ...Depth,
1119
+ 0
1120
+ ]> & {
1121
+ [K in GetModelDiscriminator<Schema, Model>]: SubModel;
1122
+ } : // leaf model — produce a flat scalar result and fix the discriminator
1123
+ FlatModelResult<Schema, SubModel, Omit, Options> & {
1124
+ [K in GetModelDiscriminator<Schema, Model>]: SubModel;
1125
+ } : never;
1109
1126
  type ModelSelectResult<Schema extends SchemaDef, Model extends GetModels<Schema>, Select, Omit, Options extends QueryOptions<Schema>, ExtResult extends ExtResultBase<Schema> = {}> = {
1110
1127
  [Key in keyof Select as Select[Key] extends false | undefined ? never : Key extends keyof ExtractExtResult<ExtResult, Model & string> ? never : Key extends '_count' ? Select[Key] extends SelectCount<Schema, Model, Options> ? Key : never : Key extends keyof Omit ? Omit[Key] extends true ? never : Key : Key]: Key extends '_count' ? SelectCountResult<Schema, Model, Select[Key]> : Key extends NonRelationFields<Schema, Model> ? MapModelFieldType<Schema, Model, Key> : Key extends RelationFields<Schema, Model> ? ModelResult<Schema, RelationFieldType<Schema, Model, Key>, Select[Key], Options, ModelFieldIsOptional<Schema, Model, Key>, FieldIsArray<Schema, Model, Key>, ExtResult> : never;
1111
1128
  };
package/dist/index.js CHANGED
@@ -82,6 +82,7 @@ __reExport(schema_exports, schema_star);
82
82
  import * as schema_star from "@zenstackhq/schema";
83
83
 
84
84
  // src/utils/object-utils.ts
85
+ import { isPlainObject } from "@zenstackhq/common-helpers";
85
86
  function extractFields(obj, fields) {
86
87
  return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
87
88
  }
@@ -93,6 +94,10 @@ function fieldsToSelectObject(fields) {
93
94
  ]));
94
95
  }
95
96
  __name(fieldsToSelectObject, "fieldsToSelectObject");
97
+ function isEmptyObject(x) {
98
+ return isPlainObject(x) && Object.keys(x).length === 0;
99
+ }
100
+ __name(isEmptyObject, "isEmptyObject");
96
101
 
97
102
  // src/client/executor/error-processor.ts
98
103
  function getDbErrorCode(error) {
@@ -605,7 +610,7 @@ __name(tmpAlias, "tmpAlias");
605
610
 
606
611
  // src/client/crud/operations/base.ts
607
612
  import { createId as cuid2 } from "@paralleldrive/cuid2";
608
- import { clone, enumerate as enumerate2, invariant as invariant7, isPlainObject as isPlainObject2 } from "@zenstackhq/common-helpers";
613
+ import { clone, enumerate as enumerate2, invariant as invariant7, isPlainObject as isPlainObject3 } from "@zenstackhq/common-helpers";
609
614
  import { default as cuid1 } from "cuid";
610
615
  import { createQueryId, expressionBuilder as expressionBuilder5, sql as sql5 } from "kysely";
611
616
  import { nanoid } from "nanoid";
@@ -729,7 +734,7 @@ var AnyNull = new AnyNullClass();
729
734
  import { invariant as invariant3 } from "@zenstackhq/common-helpers";
730
735
 
731
736
  // src/client/crud/dialects/base-dialect.ts
732
- import { enumerate, invariant as invariant2, isPlainObject, lowerCaseFirst } from "@zenstackhq/common-helpers";
737
+ import { enumerate, invariant as invariant2, isPlainObject as isPlainObject2, lowerCaseFirst } from "@zenstackhq/common-helpers";
733
738
  import { expressionBuilder, sql } from "kysely";
734
739
  import { match as match2, P } from "ts-pattern";
735
740
  var BaseCrudDialect = class {
@@ -857,7 +862,31 @@ var BaseCrudDialect = class {
857
862
  return LOGICAL_COMBINATORS.includes(key);
858
863
  }
859
864
  buildCompositeFilter(model, modelAlias, key, payload) {
860
- return match2(key).with("AND", () => this.and(...enumerate(payload).map((subPayload) => this.buildFilter(model, modelAlias, subPayload)))).with("OR", () => this.or(...enumerate(payload).map((subPayload) => this.buildFilter(model, modelAlias, subPayload)))).with("NOT", () => this.eb.not(this.buildCompositeFilter(model, modelAlias, "AND", payload))).exhaustive();
865
+ const normalizedPayload = enumerate(payload).filter((el) => {
866
+ if (typeof el === "object" && el !== null && !Array.isArray(el)) {
867
+ const entries = Object.entries(el);
868
+ return entries.some(([, v]) => v !== void 0);
869
+ } else {
870
+ return true;
871
+ }
872
+ });
873
+ const normalizedFilters = normalizedPayload.map((el) => this.buildFilter(model, modelAlias, el));
874
+ return match2(key).with("AND", () => {
875
+ if (normalizedFilters.length === 0) {
876
+ return this.true();
877
+ }
878
+ return this.and(...normalizedFilters);
879
+ }).with("OR", () => {
880
+ if (normalizedFilters.length === 0) {
881
+ return this.false();
882
+ }
883
+ return this.or(...normalizedFilters);
884
+ }).with("NOT", () => {
885
+ if (normalizedFilters.length === 0) {
886
+ return this.true();
887
+ }
888
+ return this.not(...normalizedFilters);
889
+ }).exhaustive();
861
890
  }
862
891
  buildRelationFilter(model, modelAlias, field, fieldDef, payload) {
863
892
  if (!fieldDef.array) {
@@ -1198,7 +1227,7 @@ var BaseCrudDialect = class {
1198
1227
  return this.eb(lhs, "=", this.transformInput(rhs, type, false));
1199
1228
  }
1200
1229
  buildStandardFilter(type, payload, lhs, getRhs, recurse, throwIfInvalid = false, onlyForKeys = void 0, excludeKeys = []) {
1201
- if (payload === null || !isPlainObject(payload)) {
1230
+ if (payload === null || !isPlainObject2(payload)) {
1202
1231
  return {
1203
1232
  conditions: [
1204
1233
  this.buildValueFilter(lhs, type, payload)
@@ -1215,6 +1244,9 @@ var BaseCrudDialect = class {
1215
1244
  if (excludeKeys.includes(op)) {
1216
1245
  continue;
1217
1246
  }
1247
+ if (value === void 0) {
1248
+ continue;
1249
+ }
1218
1250
  const rhs = Array.isArray(value) ? value.map(getRhs) : getRhs(value);
1219
1251
  const condition = match2(op).with("equals", () => rhs === null ? this.eb(lhs, "is", null) : this.eb(lhs, "=", rhs)).with("in", () => {
1220
1252
  invariant2(Array.isArray(rhs), "right hand side must be an array");
@@ -1272,6 +1304,9 @@ var BaseCrudDialect = class {
1272
1304
  if (key === "mode" || consumedKeys.includes(key)) {
1273
1305
  continue;
1274
1306
  }
1307
+ if (value === void 0) {
1308
+ continue;
1309
+ }
1275
1310
  invariant2(typeof value === "string", `${key} value must be a string`);
1276
1311
  const escapedValue = this.escapeLikePattern(value);
1277
1312
  const condition = match2(key).with("contains", () => this.buildStringLike(fieldRef, `%${escapedValue}%`, mode === "insensitive")).with("startsWith", () => this.buildStringLike(fieldRef, `${escapedValue}%`, mode === "insensitive")).with("endsWith", () => this.buildStringLike(fieldRef, `%${escapedValue}`, mode === "insensitive")).otherwise(() => {
@@ -1597,6 +1632,12 @@ var BaseCrudDialect = class {
1597
1632
  buildExistsExpression(innerQuery) {
1598
1633
  return this.eb.exists(innerQuery);
1599
1634
  }
1635
+ /**
1636
+ * Builds a binary comparison expression between two operands.
1637
+ */
1638
+ buildComparison(left, _leftFieldDef, op, right, _rightFieldDef) {
1639
+ return this.eb(left, op, right);
1640
+ }
1600
1641
  };
1601
1642
 
1602
1643
  // src/client/crud/dialects/lateral-join-dialect-base.ts
@@ -2031,6 +2072,33 @@ var PostgresCrudDialect = class _PostgresCrudDialect extends LateralJoinDialectB
2031
2072
  Bytes: "bytea",
2032
2073
  Json: "jsonb"
2033
2074
  };
2075
+ // Maps @db.* attribute names to PostgreSQL SQL types for use in VALUES table casts
2076
+ static dbAttributeToSqlTypeMap = {
2077
+ "@db.Uuid": "uuid",
2078
+ "@db.Citext": "citext",
2079
+ "@db.Inet": "inet",
2080
+ "@db.Bit": "bit",
2081
+ "@db.VarBit": "varbit",
2082
+ "@db.Xml": "xml",
2083
+ "@db.Json": "json",
2084
+ "@db.JsonB": "jsonb",
2085
+ "@db.ByteA": "bytea",
2086
+ "@db.Text": "text",
2087
+ "@db.Char": "bpchar",
2088
+ "@db.VarChar": "varchar",
2089
+ "@db.Date": "date",
2090
+ "@db.Time": "time",
2091
+ "@db.Timetz": "timetz",
2092
+ "@db.Timestamp": "timestamp",
2093
+ "@db.Timestamptz": "timestamptz",
2094
+ "@db.SmallInt": "smallint",
2095
+ "@db.Integer": "integer",
2096
+ "@db.BigInt": "bigint",
2097
+ "@db.Real": "real",
2098
+ "@db.DoublePrecision": "double precision",
2099
+ "@db.Decimal": "decimal",
2100
+ "@db.Boolean": "boolean"
2101
+ };
2034
2102
  constructor(schema, options) {
2035
2103
  super(schema, options);
2036
2104
  this.overrideTypeParsers();
@@ -2295,13 +2363,55 @@ var PostgresCrudDialect = class _PostgresCrudDialect extends LateralJoinDialectB
2295
2363
  receiver
2296
2364
  ]).as("$items")).select(this.eb.lit(1).as("_")).where(buildFilter(this.eb.ref("$items.value"))));
2297
2365
  }
2298
- getSqlType(zmodelType) {
2366
+ getSqlType(zmodelType, attributes) {
2367
+ if (attributes) {
2368
+ for (const attr of attributes) {
2369
+ const mapped = _PostgresCrudDialect.dbAttributeToSqlTypeMap[attr.name];
2370
+ if (mapped) {
2371
+ return mapped;
2372
+ }
2373
+ }
2374
+ }
2299
2375
  if (isEnum(this.schema, zmodelType)) {
2300
2376
  return "text";
2301
2377
  } else {
2302
2378
  return this.zmodelToSqlTypeMap[zmodelType] ?? "text";
2303
2379
  }
2304
2380
  }
2381
+ // Resolves the effective SQL type for a field: the native type from any @db.* attribute,
2382
+ // or the base ZModel SQL type if no attribute is present, or undefined if the field is unknown.
2383
+ resolveFieldSqlType(fieldDef) {
2384
+ if (!fieldDef) {
2385
+ return {
2386
+ sqlType: void 0,
2387
+ hasDbOverride: false
2388
+ };
2389
+ }
2390
+ const dbAttr = fieldDef.attributes?.find((a) => a.name.startsWith("@db."));
2391
+ if (dbAttr) {
2392
+ return {
2393
+ sqlType: _PostgresCrudDialect.dbAttributeToSqlTypeMap[dbAttr.name],
2394
+ hasDbOverride: true
2395
+ };
2396
+ }
2397
+ return {
2398
+ sqlType: this.getSqlType(fieldDef.type),
2399
+ hasDbOverride: false
2400
+ };
2401
+ }
2402
+ buildComparison(left, leftFieldDef, op, right, rightFieldDef) {
2403
+ const leftResolved = this.resolveFieldSqlType(leftFieldDef);
2404
+ const rightResolved = this.resolveFieldSqlType(rightFieldDef);
2405
+ if (leftResolved.sqlType !== rightResolved.sqlType && (leftResolved.hasDbOverride || rightResolved.hasDbOverride)) {
2406
+ if (leftResolved.hasDbOverride) {
2407
+ left = this.eb.cast(left, sql3.raw(this.getSqlType(leftFieldDef.type)));
2408
+ }
2409
+ if (rightResolved.hasDbOverride) {
2410
+ right = this.eb.cast(right, sql3.raw(this.getSqlType(rightFieldDef.type)));
2411
+ }
2412
+ }
2413
+ return super.buildComparison(left, leftFieldDef, op, right, rightFieldDef);
2414
+ }
2305
2415
  getStringCasingBehavior() {
2306
2416
  return {
2307
2417
  supportsILike: true,
@@ -2323,7 +2433,7 @@ var PostgresCrudDialect = class _PostgresCrudDialect extends LateralJoinDialectB
2323
2433
  }
2324
2434
  const eb = expressionBuilder3();
2325
2435
  return eb.selectFrom(sql3`(VALUES ${sql3.join(rows.map((row) => sql3`(${sql3.join(row.map((v) => sql3.val(v)))})`), sql3.raw(", "))})`.as("$values")).select(fields.map((f, i) => {
2326
- const mappedType = this.getSqlType(f.type);
2436
+ const mappedType = this.getSqlType(f.type, f.attributes);
2327
2437
  const castType = f.array ? sql3`${sql3.raw(mappedType)}[]` : sql3.raw(mappedType);
2328
2438
  return this.eb.cast(sql3.ref(`$values.column${i + 1}`), castType).as(f.name);
2329
2439
  }));
@@ -3351,7 +3461,7 @@ var BaseOperationHandler = class {
3351
3461
  throw createInvalidInputError("data must be an object");
3352
3462
  }
3353
3463
  const parentWhere = await this.buildUpdateParentRelationFilter(kysely, fromRelation);
3354
- let combinedWhere = where ?? {};
3464
+ let combinedWhere = where ?? true;
3355
3465
  if (Object.keys(parentWhere).length > 0) {
3356
3466
  combinedWhere = Object.keys(combinedWhere).length > 0 ? {
3357
3467
  AND: [
@@ -3624,7 +3734,7 @@ var BaseOperationHandler = class {
3624
3734
  throw createNotSupportedError("Updating with a limit is not supported for polymorphic models");
3625
3735
  }
3626
3736
  const parentWhere = await this.buildUpdateParentRelationFilter(kysely, fromRelation);
3627
- let combinedWhere = where ?? {};
3737
+ let combinedWhere = where ?? true;
3628
3738
  if (Object.keys(parentWhere).length > 0) {
3629
3739
  combinedWhere = Object.keys(combinedWhere).length > 0 ? {
3630
3740
  AND: [
@@ -3816,11 +3926,11 @@ var BaseOperationHandler = class {
3816
3926
  break;
3817
3927
  }
3818
3928
  case "delete": {
3819
- await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, true);
3929
+ await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, true, true);
3820
3930
  break;
3821
3931
  }
3822
3932
  case "deleteMany": {
3823
- await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, false);
3933
+ await this.deleteRelation(kysely, fieldModel, value, fromRelationContext, false, false);
3824
3934
  break;
3825
3935
  }
3826
3936
  default: {
@@ -3908,6 +4018,10 @@ var BaseOperationHandler = class {
3908
4018
  true
3909
4019
  ];
3910
4020
  }
4021
+ } else if (isEmptyObject(data)) {
4022
+ disconnectConditions = [
4023
+ true
4024
+ ];
3911
4025
  } else {
3912
4026
  disconnectConditions = this.normalizeRelationManipulationInput(model, data);
3913
4027
  if (disconnectConditions.length === 0) {
@@ -4030,9 +4144,9 @@ var BaseOperationHandler = class {
4030
4144
  }
4031
4145
  }
4032
4146
  }
4033
- async deleteRelation(kysely, model, data, fromRelation, throwForNotFound) {
4147
+ async deleteRelation(kysely, model, data, fromRelation, uniqueDelete, throwForNotFound) {
4034
4148
  let deleteConditions = [];
4035
- let expectedDeleteCount;
4149
+ let expectedDeleteCount = -1;
4036
4150
  if (typeof data === "boolean") {
4037
4151
  if (data === false) {
4038
4152
  return;
@@ -4040,6 +4154,15 @@ var BaseOperationHandler = class {
4040
4154
  deleteConditions = [
4041
4155
  true
4042
4156
  ];
4157
+ if (uniqueDelete) {
4158
+ expectedDeleteCount = 1;
4159
+ }
4160
+ }
4161
+ } else if (isEmptyObject(data)) {
4162
+ deleteConditions = [
4163
+ true
4164
+ ];
4165
+ if (uniqueDelete) {
4043
4166
  expectedDeleteCount = 1;
4044
4167
  }
4045
4168
  } else {
@@ -4047,7 +4170,9 @@ var BaseOperationHandler = class {
4047
4170
  if (deleteConditions.length === 0) {
4048
4171
  return;
4049
4172
  }
4050
- expectedDeleteCount = deleteConditions.length;
4173
+ if (uniqueDelete) {
4174
+ expectedDeleteCount = deleteConditions.length;
4175
+ }
4051
4176
  }
4052
4177
  let deleteResult;
4053
4178
  let deleteFromModel;
@@ -4107,7 +4232,7 @@ var BaseOperationHandler = class {
4107
4232
  });
4108
4233
  }
4109
4234
  }
4110
- if (throwForNotFound && expectedDeleteCount > (deleteResult.numAffectedRows ?? 0)) {
4235
+ if (throwForNotFound && expectedDeleteCount >= 0 && expectedDeleteCount > (deleteResult.numAffectedRows ?? 0)) {
4111
4236
  throw createNotFoundError(deleteFromModel);
4112
4237
  }
4113
4238
  }
@@ -4242,7 +4367,7 @@ var BaseOperationHandler = class {
4242
4367
  for (const [key, value] of Object.entries(args)) {
4243
4368
  if (value === void 0) {
4244
4369
  delete args[key];
4245
- } else if (value && isPlainObject2(value)) {
4370
+ } else if (value && isPlainObject3(value)) {
4246
4371
  this.doNormalizeArgs(value);
4247
4372
  }
4248
4373
  }