sqlew 2.1.4 → 3.0.2

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 (84) hide show
  1. package/CHANGELOG.md +891 -605
  2. package/README.md +302 -690
  3. package/assets/kanban-style.png +0 -0
  4. package/assets/schema.sql +531 -402
  5. package/dist/database.d.ts +9 -0
  6. package/dist/database.d.ts.map +1 -1
  7. package/dist/database.js +33 -34
  8. package/dist/database.js.map +1 -1
  9. package/dist/index.js +1024 -213
  10. package/dist/index.js.map +1 -1
  11. package/dist/migrations/add-task-tables.d.ts +47 -0
  12. package/dist/migrations/add-task-tables.d.ts.map +1 -0
  13. package/dist/migrations/add-task-tables.js +285 -0
  14. package/dist/migrations/add-task-tables.js.map +1 -0
  15. package/dist/migrations/index.d.ts +96 -0
  16. package/dist/migrations/index.d.ts.map +1 -0
  17. package/dist/migrations/index.js +239 -0
  18. package/dist/migrations/index.js.map +1 -0
  19. package/dist/migrations/migrate-decisions-to-tasks.d.ts +61 -0
  20. package/dist/migrations/migrate-decisions-to-tasks.d.ts.map +1 -0
  21. package/dist/migrations/migrate-decisions-to-tasks.js +442 -0
  22. package/dist/migrations/migrate-decisions-to-tasks.js.map +1 -0
  23. package/dist/schema.d.ts.map +1 -1
  24. package/dist/schema.js +14 -3
  25. package/dist/schema.js.map +1 -1
  26. package/dist/tools/constraints.d.ts +4 -0
  27. package/dist/tools/constraints.d.ts.map +1 -1
  28. package/dist/tools/constraints.js +6 -27
  29. package/dist/tools/constraints.js.map +1 -1
  30. package/dist/tools/context.d.ts +17 -1
  31. package/dist/tools/context.d.ts.map +1 -1
  32. package/dist/tools/context.js +195 -190
  33. package/dist/tools/context.js.map +1 -1
  34. package/dist/tools/files.d.ts.map +1 -1
  35. package/dist/tools/files.js +113 -166
  36. package/dist/tools/files.js.map +1 -1
  37. package/dist/tools/messaging.d.ts +2 -9
  38. package/dist/tools/messaging.d.ts.map +1 -1
  39. package/dist/tools/messaging.js +67 -126
  40. package/dist/tools/messaging.js.map +1 -1
  41. package/dist/tools/tasks.d.ts +90 -0
  42. package/dist/tools/tasks.d.ts.map +1 -0
  43. package/dist/tools/tasks.js +732 -0
  44. package/dist/tools/tasks.js.map +1 -0
  45. package/dist/tools/utils.d.ts +8 -1
  46. package/dist/tools/utils.d.ts.map +1 -1
  47. package/dist/tools/utils.js +50 -21
  48. package/dist/tools/utils.js.map +1 -1
  49. package/dist/types.d.ts +14 -0
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/utils/batch.d.ts +69 -0
  52. package/dist/utils/batch.d.ts.map +1 -0
  53. package/dist/utils/batch.js +148 -0
  54. package/dist/utils/batch.js.map +1 -0
  55. package/dist/utils/query-builder.d.ts +68 -0
  56. package/dist/utils/query-builder.d.ts.map +1 -0
  57. package/dist/utils/query-builder.js +116 -0
  58. package/dist/utils/query-builder.js.map +1 -0
  59. package/dist/utils/task-stale-detection.d.ts +28 -0
  60. package/dist/utils/task-stale-detection.d.ts.map +1 -0
  61. package/dist/utils/task-stale-detection.js +92 -0
  62. package/dist/utils/task-stale-detection.js.map +1 -0
  63. package/dist/utils/validators.d.ts +57 -0
  64. package/dist/utils/validators.d.ts.map +1 -0
  65. package/dist/utils/validators.js +117 -0
  66. package/dist/utils/validators.js.map +1 -0
  67. package/docs/AI_AGENT_GUIDE.md +1471 -648
  68. package/{ARCHITECTURE.md → docs/ARCHITECTURE.md} +636 -636
  69. package/docs/BEST_PRACTICES.md +481 -0
  70. package/docs/DECISION_TO_TASK_MIGRATION_GUIDE.md +457 -0
  71. package/docs/MIGRATION_CHAIN.md +280 -0
  72. package/{MIGRATION_v2.md → docs/MIGRATION_v2.md} +538 -538
  73. package/docs/SHARED_CONCEPTS.md +339 -0
  74. package/docs/TASK_ACTIONS.md +854 -0
  75. package/docs/TASK_LINKING.md +729 -0
  76. package/docs/TASK_MIGRATION.md +701 -0
  77. package/docs/TASK_OVERVIEW.md +363 -0
  78. package/docs/TASK_SYSTEM.md +1244 -0
  79. package/docs/TOOL_REFERENCE.md +471 -0
  80. package/docs/TOOL_SELECTION.md +279 -0
  81. package/docs/WORKFLOWS.md +602 -0
  82. package/docs/refactoring-summary-2025-10-17.md +365 -0
  83. package/docs/requirement-2025-10-17.md +508 -0
  84. package/package.json +64 -64
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Query builder utilities for dynamic SQL query construction
3
+ * Eliminates duplicated WHERE clause building across tool files
4
+ */
5
+ /**
6
+ * Build WHERE clause from filter conditions
7
+ * Returns both the SQL fragment and parameter array
8
+ *
9
+ * @param conditions - Array of filter conditions
10
+ * @returns Object with whereClause SQL and params array
11
+ */
12
+ export function buildWhereClause(conditions) {
13
+ if (conditions.length === 0) {
14
+ return { whereClause: '', params: [] };
15
+ }
16
+ const clauses = [];
17
+ const params = [];
18
+ for (const condition of conditions) {
19
+ switch (condition.type) {
20
+ case 'equals':
21
+ clauses.push(`${condition.field} = ?`);
22
+ params.push(condition.value);
23
+ break;
24
+ case 'like':
25
+ clauses.push(`${condition.field} LIKE ?`);
26
+ params.push(`%${condition.value}%`);
27
+ break;
28
+ case 'notLike':
29
+ clauses.push(`(${condition.field} IS NULL OR (${condition.field} NOT LIKE ? AND ${condition.field} != ?))`);
30
+ params.push(`%${condition.value}%`, condition.value);
31
+ break;
32
+ case 'greaterThanOrEqual':
33
+ clauses.push(`${condition.field} >= ?`);
34
+ params.push(condition.value);
35
+ break;
36
+ case 'lessThanOrEqual':
37
+ clauses.push(`${condition.field} <= ?`);
38
+ params.push(condition.value);
39
+ break;
40
+ case 'in':
41
+ if (condition.values.length > 0) {
42
+ if (condition.operator === 'OR') {
43
+ // Match any value (OR logic)
44
+ const inConditions = condition.values.map(() => `${condition.field} = ?`).join(' OR ');
45
+ clauses.push(`(${inConditions})`);
46
+ params.push(...condition.values);
47
+ }
48
+ else {
49
+ // Match all values (AND logic) - typically not used for IN, but included for completeness
50
+ for (const value of condition.values) {
51
+ clauses.push(`${condition.field} = ?`);
52
+ params.push(value);
53
+ }
54
+ }
55
+ }
56
+ break;
57
+ case 'likeAny':
58
+ if (condition.values.length > 0) {
59
+ if (condition.operator === 'OR') {
60
+ // Match any value with LIKE (OR logic)
61
+ const likeConditions = condition.values.map(() => `${condition.field} LIKE ?`).join(' OR ');
62
+ clauses.push(`(${likeConditions})`);
63
+ for (const value of condition.values) {
64
+ params.push(`%${value}%`);
65
+ }
66
+ }
67
+ else {
68
+ // Match all values with LIKE (AND logic)
69
+ for (const value of condition.values) {
70
+ clauses.push(`${condition.field} LIKE ?`);
71
+ params.push(`%${value}%`);
72
+ }
73
+ }
74
+ }
75
+ break;
76
+ case 'likeExclude':
77
+ if (condition.values.length > 0) {
78
+ // Exclude all specified values (NOT LIKE for each)
79
+ for (const value of condition.values) {
80
+ clauses.push(`(${condition.field} IS NULL OR (${condition.field} NOT LIKE ? AND ${condition.field} != ?))`);
81
+ params.push(`%${value}%`, value);
82
+ }
83
+ }
84
+ break;
85
+ }
86
+ }
87
+ const whereClause = clauses.length > 0 ? ' AND ' + clauses.join(' AND ') : '';
88
+ return { whereClause, params };
89
+ }
90
+ /**
91
+ * Build complete query with WHERE clause, ORDER BY, and LIMIT
92
+ *
93
+ * @param baseQuery - Base SELECT query (e.g., "SELECT * FROM table WHERE 1=1")
94
+ * @param conditions - Filter conditions
95
+ * @param orderBy - ORDER BY clause (e.g., "updated DESC")
96
+ * @param limit - LIMIT value
97
+ * @param offset - OFFSET value (optional)
98
+ * @returns Object with complete SQL query and params array
99
+ */
100
+ export function buildCompleteQuery(baseQuery, conditions, orderBy, limit, offset) {
101
+ const { whereClause, params } = buildWhereClause(conditions);
102
+ let query = baseQuery + whereClause;
103
+ if (orderBy) {
104
+ query += ` ORDER BY ${orderBy}`;
105
+ }
106
+ if (limit !== undefined) {
107
+ query += ' LIMIT ?';
108
+ params.push(limit);
109
+ }
110
+ if (offset !== undefined && offset > 0) {
111
+ query += ' OFFSET ?';
112
+ params.push(offset);
113
+ }
114
+ return { query, params };
115
+ }
116
+ //# sourceMappingURL=query-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-builder.js","sourceRoot":"","sources":["../../src/utils/query-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Auto-stale detection for Kanban Task Watcher
3
+ * Automatically transitions abandoned tasks based on time thresholds
4
+ */
5
+ import { Database } from '../types.js';
6
+ /**
7
+ * Detect and transition stale tasks automatically
8
+ *
9
+ * Detection logic:
10
+ * - Tasks in `in_progress` with `updated_ts` older than threshold → move to `waiting_review`
11
+ * - Tasks in `waiting_review` with `updated_ts` older than threshold → move to `todo`
12
+ *
13
+ * @param db - Database instance
14
+ * @returns Count of transitioned tasks
15
+ */
16
+ export declare function detectAndTransitionStaleTasks(db: Database): number;
17
+ /**
18
+ * Get current auto-stale configuration
19
+ *
20
+ * @param db - Database instance
21
+ * @returns Current configuration values
22
+ */
23
+ export declare function getStaleDetectionConfig(db: Database): {
24
+ enabled: boolean;
25
+ inProgressThresholdHours: number;
26
+ waitingReviewThresholdHours: number;
27
+ };
28
+ //# sourceMappingURL=task-stale-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-stale-detection.d.ts","sourceRoot":"","sources":["../../src/utils/task-stale-detection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA8BvC;;;;;;;;;GASG;AACH,wBAAgB,6BAA6B,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAqElE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,QAAQ,GAAG;IACrD,OAAO,EAAE,OAAO,CAAC;IACjB,wBAAwB,EAAE,MAAM,CAAC;IACjC,2BAA2B,EAAE,MAAM,CAAC;CACrC,CAkBA"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Auto-stale detection for Kanban Task Watcher
3
+ * Automatically transitions abandoned tasks based on time thresholds
4
+ */
5
+ import { getConfigBool, getConfigInt } from '../database.js';
6
+ /**
7
+ * Task status IDs (matching schema)
8
+ */
9
+ const TASK_STATUS = {
10
+ TODO: 1,
11
+ IN_PROGRESS: 2,
12
+ WAITING_REVIEW: 3,
13
+ };
14
+ /**
15
+ * Configuration keys for task stale detection
16
+ */
17
+ const CONFIG_KEYS = {
18
+ TASK_STALE_HOURS_IN_PROGRESS: 'task_stale_hours_in_progress',
19
+ TASK_STALE_HOURS_WAITING_REVIEW: 'task_stale_hours_waiting_review',
20
+ TASK_AUTO_STALE_ENABLED: 'task_auto_stale_enabled',
21
+ };
22
+ /**
23
+ * Default configuration values
24
+ */
25
+ const DEFAULTS = {
26
+ STALE_HOURS_IN_PROGRESS: 2,
27
+ STALE_HOURS_WAITING_REVIEW: 24,
28
+ AUTO_STALE_ENABLED: true,
29
+ };
30
+ /**
31
+ * Detect and transition stale tasks automatically
32
+ *
33
+ * Detection logic:
34
+ * - Tasks in `in_progress` with `updated_ts` older than threshold → move to `waiting_review`
35
+ * - Tasks in `waiting_review` with `updated_ts` older than threshold → move to `todo`
36
+ *
37
+ * @param db - Database instance
38
+ * @returns Count of transitioned tasks
39
+ */
40
+ export function detectAndTransitionStaleTasks(db) {
41
+ // 1. Check if auto-stale is enabled
42
+ const isEnabled = getConfigBool(db, CONFIG_KEYS.TASK_AUTO_STALE_ENABLED, DEFAULTS.AUTO_STALE_ENABLED);
43
+ if (!isEnabled) {
44
+ return 0;
45
+ }
46
+ // 2. Get threshold configs (in hours)
47
+ const inProgressThresholdHours = getConfigInt(db, CONFIG_KEYS.TASK_STALE_HOURS_IN_PROGRESS, DEFAULTS.STALE_HOURS_IN_PROGRESS);
48
+ const waitingReviewThresholdHours = getConfigInt(db, CONFIG_KEYS.TASK_STALE_HOURS_WAITING_REVIEW, DEFAULTS.STALE_HOURS_WAITING_REVIEW);
49
+ // Convert hours to seconds for timestamp comparison
50
+ const inProgressThresholdSeconds = inProgressThresholdHours * 3600;
51
+ const waitingReviewThresholdSeconds = waitingReviewThresholdHours * 3600;
52
+ let totalTransitioned = 0;
53
+ // 3. Transition stale tasks in a transaction
54
+ const updateStmt = db.transaction(() => {
55
+ // 3a. Find and transition in_progress tasks older than threshold to waiting_review
56
+ const inProgressTransitioned = db.prepare(`
57
+ UPDATE t_tasks
58
+ SET status_id = ?,
59
+ updated_ts = unixepoch()
60
+ WHERE status_id = ?
61
+ AND updated_ts < unixepoch() - ?
62
+ `).run(TASK_STATUS.WAITING_REVIEW, TASK_STATUS.IN_PROGRESS, inProgressThresholdSeconds);
63
+ totalTransitioned += inProgressTransitioned.changes;
64
+ // 3b. Find and transition waiting_review tasks older than threshold to todo
65
+ const waitingReviewTransitioned = db.prepare(`
66
+ UPDATE t_tasks
67
+ SET status_id = ?,
68
+ updated_ts = unixepoch()
69
+ WHERE status_id = ?
70
+ AND updated_ts < unixepoch() - ?
71
+ `).run(TASK_STATUS.TODO, TASK_STATUS.WAITING_REVIEW, waitingReviewThresholdSeconds);
72
+ totalTransitioned += waitingReviewTransitioned.changes;
73
+ });
74
+ // Execute the transaction
75
+ updateStmt();
76
+ // 4. Return count of transitioned tasks
77
+ return totalTransitioned;
78
+ }
79
+ /**
80
+ * Get current auto-stale configuration
81
+ *
82
+ * @param db - Database instance
83
+ * @returns Current configuration values
84
+ */
85
+ export function getStaleDetectionConfig(db) {
86
+ return {
87
+ enabled: getConfigBool(db, CONFIG_KEYS.TASK_AUTO_STALE_ENABLED, DEFAULTS.AUTO_STALE_ENABLED),
88
+ inProgressThresholdHours: getConfigInt(db, CONFIG_KEYS.TASK_STALE_HOURS_IN_PROGRESS, DEFAULTS.STALE_HOURS_IN_PROGRESS),
89
+ waitingReviewThresholdHours: getConfigInt(db, CONFIG_KEYS.TASK_STALE_HOURS_WAITING_REVIEW, DEFAULTS.STALE_HOURS_WAITING_REVIEW),
90
+ };
91
+ }
92
+ //# sourceMappingURL=task-stale-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-stale-detection.js","sourceRoot":"","sources":["../../src/utils/task-stale-detection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,IAAI,EAAE,CAAC;IACP,WAAW,EAAE,CAAC;IACd,cAAc,EAAE,CAAC;CACT,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,4BAA4B,EAAE,8BAA8B;IAC5D,+BAA+B,EAAE,iCAAiC;IAClE,uBAAuB,EAAE,yBAAyB;CAC1C,CAAC;AAEX;;GAEG;AACH,MAAM,QAAQ,GAAG;IACf,uBAAuB,EAAE,CAAC;IAC1B,0BAA0B,EAAE,EAAE;IAC9B,kBAAkB,EAAE,IAAI;CAChB,CAAC;AAEX;;;;;;;;;GASG;AACH,MAAM,UAAU,6BAA6B,CAAC,EAAY;IACxD,oCAAoC;IACpC,MAAM,SAAS,GAAG,aAAa,CAC7B,EAAE,EACF,WAAW,CAAC,uBAAuB,EACnC,QAAQ,CAAC,kBAAkB,CAC5B,CAAC;IAEF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,CAAC;IACX,CAAC;IAED,sCAAsC;IACtC,MAAM,wBAAwB,GAAG,YAAY,CAC3C,EAAE,EACF,WAAW,CAAC,4BAA4B,EACxC,QAAQ,CAAC,uBAAuB,CACjC,CAAC;IAEF,MAAM,2BAA2B,GAAG,YAAY,CAC9C,EAAE,EACF,WAAW,CAAC,+BAA+B,EAC3C,QAAQ,CAAC,0BAA0B,CACpC,CAAC;IAEF,oDAAoD;IACpD,MAAM,0BAA0B,GAAG,wBAAwB,GAAG,IAAI,CAAC;IACnE,MAAM,6BAA6B,GAAG,2BAA2B,GAAG,IAAI,CAAC;IAEzE,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAE1B,6CAA6C;IAC7C,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE;QACrC,mFAAmF;QACnF,MAAM,sBAAsB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;KAMzC,CAAC,CAAC,GAAG,CACJ,WAAW,CAAC,cAAc,EAC1B,WAAW,CAAC,WAAW,EACvB,0BAA0B,CAC3B,CAAC;QAEF,iBAAiB,IAAI,sBAAsB,CAAC,OAAO,CAAC;QAEpD,4EAA4E;QAC5E,MAAM,yBAAyB,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;;KAM5C,CAAC,CAAC,GAAG,CACJ,WAAW,CAAC,IAAI,EAChB,WAAW,CAAC,cAAc,EAC1B,6BAA6B,CAC9B,CAAC;QAEF,iBAAiB,IAAI,yBAAyB,CAAC,OAAO,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,UAAU,EAAE,CAAC;IAEb,wCAAwC;IACxC,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,EAAY;IAKlD,OAAO;QACL,OAAO,EAAE,aAAa,CACpB,EAAE,EACF,WAAW,CAAC,uBAAuB,EACnC,QAAQ,CAAC,kBAAkB,CAC5B;QACD,wBAAwB,EAAE,YAAY,CACpC,EAAE,EACF,WAAW,CAAC,4BAA4B,EACxC,QAAQ,CAAC,uBAAuB,CACjC;QACD,2BAA2B,EAAE,YAAY,CACvC,EAAE,EACF,WAAW,CAAC,+BAA+B,EAC3C,QAAQ,CAAC,0BAA0B,CACpC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Centralized validation utilities
3
+ * Phase 1 modularization - eliminates 27+ duplicate validation patterns
4
+ * Token savings: ~2,600 tokens across 5 tool files
5
+ */
6
+ import type { Database } from '../types.js';
7
+ /**
8
+ * Validates required string parameter (trim and check non-empty)
9
+ * @throws Error if value is empty or whitespace-only
10
+ */
11
+ export declare function validateRequired(value: string, paramName: string): string;
12
+ /**
13
+ * Validates status enum value
14
+ * @throws Error if status is not valid
15
+ */
16
+ export declare function validateStatus(status: string): 'active' | 'deprecated' | 'draft';
17
+ /**
18
+ * Validates priority string (low/medium/high/critical)
19
+ * @throws Error if priority is not valid
20
+ */
21
+ export declare function validatePriority(priority: string): 'low' | 'medium' | 'high' | 'critical';
22
+ /**
23
+ * Validates priority number (1-4 range)
24
+ * @throws Error if priority is out of range
25
+ */
26
+ export declare function validatePriorityRange(priority: number): number;
27
+ /**
28
+ * Validates layer and returns layer_id
29
+ * @throws Error if layer is invalid
30
+ */
31
+ export declare function validateLayer(db: Database, layer: string): number;
32
+ /**
33
+ * Validates message type enum
34
+ * @throws Error if message type is invalid
35
+ */
36
+ export declare function validateMessageType(msgType: string): 'decision' | 'warning' | 'request' | 'info';
37
+ /**
38
+ * Validates change type enum
39
+ * @throws Error if change type is invalid
40
+ */
41
+ export declare function validateChangeType(changeType: string): 'created' | 'modified' | 'deleted';
42
+ /**
43
+ * Validates category enum
44
+ * @throws Error if category is invalid
45
+ */
46
+ export declare function validateCategory(category: string): 'performance' | 'architecture' | 'security';
47
+ /**
48
+ * Validates string length
49
+ * @throws Error if string exceeds max length
50
+ */
51
+ export declare function validateLength(value: string, paramName: string, maxLength: number): string;
52
+ /**
53
+ * Validates number is within range
54
+ * @throws Error if number is out of range
55
+ */
56
+ export declare function validateRange(value: number, paramName: string, min: number, max: number): number;
57
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAMzE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAMhF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAMzF;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK9D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAWjE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAMhG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAMzF;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,GAAG,cAAc,GAAG,UAAU,CAM9F;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAK1F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAKhG"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Centralized validation utilities
3
+ * Phase 1 modularization - eliminates 27+ duplicate validation patterns
4
+ * Token savings: ~2,600 tokens across 5 tool files
5
+ */
6
+ /**
7
+ * Validates required string parameter (trim and check non-empty)
8
+ * @throws Error if value is empty or whitespace-only
9
+ */
10
+ export function validateRequired(value, paramName) {
11
+ const trimmed = value.trim();
12
+ if (!trimmed) {
13
+ throw new Error(`${paramName} is required`);
14
+ }
15
+ return trimmed;
16
+ }
17
+ /**
18
+ * Validates status enum value
19
+ * @throws Error if status is not valid
20
+ */
21
+ export function validateStatus(status) {
22
+ const validStatuses = ['active', 'deprecated', 'draft'];
23
+ if (!validStatuses.includes(status)) {
24
+ throw new Error(`Invalid status. Must be one of: ${validStatuses.join(', ')}`);
25
+ }
26
+ return status;
27
+ }
28
+ /**
29
+ * Validates priority string (low/medium/high/critical)
30
+ * @throws Error if priority is not valid
31
+ */
32
+ export function validatePriority(priority) {
33
+ const validPriorities = ['low', 'medium', 'high', 'critical'];
34
+ if (!validPriorities.includes(priority)) {
35
+ throw new Error(`Invalid priority. Must be one of: ${validPriorities.join(', ')}`);
36
+ }
37
+ return priority;
38
+ }
39
+ /**
40
+ * Validates priority number (1-4 range)
41
+ * @throws Error if priority is out of range
42
+ */
43
+ export function validatePriorityRange(priority) {
44
+ if (priority < 1 || priority > 4) {
45
+ throw new Error('Priority must be between 1 and 4');
46
+ }
47
+ return priority;
48
+ }
49
+ /**
50
+ * Validates layer and returns layer_id
51
+ * @throws Error if layer is invalid
52
+ */
53
+ export function validateLayer(db, layer) {
54
+ const validLayers = ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting'];
55
+ if (!validLayers.includes(layer)) {
56
+ throw new Error(`Invalid layer. Must be one of: ${validLayers.join(', ')}`);
57
+ }
58
+ const result = db.prepare('SELECT layer_id FROM m_layers WHERE layer_name = ?').get(layer);
59
+ if (!result) {
60
+ throw new Error(`Layer not found in database: ${layer}`);
61
+ }
62
+ return result.layer_id;
63
+ }
64
+ /**
65
+ * Validates message type enum
66
+ * @throws Error if message type is invalid
67
+ */
68
+ export function validateMessageType(msgType) {
69
+ const validTypes = ['decision', 'warning', 'request', 'info'];
70
+ if (!validTypes.includes(msgType)) {
71
+ throw new Error(`Invalid message type. Must be one of: ${validTypes.join(', ')}`);
72
+ }
73
+ return msgType;
74
+ }
75
+ /**
76
+ * Validates change type enum
77
+ * @throws Error if change type is invalid
78
+ */
79
+ export function validateChangeType(changeType) {
80
+ const validTypes = ['created', 'modified', 'deleted'];
81
+ if (!validTypes.includes(changeType)) {
82
+ throw new Error(`Invalid change type. Must be one of: ${validTypes.join(', ')}`);
83
+ }
84
+ return changeType;
85
+ }
86
+ /**
87
+ * Validates category enum
88
+ * @throws Error if category is invalid
89
+ */
90
+ export function validateCategory(category) {
91
+ const validCategories = ['performance', 'architecture', 'security'];
92
+ if (!validCategories.includes(category)) {
93
+ throw new Error(`Invalid category. Must be one of: ${validCategories.join(', ')}`);
94
+ }
95
+ return category;
96
+ }
97
+ /**
98
+ * Validates string length
99
+ * @throws Error if string exceeds max length
100
+ */
101
+ export function validateLength(value, paramName, maxLength) {
102
+ if (value.length > maxLength) {
103
+ throw new Error(`${paramName} exceeds maximum length of ${maxLength} characters`);
104
+ }
105
+ return value;
106
+ }
107
+ /**
108
+ * Validates number is within range
109
+ * @throws Error if number is out of range
110
+ */
111
+ export function validateRange(value, paramName, min, max) {
112
+ if (value < min || value > max) {
113
+ throw new Error(`${paramName} must be between ${min} and ${max}`);
114
+ }
115
+ return value;
116
+ }
117
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"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"}