exarch-rs 0.1.1 → 0.1.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/{exarch-rs.darwin-arm64.node → native/exarch-rs.darwin-arm64.node} +0 -0
- package/native/exarch-rs.darwin-x64.node +0 -0
- package/native/exarch-rs.linux-arm64-gnu.node +0 -0
- package/native/exarch-rs.linux-x64-gnu.node +0 -0
- package/native/exarch-rs.win32-x64-msvc.node +0 -0
- package/package.json +1 -1
- package/src/lib.rs +7 -3
- package/tests/create.test.js +13 -1
- package/tests/extract.test.js +31 -32
- package/tests/list-verify.test.js +25 -1
- package/index.d.ts +0 -657
- package/index.js +0 -588
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/lib.rs
CHANGED
|
@@ -208,9 +208,13 @@ pub fn extract_archive_sync(
|
|
|
208
208
|
let default_config = exarch_core::SecurityConfig::default();
|
|
209
209
|
let config_ref = config.map_or(&default_config, |c| c.as_core());
|
|
210
210
|
|
|
211
|
-
// Run extraction synchronously
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
// Run extraction synchronously with panic safety
|
|
212
|
+
// CRITICAL: Never panic across FFI boundary
|
|
213
|
+
let report = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
|
214
|
+
exarch_core::extract_archive(&archive_path, &output_dir, config_ref)
|
|
215
|
+
}))
|
|
216
|
+
.map_err(|_| Error::from_reason("Internal panic during archive extraction"))?
|
|
217
|
+
.map_err(convert_error)?;
|
|
214
218
|
|
|
215
219
|
Ok(ExtractionReport::from(report))
|
|
216
220
|
}
|
package/tests/create.test.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for archive creation functions
|
|
3
3
|
*/
|
|
4
|
-
const { describe, it, beforeEach } = require('node:test');
|
|
4
|
+
const { describe, it, beforeEach, afterEach } = require('node:test');
|
|
5
5
|
const assert = require('node:assert');
|
|
6
6
|
const fs = require('node:fs');
|
|
7
7
|
const path = require('node:path');
|
|
@@ -39,6 +39,12 @@ describe('createArchive (async)', () => {
|
|
|
39
39
|
outputPath = path.join(tempDir, 'output.tar.gz');
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
44
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
42
48
|
it('should create a tar.gz archive', async () => {
|
|
43
49
|
const report = await createArchive(outputPath, [sourceDir]);
|
|
44
50
|
|
|
@@ -95,6 +101,12 @@ describe('createArchiveSync', () => {
|
|
|
95
101
|
outputPath = path.join(tempDir, 'output.tar.gz');
|
|
96
102
|
});
|
|
97
103
|
|
|
104
|
+
afterEach(() => {
|
|
105
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
106
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
98
110
|
it('should create archive synchronously', () => {
|
|
99
111
|
const report = createArchiveSync(outputPath, [sourceDir]);
|
|
100
112
|
|
package/tests/extract.test.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for archive extraction functions
|
|
3
|
-
*
|
|
4
|
-
* NOTE: Extraction tests are skipped until exarch-core extract_archive API is fully implemented.
|
|
5
|
-
* The current implementation is a placeholder (see exarch-core/src/api.rs).
|
|
6
3
|
*/
|
|
7
|
-
const { describe, it, beforeEach } = require('node:test');
|
|
4
|
+
const { describe, it, beforeEach, afterEach } = require('node:test');
|
|
8
5
|
const assert = require('node:assert');
|
|
9
6
|
const fs = require('node:fs');
|
|
10
7
|
const path = require('node:path');
|
|
@@ -42,19 +39,29 @@ describe('extractArchive (async)', () => {
|
|
|
42
39
|
fs.mkdirSync(outputDir);
|
|
43
40
|
});
|
|
44
41
|
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
44
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should extract a valid archive', async () => {
|
|
47
49
|
createValidArchive(archivePath, tempDir);
|
|
48
50
|
|
|
49
51
|
const report = await extractArchive(archivePath, outputDir);
|
|
50
52
|
|
|
51
|
-
assert.
|
|
53
|
+
assert.strictEqual(report.filesExtracted, 1);
|
|
52
54
|
assert.ok(report.bytesWritten >= 13);
|
|
53
55
|
assert.ok(report.durationMs >= 0);
|
|
56
|
+
|
|
57
|
+
// Verify extracted file exists and has correct content
|
|
58
|
+
const extractedFile = path.join(outputDir, 'hello.txt');
|
|
59
|
+
assert.ok(fs.existsSync(extractedFile), 'Extracted file should exist');
|
|
60
|
+
const content = fs.readFileSync(extractedFile, 'utf8');
|
|
61
|
+
assert.strictEqual(content, 'Hello, World!');
|
|
54
62
|
});
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
it.skip('should accept custom SecurityConfig', async () => {
|
|
64
|
+
it('should accept custom SecurityConfig', async () => {
|
|
58
65
|
createValidArchive(archivePath, tempDir);
|
|
59
66
|
|
|
60
67
|
const config = new SecurityConfig();
|
|
@@ -63,15 +70,6 @@ describe('extractArchive (async)', () => {
|
|
|
63
70
|
|
|
64
71
|
assert.ok(report.filesExtracted >= 1);
|
|
65
72
|
});
|
|
66
|
-
|
|
67
|
-
it('should return empty report for valid archive (placeholder)', async () => {
|
|
68
|
-
createValidArchive(archivePath, tempDir);
|
|
69
|
-
|
|
70
|
-
const report = await extractArchive(archivePath, outputDir);
|
|
71
|
-
|
|
72
|
-
// Core extract_archive is currently a placeholder
|
|
73
|
-
assert.strictEqual(report.filesExtracted, 0);
|
|
74
|
-
});
|
|
75
73
|
});
|
|
76
74
|
|
|
77
75
|
describe('extractArchiveSync', () => {
|
|
@@ -86,18 +84,28 @@ describe('extractArchiveSync', () => {
|
|
|
86
84
|
fs.mkdirSync(outputDir);
|
|
87
85
|
});
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
afterEach(() => {
|
|
88
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
89
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should extract a valid archive synchronously', () => {
|
|
91
94
|
createValidArchive(archivePath, tempDir);
|
|
92
95
|
|
|
93
96
|
const report = extractArchiveSync(archivePath, outputDir);
|
|
94
97
|
|
|
95
|
-
assert.
|
|
98
|
+
assert.strictEqual(report.filesExtracted, 1);
|
|
96
99
|
assert.ok(report.bytesWritten >= 13);
|
|
100
|
+
|
|
101
|
+
// Verify extracted file exists and has correct content
|
|
102
|
+
const extractedFile = path.join(outputDir, 'hello.txt');
|
|
103
|
+
assert.ok(fs.existsSync(extractedFile), 'Extracted file should exist');
|
|
104
|
+
const content = fs.readFileSync(extractedFile, 'utf8');
|
|
105
|
+
assert.strictEqual(content, 'Hello, World!');
|
|
97
106
|
});
|
|
98
107
|
|
|
99
|
-
|
|
100
|
-
it.skip('should accept custom SecurityConfig', () => {
|
|
108
|
+
it('should accept custom SecurityConfig', () => {
|
|
101
109
|
createValidArchive(archivePath, tempDir);
|
|
102
110
|
|
|
103
111
|
const config = new SecurityConfig();
|
|
@@ -106,13 +114,4 @@ describe('extractArchiveSync', () => {
|
|
|
106
114
|
|
|
107
115
|
assert.ok(report.filesExtracted >= 1);
|
|
108
116
|
});
|
|
109
|
-
|
|
110
|
-
it('should return empty report for valid archive (placeholder)', () => {
|
|
111
|
-
createValidArchive(archivePath, tempDir);
|
|
112
|
-
|
|
113
|
-
const report = extractArchiveSync(archivePath, outputDir);
|
|
114
|
-
|
|
115
|
-
// Core extract_archive is currently a placeholder
|
|
116
|
-
assert.strictEqual(report.filesExtracted, 0);
|
|
117
|
-
});
|
|
118
117
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for listArchive and verifyArchive functions
|
|
3
3
|
*/
|
|
4
|
-
const { describe, it, beforeEach } = require('node:test');
|
|
4
|
+
const { describe, it, beforeEach, afterEach } = require('node:test');
|
|
5
5
|
const assert = require('node:assert');
|
|
6
6
|
const fs = require('node:fs');
|
|
7
7
|
const path = require('node:path');
|
|
@@ -38,6 +38,12 @@ describe('listArchive (async)', () => {
|
|
|
38
38
|
archivePath = path.join(tempDir, 'test.tar.gz');
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
43
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
41
47
|
it('should list archive contents', async () => {
|
|
42
48
|
createValidArchive(archivePath, tempDir);
|
|
43
49
|
|
|
@@ -78,6 +84,12 @@ describe('listArchiveSync', () => {
|
|
|
78
84
|
archivePath = path.join(tempDir, 'test.tar.gz');
|
|
79
85
|
});
|
|
80
86
|
|
|
87
|
+
afterEach(() => {
|
|
88
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
89
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
81
93
|
it('should list archive contents synchronously', () => {
|
|
82
94
|
createValidArchive(archivePath, tempDir);
|
|
83
95
|
|
|
@@ -98,6 +110,12 @@ describe('verifyArchive (async)', () => {
|
|
|
98
110
|
archivePath = path.join(tempDir, 'test.tar.gz');
|
|
99
111
|
});
|
|
100
112
|
|
|
113
|
+
afterEach(() => {
|
|
114
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
115
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
101
119
|
it('should verify a valid archive', async () => {
|
|
102
120
|
createValidArchive(archivePath, tempDir);
|
|
103
121
|
|
|
@@ -137,6 +155,12 @@ describe('verifyArchiveSync', () => {
|
|
|
137
155
|
archivePath = path.join(tempDir, 'test.tar.gz');
|
|
138
156
|
});
|
|
139
157
|
|
|
158
|
+
afterEach(() => {
|
|
159
|
+
if (tempDir && fs.existsSync(tempDir)) {
|
|
160
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
140
164
|
it('should verify archive synchronously', () => {
|
|
141
165
|
createValidArchive(archivePath, tempDir);
|
|
142
166
|
|