sdd-mcp-server 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.
Files changed (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -0
  3. package/dist/__tests__/setup.d.ts +44 -0
  4. package/dist/__tests__/setup.js +178 -0
  5. package/dist/__tests__/setup.js.map +1 -0
  6. package/dist/__tests__/test-helpers/mock-factories.d.ts +26 -0
  7. package/dist/__tests__/test-helpers/mock-factories.js +466 -0
  8. package/dist/__tests__/test-helpers/mock-factories.js.map +1 -0
  9. package/dist/adapters/cli/SDDToolAdapter.d.ts +26 -0
  10. package/dist/adapters/cli/SDDToolAdapter.js +273 -0
  11. package/dist/adapters/cli/SDDToolAdapter.js.map +1 -0
  12. package/dist/application/services/CodebaseAnalysisService.d.ts +38 -0
  13. package/dist/application/services/CodebaseAnalysisService.js +737 -0
  14. package/dist/application/services/CodebaseAnalysisService.js.map +1 -0
  15. package/dist/application/services/LocalizationService.d.ts +184 -0
  16. package/dist/application/services/LocalizationService.js +536 -0
  17. package/dist/application/services/LocalizationService.js.map +1 -0
  18. package/dist/application/services/ProjectContextService.d.ts +61 -0
  19. package/dist/application/services/ProjectContextService.js +550 -0
  20. package/dist/application/services/ProjectContextService.js.map +1 -0
  21. package/dist/application/services/ProjectInitializationService.d.ts +57 -0
  22. package/dist/application/services/ProjectInitializationService.js +485 -0
  23. package/dist/application/services/ProjectInitializationService.js.map +1 -0
  24. package/dist/application/services/ProjectService.d.ts +19 -0
  25. package/dist/application/services/ProjectService.js +159 -0
  26. package/dist/application/services/ProjectService.js.map +1 -0
  27. package/dist/application/services/QualityGateService.d.ts +62 -0
  28. package/dist/application/services/QualityGateService.js +428 -0
  29. package/dist/application/services/QualityGateService.js.map +1 -0
  30. package/dist/application/services/QualityService.d.ts +43 -0
  31. package/dist/application/services/QualityService.js +245 -0
  32. package/dist/application/services/QualityService.js.map +1 -0
  33. package/dist/application/services/SteeringDocumentService.d.ts +62 -0
  34. package/dist/application/services/SteeringDocumentService.js +694 -0
  35. package/dist/application/services/SteeringDocumentService.js.map +1 -0
  36. package/dist/application/services/TemplateService.d.ts +47 -0
  37. package/dist/application/services/TemplateService.js +438 -0
  38. package/dist/application/services/TemplateService.js.map +1 -0
  39. package/dist/application/services/WorkflowEngineService.d.ts +56 -0
  40. package/dist/application/services/WorkflowEngineService.js +348 -0
  41. package/dist/application/services/WorkflowEngineService.js.map +1 -0
  42. package/dist/application/services/WorkflowService.d.ts +22 -0
  43. package/dist/application/services/WorkflowService.js +147 -0
  44. package/dist/application/services/WorkflowService.js.map +1 -0
  45. package/dist/application/services/WorkflowValidationService.d.ts +51 -0
  46. package/dist/application/services/WorkflowValidationService.js +665 -0
  47. package/dist/application/services/WorkflowValidationService.js.map +1 -0
  48. package/dist/domain/context/ProjectContext.d.ts +350 -0
  49. package/dist/domain/context/ProjectContext.js +138 -0
  50. package/dist/domain/context/ProjectContext.js.map +1 -0
  51. package/dist/domain/i18n/index.d.ts +286 -0
  52. package/dist/domain/i18n/index.js +97 -0
  53. package/dist/domain/i18n/index.js.map +1 -0
  54. package/dist/domain/plugins/index.d.ts +498 -0
  55. package/dist/domain/plugins/index.js +157 -0
  56. package/dist/domain/plugins/index.js.map +1 -0
  57. package/dist/domain/ports.d.ts +54 -0
  58. package/dist/domain/ports.js +3 -0
  59. package/dist/domain/ports.js.map +1 -0
  60. package/dist/domain/quality/index.d.ts +361 -0
  61. package/dist/domain/quality/index.js +113 -0
  62. package/dist/domain/quality/index.js.map +1 -0
  63. package/dist/domain/services/DomainService.d.ts +18 -0
  64. package/dist/domain/services/DomainService.js +71 -0
  65. package/dist/domain/services/DomainService.js.map +1 -0
  66. package/dist/domain/templates/index.d.ts +158 -0
  67. package/dist/domain/templates/index.js +22 -0
  68. package/dist/domain/templates/index.js.map +1 -0
  69. package/dist/domain/types.d.ts +115 -0
  70. package/dist/domain/types.js +37 -0
  71. package/dist/domain/types.js.map +1 -0
  72. package/dist/domain/workflow/WorkflowStateMachine.d.ts +62 -0
  73. package/dist/domain/workflow/WorkflowStateMachine.js +286 -0
  74. package/dist/domain/workflow/WorkflowStateMachine.js.map +1 -0
  75. package/dist/index.d.ts +19 -0
  76. package/dist/index.js +97 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/infrastructure/adapters/AjvValidationAdapter.d.ts +7 -0
  79. package/dist/infrastructure/adapters/AjvValidationAdapter.js +37 -0
  80. package/dist/infrastructure/adapters/AjvValidationAdapter.js.map +1 -0
  81. package/dist/infrastructure/adapters/ConsoleLoggerAdapter.d.ts +8 -0
  82. package/dist/infrastructure/adapters/ConsoleLoggerAdapter.js +41 -0
  83. package/dist/infrastructure/adapters/ConsoleLoggerAdapter.js.map +1 -0
  84. package/dist/infrastructure/adapters/FileBasedTaskTracker.d.ts +9 -0
  85. package/dist/infrastructure/adapters/FileBasedTaskTracker.js +41 -0
  86. package/dist/infrastructure/adapters/FileBasedTaskTracker.js.map +1 -0
  87. package/dist/infrastructure/adapters/HandlebarsTemplateEngine.d.ts +8 -0
  88. package/dist/infrastructure/adapters/HandlebarsTemplateEngine.js +38 -0
  89. package/dist/infrastructure/adapters/HandlebarsTemplateEngine.js.map +1 -0
  90. package/dist/infrastructure/adapters/JsonConfigurationAdapter.d.ts +7 -0
  91. package/dist/infrastructure/adapters/JsonConfigurationAdapter.js +24 -0
  92. package/dist/infrastructure/adapters/JsonConfigurationAdapter.js.map +1 -0
  93. package/dist/infrastructure/adapters/LinusQualityAnalyzer.d.ts +9 -0
  94. package/dist/infrastructure/adapters/LinusQualityAnalyzer.js +75 -0
  95. package/dist/infrastructure/adapters/LinusQualityAnalyzer.js.map +1 -0
  96. package/dist/infrastructure/adapters/NodeFileSystemAdapter.d.ts +12 -0
  97. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js +39 -0
  98. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js.map +1 -0
  99. package/dist/infrastructure/di/container.d.ts +3 -0
  100. package/dist/infrastructure/di/container.js +98 -0
  101. package/dist/infrastructure/di/container.js.map +1 -0
  102. package/dist/infrastructure/di/types.d.ts +39 -0
  103. package/dist/infrastructure/di/types.js +45 -0
  104. package/dist/infrastructure/di/types.js.map +1 -0
  105. package/dist/infrastructure/i18n/I18nextService.d.ts +27 -0
  106. package/dist/infrastructure/i18n/I18nextService.js +357 -0
  107. package/dist/infrastructure/i18n/I18nextService.js.map +1 -0
  108. package/dist/infrastructure/mcp/CapabilityNegotiator.d.ts +21 -0
  109. package/dist/infrastructure/mcp/CapabilityNegotiator.js +75 -0
  110. package/dist/infrastructure/mcp/CapabilityNegotiator.js.map +1 -0
  111. package/dist/infrastructure/mcp/ErrorHandler.d.ts +29 -0
  112. package/dist/infrastructure/mcp/ErrorHandler.js +101 -0
  113. package/dist/infrastructure/mcp/ErrorHandler.js.map +1 -0
  114. package/dist/infrastructure/mcp/MCPServer.d.ts +25 -0
  115. package/dist/infrastructure/mcp/MCPServer.js +246 -0
  116. package/dist/infrastructure/mcp/MCPServer.js.map +1 -0
  117. package/dist/infrastructure/mcp/PromptManager.d.ts +18 -0
  118. package/dist/infrastructure/mcp/PromptManager.js +373 -0
  119. package/dist/infrastructure/mcp/PromptManager.js.map +1 -0
  120. package/dist/infrastructure/mcp/ResourceManager.d.ts +15 -0
  121. package/dist/infrastructure/mcp/ResourceManager.js +229 -0
  122. package/dist/infrastructure/mcp/ResourceManager.js.map +1 -0
  123. package/dist/infrastructure/mcp/SessionManager.d.ts +64 -0
  124. package/dist/infrastructure/mcp/SessionManager.js +221 -0
  125. package/dist/infrastructure/mcp/SessionManager.js.map +1 -0
  126. package/dist/infrastructure/mcp/ToolRegistry.d.ts +48 -0
  127. package/dist/infrastructure/mcp/ToolRegistry.js +235 -0
  128. package/dist/infrastructure/mcp/ToolRegistry.js.map +1 -0
  129. package/dist/infrastructure/platform/PlatformAdapter.d.ts +46 -0
  130. package/dist/infrastructure/platform/PlatformAdapter.js +355 -0
  131. package/dist/infrastructure/platform/PlatformAdapter.js.map +1 -0
  132. package/dist/infrastructure/plugins/HookSystem.d.ts +40 -0
  133. package/dist/infrastructure/plugins/HookSystem.js +415 -0
  134. package/dist/infrastructure/plugins/HookSystem.js.map +1 -0
  135. package/dist/infrastructure/plugins/PluginManager.d.ts +51 -0
  136. package/dist/infrastructure/plugins/PluginManager.js +650 -0
  137. package/dist/infrastructure/plugins/PluginManager.js.map +1 -0
  138. package/dist/infrastructure/plugins/PluginSteeringRegistry.d.ts +63 -0
  139. package/dist/infrastructure/plugins/PluginSteeringRegistry.js +439 -0
  140. package/dist/infrastructure/plugins/PluginSteeringRegistry.js.map +1 -0
  141. package/dist/infrastructure/plugins/PluginToolRegistry.d.ts +54 -0
  142. package/dist/infrastructure/plugins/PluginToolRegistry.js +490 -0
  143. package/dist/infrastructure/plugins/PluginToolRegistry.js.map +1 -0
  144. package/dist/infrastructure/quality/ASTAnalyzer.d.ts +65 -0
  145. package/dist/infrastructure/quality/ASTAnalyzer.js +439 -0
  146. package/dist/infrastructure/quality/ASTAnalyzer.js.map +1 -0
  147. package/dist/infrastructure/quality/LinusCodeReviewer.d.ts +52 -0
  148. package/dist/infrastructure/quality/LinusCodeReviewer.js +551 -0
  149. package/dist/infrastructure/quality/LinusCodeReviewer.js.map +1 -0
  150. package/dist/infrastructure/repositories/InMemoryProjectRepository.d.ts +10 -0
  151. package/dist/infrastructure/repositories/InMemoryProjectRepository.js +35 -0
  152. package/dist/infrastructure/repositories/InMemoryProjectRepository.js.map +1 -0
  153. package/dist/infrastructure/schemas/project.schema.d.ts +192 -0
  154. package/dist/infrastructure/schemas/project.schema.js +114 -0
  155. package/dist/infrastructure/schemas/project.schema.js.map +1 -0
  156. package/dist/infrastructure/templates/FileGenerator.d.ts +15 -0
  157. package/dist/infrastructure/templates/FileGenerator.js +385 -0
  158. package/dist/infrastructure/templates/FileGenerator.js.map +1 -0
  159. package/dist/infrastructure/templates/HandlebarsRenderer.d.ts +16 -0
  160. package/dist/infrastructure/templates/HandlebarsRenderer.js +252 -0
  161. package/dist/infrastructure/templates/HandlebarsRenderer.js.map +1 -0
  162. package/dist/infrastructure/templates/TemplateManager.d.ts +36 -0
  163. package/dist/infrastructure/templates/TemplateManager.js +777 -0
  164. package/dist/infrastructure/templates/TemplateManager.js.map +1 -0
  165. package/package.json +89 -0
@@ -0,0 +1,385 @@
1
+ // File generation and directory management implementation
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ import { injectable, inject } from 'inversify';
15
+ import { promises as fs } from 'fs';
16
+ import path from 'path';
17
+ import { randomBytes } from 'crypto';
18
+ import { TYPES } from '../di/types.js';
19
+ const DEFAULT_FILE_OPTIONS = {
20
+ backup: true,
21
+ overwrite: false,
22
+ createDirectories: true,
23
+ atomic: true
24
+ };
25
+ let FileGenerator = class FileGenerator {
26
+ logger;
27
+ renderer;
28
+ backupDirectory;
29
+ constructor(logger, renderer, backupDirectory = './.backups') {
30
+ this.logger = logger;
31
+ this.renderer = renderer;
32
+ this.backupDirectory = path.resolve(backupDirectory);
33
+ }
34
+ async generateFile(filePath, template, data, context, options = DEFAULT_FILE_OPTIONS) {
35
+ const resolvedPath = path.resolve(filePath);
36
+ const finalOptions = { ...DEFAULT_FILE_OPTIONS, ...options };
37
+ try {
38
+ // Validate the target path
39
+ const pathValidation = await this.validatePath(resolvedPath);
40
+ if (!pathValidation.isValid) {
41
+ return {
42
+ filePath: resolvedPath,
43
+ success: false,
44
+ bytesWritten: 0,
45
+ error: `Invalid path: ${pathValidation.errors.join(', ')}`,
46
+ warnings: []
47
+ };
48
+ }
49
+ // Check if file exists and handle accordingly
50
+ if (pathValidation.exists && pathValidation.isFile && !finalOptions.overwrite) {
51
+ return {
52
+ filePath: resolvedPath,
53
+ success: false,
54
+ bytesWritten: 0,
55
+ error: 'File exists and overwrite is disabled',
56
+ warnings: []
57
+ };
58
+ }
59
+ // Create backup if requested and file exists
60
+ let backupPath;
61
+ if (finalOptions.backup && pathValidation.exists && pathValidation.isFile) {
62
+ backupPath = await this.backupFile(resolvedPath);
63
+ }
64
+ // Create parent directories if needed
65
+ if (finalOptions.createDirectories) {
66
+ const parentDir = path.dirname(resolvedPath);
67
+ await fs.mkdir(parentDir, { recursive: true });
68
+ }
69
+ // Render the template
70
+ const renderedContent = await this.renderer.renderString(template, data, context);
71
+ // Write file atomically or directly
72
+ const bytesWritten = await this.writeFile(resolvedPath, renderedContent, finalOptions.atomic);
73
+ // Set permissions if specified
74
+ if (finalOptions.permissions) {
75
+ await fs.chmod(resolvedPath, finalOptions.permissions);
76
+ }
77
+ this.logger.info('File generated successfully', {
78
+ filePath: resolvedPath,
79
+ bytesWritten,
80
+ backup: !!backupPath
81
+ });
82
+ return {
83
+ filePath: resolvedPath,
84
+ success: true,
85
+ backupPath,
86
+ bytesWritten,
87
+ warnings: []
88
+ };
89
+ }
90
+ catch (error) {
91
+ this.logger.error('File generation failed', {
92
+ filePath: resolvedPath,
93
+ error: error instanceof Error ? error.message : String(error)
94
+ });
95
+ return {
96
+ filePath: resolvedPath,
97
+ success: false,
98
+ bytesWritten: 0,
99
+ error: error instanceof Error ? error.message : String(error),
100
+ warnings: []
101
+ };
102
+ }
103
+ }
104
+ async generateDirectory(dirPath, structure, context, options = DEFAULT_FILE_OPTIONS) {
105
+ const resolvedDirPath = path.resolve(dirPath);
106
+ const filesGenerated = [];
107
+ const directoriesCreated = [];
108
+ const errors = [];
109
+ const warnings = [];
110
+ try {
111
+ // Validate the target directory path
112
+ const pathValidation = await this.validatePath(resolvedDirPath);
113
+ // Create the root directory if it doesn't exist
114
+ if (!pathValidation.exists) {
115
+ await fs.mkdir(resolvedDirPath, { recursive: true });
116
+ directoriesCreated.push(resolvedDirPath);
117
+ }
118
+ // Generate files in the current directory
119
+ for (const file of structure.files) {
120
+ const filePath = path.join(resolvedDirPath, file.name);
121
+ try {
122
+ const result = await this.generateFile(filePath, file.template, file.data, context, options);
123
+ filesGenerated.push(result);
124
+ if (!result.success) {
125
+ errors.push(`Failed to generate ${file.name}: ${result.error}`);
126
+ }
127
+ if (result.warnings.length > 0) {
128
+ warnings.push(...result.warnings.map(w => `${file.name}: ${w}`));
129
+ }
130
+ }
131
+ catch (error) {
132
+ const errorMessage = `Error generating file ${file.name}: ${error instanceof Error ? error.message : String(error)}`;
133
+ errors.push(errorMessage);
134
+ filesGenerated.push({
135
+ filePath,
136
+ success: false,
137
+ bytesWritten: 0,
138
+ error: errorMessage,
139
+ warnings: []
140
+ });
141
+ }
142
+ }
143
+ // Recursively generate subdirectories
144
+ for (const [subdirName, subdirStructure] of Object.entries(structure.subdirectories)) {
145
+ const subdirPath = path.join(resolvedDirPath, subdirName);
146
+ try {
147
+ const result = await this.generateDirectory(subdirPath, subdirStructure, context, options);
148
+ filesGenerated.push(...result.filesGenerated);
149
+ directoriesCreated.push(...result.directoriesCreated);
150
+ if (result.errors.length > 0) {
151
+ errors.push(...result.errors.map(e => `${subdirName}/${e}`));
152
+ }
153
+ if (result.warnings.length > 0) {
154
+ warnings.push(...result.warnings.map(w => `${subdirName}/${w}`));
155
+ }
156
+ }
157
+ catch (error) {
158
+ errors.push(`Failed to generate subdirectory ${subdirName}: ${error instanceof Error ? error.message : String(error)}`);
159
+ }
160
+ }
161
+ const success = errors.length === 0;
162
+ this.logger.info('Directory generation completed', {
163
+ dirPath: resolvedDirPath,
164
+ success,
165
+ filesGenerated: filesGenerated.length,
166
+ directoriesCreated: directoriesCreated.length,
167
+ errors: errors.length
168
+ });
169
+ return {
170
+ dirPath: resolvedDirPath,
171
+ success,
172
+ filesGenerated,
173
+ directoriesCreated,
174
+ errors,
175
+ warnings
176
+ };
177
+ }
178
+ catch (error) {
179
+ const errorMessage = `Directory generation failed: ${error instanceof Error ? error.message : String(error)}`;
180
+ this.logger.error('Directory generation failed', {
181
+ dirPath: resolvedDirPath,
182
+ error: errorMessage
183
+ });
184
+ return {
185
+ dirPath: resolvedDirPath,
186
+ success: false,
187
+ filesGenerated,
188
+ directoriesCreated,
189
+ errors: [errorMessage],
190
+ warnings
191
+ };
192
+ }
193
+ }
194
+ async validatePath(targetPath) {
195
+ const errors = [];
196
+ try {
197
+ // Check if path contains invalid characters
198
+ if (/[<>:"|?*]/.test(targetPath)) {
199
+ errors.push('Path contains invalid characters');
200
+ }
201
+ // Check if path is absolute or relative
202
+ if (!path.isAbsolute(targetPath)) {
203
+ // This is actually fine, we'll resolve it
204
+ }
205
+ const resolvedPath = path.resolve(targetPath);
206
+ // Check if path exists and get stats
207
+ let stats = null;
208
+ let exists = false;
209
+ try {
210
+ stats = await fs.stat(resolvedPath);
211
+ exists = true;
212
+ }
213
+ catch (error) {
214
+ if (error.code !== 'ENOENT') {
215
+ errors.push(`Unable to access path: ${error instanceof Error ? error.message : String(error)}`);
216
+ }
217
+ }
218
+ // Check permissions if file/directory exists
219
+ let permissions = {
220
+ read: false,
221
+ write: false,
222
+ execute: false
223
+ };
224
+ if (exists && stats) {
225
+ try {
226
+ await fs.access(resolvedPath, fs.constants.R_OK);
227
+ permissions.read = true;
228
+ }
229
+ catch {
230
+ // No read permission
231
+ }
232
+ try {
233
+ await fs.access(resolvedPath, fs.constants.W_OK);
234
+ permissions.write = true;
235
+ }
236
+ catch {
237
+ // No write permission
238
+ }
239
+ try {
240
+ await fs.access(resolvedPath, fs.constants.X_OK);
241
+ permissions.execute = true;
242
+ }
243
+ catch {
244
+ // No execute permission
245
+ }
246
+ }
247
+ else {
248
+ // Check parent directory permissions
249
+ const parentDir = path.dirname(resolvedPath);
250
+ try {
251
+ await fs.access(parentDir, fs.constants.W_OK);
252
+ permissions.write = true;
253
+ }
254
+ catch {
255
+ errors.push('Parent directory is not writable');
256
+ }
257
+ }
258
+ return {
259
+ isValid: errors.length === 0,
260
+ exists,
261
+ isFile: exists && stats?.isFile() || false,
262
+ isDirectory: exists && stats?.isDirectory() || false,
263
+ permissions,
264
+ errors
265
+ };
266
+ }
267
+ catch (error) {
268
+ errors.push(`Path validation failed: ${error instanceof Error ? error.message : String(error)}`);
269
+ return {
270
+ isValid: false,
271
+ exists: false,
272
+ isFile: false,
273
+ isDirectory: false,
274
+ permissions: { read: false, write: false, execute: false },
275
+ errors
276
+ };
277
+ }
278
+ }
279
+ async backupFile(filePath) {
280
+ const resolvedPath = path.resolve(filePath);
281
+ const fileName = path.basename(resolvedPath);
282
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
283
+ const randomSuffix = randomBytes(4).toString('hex');
284
+ const backupName = `${fileName}.${timestamp}.${randomSuffix}.backup`;
285
+ const backupPath = path.join(this.backupDirectory, backupName);
286
+ try {
287
+ await fs.mkdir(this.backupDirectory, { recursive: true });
288
+ await fs.copyFile(resolvedPath, backupPath);
289
+ this.logger.debug('File backup created', {
290
+ original: resolvedPath,
291
+ backup: backupPath
292
+ });
293
+ return backupPath;
294
+ }
295
+ catch (error) {
296
+ this.logger.error('File backup failed', {
297
+ filePath: resolvedPath,
298
+ backupPath,
299
+ error: error instanceof Error ? error.message : String(error)
300
+ });
301
+ throw new Error(`Backup failed: ${error instanceof Error ? error.message : String(error)}`);
302
+ }
303
+ }
304
+ async restoreBackup(backupPath, originalPath) {
305
+ try {
306
+ await fs.copyFile(backupPath, originalPath);
307
+ this.logger.info('File restored from backup', {
308
+ backup: backupPath,
309
+ restored: originalPath
310
+ });
311
+ }
312
+ catch (error) {
313
+ this.logger.error('File restore failed', {
314
+ backupPath,
315
+ originalPath,
316
+ error: error instanceof Error ? error.message : String(error)
317
+ });
318
+ throw new Error(`Restore failed: ${error instanceof Error ? error.message : String(error)}`);
319
+ }
320
+ }
321
+ async cleanupBackups(olderThan) {
322
+ const deletedBackups = [];
323
+ try {
324
+ await fs.mkdir(this.backupDirectory, { recursive: true });
325
+ const backupFiles = await fs.readdir(this.backupDirectory);
326
+ for (const fileName of backupFiles) {
327
+ if (!fileName.endsWith('.backup'))
328
+ continue;
329
+ const filePath = path.join(this.backupDirectory, fileName);
330
+ const stats = await fs.stat(filePath);
331
+ if (stats.mtime < olderThan) {
332
+ await fs.unlink(filePath);
333
+ deletedBackups.push(filePath);
334
+ }
335
+ }
336
+ this.logger.info('Backup cleanup completed', {
337
+ deleted: deletedBackups.length,
338
+ olderThan: olderThan.toISOString()
339
+ });
340
+ return deletedBackups;
341
+ }
342
+ catch (error) {
343
+ this.logger.error('Backup cleanup failed', {
344
+ error: error instanceof Error ? error.message : String(error)
345
+ });
346
+ throw new Error(`Backup cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
347
+ }
348
+ }
349
+ async writeFile(filePath, content, atomic) {
350
+ if (atomic) {
351
+ // Write to temporary file first, then rename
352
+ const tempPath = `${filePath}.tmp.${randomBytes(8).toString('hex')}`;
353
+ try {
354
+ await fs.writeFile(tempPath, content, 'utf-8');
355
+ await fs.rename(tempPath, filePath);
356
+ const stats = await fs.stat(filePath);
357
+ return stats.size;
358
+ }
359
+ catch (error) {
360
+ // Clean up temp file if it exists
361
+ try {
362
+ await fs.unlink(tempPath);
363
+ }
364
+ catch {
365
+ // Ignore cleanup errors
366
+ }
367
+ throw error;
368
+ }
369
+ }
370
+ else {
371
+ // Write directly
372
+ await fs.writeFile(filePath, content, 'utf-8');
373
+ const stats = await fs.stat(filePath);
374
+ return stats.size;
375
+ }
376
+ }
377
+ };
378
+ FileGenerator = __decorate([
379
+ injectable(),
380
+ __param(0, inject(TYPES.LoggerPort)),
381
+ __param(1, inject(TYPES.TemplateRendererPort)),
382
+ __metadata("design:paramtypes", [Object, Object, Object])
383
+ ], FileGenerator);
384
+ export { FileGenerator };
385
+ //# sourceMappingURL=FileGenerator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileGenerator.js","sourceRoot":"","sources":["../../../src/infrastructure/templates/FileGenerator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { TemplateRendererPort, CompiledTemplate, TemplateData, TemplateContext } from '../../domain/templates/index.js';
2
+ import type { LoggerPort } from '../../domain/ports.js';
3
+ export declare class HandlebarsRenderer implements TemplateRendererPort {
4
+ private readonly logger;
5
+ private readonly templateCache;
6
+ private readonly handlebarsInstance;
7
+ constructor(logger: LoggerPort);
8
+ compile(template: string, name?: string): Promise<CompiledTemplate>;
9
+ render(templateName: string, data: TemplateData, context: TemplateContext): Promise<string>;
10
+ renderString(template: string, data: TemplateData, context: TemplateContext): Promise<string>;
11
+ registerHelper(name: string, helper: (...args: unknown[]) => unknown): void;
12
+ registerPartial(name: string, template: string): Promise<void>;
13
+ clearCache(): void;
14
+ private registerBuiltInHelpers;
15
+ private getRelativeTime;
16
+ }
@@ -0,0 +1,252 @@
1
+ // Handlebars template renderer implementation
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ import { injectable } from 'inversify';
15
+ import Handlebars from 'handlebars';
16
+ import { inject } from 'inversify';
17
+ import { TYPES } from '../di/types.js';
18
+ class HandlebarsCompiledTemplate {
19
+ name;
20
+ template;
21
+ compiledAt;
22
+ handlebarsTemplate;
23
+ constructor(name, template, compiledAt, handlebarsTemplate) {
24
+ this.name = name;
25
+ this.template = template;
26
+ this.compiledAt = compiledAt;
27
+ this.handlebarsTemplate = handlebarsTemplate;
28
+ }
29
+ render(data, context) {
30
+ const combinedData = {
31
+ ...data,
32
+ context,
33
+ helpers: {
34
+ formatDate: (date, format = 'YYYY-MM-DD') => {
35
+ const d = typeof date === 'string' ? new Date(date) : date;
36
+ return d.toISOString().split('T')[0];
37
+ },
38
+ uppercase: (str) => str?.toUpperCase() ?? '',
39
+ lowercase: (str) => str?.toLowerCase() ?? '',
40
+ capitalize: (str) => {
41
+ if (!str)
42
+ return '';
43
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
44
+ },
45
+ join: (array, separator = ', ') => {
46
+ if (!Array.isArray(array))
47
+ return '';
48
+ return array.join(separator);
49
+ },
50
+ default: (value, defaultValue) => value ?? defaultValue
51
+ }
52
+ };
53
+ return this.handlebarsTemplate(combinedData);
54
+ }
55
+ }
56
+ let HandlebarsRenderer = class HandlebarsRenderer {
57
+ logger;
58
+ templateCache = new Map();
59
+ handlebarsInstance;
60
+ constructor(logger) {
61
+ this.logger = logger;
62
+ this.handlebarsInstance = Handlebars.create();
63
+ this.registerBuiltInHelpers();
64
+ }
65
+ async compile(template, name) {
66
+ try {
67
+ const templateName = name ?? `template_${Date.now()}`;
68
+ const handlebarsTemplate = this.handlebarsInstance.compile(template);
69
+ const compiled = new HandlebarsCompiledTemplate(templateName, template, new Date(), handlebarsTemplate);
70
+ if (name) {
71
+ this.templateCache.set(name, compiled);
72
+ }
73
+ this.logger.debug('Template compiled successfully', { name: templateName });
74
+ return compiled;
75
+ }
76
+ catch (error) {
77
+ this.logger.error('Template compilation failed', {
78
+ name,
79
+ error: error instanceof Error ? error.message : String(error)
80
+ });
81
+ throw new Error(`Template compilation failed: ${error instanceof Error ? error.message : String(error)}`);
82
+ }
83
+ }
84
+ async render(templateName, data, context) {
85
+ const compiled = this.templateCache.get(templateName);
86
+ if (!compiled) {
87
+ throw new Error(`Template '${templateName}' not found in cache`);
88
+ }
89
+ try {
90
+ const result = compiled.render(data, context);
91
+ this.logger.debug('Template rendered successfully', { templateName });
92
+ return result;
93
+ }
94
+ catch (error) {
95
+ this.logger.error('Template rendering failed', {
96
+ templateName,
97
+ error: error instanceof Error ? error.message : String(error)
98
+ });
99
+ throw new Error(`Template rendering failed: ${error instanceof Error ? error.message : String(error)}`);
100
+ }
101
+ }
102
+ async renderString(template, data, context) {
103
+ try {
104
+ const compiled = await this.compile(template);
105
+ return compiled.render(data, context);
106
+ }
107
+ catch (error) {
108
+ this.logger.error('String template rendering failed', {
109
+ error: error instanceof Error ? error.message : String(error)
110
+ });
111
+ throw error;
112
+ }
113
+ }
114
+ registerHelper(name, helper) {
115
+ this.handlebarsInstance.registerHelper(name, helper);
116
+ this.logger.debug('Template helper registered', { name });
117
+ }
118
+ async registerPartial(name, template) {
119
+ try {
120
+ this.handlebarsInstance.registerPartial(name, template);
121
+ this.logger.debug('Template partial registered', { name });
122
+ }
123
+ catch (error) {
124
+ this.logger.error('Template partial registration failed', {
125
+ name,
126
+ error: error instanceof Error ? error.message : String(error)
127
+ });
128
+ throw new Error(`Partial registration failed: ${error instanceof Error ? error.message : String(error)}`);
129
+ }
130
+ }
131
+ clearCache() {
132
+ this.templateCache.clear();
133
+ this.logger.debug('Template cache cleared');
134
+ }
135
+ registerBuiltInHelpers() {
136
+ // Date formatting helper
137
+ this.registerHelper('formatDate', (date, format = 'YYYY-MM-DD') => {
138
+ if (!date)
139
+ return '';
140
+ const d = typeof date === 'string' ? new Date(date) : date;
141
+ if (isNaN(d.getTime()))
142
+ return '';
143
+ switch (format) {
144
+ case 'YYYY-MM-DD':
145
+ return d.toISOString().split('T')[0];
146
+ case 'MM/DD/YYYY':
147
+ return `${(d.getMonth() + 1).toString().padStart(2, '0')}/${d.getDate().toString().padStart(2, '0')}/${d.getFullYear()}`;
148
+ case 'DD/MM/YYYY':
149
+ return `${d.getDate().toString().padStart(2, '0')}/${(d.getMonth() + 1).toString().padStart(2, '0')}/${d.getFullYear()}`;
150
+ case 'relative':
151
+ return this.getRelativeTime(d);
152
+ default:
153
+ return d.toLocaleDateString();
154
+ }
155
+ });
156
+ // String manipulation helpers
157
+ this.registerHelper('uppercase', (str) => str?.toUpperCase() ?? '');
158
+ this.registerHelper('lowercase', (str) => str?.toLowerCase() ?? '');
159
+ this.registerHelper('capitalize', (str) => {
160
+ if (!str)
161
+ return '';
162
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
163
+ });
164
+ this.registerHelper('kebabCase', (str) => {
165
+ if (!str)
166
+ return '';
167
+ return str.replace(/\s+/g, '-').toLowerCase();
168
+ });
169
+ this.registerHelper('camelCase', (str) => {
170
+ if (!str)
171
+ return '';
172
+ return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '');
173
+ });
174
+ // Array and object helpers
175
+ this.registerHelper('join', (array, separator = ', ') => {
176
+ if (!Array.isArray(array))
177
+ return '';
178
+ return array.join(separator);
179
+ });
180
+ this.registerHelper('length', (value) => {
181
+ if (Array.isArray(value))
182
+ return value.length;
183
+ if (typeof value === 'string')
184
+ return value.length;
185
+ if (value && typeof value === 'object')
186
+ return Object.keys(value).length;
187
+ return 0;
188
+ });
189
+ // Conditional helpers
190
+ this.registerHelper('default', (value, defaultValue) => {
191
+ return value ?? defaultValue;
192
+ });
193
+ this.registerHelper('eq', (a, b) => a === b);
194
+ this.registerHelper('ne', (a, b) => a !== b);
195
+ this.registerHelper('gt', (a, b) => a > b);
196
+ this.registerHelper('lt', (a, b) => a < b);
197
+ this.registerHelper('gte', (a, b) => a >= b);
198
+ this.registerHelper('lte', (a, b) => a <= b);
199
+ // SDD-specific helpers
200
+ this.registerHelper('taskStatus', (completed) => {
201
+ return completed ? '[x]' : '[ ]';
202
+ });
203
+ this.registerHelper('phaseStatus', (phase, currentPhase) => {
204
+ const phases = ['INIT', 'REQUIREMENTS', 'DESIGN', 'TASKS', 'IMPLEMENTATION'];
205
+ const phaseIndex = phases.indexOf(phase);
206
+ const currentIndex = phases.indexOf(currentPhase);
207
+ if (phaseIndex < currentIndex)
208
+ return 'completed';
209
+ if (phaseIndex === currentIndex)
210
+ return 'active';
211
+ return 'pending';
212
+ });
213
+ this.registerHelper('generateId', () => {
214
+ return Math.random().toString(36).substr(2, 9);
215
+ });
216
+ this.registerHelper('indent', (text, spaces = 2) => {
217
+ if (!text)
218
+ return '';
219
+ const indent = ' '.repeat(spaces);
220
+ return text.split('\n').map(line => indent + line).join('\n');
221
+ });
222
+ this.logger.debug('Built-in template helpers registered');
223
+ }
224
+ getRelativeTime(date) {
225
+ const now = new Date();
226
+ const diffMs = now.getTime() - date.getTime();
227
+ const diffSeconds = Math.floor(diffMs / 1000);
228
+ const diffMinutes = Math.floor(diffSeconds / 60);
229
+ const diffHours = Math.floor(diffMinutes / 60);
230
+ const diffDays = Math.floor(diffHours / 24);
231
+ if (diffSeconds < 60)
232
+ return 'just now';
233
+ if (diffMinutes < 60)
234
+ return `${diffMinutes} minutes ago`;
235
+ if (diffHours < 24)
236
+ return `${diffHours} hours ago`;
237
+ if (diffDays < 7)
238
+ return `${diffDays} days ago`;
239
+ if (diffDays < 30)
240
+ return `${Math.floor(diffDays / 7)} weeks ago`;
241
+ if (diffDays < 365)
242
+ return `${Math.floor(diffDays / 30)} months ago`;
243
+ return `${Math.floor(diffDays / 365)} years ago`;
244
+ }
245
+ };
246
+ HandlebarsRenderer = __decorate([
247
+ injectable(),
248
+ __param(0, inject(TYPES.LoggerPort)),
249
+ __metadata("design:paramtypes", [Object])
250
+ ], HandlebarsRenderer);
251
+ export { HandlebarsRenderer };
252
+ //# sourceMappingURL=HandlebarsRenderer.js.map