@saidulbadhon/jssm-cli 1.6.7 → 1.7.0

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 +164 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4559,9 +4559,28 @@ Upload to ${projectName}?`,
4559
4559
  }
4560
4560
 
4561
4561
  // src/commands/pull.ts
4562
- import { writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
4562
+ import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile4 } from "fs/promises";
4563
4563
  import { join as join4, dirname } from "path";
4564
4564
  import { existsSync as existsSync2 } from "fs";
4565
+ function calculateLineDiff(oldContent, newContent) {
4566
+ if (!oldContent) {
4567
+ const lines = newContent.split("\n");
4568
+ const nonEmptyLines = lines.filter((line) => line.trim().length > 0).length;
4569
+ return { changedLines: nonEmptyLines, isNewFile: true };
4570
+ }
4571
+ const oldLines = oldContent.split("\n");
4572
+ const newLines = newContent.split("\n");
4573
+ const maxLength = Math.max(oldLines.length, newLines.length);
4574
+ let changedLines = 0;
4575
+ for (let i = 0; i < maxLength; i++) {
4576
+ const oldLine = i < oldLines.length ? oldLines[i] : "";
4577
+ const newLine = i < newLines.length ? newLines[i] : "";
4578
+ if (oldLine !== newLine) {
4579
+ changedLines++;
4580
+ }
4581
+ }
4582
+ return { changedLines, isNewFile: false };
4583
+ }
4565
4584
  async function pullCommand2(args2) {
4566
4585
  const flags = {};
4567
4586
  let pullAll = false;
@@ -4618,13 +4637,28 @@ async function pullCommand2(args2) {
4618
4637
  project,
4619
4638
  output
4620
4639
  );
4640
+ let existingContent = null;
4641
+ if (existsSync2(outputPath)) {
4642
+ try {
4643
+ existingContent = await readFile4(outputPath, "utf-8");
4644
+ } catch {
4645
+ existingContent = null;
4646
+ }
4647
+ }
4648
+ const { changedLines, isNewFile } = calculateLineDiff(
4649
+ existingContent,
4650
+ content
4651
+ );
4621
4652
  const dir = dirname(outputPath);
4622
4653
  if (dir !== process.cwd()) {
4623
4654
  await mkdir3(dir, { recursive: true });
4624
4655
  }
4625
4656
  await writeFile3(outputPath, content, "utf-8");
4626
4657
  const varCount = countVariables(content);
4627
- console.log(`\u2705 Wrote ${output} (${varCount} variables)`);
4658
+ const statusText = isNewFile ? "Created" : "Updated";
4659
+ console.log(
4660
+ `\u2705 ${statusText} ${output} (${varCount} variables, ${changedLines} line${changedLines !== 1 ? "s" : ""} changed)`
4661
+ );
4628
4662
  return;
4629
4663
  }
4630
4664
  console.log(`\u{1F4E5} Checking available files in ${project}...`);
@@ -4725,6 +4759,9 @@ async function pullCommand2(args2) {
4725
4759
  }
4726
4760
  let successCount = 0;
4727
4761
  let failCount = 0;
4762
+ let updatedFilesCount = 0;
4763
+ let newFilesCount = 0;
4764
+ let totalChangedLines = 0;
4728
4765
  for (const filename of selectedFiles) {
4729
4766
  try {
4730
4767
  const outputPath = join4(process.cwd(), filename);
@@ -4734,16 +4771,40 @@ async function pullCommand2(args2) {
4734
4771
  project,
4735
4772
  filename
4736
4773
  );
4774
+ let existingContent = null;
4775
+ if (existsSync2(outputPath)) {
4776
+ try {
4777
+ existingContent = await readFile4(outputPath, "utf-8");
4778
+ } catch {
4779
+ existingContent = null;
4780
+ }
4781
+ }
4782
+ const { changedLines, isNewFile } = calculateLineDiff(
4783
+ existingContent,
4784
+ content
4785
+ );
4737
4786
  const dir = dirname(outputPath);
4738
4787
  if (dir !== process.cwd()) {
4739
4788
  await mkdir3(dir, { recursive: true });
4740
4789
  }
4741
4790
  await writeFile3(outputPath, content, "utf-8");
4742
4791
  const varCount = countVariables(content);
4792
+ if (isNewFile) {
4793
+ newFilesCount++;
4794
+ } else {
4795
+ updatedFilesCount++;
4796
+ }
4797
+ totalChangedLines += changedLines;
4743
4798
  if (selectedFiles.length === 1) {
4744
- console.log(`\u2705 Wrote ${filename} (${varCount} variables)`);
4799
+ const statusText = isNewFile ? "Created" : "Updated";
4800
+ console.log(
4801
+ `\u2705 ${statusText} ${filename} (${varCount} variables, ${changedLines} line${changedLines !== 1 ? "s" : ""} changed)`
4802
+ );
4745
4803
  } else {
4746
- console.log(`\u2705 ${filename}: Pulled (${varCount} variables)`);
4804
+ const statusText = isNewFile ? "Created" : "Updated";
4805
+ console.log(
4806
+ `\u2705 ${filename}: ${statusText} (${varCount} variables, ${changedLines} line${changedLines !== 1 ? "s" : ""} changed)`
4807
+ );
4747
4808
  }
4748
4809
  successCount++;
4749
4810
  } catch (error) {
@@ -4758,9 +4819,29 @@ async function pullCommand2(args2) {
4758
4819
  if (successCount > 0) {
4759
4820
  console.log(` \u2705 Success: ${successCount} file(s)`);
4760
4821
  }
4822
+ if (newFilesCount > 0) {
4823
+ console.log(` \u{1F4C4} New files: ${newFilesCount}`);
4824
+ }
4825
+ if (updatedFilesCount > 0) {
4826
+ console.log(` \u{1F4DD} Updated files: ${updatedFilesCount}`);
4827
+ }
4828
+ if (totalChangedLines > 0) {
4829
+ console.log(` \u{1F4CF} Total lines changed: ${totalChangedLines}`);
4830
+ }
4761
4831
  if (failCount > 0) {
4762
4832
  console.log(` \u274C Failed: ${failCount} file(s)`);
4763
4833
  }
4834
+ } else if (successCount === 1) {
4835
+ if (newFilesCount > 0) {
4836
+ console.log(`
4837
+ \u{1F4CA} Summary: New file created`);
4838
+ } else if (updatedFilesCount > 0) {
4839
+ console.log(`
4840
+ \u{1F4CA} Summary: File updated`);
4841
+ }
4842
+ if (totalChangedLines > 0) {
4843
+ console.log(` \u{1F4CF} Lines changed: ${totalChangedLines}`);
4844
+ }
4764
4845
  }
4765
4846
  if (failCount > 0 && successCount === 0) {
4766
4847
  process.exit(1);
@@ -4779,8 +4860,27 @@ function countVariables(content) {
4779
4860
  }
4780
4861
 
4781
4862
  // src/commands/push.ts
4782
- import { readFile as readFile4 } from "fs/promises";
4863
+ import { readFile as readFile5 } from "fs/promises";
4783
4864
  import { join as join5 } from "path";
4865
+ function calculateLineDiff2(oldContent, newContent) {
4866
+ if (!oldContent) {
4867
+ const lines = newContent.split("\n");
4868
+ const nonEmptyLines = lines.filter((line) => line.trim().length > 0).length;
4869
+ return { changedLines: nonEmptyLines, isNewFile: true };
4870
+ }
4871
+ const oldLines = oldContent.split("\n");
4872
+ const newLines = newContent.split("\n");
4873
+ const maxLength = Math.max(oldLines.length, newLines.length);
4874
+ let changedLines = 0;
4875
+ for (let i = 0; i < maxLength; i++) {
4876
+ const oldLine = i < oldLines.length ? oldLines[i] : "";
4877
+ const newLine = i < newLines.length ? newLines[i] : "";
4878
+ if (oldLine !== newLine) {
4879
+ changedLines++;
4880
+ }
4881
+ }
4882
+ return { changedLines, isNewFile: false };
4883
+ }
4784
4884
  async function pushCommand2(args2) {
4785
4885
  const flags = {};
4786
4886
  for (let i = 0; i < args2.length; i++) {
@@ -4889,12 +4989,15 @@ async function pushCommand2(args2) {
4889
4989
  }
4890
4990
  let successCount = 0;
4891
4991
  let failCount = 0;
4992
+ let updatedFilesCount = 0;
4993
+ let newFilesCount = 0;
4994
+ let totalChangedLines = 0;
4892
4995
  for (const file of selectedFiles) {
4893
4996
  let fileContent = "";
4894
4997
  let fileSize = 0;
4895
4998
  try {
4896
4999
  const inputPath = join5(process.cwd(), file);
4897
- fileContent = await readFile4(inputPath, "utf-8");
5000
+ fileContent = await readFile5(inputPath, "utf-8");
4898
5001
  fileSize = Buffer.byteLength(fileContent, "utf-8");
4899
5002
  const variables = parseVariables(fileContent, file);
4900
5003
  if (variables.length === 0) {
@@ -4920,6 +5023,21 @@ async function pushCommand2(args2) {
4920
5023
  failCount++;
4921
5024
  continue;
4922
5025
  }
5026
+ let existingContent = null;
5027
+ try {
5028
+ existingContent = await pullEnvFile(
5029
+ config.host,
5030
+ config.authToken,
5031
+ project,
5032
+ file
5033
+ );
5034
+ } catch {
5035
+ existingContent = null;
5036
+ }
5037
+ const { changedLines, isNewFile } = calculateLineDiff2(
5038
+ existingContent,
5039
+ fileContent
5040
+ );
4923
5041
  const result = await pushEnvFile(
4924
5042
  config.host,
4925
5043
  config.authToken,
@@ -4929,19 +5047,35 @@ async function pushCommand2(args2) {
4929
5047
  // Use full relative path, not just filename
4930
5048
  );
4931
5049
  const tagInfo = result.environmentTag ? ` [${result.environmentTag}${result.tagSource === "auto" ? " auto" : ""}]` : "";
5050
+ if (isNewFile) {
5051
+ newFilesCount++;
5052
+ } else {
5053
+ updatedFilesCount++;
5054
+ }
5055
+ totalChangedLines += changedLines;
4932
5056
  if (selectedFiles.length === 1) {
5057
+ const statusText = isNewFile ? "Created" : "Updated";
4933
5058
  console.log(
4934
- `\u2705 Pushed ${file} (${variables.length} variables) to ${project}${tagInfo}`
5059
+ `\u2705 ${statusText} ${file} (${variables.length} variables, ${changedLines} line${changedLines !== 1 ? "s" : ""} changed) to ${project}${tagInfo}`
4935
5060
  );
4936
5061
  } else {
5062
+ const statusText = isNewFile ? "Created" : "Updated";
4937
5063
  console.log(
4938
- `\u2705 ${file}: Pushed (${variables.length} variables)${tagInfo}`
5064
+ `\u2705 ${file}: ${statusText} (${variables.length} variables, ${changedLines} line${changedLines !== 1 ? "s" : ""} changed)${tagInfo}`
4939
5065
  );
4940
5066
  }
4941
5067
  successCount++;
4942
5068
  } catch (error) {
4943
5069
  const message = error instanceof Error ? error.message : String(error);
4944
- console.error(`\u274C ${file}: Failed to push - ${message}`);
5070
+ let helpText = "";
5071
+ if (message.includes("Project") && message.includes("not found")) {
5072
+ helpText = `
5073
+ \u{1F4A1} Hint: Make sure the project '${project}' exists. You can create it with: jssm init -p ${project}`;
5074
+ } else if (message.includes("Insufficient permissions")) {
5075
+ helpText = `
5076
+ \u{1F4A1} Hint: You don't have write access to project '${project}'`;
5077
+ }
5078
+ console.error(`\u274C ${file}: Failed to push - ${message}${helpText}`);
4945
5079
  failCount++;
