@datatruck/cli 0.36.5 → 0.36.6
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/lib/utils/crypto.d.ts +1 -0
- package/lib/utils/crypto.js +7 -1
- package/lib/utils/datatruck/client.d.ts +7 -6
- package/lib/utils/datatruck/client.js +18 -15
- package/lib/utils/datatruck/repository-server.js +4 -15
- package/lib/utils/http.d.ts +16 -20
- package/lib/utils/http.js +131 -124
- package/package.json +1 -1
package/lib/utils/crypto.d.ts
CHANGED
package/lib/utils/crypto.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calcFileHash = void 0;
|
|
3
|
+
exports.assertFileChecksum = exports.calcFileHash = void 0;
|
|
4
4
|
const crypto_1 = require("crypto");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
function calcFileHash(path, algorithm) {
|
|
@@ -13,3 +13,9 @@ function calcFileHash(path, algorithm) {
|
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
15
|
exports.calcFileHash = calcFileHash;
|
|
16
|
+
async function assertFileChecksum(path, checksum, algorithm) {
|
|
17
|
+
const fileChecksum = await calcFileHash(path, algorithm);
|
|
18
|
+
if (fileChecksum !== checksum)
|
|
19
|
+
throw new Error(`Invalid checksum file: ${checksum} != ${fileChecksum}`);
|
|
20
|
+
}
|
|
21
|
+
exports.assertFileChecksum = assertFileChecksum;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { DiskStats } from "../fs";
|
|
2
3
|
import { BasicProgress } from "../progress";
|
|
3
4
|
import { AbstractFs, FsOptions } from "../virtual-fs";
|
|
@@ -12,12 +13,12 @@ export declare class RemoteFs extends AbstractFs {
|
|
|
12
13
|
});
|
|
13
14
|
isLocal(): boolean;
|
|
14
15
|
protected fetchJson(name: string, params: any[]): Promise<any>;
|
|
15
|
-
protected post(name: string, params: any[], data: string): Promise<
|
|
16
|
-
existsDir(path: string): Promise<
|
|
17
|
-
rename(source: string, target: string): Promise<
|
|
18
|
-
mkdir(path: string): Promise<
|
|
19
|
-
readFile(path: string): Promise<
|
|
20
|
-
readdir(path: string): Promise<
|
|
16
|
+
protected post(name: string, params: any[], data: string): Promise<Response>;
|
|
17
|
+
existsDir(path: string): Promise<boolean>;
|
|
18
|
+
rename(source: string, target: string): Promise<void>;
|
|
19
|
+
mkdir(path: string): Promise<void>;
|
|
20
|
+
readFile(path: string): Promise<string>;
|
|
21
|
+
readdir(path: string): Promise<string[]>;
|
|
21
22
|
readFileIfExists(path: string): Promise<string | undefined>;
|
|
22
23
|
ensureEmptyDir(path: string): Promise<void>;
|
|
23
24
|
writeFile(path: string, contents: string): Promise<void>;
|
|
@@ -27,19 +27,19 @@ class RemoteFs extends virtual_fs_1.AbstractFs {
|
|
|
27
27
|
return false;
|
|
28
28
|
}
|
|
29
29
|
async fetchJson(name, params) {
|
|
30
|
-
|
|
30
|
+
const url = (0, http_1.createHref)(`${this.url}/${name}`, {
|
|
31
|
+
params: JSON.stringify(params),
|
|
32
|
+
});
|
|
33
|
+
return await (0, http_1.fetchJson)(url, {
|
|
31
34
|
headers: this.headers,
|
|
32
|
-
query: {
|
|
33
|
-
params: JSON.stringify(params),
|
|
34
|
-
},
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
async post(name, params, data) {
|
|
38
|
-
|
|
38
|
+
const url = (0, http_1.createHref)(`${this.url}/${name}`, {
|
|
39
|
+
params: JSON.stringify(params),
|
|
40
|
+
});
|
|
41
|
+
return await (0, http_1.post)(url, data, {
|
|
39
42
|
headers: this.headers,
|
|
40
|
-
query: {
|
|
41
|
-
params: JSON.stringify(params),
|
|
42
|
-
},
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
async existsDir(path) {
|
|
@@ -67,7 +67,7 @@ class RemoteFs extends virtual_fs_1.AbstractFs {
|
|
|
67
67
|
await this.post("writeFile", [path], contents);
|
|
68
68
|
}
|
|
69
69
|
async rmAll(path) {
|
|
70
|
-
await this.fetchJson("rmAll", [path]);
|
|
70
|
+
return await this.fetchJson("rmAll", [path]);
|
|
71
71
|
}
|
|
72
72
|
async fetchDiskStats(path) {
|
|
73
73
|
if (this.options.verbose)
|
|
@@ -77,20 +77,23 @@ class RemoteFs extends virtual_fs_1.AbstractFs {
|
|
|
77
77
|
async upload(source, target) {
|
|
78
78
|
if (this.options.verbose)
|
|
79
79
|
(0, cli_1.logExec)("fs.upload", [source, target]);
|
|
80
|
-
|
|
80
|
+
const url = (0, http_1.createHref)(`${this.url}/upload`, {
|
|
81
|
+
params: JSON.stringify([target]),
|
|
82
|
+
});
|
|
83
|
+
return await (0, http_1.uploadFile)(url, source, {
|
|
81
84
|
headers: this.headers,
|
|
82
|
-
|
|
83
|
-
params: JSON.stringify([target]),
|
|
84
|
-
},
|
|
85
|
+
checksum: true,
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
88
|
async download(source, target, options = {}) {
|
|
88
89
|
if (this.options.verbose)
|
|
89
90
|
(0, cli_1.logExec)("fs.download", [source, target]);
|
|
90
|
-
|
|
91
|
+
const url = (0, http_1.createHref)(`${this.url}/download`, {
|
|
92
|
+
params: JSON.stringify([source]),
|
|
93
|
+
});
|
|
94
|
+
return await (0, http_1.downloadFile)(url, target, {
|
|
91
95
|
...options,
|
|
92
96
|
headers: this.headers,
|
|
93
|
-
query: { params: JSON.stringify([source]) },
|
|
94
97
|
});
|
|
95
98
|
}
|
|
96
99
|
}
|
|
@@ -6,10 +6,7 @@ const cli_1 = require("../cli");
|
|
|
6
6
|
const http_1 = require("../http");
|
|
7
7
|
const math_1 = require("../math");
|
|
8
8
|
const virtual_fs_1 = require("../virtual-fs");
|
|
9
|
-
const fs_1 = require("fs");
|
|
10
|
-
const promises_1 = require("fs/promises");
|
|
11
9
|
const http_2 = require("http");
|
|
12
|
-
const promises_2 = require("stream/promises");
|
|
13
10
|
exports.headerKey = {
|
|
14
11
|
user: "x-dtt-user",
|
|
15
12
|
password: "x-dtt-password",
|
|
@@ -91,16 +88,12 @@ function createDatatruckRepositoryServer(inOptions, config = {}) {
|
|
|
91
88
|
else if (action === "upload") {
|
|
92
89
|
const [target] = params;
|
|
93
90
|
const path = fs.resolvePath(target);
|
|
94
|
-
|
|
95
|
-
await (0, promises_2.pipeline)(req, file);
|
|
91
|
+
await (0, http_1.recvFile)(req, res, path);
|
|
96
92
|
}
|
|
97
93
|
else if (action === "download") {
|
|
98
94
|
const [target] = params;
|
|
99
95
|
const path = fs.resolvePath(target);
|
|
100
|
-
|
|
101
|
-
const fileStat = await (0, promises_1.stat)(path);
|
|
102
|
-
res.setHeader("Content-Length", fileStat.size);
|
|
103
|
-
await (0, promises_2.pipeline)(file, res, { end: false });
|
|
96
|
+
await (0, http_1.sendFile)(req, res, path);
|
|
104
97
|
}
|
|
105
98
|
else if (action === "writeFile") {
|
|
106
99
|
const data = await (0, http_1.readRequestData)(req);
|
|
@@ -123,7 +116,7 @@ function createDatatruckRepositoryServer(inOptions, config = {}) {
|
|
|
123
116
|
(0, cli_1.logJson)("repository-server", "request failed", { id });
|
|
124
117
|
console.error(error);
|
|
125
118
|
}
|
|
126
|
-
if (!res.headersSent)
|
|
119
|
+
if (!res.writableEnded && !res.headersSent)
|
|
127
120
|
res.writeHead(500, error.message);
|
|
128
121
|
}
|
|
129
122
|
finally {
|
|
@@ -135,12 +128,8 @@ function createDatatruckRepositoryServer(inOptions, config = {}) {
|
|
|
135
128
|
(0, cli_1.logJson)("repository-server", "response error", { id });
|
|
136
129
|
console.error(responseError);
|
|
137
130
|
}
|
|
138
|
-
if (
|
|
139
|
-
res.destroy();
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
131
|
+
if (!res.writableEnded)
|
|
142
132
|
res.end();
|
|
143
|
-
}
|
|
144
133
|
}
|
|
145
134
|
});
|
|
146
135
|
}
|
package/lib/utils/http.d.ts
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { BasicProgress } from "./progress";
|
|
3
|
-
import { IncomingMessage, Server } from "http";
|
|
4
|
+
import { IncomingMessage, Server, ServerResponse } from "http";
|
|
5
|
+
export declare function createHref(inUrl: string, query?: Record<string, string>): string;
|
|
4
6
|
export declare function closeServer(server: Server): Promise<void>;
|
|
5
7
|
export declare function readRequestData(req: IncomingMessage): Promise<string | undefined>;
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export declare function post(url: string, data: string, options?: {
|
|
17
|
-
headers?: Record<string, string>;
|
|
18
|
-
query?: Record<string, string>;
|
|
8
|
+
export declare const safeFetch: typeof fetch;
|
|
9
|
+
export declare function fetchJson<T = any>(url: string, options?: RequestInit): Promise<T | undefined>;
|
|
10
|
+
export declare function post(url: string, data: string, options?: Omit<RequestInit, "method" | "body">): Promise<Response>;
|
|
11
|
+
export declare function parseContentLength(value: string | undefined): number;
|
|
12
|
+
export declare function sendFile(req: IncomingMessage, res: ServerResponse, path: string, options?: {
|
|
13
|
+
end?: boolean;
|
|
14
|
+
checksum?: boolean;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
export declare function recvFile(req: IncomingMessage, res: ServerResponse, path: string, options?: {
|
|
17
|
+
end?: boolean;
|
|
19
18
|
}): Promise<void>;
|
|
20
|
-
export declare function downloadFile(url: string, output: string, options?: {
|
|
21
|
-
headers?: Record<string, string>;
|
|
22
|
-
query?: Record<string, string>;
|
|
19
|
+
export declare function downloadFile(url: string, output: string, options?: Omit<RequestInit, "signal"> & {
|
|
23
20
|
timeout?: number;
|
|
24
21
|
onProgress?: (progress: BasicProgress) => void;
|
|
25
22
|
}): Promise<{
|
|
26
23
|
bytes: number;
|
|
27
24
|
}>;
|
|
28
|
-
export declare function uploadFile(url: string, path: string, options?: {
|
|
29
|
-
|
|
30
|
-
query?: Record<string, string>;
|
|
25
|
+
export declare function uploadFile(url: string, path: string, options?: Omit<RequestInit, "method" | "body"> & {
|
|
26
|
+
checksum?: boolean;
|
|
31
27
|
}): Promise<void>;
|
package/lib/utils/http.js
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.uploadFile = exports.downloadFile = exports.post = exports.fetchJson = exports.
|
|
3
|
+
exports.uploadFile = exports.downloadFile = exports.recvFile = exports.sendFile = exports.parseContentLength = exports.post = exports.fetchJson = exports.safeFetch = exports.readRequestData = exports.closeServer = exports.createHref = void 0;
|
|
4
|
+
const crypto_1 = require("./crypto");
|
|
4
5
|
const math_1 = require("./math");
|
|
5
6
|
const fs_1 = require("fs");
|
|
6
7
|
const promises_1 = require("fs/promises");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
return url.startsWith("https://")
|
|
11
|
-
? (0, https_1.request)(url, options, callback)
|
|
12
|
-
: (0, http_1.request)(url, options, callback);
|
|
13
|
-
};
|
|
14
|
-
function href(inUrl, query) {
|
|
8
|
+
const stream_1 = require("stream");
|
|
9
|
+
const promises_2 = require("stream/promises");
|
|
10
|
+
function createHref(inUrl, query) {
|
|
15
11
|
const url = new URL(inUrl);
|
|
16
12
|
for (const key in query || {})
|
|
17
13
|
url.searchParams.set(key, query[key]);
|
|
18
14
|
return url.href;
|
|
19
15
|
}
|
|
16
|
+
exports.createHref = createHref;
|
|
20
17
|
async function closeServer(server) {
|
|
21
18
|
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
|
|
22
19
|
}
|
|
@@ -37,140 +34,150 @@ function readRequestData(req) {
|
|
|
37
34
|
});
|
|
38
35
|
}
|
|
39
36
|
exports.readRequestData = readRequestData;
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}, (res) => {
|
|
48
|
-
if (throwStatusCodeError && res.statusCode !== 200)
|
|
49
|
-
return reject(new Error(`GET failed: ${res.statusCode} ${res.statusMessage}`));
|
|
50
|
-
res
|
|
51
|
-
.on("data", (chunk) => {
|
|
52
|
-
if (data === undefined)
|
|
53
|
-
data = "";
|
|
54
|
-
data += chunk;
|
|
55
|
-
})
|
|
56
|
-
.on("error", reject)
|
|
57
|
-
.on("close", () => {
|
|
58
|
-
resolve({ data, status: res.statusCode });
|
|
59
|
-
});
|
|
60
|
-
})
|
|
61
|
-
.on("error", reject)
|
|
62
|
-
.end();
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
exports.fetch = fetch;
|
|
37
|
+
const safeFetch = async (...args) => {
|
|
38
|
+
const res = await fetch(...args);
|
|
39
|
+
if (res.status !== 200)
|
|
40
|
+
throw new Error(`Fetch request failed: ${res.status} ${res.statusText}`);
|
|
41
|
+
return res;
|
|
42
|
+
};
|
|
43
|
+
exports.safeFetch = safeFetch;
|
|
66
44
|
async function fetchJson(url, options = {}) {
|
|
67
|
-
const res = await
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
return JSON.parse(res.data);
|
|
45
|
+
const res = await (0, exports.safeFetch)(url, options);
|
|
46
|
+
const data = await res.text();
|
|
47
|
+
return data.length ? JSON.parse(data) : undefined;
|
|
71
48
|
}
|
|
72
49
|
exports.fetchJson = fetchJson;
|
|
73
50
|
async function post(url, data, options = {}) {
|
|
74
|
-
await
|
|
75
|
-
|
|
51
|
+
return await (0, exports.safeFetch)(url, { ...options, method: "POST", body: data });
|
|
52
|
+
}
|
|
53
|
+
exports.post = post;
|
|
54
|
+
function parseContentLength(value) {
|
|
55
|
+
if (!value || !/^\d+$/.test(value))
|
|
56
|
+
throw new Error(`Invalid 'content-length': ${value}`);
|
|
57
|
+
return Number(value);
|
|
58
|
+
}
|
|
59
|
+
exports.parseContentLength = parseContentLength;
|
|
60
|
+
async function sendFile(req, res, path, options = {}) {
|
|
61
|
+
let file;
|
|
62
|
+
try {
|
|
63
|
+
file = (0, fs_1.createReadStream)(path);
|
|
64
|
+
const fileStat = await (0, promises_1.stat)(path);
|
|
65
|
+
res.setHeader("Content-Length", fileStat.size);
|
|
66
|
+
if (options.checksum)
|
|
67
|
+
res.setHeader("x-checksum", await (0, crypto_1.calcFileHash)(path, "sha1"));
|
|
68
|
+
file.pipe(res);
|
|
69
|
+
await new Promise((resolve, reject) => {
|
|
70
|
+
file.on("error", reject);
|
|
71
|
+
req.on("error", reject);
|
|
72
|
+
res.on("error", reject).on("close", resolve);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
file?.close();
|
|
77
|
+
if (options.end)
|
|
78
|
+
res.end();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
exports.sendFile = sendFile;
|
|
82
|
+
async function recvFile(req, res, path, options = {}) {
|
|
83
|
+
let file;
|
|
84
|
+
try {
|
|
85
|
+
file = (0, fs_1.createWriteStream)(path);
|
|
86
|
+
req.pipe(file);
|
|
87
|
+
await new Promise((resolve, reject) => {
|
|
88
|
+
file.on("error", reject).on("close", resolve);
|
|
89
|
+
req.on("error", reject);
|
|
76
90
|
res.on("error", reject);
|
|
77
|
-
if (res.statusCode !== 200) {
|
|
78
|
-
reject(new Error(`Post failed: ${res.statusCode} ${res.statusMessage}`));
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
resolve();
|
|
82
|
-
}
|
|
83
91
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
92
|
+
const checksum = res.getHeader("x-checksum");
|
|
93
|
+
if (typeof checksum === "string")
|
|
94
|
+
await (0, crypto_1.assertFileChecksum)(path, checksum, "sha1");
|
|
95
|
+
}
|
|
96
|
+
finally {
|
|
97
|
+
file?.close();
|
|
98
|
+
if (options.end)
|
|
99
|
+
res.end();
|
|
100
|
+
}
|
|
88
101
|
}
|
|
89
|
-
exports.
|
|
102
|
+
exports.recvFile = recvFile;
|
|
90
103
|
async function downloadFile(url, output, options = {}) {
|
|
91
|
-
const timeout
|
|
104
|
+
const { timeout, onProgress, ...fetchOptions } = options;
|
|
92
105
|
const file = (0, fs_1.createWriteStream)(output);
|
|
93
|
-
let
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
percent: (0, math_1.progressPercent)(total, current),
|
|
109
|
-
current,
|
|
110
|
-
total,
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
res
|
|
115
|
-
.on("error", async (error) => {
|
|
106
|
+
let checksum;
|
|
107
|
+
const length = { total: 0, current: 0 };
|
|
108
|
+
let requestError;
|
|
109
|
+
try {
|
|
110
|
+
const res = await (0, exports.safeFetch)(url, {
|
|
111
|
+
...fetchOptions,
|
|
112
|
+
signal: AbortSignal.timeout(timeout ?? 3600 * 1000), // 60m
|
|
113
|
+
});
|
|
114
|
+
length.total = parseContentLength(res.headers.get("content-length") ?? undefined);
|
|
115
|
+
checksum = res.headers.get("x-checksum") ?? undefined;
|
|
116
|
+
const body = stream_1.Readable.fromWeb(res.body);
|
|
117
|
+
const progress = onProgress &&
|
|
118
|
+
new stream_1.Transform({
|
|
119
|
+
transform(chunk, encoding, callback) {
|
|
120
|
+
let error;
|
|
116
121
|
try {
|
|
117
|
-
|
|
122
|
+
length.current += chunk.byteLength;
|
|
123
|
+
onProgress({
|
|
124
|
+
percent: (0, math_1.progressPercent)(length.total, length.current),
|
|
125
|
+
current: length.current,
|
|
126
|
+
total: length.total,
|
|
127
|
+
});
|
|
118
128
|
}
|
|
119
|
-
catch (
|
|
120
|
-
|
|
121
|
-
await (0, promises_1.unlink)(output);
|
|
129
|
+
catch (progressError) {
|
|
130
|
+
error = progressError;
|
|
122
131
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
});
|
|
149
|
-
const { size: bytes } = await (0, promises_1.stat)(output);
|
|
150
|
-
if (total !== bytes)
|
|
151
|
-
throw new Error(`Invalid download size: ${total} != ${bytes}`);
|
|
152
|
-
return { bytes };
|
|
132
|
+
callback(error, chunk);
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
if (progress) {
|
|
136
|
+
await (0, promises_2.pipeline)(body, progress, file);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
await (0, promises_2.pipeline)(body, file);
|
|
140
|
+
}
|
|
141
|
+
const { size: fileLength } = await (0, promises_1.stat)(output);
|
|
142
|
+
if (length.total !== fileLength)
|
|
143
|
+
throw new Error(`Invalid download size: ${length.total} != ${fileLength}`);
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
try {
|
|
147
|
+
await (0, promises_1.unlink)(output);
|
|
148
|
+
}
|
|
149
|
+
catch (_) { }
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
if (checksum)
|
|
153
|
+
await (0, crypto_1.assertFileChecksum)(output, checksum, "sha1");
|
|
154
|
+
if (requestError)
|
|
155
|
+
throw requestError;
|
|
156
|
+
return { bytes: length.total };
|
|
153
157
|
}
|
|
154
158
|
exports.downloadFile = downloadFile;
|
|
155
159
|
async function uploadFile(url, path, options = {}) {
|
|
156
160
|
const { size } = await (0, promises_1.stat)(path);
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
const
|
|
161
|
+
const file = (0, fs_1.createReadStream)(path);
|
|
162
|
+
try {
|
|
163
|
+
const res = await fetch(url, {
|
|
164
|
+
...options,
|
|
160
165
|
method: "POST",
|
|
166
|
+
duplex: "half",
|
|
161
167
|
headers: {
|
|
162
168
|
...options.headers,
|
|
163
|
-
"Content-
|
|
169
|
+
"Content-Length": size.toString(),
|
|
170
|
+
...(options.checksum && {
|
|
171
|
+
"x-checksum": await (0, crypto_1.calcFileHash)(path, "sha1"),
|
|
172
|
+
}),
|
|
164
173
|
},
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
readStream.on("error", reject).pipe(req);
|
|
174
|
-
});
|
|
174
|
+
body: file,
|
|
175
|
+
});
|
|
176
|
+
if (res.status !== 200)
|
|
177
|
+
new Error(`Upload failed: ${res.status} ${res.statusText}`);
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
file.close();
|
|
181
|
+
}
|
|
175
182
|
}
|
|
176
183
|
exports.uploadFile = uploadFile;
|