vetasks 1.0.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.
- package/LICENSE +21 -0
- package/README.md +35 -0
- package/package.json +23 -0
- package/src/index.js +175 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Antelmo Verdugo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# task-tracker-cli
|
|
2
|
+
CLI Task manager project to practice working with the filesystem, handling user inputs, and building a simple CLI application.
|
|
3
|
+
|
|
4
|
+
The user is able to:
|
|
5
|
+
- Add, Update, and Delete tasks
|
|
6
|
+
- Mark a task as in progress or done
|
|
7
|
+
- List all tasks
|
|
8
|
+
- List all tasks that are done
|
|
9
|
+
- List all tasks that are not done
|
|
10
|
+
- List all tasks that are in progress
|
|
11
|
+
|
|
12
|
+
## Adding a new task
|
|
13
|
+
task-cli add "Buy groceries"
|
|
14
|
+
|
|
15
|
+
### Output: Task added successfully (ID: 1)
|
|
16
|
+
|
|
17
|
+
## Updating and deleting tasks
|
|
18
|
+
task-cli update 1 "Buy groceries and cook dinner"
|
|
19
|
+
|
|
20
|
+
task-cli delete 1
|
|
21
|
+
|
|
22
|
+
## Marking a task as in progress or done
|
|
23
|
+
task-cli mark-in-progress 1
|
|
24
|
+
|
|
25
|
+
task-cli mark-done 1
|
|
26
|
+
|
|
27
|
+
## Listing all tasks
|
|
28
|
+
task-cli list
|
|
29
|
+
|
|
30
|
+
## Listing tasks by status
|
|
31
|
+
task-cli list done
|
|
32
|
+
|
|
33
|
+
task-cli list todo
|
|
34
|
+
|
|
35
|
+
task-cli list in-progress
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vetasks",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI Task manager project to practice",
|
|
5
|
+
"bin": {
|
|
6
|
+
"vetasks": "src/index.js"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://github.com/Antelmo7/task-tracker-cli#readme",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/Antelmo7/task-tracker-cli/issues"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/Antelmo7/task-tracker-cli.git"
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"author": "Antelmo Verdugo <antelmoverdugo@gmail.com>",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "./src/index.js",
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
const __dirname = import.meta.dirname;
|
|
6
|
+
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
|
|
9
|
+
const tasksFilePath = path.join(__dirname, 'tasks.json');
|
|
10
|
+
|
|
11
|
+
function readTasks() {
|
|
12
|
+
if (!fs.existsSync(tasksFilePath)) {
|
|
13
|
+
try {
|
|
14
|
+
const tasks = [];
|
|
15
|
+
fs.writeFileSync(tasksFilePath, JSON.stringify(tasks));
|
|
16
|
+
return tasks;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error(error);
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
try {
|
|
22
|
+
const tasks = fs.readFileSync(tasksFilePath, 'utf8');
|
|
23
|
+
return JSON.parse(tasks);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error(error)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function updateTasksFile(tasks) {
|
|
31
|
+
try {
|
|
32
|
+
fs.writeFileSync(tasksFilePath, JSON.stringify(tasks));
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error(error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function addTask(description) {
|
|
39
|
+
const tasks = readTasks();
|
|
40
|
+
|
|
41
|
+
const task = {
|
|
42
|
+
id: (tasks.length === 0) ? 1 : parseInt(tasks[tasks.length - 1].id) + 1,
|
|
43
|
+
description,
|
|
44
|
+
status: 'todo',
|
|
45
|
+
createdAt: new Date(),
|
|
46
|
+
updatedAt: new Date(),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
tasks.push(task)
|
|
50
|
+
updateTasksFile(tasks);
|
|
51
|
+
console.log(`Task added successfully (ID: ${task.id})`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function listAllTasks() {
|
|
55
|
+
const tasks = readTasks();
|
|
56
|
+
|
|
57
|
+
if (tasks.length < 1) {
|
|
58
|
+
console.log('No tasks yet');
|
|
59
|
+
} else {
|
|
60
|
+
console.log('All tasks\n');
|
|
61
|
+
tasks.forEach(task => {
|
|
62
|
+
console.log(`Id: ${task.id} - ${task.description} (${task.status}) | Created: ${new Date(task.createdAt).toDateString()} - Updated: ${new Date(task.updatedAt).toDateString()}`);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function listTasksByStatus(status) {
|
|
68
|
+
const tasks = readTasks();
|
|
69
|
+
|
|
70
|
+
tasks.forEach(task => {
|
|
71
|
+
if (task.status === status)
|
|
72
|
+
console.log(`Id: ${task.id} - ${task.description} (${task.status}) | Created: ${new Date(task.createdAt).toDateString()} - Updated: ${new Date(task.updatedAt).toDateString()}`);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function updateTask({ taskId, newDescription }) {
|
|
77
|
+
const tasks = readTasks();
|
|
78
|
+
const taskToUpdateIndex = tasks.findIndex(task => task.id == taskId);
|
|
79
|
+
|
|
80
|
+
if (taskToUpdateIndex < 0) {
|
|
81
|
+
console.error(`Task with ID: ${taskId} does not exist`);
|
|
82
|
+
} else {
|
|
83
|
+
tasks[taskToUpdateIndex].description = newDescription;
|
|
84
|
+
updateTasksFile(tasks);
|
|
85
|
+
console.log(`Task updated successfully (ID: ${taskId})`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function deleteTask(taskId) {
|
|
90
|
+
const tasks = readTasks();
|
|
91
|
+
const taskToUpdateIndex = tasks.findIndex(task => task.id == taskId);
|
|
92
|
+
|
|
93
|
+
if (taskToUpdateIndex < 0) {
|
|
94
|
+
console.error(`Task with ID: ${taskId} does not exist`);
|
|
95
|
+
} else {
|
|
96
|
+
tasks.splice(taskToUpdateIndex, 1);
|
|
97
|
+
updateTasksFile(tasks);
|
|
98
|
+
console.log(`Task deleted successfully (ID: ${taskId})`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function changeTaskStatus({ taskId, status }) {
|
|
103
|
+
const tasks = readTasks();
|
|
104
|
+
const taskToUpdateIndex = tasks.findIndex(task => task.id == taskId);
|
|
105
|
+
|
|
106
|
+
if (taskToUpdateIndex < 0) {
|
|
107
|
+
console.error(`Task with ID: ${taskId} does not exist`);
|
|
108
|
+
} else {
|
|
109
|
+
tasks[taskToUpdateIndex].status = status;
|
|
110
|
+
updateTasksFile(tasks);
|
|
111
|
+
console.log(`Task updated successfully (ID: ${taskId})`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (args[0] === 'help' || args.length < 1) {
|
|
116
|
+
console.log(`
|
|
117
|
+
## Adding a new task:
|
|
118
|
+
task-cli add "Buy groceries"
|
|
119
|
+
### Output: Task added successfully (ID: 1)
|
|
120
|
+
|
|
121
|
+
## Updating and deleting tasks:
|
|
122
|
+
task-cli update 1 "Buy groceries and cook dinner"
|
|
123
|
+
task-cli delete 1
|
|
124
|
+
|
|
125
|
+
## Marking a task as in progress or done:
|
|
126
|
+
task-cli mark-in-progress 1
|
|
127
|
+
task-cli mark-done 1
|
|
128
|
+
|
|
129
|
+
## Listing all tasks:
|
|
130
|
+
task-cli list
|
|
131
|
+
|
|
132
|
+
## Listing tasks by status:
|
|
133
|
+
task-cli list done
|
|
134
|
+
task-cli list todo
|
|
135
|
+
task-cli list in-progress
|
|
136
|
+
`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (args[0] === 'add') {
|
|
140
|
+
const description = args.slice(1).join(" "); // Join the words after the "add" sub command
|
|
141
|
+
if (!description) {
|
|
142
|
+
console.error(`Please type a task description`);
|
|
143
|
+
} else {
|
|
144
|
+
addTask(description);
|
|
145
|
+
}
|
|
146
|
+
} else if (args[0] === 'list') {
|
|
147
|
+
const status = args[1];
|
|
148
|
+
|
|
149
|
+
if (!status) {
|
|
150
|
+
listAllTasks();
|
|
151
|
+
} else {
|
|
152
|
+
listTasksByStatus(status);
|
|
153
|
+
}
|
|
154
|
+
} else if (args[0] === 'update') {
|
|
155
|
+
const taskId = args[1];
|
|
156
|
+
const newDescription = args[2];
|
|
157
|
+
|
|
158
|
+
if (!newDescription) console.error(`Please type a task description`);
|
|
159
|
+
else updateTask({ taskId: parseInt(taskId), newDescription });
|
|
160
|
+
} else if (args[0] === 'delete') {
|
|
161
|
+
const taskId = args[1];
|
|
162
|
+
|
|
163
|
+
if (!taskId) console.error(`Please type a task ID`);
|
|
164
|
+
else deleteTask(parseInt(taskId));
|
|
165
|
+
} else if (args[0] === 'mark-in-progress') {
|
|
166
|
+
const taskId = args[1];
|
|
167
|
+
|
|
168
|
+
if (!taskId) console.error(`Please type a task ID`);
|
|
169
|
+
else changeTaskStatus({ taskId: parseInt(taskId), status: 'in-progress' });
|
|
170
|
+
} else if (args[0] === 'mark-done') {
|
|
171
|
+
const taskId = args[1];
|
|
172
|
+
|
|
173
|
+
if (!taskId) console.error(`Please type a task ID`);
|
|
174
|
+
else changeTaskStatus({ taskId: parseInt(taskId), status: 'done' });
|
|
175
|
+
}
|