{"version":3,"file":"hash.cjs","names":["fs","path","crypto"],"sources":["../src/hash.ts"],"sourcesContent":["import crypto from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Check whether seed command can be skipped or not and update hash file if needed.\n * Note that process.env.ALLOW_TO_SKIP_SEED should be set to non-zero number or 'true' to skip seed.\n * @param hashFilePath Path to the hash file.\n * @param paths Paths to the files or directories.\n * @returns Whether seed command can be skipped.\n */\nexport async function canSkipSeed(hashFilePath: string, ...paths: string[]): Promise<boolean> {\n  return (\n    (!!Number(process.env.ALLOW_TO_SKIP_SEED) || (process.env.ALLOW_TO_SKIP_SEED ?? '').toLowerCase() === 'true') &&\n    !(await updateHashFromFiles(hashFilePath, ...paths))\n  );\n}\n\n/**\n * Update hash file if the hash is different from the current one.\n * @param hashFilePath Path to the hash file.\n * @param paths Paths to the files or directories.\n * @returns Whether the hash file was updated.\n */\nexport async function updateHashFromFiles(hashFilePath: string, ...paths: string[]): Promise<boolean> {\n  let oldHash = '';\n  try {\n    oldHash = await fs.promises.readFile(hashFilePath, 'utf8');\n  } catch {\n    // do nothing\n  }\n  const newHash = await calculateHashFromFiles(...paths);\n  if (oldHash === newHash) return false;\n\n  await fs.promises.mkdir(path.dirname(hashFilePath), { recursive: true });\n  await fs.promises.writeFile(hashFilePath, newHash, 'utf8');\n  return true;\n}\n\n/**\n * Calculate hash from files.\n * @param paths Paths to the files or directories.\n * @returns Hash string.\n */\nexport async function calculateHashFromFiles(...paths: string[]): Promise<string> {\n  const hash = crypto.createHash('sha512');\n  for (const fileOrDirPath of paths.toSorted()) {\n    const stat = await fs.promises.stat(fileOrDirPath);\n    if (stat.isDirectory()) {\n      const dirents = await fs.promises.readdir(fileOrDirPath, { withFileTypes: true, recursive: true });\n      for (const dirent of dirents.toSorted((d1, d2) => d1.name.localeCompare(d2.name))) {\n        if (dirent.isFile()) {\n          // Use parentPath property which is available in Node.js 18.17.0 or later\n          hash.update(\n            await fs.promises.readFile(\n              path.join((dirent as unknown as Record<'parentPath', string>).parentPath, dirent.name),\n              'utf8'\n            )\n          );\n        }\n      }\n    } else if (stat.isFile()) {\n      hash.update(await fs.promises.readFile(fileOrDirPath, 'utf8'));\n    }\n  }\n  return hash.digest('hex');\n}\n"],"mappings":"qMAWA,eAAsB,EAAY,EAAsB,GAAG,EAAmC,CAC5F,OACG,CAAC,CAAC,OAAO,QAAQ,IAAI,kBAAkB,IAAM,QAAQ,IAAI,oBAAsB,GAAA,CAAI,YAAY,IAAM,SACtG,CAAE,MAAM,EAAoB,EAAc,GAAG,CAAK,CAEtD,CAQA,eAAsB,EAAoB,EAAsB,GAAG,EAAmC,CACpG,IAAI,EAAU,GACd,GAAI,CACF,EAAU,MAAMA,EAAAA,QAAG,SAAS,SAAS,EAAc,MAAM,CAC3D,MAAQ,CAER,CACA,IAAM,EAAU,MAAM,EAAuB,GAAG,CAAK,EAKrD,OAJI,IAAY,IAEhB,MAAMA,EAAAA,QAAG,SAAS,MAAMC,EAAAA,QAAK,QAAQ,CAAY,EAAG,CAAE,UAAW,EAAK,CAAC,EACvE,MAAMD,EAAAA,QAAG,SAAS,UAAU,EAAc,EAAS,MAAM,EAClD,GACT,CAOA,eAAsB,EAAuB,GAAG,EAAkC,CAChF,IAAM,EAAOE,EAAAA,QAAO,WAAW,QAAQ,EACvC,IAAK,IAAM,KAAiB,EAAM,SAAS,EAAG,CAC5C,IAAM,EAAO,MAAMF,EAAAA,QAAG,SAAS,KAAK,CAAa,EACjD,GAAI,EAAK,YAAY,EAAG,CACtB,IAAM,EAAU,MAAMA,EAAAA,QAAG,SAAS,QAAQ,EAAe,CAAE,cAAe,GAAM,UAAW,EAAK,CAAC,EACjG,IAAK,IAAM,KAAU,EAAQ,UAAU,EAAI,IAAO,EAAG,KAAK,cAAc,EAAG,IAAI,CAAC,EAC1E,EAAO,OAAO,GAEhB,EAAK,OACH,MAAMA,EAAAA,QAAG,SAAS,SAChBC,EAAAA,QAAK,KAAM,EAAmD,WAAY,EAAO,IAAI,EACrF,MACF,CACF,CAGN,MAAW,EAAK,OAAO,GACrB,EAAK,OAAO,MAAMD,EAAAA,QAAG,SAAS,SAAS,EAAe,MAAM,CAAC,CAEjE,CACA,OAAO,EAAK,OAAO,KAAK,CAC1B"}