Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 5 commits
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
2 changes: 1 addition & 1 deletion packages/common-helpers/src/zip.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Zips two arrays into an array of tuples.
*/
export function zip<T, U>(arr1: T[], arr2: U[]): Array<[T, U]> {
export function zip<T, U>(arr1: readonly T[], arr2: readonly U[]): Array<[T, U]> {
const length = Math.min(arr1.length, arr2.length);
const result: Array<[T, U]> = [];
for (let i = 0; i < length; i++) {
Expand Down
4 changes: 2 additions & 2 deletions packages/orm/src/client/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,15 @@ export type ClientContract<Schema extends SchemaDef, Options extends ClientOptio
$transaction<T>(
callback: (tx: Omit<ClientContract<Schema, Options>, TransactionUnsupportedMethods>) => Promise<T>,
options?: { isolationLevel?: TransactionIsolationLevel },
): Promise<T>;
): ZenStackPromise<Schema, T>;
Comment thread
ymc9 marked this conversation as resolved.
Outdated

/**
* Starts a sequential transaction.
*/
$transaction<P extends ZenStackPromise<Schema, any>[]>(
arg: [...P],
options?: { isolationLevel?: TransactionIsolationLevel },
): Promise<UnwrapTuplePromises<P>>;
): ZenStackPromise<Schema, UnwrapTuplePromises<P>>;

/**
* Returns a new client with the specified plugin installed.
Expand Down
90 changes: 44 additions & 46 deletions packages/orm/src/client/crud-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ import type {
GetEnum,
GetEnums,
GetModel,
GetModelDiscriminator,
GetModelField,
GetModelFields,
GetModelFieldType,
GetModels,
GetSubModels,
GetTypeDefField,
GetTypeDefFields,
GetTypeDefFieldType,
GetTypeDefs,
IsDelegateModel,
ModelFieldIsOptional,
NonRelationFields,
RelationFields,
Expand Down Expand Up @@ -62,20 +59,26 @@ export type DefaultModelResult<
Optional = false,
Array = false,
> = WrapType<
IsDelegateModel<Schema, Model> extends true
? // delegate model's selection result is a union of all sub-models
DelegateUnionResult<Schema, Model, Options, GetSubModels<Schema, Model>, Omit>
: {
[Key in NonRelationFields<Schema, Model> as ShouldOmitField<
Schema,
Model,
Options,
Key,
Omit
> extends true
? never
: Key]: MapModelFieldType<Schema, Model, Key>;
},
{
[Key in NonRelationFields<Schema, Model> as ShouldOmitField<Schema, Model, Options, Key, Omit> extends true
? never
: Key]: MapModelFieldType<Schema, Model, Key>;
},
// TODO: revisit how to efficiently implement discriminated sub model types
// IsDelegateModel<Schema, Model> extends true
// ? // delegate model's selection result is a union of all sub-models
// DelegateUnionResult<Schema, Model, Options, GetSubModels<Schema, Model>, Omit>
// : {
// [Key in NonRelationFields<Schema, Model> as ShouldOmitField<
// Schema,
// Model,
// Options,
// Key,
// Omit
// > extends true
// ? never
// : Key]: MapModelFieldType<Schema, Model, Key>;
// },
Comment thread
ymc9 marked this conversation as resolved.
Optional,
Array
>;
Expand Down Expand Up @@ -120,15 +123,15 @@ type SchemaLevelOmit<
Field extends GetModelFields<Schema, Model>,
> = GetModelField<Schema, Model, Field>['omit'] extends true ? true : false;

type DelegateUnionResult<
Schema extends SchemaDef,
Model extends GetModels<Schema>,
Options extends ClientOptions<Schema>,
SubModel extends GetModels<Schema>,
Omit = undefined,
> = SubModel extends string // typescript union distribution
? DefaultModelResult<Schema, SubModel, Options, Omit> & { [K in GetModelDiscriminator<Schema, Model>]: SubModel } // fixate discriminated field
: never;
// type DelegateUnionResult<
// Schema extends SchemaDef,
// Model extends GetModels<Schema>,
// Options extends ClientOptions<Schema>,
// SubModel extends GetModels<Schema>,
// Omit = undefined,
// > = SubModel extends string // typescript union distribution
// ? DefaultModelResult<Schema, SubModel, Options, Omit> & { [K in GetModelDiscriminator<Schema, Model>]: SubModel } // fixate discriminated field
// : never;

type ModelSelectResult<
Schema extends SchemaDef,
Expand Down Expand Up @@ -1029,7 +1032,7 @@ type OppositeRelationFields<
Model extends GetModels<Schema>,
Field extends GetModelFields<Schema, Model>,
Opposite = OppositeRelation<Schema, Model, Field>,
> = Opposite extends RelationInfo ? (Opposite['fields'] extends string[] ? Opposite['fields'] : []) : [];
> = Opposite extends RelationInfo ? (Opposite['fields'] extends readonly string[] ? Opposite['fields'] : []) : [];

type OppositeRelationAndFK<
Schema extends SchemaDef,
Expand Down Expand Up @@ -1083,21 +1086,16 @@ export type FindArgs<
Model extends GetModels<Schema>,
Collection extends boolean,
AllowFilter extends boolean = true,
> =
ProviderSupportsDistinct<Schema> extends true
? (Collection extends true
? SortAndTakeArgs<Schema, Model> & {
/**
* Distinct fields
*/
distinct?: OrArray<NonRelationFields<Schema, Model>>;
}
: {}) &
(AllowFilter extends true ? FilterArgs<Schema, Model> : {}) &
SelectIncludeOmit<Schema, Model, Collection>
: (Collection extends true ? SortAndTakeArgs<Schema, Model> : {}) &
(AllowFilter extends true ? FilterArgs<Schema, Model> : {}) &
SelectIncludeOmit<Schema, Model, Collection>;
> = (Collection extends true
? SortAndTakeArgs<Schema, Model> & {
/**
* Distinct fields
*/
distinct?: OrArray<NonRelationFields<Schema, Model>>;
}
: {}) &
(AllowFilter extends true ? FilterArgs<Schema, Model> : {}) &
SelectIncludeOmit<Schema, Model, Collection>;

