@schnick371/devsteps-shared 0.0.1 → 0.5.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.
Files changed (104) hide show
  1. package/README.md +66 -7
  2. package/dist/core/add.d.ts +23 -0
  3. package/dist/core/add.d.ts.map +1 -0
  4. package/dist/core/add.js +102 -0
  5. package/dist/core/add.js.map +1 -0
  6. package/dist/core/archive.d.ts +24 -0
  7. package/dist/core/archive.d.ts.map +1 -0
  8. package/dist/core/archive.js +109 -0
  9. package/dist/core/archive.js.map +1 -0
  10. package/dist/core/bulk-update.d.ts +34 -0
  11. package/dist/core/bulk-update.d.ts.map +1 -0
  12. package/dist/core/bulk-update.js +141 -0
  13. package/dist/core/bulk-update.js.map +1 -0
  14. package/dist/core/context.d.ts +54 -0
  15. package/dist/core/context.d.ts.map +1 -0
  16. package/dist/core/context.js +198 -0
  17. package/dist/core/context.js.map +1 -0
  18. package/dist/core/get.d.ts +10 -0
  19. package/dist/core/get.d.ts.map +1 -0
  20. package/dist/core/get.js +28 -0
  21. package/dist/core/get.js.map +1 -0
  22. package/dist/core/index.d.ts +9 -0
  23. package/dist/core/index.d.ts.map +1 -0
  24. package/dist/core/index.js +9 -0
  25. package/dist/core/index.js.map +1 -0
  26. package/dist/core/list.d.ts +19 -0
  27. package/dist/core/list.d.ts.map +1 -0
  28. package/dist/core/list.js +64 -0
  29. package/dist/core/list.js.map +1 -0
  30. package/dist/core/update.d.ts +23 -0
  31. package/dist/core/update.d.ts.map +1 -0
  32. package/dist/core/update.js +118 -0
  33. package/dist/core/update.js.map +1 -0
  34. package/dist/core/validation.d.ts +28 -0
  35. package/dist/core/validation.d.ts.map +1 -0
  36. package/dist/core/validation.js +205 -0
  37. package/dist/core/validation.js.map +1 -0
  38. package/dist/index.d.ts +5 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +5 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/schemas/index.d.ts +286 -0
  43. package/dist/schemas/index.d.ts.map +1 -0
  44. package/dist/schemas/index.js +200 -0
  45. package/dist/schemas/index.js.map +1 -0
  46. package/dist/schemas/project.d.ts +134 -0
  47. package/dist/schemas/project.d.ts.map +1 -0
  48. package/dist/schemas/project.js +54 -0
  49. package/dist/schemas/project.js.map +1 -0
  50. package/dist/schemas/relationships.d.ts +30 -0
  51. package/dist/schemas/relationships.d.ts.map +1 -0
  52. package/dist/schemas/relationships.js +41 -0
  53. package/dist/schemas/relationships.js.map +1 -0
  54. package/dist/types/commands.d.ts +92 -0
  55. package/dist/types/commands.d.ts.map +1 -0
  56. package/dist/types/commands.js +14 -0
  57. package/dist/types/commands.js.map +1 -0
  58. package/dist/types/index.d.ts +3 -0
  59. package/dist/types/index.d.ts.map +1 -0
  60. package/dist/types/index.js +2 -0
  61. package/dist/types/index.js.map +1 -0
  62. package/dist/utils/cache.d.ts +80 -0
  63. package/dist/utils/cache.d.ts.map +1 -0
  64. package/dist/utils/cache.js +169 -0
  65. package/dist/utils/cache.js.map +1 -0
  66. package/dist/utils/index.d.ts +72 -0
  67. package/dist/utils/index.d.ts.map +1 -0
  68. package/dist/utils/index.js +148 -0
  69. package/dist/utils/index.js.map +1 -0
  70. package/package.json +48 -15
  71. package/src/core/add.js.map +1 -0
  72. package/src/core/add.ts +145 -0
  73. package/src/core/archive.js.map +1 -0
  74. package/src/core/archive.ts +153 -0
  75. package/src/core/bulk-update.js.map +1 -0
  76. package/src/core/bulk-update.ts +180 -0
  77. package/src/core/context.js.map +1 -0
  78. package/src/core/context.ts +269 -0
  79. package/src/core/get.js.map +1 -0
  80. package/src/core/get.ts +39 -0
  81. package/src/core/index.js.map +1 -0
  82. package/src/core/index.ts +26 -0
  83. package/src/core/list.js.map +1 -0
  84. package/src/core/list.ts +96 -0
  85. package/src/core/update.js.map +1 -0
  86. package/src/core/update.ts +154 -0
  87. package/src/core/validation.ts +252 -0
  88. package/src/index.js +21 -0
  89. package/src/index.js.map +1 -0
  90. package/src/index.ts +4 -0
  91. package/src/schemas/index.js.map +1 -0
  92. package/src/schemas/index.ts +226 -0
  93. package/src/schemas/project.js.map +1 -0
  94. package/src/schemas/project.ts +73 -0
  95. package/src/schemas/relationships.ts +48 -0
  96. package/src/types/commands.js.map +1 -0
  97. package/src/types/commands.ts +116 -0
  98. package/src/types/index.js.map +1 -0
  99. package/src/types/index.ts +13 -0
  100. package/src/utils/cache.js.map +1 -0
  101. package/src/utils/cache.ts +200 -0
  102. package/src/utils/index.js.map +1 -0
  103. package/src/utils/index.ts +170 -0
  104. package/index.js +0 -6
@@ -0,0 +1,116 @@
1
+ import type { EisenhowerQuadrant, ItemType, Priority } from '../schemas/index.js';
2
+
3
+ /**
4
+ * Central type shortcuts mapping
5
+ */
6
+ export const TYPE_SHORTCUTS: Record<string, ItemType> = {
7
+ epic: 'epic',
8
+ story: 'story',
9
+ task: 'task',
10
+ req: 'requirement',
11
+ feat: 'feature',
12
+ bug: 'bug',
13
+ spike: 'spike',
14
+ test: 'test',
15
+ } as const;
16
+
17
+ /**
18
+ * Command argument types - central source of truth
19
+ */
20
+
21
+ export interface AddItemCommandArgs {
22
+ type: string; // Will be mapped via TYPE_SHORTCUTS
23
+ title: string;
24
+ description?: string;
25
+ category?: string;
26
+ priority?: string;
27
+ eisenhower?: string;
28
+ tags?: string[];
29
+ assignee?: string;
30
+ paths?: string[];
31
+ }
32
+
33
+ export interface UpdateItemCommandArgs {
34
+ id: string;
35
+ status?: string;
36
+ priority?: string;
37
+ eisenhower?: string;
38
+ superseded_by?: string;
39
+ title?: string;
40
+ description?: string;
41
+ assignee?: string;
42
+ tags?: string[];
43
+ paths?: string[];
44
+ }
45
+
46
+ export interface ListItemsCommandArgs {
47
+ type?: string;
48
+ status?: string;
49
+ priority?: string;
50
+ eisenhower?: string;
51
+ assignee?: string;
52
+ tags?: string[];
53
+ archived?: boolean;
54
+ limit?: string;
55
+ }
56
+
57
+ export interface SearchItemsCommandArgs {
58
+ query: string;
59
+ type?: string;
60
+ limit?: string;
61
+ }
62
+
63
+ export interface StatusCommandArgs {
64
+ detailed?: boolean;
65
+ }
66
+
67
+ export interface TraceCommandArgs {
68
+ id: string;
69
+ depth?: string;
70
+ }
71
+
72
+ export interface ExportCommandArgs {
73
+ format?: string;
74
+ output?: string;
75
+ types?: string[];
76
+ }
77
+
78
+ export interface ArchiveCommandArgs {
79
+ id: string;
80
+ }
81
+
82
+ export interface PurgeCommandArgs {
83
+ status?: string[];
84
+ type?: string;
85
+ }
86
+
87
+ /**
88
+ * Response types
89
+ */
90
+
91
+ export interface CommandSuccessResponse {
92
+ success: true;
93
+ message: string;
94
+ [key: string]: unknown;
95
+ }
96
+
97
+ export interface CommandErrorResponse {
98
+ success: false;
99
+ error: string;
100
+ }
101
+
102
+ export type CommandResponse = CommandSuccessResponse | CommandErrorResponse;
103
+
104
+ /**
105
+ * Index item summary type (from index.json)
106
+ */
107
+ export interface IndexItem {
108
+ id: string;
109
+ type: ItemType;
110
+ title: string;
111
+ status: string;
112
+ priority: Priority;
113
+ updated: string;
114
+ tags?: string[];
115
+ category?: string;
116
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAYA,gDAA8B"}
@@ -0,0 +1,13 @@
1
+ export type {
2
+ ItemType,
3
+ ItemStatus,
4
+ Priority,
5
+ RelationType,
6
+ LinkedItems,
7
+ GitCommit,
8
+ ItemMetadata,
9
+ DevCrumbsConfig,
10
+ DevCrumbsIndex,
11
+ } from '../schemas/index.js';
12
+
13
+ export * from './commands.js';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ import { statSync } from 'node:fs';
2
+
3
+ interface CacheEntry<T> {
4
+ data: T;
5
+ timestamp: number;
6
+ mtime?: number; // for file-based invalidation
7
+ }
8
+
9
+ export interface CacheStats {
10
+ size: number;
11
+ keys: string[];
12
+ hits: number;
13
+ misses: number;
14
+ hitRate: number;
15
+ }
16
+
17
+ /**
18
+ * Cache configuration
19
+ */
20
+ export const CACHE_CONFIG = {
21
+ PROJECT_MD_TTL: 60 * 60 * 1000, // 1 hour
22
+ PACKAGE_ANALYSIS_TTL: 30 * 60 * 1000, // 30 minutes
23
+ ITEM_COUNTS_TTL: 5 * 60 * 1000, // 5 minutes
24
+ RECENT_UPDATES_TTL: 1 * 60 * 1000, // 1 minute
25
+ MAX_CACHE_SIZE: 1000, // Maximum number of cache entries
26
+ };
27
+
28
+ /**
29
+ * Smart context cache with TTL and file-based invalidation
30
+ */
31
+ export class ContextCache {
32
+ private cache = new Map<string, CacheEntry<unknown>>();
33
+ private hits = 0;
34
+ private misses = 0;
35
+
36
+ /**
37
+ * Get cached value
38
+ * @param key Cache key
39
+ * @param maxAge Maximum age in milliseconds
40
+ * @param filePath Optional file path for mtime-based invalidation
41
+ * @returns Cached value or null if invalid/expired
42
+ */
43
+ get<T>(key: string, maxAge: number, filePath?: string): T | null {
44
+ const entry = this.cache.get(key);
45
+
46
+ if (!entry) {
47
+ this.misses++;
48
+ return null;
49
+ }
50
+
51
+ // Check file modification time
52
+ if (filePath && entry.mtime !== undefined) {
53
+ try {
54
+ const currentMtime = statSync(filePath).mtimeMs;
55
+ if (currentMtime > entry.mtime) {
56
+ this.cache.delete(key);
57
+ this.misses++;
58
+ return null;
59
+ }
60
+ } catch {
61
+ // File doesn't exist anymore, invalidate cache
62
+ this.cache.delete(key);
63
+ this.misses++;
64
+ return null;
65
+ }
66
+ }
67
+
68
+ // Check TTL
69
+ if (Date.now() - entry.timestamp > maxAge) {
70
+ this.cache.delete(key);
71
+ this.misses++;
72
+ return null;
73
+ }
74
+
75
+ this.hits++;
76
+ return entry.data as T;
77
+ }
78
+
79
+ /**
80
+ * Set cached value
81
+ * @param key Cache key
82
+ * @param data Data to cache
83
+ * @param filePath Optional file path for mtime tracking
84
+ */
85
+ set<T>(key: string, data: T, filePath?: string): void {
86
+ // Enforce max cache size (simple LRU: remove oldest)
87
+ if (this.cache.size >= CACHE_CONFIG.MAX_CACHE_SIZE) {
88
+ const firstKey = this.cache.keys().next().value;
89
+ if (firstKey) {
90
+ this.cache.delete(firstKey);
91
+ }
92
+ }
93
+
94
+ let mtime: number | undefined;
95
+ if (filePath) {
96
+ try {
97
+ mtime = statSync(filePath).mtimeMs;
98
+ } catch {
99
+ // File doesn't exist, don't track mtime
100
+ mtime = undefined;
101
+ }
102
+ }
103
+
104
+ this.cache.set(key, {
105
+ data,
106
+ timestamp: Date.now(),
107
+ mtime,
108
+ });
109
+ }
110
+
111
+ /**
112
+ * Check if key exists and is valid
113
+ * @param key Cache key
114
+ * @param maxAge Maximum age in milliseconds
115
+ * @param filePath Optional file path for mtime-based invalidation
116
+ * @returns true if valid cached value exists
117
+ */
118
+ has(key: string, maxAge: number, filePath?: string): boolean {
119
+ return this.get(key, maxAge, filePath) !== null;
120
+ }
121
+
122
+ /**
123
+ * Clear entire cache
124
+ */
125
+ clear(): void {
126
+ this.cache.clear();
127
+ this.hits = 0;
128
+ this.misses = 0;
129
+ }
130
+
131
+ /**
132
+ * Clear specific cache key
133
+ * @param key Cache key to clear
134
+ */
135
+ delete(key: string): boolean {
136
+ return this.cache.delete(key);
137
+ }
138
+
139
+ /**
140
+ * Clear cache entries matching pattern
141
+ * @param pattern Regex pattern to match keys
142
+ */
143
+ clearPattern(pattern: RegExp): number {
144
+ let cleared = 0;
145
+ for (const key of this.cache.keys()) {
146
+ if (pattern.test(key)) {
147
+ this.cache.delete(key);
148
+ cleared++;
149
+ }
150
+ }
151
+ return cleared;
152
+ }
153
+
154
+ /**
155
+ * Get cache statistics
156
+ * @returns Cache statistics including hit rate
157
+ */
158
+ stats(): CacheStats {
159
+ const total = this.hits + this.misses;
160
+ const hitRate = total > 0 ? this.hits / total : 0;
161
+
162
+ return {
163
+ size: this.cache.size,
164
+ keys: Array.from(this.cache.keys()),
165
+ hits: this.hits,
166
+ misses: this.misses,
167
+ hitRate: Math.round(hitRate * 100) / 100,
168
+ };
169
+ }
170
+
171
+ /**
172
+ * Reset hit/miss counters
173
+ */
174
+ resetStats(): void {
175
+ this.hits = 0;
176
+ this.misses = 0;
177
+ }
178
+ }
179
+
180
+ // Global singleton instance
181
+ let globalCache: ContextCache | null = null;
182
+
183
+ /**
184
+ * Get or create global cache instance
185
+ */
186
+ export function getCache(): ContextCache {
187
+ if (!globalCache) {
188
+ globalCache = new ContextCache();
189
+ }
190
+ return globalCache;
191
+ }
192
+
193
+ /**
194
+ * Clear global cache
195
+ */
196
+ export function clearGlobalCache(): void {
197
+ if (globalCache) {
198
+ globalCache.clear();
199
+ }
200
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ import type { ItemType, Methodology } from '../schemas/index.js';
2
+
3
+ // Export cache utilities
4
+ export {
5
+ ContextCache,
6
+ CACHE_CONFIG,
7
+ getCache,
8
+ clearGlobalCache,
9
+ type CacheStats,
10
+ } from './cache.js';
11
+
12
+ /**
13
+ * Type to plural directory mapping
14
+ */
15
+ export const TYPE_TO_DIRECTORY: Record<ItemType, string> = {
16
+ epic: 'epics',
17
+ story: 'stories',
18
+ task: 'tasks',
19
+ requirement: 'requirements',
20
+ feature: 'features',
21
+ bug: 'bugs',
22
+ spike: 'spikes',
23
+ test: 'tests',
24
+ };
25
+
26
+ /**
27
+ * Get methodology configuration
28
+ */
29
+ export function getMethodologyConfig(methodology: Methodology) {
30
+ const configs = {
31
+ scrum: {
32
+ item_types: ['epic', 'story', 'task', 'bug', 'spike', 'test'] as ItemType[],
33
+ item_prefixes: {
34
+ epic: 'EPIC',
35
+ story: 'STORY',
36
+ task: 'TASK',
37
+ bug: 'BUG',
38
+ spike: 'SPIKE',
39
+ test: 'TEST',
40
+ },
41
+ directories: ['epics', 'stories', 'tasks', 'bugs', 'spikes', 'tests'],
42
+ },
43
+ waterfall: {
44
+ item_types: ['requirement', 'feature', 'task', 'bug', 'test'] as ItemType[],
45
+ item_prefixes: {
46
+ requirement: 'REQ',
47
+ feature: 'FEAT',
48
+ task: 'TASK',
49
+ bug: 'BUG',
50
+ test: 'TEST',
51
+ },
52
+ directories: ['requirements', 'features', 'tasks', 'bugs', 'tests'],
53
+ },
54
+ hybrid: {
55
+ item_types: [
56
+ 'epic',
57
+ 'story',
58
+ 'requirement',
59
+ 'feature',
60
+ 'task',
61
+ 'bug',
62
+ 'spike',
63
+ 'test',
64
+ ] as ItemType[],
65
+ item_prefixes: {
66
+ epic: 'EPIC',
67
+ story: 'STORY',
68
+ requirement: 'REQ',
69
+ feature: 'FEAT',
70
+ task: 'TASK',
71
+ bug: 'BUG',
72
+ spike: 'SPIKE',
73
+ test: 'TEST',
74
+ },
75
+ directories: [
76
+ 'epics',
77
+ 'stories',
78
+ 'requirements',
79
+ 'features',
80
+ 'tasks',
81
+ 'bugs',
82
+ 'spikes',
83
+ 'tests',
84
+ ],
85
+ },
86
+ };
87
+
88
+ return configs[methodology];
89
+ }
90
+
91
+ /**
92
+ * Generates a new item ID with proper prefix and number
93
+ */
94
+ export function generateItemId(
95
+ type: string,
96
+ counter: number,
97
+ prefixes?: Record<string, string>
98
+ ): string {
99
+ const defaultPrefixes: Record<string, string> = {
100
+ epic: 'EPIC',
101
+ story: 'STORY',
102
+ task: 'TASK',
103
+ requirement: 'REQ',
104
+ feature: 'FEAT',
105
+ bug: 'BUG',
106
+ spike: 'SPIKE',
107
+ test: 'TEST',
108
+ };
109
+
110
+ const prefixMap = prefixes || defaultPrefixes;
111
+ const prefix = prefixMap[type] || 'ITEM';
112
+ const paddedNumber = counter.toString().padStart(3, '0');
113
+ return `${prefix}-${paddedNumber}`;
114
+ }
115
+
116
+ /**
117
+ * Parses an item ID into type and number
118
+ */
119
+ export function parseItemId(id: string): { type: ItemType; number: number } | null {
120
+ const match = id.match(/^(EPIC|STORY|TASK|REQ|FEAT|BUG|SPIKE|TEST)-(\d+)$/);
121
+ if (!match) return null;
122
+
123
+ const typeMap: Record<string, ItemType> = {
124
+ EPIC: 'epic',
125
+ STORY: 'story',
126
+ TASK: 'task',
127
+ REQ: 'requirement',
128
+ FEAT: 'feature',
129
+ BUG: 'bug',
130
+ SPIKE: 'spike',
131
+ TEST: 'test',
132
+ };
133
+
134
+ return {
135
+ type: typeMap[match[1]],
136
+ number: Number.parseInt(match[2], 10),
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Formats a date for display
142
+ */
143
+ export function formatDate(date: string | Date): string {
144
+ const d = typeof date === 'string' ? new Date(date) : date;
145
+ return d.toISOString();
146
+ }
147
+
148
+ /**
149
+ * Gets current timestamp in ISO format
150
+ */
151
+ export function getCurrentTimestamp(): string {
152
+ return new Date().toISOString();
153
+ }
154
+
155
+ /**
156
+ * Validates email format
157
+ */
158
+ export function isValidEmail(email: string): boolean {
159
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
160
+ }
161
+
162
+ /**
163
+ * Sanitizes a string for use in filenames
164
+ */
165
+ export function sanitizeFilename(name: string): string {
166
+ return name
167
+ .toLowerCase()
168
+ .replace(/[^a-z0-9]+/g, '-')
169
+ .replace(/^-|-$/g, '');
170
+ }
package/index.js DELETED
@@ -1,6 +0,0 @@
1
- // DevSteps Shared - Reserved Package
2
- // Full implementation coming soon
3
- module.exports = {
4
- version: '0.0.1',
5
- status: 'reserved'
6
- };