jvcs 1.0.3 → 1.0.5

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.
package/.env CHANGED
@@ -1,4 +1,4 @@
1
1
  CLIENT_ID=835069827989-3spob55ioa2ocudi3mo8u2ni2ecqohh7.apps.googleusercontent.com
2
2
  CLIENT_SECRET=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
3
3
  REDIRECT_URI=https://developers.google.com/oauthplayground
4
- REFRESH_TOKEN=1//04wJgrjHWoDOZCgYIARAAGAQSNwF-L9Iryvz_RHMDkqyYlK2wv9TiVMsvq1eghHFnbS868U-zraLb44f8dEPvpNjJEmex_IcMxUE
4
+ REFRESH_TOKEN=1//042t17dTnMbrPCgYIARAAGAQSNwF-L9IrbWfGtPAOApgx9It69gD94wHVEM8TS6K1qvBMSDNWXkzQclEdSkDBsG8CxYCfuyMeqGI
package/.jvcs/HEAD CHANGED
@@ -1 +1 @@
1
- 3a1169c8-ec67-4ce5-8024-ab4f08d7b609
1
+ f91ef83b-df7f-4137-9316-35928d9c46a3
@@ -0,0 +1,6 @@
1
+ {
2
+ "package.json": {
3
+ "hash": "2f5eb0e283834ec948f58da8a51c95ee26505ba837ffe753b65de239e8504524",
4
+ "time": "2025-10-28T18:48:37.576Z"
5
+ }
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "author": "jagdish",
3
+ "id": "f91ef83b-df7f-4137-9316-35928d9c46a3",
4
+ "message": "m1",
5
+ "timeStamp": "2025-10-28T18:48:45.420Z",
6
+ "parentId": null
7
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "jvcs",
3
+ "version": "1.0.4",
4
+ "bin": {
5
+ "jvcs": "./index.js"
6
+ },
7
+ "keywords": [],
8
+ "author": "",
9
+ "license": "ISC",
10
+ "dependencies": {
11
+ "chalk": "^4.1.2",
12
+ "crypto": "^1.0.1",
13
+ "dotenv": "^17.2.3",
14
+ "googleapis": "^164.1.0",
15
+ "inquirer": "^8.2.7",
16
+ "uuid": "^13.0.0",
17
+ "validator": "^13.15.20",
18
+ "yargs": "^18.0.0"
19
+ }
20
+ }
package/.jvcs/config.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "repoName": "backend2",
3
- "createdAt": "2025-10-27T17:03:18.444Z",
3
+ "createdAt": "2025-10-28T18:48:26.816Z",
4
4
  "remote": null,
