@saidulbadhon/jssm-cli 1.9.1 → 1.9.7

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 +84 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4179,6 +4179,13 @@ async function pushEnvFile(host, apiKey, project, content, filename = ".env") {
4179
4179
  body: JSON.stringify({ content, filename })
4180
4180
  });
4181
4181
  }
4182
+ async function deleteEnvFile(host, apiKey, project, filename) {
4183
+ const url = `${host}/projects/${encodeURIComponent(project)}/files/delete`;
4184
+ return apiRequest(url, apiKey, {
4185
+ method: "POST",
4186
+ body: JSON.stringify({ filename })
4187
+ });
4188
+ }
4182
4189
  async function pullEnvFile(host, apiKey, project, filename = ".env") {
4183
4190
  const url = `${host}/projects/${encodeURIComponent(project)}/files/pull?filename=${encodeURIComponent(
4184
4191
  filename
@@ -4886,6 +4893,9 @@ function calculateLineDiff2(oldContent, newContent) {
4886
4893
  }
4887
4894
  return { changedLines, isNewFile: false };
4888
4895
  }
4896
+ function normalizeFilePath(filePath) {
4897
+ return filePath.replace(/\\/g, "/");
4898
+ }
4889
4899
  async function pushCommand2(args2) {
4890
4900
  const flags = {};
4891
4901
  for (let i = 0; i < args2.length; i++) {
@@ -4924,15 +4934,19 @@ async function pushCommand2(args2) {
4924
4934
  console.log(` This directory is initialized for ${config.project}`);
4925
4935
  }
4926
4936
  let selectedFiles = [];
4937
+ let discoveredLocalFiles = [];
4938
+ let shouldPruneDeletedRemoteFiles = false;
4927
4939
  if (!inputFile) {
4928
4940
  const cwd = process.cwd();
4929
4941
  const envFiles = await findEnvFiles(cwd, searchDepth);
4942
+ discoveredLocalFiles = envFiles.map((f) => normalizeFilePath(f.relativePath));
4930
4943
  if (envFiles.length === 0) {
4931
4944
  console.error("\u274C No .env files found");
4932
4945
  console.error("\u{1F4A1} Create a .env file or specify one with --input <file>");
4933
4946
  process.exit(1);
4934
4947
  } else if (envFiles.length === 1) {
4935
- selectedFiles = [envFiles[0].relativePath];
4948
+ selectedFiles = [normalizeFilePath(envFiles[0].relativePath)];
4949
+ shouldPruneDeletedRemoteFiles = true;
4936
4950
  console.log(
4937
4951
  `\u{1F4C4} Found ${envFiles[0].relativePath} (${envFiles[0].variableCount} variables)`
4938
4952
  );
@@ -4959,7 +4973,8 @@ async function pushCommand2(args2) {
4959
4973
  ]
4960
4974
  });
4961
4975
  if (pushOption === "all") {
4962
- selectedFiles = envFiles.map((f) => f.relativePath);
4976
+ selectedFiles = discoveredLocalFiles;
4977
+ shouldPruneDeletedRemoteFiles = true;
4963
4978
  } else {
4964
4979
  const fileChoices = envFiles.map((file) => ({
4965
4980
  name: `${file.relativePath} (${file.variableCount} variables)`,
@@ -4976,11 +4991,11 @@ async function pushCommand2(args2) {
4976
4991
  return true;
4977
4992
  }
4978
4993
  });
4979
- selectedFiles = selected;
4994
+ selectedFiles = selected.map((file) => normalizeFilePath(file));
4980
4995
  }
4981
4996
  }
4982
4997
  } else {
4983
- selectedFiles = [inputFile];
4998
+ selectedFiles = [normalizeFilePath(inputFile)];
4984
4999
  }
4985
5000
  if (selectedFiles.length === 1) {
4986
5001
  console.log(`
@@ -4996,6 +5011,8 @@ async function pushCommand2(args2) {
4996
5011
  let failCount = 0;
4997
5012
  let updatedFilesCount = 0;
4998
5013
  let newFilesCount = 0;
5014
+ let deletedFilesCount = 0;
5015
+ let deletionEndpointUnavailable = false;
4999
5016
  let totalChangedLines = 0;
5000
5017
  for (const file of selectedFiles) {
5001
5018
  let fileContent = "";
@@ -5084,6 +5101,62 @@ async function pushCommand2(args2) {
5084
5101
  failCount++;
5085
5102
  }
5086
5103
  }
5104
+ if (shouldPruneDeletedRemoteFiles && failCount === 0) {
5105
+ try {
5106
+ const remoteFiles = (await listEnvFiles(
5107
+ config.host,
5108
+ config.authToken,
5109
+ project
5110
+ )).map((file) => normalizeFilePath(file)).filter((value, index, self) => self.indexOf(value) === index);
5111
+ const localFilesSet = new Set(discoveredLocalFiles);
5112
+ const remoteFilesToDelete = remoteFiles.filter(
5113
+ (remoteFile) => !localFilesSet.has(remoteFile)
5114
+ );
5115
+ if (remoteFilesToDelete.length > 0) {
5116
+ console.log(
5117
+ `
5118
+ \u{1F9F9} Syncing deletions: ${remoteFilesToDelete.length} remote file(s) no longer exist locally`
5119
+ );
5120
+ for (const remoteFile of remoteFilesToDelete) {
5121
+ try {
5122
+ const result = await deleteEnvFile(
5123
+ config.host,
5124
+ config.authToken,
5125
+ project,
5126
+ remoteFile
5127
+ );
5128
+ if (result.deleted) {
5129
+ deletedFilesCount++;
5130
+ console.log(`\u{1F5D1}\uFE0F Deleted ${remoteFile} from ${project}`);
5131
+ } else {
5132
+ console.log(`\u2139\uFE0F ${remoteFile} was already absent on server`);
5133
+ }
5134
+ } catch (error) {
5135
+ const message = error instanceof Error ? error.message : String(error);
5136
+ if (message.includes("HTTP 404")) {
5137
+ if (!deletionEndpointUnavailable) {
5138
+ console.error(
5139
+ "\u274C Deletion sync is not supported by this server (missing /files/delete endpoint)."
5140
+ );
5141
+ console.error(
5142
+ " \u{1F4A1} Upgrade/redeploy the backend with the latest files route changes, then run jssm push again."
5143
+ );
5144
+ deletionEndpointUnavailable = true;
5145
+ failCount++;
5146
+ }
5147
+ break;
5148
+ }
5149
+ console.error(`\u274C ${remoteFile}: Failed to delete - ${message}`);
5150
+ failCount++;
5151
+ }
5152
+ }
5153
+ }
5154
+ } catch (error) {
5155
+ const message = error instanceof Error ? error.message : String(error);
5156
+ console.error(`\u274C Failed to check remote files for deletion sync: ${message}`);
5157
+ failCount++;
5158
+ }
5159
+ }
5087
5160
  if (selectedFiles.length > 1) {
5088
5161
  console.log(`
5089
5162
  \u{1F4CA} Summary:`);
@@ -5094,6 +5167,9 @@ async function pushCommand2(args2) {
5094
5167
  if (updatedFilesCount > 0) {
5095
5168
  console.log(` \u{1F4DD} Updated files: ${updatedFilesCount}`);
5096
5169
  }
5170
+ if (deletedFilesCount > 0) {
5171
+ console.log(` \u{1F5D1}\uFE0F Deleted files: ${deletedFilesCount}`);
5172
+ }
5097
5173
  if (totalChangedLines > 0) {
5098
5174
  console.log(` \u{1F4CF} Total lines changed: ${totalChangedLines}`);
5099
5175
  }
@@ -5111,6 +5187,9 @@ async function pushCommand2(args2) {
5111
5187
  if (totalChangedLines > 0) {
5112
5188
  console.log(` \u{1F4CF} Lines changed: ${totalChangedLines}`);
5113
5189
  }
5190
+ if (deletedFilesCount > 0) {
5191
+ console.log(` \u{1F5D1}\uFE0F Remote files deleted: ${deletedFilesCount}`);
5192
+ }
5114
5193
  }
5115
5194
  if (failCount > 0) {
5116
5195
  process.exit(1);
@@ -5962,7 +6041,7 @@ ${import_chalk.default.bold("Usage in Docker:")}
5962
6041
 
5963
6042
  // src/utils/versionCheck.ts
5964
6043
  var PACKAGE_NAME = "@saidulbadhon/jssm-cli";
5965
- var CURRENT_VERSION = "1.9.1";
6044
+ var CURRENT_VERSION = "1.9.7";
5966
6045
  async function getLatestVersion() {
5967
6046
  try {
5968
6047
  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.9.1",
3
+ "version": "1.9.7",
4
4
  "private": false,
5
5
  "description": "CLI for JSSM - Simple environment variable manager",
6
6
  "author": "Saidul Badhon",