/*1* tar.ts2*3* Copyright (C) 2025 Posit Software, PBC4*5* Abstraction layer over Deno's `tar` utilities.6*/78import { TarStream, type TarStreamInput } from "tar/tar-stream";9import { join } from "../deno_ral/path.ts";10import { pathWithForwardSlashes } from "../core/path.ts";1112/**13* Creates a tar archive from the specified files and directories.14* @param outputPath The path where the tar archive will be created.15* @param filePaths An array of file and directory paths to include in the tar archive.16* @param options Optional configuration for tar creation.17* @param options.baseDir Base directory for resolving relative paths in the archive.18* @returns A promise that resolves when the tar archive is created.19*/20export async function createTarFromFiles(21outputPath: string,22filePaths: string[],23options?: { baseDir?: string },24) {25const baseDir = options?.baseDir;2627// Create array of TarStreamInput objects from file paths28const inputs: TarStreamInput[] = await Promise.all(29filePaths.map(async (path) => {30const fullPath = baseDir ? join(baseDir, path) : path;31const stat = await Deno.stat(fullPath);3233// Use original path for archive, full path for reading34const archivePath = pathWithForwardSlashes(path);3536if (stat.isDirectory) {37// Handle directory38return {39type: "directory",40path: archivePath + (archivePath.endsWith("/") ? "" : "/"),41};42} else {43// Handle file44return {45type: "file",46path: archivePath,47size: stat.size,48readable: (await Deno.open(fullPath)).readable,49};50}51}),52);5354// Create tar file using streaming API55await ReadableStream.from(inputs)56.pipeThrough(new TarStream())57.pipeTo((await Deno.create(outputPath)).writable);58}596061