Compare commits
49 Commits
Author | SHA1 | Date | |
---|---|---|---|
be1bc958d8 | |||
21434622dd | |||
50c0368ac7 | |||
78b3fcfd83 | |||
61caf51f4e | |||
be4e2cdae7 | |||
1cb8331666 | |||
aa203c5ab2 | |||
87aedd5ef5 | |||
64431703b5 | |||
120fd0b321 | |||
e6192c418e | |||
00a039936f | |||
e03c3a62b1 | |||
538eced73b | |||
fe8a5713f0 | |||
37e8a1d0f7 | |||
5143cd098d | |||
4d5ea812af | |||
500ef01ded | |||
3196a02835 | |||
de1c46ed0a | |||
b4c7b065fa | |||
93da11a951 | |||
ecd7f6d419 | |||
a3ecfe4d99 | |||
f99f6d96c5 | |||
b4be70f43a | |||
785e26e72d | |||
e1891a6aa3 | |||
f257c0c5a4 | |||
725546e409 | |||
b9645dfb99 | |||
b860aca103 | |||
39fb6e8ad1 | |||
04968a80b0 | |||
e4a2c143bc | |||
ed6d186a85 | |||
553c5dfe99 | |||
5d94efb9ee | |||
c978ca107b | |||
876c8ce9d8 | |||
7327bf1bd0 | |||
2dcb10d233 | |||
d53c46fa82 | |||
25e847a9ea | |||
cc0ecb3f16 | |||
2cd0846c74 | |||
49ab40af09 |
55
changelog.md
Normal file
55
changelog.md
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 2024-10-13 - 4.0.39 - fix(core)
|
||||||
|
Fix dependencies and update documentation.
|
||||||
|
|
||||||
|
- Ensure package uses the latest dependencies
|
||||||
|
- Reviewed and grouped imports in TypeScript files
|
||||||
|
- Updated readme with advanced usage examples
|
||||||
|
|
||||||
|
## 2024-10-13 - 4.0.38 - fix(dependencies)
|
||||||
|
Update dependencies to latest versions
|
||||||
|
|
||||||
|
- Updated @push.rocks/smartfile to version 11.0.21
|
||||||
|
- Updated @push.rocks/smartpromise to version 4.0.4
|
||||||
|
- Updated @push.rocks/smartstream to version 3.0.46
|
||||||
|
- Updated @push.rocks/smarturl to version 3.1.0
|
||||||
|
- Updated file-type to version 19.5.0
|
||||||
|
- Updated @git.zone/tsbuild to version 2.1.84
|
||||||
|
- Updated @git.zone/tsrun to version 1.2.49
|
||||||
|
- Updated @push.rocks/tapbundle to version 5.3.0
|
||||||
|
|
||||||
|
## 2024-06-08 - 4.0.24 to 4.0.37 - Fixes and Updates
|
||||||
|
Core updates and bug fixes were implemented in versions 4.0.24 through 4.0.37.
|
||||||
|
|
||||||
|
- Repeated core updates and fixes applied consistently across multiple versions.
|
||||||
|
|
||||||
|
## 2024-06-06 - 4.0.22 to 4.0.23 - Descriptions and Fixes Updates
|
||||||
|
Efforts to update documentation and core features.
|
||||||
|
|
||||||
|
- "update description" in 4.0.22
|
||||||
|
- Updates to `tsconfig` and `npmextra.json` were performed.
|
||||||
|
- Ongoing core fixes.
|
||||||
|
|
||||||
|
## 2023-11-06 - 4.0.0 - Major Update with Breaking Changes
|
||||||
|
Introduction of significant updates and breaking changes.
|
||||||
|
|
||||||
|
- Transition to new version 4.0.0 with core updates.
|
||||||
|
- Break in compatibility due to major structural changes with core functionalities.
|
||||||
|
|
||||||
|
## 2023-07-11 - 3.0.6 - Organizational Changes
|
||||||
|
Structural reorganization and updates to the organization schema.
|
||||||
|
|
||||||
|
- Switch to new organizational schema implemented.
|
||||||
|
|
||||||
|
## 2022-04-04 - 3.0.0 - Build Updates and Breaking Changes
|
||||||
|
Major build update introducing breaking changes.
|
||||||
|
|
||||||
|
- Introduction of ESM structure with breaking changes.
|
||||||
|
|
||||||
|
## 2016-01-18 - 0.0.0 to 1.0.0 - Initial Development and Launch
|
||||||
|
Initial software development and establishment of core features.
|
||||||
|
|
||||||
|
- Project set-up including Travis CI integration.
|
||||||
|
- Launch of the first full version with code restructuring.
|
||||||
|
- Added callback support.
|
3
dist_ts/index.d.ts
vendored
3
dist_ts/index.d.ts
vendored
@ -1 +1,4 @@
|
|||||||
export * from './classes.smartarchive.js';
|
export * from './classes.smartarchive.js';
|
||||||
|
export * from './classes.tartools.js';
|
||||||
|
export * from './classes.ziptools.js';
|
||||||
|
export * from './classes.gziptools.js';
|
||||||
|
@ -1,2 +1,5 @@
|
|||||||
export * from './classes.smartarchive.js';
|
export * from './classes.smartarchive.js';
|
||||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDJCQUEyQixDQUFDIn0=
|
export * from './classes.tartools.js';
|
||||||
|
export * from './classes.ziptools.js';
|
||||||
|
export * from './classes.gziptools.js';
|
||||||
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDJCQUEyQixDQUFDO0FBQzFDLGNBQWMsdUJBQXVCLENBQUM7QUFDdEMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLHdCQUF3QixDQUFDIn0=
|
@ -6,12 +6,28 @@
|
|||||||
"gitzone": {
|
"gitzone": {
|
||||||
"projectType": "npm",
|
"projectType": "npm",
|
||||||
"module": {
|
"module": {
|
||||||
"githost": "gitlab.com",
|
"githost": "code.foss.global",
|
||||||
"gitscope": "push.rocks",
|
"gitscope": "push.rocks",
|
||||||
"gitrepo": "smartarchive",
|
"gitrepo": "smartarchive",
|
||||||
"description": "work with archives",
|
"description": "A library for working with archive files, providing utilities for compressing and decompressing data.",
|
||||||
"npmPackagename": "@push.rocks/smartarchive",
|
"npmPackagename": "@push.rocks/smartarchive",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"keywords": [
|
||||||
|
"archive",
|
||||||
|
"compression",
|
||||||
|
"decompression",
|
||||||
|
"zip",
|
||||||
|
"tar",
|
||||||
|
"gzip",
|
||||||
|
"bzip2",
|
||||||
|
"file extraction",
|
||||||
|
"file creation",
|
||||||
|
"data analysis",
|
||||||
|
"file stream"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tsdoc": {
|
||||||
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
50
package.json
50
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartarchive",
|
"name": "@push.rocks/smartarchive",
|
||||||
"version": "4.0.17",
|
"version": "4.0.39",
|
||||||
"description": "work with archives",
|
"description": "A library for working with archive files, providing utilities for compressing and decompressing data.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@ -12,34 +12,35 @@
|
|||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/pushrocks/smartarchive.git"
|
"url": "https://code.foss.global/push.rocks/smartarchive.git"
|
||||||
},
|
},
|
||||||
"author": "Lossless GmbH",
|
"author": "Lossless GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/pushrocks/smartarchive/issues"
|
"url": "https://github.com/pushrocks/smartarchive/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/pushrocks/smartarchive#readme",
|
"homepage": "https://code.foss.global/push.rocks/smartarchive",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/smartfile": "^11.0.0",
|
"@push.rocks/smartdelay": "^3.0.5",
|
||||||
"@push.rocks/smartpath": "^5.0.11",
|
"@push.rocks/smartfile": "^11.0.21",
|
||||||
"@push.rocks/smartpromise": "^4.0.3",
|
"@push.rocks/smartpath": "^5.0.18",
|
||||||
"@push.rocks/smartrequest": "^2.0.21",
|
"@push.rocks/smartpromise": "^4.0.4",
|
||||||
|
"@push.rocks/smartrequest": "^2.0.22",
|
||||||
"@push.rocks/smartrx": "^3.0.7",
|
"@push.rocks/smartrx": "^3.0.7",
|
||||||
"@push.rocks/smartstream": "^3.0.28",
|
"@push.rocks/smartstream": "^3.0.46",
|
||||||
"@push.rocks/smartunique": "^3.0.6",
|
"@push.rocks/smartunique": "^3.0.9",
|
||||||
"@push.rocks/smarturl": "^3.0.7",
|
"@push.rocks/smarturl": "^3.1.0",
|
||||||
"@types/tar-stream": "^3.1.3",
|
"@types/tar-stream": "^3.1.3",
|
||||||
"fflate": "^0.8.1",
|
"fflate": "^0.8.2",
|
||||||
"file-type": "^18.7.0",
|
"file-type": "^19.5.0",
|
||||||
"tar-stream": "^3.1.6",
|
"tar-stream": "^3.1.7",
|
||||||
"through": "^2.3.8"
|
"through": "^2.3.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.66",
|
"@git.zone/tsbuild": "^2.1.84",
|
||||||
"@git.zone/tsrun": "^1.2.44",
|
"@git.zone/tsrun": "^1.2.49",
|
||||||
"@git.zone/tstest": "^1.0.84",
|
"@git.zone/tstest": "^1.0.90",
|
||||||
"@push.rocks/tapbundle": "^5.0.15"
|
"@push.rocks/tapbundle": "^5.3.0"
|
||||||
},
|
},
|
||||||
"private": false,
|
"private": false,
|
||||||
"files": [
|
"files": [
|
||||||
@ -56,5 +57,18 @@
|
|||||||
],
|
],
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 1 chrome versions"
|
"last 1 chrome versions"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"archive",
|
||||||
|
"compression",
|
||||||
|
"decompression",
|
||||||
|
"zip",
|
||||||
|
"tar",
|
||||||
|
"gzip",
|
||||||
|
"bzip2",
|
||||||
|
"file extraction",
|
||||||
|
"file creation",
|
||||||
|
"data analysis",
|
||||||
|
"file stream"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
8826
pnpm-lock.yaml
generated
8826
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
1
readme.hints.md
Normal file
1
readme.hints.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
310
readme.md
310
readme.md
@ -1,54 +1,282 @@
|
|||||||
# @push.rocks/smartarchive
|
# @push.rocks/smartarchive
|
||||||
work with archives
|
|
||||||
|
|
||||||
## Availabililty and Links
|
`@push.rocks/smartarchive` is a powerful library designed for managing archive files. It provides utilities for compressing and decompressing data in various formats such as zip, tar, gzip, and bzip2. This library aims to simplify the process of handling archive files, making it an ideal choice for projects that require manipulation of archived data.
|
||||||
* [npmjs.org (npm package)](https://www.npmjs.com/package/@push.rocks/smartarchive)
|
|
||||||
* [gitlab.com (source)](https://gitlab.com/push.rocks/smartarchive)
|
|
||||||
* [github.com (source mirror)](https://github.com/push.rocks/smartarchive)
|
|
||||||
* [docs (typedoc)](https://push.rocks.gitlab.io/smartarchive/)
|
|
||||||
|
|
||||||
## Status for master
|
## Install
|
||||||
|
|
||||||
Status Category | Status Badge
|
To install `@push.rocks/smartarchive`, you can either use npm or yarn. Run one of the following commands in your project directory:
|
||||||
-- | --
|
|
||||||
GitLab Pipelines | [](https://lossless.cloud)
|
|
||||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
|
||||||
npm | [](https://lossless.cloud)
|
|
||||||
Snyk | [](https://lossless.cloud)
|
|
||||||
TypeScript Support | [](https://lossless.cloud)
|
|
||||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
|
||||||
Code Style | [](https://lossless.cloud)
|
|
||||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
|
||||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
|
||||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
|
||||||
|
|
||||||
## Usage
|
```shell
|
||||||
|
npm install @push.rocks/smartarchive --save
|
||||||
Use TypeScript for best in class instellisense.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
import * as smartarchive from 'smartarchive';
|
|
||||||
smartarchive
|
|
||||||
.get({
|
|
||||||
from: 'https://example.com/example.zip',
|
|
||||||
toPath: '/some/local/absolute/path',
|
|
||||||
})
|
|
||||||
.then(/*...*/);
|
|
||||||
```
|
```
|
||||||
|
|
||||||
For further information read the linked docs at the top of this README.
|
or if you prefer yarn:
|
||||||
|
|
||||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
```shell
|
||||||
> | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
|
yarn add @push.rocks/smartarchive
|
||||||
|
```
|
||||||
|
|
||||||
[](https://push.rocks)
|
This will add `@push.rocks/smartarchive` to your project's dependencies.
|
||||||
|
|
||||||
## Contribution
|
## Usage
|
||||||
|
`@push.rocks/smartarchive` provides an easy-to-use API for extracting, creating, and analyzing archive files. Below, we'll cover how to get started and explore various features of the module.
|
||||||
|
|
||||||
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
|
### Importing SmartArchive
|
||||||
|
|
||||||
For further information read the linked docs at the top of this readme.
|
First, import `SmartArchive` from `@push.rocks/smartarchive` using ESM syntax:
|
||||||
|
|
||||||
## Legal
|
```typescript
|
||||||
> MIT licensed | **©** [Task Venture Capital GmbH](https://task.vc)
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
```
|
||||||
|
|
||||||
|
### Extracting Archive Files
|
||||||
|
|
||||||
|
You can extract archive files from different sources using `SmartArchive.fromArchiveUrl`, `SmartArchive.fromArchiveFile`, and `SmartArchive.fromArchiveStream`. Here's an example of extracting an archive from a URL:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function extractArchiveFromURL() {
|
||||||
|
const url = 'https://example.com/archive.zip';
|
||||||
|
const targetDir = '/path/to/extract';
|
||||||
|
|
||||||
|
const archive = await SmartArchive.fromArchiveUrl(url);
|
||||||
|
await archive.exportToFs(targetDir);
|
||||||
|
|
||||||
|
console.log('Archive extracted successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
extractArchiveFromURL();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extracting an Archive from a File
|
||||||
|
|
||||||
|
Similarly, you can extract an archive from a local file:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function extractArchiveFromFile() {
|
||||||
|
const filePath = '/path/to/archive.zip';
|
||||||
|
const targetDir = '/path/to/extract';
|
||||||
|
|
||||||
|
const archive = await SmartArchive.fromArchiveFile(filePath);
|
||||||
|
await archive.exportToFs(targetDir);
|
||||||
|
|
||||||
|
console.log('Archive extracted successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
extractArchiveFromFile();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream-Based Extraction
|
||||||
|
|
||||||
|
For larger files, you might prefer a streaming approach to prevent high memory consumption. Here’s an example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
import { createReadStream } from 'fs';
|
||||||
|
|
||||||
|
async function extractArchiveUsingStream() {
|
||||||
|
const archiveStream = createReadStream('/path/to/archive.zip');
|
||||||
|
const archive = await SmartArchive.fromArchiveStream(archiveStream);
|
||||||
|
const extractionStream = await archive.exportToStreamOfStreamFiles();
|
||||||
|
|
||||||
|
extractionStream.pipe(createWriteStream('/path/to/destination'));
|
||||||
|
}
|
||||||
|
|
||||||
|
extractArchiveUsingStream();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Analyzing Archive Files
|
||||||
|
|
||||||
|
Sometimes, you may need to inspect the contents of an archive before extracting it. The following example shows how to analyze an archive:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function analyzeArchive() {
|
||||||
|
const filePath = '/path/to/archive.zip';
|
||||||
|
|
||||||
|
const archive = await SmartArchive.fromArchiveFile(filePath);
|
||||||
|
const analysisResult = await archive.analyzeContent();
|
||||||
|
|
||||||
|
console.log(analysisResult); // Outputs details about the archive content
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzeArchive();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creating Archive Files
|
||||||
|
|
||||||
|
Creating an archive file is straightforward. Here we demonstrate creating a tar.gz archive:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function createTarGzArchive() {
|
||||||
|
const archive = new SmartArchive();
|
||||||
|
|
||||||
|
// Add directories and files
|
||||||
|
archive.addedDirectories.push('/path/to/directory1');
|
||||||
|
archive.addedFiles.push('/path/to/file1.txt');
|
||||||
|
|
||||||
|
// Export as tar.gz
|
||||||
|
const tarGzStream = await archive.exportToTarGzStream();
|
||||||
|
|
||||||
|
// Save to filesystem or handle as needed
|
||||||
|
tarGzStream.pipe(createWriteStream('/path/to/destination.tar.gz'));
|
||||||
|
}
|
||||||
|
|
||||||
|
createTarGzArchive();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stream Operations
|
||||||
|
|
||||||
|
Here's an example of using `smartarchive`'s streaming capabilities:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createReadStream, createWriteStream } from 'fs';
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function extractArchiveUsingStreams() {
|
||||||
|
const archiveStream = createReadStream('/path/to/archive.zip');
|
||||||
|
const archive = await SmartArchive.fromArchiveStream(archiveStream);
|
||||||
|
const extractionStream = await archive.exportToStreamOfStreamFiles();
|
||||||
|
|
||||||
|
extractionStream.pipe(createWriteStream('/path/to/extracted'));
|
||||||
|
}
|
||||||
|
|
||||||
|
extractArchiveUsingStreams();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Decompression Usage
|
||||||
|
|
||||||
|
`smartarchive` supports multiple compression formats. It also provides detailed control over the decompression processes:
|
||||||
|
|
||||||
|
- For ZIP files, `ZipTools` handles decompression using the `fflate` library.
|
||||||
|
- For TAR files, `TarTools` uses `tar-stream`.
|
||||||
|
- For GZIP files, `GzipTools` provides a `CompressGunzipTransform` and `DecompressGunzipTransform`.
|
||||||
|
- For BZIP2 files, `Bzip2Tools` utilizes custom streaming decompression.
|
||||||
|
|
||||||
|
Example: Working with a GZIP-compressed archive:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createReadStream, createWriteStream } from 'fs';
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function decompressGzipArchive() {
|
||||||
|
const filePath = '/path/to/archive.gz';
|
||||||
|
const targetDir = '/path/to/extract';
|
||||||
|
|
||||||
|
const archive = await SmartArchive.fromArchiveFile(filePath);
|
||||||
|
await archive.exportToFs(targetDir);
|
||||||
|
|
||||||
|
console.log('GZIP archive decompressed successfully.');
|
||||||
|
}
|
||||||
|
|
||||||
|
decompressGzipArchive();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advancing with Custom Decompression Streams
|
||||||
|
|
||||||
|
You can inject custom decompression streams where needed:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createReadStream, createWriteStream } from 'fs';
|
||||||
|
import { SmartArchive, GzipTools } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function customDecompression() {
|
||||||
|
const filePath = '/path/to/archive.gz';
|
||||||
|
const targetDir = '/path/to/extract';
|
||||||
|
|
||||||
|
const archive = await SmartArchive.fromArchiveFile(filePath);
|
||||||
|
const gzipTools = new GzipTools();
|
||||||
|
const decompressionStream = gzipTools.getDecompressionStream();
|
||||||
|
|
||||||
|
const archiveStream = await archive.getArchiveStream();
|
||||||
|
archiveStream.pipe(decompressionStream).pipe(createWriteStream(targetDir));
|
||||||
|
|
||||||
|
console.log('Custom GZIP decompression successful.');
|
||||||
|
}
|
||||||
|
|
||||||
|
customDecompression();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Pack and Unpack Tar
|
||||||
|
|
||||||
|
When dealing with tar archives, you may need to perform custom packing and unpacking:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { SmartArchive, TarTools } from '@push.rocks/smartarchive';
|
||||||
|
import { createWriteStream } from 'fs';
|
||||||
|
|
||||||
|
async function customTarOperations() {
|
||||||
|
const tarTools = new TarTools();
|
||||||
|
|
||||||
|
// Packing a directory into a tar stream
|
||||||
|
const packStream = await tarTools.packDirectory('/path/to/directory');
|
||||||
|
packStream.pipe(createWriteStream('/path/to/archive.tar'));
|
||||||
|
|
||||||
|
// Extracting files from a tar stream
|
||||||
|
const extractStream = tarTools.getDecompressionStream();
|
||||||
|
createReadStream('/path/to/archive.tar').pipe(extractStream).on('entry', (header, stream, next) => {
|
||||||
|
const writeStream = createWriteStream(`/path/to/extract/${header.name}`);
|
||||||
|
stream.pipe(writeStream);
|
||||||
|
stream.on('end', next);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
customTarOperations();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extract and Analyze All-in-One
|
||||||
|
|
||||||
|
To extract and simultaneously analyze archive content:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { createReadStream, createWriteStream } from 'fs';
|
||||||
|
import { SmartArchive } from '@push.rocks/smartarchive';
|
||||||
|
|
||||||
|
async function extractAndAnalyze() {
|
||||||
|
const filePath = '/path/to/archive.zip';
|
||||||
|
const targetDir = '/path/to/extract';
|
||||||
|
|
||||||
|
const archive = await SmartArchive.fromArchiveFile(filePath);
|
||||||
|
const analyzedStream = archive.archiveAnalyzer.getAnalyzedStream();
|
||||||
|
const extractionStream = await archive.exportToStreamOfStreamFiles();
|
||||||
|
|
||||||
|
analyzedStream.pipe(extractionStream).pipe(createWriteStream(targetDir));
|
||||||
|
|
||||||
|
analyzedStream.on('data', (chunk) => {
|
||||||
|
console.log(JSON.stringify(chunk, null, 2));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
extractAndAnalyze();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Final Words
|
||||||
|
|
||||||
|
These examples demonstrate various use cases for `@push.rocks/smartarchive`. Depending on your specific project requirements, you can adapt these examples to suit your needs. Always refer to the latest documentation for the most current information and methods available in `@push.rocks/smartarchive`.
|
||||||
|
|
||||||
|
For more information and API references, check the official [`@push.rocks/smartarchive` GitHub repository](https://code.foss.global/push.rocks/smartarchive).
|
||||||
|
|
||||||
|
## License and Legal Information
|
||||||
|
|
||||||
|
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||||
|
|
||||||
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
### Trademarks
|
||||||
|
|
||||||
|
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||||||
|
|
||||||
|
### Company Information
|
||||||
|
|
||||||
|
Task Venture Capital GmbH
|
||||||
|
Registered at District court Bremen HRB 35230 HB, Germany
|
||||||
|
|
||||||
|
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||||
|
|
||||||
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
||||||
|
@ -38,7 +38,7 @@ tap.test('should extract existing files on disk', async () => {
|
|||||||
await testSmartarchive.exportToFs(testPaths.nogitDir);
|
await testSmartarchive.exportToFs(testPaths.nogitDir);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should extract a b2zip', async () => {
|
tap.skip.test('should extract a b2zip', async () => {
|
||||||
const dataUrl = 'https://daten.offeneregister.de/de_companies_ocdata.jsonl.bz2';
|
const dataUrl = 'https://daten.offeneregister.de/de_companies_ocdata.jsonl.bz2';
|
||||||
const testArchive = await smartarchive.SmartArchive.fromArchiveUrl(dataUrl);
|
const testArchive = await smartarchive.SmartArchive.fromArchiveUrl(dataUrl);
|
||||||
await testArchive.exportToFs(
|
await testArchive.exportToFs(
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* autocreated commitinfo by @pushrocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartarchive',
|
name: '@push.rocks/smartarchive',
|
||||||
version: '4.0.17',
|
version: '4.0.39',
|
||||||
description: 'work with archives'
|
description: 'A library for working with archive files, providing utilities for compressing and decompressing data.'
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ export function unbzip2Stream() {
|
|||||||
return new plugins.smartstream.SmartDuplex({
|
return new plugins.smartstream.SmartDuplex({
|
||||||
objectMode: true,
|
objectMode: true,
|
||||||
name: 'bzip2',
|
name: 'bzip2',
|
||||||
debug: true,
|
debug: false,
|
||||||
highWaterMark: 1,
|
highWaterMark: 1,
|
||||||
writeFunction: async function (data, streamTools) {
|
writeFunction: async function (data, streamTools) {
|
||||||
// console.log(`got chunk ${counter++}`)
|
// console.log(`got chunk ${counter++}`)
|
||||||
@ -80,6 +80,9 @@ export function unbzip2Stream() {
|
|||||||
//console.error(x,'last compressing with', hasBytes, 'bytes in buffer');
|
//console.error(x,'last compressing with', hasBytes, 'bytes in buffer');
|
||||||
while (!broken && bitReader && hasBytes > bitReader.bytesRead) {
|
while (!broken && bitReader && hasBytes > bitReader.bytesRead) {
|
||||||
const result = await decompressAndPush();
|
const result = await decompressAndPush();
|
||||||
|
if (!result) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
await streamTools.push(result);
|
await streamTools.push(result);
|
||||||
}
|
}
|
||||||
if (!broken) {
|
if (!broken) {
|
||||||
|
@ -36,6 +36,8 @@ export class ArchiveAnalyzer {
|
|||||||
switch (mimeTypeArg) {
|
switch (mimeTypeArg) {
|
||||||
case 'application/gzip':
|
case 'application/gzip':
|
||||||
return this.smartArchiveRef.gzipTools.getDecompressionStream();
|
return this.smartArchiveRef.gzipTools.getDecompressionStream();
|
||||||
|
case 'application/zip':
|
||||||
|
return this.smartArchiveRef.zipTools.getDecompressionStream();
|
||||||
case 'application/x-bzip2':
|
case 'application/x-bzip2':
|
||||||
return await this.smartArchiveRef.bzip2Tools.getDecompressionStream(); // replace with your own bzip2 decompression stream
|
return await this.smartArchiveRef.bzip2Tools.getDecompressionStream(); // replace with your own bzip2 decompression stream
|
||||||
case 'application/x-tar':
|
case 'application/x-tar':
|
||||||
@ -56,6 +58,9 @@ export class ArchiveAnalyzer {
|
|||||||
firstRun = false;
|
firstRun = false;
|
||||||
const fileType = await plugins.fileType.fileTypeFromBuffer(chunkArg);
|
const fileType = await plugins.fileType.fileTypeFromBuffer(chunkArg);
|
||||||
const decompressionStream = await this.getDecompressionStream(fileType?.mime as any);
|
const decompressionStream = await this.getDecompressionStream(fileType?.mime as any);
|
||||||
|
/**
|
||||||
|
* analyzed stream emits once with this object
|
||||||
|
*/
|
||||||
const result: IAnalyzedResult = {
|
const result: IAnalyzedResult = {
|
||||||
fileType,
|
fileType,
|
||||||
isArchive: await this.mimeTypeIsArchive(fileType?.mime),
|
isArchive: await this.mimeTypeIsArchive(fileType?.mime),
|
||||||
|
@ -43,10 +43,7 @@ export class DecompressGunzipTransform extends plugins.stream.Transform {
|
|||||||
|
|
||||||
|
|
||||||
export class GzipTools {
|
export class GzipTools {
|
||||||
smartArchiveRef: SmartArchive;
|
constructor() {
|
||||||
|
|
||||||
constructor(smartArchiveRefArg: SmartArchive) {
|
|
||||||
this.smartArchiveRef = smartArchiveRefArg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCompressionStream() {
|
public getCompressionStream() {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import * as plugins from './plugins.js';
|
import * as plugins from './plugins.js';
|
||||||
import * as paths from './paths.js';
|
import * as paths from './paths.js';
|
||||||
|
|
||||||
|
import { Bzip2Tools } from './classes.bzip2tools.js';
|
||||||
import { GzipTools } from './classes.gziptools.js';
|
import { GzipTools } from './classes.gziptools.js';
|
||||||
import { TarTools } from './classes.tartools.js';
|
import { TarTools } from './classes.tartools.js';
|
||||||
import { Bzip2Tools } from './classes.bzip2tools.js';
|
import { ZipTools } from './classes.ziptools.js';
|
||||||
|
|
||||||
import { ArchiveAnalyzer, type IAnalyzedResult } from './classes.archiveanalyzer.js';
|
import { ArchiveAnalyzer, type IAnalyzedResult } from './classes.archiveanalyzer.js';
|
||||||
|
|
||||||
@ -32,8 +33,9 @@ export class SmartArchive {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
public tarTools = new TarTools(this);
|
public tarTools = new TarTools();
|
||||||
public gzipTools = new GzipTools(this);
|
public zipTools = new ZipTools();
|
||||||
|
public gzipTools = new GzipTools();
|
||||||
public bzip2Tools = new Bzip2Tools(this);
|
public bzip2Tools = new Bzip2Tools(this);
|
||||||
public archiveAnalyzer = new ArchiveAnalyzer(this);
|
public archiveAnalyzer = new ArchiveAnalyzer(this);
|
||||||
|
|
||||||
@ -77,27 +79,32 @@ export class SmartArchive {
|
|||||||
public async exportToFs(targetDir: string, fileNameArg?: string): Promise<void> {
|
public async exportToFs(targetDir: string, fileNameArg?: string): Promise<void> {
|
||||||
const done = plugins.smartpromise.defer<void>();
|
const done = plugins.smartpromise.defer<void>();
|
||||||
const streamFileStream = await this.exportToStreamOfStreamFiles();
|
const streamFileStream = await this.exportToStreamOfStreamFiles();
|
||||||
streamFileStream.pipe(new plugins.smartstream.SmartDuplex({
|
streamFileStream.pipe(
|
||||||
|
new plugins.smartstream.SmartDuplex({
|
||||||
objectMode: true,
|
objectMode: true,
|
||||||
writeFunction: async (chunkArg: plugins.smartfile.StreamFile, streamtools) => {
|
writeFunction: async (streamFileArg: plugins.smartfile.StreamFile, streamtools) => {
|
||||||
const done = plugins.smartpromise.defer<void>();
|
const done = plugins.smartpromise.defer<void>();
|
||||||
console.log(chunkArg.relativeFilePath ? chunkArg.relativeFilePath : 'no relative path');
|
console.log(streamFileArg.relativeFilePath ? streamFileArg.relativeFilePath : 'no relative path');
|
||||||
const streamFile = chunkArg;
|
const streamFile = streamFileArg;
|
||||||
const readStream = await streamFile.createReadStream();
|
const readStream = await streamFile.createReadStream();
|
||||||
await plugins.smartfile.fs.ensureDir(targetDir);
|
await plugins.smartfile.fs.ensureDir(targetDir);
|
||||||
const writePath = plugins.path.join(targetDir, (streamFile.relativeFilePath || fileNameArg));
|
const writePath = plugins.path.join(
|
||||||
|
targetDir,
|
||||||
|
streamFile.relativeFilePath || fileNameArg
|
||||||
|
);
|
||||||
await plugins.smartfile.fs.ensureDir(plugins.path.dirname(writePath));
|
await plugins.smartfile.fs.ensureDir(plugins.path.dirname(writePath));
|
||||||
const writeStream = plugins.smartfile.fsStream.createWriteStream(writePath);
|
const writeStream = plugins.smartfile.fsStream.createWriteStream(writePath);
|
||||||
readStream.pipe(writeStream);
|
readStream.pipe(writeStream);
|
||||||
writeStream.on('finish', () => {
|
writeStream.on('finish', () => {
|
||||||
done.resolve();
|
done.resolve();
|
||||||
})
|
});
|
||||||
await done.promise;
|
await done.promise;
|
||||||
},
|
},
|
||||||
finalFunction: async () => {
|
finalFunction: async () => {
|
||||||
done.resolve();
|
done.resolve();
|
||||||
}
|
},
|
||||||
}));
|
})
|
||||||
|
);
|
||||||
return done.promise;
|
return done.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,21 +121,36 @@ export class SmartArchive {
|
|||||||
async (analyzedResultChunk) => {
|
async (analyzedResultChunk) => {
|
||||||
if (analyzedResultChunk.fileType?.mime === 'application/x-tar') {
|
if (analyzedResultChunk.fileType?.mime === 'application/x-tar') {
|
||||||
const tarStream = analyzedResultChunk.decompressionStream as plugins.tarStream.Extract;
|
const tarStream = analyzedResultChunk.decompressionStream as plugins.tarStream.Extract;
|
||||||
tarStream.on(
|
tarStream.on('entry', async (header, stream, next) => {
|
||||||
'entry',
|
if (header.type === 'directory') {
|
||||||
async (header, stream, next) => {
|
console.log(`tar stream directory: ${header.name} ... skipping!`);
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`tar stream file: ${header.name}`);
|
||||||
const streamfile = plugins.smartfile.StreamFile.fromStream(stream, header.name);
|
const streamfile = plugins.smartfile.StreamFile.fromStream(stream, header.name);
|
||||||
streamFileIntake.push(streamfile);
|
streamFileIntake.push(streamfile);
|
||||||
stream.on('end', function () {
|
stream.on('end', function () {
|
||||||
next(); // ready for next entry
|
next(); // ready for next entry
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
);
|
|
||||||
tarStream.on('finish', function () {
|
tarStream.on('finish', function () {
|
||||||
console.log('finished');
|
console.log('finished');
|
||||||
streamFileIntake.signalEnd();
|
streamFileIntake.signalEnd();
|
||||||
});
|
});
|
||||||
analyzedResultChunk.resultStream.pipe(analyzedResultChunk.decompressionStream);
|
analyzedResultChunk.resultStream.pipe(analyzedResultChunk.decompressionStream);
|
||||||
|
} else if (analyzedResultChunk.fileType?.mime === 'application/zip') {
|
||||||
|
analyzedResultChunk.resultStream
|
||||||
|
.pipe(analyzedResultChunk.decompressionStream)
|
||||||
|
.pipe(new plugins.smartstream.SmartDuplex({
|
||||||
|
objectMode: true,
|
||||||
|
writeFunction: async (streamFileArg: plugins.smartfile.StreamFile, streamtools) => {
|
||||||
|
streamFileIntake.push(streamFileArg);
|
||||||
|
},
|
||||||
|
finalFunction: async () => {
|
||||||
|
streamFileIntake.signalEnd();
|
||||||
|
}
|
||||||
|
}));
|
||||||
} else if (analyzedResultChunk.isArchive && analyzedResultChunk.decompressionStream) {
|
} else if (analyzedResultChunk.isArchive && analyzedResultChunk.decompressionStream) {
|
||||||
analyzedResultChunk.resultStream
|
analyzedResultChunk.resultStream
|
||||||
.pipe(analyzedResultChunk.decompressionStream)
|
.pipe(analyzedResultChunk.decompressionStream)
|
||||||
@ -142,8 +164,9 @@ export class SmartArchive {
|
|||||||
streamFileIntake.push(streamFile);
|
streamFileIntake.push(streamFile);
|
||||||
streamFileIntake.signalEnd();
|
streamFileIntake.signalEnd();
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
objectMode: true
|
{
|
||||||
|
objectMode: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2,28 +2,119 @@ import type { SmartArchive } from './classes.smartarchive.js';
|
|||||||
import * as plugins from './plugins.js';
|
import * as plugins from './plugins.js';
|
||||||
|
|
||||||
export class TarTools {
|
export class TarTools {
|
||||||
smartArchiveRef: SmartArchive;
|
// INSTANCE
|
||||||
|
constructor() {}
|
||||||
constructor(smartArchiveRefArg: SmartArchive) {
|
|
||||||
this.smartArchiveRef = smartArchiveRefArg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// packing
|
// packing
|
||||||
public addFileToPack(pack: plugins.tarStream.Pack, fileName: string, content: string | Buffer) {
|
public async addFileToPack(
|
||||||
return new Promise<void>((resolve, reject) => {
|
pack: plugins.tarStream.Pack,
|
||||||
const entry = pack.entry({ name: fileName, size: content.length }, (err: Error) => {
|
optionsArg: {
|
||||||
|
fileName?: string;
|
||||||
|
content?:
|
||||||
|
| string
|
||||||
|
| Buffer
|
||||||
|
| plugins.smartstream.stream.Readable
|
||||||
|
| plugins.smartfile.SmartFile
|
||||||
|
| plugins.smartfile.StreamFile;
|
||||||
|
byteLength?: number;
|
||||||
|
filePath?: string;
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
return new Promise<void>(async (resolve, reject) => {
|
||||||
|
let fileName: string | null = null;
|
||||||
|
|
||||||
|
if (optionsArg.fileName) {
|
||||||
|
fileName = optionsArg.fileName;
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartfile.SmartFile) {
|
||||||
|
fileName = (optionsArg.content as plugins.smartfile.SmartFile).relative;
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartfile.StreamFile) {
|
||||||
|
fileName = (optionsArg.content as plugins.smartfile.StreamFile).relativeFilePath;
|
||||||
|
} else if (optionsArg.filePath) {
|
||||||
|
fileName = optionsArg.filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* contentByteLength is used to set the size of the entry in the tar file
|
||||||
|
*/
|
||||||
|
let contentByteLength: number;
|
||||||
|
if (optionsArg.byteLength) {
|
||||||
|
contentByteLength = optionsArg.byteLength;
|
||||||
|
} else if (typeof optionsArg.content === 'string') {
|
||||||
|
contentByteLength = Buffer.byteLength(optionsArg.content, 'utf8');
|
||||||
|
} else if (Buffer.isBuffer(optionsArg.content)) {
|
||||||
|
contentByteLength = optionsArg.content.length;
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartfile.SmartFile) {
|
||||||
|
contentByteLength = await optionsArg.content.getSize(); // assuming SmartFile has getSize method
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartfile.StreamFile) {
|
||||||
|
contentByteLength = await optionsArg.content.getSize(); // assuming StreamFile has getSize method
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartstream.stream.Readable) {
|
||||||
|
console.warn(
|
||||||
|
'@push.rocks/smartarchive: When streaming, it is recommended to provide byteLength, if known.'
|
||||||
|
);
|
||||||
|
} else if (optionsArg.filePath) {
|
||||||
|
const fileStat = await plugins.smartfile.fs.stat(optionsArg.filePath);
|
||||||
|
contentByteLength = fileStat.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* here we try to harmonize all kind of entries towards a readable stream
|
||||||
|
*/
|
||||||
|
let content: plugins.smartstream.stream.Readable;
|
||||||
|
if (Buffer.isBuffer(optionsArg.content)) {
|
||||||
|
content = plugins.smartstream.stream.Readable.from(optionsArg.content);
|
||||||
|
} else if (typeof optionsArg.content === 'string') {
|
||||||
|
content = plugins.smartstream.stream.Readable.from(Buffer.from(optionsArg.content));
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartfile.SmartFile) {
|
||||||
|
content = plugins.smartstream.stream.Readable.from(optionsArg.content.contents);
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartfile.StreamFile) {
|
||||||
|
content = await optionsArg.content.createReadStream();
|
||||||
|
} else if (optionsArg.content instanceof plugins.smartstream.stream.Readable) {
|
||||||
|
content = optionsArg.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
const entry = pack.entry(
|
||||||
|
{
|
||||||
|
name: fileName,
|
||||||
|
...(contentByteLength
|
||||||
|
? {
|
||||||
|
size: contentByteLength,
|
||||||
|
}
|
||||||
|
: null),
|
||||||
|
},
|
||||||
|
(err: Error) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
entry.write(content);
|
content.pipe(entry);
|
||||||
entry.end();
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* packs a directory from disk into a tar stream
|
||||||
|
* @param directoryPath
|
||||||
|
*/
|
||||||
|
public async packDirectory(directoryPath: string) {
|
||||||
|
const fileTree = await plugins.smartfile.fs.listFileTree(directoryPath, '**/*');
|
||||||
|
const pack = await this.getPackStream();
|
||||||
|
for (const filePath of fileTree) {
|
||||||
|
const absolutePath = plugins.path.join(directoryPath, filePath);
|
||||||
|
const fileStat = await plugins.smartfile.fs.stat(absolutePath);
|
||||||
|
await this.addFileToPack(pack, {
|
||||||
|
byteLength: fileStat.size,
|
||||||
|
filePath: absolutePath,
|
||||||
|
fileName: filePath,
|
||||||
|
content: plugins.smartfile.fsStream.createReadStream(absolutePath),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return pack;
|
||||||
|
}
|
||||||
|
|
||||||
public async getPackStream() {
|
public async getPackStream() {
|
||||||
const pack = plugins.tarStream.pack();
|
const pack = plugins.tarStream.pack();
|
||||||
return pack;
|
return pack;
|
||||||
|
74
ts/classes.ziptools.ts
Normal file
74
ts/classes.ziptools.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import type { SmartArchive } from './classes.smartarchive.js';
|
||||||
|
import * as plugins from './plugins.js';
|
||||||
|
|
||||||
|
class DecompressZipTransform extends plugins.smartstream.SmartDuplex<ArrayBufferLike> {
|
||||||
|
private streamtools: plugins.smartstream.IStreamTools;
|
||||||
|
private unzipper = new plugins.fflate.Unzip(async (fileArg) => {
|
||||||
|
let resultBuffer: Buffer;
|
||||||
|
fileArg.ondata = async (flateError, dat, final) => {
|
||||||
|
resultBuffer? resultBuffer = Buffer.concat([resultBuffer, Buffer.from(dat)])
|
||||||
|
: resultBuffer = Buffer.from(dat);
|
||||||
|
if (final) {
|
||||||
|
const streamFile = plugins.smartfile.StreamFile.fromBuffer(resultBuffer);
|
||||||
|
streamFile.relativeFilePath = fileArg.name;
|
||||||
|
this.streamtools.push(streamFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fileArg.start();
|
||||||
|
});
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
objectMode: true,
|
||||||
|
writeFunction: async (chunkArg: Buffer, streamtoolsArg) => {
|
||||||
|
this.streamtools? null : this.streamtools = streamtoolsArg;
|
||||||
|
this.unzipper.push(chunkArg, false);
|
||||||
|
},
|
||||||
|
finalFunction: async () => {
|
||||||
|
this.unzipper.push(Buffer.from(''), true);
|
||||||
|
await plugins.smartdelay.delayFor(0);
|
||||||
|
await this.streamtools.push(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.unzipper.register(plugins.fflate.UnzipInflate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class wraps fflate's zip in a Node.js Transform stream for compression
|
||||||
|
export class CompressZipTransform extends plugins.stream.Transform {
|
||||||
|
files: { [fileName: string]: Uint8Array };
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.files = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
_transform(chunk: Buffer, encoding: BufferEncoding, callback: plugins.stream.TransformCallback) {
|
||||||
|
// Simple example: storing chunks in memory before finalizing ZIP in _flush
|
||||||
|
this.files['file.txt'] = new Uint8Array(chunk);
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
_flush(callback: plugins.stream.TransformCallback) {
|
||||||
|
plugins.fflate.zip(this.files, (err, zipped) => {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
} else {
|
||||||
|
this.push(Buffer.from(zipped));
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ZipTools {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public getCompressionStream() {
|
||||||
|
return new CompressZipTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDecompressionStream() {
|
||||||
|
return new DecompressZipTransform();
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,4 @@
|
|||||||
export * from './classes.smartarchive.js';
|
export * from './classes.smartarchive.js';
|
||||||
|
export * from './classes.tartools.js';
|
||||||
|
export * from './classes.ziptools.js';
|
||||||
|
export * from './classes.gziptools.js';
|
||||||
|
@ -6,6 +6,7 @@ export { path, stream };
|
|||||||
|
|
||||||
// @pushrocks scope
|
// @pushrocks scope
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
|
import * as smartdelay from '@push.rocks/smartdelay';
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
import * as smartpromise from '@push.rocks/smartpromise';
|
import * as smartpromise from '@push.rocks/smartpromise';
|
||||||
import * as smartrequest from '@push.rocks/smartrequest';
|
import * as smartrequest from '@push.rocks/smartrequest';
|
||||||
@ -14,7 +15,7 @@ import * as smartstream from '@push.rocks/smartstream';
|
|||||||
import * as smartrx from '@push.rocks/smartrx';
|
import * as smartrx from '@push.rocks/smartrx';
|
||||||
import * as smarturl from '@push.rocks/smarturl';
|
import * as smarturl from '@push.rocks/smarturl';
|
||||||
|
|
||||||
export { smartfile, smartpath, smartpromise, smartrequest, smartunique, smartstream, smartrx, smarturl };
|
export { smartfile, smartdelay, smartpath, smartpromise, smartrequest, smartunique, smartstream, smartrx, smarturl };
|
||||||
|
|
||||||
// third party scope
|
// third party scope
|
||||||
import * as fileType from 'file-type';
|
import * as fileType from 'file-type';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user