Skip to content

Commit

Permalink
feat(schema-files-loader): Read preview feature from invalid schemas
Browse files Browse the repository at this point in the history
Integrates prisma/prisma-engines#4875.
Adapts `get_config` to changes from internals.

Closes prisma/team-orm#1143
  • Loading branch information
SevInf committed May 30, 2024
1 parent c5a3c66 commit e9d8c79
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 7 deletions.
45 changes: 43 additions & 2 deletions packages/internals/src/engine-commands/getConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,33 @@ import { ErrorArea, getWasmError, isWasmPanic, RustPanic, WasmPanic } from '../p
import { type SchemaFileInput, toMultipleSchemas } from '../utils/schemaFileInput'
import { prismaSchemaWasm } from '../wasm'
import { addVersionDetailsToErrorMessage } from './errorHelpers'
import { createDebugErrorType, parseQueryEngineError, QueryEngineErrorInit } from './queryEngineCommons'
import {
createDebugErrorType,
createSchemaValidationError,
parseQueryEngineError,
QueryEngineErrorInit,
} from './queryEngineCommons'
import { relativizePathInPSLError } from './relativizePathInPSLError'

const debug = Debug('prisma:getConfig')
const SCHEMA_VALIDATION_ERROR_CODE = 'P1012'

export interface GetConfigResponse {
config: ConfigMetaFormat
errors: GetConfigValidationError[]
}

export interface ConfigMetaFormat {
datasources: DataSource[] | []
generators: GeneratorConfig[] | []
warnings: string[] | []
}

interface GetConfigValidationError {
fileName: string | null
message: string
}

export type GetConfigOptions = {
datamodel: SchemaFileInput
cwd?: string
Expand Down Expand Up @@ -106,14 +123,24 @@ export async function getConfig(options: GetConfigOptions): Promise<ConfigMetaFo
E.chainW(({ result }) =>
// NOTE: this should never fail, as we expect returned values to be valid JSON-serializable strings
E.tryCatch(
() => JSON.parse(result) as ConfigMetaFormat,
() => JSON.parse(result) as GetConfigResponse,
(e) => ({
type: 'parse-json' as const,
reason: 'Unable to parse JSON',
error: e as Error,
}),
),
),
E.chainW((response) => {
if (response.errors.length > 0) {
return E.left({
type: 'validation-error' as const,
reason: '(get-config wasm)',
error: response.errors,
})
}
return E.right(response.config)
}),
)

if (E.isRight(configEither)) {
Expand Down Expand Up @@ -154,6 +181,14 @@ export async function getConfig(options: GetConfigOptions): Promise<ConfigMetaFo
const errorOutput = e.error.message
return new GetConfigError(parseQueryEngineError({ errorOutput, reason: e.reason }))
})
.with({ type: 'validation-error' }, (e) => {
return new GetConfigError({
_tag: 'parsed',
errorCode: SCHEMA_VALIDATION_ERROR_CODE,
reason: createSchemaValidationError(e.reason),
message: formatErrors(e.error),
})
})
.otherwise((e) => {
debugErrorType(e)
return new GetConfigError({ _tag: 'unparsed', message: e.error.message, reason: e.reason })
Expand Down Expand Up @@ -187,3 +222,9 @@ async function resolveBinaryTargets(generator: GeneratorConfig) {
generator.binaryTargets = [{ fromEnvVar: null, value: await getBinaryTargetForCurrentPlatform(), native: true }]
}
}

function formatErrors(errors: GetConfigValidationError[]) {
const formattedErrors = errors.map((e) => relativizePathInPSLError(e.message)).join('\n\n')
const errorCount = `Validation Error Count: ${errors.length}`
return `${formattedErrors}\n${errorCount}`
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const createDebugErrorType =
debug(`error of type "${type}" in ${fnName}:\n`, { reason, error })
}

function createSchemaValidationError(reason: string) {
export function createSchemaValidationError(reason: string) {
return `${red(bold('Prisma schema validation'))} - ${reason}`
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
generator client {
provider = "prisma-client-js"
previewFeatures = ["prismaSchemaFolder"]
}

model M {
field
Let me tell you a story about something.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// this is b
13 changes: 13 additions & 0 deletions packages/schema-files-loader/src/loadRelatedSchemaFiles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,16 @@ test('with feature enabled', async () => {
const files = await loadRelatedSchemaFiles(fixturePath('related-feature', 'a.prisma'))
expect(files).toEqual([loadedFile('related-feature', 'a.prisma'), loadedFile('related-feature', 'b.prisma')])
})

test('with feature enabled, starting from a file with no generator block', async () => {
const files = await loadRelatedSchemaFiles(fixturePath('related-feature', 'b.prisma'))
expect(files).toEqual([loadedFile('related-feature', 'a.prisma'), loadedFile('related-feature', 'b.prisma')])
})

test('invalid schema and feature enabled', async () => {
const files = await loadRelatedSchemaFiles(fixturePath('related-feature-invalid-schema', 'a.prisma'))
expect(files).toEqual([
loadedFile('related-feature-invalid-schema', 'a.prisma'),
loadedFile('related-feature-invalid-schema', 'b.prisma'),
])
})
6 changes: 3 additions & 3 deletions packages/schema-files-loader/src/loadRelatedSchemaFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { get_config } from '@prisma/prisma-schema-wasm'

import { LoadedFile, loadSchemaFiles } from './loadSchemaFiles'
import { FilesResolver, realFsResolver } from './resolver'
import { ConfigMetaFormat, usesPrismaSchemaFolder } from './usesPrismaSchemaFolder'
import { GetConfigResponse, usesPrismaSchemaFolder } from './usesPrismaSchemaFolder'

/**
* Given a single file path, returns
Expand Down Expand Up @@ -38,8 +38,8 @@ function isPrismaFolderEnabled(files: LoadedFile[]): boolean {
})

try {
const response = JSON.parse(get_config(params)) as ConfigMetaFormat
return usesPrismaSchemaFolder(response)
const response = JSON.parse(get_config(params)) as GetConfigResponse
return usesPrismaSchemaFolder(response.config)
} catch (e) {
return false
}
Expand Down
6 changes: 5 additions & 1 deletion packages/schema-files-loader/src/usesPrismaSchemaFolder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// Minimal subset of the return type of `getConfig` from `@prisma/internals`, used for `usesPrismaSchemaFolder`.
// This is a simplified version of the actual `ConfigMetaFormat` type, which isn't imported to avoid circular dependencies.
// This is a simplified version of the actual `ConfigMetaFormat` type, which isn't imported to avoid circular dependencies.export
export type GetConfigResponse = {
config: ConfigMetaFormat
}

export type ConfigMetaFormat = {
generators: Array<{
previewFeatures: string[]
Expand Down

0 comments on commit e9d8c79

Please sign in to comment.