Skip to content

Commit

Permalink
feat: Added support for zip[#14]
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfuxing committed Nov 5, 2024
1 parent 8b09da0 commit fc48833
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 23 deletions.
85 changes: 63 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ Utilities to compress and uncompress for Deno!
* [x] `deflate`
* [x] `gzip`
* [x] `tgz`
* [ ] `zip`
* [x] `zip`

## Changelog

[changelog](./changelog.md)

# Usage

Expand All @@ -23,9 +27,9 @@ For tar (un)compression, Deno v1.2.2+ is required. The reason can be seen here:
### Definition

```ts
import { tar } from "https://deno.land/x/[email protected].7/mod.ts";
import { tar } from "https://deno.land/x/[email protected].8/mod.ts";
// or only import tar
// import { tar } from "https://deno.land/x/[email protected].7/tar/mod.ts";
// import { tar } from "https://deno.land/x/[email protected].8/tar/mod.ts";
export interface compressInterface {
excludeSrc?: boolean; // does not contain the src directory
debug?: boolean; // list the files and folders
Expand All @@ -40,7 +44,7 @@ tar.uncompress(src, dest, options?: uncompressInterface): Promise<void>;
### Example

```ts
import { tar } from "https://deno.land/x/[email protected].7/mod.ts";
import { tar } from "https://deno.land/x/[email protected].8/mod.ts";
// compress folder
await tar.compress("./test", "./test.tar");
// compress folder, exclude src directory
Expand All @@ -64,9 +68,9 @@ import {
deflateRaw,
inflate,
inflateRaw,
} from "https://deno.land/x/[email protected].7/mod.ts";
} from "https://deno.land/x/[email protected].8/mod.ts";
// or only import deflate, inflate, deflateRaw, inflateRaw
// import { deflate, inflate, deflateRaw, inflateRaw } from "https://deno.land/x/[email protected].7/zlib/mod.ts";
// import { deflate, inflate, deflateRaw, inflateRaw } from "https://deno.land/x/[email protected].8/zlib/mod.ts";
const str = "hello world!";
const bytes = new TextEncoder().encode(str);
// with zlib header
Expand Down Expand Up @@ -107,9 +111,9 @@ and decompressing a single file.)
Useful for reading and writing large files.

