{"version":3,"file":"utils.cjs","names":["fs","Effect","safeFileExists","Option","FSyncLayer","FS","makeTempPathScoped","makePath","NodeFileSystem"],"sources":["../../src/utils.ts"],"sourcesContent":["import type { FileSystem } from '@effect/platform';\nimport { NodeFileSystem } from '@effect/platform-node';\nimport archiver from 'archiver';\nimport { bestzip } from 'bestzip';\nimport { type Cause, Effect, Option } from 'effect';\nimport execa from 'execa';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport type { ESMPluginsModule, IFile, IFiles } from './types';\nimport FS, { FSyncLayer, makePath, makeTempPathScoped, safeFileExists } from './utils/effect-fs';\n\nexport class SpawnError extends Error {\n  constructor(message: string, public stdout: string, public stderr: string) {\n    super(message);\n  }\n\n  toString() {\n    return `${this.message}\\n${this.stderr}`;\n  }\n}\n\n/**\n * Executes a child process without limitations on stdout and stderr.\n * On error (exit code is not 0), it rejects with a SpawnProcessError that contains the stdout and stderr streams,\n * on success it returns the streams in an object.\n * @param {string} command - Command\n * @param {string[]} [args] - Arguments\n * @param {Object} [options] - Options for child_process.spawn\n */\nexport function spawnProcess(command: string, args: string[], options: execa.Options) {\n  return execa(command, args, options);\n}\n\nconst rootOf = (p: string) => path.parse(path.resolve(p)).root;\nconst isPathRoot = (p: string) => rootOf(p) === path.resolve(p);\nconst findUpEffect = (\n  names: string[],\n  directory = process.cwd()\n): Effect.Effect<string, Cause.NoSuchElementException, FileSystem.FileSystem> => {\n  const dir = path.resolve(directory);\n  return Effect.all(names.map((name) => safeFileExists(path.join(dir, name)))).pipe(\n    Effect.flatMap((exist) => {\n      if (exist.some(Boolean)) return Option.some(dir);\n      if (isPathRoot(dir)) return Option.none();\n      return findUpEffect(names, path.dirname(dir));\n    })\n  );\n};\n\n/**\n * Find a file by walking up parent directories\n */\nexport const findUp = (name: string) =>\n  findUpEffect([name]).pipe(\n    Effect.orElseSucceed(() => undefined),\n    Effect.provide(FSyncLayer),\n    Effect.runSync\n  );\n\n/**\n * Forwards `rootDir` or finds project root folder.\n */\nexport const findProjectRoot = (rootDir?: string) =>\n  Effect.fromNullable(rootDir).pipe(\n    Effect.orElse(() => findUpEffect(['yarn.lock', 'pnpm-lock.yaml', 'package-lock.json'])),\n    Effect.orElseSucceed(() => undefined),\n    Effect.provide(FSyncLayer),\n    Effect.runSync\n  );\n\nexport const humanSize = (size: number) => {\n  const exponent = Math.floor(Math.log(size) / Math.log(1024));\n  const sanitized = (size / 1024 ** exponent).toFixed(2);\n\n  return `${sanitized} ${['B', 'KB', 'MB', 'GB', 'TB'][exponent]}`;\n};\n\nexport const zip = async (zipPath: string, filesPathList: IFiles, useNativeZip = false): Promise<void> => {\n  // create a temporary directory to hold the final zip structure\n  const tempDirName = `${path.basename(zipPath, path.extname(zipPath))}-${Date.now().toString()}`;\n\n  const copyFileEffect = (temp: string) => (file: IFile) => FS.copy(file.rootPath, path.join(temp, file.localPath));\n  const bestZipEffect = (temp: string) =>\n    Effect.tryPromise(() => bestzip({ source: '*', destination: zipPath, cwd: temp }));\n  const nodeZipEffect = Effect.tryPromise(() => nodeZip(zipPath, filesPathList));\n\n  const archiveEffect = makeTempPathScoped(tempDirName).pipe(\n    // copy all required files from origin path to (sometimes modified) target path\n    Effect.tap((temp) => Effect.all(filesPathList.map(copyFileEffect(temp)), { discard: true })),\n    // prepare zip folder\n    Effect.tap(() => makePath(path.dirname(zipPath))),\n    // zip the temporary directory\n    Effect.andThen((temp) => (useNativeZip ? bestZipEffect(temp) : nodeZipEffect)),\n    Effect.scoped\n  );\n\n  await archiveEffect.pipe(Effect.provide(NodeFileSystem.layer), Effect.runPromise);\n};\n\nfunction nodeZip(zipPath: string, filesPathList: IFiles): Promise<void> {\n  const zipArchive = archiver.create('zip');\n  const output = fs.createWriteStream(zipPath);\n\n  // write zip\n  output.on('open', () => {\n    zipArchive.pipe(output);\n\n    filesPathList.forEach((file) => {\n      const stats = fs.statSync(file.rootPath);\n      if (stats.isDirectory()) return;\n\n      zipArchive.append(fs.readFileSync(file.rootPath), {\n        name: file.localPath,\n        mode: stats.mode,\n        date: new Date(0), // necessary to get the same hash when zipping the same content\n      });\n    });\n\n    zipArchive.finalize();\n  });\n\n  return new Promise((resolve, reject) => {\n    output.on('close', resolve);\n    zipArchive.on('error', (err) => reject(err));\n  });\n}\n\nexport function trimExtension(entry: string) {\n  return entry.slice(0, -path.extname(entry).length);\n}\n\nexport const isEmpty = (obj: Record<string, unknown>) => {\n  // eslint-disable-next-line no-unreachable-loop\n  for (const _i in obj) return false;\n\n  return true;\n};\n\nexport const isESMModule = (obj: unknown): obj is ESMPluginsModule => {\n  return typeof obj === 'object' && obj !== null && 'default' in obj;\n};\n"],"mappings":"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"}