diff --git a/packages/generator/src/fileCreators/prisma-idb-client/classes/models/IDBModelClass.ts b/packages/generator/src/fileCreators/prisma-idb-client/classes/models/IDBModelClass.ts index e90f299..5511ce0 100644 --- a/packages/generator/src/fileCreators/prisma-idb-client/classes/models/IDBModelClass.ts +++ b/packages/generator/src/fileCreators/prisma-idb-client/classes/models/IDBModelClass.ts @@ -4,27 +4,28 @@ import { addCountMethod } from "./api/count"; import { addCreateMethod } from "./api/create"; import { addCreateManyMethod } from "./api/createMany"; import { addCreateManyAndReturn } from "./api/createManyAndReturn"; +import { addDeleteMethod } from "./api/delete"; +import { addDeleteManyMethod } from "./api/deleteMany"; import { addFindFirstMethod } from "./api/findFirst"; import { addFindFirstOrThrow } from "./api/findFirstOrThrow"; import { addFindManyMethod } from "./api/findMany"; import { addFindUniqueMethod } from "./api/findUnique"; import { addFindUniqueOrThrow } from "./api/findUniqueOrThrow"; import { addUpdateMethod } from "./api/update"; +import { addUpdateMany } from "./api/updateMany"; +import { addUpsertMethod } from "./api/upsert"; +import { addApplyOrderByClause } from "./utils/_applyOrderByClause"; import { addApplyRelations } from "./utils/_applyRelations"; import { addApplySelectClause } from "./utils/_applySelectClause"; import { addApplyWhereClause } from "./utils/_applyWhereClause"; import { addFillDefaultsFunction } from "./utils/_fillDefaults"; import { addGetNeededStoresForCreate } from "./utils/_getNeededStoresForCreate"; import { addGetNeededStoresForFind } from "./utils/_getNeededStoresForFind"; -import { addRemoveNestedCreateDataMethod } from "./utils/_removeNestedCreateData"; import { addGetNeededStoresForWhere } from "./utils/_getNeededStoresForWhere"; -import { addDeleteMethod } from "./api/delete"; -import { addDeleteManyMethod } from "./api/deleteMany"; -import { addApplyOrderByClause } from "./utils/_applyOrderByClause"; +import { addPreprocessListFields } from "./utils/_preprocessListFields"; +import { addRemoveNestedCreateDataMethod } from "./utils/_removeNestedCreateData"; import { addResolveOrderByKey } from "./utils/_resolveOrderByKey"; import { addResolveSortOrder } from "./utils/_resolveSortOrder"; -import { addPreprocessListFields } from "./utils/_preprocessListFields"; -import { addUpsertMethod } from "./api/upsert"; export function addIDBModelClass(file: SourceFile, model: Model, models: readonly Model[]) { const modelClass = file.addClass({ @@ -60,5 +61,6 @@ export function addIDBModelClass(file: SourceFile, model: Model, models: readonl addDeleteManyMethod(modelClass, model, models); addUpdateMethod(modelClass, model); + addUpdateMany(modelClass, model); addUpsertMethod(modelClass, model); } diff --git a/packages/generator/src/fileCreators/prisma-idb-client/classes/models/api/updateMany.ts b/packages/generator/src/fileCreators/prisma-idb-client/classes/models/api/updateMany.ts new file mode 100644 index 0000000..10b81d7 --- /dev/null +++ b/packages/generator/src/fileCreators/prisma-idb-client/classes/models/api/updateMany.ts @@ -0,0 +1,39 @@ +import { getUniqueIdentifiers } from "../../../../../helpers/utils"; +import { Model } from "../../../../../fileCreators/types"; +import { ClassDeclaration } from "ts-morph"; + +export function addUpdateMany(modelClass: ClassDeclaration, model: Model) { + modelClass.addMethod({ + name: "updateMany", + isAsync: true, + typeParameters: [{ name: "Q", constraint: `Prisma.Args` }], + parameters: [ + { name: "query", type: "Q" }, + { + name: "tx", + hasQuestionToken: true, + type: "IDBUtils.ReadwriteTransactionType", + }, + ], + returnType: `Promise>`, + statements: (writer) => { + // TODO: composite keys + const pk = JSON.parse(getUniqueIdentifiers(model)[0].keyPath) as string[]; + writer + // TODO: nested create stores as well + .writeLine( + `tx = tx ?? this.client._db.transaction(Array.from(this._getNeededStoresForFind(query)), "readwrite");`, + ) + .writeLine(`const records = await this.findMany({ where: query.where }, tx);`) + .writeLine(`await Promise.all(`) + .writeLine(`records.map(async (record) =>`) + .block(() => { + writer.writeLine( + `await this.update({ where: { ${pk.map((field) => `${field}: record.${field},`)} }, data: query.data }, tx);`, + ); + }) + .writeLine(`));`) + .writeLine(`return { count: records.length };`); + }, + }); +} diff --git a/packages/usage/src/prisma/prisma-idb/prisma-idb-client.ts b/packages/usage/src/prisma/prisma-idb/prisma-idb-client.ts index e1b84d4..8d00c94 100644 --- a/packages/usage/src/prisma/prisma-idb/prisma-idb-client.ts +++ b/packages/usage/src/prisma/prisma-idb/prisma-idb-client.ts @@ -797,6 +797,20 @@ class UserIDBClass extends BaseIDBModelClass { return recordWithRelations as Prisma.Result; } + async updateMany>( + query: Q, + tx?: IDBUtils.ReadwriteTransactionType, + ): Promise> { + tx = tx ?? this.client._db.transaction(Array.from(this._getNeededStoresForFind(query)), "readwrite"); + const records = await this.findMany({ where: query.where }, tx); + await Promise.all( + records.map(async (record) => { + await this.update({ where: { id: record.id }, data: query.data }, tx); + }), + ); + return { count: records.length }; + } + async upsert>( query: Q, tx?: IDBUtils.ReadwriteTransactionType, @@ -1283,6 +1297,20 @@ class ProfileIDBClass extends BaseIDBModelClass { return recordWithRelations as Prisma.Result; } + async updateMany>( + query: Q, + tx?: IDBUtils.ReadwriteTransactionType, + ): Promise> { + tx = tx ?? this.client._db.transaction(Array.from(this._getNeededStoresForFind(query)), "readwrite"); + const records = await this.findMany({ where: query.where }, tx); + await Promise.all( + records.map(async (record) => { + await this.update({ where: { id: record.id }, data: query.data }, tx); + }), + ); + return { count: records.length }; + } + async upsert>( query: Q, tx?: IDBUtils.ReadwriteTransactionType, @@ -1946,6 +1974,20 @@ class PostIDBClass extends BaseIDBModelClass { return recordWithRelations as Prisma.Result; } + async updateMany>( + query: Q, + tx?: IDBUtils.ReadwriteTransactionType, + ): Promise> { + tx = tx ?? this.client._db.transaction(Array.from(this._getNeededStoresForFind(query)), "readwrite"); + const records = await this.findMany({ where: query.where }, tx); + await Promise.all( + records.map(async (record) => { + await this.update({ where: { id: record.id }, data: query.data }, tx); + }), + ); + return { count: records.length }; + } + async upsert>( query: Q, tx?: IDBUtils.ReadwriteTransactionType, @@ -2529,6 +2571,20 @@ class CommentIDBClass extends BaseIDBModelClass { return recordWithRelations as Prisma.Result; } + async updateMany>( + query: Q, + tx?: IDBUtils.ReadwriteTransactionType, + ): Promise> { + tx = tx ?? this.client._db.transaction(Array.from(this._getNeededStoresForFind(query)), "readwrite"); + const records = await this.findMany({ where: query.where }, tx); + await Promise.all( + records.map(async (record) => { + await this.update({ where: { id: record.id }, data: query.data }, tx); + }), + ); + return { count: records.length }; + } + async upsert>( query: Q, tx?: IDBUtils.ReadwriteTransactionType, @@ -3077,6 +3133,20 @@ class AllFieldScalarTypesIDBClass extends BaseIDBModelClass { return recordWithRelations as Prisma.Result; } + async updateMany>( + query: Q, + tx?: IDBUtils.ReadwriteTransactionType, + ): Promise> { + tx = tx ?? this.client._db.transaction(Array.from(this._getNeededStoresForFind(query)), "readwrite"); + const records = await this.findMany({ where: query.where }, tx); + await Promise.all( + records.map(async (record) => { + await this.update({ where: { id: record.id }, data: query.data }, tx); + }), + ); + return { count: records.length }; + } + async upsert>( query: Q, tx?: IDBUtils.ReadwriteTransactionType, diff --git a/packages/usage/tests/modelQueries/updateMany.spec.ts b/packages/usage/tests/modelQueries/updateMany.spec.ts new file mode 100644 index 0000000..228a2ca --- /dev/null +++ b/packages/usage/tests/modelQueries/updateMany.spec.ts @@ -0,0 +1,24 @@ +import { test } from "../fixtures"; +import { expectQueryToSucceed } from "../queryRunnerHelper"; + +test("updateMany_ChangeNames_SuccessfullyUpdatesRecord", async ({ page }) => { + await expectQueryToSucceed({ + page, + model: "user", + operation: "createMany", + query: { data: [{ name: "John" }, { name: "Alice" }, { name: "Clark" }] }, + }); + + await expectQueryToSucceed({ + page, + model: "user", + operation: "updateMany", + query: { where: { name: { contains: "c", mode: "insensitive" } }, data: { name: "ALICE" } }, + }); + + await expectQueryToSucceed({ + page, + model: "user", + operation: "findMany", + }); +});