project-roadmap-tracking 0.2.0 → 0.2.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/README.md +17 -15
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.js +23 -1
- package/dist/repositories/config.repository.js +1 -1
- package/dist/services/task.service.d.ts +23 -0
- package/dist/services/task.service.js +60 -0
- package/oclif.manifest.json +15 -1
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ A modern, production-ready CLI tool for managing project tasks and roadmaps with
|
|
|
15
15
|
- 🔍 **Powerful Filtering**: Filter and sort tasks by multiple criteria
|
|
16
16
|
- 📊 **Validation**: Comprehensive roadmap validation with detailed error reporting
|
|
17
17
|
- ⚡ **Performance**: LRU caching and file watching for optimal performance
|
|
18
|
-
- 🏗️ **Modern Architecture**: Service layer, repository pattern, and
|
|
18
|
+
- 🏗️ **Modern Architecture**: Service layer, repository pattern, and 96.81% test coverage
|
|
19
19
|
- 📦 **Configuration**: Multi-level config inheritance (project → user → global)
|
|
20
20
|
- 🔄 **Backward Compatible**: Legacy mode via `--no-repo` flag
|
|
21
21
|
|
|
@@ -166,7 +166,7 @@ $ npm install -g project-roadmap-tracking
|
|
|
166
166
|
$ prt COMMAND
|
|
167
167
|
running command...
|
|
168
168
|
$ prt (--version)
|
|
169
|
-
project-roadmap-tracking/0.2.
|
|
169
|
+
project-roadmap-tracking/0.2.5 linux-x64 node-v25.4.0
|
|
170
170
|
$ prt --help [COMMAND]
|
|
171
171
|
USAGE
|
|
172
172
|
$ prt COMMAND
|
|
@@ -228,7 +228,7 @@ EXAMPLES
|
|
|
228
228
|
$ prt add
|
|
229
229
|
```
|
|
230
230
|
|
|
231
|
-
_See code: [src/commands/add.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
231
|
+
_See code: [src/commands/add.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/add.ts)_
|
|
232
232
|
|
|
233
233
|
## `prt complete TASKID`
|
|
234
234
|
|
|
@@ -253,7 +253,7 @@ EXAMPLES
|
|
|
253
253
|
$ prt complete F-001 --tests
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
_See code: [src/commands/complete.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
256
|
+
_See code: [src/commands/complete.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/complete.ts)_
|
|
257
257
|
|
|
258
258
|
## `prt help [COMMAND]`
|
|
259
259
|
|
|
@@ -300,7 +300,7 @@ EXAMPLES
|
|
|
300
300
|
$ prt init [path/to/directory]
|
|
301
301
|
```
|
|
302
302
|
|
|
303
|
-
_See code: [src/commands/init.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
303
|
+
_See code: [src/commands/init.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/init.ts)_
|
|
304
304
|
|
|
305
305
|
## `prt list`
|
|
306
306
|
|
|
@@ -329,7 +329,7 @@ EXAMPLES
|
|
|
329
329
|
$ prt list -p=h --incomplete --sort=createdAt
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
-
_See code: [src/commands/list.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
332
|
+
_See code: [src/commands/list.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/list.ts)_
|
|
333
333
|
|
|
334
334
|
## `prt pass-test TASKID`
|
|
335
335
|
|
|
@@ -353,7 +353,7 @@ EXAMPLES
|
|
|
353
353
|
$ prt pass-test F-001
|
|
354
354
|
```
|
|
355
355
|
|
|
356
|
-
_See code: [src/commands/pass-test.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
356
|
+
_See code: [src/commands/pass-test.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/pass-test.ts)_
|
|
357
357
|
|
|
358
358
|
## `prt plugins`
|
|
359
359
|
|
|
@@ -667,7 +667,7 @@ EXAMPLES
|
|
|
667
667
|
$ prt show F-001
|
|
668
668
|
```
|
|
669
669
|
|
|
670
|
-
_See code: [src/commands/show.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
670
|
+
_See code: [src/commands/show.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/show.ts)_
|
|
671
671
|
|
|
672
672
|
## `prt update TASKID`
|
|
673
673
|
|
|
@@ -676,7 +676,7 @@ Update a task in place
|
|
|
676
676
|
```
|
|
677
677
|
USAGE
|
|
678
678
|
$ prt update TASKID [--clear-notes] [-d <value>] [--no-repo] [-n <value>] [-s
|
|
679
|
-
completed|in-progress|not-started] [-t true|false] [-v]
|
|
679
|
+
completed|in-progress|not-started] [-t true|false] [--type bug|feature|improvement|planning|research] [-v]
|
|
680
680
|
|
|
681
681
|
ARGUMENTS
|
|
682
682
|
TASKID ID of the task to update
|
|
@@ -691,6 +691,8 @@ FLAGS
|
|
|
691
691
|
-v, --verbose show detailed error information including stack traces
|
|
692
692
|
--clear-notes clear all notes from the task
|
|
693
693
|
--no-repo use legacy direct file I/O instead of repository pattern
|
|
694
|
+
--type=<option> update the task type (reassigns task ID and cascades to all references)
|
|
695
|
+
<options: bug|feature|improvement|planning|research>
|
|
694
696
|
|
|
695
697
|
DESCRIPTION
|
|
696
698
|
Update a task in place
|
|
@@ -701,7 +703,7 @@ EXAMPLES
|
|
|
701
703
|
$ prt update F-002 --deps="F-001" --clear-notes
|
|
702
704
|
```
|
|
703
705
|
|
|
704
|
-
_See code: [src/commands/update.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
706
|
+
_See code: [src/commands/update.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/update.ts)_
|
|
705
707
|
|
|
706
708
|
## `prt validate`
|
|
707
709
|
|
|
@@ -722,7 +724,7 @@ EXAMPLES
|
|
|
722
724
|
$ prt validate
|
|
723
725
|
```
|
|
724
726
|
|
|
725
|
-
_See code: [src/commands/validate.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.
|
|
727
|
+
_See code: [src/commands/validate.ts](https://github.com/ZacharyEggert/project-roadmap-tracking/blob/v0.2.5/src/commands/validate.ts)_
|
|
726
728
|
<!-- commandsstop -->
|
|
727
729
|
|
|
728
730
|
## Development
|
|
@@ -769,7 +771,7 @@ prt COMMAND
|
|
|
769
771
|
|
|
770
772
|
### Testing
|
|
771
773
|
|
|
772
|
-
PRT has comprehensive test coverage (
|
|
774
|
+
PRT has comprehensive test coverage (96.81%):
|
|
773
775
|
|
|
774
776
|
- **Unit tests**: Services, repositories, utilities, errors
|
|
775
777
|
- **Command tests**: All CLI commands
|
|
@@ -795,10 +797,10 @@ yarn test:coverage:summary
|
|
|
795
797
|
For detailed architecture documentation, including design patterns, service layer architecture, repository pattern, and migration path, see [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
796
798
|
|
|
797
799
|
Key architectural features:
|
|
798
|
-
- ✓ Service layer for business logic (
|
|
799
|
-
- ✓ Repository pattern with caching and file watching (
|
|
800
|
+
- ✓ Service layer for business logic (97.43% coverage)
|
|
801
|
+
- ✓ Repository pattern with caching and file watching (94.7% coverage)
|
|
800
802
|
- ✓ Custom error hierarchy with error codes (100% coverage)
|
|
801
|
-
- ✓ Comprehensive test suite (
|
|
803
|
+
- ✓ Comprehensive test suite (96.81% overall coverage)
|
|
802
804
|
- ✓ Backward compatible legacy mode
|
|
803
805
|
|
|
804
806
|
### Contributing
|
|
@@ -12,6 +12,7 @@ export default class Update extends Command {
|
|
|
12
12
|
notes: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
13
|
status: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
tested: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
type: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
17
|
};
|
|
17
18
|
run(): Promise<void>;
|
package/dist/commands/update.js
CHANGED
|
@@ -2,9 +2,10 @@ import { Args, Command, Flags } from '@oclif/core';
|
|
|
2
2
|
import { getDefaultConfigRepository } from '../repositories/config.repository.js';
|
|
3
3
|
import { RoadmapRepository } from '../repositories/roadmap.repository.js';
|
|
4
4
|
import errorHandlerService from '../services/error-handler.service.js';
|
|
5
|
+
import taskService from '../services/task.service.js';
|
|
5
6
|
import { readConfigFile } from '../util/read-config.js';
|
|
6
7
|
import { readRoadmapFile } from '../util/read-roadmap.js';
|
|
7
|
-
import { STATUS } from '../util/types.js';
|
|
8
|
+
import { STATUS, TASK_TYPE } from '../util/types.js';
|
|
8
9
|
import { updateTaskInRoadmap } from '../util/update-task.js';
|
|
9
10
|
import { validateTaskID } from '../util/validate-task-id.js';
|
|
10
11
|
import { writeRoadmapFile } from '../util/write-roadmap.js';
|
|
@@ -38,6 +39,10 @@ export default class Update extends Command {
|
|
|
38
39
|
description: 'update whether the task passes tests',
|
|
39
40
|
options: ['true', 'false'],
|
|
40
41
|
}),
|
|
42
|
+
type: Flags.string({
|
|
43
|
+
description: 'update the task type (reassigns task ID and cascades to all references)',
|
|
44
|
+
options: [TASK_TYPE.Bug, TASK_TYPE.Feature, TASK_TYPE.Improvement, TASK_TYPE.Planning, TASK_TYPE.Research],
|
|
45
|
+
}),
|
|
41
46
|
verbose: Flags.boolean({
|
|
42
47
|
char: 'v',
|
|
43
48
|
default: false,
|
|
@@ -56,6 +61,23 @@ export default class Update extends Command {
|
|
|
56
61
|
const roadmap = flags['no-repo']
|
|
57
62
|
? await readRoadmapFile(config.path)
|
|
58
63
|
: await RoadmapRepository.fromConfig(config).load(config.path);
|
|
64
|
+
// Handle type update separately since it requires ID reassignment and cascading
|
|
65
|
+
if (flags.type) {
|
|
66
|
+
const newType = flags.type;
|
|
67
|
+
const oldTaskId = args.taskID;
|
|
68
|
+
const { newTaskId, roadmap: updatedRoadmap } = taskService.updateTaskType(roadmap, oldTaskId, newType);
|
|
69
|
+
await (flags['no-repo']
|
|
70
|
+
? writeRoadmapFile(config.path, updatedRoadmap)
|
|
71
|
+
: RoadmapRepository.fromConfig(config).save(config.path, updatedRoadmap));
|
|
72
|
+
if (newTaskId === oldTaskId) {
|
|
73
|
+
this.log(`Task ${oldTaskId} was already of type ${newType}. No changes made.`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
this.log(`Task ${oldTaskId} has been updated to type ${newType} with new ID ${newTaskId}.`);
|
|
77
|
+
this.log(`All task references to ${oldTaskId} have been updated to ${newTaskId}.`);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
59
81
|
const updateObject = {};
|
|
60
82
|
if (flags['clear-notes']) {
|
|
61
83
|
updateObject.notes = '';
|
|
@@ -76,7 +76,7 @@ export class ConfigRepository {
|
|
|
76
76
|
searchPaths: config?.searchPaths ?? this.getDefaultSearchPaths(),
|
|
77
77
|
};
|
|
78
78
|
// Initialize JSON schema validator
|
|
79
|
-
const ajv = new Ajv({ allErrors: true
|
|
79
|
+
const ajv = new Ajv({ allErrors: true });
|
|
80
80
|
this.validateSchema = ajv.compile(ConfigRepository.configSchema);
|
|
81
81
|
}
|
|
82
82
|
/**
|
|
@@ -117,6 +117,29 @@ export declare class TaskService {
|
|
|
117
117
|
* ```
|
|
118
118
|
*/
|
|
119
119
|
updateTask(roadmap: Roadmap, taskId: string, updates: Partial<Task>): Roadmap;
|
|
120
|
+
/**
|
|
121
|
+
* Updates a task's type, reassigning its ID and cascading the change to all references.
|
|
122
|
+
* When a task type is changed, a new ID is generated to match the new type prefix.
|
|
123
|
+
* All other tasks that reference the old ID in their depends-on or blocks arrays
|
|
124
|
+
* will be updated to reference the new ID.
|
|
125
|
+
*
|
|
126
|
+
* @param roadmap - The roadmap containing the task to update
|
|
127
|
+
* @param taskId - The current ID of the task to update
|
|
128
|
+
* @param newType - The new task type to assign
|
|
129
|
+
* @returns An object containing the updated Roadmap and the new task ID
|
|
130
|
+
* @throws Error if the task with the given ID is not found
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* // Change task F-001 to a bug (will become B-001 or next available B-XXX)
|
|
135
|
+
* const {roadmap: updatedRoadmap, newTaskId} = taskService.updateTaskType(roadmap, 'F-001', TASK_TYPE.Bug);
|
|
136
|
+
* // All tasks that had 'F-001' in depends-on or blocks will now have the new bug ID
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
updateTaskType(roadmap: Roadmap, taskId: string, newType: TASK_TYPE): {
|
|
140
|
+
newTaskId: TaskID;
|
|
141
|
+
roadmap: Roadmap;
|
|
142
|
+
};
|
|
120
143
|
}
|
|
121
144
|
/**
|
|
122
145
|
* Default export instance of TaskService for convenience.
|
|
@@ -159,6 +159,66 @@ export class TaskService {
|
|
|
159
159
|
tasks: [...roadmap.tasks.slice(0, taskIndex), updatedTask, ...roadmap.tasks.slice(taskIndex + 1)],
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Updates a task's type, reassigning its ID and cascading the change to all references.
|
|
164
|
+
* When a task type is changed, a new ID is generated to match the new type prefix.
|
|
165
|
+
* All other tasks that reference the old ID in their depends-on or blocks arrays
|
|
166
|
+
* will be updated to reference the new ID.
|
|
167
|
+
*
|
|
168
|
+
* @param roadmap - The roadmap containing the task to update
|
|
169
|
+
* @param taskId - The current ID of the task to update
|
|
170
|
+
* @param newType - The new task type to assign
|
|
171
|
+
* @returns An object containing the updated Roadmap and the new task ID
|
|
172
|
+
* @throws Error if the task with the given ID is not found
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```typescript
|
|
176
|
+
* // Change task F-001 to a bug (will become B-001 or next available B-XXX)
|
|
177
|
+
* const {roadmap: updatedRoadmap, newTaskId} = taskService.updateTaskType(roadmap, 'F-001', TASK_TYPE.Bug);
|
|
178
|
+
* // All tasks that had 'F-001' in depends-on or blocks will now have the new bug ID
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
updateTaskType(roadmap, taskId, newType) {
|
|
182
|
+
const task = this.findTask(roadmap, taskId);
|
|
183
|
+
if (!task) {
|
|
184
|
+
throw new TaskNotFoundError(taskId);
|
|
185
|
+
}
|
|
186
|
+
// If the type isn't changing, just return the roadmap unchanged with the same task ID
|
|
187
|
+
if (task.type === newType) {
|
|
188
|
+
return { newTaskId: taskId, roadmap };
|
|
189
|
+
}
|
|
190
|
+
// Generate a new ID for the new type
|
|
191
|
+
const newTaskId = this.generateNextId(roadmap, newType);
|
|
192
|
+
// Update the task with the new type and new ID
|
|
193
|
+
let updatedRoadmap = this.updateTask(roadmap, taskId, {
|
|
194
|
+
id: newTaskId,
|
|
195
|
+
type: newType,
|
|
196
|
+
});
|
|
197
|
+
// Cascade the ID change to all tasks that reference the old ID
|
|
198
|
+
updatedRoadmap = {
|
|
199
|
+
...updatedRoadmap,
|
|
200
|
+
tasks: updatedRoadmap.tasks.map((t) => {
|
|
201
|
+
// Skip the task we just updated
|
|
202
|
+
if (t.id === newTaskId) {
|
|
203
|
+
return t;
|
|
204
|
+
}
|
|
205
|
+
// Check if this task references the old ID in depends-on or blocks
|
|
206
|
+
const hasDependency = t['depends-on'].includes(taskId);
|
|
207
|
+
const hasBlock = t.blocks.includes(taskId);
|
|
208
|
+
if (!hasDependency && !hasBlock) {
|
|
209
|
+
return t;
|
|
210
|
+
}
|
|
211
|
+
// Update the references
|
|
212
|
+
return {
|
|
213
|
+
...t,
|
|
214
|
+
blocks: hasBlock ? t.blocks.map((id) => (id === taskId ? newTaskId : id)) : t.blocks,
|
|
215
|
+
'depends-on': hasDependency ? t['depends-on'].map((id) => (id === taskId ? newTaskId : id)) : t['depends-on'],
|
|
216
|
+
updatedAt: new Date().toISOString(),
|
|
217
|
+
};
|
|
218
|
+
}),
|
|
219
|
+
};
|
|
220
|
+
return { newTaskId, roadmap: updatedRoadmap };
|
|
221
|
+
}
|
|
162
222
|
}
|
|
163
223
|
/**
|
|
164
224
|
* Default export instance of TaskService for convenience.
|
package/oclif.manifest.json
CHANGED
|
@@ -470,6 +470,20 @@
|
|
|
470
470
|
],
|
|
471
471
|
"type": "option"
|
|
472
472
|
},
|
|
473
|
+
"type": {
|
|
474
|
+
"description": "update the task type (reassigns task ID and cascades to all references)",
|
|
475
|
+
"name": "type",
|
|
476
|
+
"hasDynamicHelp": false,
|
|
477
|
+
"multiple": false,
|
|
478
|
+
"options": [
|
|
479
|
+
"bug",
|
|
480
|
+
"feature",
|
|
481
|
+
"improvement",
|
|
482
|
+
"planning",
|
|
483
|
+
"research"
|
|
484
|
+
],
|
|
485
|
+
"type": "option"
|
|
486
|
+
},
|
|
473
487
|
"verbose": {
|
|
474
488
|
"char": "v",
|
|
475
489
|
"description": "show detailed error information including stack traces",
|
|
@@ -531,5 +545,5 @@
|
|
|
531
545
|
]
|
|
532
546
|
}
|
|
533
547
|
},
|
|
534
|
-
"version": "0.2.
|
|
548
|
+
"version": "0.2.5"
|
|
535
549
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-roadmap-tracking",
|
|
3
3
|
"description": "CLI based project task tracking",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.5",
|
|
5
5
|
"author": "ZacharyEggert",
|
|
6
6
|
"bin": {
|
|
7
7
|
"prt": "./bin/run.js"
|
|
@@ -44,7 +44,15 @@
|
|
|
44
44
|
],
|
|
45
45
|
"homepage": "https://github.com/ZacharyEggert/project-roadmap-tracking",
|
|
46
46
|
"keywords": [
|
|
47
|
-
"oclif"
|
|
47
|
+
"oclif",
|
|
48
|
+
"cli",
|
|
49
|
+
"project",
|
|
50
|
+
"roadmap",
|
|
51
|
+
"tracking",
|
|
52
|
+
"tasks",
|
|
53
|
+
"productivity",
|
|
54
|
+
"management",
|
|
55
|
+
"prt"
|
|
48
56
|
],
|
|
49
57
|
"license": "MIT",
|
|
50
58
|
"main": "dist/index.js",
|