Prechádzať zdrojové kódy

feat(scripts): добавлен скрипт с дополнительным функционалом для основного скрипта

horanchikk 7 mesiacov pred
rodič
commit
b34472e67e
1 zmenil súbory, kde vykonal 122 pridanie a 0 odobranie
  1. 122 0
      scripts/utils.ts

+ 122 - 0
scripts/utils.ts

@@ -0,0 +1,122 @@
+import fs from 'node:fs/promises'
+import { spawn } from 'node:child_process'
+import { envVars } from './config'
+import { downloadFile } from './download'
+
+export async function fileExistsAsync(filePath: string): Promise<boolean> {
+  try {
+    await fs.access(filePath)
+    return true
+  }
+  catch {
+    return false
+  }
+}
+
+export async function removeDir(dir: string): Promise<void> {
+  await fs.rm(dir, { recursive: true, force: true })
+}
+
+export async function createDir(dirPath: string): Promise<void> {
+  await fs.mkdir(dirPath, { recursive: true })
+}
+
+export async function runCommand(
+  command: string,
+  args: string[] = [],
+  options: {
+    task?: { output?: string }
+    env?: NodeJS.ProcessEnv
+    disableOutput?: boolean
+    maxOutputLines?: number
+  } = { disableOutput: false },
+): Promise<void> {
+  if (!options.env) options.env = envVars
+
+  const maxOutputLines = options.maxOutputLines ?? 10
+
+  return new Promise((resolve, reject) => {
+    const finalEnv = { ...envVars, ...(options.env || {}) }
+
+    let outputLines: string[] = [`$ ${command} ${args.join(' ')}`]
+
+    let remainingData = ''
+
+    const child = spawn(command, args, { env: finalEnv, shell: true })
+
+    const updateOutput = (data: Buffer) => {
+      const text = data.toString()
+
+      const fullText = remainingData + text
+      const lines = fullText.split('\n')
+
+      if (!fullText.endsWith('\n')) {
+        remainingData = lines.pop() ?? ''
+      }
+      else {
+        remainingData = ''
+      }
+
+      outputLines.push(...lines)
+
+      if (outputLines.length > maxOutputLines) {
+        outputLines = outputLines.slice(outputLines.length - maxOutputLines)
+      }
+
+      if (options.task) {
+        options.task.output = outputLines.join('\n')
+      }
+    }
+
+    if (!options.disableOutput) {
+      child.stdout.on('data', updateOutput)
+      child.stderr.on('data', updateOutput)
+    }
+
+    child.on('error', reject)
+
+    child.on('close', (code) => {
+      if (remainingData) {
+        outputLines.push(remainingData)
+      }
+      if (outputLines.length > maxOutputLines) {
+        outputLines = outputLines.slice(outputLines.length - maxOutputLines)
+      }
+      if (options.task) {
+        options.task.output = outputLines.join('\n')
+      }
+      if (code === 0) {
+        resolve()
+      }
+      else {
+        reject(
+          new Error(
+            `Command "${command} ${args.join(' ')}" exited with code ${code}\nOutput:\n${outputLines.join('\n')}\nENV: ${JSON.stringify(options.env)}`,
+          ),
+        )
+      }
+    })
+  })
+}
+
+export async function extractArchive(
+  archiveName: string,
+  extractCommand: string[],
+  options: { task?: { output?: string } } = {},
+) {
+  // TODO: extract zip using library
+  await runCommand('bash', ['-c', `"${extractCommand.join(' && ')}"`], options)
+}
+
+export async function ensureDownloadedAndExtracted(
+  filePath: string,
+  downloadUrl: string,
+  archiveName: string,
+  extractCommand: string[],
+  options: { task?: { output?: string } } = {},
+): Promise<void> {
+  if (!(await fileExistsAsync(filePath))) {
+    await downloadFile(options.task, downloadUrl, archiveName)
+    await extractArchive(archiveName, extractCommand, options)
+  }
+}