pinme 1.1.1-alpha.1 → 1.1.1-alpha.3

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 +282 -90
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1485,7 +1485,7 @@ var import_chalk6 = __toESM(require("chalk"));
1485
1485
  var import_figlet3 = __toESM(require("figlet"));
1486
1486
 
1487
1487
  // package.json
1488
- var version = "1.1.1-alpha.1";
1488
+ var version = "1.1.1-alpha.3";
1489
1489
 
1490
1490
  // bin/upload.ts
1491
1491
  var import_path5 = __toESM(require("path"));
@@ -4525,7 +4525,9 @@ var ipfsApiUrl = "https://pinme.dev/api/v3";
4525
4525
  var maxPollTime = parseInt(process.env.MAX_POLL_TIME_MINUTES || "5") * 60 * 1e3;
4526
4526
  var pollInterval = parseInt(process.env.POLL_INTERVAL_SECONDS || "2") * 1e3;
4527
4527
  var pollTimeout = parseInt(process.env.POLL_TIMEOUT_SECONDS || "10") * 1e3;
4528
- async function pollUploadStatus(traceId, deviceId, spinner, startTime) {
4528
+ async function pollUploadStatus(traceId, deviceId, smartProgress, startTime) {
4529
+ let consecutiveErrors = 0;
4530
+ let stopProgressUpdates = false;
4529
4531
  while (Date.now() - startTime < maxPollTime) {
4530
4532
  try {
4531
4533
  const response = await axios_default.get(
@@ -4542,28 +4544,31 @@ async function pollUploadStatus(traceId, deviceId, spinner, startTime) {
4542
4544
  );
4543
4545
  const { code, msg, data } = response.data;
4544
4546
  if (code === 200) {
4545
- const elapsed = Math.floor((Date.now() - startTime) / 1e3);
4547
+ consecutiveErrors = 0;
4548
+ stopProgressUpdates = false;
4546
4549
  if (data.is_ready) {
4547
- const progressBar = createProgressBar(1, 1);
4548
- const duration = formatDuration(elapsed);
4549
- spinner.succeed(`Upload completed ${progressBar} ${duration} (request id: ${traceId})`);
4550
+ smartProgress.complete(traceId);
4550
4551
  return data;
4551
4552
  } else {
4552
- const estimatedProgress = Math.min(elapsed / 30, 0.9);
4553
- const progressBar = createProgressBar(estimatedProgress, 1);
4554
- const duration = formatDuration(elapsed);
4555
- spinner.text = `Uploading... ${progressBar} ${duration} (request id: ${traceId})`;
4553
+ smartProgress.updateDisplay();
4556
4554
  }
4557
4555
  } else {
4558
4556
  console.log(import_chalk2.default.yellow(`Warning: ${msg}`));
4559
4557
  }
4560
4558
  } catch (error) {
4559
+ consecutiveErrors++;
4561
4560
  console.log(import_chalk2.default.yellow(`Polling error: ${error.message}`));
4561
+ if (stopProgressUpdates) {
4562
+ smartProgress.updateTimeOnly();
4563
+ }
4562
4564
  }
4563
4565
  await new Promise((resolve) => setTimeout(resolve, pollInterval));
4564
4566
  }
4565
4567
  const maxPollTimeMinutes = Math.floor(maxPollTime / (60 * 1e3));
4566
- spinner.fail(`Upload timeout after ${maxPollTimeMinutes} minutes (request id: ${traceId})`);
4568
+ smartProgress.fail(
4569
+ `Upload timeout after ${maxPollTimeMinutes} minutes`,
4570
+ traceId
4571
+ );
4567
4572
  return null;
4568
4573
  }
4569
4574
  function diagnoseDirectoryUploadError(directoryName, resData, expectedName) {
@@ -4608,10 +4613,13 @@ var ERROR_CODES = {
4608
4613
  "30001": `File too large, single file max size: ${"20"}MB,single folder max size: ${"500"}MB`,
4609
4614
  "30002": `Max storage quorum ${Number("1000") / 1e3} GB reached`
4610
4615
  };
4611
- function loadFilesToArrRecursively(directoryPath, dist) {
4616
+ function loadFilesToArrRecursively(directoryPath, dist, basePath) {
4612
4617
  const filesArr = [];
4613
4618
  const sep = import_path4.default.sep;
4614
- const basePath = import_path4.default.dirname(directoryPath) + sep;
4619
+ if (!basePath) {
4620
+ const parentDir = import_path4.default.dirname(directoryPath);
4621
+ basePath = parentDir.endsWith(sep) ? parentDir : parentDir + sep;
4622
+ }
4615
4623
  if (import_fs_extra3.default.statSync(directoryPath).isDirectory()) {
4616
4624
  const files = import_fs_extra3.default.readdirSync(directoryPath);
4617
4625
  files.forEach((file) => {
@@ -4625,14 +4633,18 @@ function loadFilesToArrRecursively(directoryPath, dist) {
4625
4633
  )} (size: ${formatSize(sizeCheck.size)})`
4626
4634
  );
4627
4635
  }
4628
- const filePathWithNoEndSep = filePath.replace(basePath, "");
4629
- const filePathEncodeSep = filePathWithNoEndSep.replaceAll(sep, "%2F");
4636
+ const relativePath = filePath.replace(basePath, "");
4637
+ const encodedPath = relativePath.replaceAll(sep, "%2F");
4630
4638
  filesArr.push({
4631
- name: filePathEncodeSep,
4639
+ name: encodedPath,
4632
4640
  path: filePath
4633
4641
  });
4634
4642
  } else if (import_fs_extra3.default.statSync(filePath).isDirectory()) {
4635
- const recursiveFiles = loadFilesToArrRecursively(filePath, dist);
4643
+ const recursiveFiles = loadFilesToArrRecursively(
4644
+ filePath,
4645
+ dist,
4646
+ basePath
4647
+ );
4636
4648
  filesArr.push(...recursiveFiles);
4637
4649
  }
4638
4650
  });
@@ -4671,18 +4683,9 @@ async function uploadDirectory(directoryPath, deviceId) {
4671
4683
  const files = loadFilesToArrRecursively(directoryPath, dist);
4672
4684
  const totalFiles = files.length;
4673
4685
  if (totalFiles === 0) {
4674
- throw new Error(`Directory ${directoryPath} is empty or contains no valid files`);
4675
- }
4676
- console.log(import_chalk2.default.gray(`
4677
- \u{1F4C1} Directory upload details:`));
4678
- console.log(import_chalk2.default.gray(` - Directory: ${dist}`));
4679
- console.log(import_chalk2.default.gray(` - Total files: ${totalFiles}`));
4680
- console.log(import_chalk2.default.gray(` - Files to upload:`));
4681
- files.slice(0, 5).forEach((file, index) => {
4682
- console.log(import_chalk2.default.gray(` ${index + 1}. ${file.name} (${file.path})`));
4683
- });
4684
- if (files.length > 5) {
4685
- console.log(import_chalk2.default.gray(` ... and ${files.length - 5} more files`));
4686
+ throw new Error(
4687
+ `Directory ${directoryPath} is empty or contains no valid files`
4688
+ );
4686
4689
  }
4687
4690
  files.forEach((file) => {
4688
4691
  if (!import_fs_extra3.default.existsSync(file.path)) {
@@ -4697,16 +4700,29 @@ async function uploadDirectory(directoryPath, deviceId) {
4697
4700
  });
4698
4701
  });
4699
4702
  const startTime = Date.now();
4700
- const spinner = (0, import_ora.default)(
4701
- `Uploading ${dist} (${totalFiles} files)... 0s`
4702
- ).start();
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) {
4710
+ }
4711
+ });
4712
+ const smartProgress = new SmartProgressBar(
4713
+ dist,
4714
+ totalFiles,
4715
+ totalSize,
4716
+ spinner
4717
+ );
4703
4718
  const timeInterval = setInterval(() => {
4704
- const elapsed = Math.floor((Date.now() - startTime) / 1e3);
4705
- const progressBar = createProgressBar(elapsed, Math.max(elapsed + 1, 30));
4706
- const duration = formatDuration(elapsed);
4707
- spinner.text = `Uploading ${dist} (${totalFiles} files) ${progressBar} ${duration}`;
4719
+ smartProgress.updateTime();
4708
4720
  }, 1e3);
4721
+ const progressInterval = setInterval(() => {
4722
+ smartProgress.updateProgress();
4723
+ }, 200);
4709
4724
  try {
4725
+ smartProgress.startUpload();
4710
4726
  const response = await axios_default.post(
4711
4727
  `${ipfsApiUrl}/add?uid=${deviceId}&cidV=1`,
4712
4728
  formData,
@@ -4718,22 +4734,23 @@ async function uploadDirectory(directoryPath, deviceId) {
4718
4734
  // 30 minutes timeout
4719
4735
  }
4720
4736
  );
4721
- clearInterval(timeInterval);
4737
+ clearInterval(progressInterval);
4738
+ smartProgress.startPolling();
4722
4739
  const { trace_id } = response.data.data;
4723
4740
  if (!trace_id) {
4724
- spinner.fail("No request id received from server");
4741
+ smartProgress.fail("No request id received from server");
4742
+ clearInterval(timeInterval);
4725
4743
  return null;
4726
4744
  }
4727
- spinner.text = `Upload initiated, waiting for completion... (request id: ${trace_id})`;
4728
- console.log(import_chalk2.default.blue(`
4729
- \u{1F50D} REQUEST ID: ${trace_id}`));
4745
+ smartProgress.updateDisplay();
4730
4746
  const uploadResult = await pollUploadStatus(
4731
4747
  trace_id,
4732
4748
  deviceId,
4733
- spinner,
4749
+ smartProgress,
4734
4750
  startTime
4735
4751
  );
4736
4752
  if (!uploadResult) {
4753
+ clearInterval(timeInterval);
4737
4754
  return null;
4738
4755
  }
4739
4756
  const directoryItem = uploadResult.upload_rst;
@@ -4750,6 +4767,7 @@ async function uploadDirectory(directoryPath, deviceId) {
4750
4767
  shortUrl: directoryItem.ShortUrl || null
4751
4768
  };
4752
4769
  saveUploadHistory(uploadData);
4770
+ clearInterval(timeInterval);
4753
4771
  return {
4754
4772
  hash: directoryItem.Hash,
4755
4773
  shortUrl: directoryItem.ShortUrl
@@ -4760,7 +4778,7 @@ async function uploadDirectory(directoryPath, deviceId) {
4760
4778
  uploadResult.upload_rst,
4761
4779
  dist
4762
4780
  );
4763
- spinner.fail(`Directory hash not found in response`);
4781
+ smartProgress.fail("Directory hash not found in response");
4764
4782
  console.log(
4765
4783
  import_chalk2.default.red(
4766
4784
  `
@@ -4773,19 +4791,23 @@ async function uploadDirectory(directoryPath, deviceId) {
4773
4791
  console.log(import_chalk2.default.blue(`
4774
4792
  \u{1F527} Solutions:`));
4775
4793
  console.log(
4776
- import_chalk2.default.gray(
4777
- ` 1. Ensure directory is not empty and contains valid files`
4778
- )
4794
+ import_chalk2.default.gray(` 1. Ensure directory is not empty and contains valid files`)
4779
4795
  );
4780
4796
  console.log(import_chalk2.default.gray(` 2. Check network connection stability`));
4781
4797
  console.log(
4782
4798
  import_chalk2.default.gray(` 3. Try uploading a smaller directory for testing`)
4783
4799
  );
4800
+ clearInterval(timeInterval);
4801
+ return null;
4784
4802
  } catch (error) {
4803
+ clearInterval(progressInterval);
4785
4804
  clearInterval(timeInterval);
4786
4805
  if (error.message && error.message.includes("multipart")) {
4787
- const errorMessage = handleMultipartError(error, `Directory upload: ${dist}`);
4788
- spinner.fail(errorMessage);
4806
+ const errorMessage = handleMultipartError(
4807
+ error,
4808
+ `Directory upload: ${dist}`
4809
+ );
4810
+ smartProgress.fail(errorMessage);
4789
4811
  console.log(import_chalk2.default.red(`
4790
4812
  \u274C ${errorMessage}`));
4791
4813
  return null;
@@ -4793,14 +4815,16 @@ async function uploadDirectory(directoryPath, deviceId) {
4793
4815
  if (error.response && error.response.data && error.response.data.code) {
4794
4816
  const errorCode = error.response.data.code.toString();
4795
4817
  if (ERROR_CODES[errorCode]) {
4796
- spinner.fail(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`);
4818
+ smartProgress.fail(
4819
+ `Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`
4820
+ );
4797
4821
  console.log(
4798
4822
  import_chalk2.default.red(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`)
4799
4823
  );
4800
4824
  return null;
4801
4825
  }
4802
4826
  }
4803
- spinner.fail(`Error: ${error.message}`);
4827
+ smartProgress.fail(`Error: ${error.message}`);
4804
4828
  console.log(import_chalk2.default.red(`Error: ${error.message}`));
4805
4829
  return null;
4806
4830
  }
@@ -4822,15 +4846,30 @@ async function uploadFile(filePath, deviceId) {
4822
4846
  if (!fileStats.isFile()) {
4823
4847
  throw new Error(`Path is not a file: ${filePath}`);
4824
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
+ `));
4825
4856
  const startTime = Date.now();
4826
- const spinner = (0, import_ora.default)(`Uploading ${fileName}... 0s`).start();
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);
4827
4865
  const timeInterval = setInterval(() => {
4828
- const elapsed = Math.floor((Date.now() - startTime) / 1e3);
4829
- const progressBar = createProgressBar(elapsed, Math.max(elapsed + 1, 20));
4830
- const duration = formatDuration(elapsed);
4831
- spinner.text = `Uploading ${fileName} ${progressBar} ${duration}`;
4866
+ smartProgress.updateTime();
4832
4867
  }, 1e3);
4868
+ const progressInterval = setInterval(() => {
4869
+ smartProgress.updateProgress();
4870
+ }, 200);
4833
4871
  try {
4872
+ smartProgress.startUpload();
4834
4873
  const formData = new import_form_data2.default();
4835
4874
  const encodedFileName = encodeURIComponent(fileName);
4836
4875
  formData.append("file", import_fs_extra3.default.createReadStream(filePath), {
@@ -4847,22 +4886,23 @@ async function uploadFile(filePath, deviceId) {
4847
4886
  // 30 minutes timeout
4848
4887
  }
4849
4888
  );
4850
- clearInterval(timeInterval);
4889
+ clearInterval(progressInterval);
4890
+ smartProgress.startPolling();
4851
4891
  const trace_id = response.data.data.trace_id;
4852
4892
  if (!trace_id) {
4853
- spinner.fail("No request id received from server");
4893
+ smartProgress.fail("No request id received from server");
4894
+ clearInterval(timeInterval);
4854
4895
  return null;
4855
4896
  }
4856
- spinner.text = `Upload initiated, waiting for completion... (request id: ${trace_id})`;
4857
- console.log(import_chalk2.default.blue(`
4858
- \u{1F50D} REQUEST ID: ${trace_id}`));
4897
+ smartProgress.updateDisplay();
4859
4898
  const uploadResult = await pollUploadStatus(
4860
4899
  trace_id,
4861
4900
  deviceId,
4862
- spinner,
4901
+ smartProgress,
4863
4902
  startTime
4864
4903
  );
4865
4904
  if (!uploadResult) {
4905
+ clearInterval(timeInterval);
4866
4906
  return null;
4867
4907
  }
4868
4908
  const fileItem = uploadResult.upload_rst;
@@ -4878,12 +4918,14 @@ async function uploadFile(filePath, deviceId) {
4878
4918
  shortUrl: fileItem.ShortUrl || null
4879
4919
  };
4880
4920
  saveUploadHistory(uploadData);
4921
+ smartProgress.complete(trace_id);
4922
+ clearInterval(timeInterval);
4881
4923
  return {
4882
4924
  hash: fileItem.Hash,
4883
4925
  shortUrl: fileItem.ShortUrl
4884
4926
  };
4885
4927
  }
4886
- spinner.fail(`File hash not found in response`);
4928
+ smartProgress.fail("File hash not found in response");
4887
4929
  console.log(
4888
4930
  import_chalk2.default.red(`
4889
4931
  \u274C File upload failed: File hash not found in response`)
@@ -4892,20 +4934,24 @@ async function uploadFile(filePath, deviceId) {
4892
4934
  \u{1F4CB} Error diagnosis information:`));
4893
4935
  console.log(import_chalk2.default.gray(` - File name: ${fileName}`));
4894
4936
  console.log(
4895
- import_chalk2.default.gray(
4896
- ` - Name returned by IPFS: ${uploadResult.upload_rst.Name}`
4897
- )
4937
+ import_chalk2.default.gray(` - Name returned by IPFS: ${uploadResult.upload_rst.Name}`)
4898
4938
  );
4899
4939
  console.log(import_chalk2.default.blue(`
4900
4940
  \u{1F527} Solutions:`));
4901
4941
  console.log(import_chalk2.default.gray(` 1. Check if file is corrupted or unreadable`));
4902
4942
  console.log(import_chalk2.default.gray(` 2. Check network connection stability`));
4903
4943
  console.log(import_chalk2.default.gray(` 3. Try uploading a smaller file for testing`));
4944
+ clearInterval(timeInterval);
4945
+ return null;
4904
4946
  } catch (error) {
4947
+ clearInterval(progressInterval);
4905
4948
  clearInterval(timeInterval);
4906
4949
  if (error.message && error.message.includes("multipart")) {
4907
- const errorMessage = handleMultipartError(error, `File upload: ${fileName}`);
4908
- spinner.fail(errorMessage);
4950
+ const errorMessage = handleMultipartError(
4951
+ error,
4952
+ `File upload: ${fileName}`
4953
+ );
4954
+ smartProgress.fail(errorMessage);
4909
4955
  console.log(import_chalk2.default.red(`
4910
4956
  \u274C ${errorMessage}`));
4911
4957
  return null;
@@ -4913,40 +4959,186 @@ async function uploadFile(filePath, deviceId) {
4913
4959
  if (error.response && error.response.data && error.response.data.code) {
4914
4960
  const errorCode = error.response.data.code.toString();
4915
4961
  if (ERROR_CODES[errorCode]) {
4916
- spinner.fail(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`);
4962
+ smartProgress.fail(
4963
+ `Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`
4964
+ );
4917
4965
  console.log(
4918
4966
  import_chalk2.default.red(`Error: ${ERROR_CODES[errorCode]} (Code: ${errorCode})`)
4919
4967
  );
4920
4968
  return null;
4921
4969
  }
4922
4970
  }
4923
- spinner.fail(`Error: ${error.message}`);
4971
+ smartProgress.fail(`Error: ${error.message}`);
4924
4972
  console.log(import_chalk2.default.red(`Error: ${error.message}`));
4925
4973
  return null;
4926
4974
  }
4927
4975
  }
4928
- function createProgressBar(current, total, width = 20) {
4929
- const percentage = Math.min(current / total, 1);
4930
- const filledWidth = Math.round(width * percentage);
4931
- const emptyWidth = width - filledWidth;
4932
- const filled = "\u2588".repeat(filledWidth);
4933
- const empty = "\u2591".repeat(emptyWidth);
4934
- return `[${filled}${empty}] ${Math.round(percentage * 100)}%`;
4935
- }
4936
- function formatDuration(seconds) {
4937
- if (seconds < 60) {
4938
- return `${seconds}s`;
4939
- } else if (seconds < 3600) {
4940
- const minutes = Math.floor(seconds / 60);
4941
- const remainingSeconds = seconds % 60;
4942
- return `${minutes}m ${remainingSeconds}s`;
4943
- } else {
4944
- const hours = Math.floor(seconds / 3600);
4945
- const minutes = Math.floor(seconds % 3600 / 60);
4946
- const remainingSeconds = seconds % 60;
4947
- return `${hours}h ${minutes}m ${remainingSeconds}s`;
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) {
5029
+ return;
5030
+ }
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";
5042
+ }
5043
+ const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
5044
+ this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
4948
5045
  }
4949
- }
5046
+ // Update time display only (called every second)
5047
+ updateTime() {
5048
+ if (this.isCompleted) {
5049
+ return;
5050
+ }
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";
5062
+ }
5063
+ const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
5064
+ this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
5065
+ }
5066
+ // Update progress bar only (called every 200ms)
5067
+ updateProgress() {
5068
+ if (this.isCompleted) {
5069
+ return;
5070
+ }
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";
5082
+ }
5083
+ const fileInfo = this.fileCount > 1 ? `${this.fileName} (${this.fileCount} files)` : this.fileName;
5084
+ this.spinner.text = `Uploading ${fileInfo} ${progressBar} ${duration} (${status})`;
5085
+ }
5086
+ // Update display (for manual updates)
5087
+ updateDisplay() {
5088
+ this.updateTime();
5089
+ }
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}`;
5095
+ }
5096
+ // Complete progress
5097
+ complete(traceId) {
5098
+ if (this.isCompleted) {
5099
+ return;
5100
+ }
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;
5111
+ }
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;
5116
+ }
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`;
5139
+ }
5140
+ }
5141
+ };
4950
5142
  async function uploadToIpfs_default(filePath) {
4951
5143
  const deviceId = getDeviceId();
4952
5144
  if (!deviceId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinme",
3
- "version": "1.1.1-alpha.1",
3
+ "version": "1.1.1-alpha.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },