@schnick371/devsteps-shared 0.0.1 → 0.5.1
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 +66 -7
- package/dist/core/add.d.ts +23 -0
- package/dist/core/add.d.ts.map +1 -0
- package/dist/core/add.js +102 -0
- package/dist/core/add.js.map +1 -0
- package/dist/core/archive.d.ts +24 -0
- package/dist/core/archive.d.ts.map +1 -0
- package/dist/core/archive.js +109 -0
- package/dist/core/archive.js.map +1 -0
- package/dist/core/bulk-update.d.ts +34 -0
- package/dist/core/bulk-update.d.ts.map +1 -0
- package/dist/core/bulk-update.js +141 -0
- package/dist/core/bulk-update.js.map +1 -0
- package/dist/core/context.d.ts +54 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +198 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/get.d.ts +10 -0
- package/dist/core/get.d.ts.map +1 -0
- package/dist/core/get.js +28 -0
- package/dist/core/get.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/list.d.ts +19 -0
- package/dist/core/list.d.ts.map +1 -0
- package/dist/core/list.js +64 -0
- package/dist/core/list.js.map +1 -0
- package/dist/core/update.d.ts +23 -0
- package/dist/core/update.d.ts.map +1 -0
- package/dist/core/update.js +118 -0
- package/dist/core/update.js.map +1 -0
- package/dist/core/validation.d.ts +28 -0
- package/dist/core/validation.d.ts.map +1 -0
- package/dist/core/validation.js +205 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/index.d.ts +286 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +200 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/project.d.ts +134 -0
- package/dist/schemas/project.d.ts.map +1 -0
- package/dist/schemas/project.js +54 -0
- package/dist/schemas/project.js.map +1 -0
- package/dist/schemas/relationships.d.ts +30 -0
- package/dist/schemas/relationships.d.ts.map +1 -0
- package/dist/schemas/relationships.js +41 -0
- package/dist/schemas/relationships.js.map +1 -0
- package/dist/types/commands.d.ts +92 -0
- package/dist/types/commands.d.ts.map +1 -0
- package/dist/types/commands.js +14 -0
- package/dist/types/commands.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cache.d.ts +80 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +169 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/index.d.ts +72 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +148 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +47 -15
- package/index.js +0 -6
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { CACHE_CONFIG, getCache } from '../utils/cache.js';
|
|
4
|
+
/**
|
|
5
|
+
* Analyze packages from workspace (with caching)
|
|
6
|
+
*/
|
|
7
|
+
export async function analyzePackages(projectDir) {
|
|
8
|
+
const cache = getCache();
|
|
9
|
+
const cacheKey = `package_analysis:${projectDir}`;
|
|
10
|
+
const packagesDir = path.join(projectDir, 'packages');
|
|
11
|
+
// Try cache first
|
|
12
|
+
const cached = cache.get(cacheKey, CACHE_CONFIG.PACKAGE_ANALYSIS_TTL, packagesDir);
|
|
13
|
+
if (cached) {
|
|
14
|
+
return cached;
|
|
15
|
+
}
|
|
16
|
+
const packages = [];
|
|
17
|
+
try {
|
|
18
|
+
const entries = await fs.readdir(packagesDir, { withFileTypes: true });
|
|
19
|
+
for (const entry of entries) {
|
|
20
|
+
if (entry.isDirectory()) {
|
|
21
|
+
const pkgPath = path.join(packagesDir, entry.name, 'package.json');
|
|
22
|
+
try {
|
|
23
|
+
const content = await fs.readFile(pkgPath, 'utf-8');
|
|
24
|
+
const pkg = JSON.parse(content);
|
|
25
|
+
packages.push({
|
|
26
|
+
name: pkg.name || entry.name,
|
|
27
|
+
purpose: pkg.description || 'No description',
|
|
28
|
+
dependencies: Object.keys(pkg.dependencies || {}),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Skip if no package.json
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// No packages directory
|
|
39
|
+
}
|
|
40
|
+
// Cache the result
|
|
41
|
+
cache.set(cacheKey, packages, packagesDir);
|
|
42
|
+
return packages;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get item counts from index (with caching)
|
|
46
|
+
*/
|
|
47
|
+
export async function getItemCounts(devstepsir) {
|
|
48
|
+
const cache = getCache();
|
|
49
|
+
const cacheKey = `item_counts:${devstepsir}`;
|
|
50
|
+
const indexPath = path.join(devstepsir, 'index.json');
|
|
51
|
+
// Try cache first
|
|
52
|
+
const cached = cache.get(cacheKey, CACHE_CONFIG.ITEM_COUNTS_TTL, indexPath);
|
|
53
|
+
if (cached) {
|
|
54
|
+
return cached;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const content = await fs.readFile(indexPath, 'utf-8');
|
|
58
|
+
const index = JSON.parse(content);
|
|
59
|
+
const counts = {
|
|
60
|
+
total: index.items.length,
|
|
61
|
+
by_type: {},
|
|
62
|
+
by_status: {},
|
|
63
|
+
};
|
|
64
|
+
for (const item of index.items) {
|
|
65
|
+
counts.by_type[item.type] = (counts.by_type[item.type] || 0) + 1;
|
|
66
|
+
counts.by_status[item.status] = (counts.by_status[item.status] || 0) + 1;
|
|
67
|
+
}
|
|
68
|
+
// Cache the result
|
|
69
|
+
cache.set(cacheKey, counts, indexPath);
|
|
70
|
+
return counts;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return { total: 0, by_type: {}, by_status: {} };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get recent updates (last N days) (with caching)
|
|
78
|
+
*/
|
|
79
|
+
export async function getRecentUpdates(devstepsir, days) {
|
|
80
|
+
const cache = getCache();
|
|
81
|
+
const cacheKey = `recent_updates:${devstepsir}:${days}`;
|
|
82
|
+
const indexPath = path.join(devstepsir, 'index.json');
|
|
83
|
+
// Try cache first
|
|
84
|
+
const cached = cache.get(cacheKey, CACHE_CONFIG.RECENT_UPDATES_TTL, indexPath);
|
|
85
|
+
if (cached) {
|
|
86
|
+
return cached;
|
|
87
|
+
}
|
|
88
|
+
const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
|
|
89
|
+
try {
|
|
90
|
+
const content = await fs.readFile(indexPath, 'utf-8');
|
|
91
|
+
const index = JSON.parse(content);
|
|
92
|
+
const updates = index.items
|
|
93
|
+
.filter((item) => new Date(item.updated).getTime() > cutoff)
|
|
94
|
+
.sort((a, b) => new Date(b.updated).getTime() - new Date(a.updated).getTime())
|
|
95
|
+
.slice(0, 10)
|
|
96
|
+
.map((item) => ({
|
|
97
|
+
id: item.id,
|
|
98
|
+
type: item.type,
|
|
99
|
+
title: item.title,
|
|
100
|
+
updated: item.updated,
|
|
101
|
+
}));
|
|
102
|
+
// Cache the result
|
|
103
|
+
cache.set(cacheKey, updates, indexPath);
|
|
104
|
+
return updates;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Read PROJECT.md if exists (with caching)
|
|
112
|
+
*/
|
|
113
|
+
export async function readProjectMd(devstepsir) {
|
|
114
|
+
const cache = getCache();
|
|
115
|
+
const cacheKey = `project_md:${devstepsir}`;
|
|
116
|
+
const projectPath = path.join(devstepsir, 'PROJECT.md');
|
|
117
|
+
// Try cache first
|
|
118
|
+
const cached = cache.get(cacheKey, CACHE_CONFIG.PROJECT_MD_TTL, projectPath);
|
|
119
|
+
if (cached !== null) {
|
|
120
|
+
return cached;
|
|
121
|
+
}
|
|
122
|
+
try {
|
|
123
|
+
const content = await fs.readFile(projectPath, 'utf-8');
|
|
124
|
+
// Parse markdown to extract context (simplified)
|
|
125
|
+
// In production, use a proper markdown parser
|
|
126
|
+
const techStack = {};
|
|
127
|
+
const packages = [];
|
|
128
|
+
// Extract tech stack (look for bullet points after "### Tech Stack")
|
|
129
|
+
const techStackMatch = content.match(/### Tech Stack\n([\s\S]*?)(?=\n###|$)/);
|
|
130
|
+
if (techStackMatch) {
|
|
131
|
+
const lines = techStackMatch[1].split('\n');
|
|
132
|
+
for (const line of lines) {
|
|
133
|
+
const match = line.match(/- \*\*(.+?)\*\*: (.+)/);
|
|
134
|
+
if (match) {
|
|
135
|
+
techStack[match[1]] = match[2];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Extract project type
|
|
140
|
+
const projectTypeMatch = content.match(/### Project Type\n(.+)/);
|
|
141
|
+
const projectType = projectTypeMatch?.[1] || 'Unknown';
|
|
142
|
+
const result = {
|
|
143
|
+
tech_stack: techStack,
|
|
144
|
+
packages,
|
|
145
|
+
project_type: projectType,
|
|
146
|
+
};
|
|
147
|
+
// Cache the result
|
|
148
|
+
cache.set(cacheKey, result, projectPath);
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Cache the null result (file doesn't exist)
|
|
153
|
+
cache.set(cacheKey, null);
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Estimate token count (rough approximation: 1 token ≈ 4 chars)
|
|
159
|
+
*/
|
|
160
|
+
export function estimateTokens(obj) {
|
|
161
|
+
const str = JSON.stringify(obj);
|
|
162
|
+
return Math.ceil(str.length / 4);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get quick context
|
|
166
|
+
*/
|
|
167
|
+
export async function getQuickContext(projectDir, devstepsir) {
|
|
168
|
+
const packages = await analyzePackages(projectDir);
|
|
169
|
+
const activeItems = await getItemCounts(devstepsir);
|
|
170
|
+
const recentUpdates = await getRecentUpdates(devstepsir, 7);
|
|
171
|
+
const staticContext = await readProjectMd(devstepsir);
|
|
172
|
+
const response = {
|
|
173
|
+
context_level: 'quick',
|
|
174
|
+
tokens_used: 0,
|
|
175
|
+
dynamic_context: {
|
|
176
|
+
packages,
|
|
177
|
+
active_items: activeItems,
|
|
178
|
+
recent_updates: recentUpdates,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
if (staticContext) {
|
|
182
|
+
response.static_context = staticContext;
|
|
183
|
+
}
|
|
184
|
+
response.tokens_used = estimateTokens(response);
|
|
185
|
+
// Add suggestions
|
|
186
|
+
const suggestions = [];
|
|
187
|
+
if (!staticContext) {
|
|
188
|
+
suggestions.push('Consider creating .devsteps/PROJECT.md for static context');
|
|
189
|
+
}
|
|
190
|
+
if (activeItems.by_status.blocked > 0) {
|
|
191
|
+
suggestions.push(`${activeItems.by_status.blocked} blocked items need attention`);
|
|
192
|
+
}
|
|
193
|
+
if (suggestions.length > 0) {
|
|
194
|
+
response.suggestions = suggestions;
|
|
195
|
+
}
|
|
196
|
+
return response;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ItemMetadata } from '../schemas/index.js';
|
|
2
|
+
export interface GetItemResult {
|
|
3
|
+
metadata: ItemMetadata;
|
|
4
|
+
description: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Core business logic for getting an item
|
|
8
|
+
*/
|
|
9
|
+
export declare function getItem(devstepsir: string, itemId: string): Promise<GetItemResult>;
|
|
10
|
+
//# sourceMappingURL=get.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../src/core/get.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,YAAY,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAsB,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAyBxF"}
|
package/dist/core/get.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { TYPE_TO_DIRECTORY, parseItemId } from '../utils/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Core business logic for getting an item
|
|
6
|
+
*/
|
|
7
|
+
export async function getItem(devstepsir, itemId) {
|
|
8
|
+
if (!existsSync(devstepsir)) {
|
|
9
|
+
throw new Error('Project not initialized. Run devsteps-init first.');
|
|
10
|
+
}
|
|
11
|
+
const parsed = parseItemId(itemId);
|
|
12
|
+
if (!parsed) {
|
|
13
|
+
throw new Error(`Invalid item ID: ${itemId}`);
|
|
14
|
+
}
|
|
15
|
+
const typeFolder = TYPE_TO_DIRECTORY[parsed.type];
|
|
16
|
+
const metadataPath = join(devstepsir, typeFolder, `${itemId}.json`);
|
|
17
|
+
const descriptionPath = join(devstepsir, typeFolder, `${itemId}.md`);
|
|
18
|
+
if (!existsSync(metadataPath)) {
|
|
19
|
+
throw new Error(`Item not found: ${itemId}`);
|
|
20
|
+
}
|
|
21
|
+
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
22
|
+
const description = existsSync(descriptionPath) ? readFileSync(descriptionPath, 'utf-8') : '';
|
|
23
|
+
return {
|
|
24
|
+
metadata,
|
|
25
|
+
description,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/core/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOnE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,UAAkB,EAAE,MAAc;IAC9D,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,OAAO,CAAC,CAAC;IACpE,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,MAAM,KAAK,CAAC,CAAC;IAErE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAiB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9F,OAAO;QACL,QAAQ;QACR,WAAW;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { addItem, type AddItemArgs, type AddItemResult } from './add.js';
|
|
2
|
+
export { getItem, type GetItemResult } from './get.js';
|
|
3
|
+
export { listItems, type ListItemsArgs, type ListItemsResult } from './list.js';
|
|
4
|
+
export { updateItem, type UpdateItemArgs, type UpdateItemResult } from './update.js';
|
|
5
|
+
export { archiveItem, type ArchiveItemResult, purgeItems, type PurgeItemsArgs, type PurgeItemsResult, } from './archive.js';
|
|
6
|
+
export { getQuickContext, analyzePackages, getItemCounts, getRecentUpdates, readProjectMd, estimateTokens, } from './context.js';
|
|
7
|
+
export { bulkUpdateItems, bulkAddTags, bulkRemoveTags, type BulkUpdateResult, } from './bulk-update.js';
|
|
8
|
+
export { validateRelationship, type ValidationResult, type WorkItem } from './validation.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EACL,WAAW,EACX,KAAK,iBAAiB,EACtB,UAAU,EACV,KAAK,cAAc,EACnB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,WAAW,EACX,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { addItem } from './add.js';
|
|
2
|
+
export { getItem } from './get.js';
|
|
3
|
+
export { listItems } from './list.js';
|
|
4
|
+
export { updateItem } from './update.js';
|
|
5
|
+
export { archiveItem, purgeItems, } from './archive.js';
|
|
6
|
+
export { getQuickContext, analyzePackages, getItemCounts, getRecentUpdates, readProjectMd, estimateTokens, } from './context.js';
|
|
7
|
+
export { bulkUpdateItems, bulkAddTags, bulkRemoveTags, } from './bulk-update.js';
|
|
8
|
+
export { validateRelationship } from './validation.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAwC,MAAM,UAAU,CAAC;AACzE,OAAO,EAAE,OAAO,EAAsB,MAAM,UAAU,CAAC;AACvD,OAAO,EAAE,SAAS,EAA4C,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,UAAU,EAA8C,MAAM,aAAa,CAAC;AACrF,OAAO,EACL,WAAW,EAEX,UAAU,GAGX,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,eAAe,EACf,WAAW,EACX,cAAc,GAEf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAwC,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { DevStepsIndex, EisenhowerQuadrant, ItemStatus, ItemType, Priority } from '../schemas/index.js';
|
|
2
|
+
export interface ListItemsArgs {
|
|
3
|
+
type?: ItemType;
|
|
4
|
+
status?: ItemStatus;
|
|
5
|
+
priority?: Priority;
|
|
6
|
+
assignee?: string;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
eisenhower?: EisenhowerQuadrant;
|
|
9
|
+
limit?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface ListItemsResult {
|
|
12
|
+
count: number;
|
|
13
|
+
items: DevStepsIndex['items'];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Core business logic for listing items with filters
|
|
17
|
+
*/
|
|
18
|
+
export declare function listItems(devstepsir: string, args?: ListItemsArgs): Promise<ListItemsResult>;
|
|
19
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/core/list.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,QAAQ,EACR,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,eAAe,CAAC,CA+D1B"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { TYPE_TO_DIRECTORY } from '../utils/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Core business logic for listing items with filters
|
|
6
|
+
*/
|
|
7
|
+
export async function listItems(devstepsir, args = {}) {
|
|
8
|
+
if (!existsSync(devstepsir)) {
|
|
9
|
+
throw new Error('Project not initialized. Run devsteps-init first.');
|
|
10
|
+
}
|
|
11
|
+
const indexPath = join(devstepsir, 'index.json');
|
|
12
|
+
const index = JSON.parse(readFileSync(indexPath, 'utf-8'));
|
|
13
|
+
let items = [...index.items];
|
|
14
|
+
// Apply filters
|
|
15
|
+
if (args.type) {
|
|
16
|
+
items = items.filter((i) => i.type === args.type);
|
|
17
|
+
}
|
|
18
|
+
if (args.status) {
|
|
19
|
+
items = items.filter((i) => i.status === args.status);
|
|
20
|
+
}
|
|
21
|
+
if (args.priority) {
|
|
22
|
+
items = items.filter((i) => i.priority === args.priority);
|
|
23
|
+
}
|
|
24
|
+
if (args.assignee) {
|
|
25
|
+
// Load full metadata for assignee filter
|
|
26
|
+
items = items.filter((i) => {
|
|
27
|
+
const metadataPath = join(devstepsir, TYPE_TO_DIRECTORY[i.type], `${i.id}.json`);
|
|
28
|
+
if (!existsSync(metadataPath))
|
|
29
|
+
return false;
|
|
30
|
+
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
31
|
+
return metadata.assignee === args.assignee;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (args.tags && args.tags.length > 0) {
|
|
35
|
+
// Load full metadata for tags filter
|
|
36
|
+
const filterTags = args.tags;
|
|
37
|
+
items = items.filter((i) => {
|
|
38
|
+
const metadataPath = join(devstepsir, TYPE_TO_DIRECTORY[i.type], `${i.id}.json`);
|
|
39
|
+
if (!existsSync(metadataPath))
|
|
40
|
+
return false;
|
|
41
|
+
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
42
|
+
return filterTags.every((tag) => metadata.tags.includes(tag));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (args.eisenhower) {
|
|
46
|
+
// Load full metadata for eisenhower filter
|
|
47
|
+
items = items.filter((i) => {
|
|
48
|
+
const metadataPath = join(devstepsir, TYPE_TO_DIRECTORY[i.type], `${i.id}.json`);
|
|
49
|
+
if (!existsSync(metadataPath))
|
|
50
|
+
return false;
|
|
51
|
+
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
52
|
+
return metadata.eisenhower === args.eisenhower;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// Apply limit
|
|
56
|
+
if (args.limit && args.limit > 0) {
|
|
57
|
+
items = items.slice(0, args.limit);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
count: items.length,
|
|
61
|
+
items,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/core/list.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { EisenhowerQuadrant, ItemMetadata, ItemStatus, Priority } from '../schemas/index.js';
|
|
2
|
+
export interface UpdateItemArgs {
|
|
3
|
+
id: string;
|
|
4
|
+
status?: ItemStatus;
|
|
5
|
+
priority?: Priority;
|
|
6
|
+
eisenhower?: EisenhowerQuadrant;
|
|
7
|
+
superseded_by?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
append_description?: string;
|
|
11
|
+
assignee?: string;
|
|
12
|
+
tags?: string[];
|
|
13
|
+
affected_paths?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface UpdateItemResult {
|
|
16
|
+
metadata: ItemMetadata;
|
|
17
|
+
oldStatus: ItemStatus;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Core business logic for updating an item
|
|
21
|
+
*/
|
|
22
|
+
export declare function updateItem(devstepsir: string, args: UpdateItemArgs): Promise<UpdateItemResult>;
|
|
23
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/core/update.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,QAAQ,EACT,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAqH3B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { TYPE_TO_DIRECTORY, getCurrentTimestamp, parseItemId } from '../utils/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Core business logic for updating an item
|
|
6
|
+
*/
|
|
7
|
+
export async function updateItem(devstepsir, args) {
|
|
8
|
+
if (!existsSync(devstepsir)) {
|
|
9
|
+
throw new Error('Project not initialized. Run devsteps-init first.');
|
|
10
|
+
}
|
|
11
|
+
const parsed = parseItemId(args.id);
|
|
12
|
+
if (!parsed) {
|
|
13
|
+
throw new Error(`Invalid item ID: ${args.id}`);
|
|
14
|
+
}
|
|
15
|
+
const typeFolder = TYPE_TO_DIRECTORY[parsed.type];
|
|
16
|
+
const metadataPath = join(devstepsir, typeFolder, `${args.id}.json`);
|
|
17
|
+
const descriptionPath = join(devstepsir, typeFolder, `${args.id}.md`);
|
|
18
|
+
if (!existsSync(metadataPath)) {
|
|
19
|
+
throw new Error(`Item not found: ${args.id}`);
|
|
20
|
+
}
|
|
21
|
+
// Read and update metadata
|
|
22
|
+
const metadata = JSON.parse(readFileSync(metadataPath, 'utf-8'));
|
|
23
|
+
const oldStatus = metadata.status;
|
|
24
|
+
// Validate status transitions (parent-child rules)
|
|
25
|
+
if (args.status === 'done') {
|
|
26
|
+
// Helper function to validate children are complete
|
|
27
|
+
const validateChildren = (relationshipType) => {
|
|
28
|
+
const children = metadata.linked_items[relationshipType];
|
|
29
|
+
if (children.length > 0) {
|
|
30
|
+
const openChildren = [];
|
|
31
|
+
for (const childId of children) {
|
|
32
|
+
const childParsed = parseItemId(childId);
|
|
33
|
+
if (childParsed) {
|
|
34
|
+
const childFolder = TYPE_TO_DIRECTORY[childParsed.type];
|
|
35
|
+
const childPath = join(devstepsir, childFolder, `${childId}.json`);
|
|
36
|
+
if (existsSync(childPath)) {
|
|
37
|
+
const childMeta = JSON.parse(readFileSync(childPath, 'utf-8'));
|
|
38
|
+
if (childMeta.status !== 'done' && childMeta.status !== 'cancelled' && childMeta.status !== 'obsolete') {
|
|
39
|
+
openChildren.push(childId);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (openChildren.length > 0) {
|
|
45
|
+
const relationLabel = relationshipType === 'implemented-by' ? 'implementation' : 'test';
|
|
46
|
+
throw new Error(`Cannot close ${args.id}: ${openChildren.length} ${relationLabel} item(s) still open: ${openChildren.join(', ')}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
// Validate implemented-by children (Scrum: Epic→Story, Story→Task; Waterfall: Requirement→Feature, Feature→Task)
|
|
51
|
+
if (['epic', 'story', 'requirement', 'feature'].includes(metadata.type)) {
|
|
52
|
+
validateChildren('implemented-by');
|
|
53
|
+
}
|
|
54
|
+
// Validate tested-by children (all parent types must have tests complete)
|
|
55
|
+
if (['epic', 'story', 'requirement', 'feature'].includes(metadata.type)) {
|
|
56
|
+
validateChildren('tested-by');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (args.status)
|
|
60
|
+
metadata.status = args.status;
|
|
61
|
+
if (args.priority)
|
|
62
|
+
metadata.priority = args.priority;
|
|
63
|
+
if (args.eisenhower)
|
|
64
|
+
metadata.eisenhower = args.eisenhower;
|
|
65
|
+
if (args.superseded_by !== undefined)
|
|
66
|
+
metadata.superseded_by = args.superseded_by;
|
|
67
|
+
if (args.title)
|
|
68
|
+
metadata.title = args.title;
|
|
69
|
+
if (args.assignee !== undefined)
|
|
70
|
+
metadata.assignee = args.assignee;
|
|
71
|
+
if (args.tags)
|
|
72
|
+
metadata.tags = args.tags;
|
|
73
|
+
if (args.affected_paths)
|
|
74
|
+
metadata.affected_paths = args.affected_paths;
|
|
75
|
+
metadata.updated = getCurrentTimestamp();
|
|
76
|
+
writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
|
|
77
|
+
// Update description
|
|
78
|
+
if (args.description && args.append_description) {
|
|
79
|
+
throw new Error('Cannot use both description and append_description simultaneously');
|
|
80
|
+
}
|
|
81
|
+
if (args.description) {
|
|
82
|
+
// Replace entire description
|
|
83
|
+
writeFileSync(descriptionPath, args.description);
|
|
84
|
+
}
|
|
85
|
+
else if (args.append_description) {
|
|
86
|
+
// Append to existing (or create new if doesn't exist)
|
|
87
|
+
const existing = existsSync(descriptionPath)
|
|
88
|
+
? readFileSync(descriptionPath, 'utf-8')
|
|
89
|
+
: '';
|
|
90
|
+
writeFileSync(descriptionPath, existing + args.append_description);
|
|
91
|
+
}
|
|
92
|
+
// Update index
|
|
93
|
+
const indexPath = join(devstepsir, 'index.json');
|
|
94
|
+
const index = JSON.parse(readFileSync(indexPath, 'utf-8'));
|
|
95
|
+
const itemIndex = index.items.findIndex((i) => i.id === args.id);
|
|
96
|
+
if (itemIndex !== -1) {
|
|
97
|
+
if (args.status)
|
|
98
|
+
index.items[itemIndex].status = args.status;
|
|
99
|
+
if (args.priority)
|
|
100
|
+
index.items[itemIndex].priority = args.priority;
|
|
101
|
+
if (args.title)
|
|
102
|
+
index.items[itemIndex].title = args.title;
|
|
103
|
+
index.items[itemIndex].updated = metadata.updated;
|
|
104
|
+
// Update stats
|
|
105
|
+
if (args.status && oldStatus !== args.status) {
|
|
106
|
+
index.stats = index.stats || { total: 0, by_type: {}, by_status: {} };
|
|
107
|
+
index.stats.by_status[oldStatus] = (index.stats.by_status[oldStatus] || 1) - 1;
|
|
108
|
+
index.stats.by_status[args.status] = (index.stats.by_status[args.status] || 0) + 1;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
index.last_updated = metadata.updated;
|
|
112
|
+
writeFileSync(indexPath, JSON.stringify(index, null, 2));
|
|
113
|
+
return {
|
|
114
|
+
metadata,
|
|
115
|
+
oldStatus,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/core/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ItemType, Methodology } from '../schemas/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validation result with detailed error messaging
|
|
4
|
+
*/
|
|
5
|
+
export interface ValidationResult {
|
|
6
|
+
valid: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
suggestion?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Minimal work item info needed for validation
|
|
12
|
+
*/
|
|
13
|
+
export interface WorkItem {
|
|
14
|
+
id: string;
|
|
15
|
+
type: ItemType;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Validate relationship between two items based on methodology
|
|
19
|
+
* Only validates "implements" relationships - all other relations are flexible
|
|
20
|
+
*
|
|
21
|
+
* @param source - Item creating the relationship (child in hierarchy)
|
|
22
|
+
* @param target - Item being referenced (parent in hierarchy)
|
|
23
|
+
* @param relationType - Type of relationship
|
|
24
|
+
* @param methodology - Project methodology (scrum, waterfall, hybrid)
|
|
25
|
+
* @returns ValidationResult with valid flag and optional error/suggestion
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateRelationship(source: WorkItem, target: WorkItem, relationType: string, methodology: Methodology): ValidationResult;
|
|
28
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGjE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,QAAQ,EAChB,MAAM,EAAE,QAAQ,EAChB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,WAAW,GACvB,gBAAgB,CA8ClB"}
|