Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
fillPlugin.ts7.25 kB
import crypto from 'crypto' import * as esbuild from 'esbuild' import os from 'os' import path from 'path' import resolve from 'resolve' type LoadCache = { [K in string]: string } type Fillers = { [k in string]: { imports?: string globals?: string contents?: string define?: string } } type FillPluginOptions = { fillerOverrides: Fillers defaultFillers?: boolean triggerPredicate?: (options: esbuild.BuildOptions) => boolean } /** * Bundle a polyfill with all its dependencies. We use paths to files in /tmp * instead of direct contents so that esbuild can include things once only. * @param cache to serve from * @param module to be compiled * @returns the path to the bundle */ const loader = (cache: LoadCache) => (module: string) => { if (cache[module]) return cache[module] const modulePkg = `${module}/package.json` const resolveOpt = { includeCoreModules: false } const modulePath = path.dirname(resolve.sync(modulePkg, resolveOpt)) const filename = `${module}${crypto.randomBytes(4).toString('hex')}.js` const outfile = path.join(os.tmpdir(), 'esbuild', filename) esbuild.buildSync({ format: 'cjs', platform: 'node', outfile: outfile, entryPoints: [modulePath], absWorkingDir: modulePath, mainFields: ['browser', 'main'], bundle: true, minify: true, }) return (cache[module] = outfile) } /** * Creates a RegExp for filtering injections * @param fillers to be filtered * @returns */ function createImportFilter(fillers: Fillers) { const fillerNames = Object.keys(fillers) return new RegExp(`^${fillerNames.join('\\/?$|^')}\\/?$`) } /** * Looks through the fillers and applies their `define` or `inject` (if they * have such a field to the esbuild `options` that we passed. * @param options from esbuild * @param fillers to be scanned */ function setInjectionsAndDefinitions(fillers: Fillers, options: esbuild.BuildOptions) { const fillerNames = Object.keys(fillers) // we make sure that it is not empty options.define = options.define ?? {} options.inject = options.inject ?? [] // we scan through fillers and apply for (const fillerName of fillerNames) { const filler = fillers[fillerName] if (filler.define) { options.define[fillerName] = filler.define } if (filler.globals) { options.inject.push(filler.globals) } } } /** * Handles the resolution step where esbuild resolves the imports before * bundling them. This allows us to inject a filler via its `path` if it was * provided. If not, we proceed to the next `onLoad` step. * @param fillers to use the path from * @param args from esbuild * @returns */ function onResolve(fillers: Fillers, args: esbuild.OnResolveArgs, namespace: string): esbuild.OnResolveResult { // removes trailing slashes in imports paths const path = args.path.replace(/\/$/, '') const item = fillers[path] // if a path is provided, we just replace it if (item.imports !== undefined) { return { path: item.imports } } // if not, we defer action to the loaders cb return { namespace, path: path, pluginData: args.importer, } } /** * Handles the load step where esbuild loads the contents of the imports before * bundling them. This allows us to inject a filler via its `contents` if it was * provided. If not, the polyfill is empty and we display an error. * @param fillers to use the contents from * @param args from esbuild */ function onLoad(fillers: Fillers, args: esbuild.OnLoadArgs): esbuild.OnLoadResult { // display useful info if no shim has been found if (fillers[args.path].contents === undefined) { throw `no shim for "${args.path}" imported by "${args.pluginData}"` } return fillers[args.path] // inject the contents } export const load = loader({}) const defaultFillersConfig: Fillers = { // enabled events: { imports: path.join(__dirname, 'fillers', 'events.ts') }, path: { imports: path.join(__dirname, 'fillers', 'path.ts') }, tty: { imports: path.join(__dirname, 'fillers', 'tty.ts') }, util: { imports: path.join(__dirname, 'fillers', 'util.ts') }, crypto: { imports: path.join(__dirname, 'fillers', 'crypto.ts') }, 'node:crypto': { imports: path.join(__dirname, 'fillers', 'crypto.ts') }, // disabled constants: { contents: '' }, domain: { contents: '' }, http: { contents: '' }, https: { contents: '' }, inherits: { contents: '' }, os: { contents: '' }, punycode: { contents: '' }, querystring: { contents: '' }, stream: { contents: '' }, string_decoder: { contents: '' }, sys: { contents: '' }, timers: { contents: '' }, url: { contents: '' }, vm: { contents: '' }, zlib: { contents: '' }, // no shims async_hooks: { contents: '' }, child_process: { contents: '' }, cluster: { contents: '' }, dns: { contents: '' }, dgram: { contents: '' }, fs: { imports: path.join(__dirname, 'fillers', 'fs.ts') }, http2: { contents: '' }, module: { contents: '' }, net: { contents: '' }, perf_hooks: { imports: path.join(__dirname, 'fillers', 'perf_hooks.ts') }, readline: { contents: '' }, repl: { contents: '' }, tls: { contents: '' }, // globals buffer: { imports: load('buffer'), globals: path.join(__dirname, 'fillers', 'buffer.ts'), }, process: { globals: path.join(__dirname, 'fillers', 'process.ts'), imports: path.join(__dirname, 'fillers', 'process.ts'), }, performance: { globals: path.join(__dirname, 'fillers', 'perf_hooks.ts'), }, __dirname: { define: '"/"' }, __filename: { define: '"index.js"' }, global: { define: 'globalThis', }, } export const smallBuffer = { buffer: { imports: path.join(__dirname, 'fillers', 'buffer-small.ts'), globals: path.join(__dirname, 'fillers', 'buffer-small.ts'), }, } export const smallDecimal = { 'decimal.js': { imports: path.join(__dirname, 'fillers', 'decimal-small.ts'), globals: path.join(__dirname, 'fillers', 'decimal-small.ts'), }, } /** * Provides a simple way to use esbuild's injection capabilities while providing * sensible defaults for node polyfills. * @see https://v2.parceljs.org/features/node-emulation/ * @see https://github.com/Richienb/node-polyfill-webpack-plugin/blob/master/index.js * @param fillerOverrides override default fillers * @returns */ const fillPlugin = ({ fillerOverrides, defaultFillers = true }: FillPluginOptions): esbuild.Plugin => ({ name: 'fillPlugin', setup(build) { const uid = Math.random().toString(36).substring(7) + '' const namespace = `fill-plugin-${uid}` // overrides const fillers = { ...(defaultFillers ? defaultFillersConfig : {}), ...fillerOverrides, } // our first step is to update options with basic injections setInjectionsAndDefinitions(fillers, build.initialOptions) // allows us to change the path of a filtered import by another build.onResolve({ filter: createImportFilter(fillers) }, (args) => { return onResolve(fillers, args, namespace) }) // if no path was provided it defers to virtual nsp `fill-plugin` build.onLoad({ filter: /.*/, namespace }, (args) => { return onLoad(fillers, args) }) }, }) export { fillPlugin }

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