bytifi 0.2.7 → 0.2.9
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/bin/bytifi.js +8 -0
- package/lib/crypto.js +6 -4
- package/lib/upload.js +6 -1
- package/package.json +1 -1
package/bin/bytifi.js
CHANGED
|
@@ -57,6 +57,7 @@ Options:
|
|
|
57
57
|
-q, --quiet Print only the share URL
|
|
58
58
|
--verbose Show API error details on stderr
|
|
59
59
|
--mime-type <type> Override detected MIME type
|
|
60
|
+
--compress Gzip-compress before encrypting (direct uploads only)
|
|
60
61
|
--concurrency <n> Parallel part workers, 1–16 (default: auto)
|
|
61
62
|
--base-url <url> API base URL (default: https://bytifi.com)
|
|
62
63
|
-h, --help Show this help
|
|
@@ -121,6 +122,7 @@ function parseUploadArgs(argv) {
|
|
|
121
122
|
quiet: false,
|
|
122
123
|
verbose: false,
|
|
123
124
|
mimeType: '',
|
|
125
|
+
compress: false,
|
|
124
126
|
concurrency: null,
|
|
125
127
|
baseUrl: 'https://bytifi.com',
|
|
126
128
|
help: false,
|
|
@@ -183,6 +185,11 @@ function parseUploadArgs(argv) {
|
|
|
183
185
|
continue
|
|
184
186
|
}
|
|
185
187
|
|
|
188
|
+
if (arg === '--compress') {
|
|
189
|
+
options.compress = true
|
|
190
|
+
continue
|
|
191
|
+
}
|
|
192
|
+
|
|
186
193
|
if (arg === '--concurrency') {
|
|
187
194
|
const raw = readFlagValue(argv, index, arg)
|
|
188
195
|
const concurrency = Number(raw)
|
|
@@ -426,6 +433,7 @@ async function runUpload(filePath, options) {
|
|
|
426
433
|
expiresInMinutes: options.expiresInMinutes,
|
|
427
434
|
deleteOnDownload: options.deleteOnDownload,
|
|
428
435
|
mimeType: options.mimeType || undefined,
|
|
436
|
+
compress: options.compress,
|
|
429
437
|
concurrency: options.concurrency ?? undefined,
|
|
430
438
|
signal: abort.signal,
|
|
431
439
|
onProgress: showProgress
|
package/lib/crypto.js
CHANGED
|
@@ -19,15 +19,15 @@ export function buildChunkIv(noncePrefix, chunkIndex) {
|
|
|
19
19
|
return iv
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
export function resolveCompressionMode(originalSize = 0) {
|
|
22
|
+
export function resolveCompressionMode(originalSize = 0, { compress = false } = {}) {
|
|
23
23
|
// Multipart uploads use fixed 32 MB encrypted parts on the server. Gzip can
|
|
24
24
|
// expand incompressible data (ISO, zip, etc.) past that limit and fail part
|
|
25
|
-
// validation, so only gzip-compress direct uploads.
|
|
25
|
+
// validation, so only gzip-compress direct uploads when explicitly requested.
|
|
26
26
|
if (originalSize > MULTIPART_THRESHOLD_BYTES) {
|
|
27
27
|
return 'none'
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
return 'gzip'
|
|
30
|
+
return compress ? 'gzip' : 'none'
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export function usesChunkCompression(meta) {
|
|
@@ -107,11 +107,12 @@ export function createEncryptionContext({
|
|
|
107
107
|
tokenBytes = crypto.randomBytes(32),
|
|
108
108
|
noncePrefix = crypto.randomBytes(8),
|
|
109
109
|
plainChunkSize = PLAIN_CHUNK_SIZE,
|
|
110
|
+
compress = false,
|
|
110
111
|
}) {
|
|
111
112
|
if (tokenBytes.length !== 32) throw new Error('Encryption token must be 32 bytes.')
|
|
112
113
|
if (noncePrefix.length !== 8) throw new Error('Nonce prefix must be 8 bytes.')
|
|
113
114
|
|
|
114
|
-
const compression = resolveCompressionMode(originalSize)
|
|
115
|
+
const compression = resolveCompressionMode(originalSize, { compress })
|
|
115
116
|
const { chunkCount, encryptedSize } = calculateEncryptedSize(originalSize, plainChunkSize)
|
|
116
117
|
const meta = buildClientEncryptionMeta({
|
|
117
118
|
plainChunkSize,
|
|
@@ -154,6 +155,7 @@ export async function resolveUploadFile(filePath, options = {}) {
|
|
|
154
155
|
originalSize: stat.size,
|
|
155
156
|
originalName,
|
|
156
157
|
mimeType,
|
|
158
|
+
compress: options.compress === true,
|
|
157
159
|
}),
|
|
158
160
|
}
|
|
159
161
|
}
|
package/lib/upload.js
CHANGED
|
@@ -91,10 +91,14 @@ async function uploadDirect(context, encryptedBuffer, {
|
|
|
91
91
|
}) {
|
|
92
92
|
const formData = new FormData()
|
|
93
93
|
const blob = new Blob([encryptedBuffer], { type: 'application/octet-stream' })
|
|
94
|
+
const clientEncryptionMeta = {
|
|
95
|
+
...context.meta,
|
|
96
|
+
encryptedSize: encryptedBuffer.length,
|
|
97
|
+
}
|
|
94
98
|
|
|
95
99
|
formData.append('file', blob, context.originalName)
|
|
96
100
|
formData.append('clientEncrypted', 'true')
|
|
97
|
-
formData.append('clientEncryptionMeta', JSON.stringify(
|
|
101
|
+
formData.append('clientEncryptionMeta', JSON.stringify(clientEncryptionMeta))
|
|
98
102
|
formData.append('deleteOnDownload', deleteOnDownload ? 'true' : 'false')
|
|
99
103
|
formData.append('expiresInMinutes', String(expiresInMinutes))
|
|
100
104
|
|
|
@@ -365,6 +369,7 @@ export async function uploadFile(filePath, options) {
|
|
|
365
369
|
|
|
366
370
|
const { absolutePath, context } = await resolveUploadFile(filePath, {
|
|
367
371
|
mimeType: options.mimeType,
|
|
372
|
+
compress: options.compress === true,
|
|
368
373
|
})
|
|
369
374
|
|
|
370
375
|
if (context.originalSize <= MULTIPART_THRESHOLD_BYTES) {
|