diff --git a/packages/client/src/client.ts b/packages/client/src/client.ts index fb85e5805..dfbb51943 100644 --- a/packages/client/src/client.ts +++ b/packages/client/src/client.ts @@ -37,29 +37,32 @@ export const buildClient = = {}>(plu class { #options: SafeOptions; + schema: Schemas.Schema; db: SchemaPluginResult; search: SearchPluginResult; transactions: TransactionPluginResult; sql: SQLPluginResult; files: FilesPluginResult; - constructor(options: BaseClientOptions = {}, schemaTables?: Schemas.Table[]) { + constructor(options: BaseClientOptions = {}, tables: Schemas.Table[]) { const safeOptions = this.#parseOptions(options); this.#options = safeOptions; const pluginOptions: XataPluginOptions = { ...this.#getFetchProps(safeOptions), cache: safeOptions.cache, - host: safeOptions.host + host: safeOptions.host, + tables }; - const db = new SchemaPlugin(schemaTables).build(pluginOptions); - const search = new SearchPlugin(db, schemaTables).build(pluginOptions); + const db = new SchemaPlugin().build(pluginOptions); + const search = new SearchPlugin(db).build(pluginOptions); const transactions = new TransactionPlugin().build(pluginOptions); const sql = new SQLPlugin().build(pluginOptions); const files = new FilesPlugin().build(pluginOptions); // We assign the namespaces after creating in case the user overrides the db plugin + this.schema = { tables }; this.db = db; this.search = search; this.transactions = transactions; diff --git a/packages/client/src/plugins.ts b/packages/client/src/plugins.ts index ff56041ff..b16338dd2 100644 --- a/packages/client/src/plugins.ts +++ b/packages/client/src/plugins.ts @@ -1,4 +1,4 @@ -import { ApiExtraProps, HostProvider } from './api'; +import { ApiExtraProps, HostProvider, Schemas } from './api'; import { CacheImpl } from './schema/cache'; export abstract class XataPlugin { @@ -8,4 +8,5 @@ export abstract class XataPlugin { export type XataPluginOptions = ApiExtraProps & { cache: CacheImpl; host: HostProvider; + tables: Schemas.Table[]; }; diff --git a/packages/client/src/schema/index.ts b/packages/client/src/schema/index.ts index c3ba586c2..16179a489 100644 --- a/packages/client/src/schema/index.ts +++ b/packages/client/src/schema/index.ts @@ -29,13 +29,13 @@ export class SchemaPlugin> extends Xa #tables: Record> = {}; #schemaTables?: Table[]; - constructor(schemaTables?: Table[]) { + constructor() { super(); - - this.#schemaTables = schemaTables; } build(pluginOptions: XataPluginOptions): SchemaPluginResult { + this.#schemaTables = pluginOptions.tables; + const db: any = new Proxy( {}, { diff --git a/packages/client/src/search/index.ts b/packages/client/src/search/index.ts index e02db7968..432de6faf 100644 --- a/packages/client/src/search/index.ts +++ b/packages/client/src/search/index.ts @@ -67,12 +67,13 @@ export type SearchPluginResult> = { export class SearchPlugin> extends XataPlugin { #schemaTables?: Table[]; - constructor(private db: SchemaPluginResult, schemaTables?: Table[]) { + constructor(private db: SchemaPluginResult) { super(); - this.#schemaTables = schemaTables; } build(pluginOptions: XataPluginOptions): SearchPluginResult { + this.#schemaTables = pluginOptions.tables; + return { all: async >(query: string, options: SearchOptions = {}) => { const { records, totalCount } = await this.#search(query, options, pluginOptions); diff --git a/packages/plugin-client-prisma/.npmignore b/packages/plugin-client-prisma/.npmignore new file mode 100644 index 000000000..c97b8ad26 --- /dev/null +++ b/packages/plugin-client-prisma/.npmignore @@ -0,0 +1,5 @@ +src +tsconfig.json +rollup.config.mjs +.eslintrc.cjs +.gitignore diff --git a/packages/plugin-client-prisma/README.md b/packages/plugin-client-prisma/README.md new file mode 100644 index 000000000..065b2b2d0 --- /dev/null +++ b/packages/plugin-client-prisma/README.md @@ -0,0 +1 @@ +# @xata.io/prisma diff --git a/packages/plugin-client-prisma/package.json b/packages/plugin-client-prisma/package.json new file mode 100644 index 000000000..24f112948 --- /dev/null +++ b/packages/plugin-client-prisma/package.json @@ -0,0 +1,33 @@ +{ + "name": "@xata.io/prisma", + "version": "0.0.1", + "description": "", + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.cjs", + "types": "./dist/index.d.ts" + } + }, + "scripts": { + "build": "rimraf dist && rollup -c", + "tsc": "tsc --noEmit" + }, + "author": "", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/xataio/client-ts/issues" + }, + "dependencies": { + "@prisma/driver-adapter-utils": "^5.4.2", + "@xata.io/client": "workspace:*" + }, + "devDependencies": { + "@prisma/client": "^5.6.0", + "prisma": "^5.6.0", + "superjson": "^2.2.1" + } +} diff --git a/packages/plugin-client-prisma/rollup.config.mjs b/packages/plugin-client-prisma/rollup.config.mjs new file mode 100644 index 000000000..9c57e2aa4 --- /dev/null +++ b/packages/plugin-client-prisma/rollup.config.mjs @@ -0,0 +1,29 @@ +import dts from 'rollup-plugin-dts'; +import esbuild from 'rollup-plugin-esbuild'; + +export default [ + { + input: 'src/index.ts', + plugins: [esbuild()], + output: [ + { + file: `dist/index.cjs`, + format: 'cjs', + sourcemap: true + }, + { + file: `dist/index.mjs`, + format: 'es', + sourcemap: true + } + ] + }, + { + input: 'src/index.ts', + plugins: [dts()], + output: { + file: `dist/index.d.ts`, + format: 'es' + } + } +]; diff --git a/packages/plugin-client-prisma/src/conversion.ts b/packages/plugin-client-prisma/src/conversion.ts new file mode 100644 index 000000000..f5749bd97 --- /dev/null +++ b/packages/plugin-client-prisma/src/conversion.ts @@ -0,0 +1,128 @@ +import { type ColumnType, ColumnTypeEnum } from '@prisma/driver-adapter-utils'; + +export function fieldToColumnType(fieldType: string): ColumnType { + switch (fieldType) { + case 'bool': + return ColumnTypeEnum.Boolean; + case 'bytea': + return ColumnTypeEnum.Bytes; + case 'char': + return ColumnTypeEnum.Text; + case 'int8': + return ColumnTypeEnum.Int64; + case 'int2': + return ColumnTypeEnum.Int32; + case 'int4': + return ColumnTypeEnum.Int32; + case 'regproc': + return ColumnTypeEnum.Text; + case 'text': + return ColumnTypeEnum.Text; + case 'oid': + return ColumnTypeEnum.Int64; + case 'tid': + return ColumnTypeEnum.Text; + case 'xid': + return ColumnTypeEnum.Text; + case 'cid': + return ColumnTypeEnum.Text; + case 'json': + return ColumnTypeEnum.Json; + case 'xml': + return ColumnTypeEnum.Text; + case 'pg_node_tree': + return ColumnTypeEnum.Text; + case 'smgr': + return ColumnTypeEnum.Text; + case 'path': + return ColumnTypeEnum.Text; + case 'polygon': + return ColumnTypeEnum.Text; + case 'cidr': + return ColumnTypeEnum.Text; + case 'float4': + return ColumnTypeEnum.Float; + case 'float8': + return ColumnTypeEnum.Double; + case 'abstime': + return ColumnTypeEnum.Text; + case 'reltime': + return ColumnTypeEnum.Text; + case 'tinterval': + return ColumnTypeEnum.Text; + case 'circle': + return ColumnTypeEnum.Text; + case 'macaddr8': + return ColumnTypeEnum.Text; + case 'money': + return ColumnTypeEnum.Numeric; + case 'macaddr': + return ColumnTypeEnum.Text; + case 'inet': + return ColumnTypeEnum.Text; + case 'aclitem': + return ColumnTypeEnum.Text; + case 'bpchar': + return ColumnTypeEnum.Text; + case 'varchar': + return ColumnTypeEnum.Text; + case 'date': + return ColumnTypeEnum.Date; + case 'time': + return ColumnTypeEnum.Time; + case 'timestamp': + return ColumnTypeEnum.DateTime; + case 'timestamptz': + return ColumnTypeEnum.DateTime; + case 'interval': + return ColumnTypeEnum.Text; + case 'timetz': + return ColumnTypeEnum.Time; + case 'bit': + return ColumnTypeEnum.Text; + case 'varbit': + return ColumnTypeEnum.Text; + case 'numeric': + return ColumnTypeEnum.Numeric; + case 'refcursor': + return ColumnTypeEnum.Text; + case 'regprocedure': + return ColumnTypeEnum.Text; + case 'regoper': + return ColumnTypeEnum.Text; + case 'regoperator': + return ColumnTypeEnum.Text; + case 'regclass': + return ColumnTypeEnum.Text; + case 'regtype': + return ColumnTypeEnum.Text; + case 'uuid': + return ColumnTypeEnum.Uuid; + case 'txid_snapshot': + return ColumnTypeEnum.Text; + case 'pg_lsn': + return ColumnTypeEnum.Text; + case 'pg_ndistinct': + return ColumnTypeEnum.Text; + case 'pg_dependencies': + return ColumnTypeEnum.Text; + case 'tsvector': + return ColumnTypeEnum.Text; + case 'tsquery': + return ColumnTypeEnum.Text; + case 'gtsvector': + return ColumnTypeEnum.Text; + case 'regconfig': + return ColumnTypeEnum.Text; + case 'regdictionary': + return ColumnTypeEnum.Text; + case 'jsonb': + return ColumnTypeEnum.Json; + case 'regnamespace': + return ColumnTypeEnum.Text; + case 'regrole': + return ColumnTypeEnum.Text; + default: + return ColumnTypeEnum.Text; + } +} diff --git a/packages/plugin-client-prisma/src/driver.ts b/packages/plugin-client-prisma/src/driver.ts new file mode 100644 index 000000000..a9dbcf983 --- /dev/null +++ b/packages/plugin-client-prisma/src/driver.ts @@ -0,0 +1,76 @@ +/* eslint-disable @typescript-eslint/require-await */ +import type { + ColumnType, + DriverAdapter, + Query, + Queryable, + Result, + ResultSet, + Transaction +} from '@prisma/driver-adapter-utils'; +import { Debug, err, ok } from '@prisma/driver-adapter-utils'; +import { Responses, SQLPluginResult } from '@xata.io/client'; +import { fieldToColumnType } from './conversion'; + +const debug = Debug('prisma:driver-adapter:xata'); + +type PerformIOResult = Responses.SQLResponse; + +abstract class XataQueryable implements Queryable { + readonly flavour = 'postgres'; + + async queryRaw(query: Query): Promise> { + const tag = '[js::query_raw]'; + debug(`${tag} %O`, query); + + const res = await this.performIO(query); + + if (!res.ok) { + return err(res.error); + } + + const { records, columns = {}, warning } = res.value; + if (warning) debug(`${tag} %O`, warning); + + const [columnNames, columnTypes] = Object.fromEntries(columns as any).reduce( + ([names, types]: [string[], ColumnType[]], [name, { type_name }]: [string, { type_name: string }]) => { + names.push(name); + types.push(fieldToColumnType(type_name)); + return [names, types]; + }, + [[], []] as [string[], ColumnType[]] + ); + + return ok({ columnNames, columnTypes, rows: records as any[] }); + } + + async executeRaw(query: Query): Promise> { + const tag = '[js::execute_raw]'; + debug(`${tag} %O`, query); + + return (await this.performIO(query)).map((r) => r.total ?? 0); + } + + abstract performIO(query: Query): Promise>; +} + +type XataClient = { sql: SQLPluginResult }; + +export class PrismaXataHTTP extends XataQueryable implements DriverAdapter { + constructor(private xata: XataClient) { + super(); + } + + override async performIO(query: Query): Promise> { + const { sql, args: values } = query; + return ok(await this.xata.sql(sql, values)); + } + + startTransaction(): Promise> { + return Promise.reject(new Error('Transactions are not supported in HTTP mode')); + } + + async close() { + return ok(undefined); + } +} diff --git a/packages/plugin-client-prisma/src/index.ts b/packages/plugin-client-prisma/src/index.ts new file mode 100644 index 000000000..de85f9761 --- /dev/null +++ b/packages/plugin-client-prisma/src/index.ts @@ -0,0 +1,12 @@ +import { SQLPlugin, XataPlugin, XataPluginOptions } from '@xata.io/client'; +import { PrismaXataHTTP } from './driver'; + +export class PrismaPlugin extends XataPlugin { + build(pluginOptions: XataPluginOptions) { + const xata = { schema: { tables: pluginOptions.tables }, sql: new SQLPlugin().build(pluginOptions) }; + + return new PrismaXataHTTP(xata, pluginOptions.tables); + } +} + +export * from './driver'; diff --git a/packages/plugin-client-prisma/test/plugin.test.ts b/packages/plugin-client-prisma/test/plugin.test.ts new file mode 100644 index 000000000..ebabfdc9b --- /dev/null +++ b/packages/plugin-client-prisma/test/plugin.test.ts @@ -0,0 +1,13 @@ +import { describe, test } from 'vitest'; +import { PrismaXataHTTP } from '../src/driver'; +import { smokeTest } from './smoke'; +import { BaseClient } from '../../client/src'; + +describe.skip('@xata.io/prisma plugin', () => { + test('run smoke tests', async () => { + const xata = new BaseClient(); + const adapter = new PrismaXataHTTP(xata); + + await smokeTest(adapter); + }); +}); diff --git a/packages/plugin-client-prisma/test/schema.prisma b/packages/plugin-client-prisma/test/schema.prisma new file mode 100644 index 000000000..9248a1ac6 --- /dev/null +++ b/packages/plugin-client-prisma/test/schema.prisma @@ -0,0 +1,116 @@ +generator client { + provider = "prisma-client-js" + output = "../../node_modules/.prisma/client" + previewFeatures = ["driverAdapters"] +} + +datasource db { + provider = "postgres" + url = env("DATABASE_URL") +} + +model type_test { + id Int @id @default(autoincrement()) + smallint_column Int @db.SmallInt + smallint_column_null Int? @db.SmallInt + int_column Int + int_column_null Int? + bigint_column BigInt + bigint_column_null BigInt? + float_column Float @db.Real + float_column_null Float? @db.Real + double_column Float + double_column_null Float? + decimal_column Decimal @db.Decimal(10, 2) + decimal_column_null Decimal? @db.Decimal(10, 2) + boolean_column Boolean + boolean_column_null Boolean? + char_column String @db.Char(10) + char_column_null String? @db.Char(10) + varchar_column String @db.VarChar(255) + varchar_column_null String? @db.VarChar(255) + text_column String + text_column_null String? + date_column DateTime @db.Date + date_column_null DateTime? @db.Date + time_column DateTime @db.Time(0) + time_column_null DateTime? @db.Time(0) + datetime_column DateTime @db.Timestamp(3) + datetime_column_null DateTime? @db.Timestamp(3) + timestamp_column DateTime @db.Timestamp(0) + timestamp_column_null DateTime? @db.Timestamp(0) + json_column Json + json_column_null Json? + enum_column type_test_enum_column + enum_column_null type_test_enum_column_null? +} + +// This will eventually supersede type_test +model type_test_2 { + id String @id @default(cuid()) + datetime_column DateTime @default(now()) @db.Timestamp(3) + datetime_column_null DateTime? @db.Timestamp(3) +} + +model Child { + c String @unique + c_1 String + c_2 String + parentId String? @unique + non_unique String? + id String @id + + @@unique([c_1, c_2]) +} + +model Parent { + p String @unique + p_1 String + p_2 String + non_unique String? + id String @id + + @@unique([p_1, p_2]) +} + +enum type_test_enum_column { + value1 + value2 + value3 +} + +enum type_test_enum_column_null { + value1 + value2 + value3 +} + +model Author { + id Int @id @default(autoincrement()) + firstName String + lastName String + age Int + posts Post[] + + @@map("authors") +} + +model Post { + id Int @id @default(autoincrement()) + title String? + published Boolean @default(false) + authorId Int? + author Author? @relation(fields: [authorId], references: [id]) + + @@index([authorId], name: "author_id") +} + +model Product { + id String @id @default(cuid()) + properties Json + properties_null Json? +} + +model leak_test { + id String @id @default(cuid()) +} diff --git a/packages/plugin-client-prisma/test/smoke.ts b/packages/plugin-client-prisma/test/smoke.ts new file mode 100644 index 000000000..507d74ec0 --- /dev/null +++ b/packages/plugin-client-prisma/test/smoke.ts @@ -0,0 +1,265 @@ +import superjson from 'superjson'; +import { PrismaClient } from '.prisma/client'; +import { setImmediate, setTimeout } from 'node:timers/promises'; +import type { DriverAdapter } from '@prisma/driver-adapter-utils'; + +export async function smokeTest(adapter: DriverAdapter) { + // wait for the database pool to be initialized + await setImmediate(0); + + // @ts-ignore Adapter types do not match + const prisma = new PrismaClient({ adapter }); + + console.log('[nodejs] connecting...'); + await prisma.$connect(); + console.log('[nodejs] connected'); + + const test = new SmokeTest(prisma, adapter.flavour); + + await test.testJSON(); + await test.testTypeTest2(); + await test.$raw(); + await test.testFindManyTypeTest(); + await test.transactionsWithConflits(); + await test.testCreateAndDeleteChildParent(); + await test.interactiveTransactions(); + await test.explicitTransaction(); + + console.log('[nodejs] disconnecting...'); + await prisma.$disconnect(); + console.log('[nodejs] disconnected'); + + console.log('[nodejs] re-connecting...'); + await prisma.$connect(); + console.log('[nodejs] re-connecting'); + + await setTimeout(0); + + console.log('[nodejs] re-disconnecting...'); + await prisma.$disconnect(); + console.log('[nodejs] re-disconnected'); +} + +class SmokeTest { + constructor(private readonly prisma: PrismaClient, readonly flavour: DriverAdapter['flavour']) {} + + async testJSON() { + const json = JSON.stringify({ + foo: 'bar', + baz: 1 + }); + + const created = await this.prisma.product.create({ + data: { + properties: json + }, + select: { + properties: true + } + }); + + console.log('[nodejs] created', superjson.serialize(created).json); + + const resultSet = await this.prisma.product.findMany({}); + console.log('[nodejs] resultSet', superjson.serialize(resultSet).json); + + await this.prisma.product.deleteMany({}); + } + + async transactionsWithConflits() { + await this.prisma.leak_test.deleteMany(); + + const one = async () => { + await this.prisma.$transaction(async (tx) => { + await tx.leak_test.create({ data: {} }); + await setTimeout(1000); + throw new Error('Abort the mission'); + }); + }; + + const two = async () => { + await setTimeout(500); + await this.prisma.leak_test.create({ data: {} }); + }; + + await this.prisma.leak_test.deleteMany(); + await Promise.allSettled([one(), two()]); + } + + async explicitTransaction() { + const [children, totalChildren] = await this.prisma.$transaction( + [this.prisma.child.findMany(), this.prisma.child.count()], + { + isolationLevel: 'Serializable' + } + ); + + console.log('[nodejs] children', superjson.serialize(children).json); + console.log('[nodejs] totalChildren', totalChildren); + } + + async $raw() { + const cleanUp = async () => { + await this.prisma.$executeRaw`DELETE FROM leak_test`; + }; + + await cleanUp(); + + await this.prisma.$executeRaw`INSERT INTO leak_test (id) VALUES (1)`; + const result = await this.prisma.$queryRaw`SELECT * FROM leak_test`; + console.log('[nodejs] result', superjson.serialize(result).json); + + await cleanUp(); + } + + async interactiveTransactions() { + const author = await this.prisma.author.create({ + data: { + firstName: 'Firstname 1 from autoincrement', + lastName: 'Lastname 1 from autoincrement', + age: 99 + } + }); + console.log('[nodejs] author', superjson.serialize(author).json); + + const result = await this.prisma.$transaction(async (tx) => { + await tx.author.deleteMany(); + await tx.post.deleteMany(); + + const author = await tx.author.create({ + data: { + firstName: 'Firstname 2 from autoincrement', + lastName: 'Lastname 2 from autoincrement', + age: 100 + } + }); + const post = await tx.post.create({ + data: { + title: 'Title from transaction', + published: false, + author: { + connect: { + id: author.id + } + } + } + }); + return { author, post }; + }); + + console.log('[nodejs] result', superjson.serialize(result).json); + } + + async testTypeTest2() { + const created = await this.prisma.type_test_2.create({ + data: {} + }); + console.log('[nodejs] created', superjson.serialize(created).json); + + const resultSet = await this.prisma.type_test_2.findMany({}); + console.log('[nodejs] resultSet', superjson.serialize(resultSet).json); + + await this.prisma.type_test_2.deleteMany({}); + } + + async testFindManyTypeTest() { + await this.testFindManyTypeTestMySQL(); + await this.testFindManyTypeTestPostgres(); + } + + private async testFindManyTypeTestMySQL() { + if (this.flavour !== 'mysql') { + return; + } + + const resultSet = await this.prisma.type_test.findMany({ + select: { + smallint_column: true, + int_column: true, + bigint_column: true, + float_column: true, + double_column: true, + decimal_column: true, + boolean_column: true, + char_column: true, + varchar_column: true, + text_column: true, + date_column: true, + time_column: true, + datetime_column: true, + timestamp_column: true, + json_column: true, + enum_column: true + } + }); + console.log('[nodejs] findMany resultSet', superjson.serialize(resultSet).json); + + return resultSet; + } + + private async testFindManyTypeTestPostgres() { + if (this.flavour !== 'postgres') { + return; + } + + const resultSet = await this.prisma.type_test.findMany({ + select: { + smallint_column: true, + int_column: true, + bigint_column: true, + float_column: true, + double_column: true, + decimal_column: true, + boolean_column: true, + char_column: true, + varchar_column: true, + text_column: true, + date_column: true, + time_column: true, + datetime_column: true, + timestamp_column: true, + json_column: true, + enum_column: true + } + }); + console.log('[nodejs] findMany resultSet', superjson.serialize(resultSet).json); + + return resultSet; + } + + async testCreateAndDeleteChildParent() { + /* Delete all child and parent records */ + + await this.prisma.child.deleteMany(); + await this.prisma.parent.deleteMany(); + + /* Create a parent with some new children */ + + await this.prisma.child.create({ + data: { + c: 'c1', + c_1: 'foo', + c_2: 'bar', + id: '0001' + } + }); + + await this.prisma.parent.create({ + data: { + p: 'p1', + p_1: '1', + p_2: '2', + id: '0001' + } + }); + + /* Delete the parent */ + + const resultDeleteMany = await this.prisma.parent.deleteMany({ + where: { + p: 'p1' + } + }); + console.log('[nodejs] resultDeleteMany', superjson.serialize(resultDeleteMany).json); + } +} diff --git a/packages/plugin-client-prisma/tsconfig.json b/packages/plugin-client-prisma/tsconfig.json new file mode 100644 index 000000000..654c56dd1 --- /dev/null +++ b/packages/plugin-client-prisma/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es2020", + "lib": ["esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "es2020", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": false, + "outDir": "dist", + "declaration": true + }, + "include": ["src"], + "exclude": ["node_modules"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1399a6139..16715c03e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -438,6 +438,25 @@ importers: specifier: workspace:* version: link:../client + packages/plugin-client-prisma: + dependencies: + '@prisma/driver-adapter-utils': + specifier: ^5.4.2 + version: 5.4.2 + '@xata.io/client': + specifier: workspace:* + version: link:../client + devDependencies: + '@prisma/client': + specifier: ^5.6.0 + version: 5.6.0(prisma@5.6.0) + prisma: + specifier: ^5.6.0 + version: 5.6.0 + superjson: + specifier: ^2.2.1 + version: 2.2.1 + packages: /@aashutoshrathi/word-wrap@1.2.6: resolution: @@ -4738,6 +4757,41 @@ packages: dev: true optional: true + /@prisma/client@5.6.0(prisma@5.6.0): + resolution: + { integrity: sha512-mUDefQFa1wWqk4+JhKPYq8BdVoFk9NFMBXUI8jAkBfQTtgx8WPx02U2HB/XbAz3GSUJpeJOKJQtNvaAIDs6sug== } + engines: { node: '>=16.13' } + requiresBuild: true + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + dependencies: + '@prisma/engines-version': 5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee + prisma: 5.6.0 + dev: true + + /@prisma/driver-adapter-utils@5.4.2: + resolution: + { integrity: sha512-V+mtlBXBxQuiOufaSH98S3x2j9G1G0+tgnx3lAlfd6YEeceTCcFFhg85rESW9UIshHvULeGFJsG7+qScgGX0Ng== } + dependencies: + debug: 4.3.4(supports-color@9.4.0) + transitivePeerDependencies: + - supports-color + dev: false + + /@prisma/engines-version@5.6.0-32.e95e739751f42d8ca026f6b910f5a2dc5adeaeee: + resolution: + { integrity: sha512-UoFgbV1awGL/3wXuUK3GDaX2SolqczeeJ5b4FVec9tzeGbSWJboPSbT0psSrmgYAKiKnkOPFSLlH6+b+IyOwAw== } + dev: true + + /@prisma/engines@5.6.0: + resolution: + { integrity: sha512-Mt2q+GNJpU2vFn6kif24oRSBQv1KOkYaterQsi0k2/lA+dLvhRX6Lm26gon6PYHwUM8/h8KRgXIUMU0PCLB6bw== } + requiresBuild: true + dev: true + /@protobufjs/aspromise@1.1.2: resolution: { integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ== } @@ -7441,6 +7495,14 @@ packages: engines: { node: '>= 0.6' } dev: true + /copy-anything@3.0.5: + resolution: + { integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== } + engines: { node: '>=12.13' } + dependencies: + is-what: 4.1.16 + dev: true + /core-js-compat@3.32.2: resolution: { integrity: sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ== } @@ -10617,6 +10679,12 @@ packages: call-bind: 1.0.2 dev: true + /is-what@4.1.16: + resolution: + { integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== } + engines: { node: '>=12.13' } + dev: true + /is-windows@1.0.2: resolution: { integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== } @@ -13610,6 +13678,16 @@ packages: parse-ms: 3.0.0 dev: false + /prisma@5.6.0: + resolution: + { integrity: sha512-EEaccku4ZGshdr2cthYHhf7iyvCcXqwJDvnoQRAJg5ge2Tzpv0e2BaMCp+CbbDUwoVTzwgOap9Zp+d4jFa2O9A== } + engines: { node: '>=16.13' } + hasBin: true + requiresBuild: true + dependencies: + '@prisma/engines': 5.6.0 + dev: true + /proc-log@1.0.0: resolution: { integrity: sha512-aCk8AO51s+4JyuYGg3Q/a6gnrlDO09NpVWePtjp7xwphcoQ04x5WAfCyugcsbLooWcMJ87CLkD4+604IckEdhg== } @@ -15209,6 +15287,14 @@ packages: acorn: 8.10.0 dev: true + /superjson@2.2.1: + resolution: + { integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA== } + engines: { node: '>=16' } + dependencies: + copy-anything: 3.0.5 + dev: true + /supports-color@5.5.0: resolution: { integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== }