pinme 1.1.2 → 1.1.3-alpha.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.
Files changed (2) hide show
  1. package/dist/index.js +458 -650
  2. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -99,7 +99,7 @@ var require_main = __commonJS({
99
99
  var fs6 = require("fs");
100
100
  var path6 = require("path");
101
101
  var os3 = require("os");
102
- var crypto = require("crypto");
102
+ var crypto2 = require("crypto");
103
103
  var packageJson = require_package();
104
104
  var version2 = packageJson.version;
105
105
  var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
@@ -295,7 +295,7 @@ var require_main = __commonJS({
295
295
  const authTag = ciphertext.subarray(-16);
296
296
  ciphertext = ciphertext.subarray(12, -16);
297
297
  try {
298
- const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
298
+ const aesgcm = crypto2.createDecipheriv("aes-256-gcm", key, nonce);
299
299
  aesgcm.setAuthTag(authTag);
300
300
  return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
301
301
  } catch (error) {
@@ -1481,15 +1481,15 @@ var require_follow_redirects = __commonJS({
1481
1481
  // bin/index.ts
1482
1482
  var import_dotenv = __toESM(require_main());
1483
1483
  var import_commander = require("commander");
1484
- var import_chalk6 = __toESM(require("chalk"));
1484
+ var import_chalk5 = __toESM(require("chalk"));
1485
1485
  var import_figlet3 = __toESM(require("figlet"));
1486
1486
 
1487
1487
  // package.json
1488
- var version = "1.1.2";
1488
+ var version = "1.1.3-alpha.2";
1489
1489
 
1490
1490
  // bin/upload.ts
1491
1491
  var import_path5 = __toESM(require("path"));
1492
- var import_chalk3 = __toESM(require("chalk"));
1492
+ var import_chalk2 = __toESM(require("chalk"));
1493
1493
  var import_inquirer = __toESM(require("inquirer"));
1494
1494
  var import_figlet = __toESM(require("figlet"));
1495
1495
 
@@ -4360,12 +4360,12 @@ var {
4360
4360
  mergeConfig: mergeConfig2
4361
4361
  } = axios_default;
4362
4362
 
4363
- // bin/utils/uploadToIpfs.ts
4363
+ // bin/utils/uploadToIpfs2.ts
4364
4364
  var import_fs_extra3 = __toESM(require("fs-extra"));
4365
4365
  var import_path4 = __toESM(require("path"));
4366
4366
  var import_form_data2 = __toESM(require("form-data"));
4367
4367
  var import_ora = __toESM(require("ora"));
4368
- var import_chalk2 = __toESM(require("chalk"));
4368
+ var crypto = __toESM(require("crypto"));
4369
4369
 
4370
4370
  // bin/utils/uploadLimits.ts
4371
4371
  var import_fs = __toESM(require("fs"));
@@ -4520,653 +4520,458 @@ function getDeviceId() {
4520
4520
  return deviceId;
4521
4521
  }
4522
4522
 
4523
- // bin/utils/uploadToIpfs.ts
4524
- var ipfsApiUrl = "https://pinme.dev/api/v3";
4525
- var maxPollTime = parseInt(process.env.MAX_POLL_TIME_MINUTES || "5") * 60 * 1e3;
4526
- var pollInterval = parseInt(process.env.POLL_INTERVAL_SECONDS || "2") * 1e3;
4527
- var pollTimeout = parseInt(process.env.POLL_TIMEOUT_SECONDS || "10") * 1e3;
4528
- async function pollUploadStatus(traceId, deviceId, smartProgress, startTime) {
4529
- let consecutiveErrors = 0;
4530
- let stopProgressUpdates = false;
4531
- while (Date.now() - startTime < maxPollTime) {
4532
- try {
4533
- const response = await axios_default.get(
4534
- `${ipfsApiUrl}/up_status?trace_id=${traceId}&uid=${deviceId}`,
4535
- {
4536
- timeout: pollTimeout,
4537
- headers: {
4538
- "User-Agent": "Pinme-CLI/1.0.0",
4539
- Accept: "*/*",
4540
- Host: new URL(ipfsApiUrl).host,
4541
- Connection: "keep-alive"
4542
- }
4543
- }
4544
- );
4545
- const { code, msg, data } = response.data;
4546
- if (code === 200) {
4547
- consecutiveErrors = 0;
4548
- stopProgressUpdates = false;
4549
- if (data.is_ready) {
4550
- smartProgress.complete(traceId);
4551
- return data;
4552
- } else {
4553
- smartProgress.updateDisplay();
4554
- }
4555
- } else {
4556
- console.log(import_chalk2.default.yellow(`Warning: ${msg}`));
4557
- }
4558
- } catch (error) {
4559
- consecutiveErrors++;
4560
- console.log(import_chalk2.default.yellow(`Polling error: ${error.message}`));
4561
- if (stopProgressUpdates) {
4562
- smartProgress.updateTimeOnly();
4563
- }
4564
- }
4565
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
4523
+ // bin/utils/uploadToIpfs2.ts
4524
+ var IPFS_API_URL = "https://up.pinme.dev/api/v3";
4525
+ var MAX_RETRIES = parseInt(process.env.MAX_RETRIES || "2");
4526
+ var RETRY_DELAY = parseInt(process.env.RETRY_DELAY_MS || "1000");
4527
+ var TIMEOUT = parseInt(process.env.TIMEOUT_MS || "600000");
4528
+ var MAX_POLL_TIME = parseInt("5") * 60 * 1e3;
4529
+ var POLL_INTERVAL = parseInt(process.env.POLL_INTERVAL_SECONDS || "2") * 1e3;
4530
+ var PROGRESS_UPDATE_INTERVAL = 200;
4531
+ var EXPECTED_UPLOAD_TIME = 6e4;
4532
+ var MAX_PROGRESS = 0.95;
4533
+ var StepProgressBar = class {
4534
+ spinner;
4535
+ fileName;
4536
+ startTime;
4537
+ currentStep = 0;
4538
+ stepStartTime = 0;
4539
+ progressInterval = null;
4540
+ constructor(fileName, isDirectory = false) {
4541
+ this.fileName = fileName;
4542
+ this.spinner = (0, import_ora.default)(`Preparing to upload ${fileName}...`).start();
4543
+ this.startTime = Date.now();
4544
+ this.stepStartTime = Date.now();
4545
+ this.startProgress();
4566
4546
  }
4567
- const maxPollTimeMinutes = Math.floor(maxPollTime / (60 * 1e3));
4568
- smartProgress.fail(
4569
- `Upload timeout after ${maxPollTimeMinutes} minutes`,
4570
- traceId
4571
- );
4572
- return null;
4573
- }
4574
- function diagnoseDirectoryUploadError(directoryName, resData, expectedName) {
4575
- const issues = [];
4576
- if (directoryName.length > 100) {
4577
- issues.push(
4578
- `Directory name too long (${directoryName.length} characters, recommended under 100 characters)`
4579
- );
4547
+ startStep(stepIndex, stepName) {
4548
+ this.currentStep = stepIndex;
4549
+ this.stepStartTime = Date.now();
4580
4550
  }
4581
- const availableName = resData.Name;
4582
- issues.push(`Name returned by IPFS: ${availableName}`);
4583
- issues.push(`Expected directory name: ${expectedName}`);
4584
- const encodedName = encodeURIComponent(directoryName);
4585
- if (encodedName !== directoryName) {
4586
- issues.push(`Directory name after encoding: ${encodedName}`);
4551
+ updateProgress(progress, total) {
4587
4552
  }
4588
- return issues.join("\n - ");
4589
- }
4590
- function handleMultipartError(error, context) {
4591
- if (error.message && error.message.includes("multipart: NextPart: EOF")) {
4592
- return `Multipart form data error: ${context}. This usually indicates:
4593
- - Empty directory or no valid files
4594
- - File access permissions issue
4595
- - Network interruption during upload
4596
- - Server-side multipart parsing error`;
4597
- }
4598
- if (error.message && error.message.includes("ENOENT")) {
4599
- return `File not found error: ${context}. Please check:
4600
- - File path is correct
4601
- - File exists and is accessible
4602
- - No permission issues`;
4603
- }
4604
- if (error.message && error.message.includes("EACCES")) {
4605
- return `Permission denied error: ${context}. Please check:
4606
- - File read permissions
4607
- - Directory access permissions
4608
- - User has sufficient privileges`;
4609
- }
4610
- return `Upload error: ${error.message}`;
4611
- }
4612
- var ERROR_CODES = {
4613
- "30001": `File too large, single file max size: ${"500"}MB,single folder max size: ${"500"}MB`,
4614
- "30002": `Max storage quorum ${Number("1000") / 1e3} GB reached`
4615
- };
4616
- function loadFilesToArrRecursively(directoryPath, dist, basePath) {
4617
- const filesArr = [];
4618
- const sep = import_path4.default.sep;
4619
- if (!basePath) {
4620
- const parentDir = import_path4.default.dirname(directoryPath);
4621
- basePath = parentDir.endsWith(sep) ? parentDir : parentDir + sep;
4622
- }
4623
- if (import_fs_extra3.default.statSync(directoryPath).isDirectory()) {
4624
- const files = import_fs_extra3.default.readdirSync(directoryPath);
4625
- files.forEach((file) => {
4626
- const filePath = import_path4.default.join(directoryPath, file);
4627
- if (import_fs_extra3.default.statSync(filePath).isFile()) {
4628
- const sizeCheck = checkFileSizeLimit(filePath);
4629
- if (sizeCheck.exceeds) {
4630
- throw new Error(
4631
- `File ${file} exceeds size limit of ${formatSize(
4632
- sizeCheck.limit
4633
- )} (size: ${formatSize(sizeCheck.size)})`
4634
- );
4635
- }
4636
- const relativePath = filePath.replace(basePath, "");
4637
- const encodedPath = relativePath.replaceAll(sep, "%2F");
4638
- filesArr.push({
4639
- name: encodedPath,
4640
- path: filePath
4641
- });
4642
- } else if (import_fs_extra3.default.statSync(filePath).isDirectory()) {
4643
- const recursiveFiles = loadFilesToArrRecursively(
4644
- filePath,
4645
- dist,
4646
- basePath
4647
- );
4648
- filesArr.push(...recursiveFiles);
4649
- }
4650
- });
4651
- } else {
4652
- console.error("Error: path must be a directory");
4553
+ completeStep() {
4653
4554
  }
4654
- return filesArr;
4655
- }
4656
- function countFilesInDirectory(directoryPath) {
4657
- let count = 0;
4658
- const files = import_fs_extra3.default.readdirSync(directoryPath);
4659
- for (const file of files) {
4660
- const filePath = import_path4.default.join(directoryPath, file);
4661
- const stats = import_fs_extra3.default.statSync(filePath);
4662
- if (stats.isFile()) {
4663
- count++;
4664
- } else if (stats.isDirectory()) {
4665
- count += countFilesInDirectory(filePath);
4666
- }
4555
+ failStep(error) {
4556
+ this.stopProgress();
4557
+ this.spinner.fail(`Upload failed: ${error}`);
4667
4558
  }
4668
- return count;
4669
- }
4670
- async function uploadDirectory(directoryPath, deviceId) {
4671
- const sizeCheck = checkDirectorySizeLimit(directoryPath);
4672
- if (sizeCheck.exceeds) {
4673
- throw new Error(
4674
- `Directory ${directoryPath} exceeds size limit of ${formatSize(
4675
- sizeCheck.limit
4676
- )} (size: ${formatSize(sizeCheck.size)})`
4677
- );
4559
+ complete() {
4560
+ this.stopProgress();
4561
+ const totalTime = Math.floor((Date.now() - this.startTime) / 1e3);
4562
+ const progressBar = this.createProgressBar(1);
4563
+ this.spinner.succeed(`Upload completed ${progressBar} 100% (${totalTime}s)`);
4678
4564
  }
4679
- const formData = new import_form_data2.default();
4680
- if (directoryPath.endsWith(import_path4.default.sep))
4681
- directoryPath = directoryPath.slice(0, -1);
4682
- const dist = directoryPath.split(import_path4.default.sep).pop() || "";
4683
- const files = loadFilesToArrRecursively(directoryPath, dist);
4684
- const totalFiles = files.length;
4685
- if (totalFiles === 0) {
4686
- throw new Error(
4687
- `Directory ${directoryPath} is empty or contains no valid files`
4688
- );
4565
+ fail(error) {
4566
+ this.stopProgress();
4567
+ const totalTime = Math.floor((Date.now() - this.startTime) / 1e3);
4568
+ this.spinner.fail(`Upload failed: ${error} (${totalTime}s)`);
4689
4569
  }
4690
- files.forEach((file) => {
4691
- if (!import_fs_extra3.default.existsSync(file.path)) {
4692
- throw new Error(`File not found: ${file.path}`);
4693
- }
4694
- const fileStats = import_fs_extra3.default.statSync(file.path);
4695
- if (!fileStats.isFile()) {
4696
- throw new Error(`Path is not a file: ${file.path}`);
4570
+ startProgress() {
4571
+ this.progressInterval = setInterval(() => {
4572
+ const elapsed = Date.now() - this.startTime;
4573
+ const progress = this.calculateProgress(elapsed);
4574
+ const progressBar = this.createProgressBar(progress);
4575
+ this.spinner.text = `Uploading ${this.fileName}... ${progressBar} ${Math.round(progress * 100)}%`;
4576
+ }, PROGRESS_UPDATE_INTERVAL);
4577
+ }
4578
+ stopProgress() {
4579
+ if (this.progressInterval) {
4580
+ clearInterval(this.progressInterval);
4581
+ this.progressInterval = null;
4697
4582
  }
4698
- formData.append("file", import_fs_extra3.default.createReadStream(file.path), {
4699
- filename: file.name
4700
- });
4583
+ }
4584
+ calculateProgress(elapsed) {
4585
+ return Math.min(elapsed / EXPECTED_UPLOAD_TIME * MAX_PROGRESS, MAX_PROGRESS);
4586
+ }
4587
+ createProgressBar(progress, width = 20) {
4588
+ const percentage = Math.min(progress, 1);
4589
+ const filledWidth = Math.round(width * percentage);
4590
+ const emptyWidth = width - filledWidth;
4591
+ return `[${"\u2588".repeat(filledWidth)}${"\u2591".repeat(emptyWidth)}]`;
4592
+ }
4593
+ };
4594
+ async function calculateMD5(filePath) {
4595
+ return new Promise((resolve, reject) => {
4596
+ const hash = crypto.createHash("md5");
4597
+ const stream4 = import_fs_extra3.default.createReadStream(filePath);
4598
+ stream4.on("data", hash.update.bind(hash));
4599
+ stream4.on("end", () => resolve(hash.digest("hex")));
4600
+ stream4.on("error", reject);
4701
4601
  });
4702
- const startTime = Date.now();
4703
- const spinner = (0, import_ora.default)(`Preparing upload...`).start();
4704
- let totalSize = 0;
4705
- files.forEach((file) => {
4706
- try {
4707
- const stats = import_fs_extra3.default.statSync(file.path);
4708
- totalSize += stats.size;
4709
- } catch (error) {
4602
+ }
4603
+ async function compressDirectory(sourcePath) {
4604
+ return new Promise((resolve, reject) => {
4605
+ const tempDir = import_path4.default.join(process.cwd(), "temp");
4606
+ if (!import_fs_extra3.default.existsSync(tempDir)) {
4607
+ import_fs_extra3.default.mkdirSync(tempDir, { recursive: true });
4608
+ }
4609
+ const outputPath = import_path4.default.join(
4610
+ tempDir,
4611
+ `${import_path4.default.basename(sourcePath)}_${Date.now()}.zip`
4612
+ );
4613
+ const output = import_fs_extra3.default.createWriteStream(outputPath);
4614
+ const zlib2 = require("zlib");
4615
+ const gzip = zlib2.createGzip({ level: 9 });
4616
+ output.on("close", () => resolve(outputPath));
4617
+ gzip.on("error", reject);
4618
+ gzip.pipe(output);
4619
+ const stats = import_fs_extra3.default.statSync(sourcePath);
4620
+ if (stats.isDirectory()) {
4621
+ const archive = require("archiver");
4622
+ const archiveStream = archive("zip", { zlib: { level: 9 } });
4623
+ archiveStream.on("error", reject);
4624
+ archiveStream.pipe(output);
4625
+ archiveStream.directory(sourcePath, false);
4626
+ archiveStream.finalize();
4627
+ } else {
4628
+ const fileStream = import_fs_extra3.default.createReadStream(sourcePath);
4629
+ fileStream.pipe(gzip);
4710
4630
  }
4711
4631
  });
4712
- const smartProgress = new SmartProgressBar(
4713
- dist,
4714
- totalFiles,
4715
- totalSize,
4716
- spinner
4717
- );
4718
- const timeInterval = setInterval(() => {
4719
- smartProgress.updateTime();
4720
- }, 1e3);
4721
- const progressInterval = setInterval(() => {
4722
- smartProgress.updateProgress();
4723
- }, 200);
4632
+ }
4633
+ async function initChunkSession(filePath, deviceId, isDirectory = false) {
4634
+ const stats = import_fs_extra3.default.statSync(filePath);
4635
+ const fileName = import_path4.default.basename(filePath);
4636
+ const fileSize = stats.size;
4637
+ const md5 = await calculateMD5(filePath);
4724
4638
  try {
4725
- smartProgress.startUpload();
4726
4639
  const response = await axios_default.post(
4727
- `${ipfsApiUrl}/add?uid=${deviceId}&cidV=1`,
4728
- formData,
4640
+ `${IPFS_API_URL}/chunk/init`,
4729
4641
  {
4730
- headers: {
4731
- ...formData.getHeaders()
4732
- },
4733
- timeout: 18e5
4734
- // 30 minutes timeout
4642
+ file_name: fileName,
4643
+ file_size: fileSize,
4644
+ md5,
4645
+ is_directory: isDirectory,
4646
+ uid: deviceId
4647
+ },
4648
+ {
4649
+ timeout: TIMEOUT,
4650
+ headers: { "Content-Type": "application/json" }
4735
4651
  }
4736
4652
  );
4737
- clearInterval(progressInterval);
4738
- smartProgress.startPolling();
4739
- const { trace_id } = response.data.data;
4740
- if (!trace_id) {
4741
- smartProgress.fail("No request id received from server");
4742
- clearInterval(timeInterval);
4743
- return null;
4744
- }
4745
- smartProgress.updateDisplay();
4746
- const uploadResult = await pollUploadStatus(
4747
- trace_id,
4748
- deviceId,
4749
- smartProgress,
4750
- startTime
4751
- );
4752
- if (!uploadResult) {
4753
- clearInterval(timeInterval);
4754
- return null;
4755
- }
4756
- const directoryItem = uploadResult.upload_rst;
4757
- if (directoryItem) {
4758
- const fileCount = countFilesInDirectory(directoryPath);
4759
- const uploadData = {
4760
- path: directoryPath,
4761
- filename: import_path4.default.basename(directoryPath),
4762
- contentHash: directoryItem.Hash,
4763
- previewHash: null,
4764
- size: sizeCheck.size,
4765
- fileCount,
4766
- isDirectory: true,
4767
- shortUrl: directoryItem.ShortUrl || null
4768
- };
4769
- saveUploadHistory(uploadData);
4770
- clearInterval(timeInterval);
4771
- return {
4772
- hash: directoryItem.Hash,
4773
- shortUrl: directoryItem.ShortUrl
4774
- };
4653
+ const { code, msg, data } = response.data;
4654
+ if (code === 200 && data) {
4655
+ return data;
4775
4656
  }
4776
- const diagnosticInfo = diagnoseDirectoryUploadError(
4777
- dist,
4778
- uploadResult.upload_rst,
4779
- dist
4780
- );
4781
- smartProgress.fail("Directory hash not found in response");
4782
- console.log(
4783
- import_chalk2.default.red(
4784
- `
4785
- \u274C Directory upload failed: Directory hash not found in response`
4786
- )
4787
- );
4788
- console.log(import_chalk2.default.yellow(`
4789
- \u{1F4CB} Error diagnosis information:`));
4790
- console.log(import_chalk2.default.gray(` - ${diagnosticInfo}`));
4791
- console.log(import_chalk2.default.blue(`
4792
- \u{1F527} Solutions:`));
4793
- console.log(
4794
- import_chalk2.default.gray(` 1. Ensure directory is not empty and contains valid files`)
4795
- );
4796
- console.log(import_chalk2.default.gray(` 2. Check network connection stability`));
4797
- console.log(
4798
- import_chalk2.default.gray(` 3. Try uploading a smaller directory for testing`)
4799
- );
4800
- clearInterval(timeInterval);
4801
- return null;
4657
+ throw new Error(`Session initialization failed: ${msg} (code: ${code})`);
4802
4658
  } catch (error) {
4803
- clearInterval(progressInterval);
4804
- clearInterval(timeInterval);
4805
- if (error.message && error.message.includes("multipart")) {
4806
- const errorMessage = handleMultipartError(
4807
- error,
4808
- `Directory upload: ${dist}`
4809
- );
4810
- smartProgress.fail(errorMessage);
4811
- console.log(import_chalk2.default.red(`
4812
- \u274C ${errorMessage}`));
4813
- return null;
4814
- }
4815
- if (error.response && error.response.data && error.response.data.code) {
4816
- const errorCode = error.response.data.code.toString();
4817
- if (ERROR_CODES[errorCode]) {
4818
- smartProgress.fail(
4819
- `Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`
4820
- );
4821
- console.log(
4822
- import_chalk2.default.red(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`)
4823
- );
4824
- return null;
4825
- }
4659
+ if (axios_default.isAxiosError(error)) {
4660
+ throw new Error(`Network error: ${error.message}`);
4826
4661
  }
4827
- smartProgress.fail(`Error: ${error.message}`);
4828
- console.log(import_chalk2.default.red(`Error: ${error.message}`));
4829
- return null;
4662
+ throw error;
4830
4663
  }
4831
4664
  }
4832
- async function uploadFile(filePath, deviceId) {
4833
- const sizeCheck = checkFileSizeLimit(filePath);
4834
- if (sizeCheck.exceeds) {
4835
- throw new Error(
4836
- `File ${filePath} exceeds size limit of ${formatSize(
4837
- sizeCheck.limit
4838
- )} (size: ${formatSize(sizeCheck.size)})`
4839
- );
4840
- }
4841
- const fileName = filePath.split(import_path4.default.sep).pop() || "";
4842
- if (!import_fs_extra3.default.existsSync(filePath)) {
4843
- throw new Error(`File not found: ${filePath}`);
4844
- }
4845
- const fileStats = import_fs_extra3.default.statSync(filePath);
4846
- if (!fileStats.isFile()) {
4847
- throw new Error(`Path is not a file: ${filePath}`);
4848
- }
4849
- console.log(import_chalk2.default.blue("\n\u{1F4C4} File Upload Analysis:"));
4850
- console.log(import_chalk2.default.gray(` File path: ${filePath}`));
4851
- console.log(import_chalk2.default.gray(` File name: ${fileName}`));
4852
- console.log(import_chalk2.default.gray(` File size: ${formatSize(fileStats.size)}`));
4853
- console.log(import_chalk2.default.gray(` File exists: ${import_fs_extra3.default.existsSync(filePath)}`));
4854
- console.log(import_chalk2.default.gray(` Is file: ${fileStats.isFile()}
4855
- `));
4856
- const startTime = Date.now();
4857
- const spinner = (0, import_ora.default)(`Preparing upload...`).start();
4858
- let totalSize = 0;
4859
- try {
4860
- const stats = import_fs_extra3.default.statSync(filePath);
4861
- totalSize = stats.size;
4862
- } catch (error) {
4863
- }
4864
- const smartProgress = new SmartProgressBar(fileName, 1, totalSize, spinner);
4865
- const timeInterval = setInterval(() => {
4866
- smartProgress.updateTime();
4867
- }, 1e3);
4868
- const progressInterval = setInterval(() => {
4869
- smartProgress.updateProgress();
4870
- }, 200);
4665
+ async function uploadChunkWithAbort(sessionId, chunkIndex, chunkData, deviceId, signal, retryCount = 0) {
4871
4666
  try {
4872
- smartProgress.startUpload();
4873
- const formData = new import_form_data2.default();
4874
- const encodedFileName = encodeURIComponent(fileName);
4875
- formData.append("file", import_fs_extra3.default.createReadStream(filePath), {
4876
- filename: encodedFileName
4667
+ if (signal.aborted) {
4668
+ throw new Error("Request cancelled");
4669
+ }
4670
+ const form = new import_form_data2.default();
4671
+ form.append("session_id", sessionId);
4672
+ form.append("chunk_index", chunkIndex.toString());
4673
+ form.append("uid", deviceId);
4674
+ form.append("chunk", chunkData, {
4675
+ filename: `chunk_${chunkIndex}`,
4676
+ contentType: "application/octet-stream"
4877
4677
  });
4878
4678
  const response = await axios_default.post(
4879
- `${ipfsApiUrl}/add?uid=${deviceId}&cidV=1`,
4880
- formData,
4679
+ `${IPFS_API_URL}/chunk/upload`,
4680
+ form,
4881
4681
  {
4882
- headers: {
4883
- ...formData.getHeaders()
4884
- },
4885
- timeout: 18e5
4886
- // 30 minutes timeout
4682
+ headers: { ...form.getHeaders() },
4683
+ timeout: TIMEOUT,
4684
+ signal
4887
4685
  }
4888
4686
  );
4889
- clearInterval(progressInterval);
4890
- smartProgress.startPolling();
4891
- const trace_id = response.data.data.trace_id;
4892
- if (!trace_id) {
4893
- smartProgress.fail("No request id received from server");
4894
- clearInterval(timeInterval);
4895
- return null;
4896
- }
4897
- smartProgress.updateDisplay();
4898
- const uploadResult = await pollUploadStatus(
4899
- trace_id,
4900
- deviceId,
4901
- smartProgress,
4902
- startTime
4903
- );
4904
- if (!uploadResult) {
4905
- clearInterval(timeInterval);
4906
- return null;
4907
- }
4908
- const fileItem = uploadResult.upload_rst;
4909
- if (fileItem) {
4910
- const uploadData = {
4911
- path: filePath,
4912
- filename: fileName,
4913
- contentHash: fileItem.Hash,
4914
- previewHash: null,
4915
- size: sizeCheck.size,
4916
- fileCount: 1,
4917
- isDirectory: false,
4918
- shortUrl: fileItem.ShortUrl || null
4919
- };
4920
- saveUploadHistory(uploadData);
4921
- smartProgress.complete(trace_id);
4922
- clearInterval(timeInterval);
4923
- return {
4924
- hash: fileItem.Hash,
4925
- shortUrl: fileItem.ShortUrl
4926
- };
4687
+ const { code, msg, data } = response.data;
4688
+ if (code === 200 && data) {
4689
+ return data;
4927
4690
  }
4928
- smartProgress.fail("File hash not found in response");
4929
- console.log(
4930
- import_chalk2.default.red(`
4931
- \u274C File upload failed: File hash not found in response`)
4932
- );
4933
- console.log(import_chalk2.default.yellow(`
4934
- \u{1F4CB} Error diagnosis information:`));
4935
- console.log(import_chalk2.default.gray(` - File name: ${fileName}`));
4936
- console.log(
4937
- import_chalk2.default.gray(` - Name returned by IPFS: ${uploadResult.upload_rst.Name}`)
4938
- );
4939
- console.log(import_chalk2.default.blue(`
4940
- \u{1F527} Solutions:`));
4941
- console.log(import_chalk2.default.gray(` 1. Check if file is corrupted or unreadable`));
4942
- console.log(import_chalk2.default.gray(` 2. Check network connection stability`));
4943
- console.log(import_chalk2.default.gray(` 3. Try uploading a smaller file for testing`));
4944
- clearInterval(timeInterval);
4945
- return null;
4691
+ throw new Error(`Chunk upload failed: ${msg} (code: ${code})`);
4946
4692
  } catch (error) {
4947
- clearInterval(progressInterval);
4948
- clearInterval(timeInterval);
4949
- if (error.message && error.message.includes("multipart")) {
4950
- const errorMessage = handleMultipartError(
4951
- error,
4952
- `File upload: ${fileName}`
4693
+ if (error.name === "CanceledError" || signal.aborted) {
4694
+ throw new Error("Request cancelled");
4695
+ }
4696
+ if (retryCount < MAX_RETRIES) {
4697
+ await delayWithAbortCheck(RETRY_DELAY, signal);
4698
+ return uploadChunkWithAbort(
4699
+ sessionId,
4700
+ chunkIndex,
4701
+ chunkData,
4702
+ deviceId,
4703
+ signal,
4704
+ retryCount + 1
4953
4705
  );
4954
- smartProgress.fail(errorMessage);
4955
- console.log(import_chalk2.default.red(`
4956
- \u274C ${errorMessage}`));
4957
- return null;
4958
4706
  }
4959
- if (error.response && error.response.data && error.response.data.code) {
4960
- const errorCode = error.response.data.code.toString();
4961
- if (ERROR_CODES[errorCode]) {
4962
- smartProgress.fail(
4963
- `Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`
4964
- );
4965
- console.log(
4966
- import_chalk2.default.red(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`)
4967
- );
4968
- return null;
4969
- }
4970
- }
4971
- smartProgress.fail(`Error: ${error.message}`);
4972
- console.log(import_chalk2.default.red(`Error: ${error.message}`));
4973
- return null;
4707
+ throw new Error(
4708
+ `Chunk ${chunkIndex + 1} upload failed after ${MAX_RETRIES} retries: ${error.message}`
4709
+ );
4974
4710
  }
4975
4711
  }
4976
- var SmartProgressBar = class {
4977
- timeConstant;
4978
- startTime;
4979
- uploadStartTime;
4980
- isUploading;
4981
- isPolling;
4982
- fileCount;
4983
- totalSize;
4984
- spinner;
4985
- fileName;
4986
- isCompleted;
4987
- // Add completion flag
4988
- constructor(fileName, fileCount, totalSize, spinner) {
4989
- this.fileName = fileName;
4990
- this.fileCount = fileCount;
4991
- this.totalSize = totalSize;
4992
- this.spinner = spinner;
4993
- this.timeConstant = this.calcTimeConstant(fileCount, totalSize);
4994
- this.startTime = Date.now();
4995
- this.uploadStartTime = 0;
4996
- this.isUploading = false;
4997
- this.isPolling = false;
4998
- this.isCompleted = false;
4999
- }
5000
- // Calculate time constant based on file count and total size
5001
- calcTimeConstant(fileCount, totalSize) {
5002
- const base = 8e3;
5003
- const countFactor = 0.3 * Math.log(1 + fileCount);
5004
- const sizeFactor = 0.7 * Math.log(1 + totalSize / 1024 / 1024);
5005
- const minTimeConstant = 15e3;
5006
- const calculatedTimeConstant = base * (1 + countFactor + sizeFactor);
5007
- return Math.max(calculatedTimeConstant, minTimeConstant);
5008
- }
5009
- // Calculate progress using exponential decay model with upper limit
5010
- calculateProgress() {
5011
- const elapsed = Date.now() - this.startTime;
5012
- const rawProgress = 1 - Math.exp(-elapsed / this.timeConstant);
5013
- const maxProgress = this.isPolling ? 0.95 : 0.9;
5014
- return Math.min(rawProgress, maxProgress);
5015
- }
5016
- // Start upload phase
5017
- startUpload() {
5018
- this.isUploading = true;
5019
- this.uploadStartTime = Date.now();
5020
- }
5021
- // Start polling phase
5022
- startPolling() {
5023
- this.isPolling = true;
5024
- this.isUploading = false;
5025
- }
5026
- // Update progress display
5027
- update() {
5028
- if (this.isCompleted) {
4712
+ async function delayWithAbortCheck(delay, signal) {
4713
+ return new Promise((resolve, reject) => {
4714
+ const timeoutId = setTimeout(() => {
4715
+ if (signal.aborted) {
4716
+ reject(new Error("Request cancelled"));
4717
+ } else {
4718
+ resolve();
4719
+ }
4720
+ }, delay);
4721
+ if (signal.aborted) {
4722
+ clearTimeout(timeoutId);
4723
+ reject(new Error("Request cancelled"));
5029
4724
  return;
5030
4725
  }
5031
- const progress = this.calculateProgress();
5032
- const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
5033
- const progressBar = this.createProgressBar(progress);
5034
- const duration = this.formatDuration(elapsed);
5035
- let status = "";
5036
- if (this.isUploading) {
5037
- status = "uploading";
5038
- } else if (this.isPolling) {
5039
- status = "processing";
5040
- } else {
5041
- status = "preparing";
4726
+ const checkInterval = setInterval(() => {
4727
+ if (signal.aborted) {
4728
+ clearTimeout(timeoutId);
4729
+ clearInterval(checkInterval);
4730
+ reject(new Error("Request cancelled"));
4731
+ }
4732
+ }, 50);
4733
+ });
4734
+ }
4735
+ async function uploadFileChunks(filePath, sessionId, totalChunks, chunkSize, deviceId, progressBar) {
4736
+ const fileData = import_fs_extra3.default.readFileSync(filePath);
4737
+ const abortController = new AbortController();
4738
+ let completedCount = 0;
4739
+ let hasFatalError = false;
4740
+ let fatalError = null;
4741
+ const uploadTasks = Array.from({ length: totalChunks }, (_, chunkIndex) => {
4742
+ const start = chunkIndex * chunkSize;
4743
+ const end = Math.min(start + chunkSize, fileData.length);
4744
+ const chunkData = fileData.slice(start, end);
4745
+ return async () => {
4746
+ if (abortController.signal.aborted) return;
4747
+ try {
4748
+ await uploadChunkWithAbort(
4749
+ sessionId,
4750
+ chunkIndex,
4751
+ chunkData,
4752
+ deviceId,
4753
+ abortController.signal
4754
+ );
4755
+ if (abortController.signal.aborted) return;
4756
+ completedCount++;
4757
+ progressBar.updateProgress(completedCount, totalChunks);
4758
+ } catch (error) {
4759
+ if (error.name === "AbortError" || abortController.signal.aborted) {
4760
+ return;
4761
+ }
4762
+ hasFatalError = true;
4763
+ fatalError = `Chunk ${chunkIndex + 1}/${totalChunks} upload failed: ${error.message}`;
4764
+ abortController.abort();
4765
+ throw new Error(fatalError);
4766
+ }
4767
+ };
4768
+ });
4769
+ try {
4770
+ const results = await Promise.allSettled(uploadTasks.map((task) => task()));
4771
+ const failedResults = results.filter((result) => result.status === "rejected");
4772
+ if (failedResults.length > 0) {
4773
+ const firstFailure = failedResults[0];
4774
+ throw new Error(firstFailure.reason.message || "Error occurred during upload");
4775
+ }
4776
+ if (hasFatalError) {
4777
+ throw new Error(fatalError || "Unknown error occurred during upload");
5042
4778
  }
5043
- const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
5044
- this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
4779
+ } catch (error) {
4780
+ throw fatalError ? new Error(fatalError) : error;
5045
4781
  }
5046
- // Update time display only (called every second)
5047
- updateTime() {
5048
- if (this.isCompleted) {
5049
- return;
4782
+ }
4783
+ async function completeChunkUpload(sessionId, deviceId) {
4784
+ try {
4785
+ const response = await axios_default.post(
4786
+ `${IPFS_API_URL}/chunk/complete`,
4787
+ { session_id: sessionId, uid: deviceId },
4788
+ {
4789
+ timeout: TIMEOUT,
4790
+ headers: { "Content-Type": "application/json" }
4791
+ }
4792
+ );
4793
+ const { code, msg, data } = response.data;
4794
+ if (code === 200 && data) {
4795
+ return data.trace_id;
5050
4796
  }
5051
- const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
5052
- const duration = this.formatDuration(elapsed);
5053
- const progress = this.calculateProgress();
5054
- const progressBar = this.createProgressBar(progress);
5055
- let status = "";
5056
- if (this.isUploading) {
5057
- status = "uploading";
5058
- } else if (this.isPolling) {
5059
- status = "processing";
5060
- } else {
5061
- status = "preparing";
4797
+ throw new Error(`Complete upload failed: ${msg} (code: ${code})`);
4798
+ } catch (error) {
4799
+ if (axios_default.isAxiosError(error)) {
4800
+ throw new Error(`Network error: ${error.message}`);
5062
4801
  }
5063
- const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
5064
- this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
4802
+ throw error;
5065
4803
  }
5066
- // Update progress bar only (called every 200ms)
5067
- updateProgress() {
5068
- if (this.isCompleted) {
5069
- return;
4804
+ }
4805
+ async function getChunkStatus(sessionId, deviceId) {
4806
+ try {
4807
+ const response = await axios_default.get(
4808
+ `${IPFS_API_URL}/up_status`,
4809
+ {
4810
+ params: { trace_id: sessionId, uid: deviceId },
4811
+ timeout: TIMEOUT,
4812
+ headers: { "Content-Type": "application/json" }
4813
+ }
4814
+ );
4815
+ const { code, msg, data } = response.data;
4816
+ if (code === 200) {
4817
+ return data;
5070
4818
  }
5071
- const progress = this.calculateProgress();
5072
- const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
5073
- const progressBar = this.createProgressBar(progress);
5074
- const duration = this.formatDuration(elapsed);
5075
- let status = "";
5076
- if (this.isUploading) {
5077
- status = "uploading";
5078
- } else if (this.isPolling) {
5079
- status = "processing";
5080
- } else {
5081
- status = "preparing";
4819
+ throw new Error(`Server returned error: ${msg} (code: ${code})`);
4820
+ } catch (error) {
4821
+ if (axios_default.isAxiosError(error)) {
4822
+ throw new Error(`Network error: ${error.message}`);
5082
4823
  }
5083
- const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
5084
- this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
4824
+ throw error;
5085
4825
  }
5086
- // Update display (for manual updates)
5087
- updateDisplay() {
5088
- this.updateTime();
4826
+ }
4827
+ async function monitorChunkProgress(traceId, deviceId) {
4828
+ let consecutiveErrors = 0;
4829
+ const startTime = Date.now();
4830
+ while (Date.now() - startTime < MAX_POLL_TIME) {
4831
+ try {
4832
+ const status = await getChunkStatus(traceId, deviceId);
4833
+ consecutiveErrors = 0;
4834
+ if (status.is_ready && status.upload_rst.Hash) {
4835
+ return {
4836
+ hash: status.upload_rst.Hash,
4837
+ shortUrl: status.upload_rst.ShortUrl
4838
+ };
4839
+ }
4840
+ } catch (error) {
4841
+ consecutiveErrors++;
4842
+ if (consecutiveErrors > 10) {
4843
+ throw new Error(`Polling failed: ${error.message}`);
4844
+ }
4845
+ }
4846
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
5089
4847
  }
5090
- // Update progress display only (no progress bar)
5091
- updateTimeOnly() {
5092
- const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
5093
- const duration = this.formatDuration(elapsed);
5094
- this.spinner.text = `Uploading ${this.fileName} ${duration}`;
4848
+ const maxPollTimeMinutes = Math.floor(MAX_POLL_TIME / (60 * 1e3));
4849
+ throw new Error(`Polling timeout after ${maxPollTimeMinutes} minutes`);
4850
+ }
4851
+ async function uploadDirectoryInChunks(directoryPath, deviceId) {
4852
+ const sizeCheck = checkDirectorySizeLimit(directoryPath);
4853
+ if (sizeCheck.exceeds) {
4854
+ throw new Error(
4855
+ `Directory ${directoryPath} exceeds size limit ${formatSize(sizeCheck.limit)} (size: ${formatSize(sizeCheck.size)})`
4856
+ );
5095
4857
  }
5096
- // Complete progress
5097
- complete(traceId) {
5098
- if (this.isCompleted) {
5099
- return;
4858
+ const progressBar = new StepProgressBar(import_path4.default.basename(directoryPath), true);
4859
+ try {
4860
+ progressBar.startStep(0, "Preparing compression");
4861
+ const compressedPath = await compressDirectory(directoryPath);
4862
+ progressBar.completeStep();
4863
+ progressBar.startStep(1, "Initializing session");
4864
+ const sessionInfo = await initChunkSession(compressedPath, deviceId, true);
4865
+ progressBar.completeStep();
4866
+ progressBar.startStep(2, "Chunk upload");
4867
+ await uploadFileChunks(
4868
+ compressedPath,
4869
+ sessionInfo.session_id,
4870
+ sessionInfo.total_chunks,
4871
+ sessionInfo.chunk_size,
4872
+ deviceId,
4873
+ progressBar
4874
+ );
4875
+ progressBar.completeStep();
4876
+ progressBar.startStep(3, "Completing upload");
4877
+ const traceId = await completeChunkUpload(sessionInfo.session_id, deviceId);
4878
+ progressBar.completeStep();
4879
+ progressBar.startStep(4, "Waiting for processing");
4880
+ const result = await monitorChunkProgress(traceId, deviceId);
4881
+ progressBar.completeStep();
4882
+ try {
4883
+ import_fs_extra3.default.unlinkSync(compressedPath);
4884
+ } catch (error) {
5100
4885
  }
5101
- const progressBar = this.createProgressBar(1);
5102
- const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
5103
- const duration = this.formatDuration(elapsed);
5104
- this.spinner.succeed(`Upload completed ${progressBar} ${duration}`);
5105
- this.isCompleted = true;
5106
- }
5107
- // Fail progress
5108
- fail(message, traceId) {
5109
- if (this.isCompleted) {
5110
- return;
4886
+ const uploadData = {
4887
+ path: directoryPath,
4888
+ filename: import_path4.default.basename(directoryPath),
4889
+ contentHash: (result == null ? void 0 : result.hash) || "unknown",
4890
+ size: sizeCheck.size,
4891
+ fileCount: 0,
4892
+ isDirectory: true,
4893
+ shortUrl: (result == null ? void 0 : result.shortUrl) || null
4894
+ };
4895
+ saveUploadHistory(uploadData);
4896
+ if (!(result == null ? void 0 : result.hash)) {
4897
+ throw new Error("Server did not return valid hash value");
5111
4898
  }
5112
- const elapsed = Math.floor((Date.now() - this.startTime) / 1e3);
5113
- const duration = this.formatDuration(elapsed);
5114
- this.spinner.fail(`${message} ${duration}`);
5115
- this.isCompleted = true;
4899
+ progressBar.complete();
4900
+ return result;
4901
+ } catch (error) {
4902
+ progressBar.fail(error.message);
4903
+ throw error;
5116
4904
  }
5117
- // Create visual progress bar
5118
- createProgressBar(progress, width = 20) {
5119
- const percentage = Math.min(progress, 1);
5120
- const filledWidth = Math.round(width * percentage);
5121
- const emptyWidth = width - filledWidth;
5122
- const filled = "\u2588".repeat(filledWidth);
5123
- const empty = "\u2591".repeat(emptyWidth);
5124
- return `[${filled}${empty}] ${Math.round(percentage * 100)}%`;
5125
- }
5126
- // Format time duration
5127
- formatDuration(seconds) {
5128
- if (seconds < 60) {
5129
- return `${seconds}s`;
5130
- } else if (seconds < 3600) {
5131
- const minutes = Math.floor(seconds / 60);
5132
- const remainingSeconds = seconds % 60;
5133
- return `${minutes}m ${remainingSeconds}s`;
5134
- } else {
5135
- const hours = Math.floor(seconds / 3600);
5136
- const minutes = Math.floor(seconds % 3600 / 60);
5137
- const remainingSeconds = seconds % 60;
5138
- return `${hours}h ${minutes}m ${remainingSeconds}s`;
4905
+ }
4906
+ async function uploadFileInChunks(filePath, deviceId) {
4907
+ const sizeCheck = checkFileSizeLimit(filePath);
4908
+ if (sizeCheck.exceeds) {
4909
+ throw new Error(
4910
+ `File ${filePath} exceeds size limit ${formatSize(sizeCheck.limit)} (size: ${formatSize(sizeCheck.size)})`
4911
+ );
4912
+ }
4913
+ const fileName = import_path4.default.basename(filePath);
4914
+ const progressBar = new StepProgressBar(fileName, false);
4915
+ try {
4916
+ progressBar.startStep(0, "Initializing session");
4917
+ const sessionInfo = await initChunkSession(filePath, deviceId, false);
4918
+ progressBar.completeStep();
4919
+ progressBar.startStep(1, "Chunk upload");
4920
+ await uploadFileChunks(
4921
+ filePath,
4922
+ sessionInfo.session_id,
4923
+ sessionInfo.total_chunks,
4924
+ sessionInfo.chunk_size,
4925
+ deviceId,
4926
+ progressBar
4927
+ );
4928
+ progressBar.completeStep();
4929
+ progressBar.startStep(2, "Completing upload");
4930
+ const traceId = await completeChunkUpload(sessionInfo.session_id, deviceId);
4931
+ progressBar.completeStep();
4932
+ progressBar.startStep(3, "Waiting for processing");
4933
+ const result = await monitorChunkProgress(traceId, deviceId);
4934
+ progressBar.completeStep();
4935
+ const uploadData = {
4936
+ path: filePath,
4937
+ filename: fileName,
4938
+ contentHash: (result == null ? void 0 : result.hash) || "unknown",
4939
+ previewHash: null,
4940
+ size: sizeCheck.size,
4941
+ fileCount: 1,
4942
+ isDirectory: false,
4943
+ shortUrl: (result == null ? void 0 : result.shortUrl) || null
4944
+ };
4945
+ saveUploadHistory(uploadData);
4946
+ if (!(result == null ? void 0 : result.hash)) {
4947
+ throw new Error("Server did not return valid hash value");
5139
4948
  }
4949
+ progressBar.complete();
4950
+ return result;
4951
+ } catch (error) {
4952
+ progressBar.fail(error.message);
4953
+ throw error;
5140
4954
  }
5141
- };
5142
- async function uploadToIpfs_default(filePath) {
4955
+ }
4956
+ async function uploadToIpfs2_default(filePath) {
5143
4957
  const deviceId = getDeviceId();
5144
4958
  if (!deviceId) {
5145
4959
  throw new Error("Device ID not found");
5146
4960
  }
5147
- let contentHash = "";
5148
- let shortUrl = "";
5149
- if (import_fs_extra3.default.statSync(filePath).isDirectory()) {
5150
- const result = await uploadDirectory(filePath, deviceId);
5151
- if (result) {
5152
- contentHash = result.hash;
5153
- shortUrl = result.shortUrl || "";
5154
- }
5155
- } else {
5156
- const result = await uploadFile(filePath, deviceId);
5157
- if (result) {
5158
- contentHash = result.hash;
5159
- shortUrl = result.shortUrl || "";
4961
+ try {
4962
+ const isDirectory = import_fs_extra3.default.statSync(filePath).isDirectory();
4963
+ const result = isDirectory ? await uploadDirectoryInChunks(filePath, deviceId) : await uploadFileInChunks(filePath, deviceId);
4964
+ if (result == null ? void 0 : result.hash) {
4965
+ return {
4966
+ contentHash: result.hash,
4967
+ previewHash: null,
4968
+ shortUrl: result.shortUrl
4969
+ };
5160
4970
  }
4971
+ return null;
4972
+ } catch (error) {
4973
+ return null;
5161
4974
  }
5162
- if (contentHash) {
5163
- return {
5164
- contentHash,
5165
- previewHash: null,
5166
- shortUrl
5167
- };
5168
- }
5169
- return null;
5170
4975
  }
5171
4976
 
5172
4977
  // bin/upload.ts
@@ -5195,7 +5000,7 @@ function checkPathSync(inputPath) {
5195
5000
  }
5196
5001
  return null;
5197
5002
  } catch (error) {
5198
- console.error(import_chalk3.default.red(`error checking path: ${error.message}`));
5003
+ console.error(import_chalk2.default.red(`error checking path: ${error.message}`));
5199
5004
  return null;
5200
5005
  }
5201
5006
  }
@@ -5214,26 +5019,27 @@ var upload_default = async (options) => {
5214
5019
  if (argPath && !argPath.startsWith("-")) {
5215
5020
  const absolutePath = checkPathSync(argPath);
5216
5021
  if (!absolutePath) {
5217
- console.log(import_chalk3.default.red(`path ${argPath} does not exist`));
5022
+ console.log(import_chalk2.default.red(`path ${argPath} does not exist`));
5218
5023
  return;
5219
5024
  }
5220
- console.log(import_chalk3.default.blue(`uploading ${absolutePath} to ipfs...`));
5025
+ console.log(import_chalk2.default.blue(`uploading ${absolutePath} to ipfs...`));
5221
5026
  try {
5222
- const result = await uploadToIpfs_default(absolutePath);
5027
+ const result = await uploadToIpfs2_default(absolutePath);
5223
5028
  if (result) {
5224
5029
  const encryptedCID = encryptHash(result.contentHash, secretKey);
5225
5030
  console.log(
5226
- import_chalk3.default.cyan(
5031
+ import_chalk2.default.cyan(
5227
5032
  import_figlet.default.textSync("Successful", { horizontalLayout: "full" })
5228
5033
  )
5229
5034
  );
5230
- console.log(import_chalk3.default.cyan(`URL:`));
5231
- console.log(import_chalk3.default.cyan(`${URL2}${encryptedCID}`));
5035
+ console.log(import_chalk2.default.cyan(`URL:`));
5036
+ console.log(import_chalk2.default.cyan(`${URL2}${encryptedCID}`));
5037
+ console.log(import_chalk2.default.green("\n\u{1F389} \u4E0A\u4F20\u5B8C\u6210\uFF0C\u7A0B\u5E8F\u9000\u51FA"));
5232
5038
  }
5233
5039
  } catch (error) {
5234
- console.error(import_chalk3.default.red(`Error: ${error.message}`));
5040
+ console.error(import_chalk2.default.red(`Error: ${error.message}`));
5235
5041
  }
5236
- return;
5042
+ process.exit(0);
5237
5043
  }
5238
5044
  const answer = await import_inquirer.default.prompt([
5239
5045
  {
@@ -5245,44 +5051,46 @@ var upload_default = async (options) => {
5245
5051
  if (answer.path) {
5246
5052
  const absolutePath = checkPathSync(answer.path);
5247
5053
  if (!absolutePath) {
5248
- console.log(import_chalk3.default.red(`path ${answer.path} does not exist`));
5054
+ console.log(import_chalk2.default.red(`path ${answer.path} does not exist`));
5249
5055
  return;
5250
5056
  }
5251
- console.log(import_chalk3.default.blue(`uploading ${absolutePath} to ipfs...`));
5057
+ console.log(import_chalk2.default.blue(`uploading ${absolutePath} to ipfs...`));
5252
5058
  try {
5253
- const result = await uploadToIpfs_default(absolutePath);
5059
+ const result = await uploadToIpfs2_default(absolutePath);
5254
5060
  if (result) {
5255
5061
  const encryptedCID = encryptHash(result.contentHash, secretKey);
5256
5062
  console.log(
5257
- import_chalk3.default.cyan(
5063
+ import_chalk2.default.cyan(
5258
5064
  import_figlet.default.textSync("Successful", { horizontalLayout: "full" })
5259
5065
  )
5260
5066
  );
5261
- console.log(import_chalk3.default.cyan(`URL:`));
5262
- console.log(import_chalk3.default.cyan(`${URL2}${encryptedCID}`));
5067
+ console.log(import_chalk2.default.cyan(`URL:`));
5068
+ console.log(import_chalk2.default.cyan(`${URL2}${encryptedCID}`));
5069
+ console.log(import_chalk2.default.green("\n\u{1F389} \u4E0A\u4F20\u5B8C\u6210\uFF0C\u7A0B\u5E8F\u9000\u51FA"));
5263
5070
  }
5264
5071
  } catch (error) {
5265
- console.error(import_chalk3.default.red(`Error: ${error.message}`));
5072
+ console.error(import_chalk2.default.red(`Error: ${error.message}`));
5266
5073
  }
5074
+ process.exit(0);
5267
5075
  }
5268
5076
  } catch (error) {
5269
- console.error(import_chalk3.default.red(`error executing: ${error.message}`));
5077
+ console.error(import_chalk2.default.red(`error executing: ${error.message}`));
5270
5078
  console.error(error.stack);
5271
5079
  }
5272
5080
  };
5273
5081
 
5274
5082
  // bin/remove.ts
5275
- var import_chalk5 = __toESM(require("chalk"));
5083
+ var import_chalk4 = __toESM(require("chalk"));
5276
5084
  var import_inquirer2 = __toESM(require("inquirer"));
5277
5085
  var import_figlet2 = __toESM(require("figlet"));
5278
5086
 
5279
5087
  // bin/utils/removeFromIpfs.ts
5280
- var import_chalk4 = __toESM(require("chalk"));
5281
- var ipfsApiUrl2 = "https://pinme.dev/api/v3";
5088
+ var import_chalk3 = __toESM(require("chalk"));
5089
+ var ipfsApiUrl = "https://up.pinme.dev/api/v3";
5282
5090
  async function removeFromIpfs(value, type = "hash") {
5283
5091
  try {
5284
5092
  const uid = getDeviceId();
5285
- console.log(import_chalk4.default.blue(`Removing content from IPFS: ${value}...`));
5093
+ console.log(import_chalk3.default.blue(`Removing content from IPFS: ${value}...`));
5286
5094
  const queryParams = new URLSearchParams({
5287
5095
  uid
5288
5096
  });
@@ -5291,37 +5099,37 @@ async function removeFromIpfs(value, type = "hash") {
5291
5099
  } else {
5292
5100
  queryParams.append("arg", value);
5293
5101
  }
5294
- const response = await axios_default.post(`${ipfsApiUrl2}/block/rm?${queryParams.toString()}`, {
5102
+ const response = await axios_default.post(`${ipfsApiUrl}/block/rm?${queryParams.toString()}`, {
5295
5103
  timeout: 3e4
5296
5104
  // 30 seconds timeout
5297
5105
  });
5298
5106
  const { code, msg, data } = response.data;
5299
5107
  if (code === 200) {
5300
- console.log(import_chalk4.default.green("\u2713 Removal successful!"));
5301
- console.log(import_chalk4.default.cyan(`Content ${type}: ${value} has been removed from IPFS network`));
5108
+ console.log(import_chalk3.default.green("\u2713 Removal successful!"));
5109
+ console.log(import_chalk3.default.cyan(`Content ${type}: ${value} has been removed from IPFS network`));
5302
5110
  return true;
5303
5111
  } else {
5304
- console.log(import_chalk4.default.red("\u2717 Removal failed"));
5305
- console.log(import_chalk4.default.red(`Error: ${msg || "Unknown error occurred"}`));
5112
+ console.log(import_chalk3.default.red("\u2717 Removal failed"));
5113
+ console.log(import_chalk3.default.red(`Error: ${msg || "Unknown error occurred"}`));
5306
5114
  return false;
5307
5115
  }
5308
5116
  } catch (error) {
5309
- console.log(import_chalk4.default.red("\u2717 Removal failed", error));
5117
+ console.log(import_chalk3.default.red("\u2717 Removal failed", error));
5310
5118
  if (error.response) {
5311
5119
  const { status, data } = error.response;
5312
- console.log(import_chalk4.default.red(`HTTP Error ${status}: ${(data == null ? void 0 : data.msg) || "Server error"}`));
5120
+ console.log(import_chalk3.default.red(`HTTP Error ${status}: ${(data == null ? void 0 : data.msg) || "Server error"}`));
5313
5121
  if (status === 404) {
5314
- console.log(import_chalk4.default.yellow("Content not found on the network or already removed"));
5122
+ console.log(import_chalk3.default.yellow("Content not found on the network or already removed"));
5315
5123
  } else if (status === 403) {
5316
- console.log(import_chalk4.default.yellow("Permission denied - you may not have access to remove this content"));
5124
+ console.log(import_chalk3.default.yellow("Permission denied - you may not have access to remove this content"));
5317
5125
  } else if (status === 500) {
5318
- console.log(import_chalk4.default.yellow("Server internal error - please try again later"));
5126
+ console.log(import_chalk3.default.yellow("Server internal error - please try again later"));
5319
5127
  }
5320
5128
  } else if (error.request) {
5321
- console.log(import_chalk4.default.red("Network error: Unable to connect to IPFS service"));
5322
- console.log(import_chalk4.default.yellow("Please check your internet connection and try again"));
5129
+ console.log(import_chalk3.default.red("Network error: Unable to connect to IPFS service"));
5130
+ console.log(import_chalk3.default.yellow("Please check your internet connection and try again"));
5323
5131
  } else {
5324
- console.log(import_chalk4.default.red(`Error: ${error.message}`));
5132
+ console.log(import_chalk3.default.red(`Error: ${error.message}`));
5325
5133
  }
5326
5134
  return false;
5327
5135
  }
@@ -5380,30 +5188,30 @@ var remove_default = async (options) => {
5380
5188
  if (argHash && !argHash.startsWith("-")) {
5381
5189
  const parsedInput = parseInput(argHash);
5382
5190
  if (!parsedInput) {
5383
- console.log(import_chalk5.default.red(`Invalid input format: ${argHash}`));
5384
- console.log(import_chalk5.default.yellow("Supported formats:"));
5385
- console.log(import_chalk5.default.yellow(" - IPFS hash: bafybeig..."));
5386
- console.log(import_chalk5.default.yellow(" - Full URL: https://bafybeig....pinme.dev"));
5387
- console.log(import_chalk5.default.yellow(" - Subname: 3abt6ztu"));
5388
- console.log(import_chalk5.default.yellow(" - Subname URL: https://3abt6ztu.pinit.eth.limo"));
5191
+ console.log(import_chalk4.default.red(`Invalid input format: ${argHash}`));
5192
+ console.log(import_chalk4.default.yellow("Supported formats:"));
5193
+ console.log(import_chalk4.default.yellow(" - IPFS hash: bafybeig..."));
5194
+ console.log(import_chalk4.default.yellow(" - Full URL: https://bafybeig....pinme.dev"));
5195
+ console.log(import_chalk4.default.yellow(" - Subname: 3abt6ztu"));
5196
+ console.log(import_chalk4.default.yellow(" - Subname URL: https://3abt6ztu.pinit.eth.limo"));
5389
5197
  return;
5390
5198
  }
5391
5199
  try {
5392
5200
  const success = await removeFromIpfs(parsedInput.value, parsedInput.type);
5393
5201
  if (success) {
5394
5202
  console.log(
5395
- import_chalk5.default.cyan(
5203
+ import_chalk4.default.cyan(
5396
5204
  import_figlet2.default.textSync("Successful", { horizontalLayout: "full" })
5397
5205
  )
5398
5206
  );
5399
5207
  }
5400
5208
  } catch (error) {
5401
- console.error(import_chalk5.default.red(`Error: ${error.message}`));
5209
+ console.error(import_chalk4.default.red(`Error: ${error.message}`));
5402
5210
  }
5403
5211
  return;
5404
5212
  }
5405
- console.log(import_chalk5.default.yellow("\u26A0\uFE0F Warning: This action will permanently remove the content from IPFS network"));
5406
- console.log(import_chalk5.default.yellow("\u26A0\uFE0F Make sure you have the correct IPFS hash"));
5213
+ console.log(import_chalk4.default.yellow("\u26A0\uFE0F Warning: This action will permanently remove the content from IPFS network"));
5214
+ console.log(import_chalk4.default.yellow("\u26A0\uFE0F Make sure you have the correct IPFS hash"));
5407
5215
  console.log("");
5408
5216
  const confirmAnswer = await import_inquirer2.default.prompt([
5409
5217
  {
@@ -5414,7 +5222,7 @@ var remove_default = async (options) => {
5414
5222
  }
5415
5223
  ]);
5416
5224
  if (!confirmAnswer.confirm) {
5417
- console.log(import_chalk5.default.yellow("Operation cancelled"));
5225
+ console.log(import_chalk4.default.yellow("Operation cancelled"));
5418
5226
  return;
5419
5227
  }
5420
5228
  const answer = await import_inquirer2.default.prompt([
@@ -5437,7 +5245,7 @@ var remove_default = async (options) => {
5437
5245
  if (answer.input) {
5438
5246
  const parsedInput = parseInput(answer.input.trim());
5439
5247
  if (!parsedInput) {
5440
- console.log(import_chalk5.default.red("Invalid input format"));
5248
+ console.log(import_chalk4.default.red("Invalid input format"));
5441
5249
  return;
5442
5250
  }
5443
5251
  const finalConfirm = await import_inquirer2.default.prompt([
@@ -5449,24 +5257,24 @@ var remove_default = async (options) => {
5449
5257
  }
5450
5258
  ]);
5451
5259
  if (!finalConfirm.confirm) {
5452
- console.log(import_chalk5.default.yellow("Operation cancelled"));
5260
+ console.log(import_chalk4.default.yellow("Operation cancelled"));
5453
5261
  return;
5454
5262
  }
5455
5263
  try {
5456
5264
  const success = await removeFromIpfs(parsedInput.value, parsedInput.type);
5457
5265
  if (success) {
5458
5266
  console.log(
5459
- import_chalk5.default.cyan(
5267
+ import_chalk4.default.cyan(
5460
5268
  import_figlet2.default.textSync("Successful", { horizontalLayout: "full" })
5461
5269
  )
5462
5270
  );
5463
5271
  }
5464
5272
  } catch (error) {
5465
- console.error(import_chalk5.default.red(`Error: ${error.message}`));
5273
+ console.error(import_chalk4.default.red(`Error: ${error.message}`));
5466
5274
  }
5467
5275
  }
5468
5276
  } catch (error) {
5469
- console.error(import_chalk5.default.red(`Error executing remove command: ${error.message}`));
5277
+ console.error(import_chalk4.default.red(`Error executing remove command: ${error.message}`));
5470
5278
  console.error(error.stack);
5471
5279
  }
5472
5280
  };
@@ -5475,11 +5283,11 @@ var remove_default = async (options) => {
5475
5283
  import_dotenv.default.config();
5476
5284
  function showBanner() {
5477
5285
  console.log(
5478
- import_chalk6.default.cyan(
5286
+ import_chalk5.default.cyan(
5479
5287
  import_figlet3.default.textSync("Pinme", { horizontalLayout: "full" })
5480
5288
  )
5481
5289
  );
5482
- console.log(import_chalk6.default.cyan("A command-line tool for uploading files to IPFS\n"));
5290
+ console.log(import_chalk5.default.cyan("A command-line tool for uploading files to IPFS\n"));
5483
5291
  }
5484
5292
  var program = new import_commander.Command();
5485
5293
  program.name("pinme").version(version).option("-v, --version", "output the current version");