```ts
import { GzipStream } from "https://deno.land/x/[email protected].7/mod.ts";
import { GzipStream } from "https://deno.land/x/[email protected].8/mod.ts";
// or only import GzipStream
// import { GzipStream } from "https://deno.land/x/[email protected].7/gzip/mod.ts";
// import { GzipStream } from "https://deno.land/x/[email protected].8/gzip/mod.ts";
const gzip = new GzipStream();
gzip.on("progress", (progress: string) => {
console.log(progress); // 0.00% => 100.00%
Expand All @@ -125,9 +129,9 @@ await gzip.uncompress("./big.mkv.gz", "./big.mkv");
import {
gunzipFile,
gzipFile,
} from "https://deno.land/x/[email protected].7/mod.ts";
} from "https://deno.land/x/[email protected].8/mod.ts";
// or only import gzipFile, gunzipFile
// import { gzipFile, gunzipFile } from "https://deno.land/x/[email protected].7/gzip/mod.ts";
// import { gzipFile, gunzipFile } from "https://deno.land/x/[email protected].8/gzip/mod.ts";
await gzipFile("./deno.txt", "./deno.txt.gz");
await gunzipFile("./deno.txt.gz", "./deno.txt");
```
Expand All @@ -138,9 +142,9 @@ await gunzipFile("./deno.txt.gz", "./deno.txt");
> implementation.
```ts
import { gunzip, gzip } from "https://deno.land/x/[email protected].7/mod.ts";
import { gunzip, gzip } from "https://deno.land/x/[email protected].8/mod.ts";
// or only import gzip, gunzip
// import { gzip, gunzip } from "https://deno.land/x/[email protected].7/zlib/mod.ts";
// import { gzip, gunzip } from "https://deno.land/x/[email protected].8/zlib/mod.ts";
// gzip
const bytes = new TextEncoder().encode("hello");
const compressed = gzip(bytes);
Expand All @@ -153,9 +157,9 @@ const decompressed = gunzip(compressed);
### Definition

```ts
import { tgz } from "https://deno.land/x/[email protected].7/mod.ts";
import { tgz } from "https://deno.land/x/[email protected].8/mod.ts";
// or only import tgz
// import { tgz } from "https://deno.land/x/[email protected].7/tgz/mod.ts";
// import { tgz } from "https://deno.land/x/[email protected].8/tgz/mod.ts";
export interface compressInterface {
excludeSrc?: boolean; // does not contain the src directory
debug?: boolean; // list the files and folders
Expand All @@ -170,7 +174,7 @@ tgz.uncompress(src, dest, options?: uncompressInterface): Promise<void>;
### Example

```ts
import { tgz } from "https://deno.land/x/[email protected].7/mod.ts";
import { tgz } from "https://deno.land/x/[email protected].8/mod.ts";
// compress folder
await tgz.compress("./test", "./test.tar.gz");
// compress folder, exclude src directory
Expand All @@ -183,21 +187,58 @@ await tgz.uncompress("./test.tar.gz", "./dest");

## `zip`

*Not yet implemented*
> code from `https://github.com/fakoua/deno-zip`
### Definition

```ts
import { zip } from "https://deno.land/x/[email protected]/mod.ts";
import { zip } from "https://deno.land/x/[email protected]/mod.ts";
// or only import zip
// import { zip } from "https://deno.land/x/[email protected]/zip/mod.ts";

export interface compressInterface {
excludeSrc?: boolean; // does not contain the src directory
debug?: boolean; // list the files and folders
// Indicates whether to overwrite the existing archive file
overwrite?: boolean;
// An array of flags to customize the compression process
flags?: string[];
}

export interface uncompressInterface {
debug?: boolean; // list the files and folders
// Whether to overwrite existing files
overwrite?: boolean;
// Whether to include the file name in the destination path
includeFileName?: boolean;
}
zip.compress(src, dest, options?: compressInterface): Promise<void>;
zip.uncompress(src, dest, options?: uncompressInterface): Promise<void>;

zip.compress(src, dest, options?: compressInterface): Promise<boolean>;
zip.uncompress(src, dest, options?: uncompressInterface): Promise<string | false>;
```

### Example

```ts
// zip From File
console.log(await zip.compress("./myfiles")); //=> boolean
console.log(await zip.compress("./mypicter.png", "new-dir/mypicter.zip")); //=> boolean
console.log(
await zip.compress(["./mypicters", "./textpalne.txt"], "compressed.zip", {
overwrite: true,
})
); //=> boolean

// unZip From File
console.log(await zip.uncompress("myfile.zip")); //=> ./
console.log(await zip.uncompress("myfile.zip", "new-dir")); //=> new-dir
console.log(
await zip.uncompress("myfile.zip", null, {
includeFileName: true,
})
); //=> myfile
console.log(
await zip.uncompress("myfile.zip", "new-dir", {
includeFileName: true,
})
); //=> new-dir\myfile
```

# test
Expand Down
12 changes: 12 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Changelog

### v0.4.8 - 2024.11.5

- Added support for zip[#14]

### v0.4.7 - 2024.11.5

- Added support for JSR
- Replace 'any' types with specific types
- Migrate from Deno 1.x to 2.x
- fix[#18]
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@deno-library/compress",
"version": "0.4.7",
"version": "0.4.8",
"exports": "./mod.ts"
}
59 changes: 59 additions & 0 deletions zip/compress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { exists, join } from "./deps.ts";

export interface compressInterface {
// Indicates whether to overwrite the existing archive file
overwrite?: boolean;
// An array of flags to customize the compression process
flags?: string[];
}

/**
* Compresses the specified files into an archive.
*
* @param src - The file(s) to compress. It can be a single file or an array of files.
* @param dest - The name of the archive file. Defaults to "./archive.zip".
* @param options - Optional compress options.
* @returns A promise that resolves to a boolean indicating whether the compression was successful.
*/
export async function compress(
src: string | string[],
dest: string = "./archive.zip",
options?: compressInterface,
): Promise<boolean> {
return await compressProcess(src, dest, options);
}

const compressProcess = async (
src: string | string[],
dest: string = "./archive.zip",
options?: compressInterface,
): Promise<boolean> => {
if (await exists(dest) && !(options?.overwrite)) {
throw `The archive file ${
join(Deno.cwd(), dest)
} already exists, Use the {overwrite: true} option to overwrite the existing archive file`;
}
const filesList = typeof src === "string"
? src
: src.join(Deno.build.os === "windows" ? ", " : " ");

const cmd = Deno.build.os === "windows" ? "PowerShell" : "zip";
const args = Deno.build.os === "windows"
? [
"Compress-Archive",
"-Path",
filesList,
"-DestinationPath",
dest,
options?.overwrite ? "-Force" : "",
]
: ["-r", ...options?.flags ?? [], dest, ...filesList.split(" ")];
const p = new Deno.Command(cmd, {
args: args,
stderr: "piped",
stdout: "piped",
});
const child = p.spawn();
const processStatus = (await child.status).success;
return processStatus;
};
2 changes: 2 additions & 0 deletions zip/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { exists } from "jsr:@std/[email protected]";
export { join } from "jsr:@std/[email protected]";
2 changes: 2 additions & 0 deletions zip/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { compress } from "./compress.ts";
export { uncompress } from "./uncompress.ts";
69 changes: 69 additions & 0 deletions zip/uncompress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { exists, join } from "./deps.ts";

export interface uncompressInterface {
// Whether to overwrite existing files
overwrite?: boolean;
// Whether to include the file name in the destination path
includeFileName?: boolean;
}

/**
* Uncompresses a zip file.
* @param src - The path to the zip file.
* @param dest - The path where the extracted files will be placed. Defaults to "./" if not provided.
* @param options - Optional uncompression options.
* @returns A promise that resolves to the path of the extracted files, or `false` if the uncompression process failed.
* @throws Throws an error if the zip file does not exist.
*/
export async function uncompress(
src: string,
dest: string = "./",
options?: uncompressInterface,
): Promise<string | false> {
// check if the zip file is exist
if (!await exists(src)) {
throw "this file does not found";
}

// the file name with aut extension
const fileNameWithOutExt = getFileNameFromPath(src);
// get the extract file and add fileNameWithOutExt whene options.includeFileName is true
const fullDestinationPath = options?.includeFileName
? join(dest, fileNameWithOutExt)
: dest;

// return the unzipped file path or false whene the unzipping Process failed
return await uncompressProcess(src, fullDestinationPath, options)
? fullDestinationPath
: false;
};

const uncompressProcess = async (
zipSourcePath: string,
destinationPath: string,
options?: uncompressInterface,
): Promise<boolean> => {
const cmd = Deno.build.os === "windows" ? "PowerShell" : "unzip";
const args = Deno.build.os === "windows"
? [
"Expand-Archive",
"-Path",
`"${zipSourcePath}"`,
"-DestinationPath",
`"${destinationPath}"`,
options?.overwrite ? "-Force" : "",
]
: [options?.overwrite ? "-o" : "", zipSourcePath, "-d", destinationPath];
const p = new Deno.Command(cmd, {
args: args,
stderr: "piped",
stdout: "piped",
});
const child = p.spawn();
const processStatus = (await child.status).success;
return processStatus;
};

function getFileNameFromPath(filePath: string): string {
return filePath.split("/").at(-1)?.split(".").slice(0, -1).join(".") || "";
}

0 comments on commit fc48833

Please sign in to comment.