const { download } = require('@prisma/fetch-engine')
const fs = require('fs')
const path = require('path')
const pkgUp = require('pkg-up')
const Debug = require('debug')
const debug = Debug('prisma2:download')

const binaryPath = eval(`require('path').join(__dirname, '../')`)
const pkg = eval(`require(require('path').join(binaryPath, 'package.json'))`)

const version = (pkg && pkg.prisma && pkg.prisma.version) || 'latest'

download({
  binaries: {
    'query-engine': binaryPath,
    'migration-engine': binaryPath,
    'introspection-engine': binaryPath,
  },
  showProgress: true,
  version,
  failSilent: true,
})

// if we are in a Now context, ensure that `prisma2 generate` is in the postinstall hook
if (process.env.INIT_CWD && process.env.NOW_BUILDER) {
  ensurePostInstall().catch(e => {
    debug(e)
  })
}

async function ensurePostInstall() {
  const initPkgPath = eval(`require('path').resolve(process.env.INIT_CWD, 'package.json')`)
  if (fs.existsSync(initPkgPath)) {
    if (addPostInstallHook(initPkgPath)) {
      return
    }
  } else {
    // walk up all the way
    let cwd = path.join(process.cwd(), '..')
    let pkgPath
    do {
      pkgPath = await pkgUp({
        cwd,
      })
      cwd = path.join(pkgPath, '../..')
    } while (pkgPath && !addPostInstallHook(pkgPath))
  }
}

function readJson(filePath) {
  return JSON.parse(fs.readFileSync(filePath, 'utf-8'))
}

function addPostInstallHook(pkgPath) {
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
  // only update package.json if prisma2 is a dependency or devDependency
  if (!json.dependencies['prisma2'] && !json.devDependencies['prisma2']) {
    return false
  }

  pkg.scripts = pkg.scripts || {}

  if (!pkg.scripts.postinstall) {
    pkg.scripts.postinstall = `prisma2 generate || true`
  } else {
    if (!pkg.scripts.postinstall.includes('prisma2 generate')) {
      pkg.scripts.postinstall = `prisma2 generate || true && ${pkg.scripts.postinstall}`
    }
  }

  fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2))
  return true
}

@@ -216,20 +216,19 @@
 t binary
-Path
+Dir
  = eval(
@@ -322,20 +322,19 @@
 n(binary
-Path
+Dir
 , 'packa
@@ -422,19 +422,362 @@
 t'%0A%0A
-download(%7B%0A
+const lockFile = path.join(binaryDir, 'download-lock')%0A%0Alet createdLockFile = false%0Aasync function main() %7B%0A  if (fs.existsSync(lockFile) && JSON.parse(fs.readFileSync(lockFile) %3E Date.now() - 20000)) %7B%0A    debug(%60Lock file already exists, so we're skipping the download of the prisma2 binaries%60)%0A  %7D else %7B%0A    createLockFile()%0A    await download(%7B%0A    
   bi
@@ -786,16 +786,20 @@
 ries: %7B%0A
+    
     'que
@@ -812,30 +812,33 @@
 ine': binary
-Path,%0A
+Dir,%0A    
     'migrati
@@ -855,22 +855,25 @@
 : binary
-Path,%0A
+Dir,%0A    
     'int
@@ -902,19 +902,26 @@
 nary
-Path,%0A
+Dir,%0A    
   %7D,%0A
+    
   sh
@@ -938,16 +938,20 @@
 : true,%0A
+    
   versio
@@ -953,16 +953,20 @@
 ersion,%0A
+    
   failSi
@@ -977,17 +977,316 @@
 : true,%0A
-%7D
+    %7D).catch(e =%3E debug(e))%0A%0A    cleanupLockFile()%0A  %7D%0A%7D%0A%0Afunction createLockFile() %7B%0A  createdLockFile = true%0A  fs.writeFileSync(lockFile, Date.now())%0A%7D%0A%0Afunction cleanupLockFile() %7B%0A  if (createdLockFile) %7B%0A    try %7B%0A      fs.unlinkSync(lockFile)%0A    %7D catch (e) %7B%0A      debug(e)%0A    %7D%0A  %7D%0A%7D%0A%0Amain(
 )%0A%0A// if
@@ -2703,8 +2703,137 @@
  true%0A%7D%0A
+%0Aprocess.on('beforeExit', () =%3E %7B%0A  cleanupLockFile()%0A%7D)%0A%0Aprocess.once('SIGINT', () =%3E %7B%0A  cleanupLockFile()%0A  process.exit()%0A%7D)%0A

add lockfile mechanism