@mcp-consultant-tools/azure-devops 27.0.0-beta.1 → 27.0.0-beta.3

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.
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Git Utilities for Work Item Sync
3
+ *
4
+ * Handles git operations for auto-commit functionality.
5
+ * All git operations are optional and fail gracefully.
6
+ */
7
+ import { exec } from 'node:child_process';
8
+ import { promisify } from 'node:util';
9
+ import * as path from 'node:path';
10
+ const execAsync = promisify(exec);
11
+ /**
12
+ * Check if the current directory is a git repository
13
+ */
14
+ export async function isGitRepo(cwd) {
15
+ try {
16
+ await execAsync('git rev-parse --is-inside-work-tree', {
17
+ cwd: cwd || process.cwd(),
18
+ });
19
+ return true;
20
+ }
21
+ catch {
22
+ return false;
23
+ }
24
+ }
25
+ /**
26
+ * Git add a file
27
+ */
28
+ async function gitAdd(filePath, cwd) {
29
+ await execAsync(`git add "${filePath}"`, {
30
+ cwd: cwd || process.cwd(),
31
+ });
32
+ }
33
+ /**
34
+ * Git commit with a message
35
+ */
36
+ async function gitCommit(message, cwd) {
37
+ const { stdout } = await execAsync(`git commit -m "${message.replace(/"/g, '\\"')}"`, {
38
+ cwd: cwd || process.cwd(),
39
+ });
40
+ return stdout;
41
+ }
42
+ /**
43
+ * Auto-commit a work item file after pull
44
+ * Returns result indicating success or failure (non-blocking)
45
+ */
46
+ export async function autoCommitPulledFile(filePath, workItemId, revision, cwd) {
47
+ try {
48
+ // Check if we're in a git repo
49
+ if (!await isGitRepo(cwd)) {
50
+ return {
51
+ committed: false,
52
+ error: 'Not a git repository',
53
+ };
54
+ }
55
+ // Get relative path for cleaner commit message
56
+ const workingDir = cwd || process.cwd();
57
+ const relativePath = path.relative(workingDir, filePath);
58
+ // Add the file
59
+ await gitAdd(filePath, workingDir);
60
+ // Commit with descriptive message
61
+ const commitMessage = `Pull user story #${workItemId} from ADO (rev ${revision})`;
62
+ await gitCommit(commitMessage, workingDir);
63
+ return {
64
+ committed: true,
65
+ message: commitMessage,
66
+ };
67
+ }
68
+ catch (error) {
69
+ // Git failures are non-blocking - log and continue
70
+ console.error(`Git auto-commit failed for work item #${workItemId}: ${error.message}`);
71
+ return {
72
+ committed: false,
73
+ error: error.message,
74
+ };
75
+ }
76
+ }
77
+ /**
78
+ * Auto-commit multiple work item files in a single commit
79
+ */
80
+ export async function autoCommitMultipleFiles(files, revision, cwd) {
81
+ if (files.length === 0) {
82
+ return { committed: false, error: 'No files to commit' };
83
+ }
84
+ try {
85
+ // Check if we're in a git repo
86
+ if (!await isGitRepo(cwd)) {
87
+ return {
88
+ committed: false,
89
+ error: 'Not a git repository',
90
+ };
91
+ }
92
+ const workingDir = cwd || process.cwd();
93
+ // Add all files
94
+ for (const file of files) {
95
+ await gitAdd(file.filePath, workingDir);
96
+ }
97
+ // Build commit message
98
+ const ids = files.map(f => `#${f.workItemId}`).join(', ');
99
+ const commitMessage = files.length === 1
100
+ ? `Pull user story ${ids} from ADO`
101
+ : `Pull user stories ${ids} from ADO`;
102
+ await gitCommit(commitMessage, workingDir);
103
+ return {
104
+ committed: true,
105
+ message: commitMessage,
106
+ };
107
+ }
108
+ catch (error) {
109
+ console.error(`Git auto-commit failed: ${error.message}`);
110
+ return {
111
+ committed: false,
112
+ error: error.message,
113
+ };
114
+ }
115
+ }
116
+ //# sourceMappingURL=git-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-utils.js","sourceRoot":"","sources":["../../src/sync/git-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAY;IAC1C,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,qCAAqC,EAAE;YACrD,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;SAC1B,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,MAAM,CAAC,QAAgB,EAAE,GAAY;IAClD,MAAM,SAAS,CAAC,YAAY,QAAQ,GAAG,EAAE;QACvC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;KAC1B,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,GAAY;IACpD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,kBAAkB,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE;QACpF,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;KAC1B,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAWD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,QAAgB,EAChB,UAAkB,EAClB,QAAgB,EAChB,GAAY;IAEZ,IAAI,CAAC;QACH,+BAA+B;QAC/B,IAAI,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,sBAAsB;aAC9B,CAAC;QACJ,CAAC;QAED,+CAA+C;QAC/C,MAAM,UAAU,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACxC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEzD,eAAe;QACf,MAAM,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAEnC,kCAAkC;QAClC,MAAM,aAAa,GAAG,oBAAoB,UAAU,kBAAkB,QAAQ,GAAG,CAAC;QAClF,MAAM,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAE3C,OAAO;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,aAAa;SACvB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,mDAAmD;QACnD,OAAO,CAAC,KAAK,CAAC,yCAAyC,UAAU,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACvF,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,KAAK,CAAC,OAAO;SACrB,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,KAAiD,EACjD,QAAgB,EAChB,GAAY;IAEZ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,CAAC;QACH,+BAA+B;QAC/B,IAAI,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,sBAAsB;aAC9B,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAExC,gBAAgB;QAChB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC1C,CAAC;QAED,uBAAuB;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,KAAK,CAAC;YACtC,CAAC,CAAC,mBAAmB,GAAG,WAAW;YACnC,CAAC,CAAC,qBAAqB,GAAG,WAAW,CAAC;QAExC,MAAM,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAE3C,OAAO;YACL,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,aAAa;SACvB,CAAC;IACJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO;YACL,SAAS,EAAE,KAAK;YAChB,KAAK,EAAE,KAAK,CAAC,OAAO;SACrB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * HTML Detection Utility
3
+ *
4
+ * Detects whether ADO work item content is HTML (legacy) or Markdown format.
5
+ * ADO supports both formats and we can only sync markdown fields.
6
+ */
7
+ /**
8
+ * Additional custom fields that can be synced.
9
+ * These are configurable via environment variables since field names may vary by organization.
10
+ *
11
+ * Default field names are based on typical ADO custom field patterns.
12
+ * GUID-based fields (like pre/post deployment) may vary between organizations.
13
+ */
14
+ export interface AdditionalFieldConfig {
15
+ howToTest: string;
16
+ deploymentInformation: string;
17
+ predeploymentSteps: string;
18
+ postdeploymentSteps: string;
19
+ }
20
+ /**
21
+ * Get additional field configuration from environment variables
22
+ * Falls back to common default field names
23
+ */
24
+ export declare function getAdditionalFieldConfig(): AdditionalFieldConfig;
25
+ /**
26
+ * Human-readable names for additional fields (for display/logging)
27
+ */
28
+ export declare const ADDITIONAL_FIELD_DISPLAY_NAMES: Record<keyof AdditionalFieldConfig, string>;
29
+ /**
30
+ * Check if content is HTML format (as opposed to markdown)
31
+ *
32
+ * @param content - The content string to check
33
+ * @returns true if content appears to be HTML, false if markdown or empty
34
+ */
35
+ export declare function isHtmlContent(content: string | null | undefined): boolean;
36
+ /**
37
+ * Field format result type
38
+ */
39
+ export type FieldFormat = 'markdown' | 'html' | 'not_present';
40
+ /**
41
+ * Result of checking additional field formats
42
+ */
43
+ export interface AdditionalFieldFormats {
44
+ howToTest: FieldFormat;
45
+ deploymentInformation: FieldFormat;
46
+ predeploymentSteps: FieldFormat;
47
+ postdeploymentSteps: FieldFormat;
48
+ }
49
+ /**
50
+ * Full field format check result
51
+ */
52
+ export interface FieldFormatResult {
53
+ description: 'markdown' | 'html';
54
+ acceptanceCriteria: 'markdown' | 'html';
55
+ ready: boolean;
56
+ warnings: string[];
57
+ additionalFields: AdditionalFieldFormats;
58
+ details: {
59
+ descriptionLength: number;
60
+ acceptanceCriteriaLength: number;
61
+ };
62
+ }
63
+ /**
64
+ * Check field formats for a work item
65
+ *
66
+ * Primary fields (Description, Acceptance Criteria): If HTML, work item is not ready for sync.
67
+ * Secondary fields (How to Test, Deployment fields): If HTML, warn but allow sync (skip those fields).
68
+ *
69
+ * @param workItem - The work item object from ADO API
70
+ * @returns Object with field format information
71
+ */
72
+ export declare function checkFieldFormats(workItem: {
73
+ fields?: {
74
+ 'System.Description'?: string;
75
+ 'Microsoft.VSTS.Common.AcceptanceCriteria'?: string;
76
+ [key: string]: any;
77
+ };
78
+ }): FieldFormatResult;
79
+ /**
80
+ * Get human-readable conversion instructions
81
+ */
82
+ export declare function getConversionInstructions(): string;
83
+ //# sourceMappingURL=html-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-detection.d.ts","sourceRoot":"","sources":["../../src/sync/html-detection.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,qBAAqB,CAOhE;AAED;;GAEG;AACH,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,MAAM,qBAAqB,EAAE,MAAM,CAKtF,CAAC;AA8BF;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAsBzE;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,aAAa,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,WAAW,CAAC;IACvB,qBAAqB,EAAE,WAAW,CAAC;IACnC,kBAAkB,EAAE,WAAW,CAAC;IAChC,mBAAmB,EAAE,WAAW,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,UAAU,GAAG,MAAM,CAAC;IACjC,kBAAkB,EAAE,UAAU,GAAG,MAAM,CAAC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,OAAO,EAAE;QACP,iBAAiB,EAAE,MAAM,CAAC;QAC1B,wBAAwB,EAAE,MAAM,CAAC;KAClC,CAAC;CACH;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE;IAC1C,MAAM,CAAC,EAAE;QACP,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,0CAA0C,CAAC,EAAE,MAAM,CAAC;QACpD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH,GAAG,iBAAiB,CAmDpB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAUlD"}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * HTML Detection Utility
3
+ *
4
+ * Detects whether ADO work item content is HTML (legacy) or Markdown format.
5
+ * ADO supports both formats and we can only sync markdown fields.
6
+ */
7
+ /**
8
+ * Get additional field configuration from environment variables
9
+ * Falls back to common default field names
10
+ */
11
+ export function getAdditionalFieldConfig() {
12
+ return {
13
+ howToTest: process.env.AZUREDEVOPS_SYNC_FIELD_HOW_TO_TEST || 'Custom.Howtotest',
14
+ deploymentInformation: process.env.AZUREDEVOPS_SYNC_FIELD_DEPLOYMENT_INFO || 'Custom.Deploymentinformation',
15
+ predeploymentSteps: process.env.AZUREDEVOPS_SYNC_FIELD_PREDEPLOY || 'Custom.7519d1bc-5305-4905-822b-2b380e61b154',
16
+ postdeploymentSteps: process.env.AZUREDEVOPS_SYNC_FIELD_POSTDEPLOY || 'Custom.abd6763f-a242-4938-85ed-bda419e34e7e',
17
+ };
18
+ }
19
+ /**
20
+ * Human-readable names for additional fields (for display/logging)
21
+ */
22
+ export const ADDITIONAL_FIELD_DISPLAY_NAMES = {
23
+ howToTest: 'How to Test',
24
+ deploymentInformation: 'Deployment Information',
25
+ predeploymentSteps: 'Predeployment Steps',
26
+ postdeploymentSteps: 'Postdeployment Steps',
27
+ };
28
+ // Structural HTML patterns that indicate the content is HTML (not markdown)
29
+ const HTML_STRUCTURAL_PATTERNS = [
30
+ /<div[^>]*>/i, // <div> tags
31
+ /<p[^>]*>/i, // <p> tags
32
+ /<h[1-6][^>]*>/i, // HTML heading tags
33
+ /<strong[^>]*>/i, // <strong> tags (instead of **)
34
+ /<em[^>]*>/i, // <em> tags (instead of *)
35
+ /<ul[^>]*>/i, // HTML unordered lists
36
+ /<ol[^>]*>/i, // HTML ordered lists
37
+ /<li[^>]*>/i, // List items in HTML
38
+ /<table[^>]*>/i, // HTML tables
39
+ /<tr[^>]*>/i, // Table rows
40
+ /<td[^>]*>/i, // Table cells
41
+ /<span[^>]*>/i, // Span elements (ADO often uses these)
42
+ ];
43
+ // Markdown patterns that indicate the content is already markdown
44
+ const MARKDOWN_PATTERNS = [
45
+ /^#{1,6}\s+/m, // Markdown headings (# Heading)
46
+ /\*\*[^*]+\*\*/, // Bold text with **
47
+ /^\s*[-*+]\s+/m, // Unordered list items (-, *, +)
48
+ /^\s*\d+\.\s+/m, // Numbered list items (1. item)
49
+ /\[.+?\]\(.+?\)/, // Markdown links [text](url)
50
+ /```[\s\S]*?```/, // Fenced code blocks
51
+ /`[^`]+`/, // Inline code
52
+ /^\s*>\s+/m, // Block quotes
53
+ ];
54
+ /**
55
+ * Check if content is HTML format (as opposed to markdown)
56
+ *
57
+ * @param content - The content string to check
58
+ * @returns true if content appears to be HTML, false if markdown or empty
59
+ */
60
+ export function isHtmlContent(content) {
61
+ if (!content?.trim()) {
62
+ return false;
63
+ }
64
+ // If clear markdown syntax is present, treat as markdown (even if some inline HTML exists)
65
+ // This handles cases where users mix markdown with allowed inline HTML
66
+ for (const pattern of MARKDOWN_PATTERNS) {
67
+ if (pattern.test(content)) {
68
+ return false;
69
+ }
70
+ }
71
+ // Check for structural HTML patterns that indicate this is HTML content
72
+ for (const pattern of HTML_STRUCTURAL_PATTERNS) {
73
+ if (pattern.test(content)) {
74
+ return true;
75
+ }
76
+ }
77
+ // Default to markdown (plain text is valid markdown)
78
+ return false;
79
+ }
80
+ /**
81
+ * Check field formats for a work item
82
+ *
83
+ * Primary fields (Description, Acceptance Criteria): If HTML, work item is not ready for sync.
84
+ * Secondary fields (How to Test, Deployment fields): If HTML, warn but allow sync (skip those fields).
85
+ *
86
+ * @param workItem - The work item object from ADO API
87
+ * @returns Object with field format information
88
+ */
89
+ export function checkFieldFormats(workItem) {
90
+ const fields = workItem.fields || {};
91
+ const fieldConfig = getAdditionalFieldConfig();
92
+ const description = fields['System.Description'] || '';
93
+ const acceptanceCriteria = fields['Microsoft.VSTS.Common.AcceptanceCriteria'] || '';
94
+ const descriptionIsHtml = isHtmlContent(description);
95
+ const acceptanceCriteriaIsHtml = isHtmlContent(acceptanceCriteria);
96
+ // Check additional fields
97
+ const warnings = [];
98
+ const additionalFields = {
99
+ howToTest: 'not_present',
100
+ deploymentInformation: 'not_present',
101
+ predeploymentSteps: 'not_present',
102
+ postdeploymentSteps: 'not_present',
103
+ };
104
+ // Helper to check an additional field
105
+ const checkAdditionalField = (fieldName, configKey) => {
106
+ const content = fields[fieldName];
107
+ if (!content || !content.trim()) {
108
+ return 'not_present';
109
+ }
110
+ if (isHtmlContent(content)) {
111
+ warnings.push(`${ADDITIONAL_FIELD_DISPLAY_NAMES[configKey]} is HTML - will be skipped`);
112
+ return 'html';
113
+ }
114
+ return 'markdown';
115
+ };
116
+ additionalFields.howToTest = checkAdditionalField(fieldConfig.howToTest, 'howToTest');
117
+ additionalFields.deploymentInformation = checkAdditionalField(fieldConfig.deploymentInformation, 'deploymentInformation');
118
+ additionalFields.predeploymentSteps = checkAdditionalField(fieldConfig.predeploymentSteps, 'predeploymentSteps');
119
+ additionalFields.postdeploymentSteps = checkAdditionalField(fieldConfig.postdeploymentSteps, 'postdeploymentSteps');
120
+ return {
121
+ description: descriptionIsHtml ? 'html' : 'markdown',
122
+ acceptanceCriteria: acceptanceCriteriaIsHtml ? 'html' : 'markdown',
123
+ ready: !descriptionIsHtml && !acceptanceCriteriaIsHtml,
124
+ warnings,
125
+ additionalFields,
126
+ details: {
127
+ descriptionLength: description.length,
128
+ acceptanceCriteriaLength: acceptanceCriteria.length,
129
+ }
130
+ };
131
+ }
132
+ /**
133
+ * Get human-readable conversion instructions
134
+ */
135
+ export function getConversionInstructions() {
136
+ return `To convert HTML fields to markdown in Azure DevOps:
137
+ 1. Open the work item in Azure DevOps
138
+ 2. Click in the Description or Acceptance Criteria field
139
+ 3. Look for the "Convert to Markdown" button in the toolbar
140
+ 4. Click it and confirm the conversion
141
+ 5. Save the work item
142
+ 6. Re-run the sync command
143
+
144
+ Note: Some organizations may have HTML format enforced. Contact your ADO admin if the option is not available.`;
145
+ }
146
+ //# sourceMappingURL=html-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-detection.js","sourceRoot":"","sources":["../../src/sync/html-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Work Item Sync Module
3
+ *
4
+ * Exports all sync-related utilities for syncing ADO work items to local markdown files.
5
+ */
6
+ export * from './html-detection.js';
7
+ export * from './markdown-serializer.js';
8
+ export * from './file-utils.js';
9
+ export * from './git-utils.js';
10
+ export * from './task-serializer.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Work Item Sync Module
3
+ *
4
+ * Exports all sync-related utilities for syncing ADO work items to local markdown files.
5
+ */
6
+ export * from './html-detection.js';
7
+ export * from './markdown-serializer.js';
8
+ export * from './file-utils.js';
9
+ export * from './git-utils.js';
10
+ export * from './task-serializer.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Markdown Serialization Utilities
3
+ *
4
+ * Convert between ADO work items and local markdown files.
5
+ * Uses YAML frontmatter for metadata and markdown sections for content.
6
+ */
7
+ export interface WorkItemFrontmatter {
8
+ id: number;
9
+ title: string;
10
+ type: string;
11
+ state: string;
12
+ url: string;
13
+ assignedTo?: string;
14
+ storyPoints?: number;
15
+ parent?: number;
16
+ moscow?: string;
17
+ tags?: string[];
18
+ areaPath?: string;
19
+ iterationPath?: string;
20
+ lastSyncedRevision: number;
21
+ lastSyncedAt: string;
22
+ }
23
+ export interface AdditionalFields {
24
+ howToTest?: string;
25
+ deploymentInformation?: string;
26
+ predeploymentSteps?: string;
27
+ postdeploymentSteps?: string;
28
+ }
29
+ export interface ParsedWorkItemFile {
30
+ frontmatter: WorkItemFrontmatter;
31
+ description: string;
32
+ acceptanceCriteria: string;
33
+ additionalFields: AdditionalFields;
34
+ rawContent: string;
35
+ }
36
+ export interface CommentsFrontmatter {
37
+ id: number;
38
+ title: string;
39
+ commentCount: number;
40
+ lastSyncedAt: string;
41
+ }
42
+ export interface ParsedComment {
43
+ author: string;
44
+ date: string;
45
+ content: string;
46
+ }
47
+ /**
48
+ * Result of converting work item to markdown
49
+ */
50
+ export interface WorkItemToMarkdownResult {
51
+ content: string;
52
+ skippedFields: string[];
53
+ }
54
+ /**
55
+ * Convert an ADO work item to markdown file content
56
+ *
57
+ * @param workItem - The work item from ADO API
58
+ * @param revision - The revision number
59
+ * @returns Object with markdown content and list of skipped fields (if any were HTML)
60
+ */
61
+ export declare function workItemToMarkdown(workItem: any, revision: number): WorkItemToMarkdownResult;
62
+ /**
63
+ * Parse a markdown file to extract frontmatter and content sections
64
+ */
65
+ export declare function parseWorkItemMarkdown(content: string): ParsedWorkItemFile;
66
+ /**
67
+ * Convert ADO comments to a read-only markdown file
68
+ */
69
+ export declare function commentsToMarkdown(workItem: any, comments: any[]): string;
70
+ /**
71
+ * Build ADO patch operations from parsed markdown changes
72
+ * Only updates fields that have actually changed
73
+ */
74
+ export declare function buildPatchOperations(parsed: ParsedWorkItemFile, currentWorkItem: any): {
75
+ operations: any[];
76
+ skippedFields: string[];
77
+ };
78
+ /**
79
+ * Update the lastSyncedRevision in a markdown file content
80
+ */
81
+ export declare function updateSyncRevision(content: string, newRevision: number): string;
82
+ /**
83
+ * Frontmatter for new work items (before they have an ID)
84
+ */
85
+ export interface NewWorkItemFrontmatter {
86
+ title: string;
87
+ type: string;
88
+ state: string;
89
+ parent: number;
90
+ assignedTo?: string;
91
+ storyPoints?: number;
92
+ moscow?: string;
93
+ tags?: string[];
94
+ areaPath?: string;
95
+ iterationPath?: string;
96
+ }
97
+ /**
98
+ * Parsed new work item file structure
99
+ */
100
+ export interface ParsedNewWorkItemFile {
101
+ frontmatter: NewWorkItemFrontmatter;
102
+ description: string;
103
+ acceptanceCriteria: string;
104
+ additionalFields: AdditionalFields;
105
+ rawContent: string;
106
+ }
107
+ /**
108
+ * Check if a work item frontmatter indicates a new (not yet created) work item
109
+ * New work items don't have an 'id' field
110
+ */
111
+ export declare function isNewWorkItem(frontmatter: Record<string, any>): boolean;
112
+ /**
113
+ * Parse a markdown file for a NEW work item (no id required)
114
+ */
115
+ export declare function parseNewWorkItemMarkdown(content: string): ParsedNewWorkItemFile;
116
+ /**
117
+ * Build ADO fields object for creating a new work item
118
+ * Inherits areaPath and iterationPath from parent work item
119
+ */
120
+ export declare function buildNewWorkItemFields(parsed: ParsedNewWorkItemFile, parentWorkItem: any): Record<string, any>;
121
+ /**
122
+ * Generate a new work item template markdown file
123
+ */
124
+ export declare function generateNewWorkItemTemplate(parentId: number, parentTitle: string, project: string, workItemType?: string): string;
125
+ /**
126
+ * Update a new work item file after creation with the assigned ID
127
+ * Converts it from a "new" file to a synced file with proper frontmatter
128
+ */
129
+ export declare function convertNewFileToSynced(content: string, workItemId: number, revision: number, url: string): string;
130
+ //# sourceMappingURL=markdown-serializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-serializer.d.ts","sourceRoot":"","sources":["../../src/sync/markdown-serializer.ts"],"names":[],"mappings":"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"}