@esthernandez/vibe-doc 0.1.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 (95) hide show
  1. package/dist/checker/index.d.ts +34 -0
  2. package/dist/checker/index.d.ts.map +1 -0
  3. package/dist/checker/index.js +154 -0
  4. package/dist/checker/staleness.d.ts +26 -0
  5. package/dist/checker/staleness.d.ts.map +1 -0
  6. package/dist/checker/staleness.js +56 -0
  7. package/dist/classifier/index.d.ts +26 -0
  8. package/dist/classifier/index.d.ts.map +1 -0
  9. package/dist/classifier/index.js +146 -0
  10. package/dist/classifier/llm-prompt.d.ts +12 -0
  11. package/dist/classifier/llm-prompt.d.ts.map +1 -0
  12. package/dist/classifier/llm-prompt.js +123 -0
  13. package/dist/classifier/scoring-engine.d.ts +41 -0
  14. package/dist/classifier/scoring-engine.d.ts.map +1 -0
  15. package/dist/classifier/scoring-engine.js +197 -0
  16. package/dist/classifier/signals.d.ts +16 -0
  17. package/dist/classifier/signals.d.ts.map +1 -0
  18. package/dist/classifier/signals.js +305 -0
  19. package/dist/gap-analyzer/breadcrumbs.d.ts +18 -0
  20. package/dist/gap-analyzer/breadcrumbs.d.ts.map +1 -0
  21. package/dist/gap-analyzer/breadcrumbs.js +314 -0
  22. package/dist/gap-analyzer/index.d.ts +13 -0
  23. package/dist/gap-analyzer/index.d.ts.map +1 -0
  24. package/dist/gap-analyzer/index.js +88 -0
  25. package/dist/gap-analyzer/matrix.d.ts +29 -0
  26. package/dist/gap-analyzer/matrix.d.ts.map +1 -0
  27. package/dist/gap-analyzer/matrix.js +137 -0
  28. package/dist/gap-analyzer/tier-assigner.d.ts +22 -0
  29. package/dist/gap-analyzer/tier-assigner.d.ts.map +1 -0
  30. package/dist/gap-analyzer/tier-assigner.js +112 -0
  31. package/dist/generator/docx-writer.d.ts +15 -0
  32. package/dist/generator/docx-writer.d.ts.map +1 -0
  33. package/dist/generator/docx-writer.js +271 -0
  34. package/dist/generator/extractor.d.ts +11 -0
  35. package/dist/generator/extractor.d.ts.map +1 -0
  36. package/dist/generator/extractor.js +459 -0
  37. package/dist/generator/index.d.ts +25 -0
  38. package/dist/generator/index.d.ts.map +1 -0
  39. package/dist/generator/index.js +106 -0
  40. package/dist/generator/markdown-writer.d.ts +27 -0
  41. package/dist/generator/markdown-writer.d.ts.map +1 -0
  42. package/dist/generator/markdown-writer.js +85 -0
  43. package/dist/index.d.ts +7 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +372 -0
  46. package/dist/scanner/artifact-scanner.d.ts +16 -0
  47. package/dist/scanner/artifact-scanner.d.ts.map +1 -0
  48. package/dist/scanner/artifact-scanner.js +189 -0
  49. package/dist/scanner/code-scanner.d.ts +17 -0
  50. package/dist/scanner/code-scanner.d.ts.map +1 -0
  51. package/dist/scanner/code-scanner.js +69 -0
  52. package/dist/scanner/file-scanner.d.ts +16 -0
  53. package/dist/scanner/file-scanner.d.ts.map +1 -0
  54. package/dist/scanner/file-scanner.js +119 -0
  55. package/dist/scanner/git-scanner.d.ts +10 -0
  56. package/dist/scanner/git-scanner.d.ts.map +1 -0
  57. package/dist/scanner/git-scanner.js +120 -0
  58. package/dist/scanner/index.d.ts +15 -0
  59. package/dist/scanner/index.d.ts.map +1 -0
  60. package/dist/scanner/index.js +106 -0
  61. package/dist/state/index.d.ts +20 -0
  62. package/dist/state/index.d.ts.map +1 -0
  63. package/dist/state/index.js +141 -0
  64. package/dist/state/schema.d.ts +101 -0
  65. package/dist/state/schema.d.ts.map +1 -0
  66. package/dist/state/schema.js +6 -0
  67. package/dist/templates/embedded/adr.md +45 -0
  68. package/dist/templates/embedded/api-spec.md +55 -0
  69. package/dist/templates/embedded/data-model.md +55 -0
  70. package/dist/templates/embedded/deployment-procedure.md +63 -0
  71. package/dist/templates/embedded/runbook.md +55 -0
  72. package/dist/templates/embedded/test-plan.md +55 -0
  73. package/dist/templates/embedded/threat-model.md +47 -0
  74. package/dist/templates/index.d.ts +20 -0
  75. package/dist/templates/index.d.ts.map +1 -0
  76. package/dist/templates/index.js +106 -0
  77. package/dist/templates/registry.d.ts +31 -0
  78. package/dist/templates/registry.d.ts.map +1 -0
  79. package/dist/templates/registry.js +172 -0
  80. package/dist/templates/renderer.d.ts +26 -0
  81. package/dist/templates/renderer.d.ts.map +1 -0
  82. package/dist/templates/renderer.js +145 -0
  83. package/dist/utils/language-detect.d.ts +14 -0
  84. package/dist/utils/language-detect.d.ts.map +1 -0
  85. package/dist/utils/language-detect.js +58 -0
  86. package/dist/utils/logger.d.ts +16 -0
  87. package/dist/utils/logger.d.ts.map +1 -0
  88. package/dist/utils/logger.js +35 -0
  89. package/dist/versioning/differ.d.ts +20 -0
  90. package/dist/versioning/differ.d.ts.map +1 -0
  91. package/dist/versioning/differ.js +160 -0
  92. package/dist/versioning/index.d.ts +44 -0
  93. package/dist/versioning/index.d.ts.map +1 -0
  94. package/dist/versioning/index.js +165 -0
  95. package/package.json +40 -0
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ /**
3
+ * Remote Template Registry Module
4
+ * Handles checking for and downloading remote template updates
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.checkForUpdates = checkForUpdates;
41
+ exports.downloadTemplate = downloadTemplate;
42
+ const path = __importStar(require("path"));
43
+ const fs = __importStar(require("fs"));
44
+ const logger_1 = require("../utils/logger");
45
+ /**
46
+ * Check for template updates by fetching the manifest
47
+ * Falls back gracefully when offline
48
+ */
49
+ async function checkForUpdates(manifestUrl, cacheDir) {
50
+ try {
51
+ logger_1.logger.debug('Checking for template updates', { manifestUrl });
52
+ const manifest = await fetchManifest(manifestUrl);
53
+ const updates = await compareWithCache(manifest.templates, cacheDir);
54
+ return {
55
+ hasUpdates: updates.length > 0,
56
+ availableUpdates: updates,
57
+ timestamp: manifest.timestamp,
58
+ };
59
+ }
60
+ catch (error) {
61
+ logger_1.logger.warn('Failed to check for updates, using cached templates', {
62
+ error: String(error),
63
+ });
64
+ return {
65
+ hasUpdates: false,
66
+ availableUpdates: [],
67
+ timestamp: new Date().toISOString(),
68
+ };
69
+ }
70
+ }
71
+ /**
72
+ * Download a template and cache it
73
+ */
74
+ async function downloadTemplate(docType, url, cacheDir) {
75
+ try {
76
+ logger_1.logger.debug('Downloading template', { docType, url });
77
+ const content = await fetchTemplate(url);
78
+ const templatesDir = path.join(cacheDir, 'templates');
79
+ // Ensure templates directory exists
80
+ fs.mkdirSync(templatesDir, { recursive: true });
81
+ const cachePath = path.join(templatesDir, `${docType}.md`);
82
+ fs.writeFileSync(cachePath, content, 'utf-8');
83
+ logger_1.logger.info('Template downloaded and cached', { docType, path: cachePath });
84
+ }
85
+ catch (error) {
86
+ logger_1.logger.error('Failed to download template', { docType, error: String(error) });
87
+ throw new Error(`Failed to download template for ${docType}: ${String(error)}`);
88
+ }
89
+ }
90
+ /**
91
+ * Fetch a manifest from a remote URL with timeout
92
+ */
93
+ async function fetchManifest(manifestUrl) {
94
+ const controller = new AbortController();
95
+ const timeoutId = setTimeout(() => controller.abort(), 5000);
96
+ try {
97
+ const response = await fetch(manifestUrl, {
98
+ signal: controller.signal,
99
+ });
100
+ if (!response.ok) {
101
+ throw new Error(`Failed to fetch manifest: ${response.status} ${response.statusText}`);
102
+ }
103
+ return (await response.json());
104
+ }
105
+ finally {
106
+ clearTimeout(timeoutId);
107
+ }
108
+ }
109
+ /**
110
+ * Fetch template content from a remote URL with timeout
111
+ */
112
+ async function fetchTemplate(url) {
113
+ const controller = new AbortController();
114
+ const timeoutId = setTimeout(() => controller.abort(), 10000);
115
+ try {
116
+ const response = await fetch(url, {
117
+ signal: controller.signal,
118
+ });
119
+ if (!response.ok) {
120
+ throw new Error(`Failed to fetch template: ${response.status} ${response.statusText}`);
121
+ }
122
+ return await response.text();
123
+ }
124
+ finally {
125
+ clearTimeout(timeoutId);
126
+ }
127
+ }
128
+ /**
129
+ * Compare remote templates with cached versions
130
+ * Returns list of templates with updates available
131
+ */
132
+ async function compareWithCache(remoteTemplates, cacheDir) {
133
+ const updates = [];
134
+ for (const remoteTemplate of remoteTemplates) {
135
+ const cachePath = path.join(cacheDir, 'templates', `${remoteTemplate.docType}.md`);
136
+ // Check if cached version exists
137
+ if (!fs.existsSync(cachePath)) {
138
+ updates.push({
139
+ docType: remoteTemplate.docType,
140
+ url: remoteTemplate.url,
141
+ hash: remoteTemplate.hash,
142
+ version: remoteTemplate.version,
143
+ });
144
+ continue;
145
+ }
146
+ // Compare hashes
147
+ const cachedContent = fs.readFileSync(cachePath, 'utf-8');
148
+ const cachedHash = hashContent(cachedContent);
149
+ if (cachedHash !== remoteTemplate.hash) {
150
+ updates.push({
151
+ docType: remoteTemplate.docType,
152
+ url: remoteTemplate.url,
153
+ hash: remoteTemplate.hash,
154
+ version: remoteTemplate.version,
155
+ });
156
+ }
157
+ }
158
+ return updates;
159
+ }
160
+ /**
161
+ * Simple hash function for content comparison
162
+ * Not for security, just for change detection
163
+ */
164
+ function hashContent(content) {
165
+ let hash = 0;
166
+ for (let i = 0; i < content.length; i++) {
167
+ const char = content.charCodeAt(i);
168
+ hash = (hash << 5) - hash + char;
169
+ hash = hash & hash; // Convert to 32-bit integer
170
+ }
171
+ return Math.abs(hash).toString(16);
172
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Template Renderer Module
3
+ * Renders templates with extracted and user-provided data
4
+ */
5
+ /**
6
+ * Data provided to the renderer
7
+ */
8
+ export interface RenderData {
9
+ extracted: Record<string, string>;
10
+ user: Record<string, string>;
11
+ metadata: {
12
+ docType: string;
13
+ generatedAt: string;
14
+ classification: string;
15
+ sourceArtifacts: number;
16
+ };
17
+ }
18
+ /**
19
+ * Render a template by replacing tokens with data
20
+ * - {{extracted.<section-name>}} - auto-extracted data
21
+ * - {{user.<section-name>}} - user-provided data
22
+ * Marks empty sections with guidance comments
23
+ * Tags confidence levels per section
24
+ */
25
+ export declare function renderTemplate(template: string, data: RenderData): string;
26
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/templates/renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAaD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAwFzE"}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ /**
3
+ * Template Renderer Module
4
+ * Renders templates with extracted and user-provided data
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.renderTemplate = renderTemplate;
8
+ const logger_1 = require("../utils/logger");
9
+ /**
10
+ * Render a template by replacing tokens with data
11
+ * - {{extracted.<section-name>}} - auto-extracted data
12
+ * - {{user.<section-name>}} - user-provided data
13
+ * Marks empty sections with guidance comments
14
+ * Tags confidence levels per section
15
+ */
16
+ function renderTemplate(template, data) {
17
+ let rendered = template;
18
+ const confidenceLevels = [];
19
+ // Extract all token patterns
20
+ const tokenPattern = /\{\{(extracted|user)\.([a-z0-9\-]+)\}\}/g;
21
+ const tokens = new Map();
22
+ let match;
23
+ while ((match = tokenPattern.exec(template)) !== null) {
24
+ const [fullToken, scope, sectionName] = match;
25
+ tokens.set(fullToken, sectionName);
26
+ }
27
+ // Replace tokens and track confidence
28
+ for (const [token, sectionName] of tokens.entries()) {
29
+ const [, scope] = token.match(/\{\{(extracted|user)/) || [];
30
+ const source = scope;
31
+ const extractedValue = data.extracted[sectionName]?.trim() || '';
32
+ const userValue = data.user[sectionName]?.trim() || '';
33
+ // Prefer user-provided data over extracted
34
+ let replacement;
35
+ let confidence;
36
+ let dataSource;
37
+ if (scope === 'user') {
38
+ if (userValue) {
39
+ replacement = userValue;
40
+ confidence = 'high';
41
+ dataSource = 'user';
42
+ }
43
+ else if (extractedValue) {
44
+ // User section can show extracted data as fallback with medium confidence
45
+ replacement = extractedValue;
46
+ confidence = 'medium';
47
+ dataSource = 'extracted';
48
+ }
49
+ else {
50
+ replacement = '';
51
+ confidence = 'low';
52
+ dataSource = 'empty';
53
+ }
54
+ }
55
+ else {
56
+ // extracted scope
57
+ if (extractedValue) {
58
+ replacement = extractedValue;
59
+ confidence = 'high';
60
+ dataSource = 'extracted';
61
+ }
62
+ else {
63
+ replacement = '';
64
+ confidence = 'low';
65
+ dataSource = 'empty';
66
+ }
67
+ }
68
+ rendered = rendered.replace(token, replacement);
69
+ confidenceLevels.push({ section: sectionName, confidence, source: dataSource });
70
+ logger_1.logger.debug('Rendered token', {
71
+ sectionName,
72
+ scope,
73
+ confidence,
74
+ hasData: !!replacement,
75
+ });
76
+ }
77
+ // Mark empty sections with guidance comments
78
+ const guidancePattern = /<!-- NEEDS INPUT: ([^-]*) -->/g;
79
+ let guidanceIndex = 0;
80
+ rendered = rendered.replace(guidancePattern, (match, guidance) => {
81
+ if (guidanceIndex < confidenceLevels.length) {
82
+ const { confidence } = confidenceLevels[guidanceIndex];
83
+ if (confidence === 'low') {
84
+ // Keep the guidance comment for empty sections
85
+ guidanceIndex++;
86
+ return match;
87
+ }
88
+ }
89
+ guidanceIndex++;
90
+ // Remove guidance comments for sections with data
91
+ return '';
92
+ });
93
+ // Add confidence metadata as a comment at the top
94
+ const confidenceSummary = generateConfidenceSummary(confidenceLevels);
95
+ rendered = addMetadataComment(rendered, data.metadata, confidenceSummary);
96
+ return rendered;
97
+ }
98
+ /**
99
+ * Generate a summary of confidence levels per section
100
+ */
101
+ function generateConfidenceSummary(levels) {
102
+ const summary = {};
103
+ for (const { section, confidence } of levels) {
104
+ summary[section] = confidence;
105
+ }
106
+ return summary;
107
+ }
108
+ /**
109
+ * Add metadata comment to the rendered template
110
+ */
111
+ function addMetadataComment(template, metadata, confidenceSummary) {
112
+ const frontmatterMatch = template.match(/^---\n([\s\S]*?)\n---/);
113
+ if (!frontmatterMatch) {
114
+ logger_1.logger.warn('No frontmatter found in template');
115
+ return template;
116
+ }
117
+ const frontmatterEnd = frontmatterMatch[0].length;
118
+ const confidenceComment = generateConfidenceComment(metadata, confidenceSummary);
119
+ return (template.slice(0, frontmatterEnd) +
120
+ '\n' +
121
+ confidenceComment +
122
+ '\n' +
123
+ template.slice(frontmatterEnd));
124
+ }
125
+ /**
126
+ * Generate a markdown comment with metadata and confidence levels
127
+ */
128
+ function generateConfidenceComment(metadata, confidenceSummary) {
129
+ const highConfidence = Object.entries(confidenceSummary)
130
+ .filter(([, level]) => level === 'high')
131
+ .map(([section]) => section);
132
+ const lowConfidence = Object.entries(confidenceSummary)
133
+ .filter(([, level]) => level === 'low')
134
+ .map(([section]) => section);
135
+ const lines = [
136
+ '<!--',
137
+ `Generated: ${metadata.generatedAt}`,
138
+ `Classification: ${metadata.classification}`,
139
+ `Source artifacts: ${metadata.sourceArtifacts}`,
140
+ `High confidence sections: ${highConfidence.length} - ${highConfidence.join(', ') || 'none'}`,
141
+ `Needs input: ${lowConfidence.length} - ${lowConfidence.join(', ') || 'none'}`,
142
+ '-->',
143
+ ];
144
+ return lines.join('\n');
145
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Language Detection Utility
3
+ * Detects programming languages based on package configuration files
4
+ */
5
+ export interface DetectedLanguage {
6
+ name: string;
7
+ confidence: number;
8
+ }
9
+ /**
10
+ * Detects programming languages from a list of package config file paths
11
+ * Returns array of detected languages with confidence scores
12
+ */
13
+ export declare function detectLanguages(packageConfigPaths: string[]): DetectedLanguage[];
14
+ //# sourceMappingURL=language-detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"language-detect.d.ts","sourceRoot":"","sources":["../../src/utils/language-detect.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,kBAAkB,EAAE,MAAM,EAAE,GAC3B,gBAAgB,EAAE,CA0DpB"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Language Detection Utility
4
+ * Detects programming languages based on package configuration files
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.detectLanguages = detectLanguages;
8
+ /**
9
+ * Detects programming languages from a list of package config file paths
10
+ * Returns array of detected languages with confidence scores
11
+ */
12
+ function detectLanguages(packageConfigPaths) {
13
+ const languageMap = new Map();
14
+ for (const filePath of packageConfigPaths) {
15
+ const fileName = filePath.split('/').pop() || '';
16
+ // Node.js/TypeScript
17
+ if (fileName === 'package.json') {
18
+ languageMap.set('TypeScript/JavaScript', (languageMap.get('TypeScript/JavaScript') || 0) + 1);
19
+ }
20
+ // Python
21
+ if (fileName === 'pyproject.toml' || fileName === 'setup.py') {
22
+ languageMap.set('Python', (languageMap.get('Python') || 0) + 1);
23
+ }
24
+ // Rust
25
+ if (fileName === 'Cargo.toml') {
26
+ languageMap.set('Rust', (languageMap.get('Rust') || 0) + 1);
27
+ }
28
+ // Go
29
+ if (fileName === 'go.mod') {
30
+ languageMap.set('Go', (languageMap.get('Go') || 0) + 1);
31
+ }
32
+ // Java/Kotlin
33
+ if (fileName === 'pom.xml') {
34
+ languageMap.set('Java/Kotlin', (languageMap.get('Java/Kotlin') || 0) + 1);
35
+ }
36
+ if (fileName === 'build.gradle' || fileName === 'build.gradle.kts') {
37
+ languageMap.set('Java/Kotlin', (languageMap.get('Java/Kotlin') || 0) + 1);
38
+ }
39
+ // C# / .NET
40
+ if (fileName === 'project.csproj' || fileName.endsWith('.csproj')) {
41
+ languageMap.set('C#/.NET', (languageMap.get('C#/.NET') || 0) + 1);
42
+ }
43
+ // Ruby
44
+ if (fileName === 'Gemfile') {
45
+ languageMap.set('Ruby', (languageMap.get('Ruby') || 0) + 1);
46
+ }
47
+ // PHP
48
+ if (fileName === 'composer.json') {
49
+ languageMap.set('PHP', (languageMap.get('PHP') || 0) + 1);
50
+ }
51
+ }
52
+ // Convert to array and sort by count (confidence)
53
+ const languages = Array.from(languageMap.entries()).map(([name, count]) => ({
54
+ name,
55
+ confidence: Math.min(count / packageConfigPaths.length, 1),
56
+ }));
57
+ return languages.sort((a, b) => b.confidence - a.confidence);
58
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Structured Logger
3
+ * Simple logging utility with info, warn, error, and debug levels
4
+ */
5
+ declare class Logger {
6
+ private isDev;
7
+ private formatTimestamp;
8
+ private format;
9
+ info(message: string, data?: unknown): void;
10
+ warn(message: string, data?: unknown): void;
11
+ error(message: string, data?: unknown): void;
12
+ debug(message: string, data?: unknown): void;
13
+ }
14
+ export declare const logger: Logger;
15
+ export {};
16
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,cAAM,MAAM;IACV,OAAO,CAAC,KAAK,CAA0C;IAEvD,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,MAAM;IAMd,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;CAK7C;AAED,eAAO,MAAM,MAAM,QAAe,CAAC"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Structured Logger
4
+ * Simple logging utility with info, warn, error, and debug levels
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.logger = void 0;
8
+ class Logger {
9
+ constructor() {
10
+ this.isDev = process.env.NODE_ENV === 'development';
11
+ }
12
+ formatTimestamp() {
13
+ return new Date().toISOString();
14
+ }
15
+ format(level, message, data) {
16
+ const timestamp = this.formatTimestamp();
17
+ const dataStr = data ? ` ${JSON.stringify(data)}` : '';
18
+ return `[${timestamp}] [${level.toUpperCase()}] ${message}${dataStr}`;
19
+ }
20
+ info(message, data) {
21
+ console.log(this.format('info', message, data));
22
+ }
23
+ warn(message, data) {
24
+ console.warn(this.format('warn', message, data));
25
+ }
26
+ error(message, data) {
27
+ console.error(this.format('error', message, data));
28
+ }
29
+ debug(message, data) {
30
+ if (this.isDev) {
31
+ console.debug(this.format('debug', message, data));
32
+ }
33
+ }
34
+ }
35
+ exports.logger = new Logger();
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Diff Summary Generator
3
+ * Produces human-readable summaries of changes between document versions
4
+ */
5
+ export interface DiffSummary {
6
+ sectionsAdded: string[];
7
+ sectionsRemoved: string[];
8
+ sectionsChanged: string[];
9
+ linesAdded: number;
10
+ linesRemoved: number;
11
+ summary: string;
12
+ }
13
+ /**
14
+ * Generate a diff summary between two document versions
15
+ * @param oldContent - Previous version content
16
+ * @param newContent - New version content
17
+ * @returns DiffSummary with changes and statistics
18
+ */
19
+ export declare function generateDiffSummary(oldContent: string, newContent: string): DiffSummary;
20
+ //# sourceMappingURL=differ.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"differ.d.ts","sourceRoot":"","sources":["../../src/versioning/differ.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,CAqDvF"}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ /**
3
+ * Diff Summary Generator
4
+ * Produces human-readable summaries of changes between document versions
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.generateDiffSummary = generateDiffSummary;
41
+ const Diff = __importStar(require("diff"));
42
+ /**
43
+ * Generate a diff summary between two document versions
44
+ * @param oldContent - Previous version content
45
+ * @param newContent - New version content
46
+ * @returns DiffSummary with changes and statistics
47
+ */
48
+ function generateDiffSummary(oldContent, newContent) {
49
+ const oldLines = oldContent.split('\n');
50
+ const newLines = newContent.split('\n');
51
+ // Get line-level changes
52
+ const changes = Diff.diffLines(oldContent, newContent);
53
+ // Count additions and removals
54
+ let linesAdded = 0;
55
+ let linesRemoved = 0;
56
+ for (const change of changes) {
57
+ if (change.added) {
58
+ linesAdded += change.value.split('\n').filter((l) => l.length > 0).length;
59
+ }
60
+ else if (change.removed) {
61
+ linesRemoved += change.value.split('\n').filter((l) => l.length > 0).length;
62
+ }
63
+ }
64
+ // Extract sections (markdown headers)
65
+ const oldSections = extractSections(oldLines);
66
+ const newSections = extractSections(newLines);
67
+ // Compare sections
68
+ const sectionsAdded = newSections.filter((s) => !oldSections.includes(s));
69
+ const sectionsRemoved = oldSections.filter((s) => !newSections.includes(s));
70
+ const sectionsChanged = findChangedSections(oldContent, newContent, oldSections, newSections);
71
+ // Build summary
72
+ const summaryParts = [];
73
+ if (sectionsAdded.length > 0) {
74
+ summaryParts.push(`Added ${sectionsAdded.length} section(s)`);
75
+ }
76
+ if (sectionsRemoved.length > 0) {
77
+ summaryParts.push(`Removed ${sectionsRemoved.length} section(s)`);
78
+ }
79
+ if (sectionsChanged.length > 0) {
80
+ summaryParts.push(`Updated ${sectionsChanged.length} section(s)`);
81
+ }
82
+ summaryParts.push(`+${linesAdded} -${linesRemoved} lines`);
83
+ const summary = summaryParts.join(', ');
84
+ return {
85
+ sectionsAdded,
86
+ sectionsRemoved,
87
+ sectionsChanged,
88
+ linesAdded,
89
+ linesRemoved,
90
+ summary,
91
+ };
92
+ }
93
+ /**
94
+ * Extract all markdown headers from content
95
+ * Matches ## and ### level headers
96
+ */
97
+ function extractSections(lines) {
98
+ const sections = [];
99
+ for (const line of lines) {
100
+ if (line.match(/^##\s+/) || line.match(/^###\s+/)) {
101
+ // Extract header text (remove markdown syntax)
102
+ const text = line.replace(/^#+\s+/, '').trim();
103
+ if (text.length > 0) {
104
+ sections.push(text);
105
+ }
106
+ }
107
+ }
108
+ return sections;
109
+ }
110
+ /**
111
+ * Find sections that exist in both versions but have changed content
112
+ * This is a heuristic: we check if section content differs
113
+ */
114
+ function findChangedSections(oldContent, newContent, oldSections, newSections) {
115
+ const common = oldSections.filter((s) => newSections.includes(s));
116
+ const changed = [];
117
+ for (const section of common) {
118
+ // Extract content for this section from both versions
119
+ const oldSectionContent = extractSectionContent(oldContent, section);
120
+ const newSectionContent = extractSectionContent(newContent, section);
121
+ // If content differs, it's changed
122
+ if (oldSectionContent !== newSectionContent) {
123
+ changed.push(section);
124
+ }
125
+ }
126
+ return changed;
127
+ }
128
+ /**
129
+ * Extract the content of a specific section from markdown
130
+ * Returns text from the header until the next header of same or higher level
131
+ */
132
+ function extractSectionContent(content, sectionTitle) {
133
+ const lines = content.split('\n');
134
+ let startIdx = -1;
135
+ let endIdx = lines.length;
136
+ // Find the section header
137
+ for (let i = 0; i < lines.length; i++) {
138
+ if (lines[i].includes(sectionTitle)) {
139
+ startIdx = i;
140
+ break;
141
+ }
142
+ }
143
+ if (startIdx === -1) {
144
+ return '';
145
+ }
146
+ // Find the next header of same or higher level (## or ###)
147
+ const headerMatch = lines[startIdx].match(/^(#+)\s+/);
148
+ const headerLevel = headerMatch ? headerMatch[1].length : 0;
149
+ for (let i = startIdx + 1; i < lines.length; i++) {
150
+ const nextHeaderMatch = lines[i].match(/^(#+)\s+/);
151
+ if (nextHeaderMatch) {
152
+ const nextLevel = nextHeaderMatch[1].length;
153
+ if (nextLevel <= headerLevel) {
154
+ endIdx = i;
155
+ break;
156
+ }
157
+ }
158
+ }
159
+ return lines.slice(startIdx, endIdx).join('\n');
160
+ }