@neoware_inc/neozipkit 0.5.0
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/README.md +134 -0
- package/dist/browser/ZipkitBrowser.d.ts +27 -0
- package/dist/browser/ZipkitBrowser.d.ts.map +1 -0
- package/dist/browser/ZipkitBrowser.js +303 -0
- package/dist/browser/ZipkitBrowser.js.map +1 -0
- package/dist/browser/index.d.ts +9 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.esm.d.ts +12 -0
- package/dist/browser/index.esm.d.ts.map +1 -0
- package/dist/browser/index.esm.js +46 -0
- package/dist/browser/index.esm.js.map +1 -0
- package/dist/browser/index.js +38 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser-esm/index.d.ts +9 -0
- package/dist/browser-esm/index.js +50211 -0
- package/dist/browser-esm/index.js.map +7 -0
- package/dist/browser-umd/index.d.ts +9 -0
- package/dist/browser-umd/index.js +50221 -0
- package/dist/browser-umd/index.js.map +7 -0
- package/dist/browser-umd/index.min.js +39 -0
- package/dist/browser.d.ts +9 -0
- package/dist/browser.js +38 -0
- package/dist/core/ZipCompress.d.ts +99 -0
- package/dist/core/ZipCompress.d.ts.map +1 -0
- package/dist/core/ZipCompress.js +287 -0
- package/dist/core/ZipCompress.js.map +1 -0
- package/dist/core/ZipCopy.d.ts +175 -0
- package/dist/core/ZipCopy.d.ts.map +1 -0
- package/dist/core/ZipCopy.js +310 -0
- package/dist/core/ZipCopy.js.map +1 -0
- package/dist/core/ZipDecompress.d.ts +57 -0
- package/dist/core/ZipDecompress.d.ts.map +1 -0
- package/dist/core/ZipDecompress.js +155 -0
- package/dist/core/ZipDecompress.js.map +1 -0
- package/dist/core/ZipEntry.d.ts +138 -0
- package/dist/core/ZipEntry.d.ts.map +1 -0
- package/dist/core/ZipEntry.js +829 -0
- package/dist/core/ZipEntry.js.map +1 -0
- package/dist/core/Zipkit.d.ts +315 -0
- package/dist/core/Zipkit.d.ts.map +1 -0
- package/dist/core/Zipkit.js +647 -0
- package/dist/core/Zipkit.js.map +1 -0
- package/dist/core/ZstdManager.d.ts +56 -0
- package/dist/core/ZstdManager.d.ts.map +1 -0
- package/dist/core/ZstdManager.js +144 -0
- package/dist/core/ZstdManager.js.map +1 -0
- package/dist/core/components/HashCalculator.d.ts +138 -0
- package/dist/core/components/HashCalculator.d.ts.map +1 -0
- package/dist/core/components/HashCalculator.js +360 -0
- package/dist/core/components/HashCalculator.js.map +1 -0
- package/dist/core/components/Logger.d.ts +73 -0
- package/dist/core/components/Logger.d.ts.map +1 -0
- package/dist/core/components/Logger.js +156 -0
- package/dist/core/components/Logger.js.map +1 -0
- package/dist/core/components/ProgressTracker.d.ts +43 -0
- package/dist/core/components/ProgressTracker.d.ts.map +1 -0
- package/dist/core/components/ProgressTracker.js +112 -0
- package/dist/core/components/ProgressTracker.js.map +1 -0
- package/dist/core/components/Support.d.ts +64 -0
- package/dist/core/components/Support.d.ts.map +1 -0
- package/dist/core/components/Support.js +71 -0
- package/dist/core/components/Support.js.map +1 -0
- package/dist/core/components/Util.d.ts +26 -0
- package/dist/core/components/Util.d.ts.map +1 -0
- package/dist/core/components/Util.js +95 -0
- package/dist/core/components/Util.js.map +1 -0
- package/dist/core/constants/Errors.d.ts +52 -0
- package/dist/core/constants/Errors.d.ts.map +1 -0
- package/dist/core/constants/Errors.js +67 -0
- package/dist/core/constants/Errors.js.map +1 -0
- package/dist/core/constants/Headers.d.ts +170 -0
- package/dist/core/constants/Headers.d.ts.map +1 -0
- package/dist/core/constants/Headers.js +194 -0
- package/dist/core/constants/Headers.js.map +1 -0
- package/dist/core/encryption/Manager.d.ts +58 -0
- package/dist/core/encryption/Manager.d.ts.map +1 -0
- package/dist/core/encryption/Manager.js +121 -0
- package/dist/core/encryption/Manager.js.map +1 -0
- package/dist/core/encryption/ZipCrypto.d.ts +172 -0
- package/dist/core/encryption/ZipCrypto.d.ts.map +1 -0
- package/dist/core/encryption/ZipCrypto.js +554 -0
- package/dist/core/encryption/ZipCrypto.js.map +1 -0
- package/dist/core/encryption/index.d.ts +9 -0
- package/dist/core/encryption/index.d.ts.map +1 -0
- package/dist/core/encryption/index.js +17 -0
- package/dist/core/encryption/index.js.map +1 -0
- package/dist/core/encryption/types.d.ts +29 -0
- package/dist/core/encryption/types.d.ts.map +1 -0
- package/dist/core/encryption/types.js +12 -0
- package/dist/core/encryption/types.js.map +1 -0
- package/dist/core/index.d.ts +27 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +59 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/version.d.ts +5 -0
- package/dist/core/version.d.ts.map +1 -0
- package/dist/core/version.js +31 -0
- package/dist/core/version.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/node/ZipCompressNode.d.ts +123 -0
- package/dist/node/ZipCompressNode.d.ts.map +1 -0
- package/dist/node/ZipCompressNode.js +565 -0
- package/dist/node/ZipCompressNode.js.map +1 -0
- package/dist/node/ZipCopyNode.d.ts +165 -0
- package/dist/node/ZipCopyNode.d.ts.map +1 -0
- package/dist/node/ZipCopyNode.js +347 -0
- package/dist/node/ZipCopyNode.js.map +1 -0
- package/dist/node/ZipDecompressNode.d.ts +197 -0
- package/dist/node/ZipDecompressNode.d.ts.map +1 -0
- package/dist/node/ZipDecompressNode.js +678 -0
- package/dist/node/ZipDecompressNode.js.map +1 -0
- package/dist/node/ZipkitNode.d.ts +466 -0
- package/dist/node/ZipkitNode.d.ts.map +1 -0
- package/dist/node/ZipkitNode.js +1426 -0
- package/dist/node/ZipkitNode.js.map +1 -0
- package/dist/node/index.d.ts +25 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +54 -0
- package/dist/node/index.js.map +1 -0
- package/dist/types/index.d.ts +45 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +11 -0
- package/dist/types/index.js.map +1 -0
- package/examples/README.md +261 -0
- package/examples/append-data.json +44 -0
- package/examples/copy-zip-append.ts +139 -0
- package/examples/copy-zip.ts +152 -0
- package/examples/create-zip.ts +172 -0
- package/examples/extract-zip.ts +118 -0
- package/examples/list-zip.ts +161 -0
- package/examples/test-files/data.json +116 -0
- package/examples/test-files/document.md +80 -0
- package/examples/test-files/document.txt +6 -0
- package/examples/test-files/file1.txt +48 -0
- package/examples/test-files/file2.txt +80 -0
- package/examples/tsconfig.json +44 -0
- package/package.json +167 -0
- package/src/browser/ZipkitBrowser.ts +305 -0
- package/src/browser/index.esm.ts +32 -0
- package/src/browser/index.ts +19 -0
- package/src/core/ZipCompress.ts +370 -0
- package/src/core/ZipCopy.ts +434 -0
- package/src/core/ZipDecompress.ts +191 -0
- package/src/core/ZipEntry.ts +917 -0
- package/src/core/Zipkit.ts +794 -0
- package/src/core/ZstdManager.ts +165 -0
- package/src/core/components/HashCalculator.ts +384 -0
- package/src/core/components/Logger.ts +180 -0
- package/src/core/components/ProgressTracker.ts +134 -0
- package/src/core/components/Support.ts +77 -0
- package/src/core/components/Util.ts +91 -0
- package/src/core/constants/Errors.ts +78 -0
- package/src/core/constants/Headers.ts +205 -0
- package/src/core/encryption/Manager.ts +137 -0
- package/src/core/encryption/ZipCrypto.ts +650 -0
- package/src/core/encryption/index.ts +15 -0
- package/src/core/encryption/types.ts +33 -0
- package/src/core/index.ts +42 -0
- package/src/core/version.ts +33 -0
- package/src/index.ts +19 -0
- package/src/node/ZipCompressNode.ts +618 -0
- package/src/node/ZipCopyNode.ts +437 -0
- package/src/node/ZipDecompressNode.ts +793 -0
- package/src/node/ZipkitNode.ts +1706 -0
- package/src/node/index.ts +40 -0
- package/src/types/index.ts +68 -0
- package/src/types/modules.d.ts +22 -0
- package/src/types/opentimestamps.d.ts +1 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global Logger Utility for NeoZipKit
|
|
3
|
+
* Provides centralized console control with configurable log levels
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
|
|
7
|
+
|
|
8
|
+
export interface LoggerConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
level: LogLevel;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Global Logger class for controlling console output throughout NeoZipKit
|
|
15
|
+
*/
|
|
16
|
+
export class Logger {
|
|
17
|
+
private static config: LoggerConfig = {
|
|
18
|
+
enabled: true,
|
|
19
|
+
level: 'info'
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
private static originalConsole = {
|
|
23
|
+
log: console.log,
|
|
24
|
+
error: console.error,
|
|
25
|
+
warn: console.warn,
|
|
26
|
+
debug: console.debug,
|
|
27
|
+
info: console.info
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Configure the logger
|
|
32
|
+
*/
|
|
33
|
+
static configure(config: Partial<LoggerConfig>): void {
|
|
34
|
+
this.config = { ...this.config, ...config };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get current logger configuration
|
|
39
|
+
*/
|
|
40
|
+
static getConfig(): LoggerConfig {
|
|
41
|
+
return { ...this.config };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Enable logging
|
|
46
|
+
*/
|
|
47
|
+
static enable(): void {
|
|
48
|
+
this.config.enabled = true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Disable all logging
|
|
53
|
+
*/
|
|
54
|
+
static disable(): void {
|
|
55
|
+
this.config.enabled = false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Set log level
|
|
60
|
+
*/
|
|
61
|
+
static setLevel(level: LogLevel): void {
|
|
62
|
+
this.config.level = level;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Check if a log level should be output
|
|
68
|
+
*/
|
|
69
|
+
private static shouldLog(level: LogLevel): boolean {
|
|
70
|
+
if (!this.config.enabled) return false;
|
|
71
|
+
|
|
72
|
+
const levels: LogLevel[] = ['debug', 'info', 'warn', 'error', 'silent'];
|
|
73
|
+
const currentLevelIndex = levels.indexOf(this.config.level);
|
|
74
|
+
const requestedLevelIndex = levels.indexOf(level);
|
|
75
|
+
|
|
76
|
+
return requestedLevelIndex >= currentLevelIndex;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Log a message
|
|
81
|
+
*/
|
|
82
|
+
static log(...args: any[]): void {
|
|
83
|
+
if (this.shouldLog('info')) {
|
|
84
|
+
this.originalConsole.log(...args);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Log an error message
|
|
90
|
+
*/
|
|
91
|
+
static error(...args: any[]): void {
|
|
92
|
+
if (this.shouldLog('error')) {
|
|
93
|
+
this.originalConsole.error(...args);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Log a warning message
|
|
99
|
+
*/
|
|
100
|
+
static warn(...args: any[]): void {
|
|
101
|
+
if (this.shouldLog('warn')) {
|
|
102
|
+
this.originalConsole.warn(...args);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Log a debug message
|
|
108
|
+
*/
|
|
109
|
+
static debug(...args: any[]): void {
|
|
110
|
+
if (this.shouldLog('debug')) {
|
|
111
|
+
// Use console.log for debug messages to ensure they're visible
|
|
112
|
+
this.originalConsole.log(...args);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Log an info message
|
|
118
|
+
*/
|
|
119
|
+
static info(...args: any[]): void {
|
|
120
|
+
if (this.shouldLog('info')) {
|
|
121
|
+
this.originalConsole.info(...args);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Override console methods globally (use with caution)
|
|
128
|
+
*/
|
|
129
|
+
static overrideConsole(): void {
|
|
130
|
+
console.log = (...args: any[]) => this.log(...args);
|
|
131
|
+
console.error = (...args: any[]) => this.error(...args);
|
|
132
|
+
console.warn = (...args: any[]) => this.warn(...args);
|
|
133
|
+
console.debug = (...args: any[]) => this.debug(...args);
|
|
134
|
+
console.info = (...args: any[]) => this.info(...args);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Restore original console methods
|
|
139
|
+
*/
|
|
140
|
+
static restoreConsole(): void {
|
|
141
|
+
console.log = this.originalConsole.log;
|
|
142
|
+
console.error = this.originalConsole.error;
|
|
143
|
+
console.warn = this.originalConsole.warn;
|
|
144
|
+
console.debug = this.originalConsole.debug;
|
|
145
|
+
console.info = this.originalConsole.info;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Environment-based configuration
|
|
152
|
+
*/
|
|
153
|
+
export function configureLoggerFromEnvironment(): void {
|
|
154
|
+
const env = typeof process !== 'undefined' ? process.env : {};
|
|
155
|
+
|
|
156
|
+
// Check for NEOZIP_DEBUG environment variable
|
|
157
|
+
if (env.NEOZIP_DEBUG === 'false') {
|
|
158
|
+
Logger.disable();
|
|
159
|
+
} else if (env.NEOZIP_DEBUG === 'true') {
|
|
160
|
+
Logger.enable();
|
|
161
|
+
Logger.setLevel('debug');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Check for NEOZIP_LOG_LEVEL
|
|
165
|
+
if (env.NEOZIP_LOG_LEVEL) {
|
|
166
|
+
const level = env.NEOZIP_LOG_LEVEL as LogLevel;
|
|
167
|
+
if (['debug', 'info', 'warn', 'error', 'silent'].includes(level)) {
|
|
168
|
+
Logger.setLevel(level);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Check for NODE_ENV
|
|
173
|
+
if (env.NODE_ENV === 'production') {
|
|
174
|
+
Logger.setLevel('error');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Auto-configure from environment on import
|
|
179
|
+
// Only run in Node.js environment
|
|
180
|
+
configureLoggerFromEnvironment();
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress tracker for streaming operations
|
|
3
|
+
* Provides real-time progress updates and ETA calculations
|
|
4
|
+
*/
|
|
5
|
+
export class ProgressTracker {
|
|
6
|
+
private startTime: number;
|
|
7
|
+
private lastUpdateTime: number;
|
|
8
|
+
private totalBytes: number;
|
|
9
|
+
private processedBytes: number;
|
|
10
|
+
private fileName: string;
|
|
11
|
+
private lastReportedPercent: number = -1;
|
|
12
|
+
|
|
13
|
+
constructor(fileName: string, totalBytes: number) {
|
|
14
|
+
this.fileName = fileName;
|
|
15
|
+
this.totalBytes = totalBytes;
|
|
16
|
+
this.processedBytes = 0;
|
|
17
|
+
this.startTime = Date.now();
|
|
18
|
+
this.lastUpdateTime = this.startTime;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Update progress with bytes processed
|
|
23
|
+
* @param bytesProcessed - Number of bytes processed in this update
|
|
24
|
+
*/
|
|
25
|
+
update(bytesProcessed: number): void {
|
|
26
|
+
this.processedBytes += bytesProcessed;
|
|
27
|
+
this.reportProgress();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Set total bytes (useful when file size changes)
|
|
32
|
+
*/
|
|
33
|
+
setTotalBytes(totalBytes: number): void {
|
|
34
|
+
this.totalBytes = totalBytes;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Report progress if enough time has passed or significant progress made
|
|
39
|
+
*/
|
|
40
|
+
private reportProgress(): void {
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
const percent = Math.floor((this.processedBytes / this.totalBytes) * 100);
|
|
43
|
+
|
|
44
|
+
// Report if:
|
|
45
|
+
// 1. 1% or more progress made, OR
|
|
46
|
+
// 2. 500ms have passed since last report
|
|
47
|
+
const shouldReport =
|
|
48
|
+
percent > this.lastReportedPercent ||
|
|
49
|
+
(now - this.lastUpdateTime) > 500;
|
|
50
|
+
|
|
51
|
+
if (shouldReport) {
|
|
52
|
+
this.lastReportedPercent = percent;
|
|
53
|
+
this.lastUpdateTime = now;
|
|
54
|
+
this.printProgress();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Print progress information
|
|
60
|
+
*/
|
|
61
|
+
private printProgress(): void {
|
|
62
|
+
const elapsed = (Date.now() - this.startTime) / 1000;
|
|
63
|
+
const rate = this.processedBytes / elapsed;
|
|
64
|
+
const eta = this.totalBytes > this.processedBytes
|
|
65
|
+
? (this.totalBytes - this.processedBytes) / rate
|
|
66
|
+
: 0;
|
|
67
|
+
const percent = Math.floor((this.processedBytes / this.totalBytes) * 100);
|
|
68
|
+
|
|
69
|
+
const formatBytes = (bytes: number): string => {
|
|
70
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
71
|
+
let size = bytes;
|
|
72
|
+
let unitIndex = 0;
|
|
73
|
+
|
|
74
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
75
|
+
size /= 1024;
|
|
76
|
+
unitIndex++;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `${size.toFixed(1)}${units[unitIndex]}`;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const formatTime = (seconds: number): string => {
|
|
83
|
+
if (seconds < 60) return `${seconds.toFixed(0)}s`;
|
|
84
|
+
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${(seconds % 60).toFixed(0)}s`;
|
|
85
|
+
return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
process.stdout.write(
|
|
89
|
+
`\r${this.fileName}: ${percent}% (${formatBytes(this.processedBytes)}/${formatBytes(this.totalBytes)}) ` +
|
|
90
|
+
`[${formatBytes(rate)}/s] ETA: ${formatTime(eta)}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Complete progress tracking
|
|
96
|
+
*/
|
|
97
|
+
complete(): void {
|
|
98
|
+
const elapsed = (Date.now() - this.startTime) / 1000;
|
|
99
|
+
const rate = this.processedBytes / elapsed;
|
|
100
|
+
|
|
101
|
+
const formatBytes = (bytes: number): string => {
|
|
102
|
+
const units = ['B', 'KB', 'MB', 'GB'];
|
|
103
|
+
let size = bytes;
|
|
104
|
+
let unitIndex = 0;
|
|
105
|
+
|
|
106
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
107
|
+
size /= 1024;
|
|
108
|
+
unitIndex++;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return `${size.toFixed(1)}${units[unitIndex]}`;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
console.log(
|
|
115
|
+
`\r${this.fileName}: 100% (${formatBytes(this.processedBytes)}) ` +
|
|
116
|
+
`[${formatBytes(rate)}/s] completed in ${elapsed.toFixed(1)}s`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get current progress percentage
|
|
122
|
+
*/
|
|
123
|
+
getProgressPercent(): number {
|
|
124
|
+
return Math.floor((this.processedBytes / this.totalBytes) * 100);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get processing rate in bytes per second
|
|
129
|
+
*/
|
|
130
|
+
getProcessingRate(): number {
|
|
131
|
+
const elapsed = (Date.now() - this.startTime) / 1000;
|
|
132
|
+
return this.processedBytes / elapsed;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// ======================================
|
|
2
|
+
// Support.ts
|
|
3
|
+
// A utility module for detecting platform capabilities and features
|
|
4
|
+
// Copyright (c) 2024 NeoWare, Inc. All rights reserved.
|
|
5
|
+
// ======================================
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Platform and environment feature detection utility
|
|
9
|
+
* Provides boolean flags indicating support for various features needed by NeoZip
|
|
10
|
+
*
|
|
11
|
+
* @namespace Support
|
|
12
|
+
* @property {boolean} base64 - Always true, indicates base64 encoding support
|
|
13
|
+
* @property {boolean} array - Always true, indicates Array support
|
|
14
|
+
* @property {boolean} string - Always true, indicates String support
|
|
15
|
+
* @property {boolean} isNode - True if running in Node.js environment
|
|
16
|
+
* @property {boolean} buffer - True if Node.js Buffer is available
|
|
17
|
+
* @property {boolean} uint8array - True if Uint8Array is supported
|
|
18
|
+
* @property {boolean} arrayBuffer - True if both ArrayBuffer and Uint8Array are supported
|
|
19
|
+
* @property {boolean} blob - True if Blob creation with ArrayBuffer is supported
|
|
20
|
+
* @property {boolean} streams - True if ReadableStream and WritableStream are supported
|
|
21
|
+
* @property {boolean} fileReader - True if FileReader is supported
|
|
22
|
+
*/
|
|
23
|
+
const Support = {
|
|
24
|
+
/** Base64 encoding support (always true) */
|
|
25
|
+
base64: true,
|
|
26
|
+
/** Array support (always true) */
|
|
27
|
+
array: true,
|
|
28
|
+
/** String support (always true) */
|
|
29
|
+
string: true,
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Detects if code is running in Node.js environment
|
|
33
|
+
* True if process.versions.node exists, undefined in browser
|
|
34
|
+
*/
|
|
35
|
+
isNode: true,
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Detects if Node.js Buffer is available
|
|
39
|
+
* True in Node.js, undefined in browser
|
|
40
|
+
*/
|
|
41
|
+
buffer: true,
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Detects support for Uint8Array typed array
|
|
45
|
+
* Used for binary data handling
|
|
46
|
+
*/
|
|
47
|
+
uint8array: true,
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Detects support for both ArrayBuffer and Uint8Array
|
|
51
|
+
* Required for binary data operations
|
|
52
|
+
*/
|
|
53
|
+
arrayBuffer: typeof ArrayBuffer !== "undefined" && typeof Uint8Array !== "undefined",
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Detects support for Blob with ArrayBuffer
|
|
57
|
+
* Tests by attempting to create an empty ZIP Blob
|
|
58
|
+
* @returns {boolean} True if Blob creation succeeds
|
|
59
|
+
*/
|
|
60
|
+
blob: true,
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Detects support for Streams API
|
|
64
|
+
* Checks for ReadableStream/WritableStream in browser
|
|
65
|
+
* or 'stream' module in Node.js
|
|
66
|
+
* @returns {boolean} True if streams are supported in current environment
|
|
67
|
+
*/
|
|
68
|
+
streams: true,
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Detects support for FileReader
|
|
72
|
+
* @returns {boolean} True if FileReader is supported
|
|
73
|
+
*/
|
|
74
|
+
fileReader: false
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export default Support;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// ======================================
|
|
2
|
+
// Util.ts
|
|
3
|
+
// Copyright (c) 2024 NeoWare, Inc. All rights reserved.
|
|
4
|
+
// ======================================
|
|
5
|
+
// Utility functions
|
|
6
|
+
|
|
7
|
+
import Support from "./Support";
|
|
8
|
+
import Errors from "../constants/Errors";
|
|
9
|
+
import { TIMESTAMP_SUBMITTED, TIMESTAMP_METADATA, TOKENIZED_METADATA } from "../constants/Headers";
|
|
10
|
+
|
|
11
|
+
export const DATATYPE = {
|
|
12
|
+
STRING: "string",
|
|
13
|
+
BUFFER: "buffer",
|
|
14
|
+
ARRAY: "array",
|
|
15
|
+
ARRAYBUFFER: "arraybuffer",
|
|
16
|
+
U8ARRAY: "uint8array",
|
|
17
|
+
BLOB: "blob",
|
|
18
|
+
STREAM: "stream",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Parse a 64-bit unsigned integer from a buffer
|
|
22
|
+
export function readBigUInt64LE(buffer: Buffer, index: number): number {
|
|
23
|
+
var buf = Buffer.from(buffer.subarray(index, index + 8));
|
|
24
|
+
buf.swap64();
|
|
25
|
+
|
|
26
|
+
return parseInt(`0x${buf.toString("hex")}`);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// C-style uInt32 Multiply (discards higher bits, when JS multiply discards lower bits)
|
|
30
|
+
export const uMul = (a: number, b: number) => Math.imul(a, b) >>> 0;
|
|
31
|
+
|
|
32
|
+
interface StreamLike {
|
|
33
|
+
on: Function;
|
|
34
|
+
pause: Function;
|
|
35
|
+
resume: Function;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function isStream(obj: unknown): obj is StreamLike {
|
|
39
|
+
if (!obj || typeof obj !== 'object') return false;
|
|
40
|
+
const streamLike = obj as StreamLike;
|
|
41
|
+
return typeof streamLike.on === "function" &&
|
|
42
|
+
typeof streamLike.pause === "function" &&
|
|
43
|
+
typeof streamLike.resume === "function";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Return the type of the input.
|
|
47
|
+
// The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer.
|
|
48
|
+
// If the type is not supported, throw an exception.
|
|
49
|
+
export function getTypeOf(input: string|Buffer|Blob|Array<any>|ArrayBuffer|Uint8Array): string {
|
|
50
|
+
if (typeof input === "string") {
|
|
51
|
+
if (!Support.string)
|
|
52
|
+
throw new Error(Errors.DATATYPE_STRING_UNSUPPORTED);
|
|
53
|
+
return DATATYPE.STRING;
|
|
54
|
+
}
|
|
55
|
+
else if (Object.prototype.toString.call(input) === "[object Array]") {
|
|
56
|
+
if (!Support.array)
|
|
57
|
+
throw new Error(Errors.DATATYPE_ARRAY_UNSUPPORTED);
|
|
58
|
+
return DATATYPE.ARRAY;
|
|
59
|
+
}
|
|
60
|
+
else if (Buffer.isBuffer(input)) {
|
|
61
|
+
if (!Support.buffer)
|
|
62
|
+
throw new Error(Errors.DATATYPE_BUFFER_UNSUPPORTED);
|
|
63
|
+
return DATATYPE.BUFFER;
|
|
64
|
+
} else if (input instanceof Blob) {
|
|
65
|
+
if (!Support.blob)
|
|
66
|
+
throw new Error(Errors.DATATYPE_BLOB_UNSUPPORTED);
|
|
67
|
+
return DATATYPE.BLOB;
|
|
68
|
+
} else if (input instanceof Uint8Array) {
|
|
69
|
+
if (!Support.uint8array)
|
|
70
|
+
throw new Error(Errors.DATATYPE_U8ARRAY_UNSUPPORTED);
|
|
71
|
+
return DATATYPE.U8ARRAY;
|
|
72
|
+
}
|
|
73
|
+
else if (input instanceof ArrayBuffer) {
|
|
74
|
+
if (!Support.arrayBuffer)
|
|
75
|
+
throw new Error(Errors.DATATYPE_ARRAYBUFFER_UNSUPPORTED);
|
|
76
|
+
return DATATYPE.ARRAYBUFFER;
|
|
77
|
+
} else { // Add an else block to handle unsupported types
|
|
78
|
+
throw new Error(Errors.DATATYPE_UNSUPPORTED);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if a filename is a metadata file
|
|
84
|
+
* @param filename The filename to check
|
|
85
|
+
* @returns True if the file is a metadata file (META-INF)
|
|
86
|
+
*/
|
|
87
|
+
export const isMetadataFile = (filename: string): boolean => {
|
|
88
|
+
return filename === TIMESTAMP_SUBMITTED ||
|
|
89
|
+
filename === TIMESTAMP_METADATA ||
|
|
90
|
+
filename === TOKENIZED_METADATA;
|
|
91
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// ======================================
|
|
2
|
+
// Errors.ts
|
|
3
|
+
// Copyright (c) 2024 NeoWare, Inc. All rights reserved.
|
|
4
|
+
// ======================================
|
|
5
|
+
// Error messages
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
/* Header error messages */
|
|
9
|
+
INVALID_LOC: "Invalid LOC header (bad signature)",
|
|
10
|
+
INVALID_CEN: "Invalid CEN header (bad signature)",
|
|
11
|
+
INVALID_END: "Invalid END header (bad signature)",
|
|
12
|
+
|
|
13
|
+
/* ZipEntry error messages*/
|
|
14
|
+
NO_DATA: "Nothing to decompress",
|
|
15
|
+
FILE_IN_THE_WAY: "There is a file in the way: %s",
|
|
16
|
+
UNKNOWN_METHOD: "Invalid/unsupported compression method",
|
|
17
|
+
|
|
18
|
+
/* Encryption Errors */
|
|
19
|
+
STRONG_ENCRYPT_UNSUPPORTED: "Strong Encryption is not supported",
|
|
20
|
+
|
|
21
|
+
/* Timestamp error messages */
|
|
22
|
+
INVALID_TIMESTAMP: "Invalid timestamp",
|
|
23
|
+
TIMESTAMP_FAILED: "Failed to create the timestamp",
|
|
24
|
+
|
|
25
|
+
/* Inflater error messages */
|
|
26
|
+
AVAIL_DATA: "inflate::Available inflate data did not terminate",
|
|
27
|
+
INVALID_DISTANCE: "inflate::Invalid literal/length or distance code in fixed or dynamic block",
|
|
28
|
+
TO_MANY_CODES: "inflate::Dynamic block code description: too many length or distance codes",
|
|
29
|
+
INVALID_REPEAT_LEN: "inflate::Dynamic block code description: repeat more than specified lengths",
|
|
30
|
+
INVALID_REPEAT_FIRST: "inflate::Dynamic block code description: repeat lengths with no first length",
|
|
31
|
+
INCOMPLETE_CODES: "inflate::Dynamic block code description: code lengths codes incomplete",
|
|
32
|
+
INVALID_DYN_DISTANCE: "inflate::Dynamic block code description: invalid distance code lengths",
|
|
33
|
+
INVALID_CODES_LEN: "inflate::Dynamic block code description: invalid literal/length code lengths",
|
|
34
|
+
INVALID_STORE_BLOCK: "inflate::Stored block length did not match one's complement",
|
|
35
|
+
INVALID_BLOCK_TYPE: "inflate::Invalid block type (type == 3)",
|
|
36
|
+
|
|
37
|
+
/* Extract error messages */
|
|
38
|
+
INVALID_CMP_DATA_LENGTH: "Compressed data length does not match the expected length",
|
|
39
|
+
EXTRACT_FAILED: "Failed to extract file",
|
|
40
|
+
INVALID_CRC: "CRC32 checksum does not match the expected value",
|
|
41
|
+
UNKNOWN_SHA256: "The SHA-256 hash has not been saved",
|
|
42
|
+
INVALID_SHA256: "The SHA-256 hash does not match the expected value",
|
|
43
|
+
|
|
44
|
+
/* NEO-ZIP error messages */
|
|
45
|
+
CANT_EXTRACT_FILE: "Could not extract the file",
|
|
46
|
+
CANT_OVERRIDE: "Target file already exists",
|
|
47
|
+
NO_ZIP: "No zip file was loaded",
|
|
48
|
+
NO_ENTRY: "Entry doesn't exist",
|
|
49
|
+
DIRECTORY_CONTENT_ERROR: "A directory cannot have content",
|
|
50
|
+
FILE_NOT_FOUND: "File not found: %s",
|
|
51
|
+
NOT_IMPLEMENTED: "Not implemented",
|
|
52
|
+
INVALID_FILENAME: "Invalid filename",
|
|
53
|
+
INVALID_FORMAT: "Invalid or unsupported zip format. No END header found",
|
|
54
|
+
|
|
55
|
+
// NeoZipKit error messages
|
|
56
|
+
NO_STREAM_SUPPORT: "Streams are not supported in this environment",
|
|
57
|
+
NO_BLOB_SUPPORT: "Blobs are not supported in this environment",
|
|
58
|
+
NO_FILE_READER_SUPPORT: "FileReader is not supported in this environment",
|
|
59
|
+
|
|
60
|
+
// Create Zip error messages
|
|
61
|
+
NO_FILES: "No files added, Zip file not created",
|
|
62
|
+
|
|
63
|
+
DATATYPE_STRING_UNSUPPORTED: "The String type is not supported by this platform.",
|
|
64
|
+
DATATYPE_ARRAY_UNSUPPORTED: "The Array type is not supported by this platform.",
|
|
65
|
+
DATATYPE_BUFFER_UNSUPPORTED: "The Buffer type is not supported by this platform.",
|
|
66
|
+
DATATYPE_BLOB_UNSUPPORTED: "The Blob type is not supported by this platform.",
|
|
67
|
+
DATATYPE_U8ARRAY_UNSUPPORTED: "The uint8Array type is not supported by this platform.",
|
|
68
|
+
DATATYPE_ARRAYBUFFER_UNSUPPORTED: "The ArrayBuffer type is not supported by this platform.",
|
|
69
|
+
DATATYPE_UNSUPPORTED: "Unsupported input type.",
|
|
70
|
+
|
|
71
|
+
COMPRESS_FAILED: 'Failed to compress data',
|
|
72
|
+
COMPRESSION_ERROR: 'Error occurred during compression',
|
|
73
|
+
DECOMPRESSION_ERROR: 'Error occurred during decompression',
|
|
74
|
+
|
|
75
|
+
ENCRYPT_FAILED: 'Encryption failed',
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
|