5
5
  "owner": {
6
6
  "username": "jagdish",
@@ -1,6 +1,6 @@
1
1
  {
2
- "index.js": {
3
- "hash": "ba4b020c3a1b7cd4e9bb5d8ea1979236ced22891fff322dc38c567917a04eb03",
4
- "time": "2025-10-27T17:03:25.838Z"
2
+ "package.json": {
3
+ "hash": "2f5eb0e283834ec948f58da8a51c95ee26505ba837ffe753b65de239e8504524",
4
+ "time": "2025-10-28T18:48:37.576Z"
5
5
  }
6
6
  }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "jvcs",
3
+ "version": "1.0.4",
4
+ "bin": {
5
+ "jvcs": "./index.js"
6
+ },
7
+ "keywords": [],
8
+ "author": "",
9
+ "license": "ISC",
10
+ "dependencies": {
11
+ "chalk": "^4.1.2",
12
+ "crypto": "^1.0.1",
13
+ "dotenv": "^17.2.3",
14
+ "googleapis": "^164.1.0",
15
+ "inquirer": "^8.2.7",
16
+ "uuid": "^13.0.0",
17
+ "validator": "^13.15.20",
18
+ "yargs": "^18.0.0"
19
+ }
20
+ }
@@ -0,0 +1,31 @@
1
+ const chalk = require("chalk")
2
+
3
+ async function handleDbForRepo(reponame,driveId,parentId,Content,token) {
4
+
5
+ try {
6
+
7
+ const response = await fetch("http://localhost:3000/createCLIRepo", {
8
+ method: "POST",
9
+ headers: {
10
+ 'Content-Type': "application/json"
11
+ },
12
+ body: JSON.stringify({reponame,driveId,parentId,content:Content,token})
13
+ })
14
+
15
+ const result = await response.json()
16
+ if(!result.status) {
17
+ console.log(chalk.red(`Server Error: ${result.message || "Unknown error"}`));
18
+ return;
19
+ }
20
+
21
+ console.log(chalk.bold.green(`${result.message}`));
22
+
23
+ }
24
+ catch(error) {
25
+ console.log(chalk.red("Failed to contact backend server."));
26
+ console.log(chalk.red(error.message))
27
+ }
28
+
29
+ }
30
+
31
+ module.exports = handleDbForRepo
@@ -15,11 +15,13 @@ const oauth2client = new google.auth.OAuth2(
15
15
  REDIRECT_URI
16
16
  );
17
17
 
18
+
19
+ // hello
18
20
  oauth2client.setCredentials({ refresh_token: REFRESH_TOKEN });
19
21
 
20
22
  const drive = google.drive({
21
23
  version: 'v3',
22
24
  auth: oauth2client
23
25
  });
24
-
26
+ //hello
25
27
  module.exports = { drive };
@@ -75,7 +75,7 @@ async function addCmd(paths) {
75
75
  let targets = []
76
76
  if(paths.length === 1 && paths[0] === ".") {
77
77
  targets = await fs.readdir(process.cwd(),{withFileTypes: true})
78
- targets = targets.filter((target)=> target.name !== ".jvcs").map((item)=> path.resolve(process.cwd(),item.name))
78
+ targets = targets.filter((target)=> target.name !== ".jvcs" && target.name !== "node_modules").map((item)=> path.resolve(process.cwd(),item.name))
79
79
  }
80
80
  else {
81
81
  targets = paths.map((p)=> path.resolve(process.cwd(),p))
@@ -2,7 +2,6 @@ const { drive } = require("../config/drive-config");
2
2
 
3
3
  async function getDirectoryStructure(username,reponame,commitId) {
4
4
 
5
-
6
5
  async function findOrCreateFolder(name,parentId=null) {
7
6
 
8
7
  const query = [
@@ -45,10 +44,10 @@ async function getDirectoryStructure(username,reponame,commitId) {
45
44
  const commitFolder = await findOrCreateFolder(commitFolderName,repoFolder.id)
46
45
 
47
46
  return {
48
- githubClone: githubClone.id,
49
- userFolder: userFolder.id,
50
- repoFolder: repoFolder.id,
51
- commitFolder: commitFolder.id,
47
+ githubCloneId: githubClone.id,
48
+ userFolderId: userFolder.id,
49
+ repoFolderId: repoFolder.id,
50
+ commitFolderId: commitFolder.id,
52
51
  commitAlreadyExists: commitFolder.alreadyExists
53
52
  }
54
53
  }
@@ -4,8 +4,12 @@ const chalk = require("chalk")
4
4
  const { drive } = require("../config/drive-config")
5
5
  const { getGlobalConfig, checkGlobalConfig, checkforjvcs } = require("./utility")
6
6
  const getDirectoryStructure = require("./driveUtility")
7
+ const handleDbForRepo = require("../apicall/handleDbForRepo")
7
8
 
8
- async function uploadFile(localFile, parentId) {
9
+
10
+
11
+
12
+ async function uploadFile(localFile, parentId,data) {
9
13
 
10
14
  try {
11
15
 
@@ -27,6 +31,7 @@ async function uploadFile(localFile, parentId) {
27
31
  })
28
32
 
29
33
  console.log(chalk.gray(` ↳ Uploaded: ${fileName}`));
34
+ data.files.push({name:fileName,driveId:res.data.id,parentId:parentId,type:"file"})
30
35
  return res.data.id;
31
36
  }
32
37
  catch(error) {
@@ -34,7 +39,7 @@ async function uploadFile(localFile, parentId) {
34
39
  }
35
40
  }
36
41
 
37
- async function uploadDirectory(localDir, parentId) {
42
+ async function uploadDirectory(localDir, parentId,data) {
38
43
 
39
44
  const entries = fs.readdirSync(localDir, {withFileTypes: true})
40
45
 
@@ -54,10 +59,11 @@ async function uploadDirectory(localDir, parentId) {
54
59
  fields: "id"
55
60
  })
56
61
 
57
- await uploadDirectory(entryPath,folder.data.id)
62
+ data.files.push({name:entry.name,driveId:folder.data.id,parentId:parentId,type:"folder"})
63
+ await uploadDirectory(entryPath,folder.data.id,data)
58
64
  }
59
65
  else {
60
- await uploadFile(entryPath,parentId)
66
+ await uploadFile(entryPath,parentId,data)
61
67
  }
62
68
  }
63
69
  }
@@ -66,6 +72,8 @@ async function pushCmd() {
66
72
 
67
73
  try {
68
74
 
75
+ let userFolderId,repoFolderId
76
+
69
77
  if(!checkGlobalConfig()) {
70
78
  console.log(chalk.red("No existing session found. Please login or signup."))
71
79
  console.log(chalk.green("jvcs --help for help"))
@@ -103,9 +111,12 @@ async function pushCmd() {
103
111
  }
104
112
 
105
113
  console.log(chalk.blue("Pushing commits of ",reponame," to cloud storage..."))
106
-
114
+
115
+ const Content = []
107
116
  for(const commitId of commitFolders) {
108
-
117
+ let data = {}
118
+ data.files = []
119
+ data.uuid = commitId
109
120
  const commitFolder = path.join(commitDir,commitId)
110
121
  const metaPath = path.join(commitFolder,"meta.json")
111
122
 
@@ -123,18 +134,26 @@ async function pushCmd() {
123
134
  console.log(chalk.gray(` author: ${author}`));
124
135
  console.log(chalk.gray(` time: ${timeStamp}`));
125
136
 
126
- const { commitFolderId : driveCommitId , commitAlreadyExists } = await getDirectoryStructure(configData.username,reponame,commitId)
127
-
137
+ const folderStructure = await getDirectoryStructure(configData.username,reponame,commitId)
138
+ const driveCommitId = folderStructure.commitFolderId;
139
+ repoFolderId = folderStructure.repoFolderId;
140
+ userFolderId = folderStructure.userFolderId;
141
+ const commitAlreadyExists = folderStructure.commitAlreadyExists;
142
+
128
143
  if (commitAlreadyExists) {
129
144
  console.log(chalk.yellow(`Skipping ${commitId} (already uploaded)`));
130
145
  continue;
131
146
  }
132
147
 
133
- await uploadDirectory(commitFolder,driveCommitId)
148
+ await uploadDirectory(commitFolder,driveCommitId,data)
134
149
  console.log(chalk.green(`Commit ${commitId} uploaded successfully!`));
150
+ Content.push(data)
135
151
  }
136
152
 
137
153
  console.log(chalk.bold.green("\nAll commits pushed successfully!"));
154
+
155
+ // database call for creating/updating an repository
156
+ await handleDbForRepo(reponame,repoFolderId,userFolderId,Content,configData.token)
138
157
  }
139
158
  catch(error) {
140
159
  console.log(chalk.red.bold("\nPush Failed"));
@@ -0,0 +1,193 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const chalk = require("chalk");
4
+ const { checkGlobalConfig, getGlobalConfig, checkforjvcs } = require("./utility");
5
+ const drive = require("../config/drive-config")
6
+
7
+ function copyDir(targetCommitFolder) {
8
+
9
+ const cwd = process.cwd()
10
+ const entries = fs.readdirSync(targetCommitFolder, {recursive: true})
11
+
12
+ for(const entry of entries) {
13
+
14
+ const srcpath = path.join(targetCommitFolder,entry.name)
15
+ const destpath = path.join(cwd,entry.name)
16
+
17
+ if(entry.isDirectory()) {
18
+ fs.mkdirSync(destpath, { recursive: true });
19
+ copyDir(srcpath, destpath);
20
+ }
21
+ else {
22
+ fs.copyFileSync(srcpath, destpath);
23
+ }
24
+ }
25
+ }
26
+
27
+ function cleanCWD() {
28
+
29
+ const cwd = process.cwd()
30
+ const entries = fs.readdirSync(cwd, {withFileTypes: true})
31
+
32
+ for(const entry of entries) {
33
+ if(entry.name === ".jvcs") continue
34
+ const deleteEntry = path.join(cwd,entry.name)
35
+ fs.rmSync(deleteEntry, {recursive: true, force: true})
36
+ }
37
+ }
38
+
39
+ function getCommitsToDelete(commitFolder,currentCommit,targetCommit) {
40
+
41
+ let toDelete = []
42
+
43
+ while(currentCommit && currentCommit !== targetCommit) {
44
+
45
+ const commitPath = path.join(commitFolder,currentCommit)
46
+ const metaPath = path.join(commitPath,"meta.json")
47
+
48
+ if(!fs.existsSync(commitPath)) break
49
+ toDelete.push(currentCommit)
50
+
51
+ let parent = null
52
+ if(fs.existsSync(metaPath)) {
53
+ const data = JSON.parse(fs.readFileSync(metaPath,"utf-8"))
54
+ parent = data.parent || null
55
+ }
56
+
57
+ currentCommit = parent
58
+ }
59
+
60
+ return toDelete
61
+ }
62
+
63
+ function deleteLocalCommits(commitDir,Ids) {
64
+
65
+ for(const id of Ids) {
66
+ const p = path.join(commitDir,id)
67
+ fs.rmSync(p, {recursive: true, force: true})
68
+ console.log(chalk.red(`Deleted local commit ${id}`))
69
+ }
70
+ }
71
+
72
+ async function deleteCommitsFromDrive(ids) {
73
+
74
+ let folderName = null
75
+ try {
76
+ for(const id of ids) {
77
+ folderName = `commit_${id}`
78
+
79
+ const res = await drive.files.list({
80
+ q: `name=${folderName} and trashed=false`,
81
+ fields: "files(id,name)"
82
+ })
83
+
84
+ if(res.data.files.length > 0) {
85
+ const fileId = res.data.files[0].id;
86
+ await drive.files.delete({fileId})
87
+ console.log(chalk.red(`Deleted folder ${folderName} from remote`));
88
+ }
89
+ else {
90
+ console.log(chalk.gray(`Drive folder ${folderName} not found.`));
91
+ }
92
+ }
93
+ }
94
+ catch(error) {
95
+ console.log(chalk.red(`Failed to delete ${folderName} from remote: ${err.message}`));
96
+ }
97
+ }
98
+
99
+ async function deleteCommitsFromDatabase(configData,toDelete,reponame) {
100
+
101
+ try {
102
+
103
+ const response = await fetch("http://localhost:3000/deleteCommit", {
104
+ method: "POST",
105
+ headers: {
106
+ 'Content-Type': 'application/json'
107
+ },
108
+ body: JSON.stringify({token:configData.token,email:configData.email,username:configData.username,toDelete,reponame})
109
+ })
110
+
111
+ const data = await response.json()
112
+
113
+ if(data.status === true) {
114
+ console.log(chalk.green("Removed previous commits from DB"))
115
+ }
116
+ else {
117
+ console.log(chalk.red(data.message))
118
+ }
119
+ }
120
+ catch(error) {
121
+ console.log(chalk.red(error || error.message))
122
+ }
123
+ }
124
+
125
+ async function revertCmd(commitId) {
126
+
127
+ if(!checkGlobalConfig()) {
128
+ console.log(chalk.red("No existing session found. Please login or signup."));
129
+ console.log(chalk.green("jvcs --help for help"));
130
+ return;
131
+ }
132
+
133
+ const configData = getGlobalConfig();
134
+ if(!configData) {
135
+ console.log(chalk.red("No existing session found. Please login or signup."));
136
+ return;
137
+ }
138
+
139
+ if(!checkforjvcs()) {
140
+ console.log(chalk.red("Repository is not initialized or is deleted."));
141
+ return;
142
+ }
143
+
144
+ // actual implementation
145
+ const cwd = process.cwd()
146
+ const jvcsDir = path.join(cwd,".jvcs")
147
+ const commitFolder = path.join(jvcsDir,"commits")
148
+ const targetCommitFolder = path.join(commitFolder,commitId)
149
+ const headFile = path.join(jvcsDir,"HEAD")
150
+
151
+ if(!fs.existsSync(jvcsDir)) {
152
+ console.log(chalk.red("Repository is not initialized or is deleted."));
153
+ return;
154
+ }
155
+
156
+ if(!fs.existsSync(commitFolder)) {
157
+ console.log(chalk.red("You have made no commits yet. Revert not possible"))
158
+ return
159
+ }
160
+
161
+ if(!fs.existsSync(targetCommitFolder)) {
162
+ console.log(chalk.red("No commit exists with commit Id : ",commitId))
163
+ return
164
+ }
165
+
166
+
167
+ const currentHead = fs.readFileSync(headFile,"utf-8").trim()
168
+
169
+ if(currentHead === commitId) {
170
+ console.log(chalk.green("HEAD is already at the given commit"))
171
+ return
172
+ }
173
+
174
+ // get commits to delete
175
+ const toDelete = getCommitsToDelete(commitFolder,currentHead,commitId)
176
+
177
+ // clear the current working directory except .jvcs
178
+ cleanCWD()
179
+
180
+ // copy the content of commit to cwd
181
+ copyDir(targetCommitFolder)
182
+
183
+ fs.writeFileSync(headFile,commitId,"utf-8")
184
+ console.log(chalk.green(`HEAD moved to ${commitId}`));
185
+
186
+ deleteLocalCommits(commitFolder,toDelete)
187
+ await deleteCommitsFromDrive(toDelete)
188
+ await deleteCommitsFromDatabase(configData,toDelete,path.basename(process.cwd()))
189
+
190
+ console.log(chalk.green(`Successfully reverted to commit ${commitId}`));
191
+ }
192
+
193
+ module.exports = revertCmd
@@ -0,0 +1,160 @@
1
+ // Untracked files
2
+ // Files that exist in your working directory (project folder) but have never been added to staging or committed.
3
+
4
+ // Changes to be committed
5
+ // Files that are in the staging area (.jvcs/staging) — meaning, you’ve already added them using jvcs add, but haven’t committed yet.
6
+
7
+ // Changes not staged for commit
8
+ // Files that were already added to staging earlier, but you modified them again in your working directory after staging — i.e., the staged copy and working copy are different.
9
+
10
+ const fs = require("fs");
11
+ const path = require("path");
12
+ const crypto = require("crypto");
13
+ const chalk = require("chalk");
14
+ const { checkGlobalConfig, getGlobalConfig, checkforjvcs } = require("./utility");
15
+
16
+ // normalize relative path to use forward slashes for consistent comparisons
17
+ function normalizeRel(p) {
18
+ return p.split(path.sep).join("/")
19
+ }
20
+
21
+ function hashfile(filepath) {
22
+ try {
23
+ const data = fs.readFileSync(filepath)
24
+ return crypto.createHash("sha256").update(data).digest("hex")
25
+ }
26
+ catch(error) {
27
+ // return null
28
+ }
29
+ }
30
+
31
+
32
+ function getAllFiles(dir, rootDir=dir, collected=[]) {
33
+
34
+ if (!fs.existsSync(dir)) return collected;
35
+
36
+ const entries = fs.readdirSync(dir,{withFileTypes:true})
37
+
38
+ for(const entry of entries) {
39
+ const fullPath = path.join(dir,entry.name)
40
+ const rel = normalizeRel(path.relative(rootDir,fullPath))
41
+
42
+ if(entry.isDirectory() && (entry.name === ".jvcs" || entry.name === "node_modules"))
43
+ continue;
44
+
45
+ if(entry.isFile() && (entry.name === "meta.json" || entry.name === "jvcs_hashcode.json"))
46
+ continue;
47
+
48
+ if(entry.isFile()) {
49
+ collected.push(rel);
50
+ }
51
+ else if(entry.isDirectory()) {
52
+ getAllFiles(fullPath, rootDir, collected);
53
+ }
54
+
55
+ }
56
+
57
+ return collected
58
+ }
59
+
60
+ async function statusCmd() {
61
+
62
+ if(!checkGlobalConfig()) {
63
+ console.log(chalk.red("No existing session found. Please login or signup."));
64
+ console.log(chalk.green("jvcs --help for help"));
65
+ return;
66
+ }
67
+
68
+ const configData = getGlobalConfig();
69
+ if(!configData) {
70
+ console.log(chalk.red("No existing session found. Please login or signup."));
71
+ return;
72
+ }
73
+
74
+ if(!checkforjvcs()) {
75
+ console.log(chalk.red("Repository is not initialized or is deleted."));
76
+ return;
77
+ }
78
+
79
+ const cwd = process.cwd()
80
+ const jvcsDir = path.join(cwd,".jvcs")
81
+ const commitDir = path.join(jvcsDir,"commits")
82
+ const stagingDir = path.join(jvcsDir,"staging")
83
+ const headFile = path.join(jvcsDir, "HEAD");
84
+
85
+ if(!fs.existsSync(jvcsDir)) {
86
+ console.log(chalk.red("No repository exists. Please create one using 'jvcs init'"))
87
+ return
88
+ }
89
+
90
+ // collect files (all relative to cwd, normalized)
91
+ const cwdFiles = getAllFiles(cwd, cwd, []);
92
+ const stagedFiles = fs.existsSync(stagingDir) ? getAllFiles(stagingDir, stagingDir, []).map(f => normalizeRel(f)) : [];
93
+ let commitedFiles = []
94
+ if(fs.existsSync(commitDir)) {
95
+ const commits = fs.readdirSync(commitDir)
96
+ if(commits.length > 0) {
97
+ const lastCommit = `${fs.readFileSync(headFile, "utf-8").trim()}`;
98
+ const commitPath = path.join(commitDir, lastCommit);
99
+ commitedFiles = getAllFiles(commitPath, commitPath, []).map(f => normalizeRel(f))
100
+ }
101
+ }
102
+
103
+ // use Sets for fast looku
104
+ const committedSet = new Set(commitedFiles);
105
+ const stagedSet = new Set(stagedFiles);
106
+
107
+ // Untracked: present in cwd but not in staging or commits
108
+ const untracked = cwdFiles.filter(f => !stagedSet.has(f) && !committedSet.has(f));
109
+
110
+ // Changes to be committed: present in staging but not in (any) commits
111
+ const toBeCommitted = stagedFiles.filter(f => !committedSet.has(f));
112
+
113
+ // Changes not staged for commit: present in staging and in cwd, but changed in cwd compared to staged copy
114
+ const modified = stagedFiles.filter((file)=> {
115
+ const cwdFilePath = path.join(process.cwd(),file)
116
+ const stagedFilePath = path.join(stagingDir,file)
117
+
118
+ if(!fs.existsSync(cwdFilePath) || !fs.existsSync(stagedFilePath))
119
+ return false
120
+
121
+ const cwdHash = hashfile(cwdFilePath)
122
+ const stagingHash = hashfile(stagedFilePath)
123
+
124
+ return cwdHash !== stagingHash
125
+ })
126
+
127
+
128
+ // output
129
+ console.log(chalk.bold.blue(`\nOn branch: main (default)`));
130
+
131
+ console.log(chalk.bold.green("\nChanges to be committed (files that are staged but not commited):"));
132
+ if(toBeCommitted.length > 0) {
133
+ toBeCommitted.forEach(f => console.log(chalk.green(`\t${f}`)));
134
+ }
135
+ else {
136
+ console.log(chalk.gray("\tNo changes added to commit"));
137
+ }
138
+
139
+ console.log(chalk.bold.yellow("\nChanges not staged for commit (files that are modified after adding to staging area):"));
140
+ if(modified.length > 0) {
141
+ modified.forEach(f => console.log(chalk.yellow(`\t${f}`)));
142
+ }
143
+ else {
144
+ console.log(chalk.gray("\tNo modified files detected"));
145
+ }
146
+
147
+ console.log(chalk.bold.red("\nUntracked files (files that are not staged or commited):"));
148
+ if(untracked.length > 0) {
149
+ untracked.forEach(f => console.log(chalk.red(`\t${f}`)));
150
+ }
151
+ else {
152
+ console.log(chalk.gray("\tNo untracked files"));
153
+ }
154
+
155
+ console.log(chalk.gray("\n(use 'jvcs add <file>' to stage changes)"));
156
+ console.log(chalk.gray("(use 'jvcs commit -m \"message\"' to commit changes)"));
157
+ console.log(chalk.gray("(use 'jvcs unstage <file>/<folder> to unstage a file/folder')"))
158
+ }
159
+
160
+ module.exports = statusCmd
@@ -10,6 +10,7 @@ function checkGlobalConfig() {
10
10
  function getGlobalConfig() {
11
11
  if(checkGlobalConfig()) {
12
12
  const configData = JSON.parse(fs.readFileSync(config,"utf-8"))
13
+ if(configData.username && configData.email && configData.token)
13
14
  return configData
14
15
  }
15
16
 
package/index.js CHANGED
@@ -13,8 +13,9 @@ const commitCmd = require("./controllers/commit")
13
13
  const unstageCmd = require("./controllers/unstage")
14
14
  const logCmd = require("./controllers/log");
15
15
  const pushCmd = require("./controllers/push");
16
-
17
-
16
+ const statusCmd = require("./controllers/status")
17
+ const revertCmd = require("./controllers/revert")
18
+ //
18
19
  yargs(hideBin(process.argv))
19
20
  .scriptName("jvcs")
20
21
  .command(
@@ -117,7 +118,7 @@ yargs(hideBin(process.argv))
117
118
  )
118
119
  .command(
119
120
  "log",
120
- "show details of all commits",
121
+ chalk.blue("show details of all commits"),
121
122
  {},
122
123
  async ()=> {
123
124
  try {
@@ -130,7 +131,7 @@ yargs(hideBin(process.argv))
130
131
  )
131
132
  .command(
132
133
  "push",
133
- "Push all the commits to remote",
134
+ chalk.blue("Push all the commits to remote"),
134
135
  {},
135
136
  async ()=> {
136
137
  try {
@@ -141,6 +142,37 @@ yargs(hideBin(process.argv))
141
142
  }
142
143
  }
143
144
  )
145
+ .command(
146
+ "status",
147
+ chalk.blue("Check status of each file/folder"),
148
+ {},
149
+ async ()=> {
150
+ try {
151
+ await statusCmd()
152
+ }
153
+ catch(error) {
154
+ console.log(chalk.red(error))
155
+ }
156
+ }
157
+ )
158
+ .command(
159
+ "revert <commitId>",
160
+ chalk.blue("Replace your working directory with specific commit you made previously"),
161
+ (yargs)=> {
162
+ return yargs.positional("commitId", {
163
+ type: 'string',
164
+ describe: 'commitId to move your head'
165
+ })
166
+ },
167
+ async (argv)=> {
168
+ try {
169
+ await revertCmd(argv.commitId)
170
+ }
171
+ catch(error) {
172
+ console.log(chalk.red(error))
173
+ }
174
+ }
175
+ )
144
176
  .demandCommand(1, chalk.yellow("You need at least one command"))
145
177
  .help()
146
178
  .parse();
package/package.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "name": "jvcs",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "bin": {
5
5
  "jvcs": "./index.js"
6
6
  },
7
7
  "keywords": [],
8
8
  "author": "",
9
9
  "license": "ISC",
10
- "description": "",
11
10
  "dependencies": {
12
11
  "chalk": "^4.1.2",
13
12
  "crypto": "^1.0.1",
@@ -18,4 +17,4 @@
18
17
  "validator": "^13.15.20",
19
18
  "yargs": "^18.0.0"
20
19
  }
21
- }
20
+ }
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const yargs = require("yargs");
4
- const { hideBin } = require("yargs/helpers");
5
- const chalk = require("chalk");
6
- const dotenv = require("dotenv")
7
- dotenv.config()
8
-
9
- const beginCmd = require("./controllers/begin")
10
- const initCmd = require("./controllers/init")
11
- const addCmd = require("./controllers/add")
12
- const commitCmd = require("./controllers/commit")
13
- const unstageCmd = require("./controllers/unstage")
14
- const logCmd = require("./controllers/log");
15
- const pushCmd = require("./controllers/push");
16
-
17
-
18
- yargs(hideBin(process.argv))
19
- .scriptName("jvcs")
20
- .command(
21
- "begin",
22
- chalk.blue("Initialize the Version Control System (login/signup).\n"),
23
- {},
24
- async () => {
25
- try {
26
- await beginCmd()
27
- }
28
- catch(error) {
29
- console.log(chalk.red(error))
30
- }
31
- }
32
- )
33
- .command(
34
- "init",
35
- chalk.blue("Create an empty repository.\n"),
36
- {},
37
- async () => {
38
- try {
39
- await initCmd()
40
- }
41
- catch(error) {
42
- console.log(chalk.red(error))
43
- }
44
- }
45
- )
46
- .command(
47
- "add <paths...>",
48
- chalk.blue(
49
- `Add files or folders to the staging area.
50
-
51
- Command | Description
52
- ---------------------------------|-------------------
53
- jvcs add . | all files/folders
54
- jvcs add <file1> <file2> | multiple files
55
- jvcs add <folder1> <folder2> | multiple folders
56
- jvcs add <file> <folder> | files and folders\n`
57
- ),
58
- (yargs)=> {
59
- return yargs.positional("paths", {
60
- type: 'string',
61
- describe: 'Files and folders to stage'
62
- })
63
- },
64
- async (argv) => {
65
- try {
66
- await addCmd(argv.paths)
67
- }
68
- catch(error) {
69
- console.log(chalk.red(error))
70
- }
71
- }
72
- )
73
- .command(
74
- "commit <message>",
75
- chalk.blue("Commit all the files/folders inside staging area\n"),
76
- (yargs)=> {
77
- return yargs.positional("message", {
78
- type: 'string',
79
- describe: 'Some message with your commit'
80
- })
81
- },
82
- async (argv)=> {
83
- try {
84
- await commitCmd(argv.message)
85
- }
86
- catch(error) {
87
- console.log(chalk.red(error))
88
- }
89
- }
90
- )
91
- .command(
92
- "unstage <paths...>",
93
- chalk.blue(`
94
- Remove files and folders from staging area
95
-
96
- Command | Description
97
- ---------------------------------|-------------------
98
- jvcs unstage . | all files/folders
99
- jvcs unstage <file1> <file2> | multiple files
100
- jvcs unstage <folder1> <folder2> | multiple folders
101
- jvcs unstage <file> <folder> | files and folders\n
102
- `),
103
- (yargs)=> {
104
- return yargs.positional("paths", {
105
- type: 'string',
106
- describe: 'Files and folders to unstage'
107
- })
108
- },
109
- async (argv)=> {
110
- try {
111
- await unstageCmd(argv.paths)
112
- }
113
- catch(error) {
114
- console.log(chalk.red(error))
115
- }
116
- }
117
- )
118
- .command(
119
- "log",
120
- "show details of all commits",
121
- {},
122
- async ()=> {
123
- try {
124
- await logCmd()
125
- }
126
- catch(error) {
127
- console.log(chalk.red(error))
128
- }
129
- }
130
- )
131
- .command(
132
- "push",
133
- "Push all the commits to remote",
134
- {},
135
- async ()=> {
136
- try {
137
- await pushCmd()
138
- }
139
- catch(error) {
140
- console.log(chalk.red(error))
141
- }
142
- }
143
- )
144
- .demandCommand(1, chalk.yellow("You need at least one command"))
145
- .help()
146
- .parse();
@@ -1,6 +0,0 @@
1
- {
2
- "index.js": {
3
- "hash": "ba4b020c3a1b7cd4e9bb5d8ea1979236ced22891fff322dc38c567917a04eb03",
4
- "time": "2025-10-27T17:03:25.838Z"
5
- }
6
- }
@@ -1,7 +0,0 @@
1
- {
2
- "author": "jagdish",
3
- "id": "3a1169c8-ec67-4ce5-8024-ab4f08d7b609",
4
- "message": "m2",
5
- "timeStamp": "2025-10-27T17:04:27.217Z",
6
- "parentId": "c362f97f-997b-499a-bb45-9e67f298f61e"
7
- }
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const yargs = require("yargs");
4
- const { hideBin } = require("yargs/helpers");
5
- const chalk = require("chalk");
6
- const dotenv = require("dotenv")
7
- dotenv.config()
8
-
9
- const beginCmd = require("./controllers/begin")
10
- const initCmd = require("./controllers/init")
11
- const addCmd = require("./controllers/add")
12
- const commitCmd = require("./controllers/commit")
13
- const unstageCmd = require("./controllers/unstage")
14
- const logCmd = require("./controllers/log");
15
- const pushCmd = require("./controllers/push");
16
-
17
-
18
- yargs(hideBin(process.argv))
19
- .scriptName("jvcs")
20
- .command(
21
- "begin",
22
- chalk.blue("Initialize the Version Control System (login/signup).\n"),
23
- {},
24
- async () => {
25
- try {
26
- await beginCmd()
27
- }
28
- catch(error) {
29
- console.log(chalk.red(error))
30
- }
31
- }
32
- )
33
- .command(
34
- "init",
35
- chalk.blue("Create an empty repository.\n"),
36
- {},
37
- async () => {
38
- try {
39
- await initCmd()
40
- }
41
- catch(error) {
42
- console.log(chalk.red(error))
43
- }
44
- }
45
- )
46
- .command(
47
- "add <paths...>",
48
- chalk.blue(
49
- `Add files or folders to the staging area.
50
-
51
- Command | Description
52
- ---------------------------------|-------------------
53
- jvcs add . | all files/folders
54
- jvcs add <file1> <file2> | multiple files
55
- jvcs add <folder1> <folder2> | multiple folders
56
- jvcs add <file> <folder> | files and folders\n`
57
- ),
58
- (yargs)=> {
59
- return yargs.positional("paths", {
60
- type: 'string',
61
- describe: 'Files and folders to stage'
62
- })
63
- },
64
- async (argv) => {
65
- try {
66
- await addCmd(argv.paths)
67
- }
68
- catch(error) {
69
- console.log(chalk.red(error))
70
- }
71
- }
72
- )
73
- .command(
74
- "commit <message>",
75
- chalk.blue("Commit all the files/folders inside staging area\n"),
76
- (yargs)=> {
77
- return yargs.positional("message", {
78
- type: 'string',
79
- describe: 'Some message with your commit'
80
- })
81
- },
82
- async (argv)=> {
83
- try {
84
- await commitCmd(argv.message)
85
- }
86
- catch(error) {
87
- console.log(chalk.red(error))
88
- }
89
- }
90
- )
91
- .command(
92
- "unstage <paths...>",
93
- chalk.blue(`
94
- Remove files and folders from staging area
95
-
96
- Command | Description
97
- ---------------------------------|-------------------
98
- jvcs unstage . | all files/folders
99
- jvcs unstage <file1> <file2> | multiple files
100
- jvcs unstage <folder1> <folder2> | multiple folders
101
- jvcs unstage <file> <folder> | files and folders\n
102
- `),
103
- (yargs)=> {
104
- return yargs.positional("paths", {
105
- type: 'string',
106
- describe: 'Files and folders to unstage'
107
- })
108
- },
109
- async (argv)=> {
110
- try {
111
- await unstageCmd(argv.paths)
112
- }
113
- catch(error) {
114
- console.log(chalk.red(error))
115
- }
116
- }
117
- )
118
- .command(
119
- "log",
120
- "show details of all commits",
121
- {},
122
- async ()=> {
123
- try {
124
- await logCmd()
125
- }
126
- catch(error) {
127
- console.log(chalk.red(error))
128
- }
129
- }
130
- )
131
- .command(
132
- "push",
133
- "Push all the commits to remote",
134
- {},
135
- async ()=> {
136
- try {
137
- await pushCmd()
138
- }
139
- catch(error) {
140
- console.log(chalk.red(error))
141
- }
142
- }
143
- )
144
- .demandCommand(1, chalk.yellow("You need at least one command"))
145
- .help()
146
- .parse();
@@ -1,6 +0,0 @@
1
- {
2
- "index.js": {
3
- "hash": "ba4b020c3a1b7cd4e9bb5d8ea1979236ced22891fff322dc38c567917a04eb03",
4
- "time": "2025-10-27T17:03:25.838Z"
5
- }
6
- }
@@ -1,7 +0,0 @@
1
- {
2
- "author": "jagdish",
3
- "id": "c362f97f-997b-499a-bb45-9e67f298f61e",
4
- "message": "m1",
5
- "timeStamp": "2025-10-27T17:03:35.670Z",
6
- "parentId": null
7
- }
@@ -1,146 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const yargs = require("yargs");
4
- const { hideBin } = require("yargs/helpers");
5
- const chalk = require("chalk");
6
- const dotenv = require("dotenv")
7
- dotenv.config()
8
-
9
- const beginCmd = require("./controllers/begin")
10
- const initCmd = require("./controllers/init")
11
- const addCmd = require("./controllers/add")
12
- const commitCmd = require("./controllers/commit")
13
- const unstageCmd = require("./controllers/unstage")
14
- const logCmd = require("./controllers/log");
15
- const pushCmd = require("./controllers/push");
16
-
17
-
18
- yargs(hideBin(process.argv))
19
- .scriptName("jvcs")
20
- .command(
21
- "begin",
22
- chalk.blue("Initialize the Version Control System (login/signup).\n"),
23
- {},
24
- async () => {
25
- try {
26
- await beginCmd()
27
- }
28
- catch(error) {
29
- console.log(chalk.red(error))
30
- }
31
- }
32
- )
33
- .command(
34
- "init",
35
- chalk.blue("Create an empty repository.\n"),
36
- {},
37
- async () => {
38
- try {
39
- await initCmd()
40
- }
41
- catch(error) {
42
- console.log(chalk.red(error))
43
- }
44
- }
45
- )
46
- .command(
47
- "add <paths...>",
48
- chalk.blue(
49
- `Add files or folders to the staging area.
50
-
51
- Command | Description
52
- ---------------------------------|-------------------
53
- jvcs add . | all files/folders
54
- jvcs add <file1> <file2> | multiple files
55
- jvcs add <folder1> <folder2> | multiple folders
56
- jvcs add <file> <folder> | files and folders\n`
57
- ),
58
- (yargs)=> {
59
- return yargs.positional("paths", {
60
- type: 'string',
61
- describe: 'Files and folders to stage'
62
- })
63
- },
64
- async (argv) => {
65
- try {
66
- await addCmd(argv.paths)
67
- }
68
- catch(error) {
69
- console.log(chalk.red(error))
70
- }
71
- }
72
- )
73
- .command(
74
- "commit <message>",
75
- chalk.blue("Commit all the files/folders inside staging area\n"),
76
- (yargs)=> {
77
- return yargs.positional("message", {
78
- type: 'string',
79
- describe: 'Some message with your commit'
80
- })
81
- },
82
- async (argv)=> {
83
- try {
84
- await commitCmd(argv.message)
85
- }
86
- catch(error) {
87
- console.log(chalk.red(error))
88
- }
89
- }
90
- )
91
- .command(
92
- "unstage <paths...>",
93
- chalk.blue(`
94
- Remove files and folders from staging area
95
-
96
- Command | Description
97
- ---------------------------------|-------------------
98
- jvcs unstage . | all files/folders
99
- jvcs unstage <file1> <file2> | multiple files
100
- jvcs unstage <folder1> <folder2> | multiple folders
101
- jvcs unstage <file> <folder> | files and folders\n
102
- `),
103
- (yargs)=> {
104
- return yargs.positional("paths", {
105
- type: 'string',
106
- describe: 'Files and folders to unstage'
107
- })
108
- },
109
- async (argv)=> {
110
- try {
111
- await unstageCmd(argv.paths)
112
- }
113
- catch(error) {
114
- console.log(chalk.red(error))
115
- }
116
- }
117
- )
118
- .command(
119
- "log",
120
- "show details of all commits",
121
- {},
122
- async ()=> {
123
- try {
124
- await logCmd()
125
- }
126
- catch(error) {
127
- console.log(chalk.red(error))
128
- }
129
- }
130
- )
131
- .command(
132
- "push",
133
- "Push all the commits to remote",
134
- {},
135
- async ()=> {
136
- try {
137
- await pushCmd()
138
- }
139
- catch(error) {
140
- console.log(chalk.red(error))
141
- }
142
- }
143
- )
144
- .demandCommand(1, chalk.yellow("You need at least one command"))
145
- .help()
146
- .parse();