🏡 index : quine-global/webdriverio.git

import fs from 'node:fs/promises'
import url from 'node:url'
import path from 'node:path'
import unzipper from 'unzipper'
import { Readable } from 'node:stream'

import { Octokit } from '@octokit/rest'

// GitHub repository information
const REPO_OWNER = 'webdriverio'
const REPO_NAME = 'i18n'

const GITHUB_TOKEN = process.env.GITHUB_AUTH
if (!GITHUB_TOKEN) {
    throw new Error('GITHUB_AUTH is not set')
}

const IGNORE_FILES = ['src', 'package.json', 'package-lock.json', 'README.md', 'LICENSE', 'tsconfig.json']

const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
const octokit = new Octokit({ auth: GITHUB_TOKEN })

export function downloadDocsTranslations() {
    return downloadAndExtractRepo(REPO_OWNER, REPO_NAME)
}

async function downloadAndExtractRepo(owner: string, repo: string, branch?: string) {
    // Step 1: Determine default branch if not specified
    if (!branch) {
        const { data } = await octokit.repos.get({ owner, repo })
        branch = data.default_branch
    }

    // Step 2: Download the zipball
    const url = `https://api.github.com/repos/${owner}/${repo}/zipball/${branch}`
    console.log(`Downloading ${url}...`)

    const response = await fetch(url, {
        headers: {
            Authorization: `token ${GITHUB_TOKEN}`,
            Accept: 'application/vnd.github.v3+json',
        },
    })

    if (!response.ok) {
        throw new Error(`Failed to download repo zip: ${response.status} ${response.statusText}`)
    }

    // Create a temp directory for initial extraction
    const tempExtractPath = path.resolve(__dirname, '..', '..', 'temp_extract')
    const finalExtractPath = path.resolve(__dirname, '..', '..', 'website', 'i18n')

    // Ensure both directories exist
    await fs.mkdir(tempExtractPath, { recursive: true })
    await fs.mkdir(finalExtractPath, { recursive: true })

    try {
        // Step 3: Extract to temp directory first
        await new Promise((resolve, reject) => {
            if (!response.body) {
                return reject(new Error('Response body is null'))
            }

            // Convert ReadableStream to Node.js stream
            // @ts-ignore - Type compatibility issue between web streams and node streams
            const nodeStream = Readable.fromWeb(response.body)

            nodeStream
                .pipe(unzipper.Extract({ path: tempExtractPath }))
                .on('close', resolve)
                .on('error', reject)
        })

        // Step 4: Move contents from temp directory to final location
        const extractedDirs = await fs.readdir(tempExtractPath)
        const repoDir = extractedDirs[0] // This should be the GitHub repository directory (e.g., webdriverio-i18n-7b50bc6)
        const repoDirPath = path.join(tempExtractPath, repoDir)

        // Copy all contents from the repo directory to the final location
        const files = await fs.readdir(repoDirPath)
        for (const file of files) {
            const baseName = path.basename(file)
            if (baseName.startsWith('.') || IGNORE_FILES.includes(baseName)) {
                continue
            }

            const srcPath = path.join(repoDirPath, file)
            const destPath = path.join(finalExtractPath, file)

            // Handle the case if the file already exists in the destination
            try {
                await fs.rm(destPath, { recursive: true, force: true })
            } catch {
                // Ignore if file doesn't exist
            }

            await fs.cp(srcPath, destPath, { recursive: true })
        }

        console.log(`Repository extracted to ${finalExtractPath}`)
    } finally {
        // Clean up temp directory
        try {
            await fs.rm(tempExtractPath, { recursive: true, force: true })
        } catch (err) {
            console.warn('Failed to clean up temporary directory:', err)
        }
    }
}