reproducible-tar
TypeScript icon, indicating that this package has built-in type declarations

1.0.0 • Public • Published

tar-transform

npm package tar-transform GitHub package.json dependency version (dev dep on branch) semantic-release

a Node.js library to extract, transform and re-pack tarball entries in form of stream

Install

npm install tar-transform
yarn add tar-transform

Usage

🔭 extract (gzipped) tarball as a stream of tar entries

Try tar-transform extract in RunKit

const tt = require("tar-transform");
const fetch = require("node-fetch");
 
const extractStream = tt.extract({
  // boolean | "auto". default is "auto".
  // indicates whether a gzipped tarball file stream is written to this stream
  gzip: true,
});
 
const resp = await fetch(
  "https://codeload.github.com/EqualMa/tar-transform/tar.gz/master",
);
resp.body.pipe(extractStream);
 
const entries = [];
 
// `for await ... of ...` is an easy way to consume a stream
// this syntax is available on Node.js >= 10
for await (const entry of extractStream) {
  entries.push(entry.headers);
  // NOTE: remember to resume the current entry stream to continue
  entry.stream.resume();
}
 
console.log(entries);

📦 Pack a stream of entries into a (gzipped) tarball

Try tar-transform pack in RunKit

const tt = require("tar-transform");
const fetch = require("node-fetch");
const { Readable } = require("stream");
const fs = require("fs");
 
const packStream = tt.pack({
  // boolean | zlib.ZlibOptions
  // indicates whether to gzip the tarball
  gzip: true,
});
 
const imageResp = await fetch("https://github.com/EqualMa.png");
const imageSize = parseInt(imageResp.headers.get("Content-Length"));
 
Readable.from([
  { headers: { name: "README.md" }, content: "# tar-transform" },
  { headers: { name: "hello/world.txt" }, content: "Hello World!" },
  { headers: { name: "emptyDir", type: "directory" } },
  {
    headers: { name: "author-avatar.png" },
    stream: imageResp.body,
  },
])
  .pipe(packStream)
  .pipe(fs.createWriteStream("tar-transform-pack-demo.tgz"));

✂️ transform, remove entries from, or add entries into a (gzipped) tarball

Try tar-transform transform in RunKit

Transform as is ( no-op )

const tt = require("tar-transform");
 
const tgzStream = (
  await fetch(
    "https://runkit.io/equalma/tar-transform-pack/branches/master/tgz",
  )
).body;
 
// extract a stream of tar entries from a tarball
const extractStream = tt.extract();
 
// transform
const transformStream = tt.transform({
  onEntry(entry) {
    this.push(entry);
  },
});
 
// repack to tgz
const packStream = tt.pack({ gzip: true });
 
tgzStream
  .pipe(extractStream)
  .pipe(transformStream)
  .pipe(packStream)
  .pipe(require("fs").createWriteStream("tar-transform-demo.tgz"))
  .on("error", console.error);

Transform path for each entry

The following example prefixes the path of each entry with my-root/

const transformStream = tt.transform({
  onEntry(entry) {
    const headers = this.util.headersWithNewName(
      entry.headers,
      "my-root/" + entry.headers.name,
    );
 
    this.push({ ...entry, headers });
  },
});

edit file content

The following example prefixes content of *.txt files with HACKED BY tar-transform

const transformStream = tt.transform({
  async onEntry(entry) {
    if (entry.headers.name.endsWith(".txt")) {
      const oldContent = await this.util.stringContentOfTarEntry(entry);
      const newContent = "HACKED BY tar-transform\n" + oldContent;
      this.push({
        headers: entry.headers,
        content: newContent,
      });
    } else {
      this.push(entry);
    }
  },
});

remove files from tarball

The following example removes all *.png files

const transformStream = tt.transform({
  onEntry(entry) {
    if (entry.headers.name.endsWith(".png")) {
      this.pass(entry);
    } else {
      this.push(entry);
    }
  },
});

add files to tarball

The following example adds a file named file-structure.txt containing the directory structure

const transformStream = tt.transform({
  initCtx: [],
  onEntry(entry) {
    this.ctx.push([entry.headers.name, entry.headers.type]);
    this.push(entry);
  },
  onEnd() {
    this.push({
      headers: { name: "file-structure.txt" },
      content: this.ctx.map(([name, type]) => `[${type}]\t${name}`).join("\n"),
    });
  },
});

Package Sidebar

Install

npm i reproducible-tar

Weekly Downloads

0

Version

1.0.0

License

MIT

Unpacked Size

11.1 kB

Total Files

4

Last publish

Collaborators

  • sambacha