ecus-cli
Version:
A Command line interface of ECUS
183 lines (182 loc) • 7.67 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.chunkUploadFile = exports.uploadWithProgress = void 0;
const got_1 = __importDefault(require("got"));
const cli_progress_1 = __importDefault(require("cli-progress"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
function uploadWithProgress(url, requestOptions) {
return __awaiter(this, void 0, void 0, function* () {
const res = got_1.default.stream.put(url, requestOptions);
const uploadBar = new cli_progress_1.default.SingleBar({}, cli_progress_1.default.Presets.shades_classic);
uploadBar.start(100, 0);
const stopProgress = () => {
uploadBar.stop();
};
res.on("uploadProgress", (progress) => {
if (progress.total) {
uploadBar.setTotal(progress.total);
uploadBar.update(progress.transferred);
}
else {
uploadBar.setTotal(100);
uploadBar.update(progress.percent);
}
if (progress.percent >= 100) {
stopProgress();
}
});
const chunks = [];
res.on("data", (chunk) => chunks.push(chunk));
return new Promise((resolve, reject) => {
res.on("end", () => {
stopProgress();
resolve(Buffer.concat(chunks).toString("utf-8"));
});
res.on("error", (err) => {
reject(err);
});
});
});
}
exports.uploadWithProgress = uploadWithProgress;
/**
* Chunk upload file
* @param baseUrl API base URL
* @param filePath File path
* @param authHeaders Authentication headers
* @param projectId Project ID
* @returns Upload result
*/
function chunkUploadFile(baseUrl, filePath, authHeaders, projectId, updateData) {
return __awaiter(this, void 0, void 0, function* () {
const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB chunk size
const uploadId = Date.now().toString(); // Generate upload ID
const fileName = path_1.default.basename(filePath);
const fileSize = fs_1.default.statSync(filePath).size;
const totalChunks = Math.ceil(fileSize / CHUNK_SIZE);
const uploadBar = new cli_progress_1.default.SingleBar({
format: "Uploading [{bar}] {percentage}% | {value}/{total} Chunks | {status}",
}, cli_progress_1.default.Presets.shades_classic);
uploadBar.start(totalChunks, 0, { status: "Starting..." });
try {
for (let i = 0; i < totalChunks; i++) {
uploadBar.update(i, {
status: `Uploading chunk ${i + 1}/${totalChunks}`,
});
const chunkBuffer = yield readFileChunk(filePath, i * CHUNK_SIZE, CHUNK_SIZE);
const result = yield uploadChunk(baseUrl, chunkBuffer, uploadId, i, totalChunks, authHeaders, projectId);
if (!result.success) {
throw new Error(`Chunk upload failed: ${result.error}`);
}
}
// All chunks uploaded, assemble file
uploadBar.update(totalChunks, { status: "Assembling file..." });
const assembleResult = yield assembleChunks(baseUrl, uploadId, fileName, authHeaders, projectId, updateData);
uploadBar.stop();
return assembleResult;
}
catch (error) {
uploadBar.stop();
console.error("Upload error:", error);
yield cleanupChunks(baseUrl, uploadId, authHeaders, projectId);
throw error;
}
});
}
exports.chunkUploadFile = chunkUploadFile;
/**
* Read a specific chunk of a file
*/
function readFileChunk(filePath, start, chunkSize) {
return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const fileHandle = fs_1.default.openSync(filePath, "r");
const buffer = Buffer.alloc(chunkSize);
fs_1.default.read(fileHandle, buffer, 0, chunkSize, start, (err, bytesRead) => {
fs_1.default.closeSync(fileHandle);
if (err) {
reject(err);
return;
}
// If the number of bytes read is less than chunkSize, it means the end of the file has been reached, trim the buffer
resolve(bytesRead < chunkSize ? buffer.slice(0, bytesRead) : buffer);
});
});
});
}
/**
* Upload a single chunk
*/
function uploadChunk(baseUrl, chunk, uploadId, chunkIndex, totalChunks, authHeaders, projectId) {
return __awaiter(this, void 0, void 0, function* () {
try {
const response = yield got_1.default.patch(`${baseUrl}/api/${projectId}/upload/chunked`, {
headers: Object.assign(Object.assign({}, authHeaders), { "upload-id": uploadId, "chunk-index": chunkIndex.toString(), "total-chunks": totalChunks.toString() }),
body: chunk,
});
return JSON.parse(response.body);
}
catch (error) {
if (error instanceof Error) {
console.error(`Failed to upload chunk ${chunkIndex}:`, error.message);
}
throw error;
}
});
}
/**
* Assemble uploaded chunks
*/
function assembleChunks(baseUrl, uploadId, filename, authHeaders, projectId, updateData) {
return __awaiter(this, void 0, void 0, function* () {
try {
const response = yield got_1.default.post(`${baseUrl}/api/${projectId}/upload/chunked/assemble`, {
headers: Object.assign(Object.assign({}, authHeaders), { "Content-Type": "application/json" }),
json: Object.assign({ uploadId,
filename }, updateData),
});
return JSON.parse(response.body);
}
catch (error) {
if (error instanceof Error) {
console.error("Failed to assemble chunks:", error.message);
}
throw error;
}
});
}
/**
* Clean up chunk files
*/
function cleanupChunks(baseUrl, uploadId, authHeaders, projectId) {
return __awaiter(this, void 0, void 0, function* () {
try {
const response = yield got_1.default.delete(`${baseUrl}/api/${projectId}/upload/chunked?uploadId=${uploadId}`, {
headers: authHeaders,
});
return JSON.parse(response.body);
}
catch (error) {
if (error instanceof Error) {
console.error("Failed to cleanup chunks:", error.message);
}
return {
success: false,
error: error instanceof Error ? error.message : "Unknown error",
};
}
});
}