export type FindManyArgs<Schema extends SchemaDef, Model extends GetModels<Schema>> = FindArgs<Schema, Model, true>;

Expand Down Expand Up @@ -2002,7 +2000,7 @@ type NestedDeleteManyInput<

type NonOwnedRelationFields<Schema extends SchemaDef, Model extends GetModels<Schema>> = keyof {
[Key in RelationFields<Schema, Model> as GetModelField<Schema, Model, Key>['relation'] extends {
references: unknown[];
references: readonly unknown[];
}
? never
: Key]: true;
Expand All @@ -2014,8 +2012,8 @@ type HasToManyRelations<Schema extends SchemaDef, Model extends GetModels<Schema
? false
: true;

Comment thread
ymc9 marked this conversation as resolved.
type ProviderSupportsDistinct<Schema extends SchemaDef> = Schema['provider']['type'] extends 'postgresql'
? true
: false;
// type ProviderSupportsDistinct<Schema extends SchemaDef> = Schema['provider']['type'] extends 'postgresql'
// ? true
// : false;

// #endregion
10 changes: 5 additions & 5 deletions packages/orm/src/client/crud/operations/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
data: any,
fromRelation?: FromRelationContext,
creatingForDelegate = false,
returnFields?: string[],
returnFields?: readonly string[],
): Promise<unknown> {
const modelDef = this.requireModel(model);

Expand Down Expand Up @@ -662,7 +662,7 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
input: { data: any; skipDuplicates?: boolean },
returnData: ReturnData,
fromRelation?: FromRelationContext,
fieldsToReturn?: string[],
fieldsToReturn?: readonly string[],
): Promise<Result> {
if (!input.data || (Array.isArray(input.data) && input.data.length === 0)) {
// nothing todo
Expand Down Expand Up @@ -901,7 +901,7 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
fromRelation?: FromRelationContext,
allowRelationUpdate = true,
throwIfNotFound = true,
fieldsToReturn?: string[],
fieldsToReturn?: readonly string[],
): Promise<unknown> {
if (!data || typeof data !== 'object') {
throw createInvalidInputError('data must be an object');
Expand Down Expand Up @@ -1207,7 +1207,7 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
limit: number | undefined,
returnData: ReturnData,
filterModel?: string,
fieldsToReturn?: string[],
fieldsToReturn?: readonly string[],
): Promise<Result> {
if (typeof data !== 'object') {
throw createInvalidInputError('data must be an object');
Expand Down Expand Up @@ -1923,7 +1923,7 @@ export abstract class BaseOperationHandler<Schema extends SchemaDef> {
where: any,
limit?: number,
filterModel?: string,
fieldsToReturn?: string[],
fieldsToReturn?: readonly string[],
): Promise<QueryResult<unknown>> {
filterModel ??= model;

Expand Down
2 changes: 1 addition & 1 deletion packages/orm/src/client/crud/validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ export class InputValidator<Schema extends SchemaDef> {
return result;
}

private makeScalarSchema(type: string, attributes?: AttributeApplication[]) {
private makeScalarSchema(type: string, attributes?: readonly AttributeApplication[]) {
if (this.schema.typeDefs && type in this.schema.typeDefs) {
return this.makeTypeDefSchema(type);
} else if (this.schema.enums && type in this.schema.enums) {
Expand Down
24 changes: 18 additions & 6 deletions packages/orm/src/client/crud/validator/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ function getArgValue<T extends string | number | boolean>(expr: Expression | und
return expr.value as T;
}

export function addStringValidation(schema: z.ZodString, attributes: AttributeApplication[] | undefined): z.ZodSchema {
export function addStringValidation(
schema: z.ZodString,
attributes: readonly AttributeApplication[] | undefined,
): z.ZodSchema {
if (!attributes || attributes.length === 0) {
return schema;
}
Expand Down Expand Up @@ -86,7 +89,10 @@ export function addStringValidation(schema: z.ZodString, attributes: AttributeAp
return result;
}

export function addNumberValidation(schema: z.ZodNumber, attributes: AttributeApplication[] | undefined): z.ZodSchema {
export function addNumberValidation(
schema: z.ZodNumber,
attributes: readonly AttributeApplication[] | undefined,
): z.ZodSchema {
if (!attributes || attributes.length === 0) {
return schema;
}
Expand Down Expand Up @@ -114,7 +120,10 @@ export function addNumberValidation(schema: z.ZodNumber, attributes: AttributeAp
return result;
}

export function addBigIntValidation(schema: z.ZodBigInt, attributes: AttributeApplication[] | undefined): z.ZodSchema {
export function addBigIntValidation(
schema: z.ZodBigInt,
attributes: readonly AttributeApplication[] | undefined,
): z.ZodSchema {
if (!attributes || attributes.length === 0) {
return schema;
}
Expand Down Expand Up @@ -145,7 +154,7 @@ export function addBigIntValidation(schema: z.ZodBigInt, attributes: AttributeAp

export function addDecimalValidation(
schema: z.ZodType<Decimal> | z.ZodString,
attributes: AttributeApplication[] | undefined,
attributes: readonly AttributeApplication[] | undefined,
addExtraValidation: boolean,
): z.ZodSchema {
let result: z.ZodSchema = schema;
Expand Down Expand Up @@ -224,7 +233,7 @@ export function addDecimalValidation(

export function addListValidation(
schema: z.ZodArray<any>,
attributes: AttributeApplication[] | undefined,
attributes: readonly AttributeApplication[] | undefined,
): z.ZodSchema {
if (!attributes || attributes.length === 0) {
return schema;
Expand All @@ -248,7 +257,10 @@ export function addListValidation(
return result;
}

export function addCustomValidation(schema: z.ZodSchema, attributes: AttributeApplication[] | undefined): z.ZodSchema {
export function addCustomValidation(
schema: z.ZodSchema,
attributes: readonly AttributeApplication[] | undefined,
): z.ZodSchema {
const attrs = attributes?.filter((a) => a.name === '@@validate');
if (!attrs || attrs.length === 0) {
return schema;
Expand Down
4 changes: 2 additions & 2 deletions packages/orm/src/client/helpers/schema-db-pusher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ export class SchemaDbPusher<Schema extends SchemaDef> {
const baseModelDef = requireModel(this.schema, modelDef.baseModel);
table = table.addForeignKeyConstraint(
`fk_${modelDef.baseModel}_delegate`,
baseModelDef.idFields,
baseModelDef.idFields as string[],
modelDef.baseModel,
baseModelDef.idFields,
baseModelDef.idFields as string[],
(cb) => cb.onDelete('cascade').onUpdate('cascade'),
);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/orm/src/utils/object-utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* Extract fields from an object.
*/
export function extractFields(obj: any, fields: string[]) {
export function extractFields(obj: any, fields: readonly string[]) {
return Object.fromEntries(Object.entries(obj).filter(([key]) => fields.includes(key)));
}

/**
* Create an object with fields as keys and true values.
*/
export function fieldsToSelectObject(fields: string[]): Record<string, boolean> {
export function fieldsToSelectObject(fields: readonly string[]): Record<string, boolean> {
return Object.fromEntries(fields.map((f) => [f, true]));
}
Loading