4946
5080
  }
4947
5081
  }
@@ -4949,9 +5083,29 @@ async function pushCommand2(args2) {
4949
5083
  console.log(`
4950
5084
  \u{1F4CA} Summary:`);
4951
5085
  console.log(` \u2705 Success: ${successCount} file(s)`);
5086
+ if (newFilesCount > 0) {
5087
+ console.log(` \u{1F4C4} New files: ${newFilesCount}`);
5088
+ }
5089
+ if (updatedFilesCount > 0) {
5090
+ console.log(` \u{1F4DD} Updated files: ${updatedFilesCount}`);
5091
+ }
5092
+ if (totalChangedLines > 0) {
5093
+ console.log(` \u{1F4CF} Total lines changed: ${totalChangedLines}`);
5094
+ }
4952
5095
  if (failCount > 0) {
4953
5096
  console.log(` \u274C Failed: ${failCount} file(s)`);
4954
5097
  }
5098
+ } else if (successCount === 1) {
5099
+ if (newFilesCount > 0) {
5100
+ console.log(`
5101
+ \u{1F4CA} Summary: New file created`);
5102
+ } else if (updatedFilesCount > 0) {
5103
+ console.log(`
5104
+ \u{1F4CA} Summary: File updated`);
5105
+ }
5106
+ if (totalChangedLines > 0) {
5107
+ console.log(` \u{1F4CF} Lines changed: ${totalChangedLines}`);
5108
+ }
4955
5109
  }
4956
5110
  if (failCount > 0) {
4957
5111
  process.exit(1);
@@ -5876,7 +6030,7 @@ ${import_chalk.default.bold("Usage in Docker:")}
5876
6030
 
5877
6031
  // src/utils/versionCheck.ts
5878
6032
  var PACKAGE_NAME = "@saidulbadhon/jssm-cli";
5879
- var CURRENT_VERSION = "1.6.7";
6033
+ var CURRENT_VERSION = "1.7.0";
5880
6034
  async function getLatestVersion() {
5881
6035
  try {
5882
6036
  const response = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saidulbadhon/jssm-cli",
3
- "version": "1.6.7",
3
+ "version": "1.7.0",
4
4
  "private": false,
5
5
  "description": "CLI for JSSM - Simple environment variable manager",
6
6
  "author": "Saidul Badhon",