{"version":3,"file":"integrity.js","sourceRoot":"","sources":["../../src/asar/integrity.ts"],"names":[],"mappings":"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","sourcesContent":["import { FilterStats, log, statOrNull, walk } from \"builder-util\"\nimport { createHash } from \"crypto\"\nimport { readdir } from \"fs/promises\"\nimport * as path from \"path\"\nimport { FileMatcher } from \"../fileMatcher\"\nimport { readAsarHeader } from \"./asar\"\n\nexport interface AsarIntegrityOptions {\n  readonly resourcesPath: string\n  readonly resourcesRelativePath: string\n  readonly resourcesDestinationPath: string\n  readonly extraResourceMatchers: Array<FileMatcher> | null\n}\n\nexport interface HeaderHash {\n  algorithm: \"SHA256\"\n  hash: string\n}\n\nexport interface AsarIntegrity {\n  [key: string]: HeaderHash\n}\n\nexport async function computeData({ resourcesPath, resourcesRelativePath, resourcesDestinationPath, extraResourceMatchers }: AsarIntegrityOptions): Promise<AsarIntegrity> {\n  type Match = Pick<FileMatcher, \"to\" | \"from\">\n  type IntegrityMap = {\n    [filepath: string]: string\n  }\n  const isAsar = (filepath: string) => filepath.endsWith(\".asar\")\n\n  const resources = await readdir(resourcesPath)\n  const resourceAsars = resources.filter(isAsar).reduce<IntegrityMap>(\n    (prev, filename) => ({\n      ...prev,\n      [path.join(resourcesRelativePath, filename)]: path.join(resourcesPath, filename),\n    }),\n    {}\n  )\n\n  const extraResources = await Promise.all(\n    (extraResourceMatchers ?? []).map(async (matcher: FileMatcher): Promise<Match[]> => {\n      const { from, to } = matcher\n      const stat = await statOrNull(from)\n      if (stat == null) {\n        log.warn({ from }, `file source doesn't exist`)\n        return []\n      }\n      if (stat.isFile()) {\n        return [{ from, to }]\n      }\n\n      if (matcher.isEmpty() || matcher.containsOnlyIgnore()) {\n        matcher.prependPattern(\"**/*\")\n      }\n      const matcherFilter = matcher.createFilter()\n      const extraResourceMatches = await walk(matcher.from, (file: string, stats: FilterStats) => matcherFilter(file, stats) || stats.isDirectory())\n      return extraResourceMatches.map(from => ({ from, to: matcher.to }))\n    })\n  )\n  const extraResourceAsars = extraResources\n    .flat(1)\n    .filter(match => isAsar(match.from))\n    .reduce<IntegrityMap>((prev, { to, from }) => {\n      const prefix = path.relative(resourcesDestinationPath, to)\n      return {\n        ...prev,\n        [path.join(resourcesRelativePath, prefix, path.basename(from))]: from,\n      }\n    }, {})\n\n  // sort to produce constant result\n  const allAsars = [...Object.entries(resourceAsars), ...Object.entries(extraResourceAsars)].sort(([name1], [name2]) => name1.localeCompare(name2))\n  const hashes = await Promise.all(allAsars.map(async ([, from]) => hashHeader(from)))\n  const asarIntegrity: AsarIntegrity = {}\n  for (let i = 0; i < allAsars.length; i++) {\n    const [asar] = allAsars[i]\n    asarIntegrity[asar] = hashes[i]\n  }\n  return asarIntegrity\n}\n\nasync function hashHeader(file: string): Promise<HeaderHash> {\n  const hash = createHash(\"sha256\")\n  const { header } = await readAsarHeader(file)\n  hash.update(header)\n  return {\n    algorithm: \"SHA256\",\n    hash: hash.digest(\"hex\"),\n  }\n}\n"]}