| |
| const childProcess = require('child_process') |
| const { promisify } = require('util') |
| const fs = require('fs') |
| const path = require('path') |
| const c = require('./colors') |
|
|
| const exec = promisify(childProcess.exec) |
|
|
| function debug(message, ...optionalParams) { |
| if (process.env.DEBUG && process.env.DEBUG === 'prisma:postinstall') { |
| console.log(message, ...optionalParams) |
| } |
| } |
| |
| |
| |
| |
| function addPackageJSON(pth) { |
| if (pth.endsWith('package.json')) return pth |
| return path.join(pth, 'package.json') |
| } |
|
|
| |
| |
| |
| |
| |
| |
| function findPackageRoot(startPath, limit = 10) { |
| if (!startPath || !fs.existsSync(startPath)) return null |
| let currentPath = startPath |
| |
| for (let i = 0; i < limit; i++) { |
| const pkgPath = addPackageJSON(currentPath) |
| if (fs.existsSync(pkgPath)) { |
| try { |
| const pkg = require(pkgPath) |
| if (pkg.name && !['@prisma/cli', 'prisma'].includes(pkg.name)) { |
| return pkgPath.replace('package.json', '') |
| } |
| } catch {} |
| } |
| currentPath = path.join(currentPath, '../') |
| } |
| return null |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| async function main() { |
| if (process.env.INIT_CWD) { |
| process.chdir(process.env.INIT_CWD) |
| |
| } |
|
|
| await createDefaultGeneratedThrowFiles() |
|
|
| |
| const localPath = getLocalPackagePath() |
|
|
| |
| const installedGlobally = localPath ? undefined : await isInstalledGlobally() |
|
|
| |
| const root = findPackageRoot(localPath) |
|
|
| process.env.PRISMA_GENERATE_IN_POSTINSTALL = root ? root : 'true' |
|
|
| debug({ |
| localPath, |
| installedGlobally, |
| init_cwd: process.env.INIT_CWD, |
| PRISMA_GENERATE_IN_POSTINSTALL: process.env.PRISMA_GENERATE_IN_POSTINSTALL, |
| }) |
| try { |
| if (localPath) { |
| await run('node', [localPath, 'generate', '--postinstall', doubleQuote(getPostInstallTrigger())]) |
| return |
| } |
| if (installedGlobally) { |
| await run('prisma', ['generate', '--postinstall', doubleQuote(getPostInstallTrigger())]) |
| return |
| } |
| } catch (e) { |
| |
| if (e && e !== 1) { |
| console.error(e) |
| } |
| debug(e) |
| } |
|
|
| if (!localPath && !installedGlobally) { |
| console.error( |
| `${c.yellow( |
| 'warning', |
| )} In order to use "@prisma/client", please install Prisma CLI. You can install it with "npm add -D prisma".`, |
| ) |
| } |
| } |
|
|
| function getLocalPackagePath() { |
| try { |
| const packagePath = require.resolve('prisma/package.json') |
| if (packagePath) { |
| return require.resolve('prisma') |
| } |
| } catch (e) {} |
|
|
| |
| try { |
| const packagePath = require.resolve('@prisma/cli/package.json') |
| if (packagePath) { |
| return require.resolve('@prisma/cli') |
| } |
| } catch (e) {} |
|
|
| return null |
| } |
|
|
| async function isInstalledGlobally() { |
| try { |
| const result = await exec('prisma -v') |
| if (result.stdout.includes('@prisma/client')) { |
| return true |
| } else { |
| console.error(`${c.yellow('warning')} You still have the ${c.bold('prisma')} cli (Prisma 1) installed globally. |
| Please uninstall it with either ${c.green('npm remove -g prisma')} or ${c.green('yarn global remove prisma')}.`) |
| } |
| } catch (e) { |
| return false |
| } |
| } |
|
|
| if (!process.env.PRISMA_SKIP_POSTINSTALL_GENERATE) { |
| main() |
| .catch((e) => { |
| if (e.stderr) { |
| if (e.stderr.includes(`Can't find schema.prisma`)) { |
| console.error( |
| `${c.yellow('warning')} @prisma/client needs a ${c.bold('schema.prisma')} to function, but couldn't find it. |
| Please either create one manually or use ${c.bold('prisma init')}. |
| Once you created it, run ${c.bold('prisma generate')}. |
| To keep Prisma related things separate, we recommend creating it in a subfolder called ${c.underline( |
| './prisma', |
| )} like so: ${c.underline('./prisma/schema.prisma')}\n`, |
| ) |
| } else { |
| console.error(e.stderr) |
| } |
| } else { |
| console.error(e) |
| } |
| process.exit(0) |
| }) |
| .finally(() => { |
| debug(`postinstall trigger: ${getPostInstallTrigger()}`) |
| }) |
| } |
|
|
| function run(cmd, params, cwd = process.cwd()) { |
| const child = childProcess.spawn(cmd, params, { |
| stdio: ['pipe', 'inherit', 'inherit'], |
| cwd, |
| }) |
|
|
| return new Promise((resolve, reject) => { |
| child.on('close', () => { |
| resolve(undefined) |
| }) |
| child.on('exit', (code) => { |
| if (code === 0) { |
| resolve(undefined) |
| } else { |
| reject(code) |
| } |
| }) |
| child.on('error', () => { |
| reject() |
| }) |
| }) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| async function createDefaultGeneratedThrowFiles() { |
| try { |
| const dotPrismaClientDir = path.join(__dirname, '../../../.prisma/client') |
|
|
| await makeDir(dotPrismaClientDir) |
|
|
| const defaultFileConfig = { |
| js: path.join(__dirname, 'default-index.js'), |
| ts: path.join(__dirname, 'default-index.d.ts'), |
| } |
|
|
| |
| |
| |
| const defaultFiles = { |
| index: defaultFileConfig, |
| edge: defaultFileConfig, |
| default: defaultFileConfig, |
| wasm: defaultFileConfig, |
| 'index-browser': { |
| js: path.join(__dirname, 'default-index.js'), |
| ts: undefined, |
| }, |
| } |
|
|
| for (const file of Object.keys(defaultFiles)) { |
| const { js, ts } = defaultFiles[file] ?? {} |
| const dotPrismaJsFilePath = path.join(dotPrismaClientDir, `${file}.js`) |
| const dotPrismaTsFilePath = path.join(dotPrismaClientDir, `${file}.d.ts`) |
|
|
| if (js && !fs.existsSync(dotPrismaJsFilePath) && fs.existsSync(js)) { |
| await fs.promises.copyFile(js, dotPrismaJsFilePath) |
| } |
|
|
| if (ts && !fs.existsSync(dotPrismaTsFilePath) && fs.existsSync(ts)) { |
| await fs.promises.copyFile(ts, dotPrismaTsFilePath) |
| } |
| } |
| } catch (e) { |
| console.error(e) |
| } |
| } |
|
|
| |
| function makeDir(input) { |
| const make = async (pth) => { |
| try { |
| await fs.promises.mkdir(pth) |
|
|
| return pth |
| } catch (error) { |
| if (error.code === 'EPERM') { |
| throw error |
| } |
|
|
| if (error.code === 'ENOENT') { |
| if (path.dirname(pth) === pth) { |
| throw new Error(`operation not permitted, mkdir '${pth}'`) |
| } |
|
|
| if (error.message.includes('null bytes')) { |
| throw error |
| } |
|
|
| await make(path.dirname(pth)) |
|
|
| return make(pth) |
| } |
|
|
| try { |
| const stats = await fs.promises.stat(pth) |
| if (!stats.isDirectory()) { |
| throw new Error('The path is not a directory') |
| } |
| } catch (_) { |
| throw error |
| } |
|
|
| return pth |
| } |
| } |
|
|
| return make(path.resolve(input)) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| function getPostInstallTrigger() { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| const maybe_npm_config_argv_string = process.env.npm_config_argv |
|
|
| if (maybe_npm_config_argv_string === undefined) { |
| return UNABLE_TO_FIND_POSTINSTALL_TRIGGER__ENVAR_MISSING |
| } |
|
|
| let npm_config_argv |
| try { |
| npm_config_argv = JSON.parse(maybe_npm_config_argv_string) |
| } catch (e) { |
| return `${UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_PARSE_ERROR}: ${maybe_npm_config_argv_string}` |
| } |
|
|
| if (typeof npm_config_argv !== 'object' || npm_config_argv === null) { |
| return `${UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_SCHEMA_ERROR}: ${maybe_npm_config_argv_string}` |
| } |
|
|
| const npm_config_argv_original_arr = npm_config_argv.original |
|
|
| if (!Array.isArray(npm_config_argv_original_arr)) { |
| return `${UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_SCHEMA_ERROR}: ${maybe_npm_config_argv_string}` |
| } |
|
|
| const npm_config_argv_original = npm_config_argv_original_arr.filter((arg) => arg !== '').join(' ') |
|
|
| const command = |
| npm_config_argv_original === '' |
| ? getPackageManagerName() |
| : [getPackageManagerName(), npm_config_argv_original].join(' ') |
|
|
| return command |
| } |
|
|
| |
| |
| |
| function doubleQuote(x) { |
| return `"${x}"` |
| } |
|
|
| |
| |
| |
| |
| function getPackageManagerName() { |
| const userAgent = process.env.npm_config_user_agent |
| if (!userAgent) return 'MISSING_NPM_CONFIG_USER_AGENT' |
|
|
| const name = parsePackageManagerName(userAgent) |
| if (!name) return `UNKNOWN_NPM_CONFIG_USER_AGENT(${userAgent})` |
|
|
| return name |
| } |
|
|
| |
| |
| |
| function parsePackageManagerName(userAgent) { |
| let packageManager = null |
|
|
| |
| |
| |
| |
| if (userAgent) { |
| const matchResult = userAgent.match(/^([^/]+)\/.+/) |
| if (matchResult) { |
| packageManager = matchResult[1].trim() |
| } |
| } |
|
|
| return packageManager |
| } |
|
|
| |
| const UNABLE_TO_FIND_POSTINSTALL_TRIGGER__ENVAR_MISSING = 'UNABLE_TO_FIND_POSTINSTALL_TRIGGER__ENVAR_MISSING' |
| |
| const UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_PARSE_ERROR = 'UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_PARSE_ERROR' |
| |
| const UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_SCHEMA_ERROR = 'UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_SCHEMA_ERROR' |
|
|
| |
|
|
| exports.UNABLE_TO_FIND_POSTINSTALL_TRIGGER__ENVAR_MISSING = UNABLE_TO_FIND_POSTINSTALL_TRIGGER__ENVAR_MISSING |
| exports.UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_PARSE_ERROR = UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_PARSE_ERROR |
| exports.UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_SCHEMA_ERROR = UNABLE_TO_FIND_POSTINSTALL_TRIGGER_JSON_SCHEMA_ERROR |
| exports.getPostInstallTrigger = getPostInstallTrigger |
|
|