🏡 index : quine-global-boneyard/electron-builder.git

const chalk = require("chalk")
const depCheck = require("depcheck")
const fs = require("fs-extra")
const path = require("path")
const knownUnusedDevDependencies = new Set([
  "@babel/plugin-transform-modules-commonjs", // Not sure what this is used for, but keeping just in case (for now)
  "@changesets/changelog-github", // Used in package.json CI/CD logic
  "typedoc-plugin-markdown", // Used in typedoc config
  // Eslint config doesn't get scanned by depCheck
  "@stylistic/eslint-plugin",
  "@typescript-eslint/eslint-plugin",
  "@typescript-eslint/parser",
  "eslint-config-prettier",
  "eslint-plugin-prettier",
  "@rollup/plugin-typescript",
])
const knownMissedDependencies = new Set(["babel-core", "babel-preset-env", "babel-preset-stage-0", "babel-preset-react"])

const rootDir = path.join(__dirname, "..")
const packageDir = path.join(rootDir, "packages")

async function check(projectDir, devPackageData) {
  const packageName = path.basename(projectDir)
  // console.log(`Checking ${projectDir}`)

  const result = await new Promise(resolve => {
    depCheck(projectDir, { ignoreDirs: ["out", "test", "pages", "typings", "docker", "certs", "templates", "vendor"] }, resolve)
  })

  let unusedDependencies = result.dependencies
  if (unusedDependencies.length > 0) {
    // Check root for unused deps (which could be cloned to any folder name, so we check basename of cwd)
    if (packageName === path.basename(process.cwd())) {
      unusedDependencies = unusedDependencies.filter(it => it !== "dmg-license")
    }
    if (packageName === "electron-builder") {
      unusedDependencies = unusedDependencies.filter(it => it !== "dmg-builder")
    }
    if (unusedDependencies.length > 0) {
      console.error(`${chalk.bold(packageName)} Unused dependencies: ${JSON.stringify(unusedDependencies, null, 2)}`)
      return false
    }
  }

  let unusedDevDependencies = result.devDependencies.filter(it => !it.startsWith("@types/") && !knownUnusedDevDependencies.has(it))
  if (packageName === "dmg-builder") {
    unusedDevDependencies = unusedDevDependencies.filter(it => it !== "temp-file")
  }
  if (unusedDevDependencies.length > 0) {
    console.error(`${chalk.bold(packageName)} Unused devDependencies: ${JSON.stringify(unusedDevDependencies, null, 2)}`)
    return false
  }

  delete result.missing.electron
  const toml = result.missing.toml
  if (toml != null && toml.length === 1 && toml[0].endsWith("config.js")) {
    delete result.missing.toml
  }

  if (packageName === "electron-builder") {
    delete result.missing["electron-publish"]
  }

  for (const name of Object.keys(result.missing)) {
    if (
      name === "electron-builder-squirrel-windows" ||
      name === "electron-webpack" ||
      (packageName === "app-builder-lib" && (name === "dmg-builder" || knownMissedDependencies.has(name) || name.startsWith("@babel/")))
    ) {
      delete result.missing[name]
    }
  }

  if (Object.keys(result.missing).length > 0) {
    console.error(`${chalk.bold(packageName)} Missing dependencies: ${JSON.stringify(result.missing, null, 2)}`)
    return false
  }

  const packageData = await fs.readJson(path.join(projectDir, "package.json"))
  for (const name of devPackageData.devDependencies == null ? [] : Object.keys(devPackageData.devDependencies)) {
    if (packageData.dependencies != null && packageData.dependencies[name] != null) {
      continue
    }

    const usages = result.using[name]
    if (usages == null || usages.length === 0) {
      continue
    }

    for (const file of usages) {
      if (file.startsWith(path.join(projectDir, "src") + path.sep)) {
        console.error(`${chalk.bold(packageName)} Dev dependency ${name} is used in the sources`)
        return false
      }
    }
  }

  return true
}

async function main() {
  const packages = (await fs.readdir(packageDir)).filter(it => !it.includes(".")).sort()
  const devPackageData = await fs.readJson(path.join(rootDir, "package.json"))
  const checkRoot = await check(process.cwd(), devPackageData)
  const checkPackages = await Promise.all(packages.map(it => check(path.join(packageDir, it), devPackageData)))
  if (checkRoot === false || checkPackages.includes(false)) {
    process.exitCode = 1
  }
}

main().catch(error => {
  console.error(chalk.red((error.stack || error).toString()))
  process.exit(1)
})