@voxframeworks/linetools 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/main.js +2 -1
- package/package.json +1 -1
- package/readme.md +9 -2
- package/tools/tar.js +134 -62
package/main.js
CHANGED
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -20,8 +20,15 @@ The list of commands we have is:
|
|
|
20
20
|
• cp
|
|
21
21
|
• mv
|
|
22
22
|
• touch
|
|
23
|
-
• tar (
|
|
24
|
-
|
|
23
|
+
• tar (fixed)
|
|
24
|
+
-----------------
|
|
25
|
+
Tar usage:
|
|
26
|
+
linetools.tar('testOUT', 'testDir', 'rezip')
|
|
27
|
+
TestDir = Directory to be zipped
|
|
28
|
+
TestOut = Directory for the zip to be put in
|
|
29
|
+
rezip = zip
|
|
30
|
+
unzip = unzip
|
|
31
|
+
------------------
|
|
25
32
|
We will be adding more soon!
|
|
26
33
|
|
|
27
34
|
By VoxFrameworks
|
package/tools/tar.js
CHANGED
|
@@ -1,69 +1,141 @@
|
|
|
1
|
-
|
|
1
|
+
// lib/tar.js
|
|
2
|
+
/**
|
|
3
|
+
* Tiny wrapper around the `tar` package.
|
|
4
|
+
*
|
|
5
|
+
* linetools.tar(target, source, type)
|
|
6
|
+
*
|
|
7
|
+
* target – where the archive should be written (for "rezip")
|
|
8
|
+
* OR the archive to read (for "unzip").
|
|
9
|
+
* It may be:
|
|
10
|
+
* • a full filename, e.g. "out/pkg.tar.gz"
|
|
11
|
+
* • a directory name – the function will create
|
|
12
|
+
* "archive.tar" (or "archive.tar.gz") inside it.
|
|
13
|
+
*
|
|
14
|
+
* source – folder to pack / file to pack (rezip) OR
|
|
15
|
+
* destination folder for extraction (unzip)
|
|
16
|
+
*
|
|
17
|
+
* type – "rezip" (create) or "unzip" (extract)
|
|
18
|
+
*
|
|
19
|
+
* Supports g‑zipped archives when the target ends with ".gz" or ".tar.gz".
|
|
20
|
+
*
|
|
21
|
+
* @param {string} targetPath
|
|
22
|
+
* @param {string} sourcePath
|
|
23
|
+
* @param {'unzip'|'rezip'} type
|
|
24
|
+
* @returns {Promise<void>}
|
|
25
|
+
*/
|
|
26
|
+
const tar = require('tar');
|
|
2
27
|
const fs = require('fs').promises;
|
|
3
28
|
const path = require('path');
|
|
4
29
|
|
|
30
|
+
async function ensureDir(dir) {
|
|
31
|
+
await fs.mkdir(dir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a *file* name for the archive.
|
|
36
|
+
* If `targetPath` already points to an existing directory,
|
|
37
|
+
* a default filename (`archive.tar` or `archive.tar.gz`) is added.
|
|
38
|
+
* If no extension is supplied, `.tar` (or `.tar.gz` for gzip) is appended.
|
|
39
|
+
*/
|
|
40
|
+
async function resolveTargetFile(targetPath, mode) {
|
|
41
|
+
const stat = await fs.lstat(targetPath).catch(() => null);
|
|
42
|
+
|
|
43
|
+
// ── target is an existing directory → add a default filename ──
|
|
44
|
+
if (stat && stat.isDirectory()) {
|
|
45
|
+
if (mode !== 'rezip')
|
|
46
|
+
throw new Error(
|
|
47
|
+
'When extracting, targetPath must be a file (the tarball).'
|
|
48
|
+
);
|
|
49
|
+
const defaultName = targetPath.endsWith('.gz')
|
|
50
|
+
? 'archive.tar.gz'
|
|
51
|
+
: 'archive.tar';
|
|
52
|
+
return path.join(targetPath, defaultName);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ── target does NOT exist – make sure its parent directory exists ──
|
|
56
|
+
const parent = path.dirname(targetPath);
|
|
57
|
+
await ensureDir(parent);
|
|
58
|
+
|
|
59
|
+
// ── does it already have a proper .tar/.tar.gz extension? ──
|
|
60
|
+
const hasTarExt = targetPath.endsWith('.tar') || targetPath.endsWith('.tar.gz');
|
|
61
|
+
if (hasTarExt) return targetPath;
|
|
62
|
+
|
|
63
|
+
// ── no extension – infer one. If the caller added a trailing ".gz"
|
|
64
|
+
// (e.g. "out/.gz") we treat it as a request for gzip compression.
|
|
65
|
+
const inferred = targetPath + (mode === 'rezip' && targetPath.endsWith('.gz')
|
|
66
|
+
? '.tar.gz'
|
|
67
|
+
: '.tar');
|
|
68
|
+
return inferred;
|
|
69
|
+
}
|
|
70
|
+
|
|
5
71
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {string} targetPath - The path to the tarball file (output for rezip, input for unzip).
|
|
8
|
-
* @param {string} sourcePath - The source directory/files for rezip, or the destination directory for unzip.
|
|
9
|
-
* @param {'unzip' | 'rezip'} type - The operation type.
|
|
72
|
+
* Core operation – create (`rezip`) or extract (`unzip`) a tarball.
|
|
10
73
|
*/
|
|
11
|
-
async function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
async function tarOperation(targetPath, sourcePath, type) {
|
|
75
|
+
// -----------------------------------------------------------------
|
|
76
|
+
// 1️⃣ UNZIP – extract archive into a directory
|
|
77
|
+
// -----------------------------------------------------------------
|
|
78
|
+
if (type === 'unzip') {
|
|
79
|
+
await ensureDir(sourcePath);
|
|
80
|
+
console.log(`🔽 Extracting '${targetPath}' → '${sourcePath}' …`);
|
|
81
|
+
|
|
82
|
+
await tar.extract({
|
|
83
|
+
file: targetPath,
|
|
84
|
+
cwd: sourcePath, // extract *into* this folder
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
console.log('✅ Extraction finished.');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// -----------------------------------------------------------------
|
|
92
|
+
// 2️⃣ REZIP – create a tarball from a folder *or* a single file
|
|
93
|
+
// -----------------------------------------------------------------
|
|
94
|
+
if (type === 'rezip') {
|
|
95
|
+
// Resolve a real filename for the archive (adds .tar/.tar.gz if needed)
|
|
96
|
+
const finalTarget = await resolveTargetFile(targetPath, 'rezip');
|
|
97
|
+
|
|
98
|
+
// Determine if the source is a file or a directory
|
|
99
|
+
const srcStat = await fs.lstat(sourcePath).catch(() => {
|
|
100
|
+
throw new Error(`Source path does not exist: ${sourcePath}`);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// tar.create() needs:
|
|
104
|
+
// - cwd : where the files are looked up
|
|
105
|
+
// - file: the output tarball
|
|
106
|
+
// - gzip: true if we want *.tar.gz
|
|
107
|
+
const tarOpts = {
|
|
108
|
+
cwd: srcStat.isDirectory() ? sourcePath : path.dirname(sourcePath),
|
|
109
|
+
file: finalTarget,
|
|
110
|
+
gzip: finalTarget.endsWith('.gz'), // true for .tar.gz, false for .tar
|
|
111
|
+
portable: true, // reproducible timestamps
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Decide which entries to feed to tar:
|
|
115
|
+
// • directory → pack everything inside it (['.'])
|
|
116
|
+
// • file → pack only that one file (basename)
|
|
117
|
+
const entries = srcStat.isDirectory()
|
|
118
|
+
? ['.']
|
|
119
|
+
: [path.basename(sourcePath)];
|
|
120
|
+
|
|
121
|
+
console.log(
|
|
122
|
+
`📦 Creating ${tarOpts.gzip ? 'gzip‑compressed ' : ''}` +
|
|
123
|
+
`tarball '${finalTarget}' from ${srcStat.isDirectory() ? 'folder' : 'file'} ` +
|
|
124
|
+
`'${sourcePath}' …`
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// `tar.create` returns a promise that resolves when the stream finishes.
|
|
128
|
+
await tar.create(tarOpts, entries);
|
|
129
|
+
|
|
130
|
+
console.log('✅ Tarball created successfully.');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// -----------------------------------------------------------------
|
|
135
|
+
// 3️⃣ WRONG TYPE
|
|
136
|
+
// -----------------------------------------------------------------
|
|
137
|
+
throw new Error('Invalid type – use "unzip" or "rezip".');
|
|
67
138
|
}
|
|
68
139
|
|
|
69
|
-
|
|
140
|
+
// Export the function that the consumer will receive as `linetools.tar`
|
|
141
|
+
module.exports = tarOperation;
|