diff --git a/packages/cli/package.json b/packages/cli/package.json index 975518582210..496e44b3b960 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -183,7 +183,7 @@ "@prisma/config": "workspace:*", "@prisma/dev": "0.20.0", "@prisma/engines": "workspace:*", - "@prisma/studio-core": "0.16.3", + "@prisma/studio-core": "0.21.1", "mysql2": "3.15.3", "postgres": "3.4.7" }, diff --git a/packages/cli/src/Studio.ts b/packages/cli/src/Studio.ts index 2969a7b1bc6d..c1109c2d36d0 100644 --- a/packages/cli/src/Studio.ts +++ b/packages/cli/src/Studio.ts @@ -4,7 +4,7 @@ import { serve } from '@hono/node-server' import type { PrismaConfigInternal } from '@prisma/config' import { arg, type Command, format, HelpError, isError } from '@prisma/internals' import type { Executor, SequenceExecutor } from '@prisma/studio-core/data' -import { serializeError, type StudioBFFRequest } from '@prisma/studio-core/data/bff' +import { type SerializedError, serializeError, type StudioBFFRequest } from '@prisma/studio-core/data/bff' import { createMySQL2Executor } from '@prisma/studio-core/data/mysql2' import { createNodeSQLiteExecutor } from '@prisma/studio-core/data/node-sqlite' import { createPostgresJSExecutor } from '@prisma/studio-core/data/postgresjs' @@ -347,7 +347,7 @@ ${bold('Examples')} const [error, results] = await executor.execute(request.query) if (error) { - return ctx.json([serializeError(error)]) + return ctx.json([serializeBffError(error)]) } return ctx.json([null, results]) @@ -355,19 +355,19 @@ ${bold('Examples')} if (procedure === 'sequence') { if (!('executeSequence' in executor)) { - return ctx.json([[serializeError(new Error('Executor does not support sequences'))]]) + return ctx.json([[serializeBffError(new Error('Executor does not support sequences'))]]) } const [[error0, result0], maybeResult1] = await (executor as SequenceExecutor).executeSequence(request.sequence) if (error0) { - return ctx.json([[serializeError(error0)]]) + return ctx.json([[serializeBffError(error0)]]) } const [error1, result1] = maybeResult1 || [] if (error1) { - return ctx.json([[null, result0], [serializeError(error1)]]) + return ctx.json([[null, result0], [serializeBffError(error1)]]) } return ctx.json([ @@ -376,6 +376,23 @@ ${bold('Examples')} ]) } + if (procedure === 'sql-lint') { + if (!executor.lintSql) { + return ctx.json([serializeBffError(new Error('Executor does not support SQL lint'))]) + } + + const [error, result] = await executor.lintSql({ + schemaVersion: request.schemaVersion, + sql: request.sql, + }) + + if (error) { + return ctx.json([serializeBffError(error)]) + } + + return ctx.json([null, result]) + } + procedure satisfies undefined return ctx.text('Unknown procedure', { status: 500 }) @@ -441,6 +458,54 @@ function getUrlBasePath(url: string | undefined, configPath: string | null): str return url ? process.cwd() : configPath ? dirname(configPath) : process.cwd() } +function serializeBffError(error: unknown): SerializedError { + return getSerializedBffError(error) ?? serializeError(error) +} + +function getSerializedBffError(error: unknown): SerializedError | null { + if (isSerializedError(error)) { + return error + } + + if (!isRecord(error)) { + return null + } + + const nestedError = error.error + + if (isSerializedError(nestedError)) { + return nestedError + } + + const rpcSerializedError = error['@@error'] + + if (isSerializedError(rpcSerializedError)) { + return rpcSerializedError + } + + return null +} + +function isSerializedError(error: unknown): error is SerializedError { + if (!isRecord(error)) { + return false + } + + if (typeof error.name !== 'string' || typeof error.message !== 'string') { + return false + } + + if (error.errors === undefined) { + return true + } + + return Array.isArray(error.errors) && error.errors.every(isSerializedError) +} + +function isRecord(value: unknown): value is Record { + return typeof value === 'object' && value !== null +} + function isAccelerateProtocol(protocol: string): boolean { return protocol === 'prisma' || protocol === 'prisma+postgres' } diff --git a/packages/cli/src/__tests__/Studio.vitest.ts b/packages/cli/src/__tests__/Studio.vitest.ts index 278c770a596b..03886679a3c3 100644 --- a/packages/cli/src/__tests__/Studio.vitest.ts +++ b/packages/cli/src/__tests__/Studio.vitest.ts @@ -2,6 +2,23 @@ import { defaultTestConfig } from '@prisma/config' import { beforeEach, describe, expect, test, vi } from 'vitest' const createPoolMock = vi.fn(() => ({ end: vi.fn() })) +const serveMock = vi.fn(() => ({ close: vi.fn() })) +const createPostgresJSExecutorMock = vi.fn(() => ({ + execute: vi.fn(), +})) +const serializeErrorMock = vi.fn((error: unknown) => { + if (error instanceof Error) { + return { + message: error.message, + name: error.name, + } + } + + return { + message: JSON.stringify(error), + name: 'UnknownError', + } +}) vi.mock('mysql2/promise', () => { return { @@ -11,7 +28,7 @@ vi.mock('mysql2/promise', () => { vi.mock('@hono/node-server', () => { return { - serve: vi.fn(() => ({ close: vi.fn() })), + serve: serveMock, } }) @@ -25,7 +42,7 @@ vi.mock('@prisma/studio-core/data/mysql2', () => { vi.mock('@prisma/studio-core/data/bff', () => { return { - serializeError: vi.fn(() => ({ message: 'mock-error' })), + serializeError: serializeErrorMock, } }) @@ -39,9 +56,7 @@ vi.mock('@prisma/studio-core/data/node-sqlite', () => { vi.mock('@prisma/studio-core/data/postgresjs', () => { return { - createPostgresJSExecutor: vi.fn(() => ({ - execute: vi.fn(), - })), + createPostgresJSExecutor: createPostgresJSExecutorMock, } }) @@ -49,6 +64,9 @@ describe('Studio MySQL URL compatibility', () => { beforeEach(() => { vi.resetModules() createPoolMock.mockClear() + createPostgresJSExecutorMock.mockClear() + serveMock.mockClear() + serializeErrorMock.mockClear() }) test('converts sslaccept=strict to mysql2 ssl JSON', async () => { @@ -120,3 +138,192 @@ describe('Studio MySQL URL compatibility', () => { expect(passedUrl.searchParams.get('ssl')).toBe('{"rejectUnauthorized":false}') }) }) + +describe('Studio BFF', () => { + beforeEach(() => { + vi.resetModules() + createPoolMock.mockClear() + createPostgresJSExecutorMock.mockClear() + serveMock.mockClear() + serializeErrorMock.mockClear() + }) + + test('routes sql-lint requests to executor.lintSql', async () => { + const lintSqlMock = vi.fn(() => + Promise.resolve([ + null, + { + diagnostics: [{ from: 0, message: 'lint-ok', severity: 'info', to: 1 }], + schemaVersion: 'v1', + }, + ]), + ) + + await startStudioBff({ + execute: vi.fn(), + lintSql: lintSqlMock, + }) + + const response = await getBffResponse({ + procedure: 'sql-lint', + schemaVersion: 'v1', + sql: 'select 1', + }) + + expect(lintSqlMock).toHaveBeenCalledWith({ + schemaVersion: 'v1', + sql: 'select 1', + }) + expect(await response.json()).toEqual([ + null, + { + diagnostics: [{ from: 0, message: 'lint-ok', severity: 'info', to: 1 }], + schemaVersion: 'v1', + }, + ]) + }) + + test('unwraps RPC-serialized sql-lint errors', async () => { + await startStudioBff({ + execute: vi.fn(), + lintSql: vi.fn(() => + Promise.resolve([ + { + '@@error': { + message: 'relation "missing_table" does not exist', + name: 'PostgresError', + }, + }, + ]), + ), + }) + + const response = await getBffResponse({ + procedure: 'sql-lint', + schemaVersion: 'v1', + sql: 'select * from missing_table', + }) + + expect(serializeErrorMock).not.toHaveBeenCalled() + expect(await response.json()).toEqual([ + { + message: 'relation "missing_table" does not exist', + name: 'PostgresError', + }, + ]) + }) + + test('passes through top-level serialized sql-lint errors', async () => { + await startStudioBff({ + execute: vi.fn(), + lintSql: vi.fn(() => + Promise.resolve([ + { + message: 'syntax error at or near "from"', + name: 'PostgresError', + }, + ]), + ), + }) + + const response = await getBffResponse({ + procedure: 'sql-lint', + schemaVersion: 'v1', + sql: 'select from', + }) + + expect(serializeErrorMock).not.toHaveBeenCalled() + expect(await response.json()).toEqual([ + { + message: 'syntax error at or near "from"', + name: 'PostgresError', + }, + ]) + }) + + test('unwraps nested serialized sql-lint errors', async () => { + await startStudioBff({ + execute: vi.fn(), + lintSql: vi.fn(() => + Promise.resolve([ + { + error: { + message: 'relation "users" does not exist', + name: 'PostgresError', + }, + }, + ]), + ), + }) + + const response = await getBffResponse({ + procedure: 'sql-lint', + schemaVersion: 'v1', + sql: 'select * from users', + }) + + expect(serializeErrorMock).not.toHaveBeenCalled() + expect(await response.json()).toEqual([ + { + message: 'relation "users" does not exist', + name: 'PostgresError', + }, + ]) + }) + + test('falls back to serializeError for unknown sql-lint error shapes', async () => { + await startStudioBff({ + execute: vi.fn(), + lintSql: vi.fn(() => + Promise.resolve([ + { + message: 'missing name field', + } as never, + ]), + ), + }) + + const response = await getBffResponse({ + procedure: 'sql-lint', + schemaVersion: 'v1', + sql: 'select 1', + }) + + expect(serializeErrorMock).toHaveBeenCalledTimes(1) + expect(await response.json()).toEqual([ + { + message: '{"message":"missing name field"}', + name: 'UnknownError', + }, + ]) + }) +}) + +async function getBffResponse(body: unknown): Promise { + const fetchHandler = serveMock.mock.calls.at(-1)?.[0]?.fetch as ((request: Request) => Promise) | undefined + + if (!fetchHandler) { + throw new Error('Studio server fetch handler was not registered') + } + + return fetchHandler( + new Request('http://localhost:5555/bff', { + body: JSON.stringify(body), + headers: { + 'content-type': 'application/json', + }, + method: 'POST', + }), + ) +} + +async function startStudioBff(executor: { execute: ReturnType; lintSql?: ReturnType }) { + createPostgresJSExecutorMock.mockReturnValueOnce(executor) + + const { Studio } = await import('../Studio') + + await Studio.new().parse( + ['--browser', 'none', '--port', '5555', '--url', 'postgresql://user:password@localhost:5432/db'], + defaultTestConfig(), + ) +} diff --git a/packages/client-generator-js/package.json b/packages/client-generator-js/package.json index 0f35d2bb8703..eae2ed64d205 100644 --- a/packages/client-generator-js/package.json +++ b/packages/client-generator-js/package.json @@ -28,7 +28,7 @@ "@prisma/client-common": "workspace:*", "@prisma/debug": "workspace:*", "@prisma/dmmf": "workspace:*", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/engines-version": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/fetch-engine": "workspace:*", "@prisma/generator": "workspace:*", "@prisma/get-platform": "workspace:*", diff --git a/packages/client-generator-ts/package.json b/packages/client-generator-ts/package.json index a80322797155..48c41ad84759 100644 --- a/packages/client-generator-ts/package.json +++ b/packages/client-generator-ts/package.json @@ -28,7 +28,7 @@ "@prisma/client-common": "workspace:*", "@prisma/debug": "workspace:*", "@prisma/dmmf": "workspace:*", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/engines-version": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/fetch-engine": "workspace:*", "@prisma/generator": "workspace:*", "@prisma/get-platform": "workspace:*", diff --git a/packages/client-runtime-utils/src/nullTypes.ts b/packages/client-runtime-utils/src/nullTypes.ts index bcc78145c2e7..1b7adb44a870 100644 --- a/packages/client-runtime-utils/src/nullTypes.ts +++ b/packages/client-runtime-utils/src/nullTypes.ts @@ -4,10 +4,20 @@ */ const secret = Symbol() +/** + * Global symbol used to identify ObjectEnumValue instances across bundle + * boundaries. `Symbol.for()` returns the same symbol globally, so it works + * even when multiple copies of this module are loaded (e.g., browser and + * server bundles in Next.js, or HMR reloads). + * See: https://github.com/prisma/prisma/issues/29257 + */ +const PRISMA_OBJECT_ENUM_VALUE = Symbol.for('prisma.objectEnumValue') + /** * Base class for unique values of object-valued enums. */ export abstract class ObjectEnumValue { + readonly [PRISMA_OBJECT_ENUM_VALUE] = true #representation: string constructor(arg?: symbol) { @@ -80,6 +90,19 @@ export const DbNull = new DbNullClass(secret) export const JsonNull = new JsonNullClass(secret) export const AnyNull = new AnyNullClass(secret) +/** + * Check if a value is an ObjectEnumValue instance. Uses a global symbol + * instead of instanceof to work across bundle boundaries (e.g., when a + * Next.js app bundles browser and server code separately, creating duplicate + * module instances of @prisma/client-runtime-utils). + * See: https://github.com/prisma/prisma/issues/29257 + */ +export function isObjectEnumValue(value: unknown): value is ObjectEnumValue { + return ( + typeof value === 'object' && value !== null && (value as Record)[PRISMA_OBJECT_ENUM_VALUE] === true + ) +} + /** * Check if a value is the DBNull singleton instance. */ diff --git a/packages/client/package.json b/packages/client/package.json index a86e9cd4fa18..e37ecd83df91 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -198,7 +198,7 @@ "@prisma/dmmf": "workspace:*", "@prisma/driver-adapter-utils": "workspace:*", "@prisma/engines": "workspace:*", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/engines-version": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/fetch-engine": "workspace:*", "@prisma/generator": "workspace:*", "@prisma/generator-helper": "workspace:*", @@ -210,7 +210,7 @@ "@prisma/migrate": "workspace:*", "@prisma/param-graph": "workspace:*", "@prisma/param-graph-builder": "workspace:*", - "@prisma/query-compiler-wasm": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/query-compiler-wasm": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/query-plan-executor": "workspace:*", "@prisma/sqlcommenter": "workspace:*", "@prisma/sqlcommenter-trace-context": "workspace:*", diff --git a/packages/client/src/runtime/core/errorRendering/ArgumentsRenderingTree.ts b/packages/client/src/runtime/core/errorRendering/ArgumentsRenderingTree.ts index 0405223e8337..3ae57b8ce3d6 100644 --- a/packages/client/src/runtime/core/errorRendering/ArgumentsRenderingTree.ts +++ b/packages/client/src/runtime/core/errorRendering/ArgumentsRenderingTree.ts @@ -1,5 +1,5 @@ import { uncapitalize } from '@prisma/client-common' -import { ObjectEnumValue } from '@prisma/client-runtime-utils' +import { isObjectEnumValue } from '@prisma/client-runtime-utils' import { Writer } from '@prisma/ts-builders' import { ErrorFormat } from '../../getPrismaClient' @@ -95,7 +95,7 @@ function buildInputValue(value: unknown) { return new ScalarValue(`new Date("${dateStr}")`) } - if (value instanceof ObjectEnumValue) { + if (isObjectEnumValue(value)) { return new ScalarValue(`Prisma.${value._getName()}`) } diff --git a/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.ts b/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.ts index 76f942fc6b54..bb0addfc6657 100644 --- a/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.ts +++ b/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.test.ts @@ -784,6 +784,101 @@ test('args - AnyNull field', () => { `) }) +function makeCrossBundleNullValue(name: string) { + const value = Object.create(null) + value[Symbol.for('prisma.objectEnumValue')] = true + value._getName = () => name + value._getNamespace = () => 'NullTypes' + return value +} + +test('args - cross-bundle DbNull serializes correctly', () => { + expect( + serialize({ + modelName: 'User', + action: 'findMany', + args: { where: { jsonColumn: makeCrossBundleNullValue('DbNull') } }, + }), + ).toMatchInlineSnapshot(` + "{ + "modelName": "User", + "action": "findMany", + "query": { + "arguments": { + "where": { + "jsonColumn": { + "$type": "Enum", + "value": "DbNull" + } + } + }, + "selection": { + "$composites": true, + "$scalars": true + } + } + }" + `) +}) + +test('args - cross-bundle JsonNull serializes correctly', () => { + expect( + serialize({ + modelName: 'User', + action: 'findMany', + args: { where: { jsonColumn: makeCrossBundleNullValue('JsonNull') } }, + }), + ).toMatchInlineSnapshot(` + "{ + "modelName": "User", + "action": "findMany", + "query": { + "arguments": { + "where": { + "jsonColumn": { + "$type": "Enum", + "value": "JsonNull" + } + } + }, + "selection": { + "$composites": true, + "$scalars": true + } + } + }" + `) +}) + +test('args - cross-bundle AnyNull serializes correctly', () => { + expect( + serialize({ + modelName: 'User', + action: 'findMany', + args: { where: { jsonColumn: makeCrossBundleNullValue('AnyNull') } }, + }), + ).toMatchInlineSnapshot(` + "{ + "modelName": "User", + "action": "findMany", + "query": { + "arguments": { + "where": { + "jsonColumn": { + "$type": "Enum", + "value": "AnyNull" + } + } + }, + "selection": { + "$composites": true, + "$scalars": true + } + } + }" + `) +}) + test('args - array', () => { expect( serialize({ diff --git a/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.ts b/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.ts index 443ecc13d783..34ed986f1c73 100644 --- a/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.ts +++ b/packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.ts @@ -1,5 +1,5 @@ import { RuntimeDataModel, RuntimeModel, uncapitalize } from '@prisma/client-common' -import { isAnyNull, isDbNull, isJsonNull, ObjectEnumValue } from '@prisma/client-runtime-utils' +import { isObjectEnumValue } from '@prisma/client-runtime-utils' import { assertNever } from '@prisma/internals' import { ErrorFormat } from '../../getPrismaClient' @@ -324,11 +324,12 @@ function serializeArgumentsValue( return { $type: 'Decimal', value: jsValue.toFixed() } } - if (jsValue instanceof ObjectEnumValue) { - if (!isDbNull(jsValue) && !isJsonNull(jsValue) && !isAnyNull(jsValue)) { - throw new Error('Invalid ObjectEnumValue') + if (isObjectEnumValue(jsValue)) { + const name = jsValue._getName() + if (name !== 'DbNull' && name !== 'JsonNull' && name !== 'AnyNull') { + throw new Error(`Invalid ObjectEnumValue: expected DbNull, JsonNull, or AnyNull, got ${name}`) } - return { $type: 'Enum', value: jsValue._getName() } + return { $type: 'Enum', value: name } } if (isJSONConvertible(jsValue)) { diff --git a/packages/client/src/runtime/index-browser.ts b/packages/client/src/runtime/index-browser.ts index 7d0073b5c486..e94ba26355f1 100644 --- a/packages/client/src/runtime/index-browser.ts +++ b/packages/client/src/runtime/index-browser.ts @@ -2,7 +2,16 @@ import * as Public from './core/public' export { makeStrictEnum } from './strictEnum' export { getRuntime } from './utils/getRuntime' -export { AnyNull, DbNull, isAnyNull, isDbNull, isJsonNull, JsonNull, NullTypes } from '@prisma/client-runtime-utils' +export { + AnyNull, + DbNull, + isAnyNull, + isDbNull, + isJsonNull, + isObjectEnumValue, + JsonNull, + NullTypes, +} from '@prisma/client-runtime-utils' export { Decimal } from '@prisma/client-runtime-utils' export { Public } diff --git a/packages/client/src/runtime/index.ts b/packages/client/src/runtime/index.ts index 8c4dbcd8d95c..765cfc302a18 100644 --- a/packages/client/src/runtime/index.ts +++ b/packages/client/src/runtime/index.ts @@ -43,6 +43,7 @@ export { isAnyNull, isDbNull, isJsonNull, + isObjectEnumValue, JsonNull, NullTypes, ObjectEnumValue, diff --git a/packages/client/src/runtime/utils/deepCloneArgs.test.ts b/packages/client/src/runtime/utils/deepCloneArgs.test.ts index 64f24cec483d..ee0c87c294d6 100644 --- a/packages/client/src/runtime/utils/deepCloneArgs.test.ts +++ b/packages/client/src/runtime/utils/deepCloneArgs.test.ts @@ -39,6 +39,18 @@ describe('deepCloneArgs', () => { expect(isSkip(cloned.data[0])).toBe(true) }) + test('preserves cross-bundle ObjectEnumValue through cloning', () => { + const crossBundleDbNull = Object.create(null) + crossBundleDbNull[Symbol.for('prisma.objectEnumValue')] = true + crossBundleDbNull._getName = () => 'DbNull' + crossBundleDbNull._getNamespace = () => 'NullTypes' + + const args = { data: { field: crossBundleDbNull } } + const cloned = deepCloneArgs(args) as Record + + expect(cloned.data.field).toBe(crossBundleDbNull) + }) + test('still deep clones regular objects', () => { const inner = { foo: 'bar' } const args = { data: inner } diff --git a/packages/client/src/runtime/utils/deepCloneArgs.ts b/packages/client/src/runtime/utils/deepCloneArgs.ts index 2843f8df71a7..baf83822e731 100644 --- a/packages/client/src/runtime/utils/deepCloneArgs.ts +++ b/packages/client/src/runtime/utils/deepCloneArgs.ts @@ -1,4 +1,4 @@ -import { Decimal, ObjectEnumValue, Sql } from '@prisma/client-runtime-utils' +import { Decimal, isObjectEnumValue, Sql } from '@prisma/client-runtime-utils' import { assertNever } from '@prisma/internals' import { isFieldRef } from '../core/model/FieldRef' @@ -44,7 +44,7 @@ function cloneTypedSql(rawParam: UnknownTypedSql): UnknownTypedSql { // based on https://github.com/lukeed/klona/blob/v2.0.6/src/index.js function deepCloneValue(x: JsInputValue): JsInputValue { - if (typeof x !== 'object' || x == null || x instanceof ObjectEnumValue || isFieldRef(x) || isSkip(x)) { + if (typeof x !== 'object' || x == null || isObjectEnumValue(x) || isFieldRef(x) || isSkip(x)) { return x } diff --git a/packages/client/tests/functional/json-null-types/tests.ts b/packages/client/tests/functional/json-null-types/tests.ts index 8f715d8ec0b1..e37543a1c59b 100644 --- a/packages/client/tests/functional/json-null-types/tests.ts +++ b/packages/client/tests/functional/json-null-types/tests.ts @@ -72,15 +72,14 @@ testMatrix.setupTestSuite( expect(Prisma.AnyNull).toBeInstanceOf(Prisma.NullTypes.AnyNull) }) - test('custom instances are not allowed', async () => { - await expect( - prisma.requiredJsonField.create({ - data: { - // @ts-expect-error - json: new Prisma.NullTypes.JsonNull(), - }, - }), - ).rejects.toMatchPrismaErrorInlineSnapshot(`"Invalid ObjectEnumValue"`) + test('custom instances are accepted for cross-bundle compatibility', async () => { + const record = await prisma.requiredJsonField.create({ + data: { + // @ts-expect-error + json: new Prisma.NullTypes.JsonNull(), + }, + }) + expect(record.json).toBeNull() }) }) }, diff --git a/packages/engines/package.json b/packages/engines/package.json index 11ebc17867e8..523d6327b3e2 100644 --- a/packages/engines/package.json +++ b/packages/engines/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@prisma/debug": "workspace:*", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/engines-version": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/fetch-engine": "workspace:*", "@prisma/get-platform": "workspace:*" }, diff --git a/packages/fetch-engine/package.json b/packages/fetch-engine/package.json index 3d85667e9756..986c4e1724c4 100644 --- a/packages/fetch-engine/package.json +++ b/packages/fetch-engine/package.json @@ -37,7 +37,7 @@ }, "dependencies": { "@prisma/debug": "workspace:*", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/engines-version": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/get-platform": "workspace:*" }, "scripts": { diff --git a/packages/internals/package.json b/packages/internals/package.json index f012dd2c64aa..f1a14de408c6 100644 --- a/packages/internals/package.json +++ b/packages/internals/package.json @@ -74,8 +74,8 @@ "@prisma/generator": "workspace:*", "@prisma/generator-helper": "workspace:*", "@prisma/get-platform": "workspace:*", - "@prisma/prisma-schema-wasm": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", - "@prisma/schema-engine-wasm": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/prisma-schema-wasm": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", + "@prisma/schema-engine-wasm": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/schema-files-loader": "workspace:*", "arg": "5.0.2", "prompts": "2.4.2" diff --git a/packages/migrate/package.json b/packages/migrate/package.json index 6bb1d153752e..7747144fd520 100644 --- a/packages/migrate/package.json +++ b/packages/migrate/package.json @@ -54,7 +54,7 @@ "@prisma/config": "workspace:*", "@prisma/debug": "workspace:*", "@prisma/driver-adapter-utils": "workspace:*", - "@prisma/engines-version": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/engines-version": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "@prisma/generator": "workspace:*", "@prisma/get-platform": "workspace:*", "@prisma/internals": "workspace:*", diff --git a/packages/schema-files-loader/package.json b/packages/schema-files-loader/package.json index 3ab27ce258a2..7cf695ba065f 100644 --- a/packages/schema-files-loader/package.json +++ b/packages/schema-files-loader/package.json @@ -22,7 +22,7 @@ ], "sideEffects": false, "dependencies": { - "@prisma/prisma-schema-wasm": "7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919", + "@prisma/prisma-schema-wasm": "7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2", "fs-extra": "11.3.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c38bb0ccc19..0279eb76867b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -431,8 +431,8 @@ importers: specifier: workspace:* version: link:../engines '@prisma/studio-core': - specifier: 0.16.3 - version: 0.16.3 + specifier: 0.21.1 + version: 0.21.1 mysql2: specifier: 3.15.3 version: 3.15.3 @@ -730,8 +730,8 @@ importers: specifier: workspace:* version: link:../engines '@prisma/engines-version': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/fetch-engine': specifier: workspace:* version: link:../fetch-engine @@ -766,8 +766,8 @@ importers: specifier: workspace:* version: link:../param-graph-builder '@prisma/query-compiler-wasm': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/query-plan-executor': specifier: workspace:* version: link:../query-plan-executor @@ -1010,8 +1010,8 @@ importers: specifier: workspace:* version: link:../dmmf '@prisma/engines-version': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/fetch-engine': specifier: workspace:* version: link:../fetch-engine @@ -1083,8 +1083,8 @@ importers: specifier: workspace:* version: link:../dmmf '@prisma/engines-version': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/fetch-engine': specifier: workspace:* version: link:../fetch-engine @@ -1199,8 +1199,8 @@ importers: specifier: workspace:* version: link:../debug '@prisma/engines-version': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/fetch-engine': specifier: workspace:* version: link:../fetch-engine @@ -1233,8 +1233,8 @@ importers: specifier: workspace:* version: link:../debug '@prisma/engines-version': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/get-platform': specifier: workspace:* version: link:../get-platform @@ -1501,11 +1501,11 @@ importers: specifier: workspace:* version: link:../get-platform '@prisma/prisma-schema-wasm': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/schema-engine-wasm': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/schema-files-loader': specifier: workspace:* version: link:../schema-files-loader @@ -1645,8 +1645,8 @@ importers: specifier: workspace:* version: link:../driver-adapter-utils '@prisma/engines-version': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 '@prisma/generator': specifier: workspace:* version: link:../generator @@ -1807,8 +1807,8 @@ importers: packages/schema-files-loader: dependencies: '@prisma/prisma-schema-wasm': - specifier: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 - version: 7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919 + specifier: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 + version: 7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2 fs-extra: specifier: 11.3.0 version: 11.3.0 @@ -3566,8 +3566,8 @@ packages: '@prisma/dev@0.20.0': resolution: {integrity: sha512-ovlBYwWor0OzG+yH4J3Ot+AneD818BttLA+Ii7wjbcLHUrnC4tbUPVGyNd3c/+71KETPKZfjhkTSpdS15dmXNQ==} - '@prisma/engines-version@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': - resolution: {integrity: sha512-5FIKY3KoYQlBuZC2yc16EXfVRQ8HY+fLqgxkYfWCtKhRb3ajCRzP/rPeoSx11+NueJDANdh4hjY36mdmrTcGSg==} + '@prisma/engines-version@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': + resolution: {integrity: sha512-Cc8tbAHzLfoq3esQvGkyDW+F+XjqiNFLGDyN98wdDMMk/IWaBUkEtGRrU9S+/79dmRAnFRjSYFWTimcHWHQROg==} '@prisma/get-platform@7.2.0': resolution: {integrity: sha512-k1V0l0Td1732EHpAfi2eySTezyllok9dXb6UQanajkJQzPUGi3vO2z7jdkz67SypFTdmbnyGYxvEvYZdZsMAVA==} @@ -3578,20 +3578,20 @@ packages: '@prisma/ppg@1.0.1': resolution: {integrity: sha512-rRRXuPPerXwNWjSA3OE0e/bqXSTfsE82EsMvoiluc0fN0DizQSe3937/Tnl5+DPbxY5rdAOlYjWXG0A2wwTbKA==} - '@prisma/prisma-schema-wasm@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': - resolution: {integrity: sha512-DV5lGaN01UD4t9kilHXekw7oruBvigjkvYspaCq+D961zAYJrXuSDVXe4wM0EDVml0ujoa3apNf/QRxv0ecVuA==} + '@prisma/prisma-schema-wasm@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': + resolution: {integrity: sha512-WSzz3woNQDkSEvtWYbsQHNa4rpOsVQIn3hgJfF2ZvDplM1WpR9jQhcKg+oJvkvuw1L4U6s8DJwis+1OPxdKP4w==} - '@prisma/query-compiler-wasm@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': - resolution: {integrity: sha512-kjrNCKHwoEWp+5TNDPJPYtkjnA23QQaqiOnxb04Tq31fDd1d17ilMnq9nDjxzx7//WgGXONbXQBHvnLG5+GZSw==} + '@prisma/query-compiler-wasm@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': + resolution: {integrity: sha512-yH+zlS0ppi6IByxKRnMXxr31xgT0oGEMWCXIWSMDX7YyQAaO/hJwEmylZ4RZEdzX3sH77vIjGgMyo8x0tL7LKg==} '@prisma/query-plan-executor@7.2.0': resolution: {integrity: sha512-EOZmNzcV8uJ0mae3DhTsiHgoNCuu1J9mULQpGCh62zN3PxPTd+qI9tJvk5jOst8WHKQNwJWR3b39t0XvfBB0WQ==} - '@prisma/schema-engine-wasm@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': - resolution: {integrity: sha512-v7E/pxOvzJyILTK5ZvBs7fLjcoFPG2t6BdnAsfKIZtQZlQz7TyTC3kkZvcigtnV/6/ktVOsd0RQFIk0rD4e5lg==} + '@prisma/schema-engine-wasm@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': + resolution: {integrity: sha512-K24B6BuekBE78rENW0iSSBaQR23Z6zlz+Ob0KmsMB6W8LFMKrP9qd7ewPnHUvGfCD5SJthisYvtEr0y+nktblQ==} - '@prisma/studio-core@0.16.3': - resolution: {integrity: sha512-mlORrIeF2GwshPqRR6Oho3b4GC9oupTjWu0R09qosjtORfihgYoJmW201Yvnyj99wZRz+vw9NnS9pH6LQ5Dx5w==} + '@prisma/studio-core@0.21.1': + resolution: {integrity: sha512-bOGqG/eMQtKC0XVvcVLRmhWWzm/I+0QUWqAEhEBtetpuS3k3V4IWqKGUONkAIT223DNXJMxMtZp36b1FmcdPeg==} engines: {node: ^20.19 || ^22.12 || ^24.0, pnpm: '8'} peerDependencies: '@types/react': ^18.0.0 || ^19.0.0 @@ -10059,7 +10059,7 @@ snapshots: transitivePeerDependencies: - typescript - '@prisma/engines-version@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': {} + '@prisma/engines-version@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': {} '@prisma/get-platform@7.2.0': dependencies: @@ -10076,15 +10076,15 @@ snapshots: - bufferutil - utf-8-validate - '@prisma/prisma-schema-wasm@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': {} + '@prisma/prisma-schema-wasm@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': {} - '@prisma/query-compiler-wasm@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': {} + '@prisma/query-compiler-wasm@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': {} '@prisma/query-plan-executor@7.2.0': {} - '@prisma/schema-engine-wasm@7.5.0-10.94a226be1cf2967af2541cca5529f0f7ba866919': {} + '@prisma/schema-engine-wasm@7.5.0-13.0f1690a1b5dcd01b5341a4f411f07767f1f76fc2': {} - '@prisma/studio-core@0.16.3': {} + '@prisma/studio-core@0.21.1': {} '@redocly/ajv@8.17.1': dependencies: