Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
handleViewsIO.ts4.81 kB
import { fsFunctional, pathToPosix } from '@prisma/internals' import * as E from 'fp-ts/lib/Either' import { pipe } from 'fp-ts/lib/function' import * as T from 'fp-ts/lib/Task' import * as TE from 'fp-ts/lib/TaskEither' import path from 'path' import { match } from 'ts-pattern' export interface IntrospectionViewDefinition { // The database or schema where the view is located schema: string // The name of the view name: string // The database SQL query that defines the view definition: string } type HandleViewsIOParams = { views: IntrospectionViewDefinition[] viewsDirectoryPath: string } /** * For any given view definitions, the CLI must either create or update the corresponding view definition files * in the file system, in `${path.dirname(schemaPath)}/views/{viewDbSchema}/{viewName}.sql`. * If some other non ".sql" files or folders exist within the `views` directory, the CLI must preserve them. * In case of empty folders, these are deleted silently. */ export async function handleViewsIO({ views, viewsDirectoryPath }: HandleViewsIOParams): Promise<void> { const posixViewsDirectoryPath = pathToPosix(viewsDirectoryPath) if (views.length === 0) { await cleanLeftoversIO(posixViewsDirectoryPath) return } const { viewFilesToKeep } = await createViewsIO(posixViewsDirectoryPath, views) await cleanLeftoversIO(posixViewsDirectoryPath, viewFilesToKeep) } async function createViewsIO( viewsDir: string, views: IntrospectionViewDefinition[], ): Promise<{ viewFilesToKeep: string[] }> { // collect the newest view definitions const viewEntries = views.map(({ schema, ...rest }) => { const viewDir = path.posix.join(viewsDir, schema) return [viewDir, rest] as const }) // collect the paths to the view directories (identified by their db schema name) corresponding to the newest view definitions, // which will be created later if they don't exist const viewPathsToWrite: string[] = viewEntries.map(([viewDir]) => viewDir) // collect the files paths and content for the newest views' SQL definitions, which will be created later if they don't exist const viewsFilesToWrite = viewEntries.map(([viewDir, { name, definition }]) => { const viewFile = path.posix.join(viewDir, `${name}.sql`) return { path: viewFile, content: definition } as const }) const viewFilesToKeep = viewsFilesToWrite.map(({ path }) => path) const pipeline = pipe( // create the views directory, idempotently fsFunctional.createDirIfNotExists(viewsDir), // create the view directories, idempotently and concurrently, collapsing the possible errors TE.chainW(() => TE.traverseArray(fsFunctional.createDirIfNotExists)(viewPathsToWrite)), // write the view definitions in the directories just created, idempotently and concurrently, collapsing the possible errors TE.chainW(() => TE.traverseArray(fsFunctional.writeFile)(viewsFilesToWrite)), ) const either = await pipeline() if (E.isRight(either)) { return { viewFilesToKeep } } // failure: check which error to throw const error = match(either.left) .with({ type: 'fs-create-dir' }, (e) => { throw new Error(`Error creating the directory: ${e.meta.dir}.\n${e.error}.`) }) .with({ type: 'fs-write-file' }, (e) => { throw new Error(`Error writing the view definition\n${e.meta.content}\nto file ${e.meta.path}.\n${e.error}.`) }) .exhaustive() throw error } /** * - Delete every *.sql file in the subfolders of viewsDir * - Delete any empty subfolders * - Delete viewsDir if it is empty */ async function cleanLeftoversIO(viewsDir: string, viewFilesToKeep: string[] = []): Promise<void> { const pipeline = pipe( // remove any SQL files in the views directory beyond the ones just created, concurrently, collapsing the possible errors fsFunctional.getFilesInDir(viewsDir, '**/*/*.sql'), T.chain((filesInViewsDir) => { const viewFilesToRemove = filesInViewsDir.filter((file) => !viewFilesToKeep.includes(file)) return TE.traverseArray(fsFunctional.removeFile)(viewFilesToRemove) }), // remove any empty directories in the views directory, recursively TE.chainW(() => fsFunctional.removeEmptyDirs(viewsDir)), ) const either = await pipeline() if (E.isRight(either)) { return } // failure: check which error to throw const error = match(either.left) .with({ type: 'fs-remove-empty-dirs' }, (e) => { throw new Error(`Error removing empty directories in: ${e.meta.dir}.\n${e.error}.`) }) .with({ type: 'fs-remove-file' }, (e) => { throw new Error(`Error removing the file: ${e.meta.filePath}.\n${e.error}.`) }) .exhaustive() // We execute the cleanup and ignore the possible errors await pipeline() throw error }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prisma/prisma'

If you have feedback or need assistance with the MCP directory API, please join our Discord server