specweave 1.0.459 → 1.0.461
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.
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts +1 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +3 -3
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts +9 -0
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +43 -3
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.d.ts +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js +6 -6
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.d.ts +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +3 -3
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/lib/vendor/sync/config.d.ts +73 -0
- package/plugins/specweave/lib/vendor/sync/config.js +132 -0
- package/plugins/specweave/lib/vendor/sync/config.js.map +1 -0
- package/plugins/specweave/lib/vendor/sync/provider-router.d.ts +86 -0
- package/plugins/specweave/lib/vendor/sync/provider-router.js +147 -0
- package/plugins/specweave/lib/vendor/sync/provider-router.js.map +1 -0
- package/plugins/specweave/lib/vendor/sync/status-mapper.d.ts +120 -0
- package/plugins/specweave/lib/vendor/sync/status-mapper.js +164 -0
- package/plugins/specweave/lib/vendor/sync/status-mapper.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/project-detection.d.ts +250 -0
- package/plugins/specweave/lib/vendor/utils/project-detection.js +560 -0
- package/plugins/specweave/lib/vendor/utils/project-detection.js.map +1 -0
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +3 -3
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +3 -3
- package/plugins/specweave-ado/lib/ado-spec-sync.js +41 -3
- package/plugins/specweave-ado/lib/ado-spec-sync.ts +47 -3
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.js +6 -6
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.ts +6 -6
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +3 -3
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.ts +3 -3
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Config — Permission Presets & Config Validation
|
|
3
|
+
*
|
|
4
|
+
* ADR-0236: Named presets replace 8+ booleans.
|
|
5
|
+
* 4 presets: read-only, push-only, bidirectional, full-control
|
|
6
|
+
* With optional per-flag overrides.
|
|
7
|
+
*/
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Preset defaults
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export const PRESET_DEFAULTS = {
|
|
12
|
+
'read-only': {
|
|
13
|
+
canRead: true,
|
|
14
|
+
canUpdateStatus: false,
|
|
15
|
+
canUpsert: false,
|
|
16
|
+
canDelete: false,
|
|
17
|
+
},
|
|
18
|
+
'push-only': {
|
|
19
|
+
canRead: false,
|
|
20
|
+
canUpdateStatus: true,
|
|
21
|
+
canUpsert: true,
|
|
22
|
+
canDelete: false,
|
|
23
|
+
},
|
|
24
|
+
bidirectional: {
|
|
25
|
+
canRead: true,
|
|
26
|
+
canUpdateStatus: true,
|
|
27
|
+
canUpsert: true,
|
|
28
|
+
canDelete: false,
|
|
29
|
+
},
|
|
30
|
+
'full-control': {
|
|
31
|
+
canRead: true,
|
|
32
|
+
canUpdateStatus: true,
|
|
33
|
+
canUpsert: true,
|
|
34
|
+
canDelete: true,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// Permission resolution
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
/**
|
|
41
|
+
* Resolve effective permissions from preset + overrides + legacy settings.
|
|
42
|
+
*
|
|
43
|
+
* Priority: preset → overrides → effective
|
|
44
|
+
* If no preset, falls back to legacy boolean settings.
|
|
45
|
+
*/
|
|
46
|
+
export function resolvePermissions(preset, overrides, legacySettings) {
|
|
47
|
+
let base;
|
|
48
|
+
if (preset && PRESET_DEFAULTS[preset]) {
|
|
49
|
+
base = { ...PRESET_DEFAULTS[preset] };
|
|
50
|
+
}
|
|
51
|
+
else if (legacySettings) {
|
|
52
|
+
// Backward compat: map old booleans to new permissions
|
|
53
|
+
base = {
|
|
54
|
+
canRead: legacySettings.canUpdateExternalItems ?? true,
|
|
55
|
+
canUpdateStatus: legacySettings.canUpdateStatus ?? true,
|
|
56
|
+
canUpsert: legacySettings.canUpsertInternalItems ?? true,
|
|
57
|
+
canDelete: false, // legacy system had no delete
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Default to read-only
|
|
62
|
+
base = { ...PRESET_DEFAULTS['read-only'] };
|
|
63
|
+
}
|
|
64
|
+
if (overrides) {
|
|
65
|
+
if (overrides.canRead !== undefined)
|
|
66
|
+
base.canRead = overrides.canRead;
|
|
67
|
+
if (overrides.canUpdateStatus !== undefined)
|
|
68
|
+
base.canUpdateStatus = overrides.canUpdateStatus;
|
|
69
|
+
if (overrides.canUpsert !== undefined)
|
|
70
|
+
base.canUpsert = overrides.canUpsert;
|
|
71
|
+
if (overrides.canDelete !== undefined)
|
|
72
|
+
base.canDelete = overrides.canDelete;
|
|
73
|
+
}
|
|
74
|
+
return base;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validate sync configuration for consistency and report issues.
|
|
78
|
+
*/
|
|
79
|
+
export function validateSyncConfigConsistency(config, syncMetadata) {
|
|
80
|
+
const issues = [];
|
|
81
|
+
// Check: enabled=false with write flags=true
|
|
82
|
+
if (config.enabled === false && config.settings) {
|
|
83
|
+
const { canUpsertInternalItems, canUpdateExternalItems, canUpdateStatus } = config.settings;
|
|
84
|
+
if (canUpsertInternalItems || canUpdateExternalItems || canUpdateStatus) {
|
|
85
|
+
issues.push({
|
|
86
|
+
type: 'contradiction',
|
|
87
|
+
message: 'Sync is disabled but write permissions are enabled. The effective behavior is disabled (sync.enabled=false overrides all).',
|
|
88
|
+
suggestedFix: 'Either set sync.enabled=true to use the permissions, or set all permission flags to false.',
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check: provider enabled but incomplete config (legacy format only)
|
|
93
|
+
// Skip these checks when the provider is configured via profiles instead
|
|
94
|
+
if (config.enabled !== false) {
|
|
95
|
+
const profileProviders = new Set(Object.values(config.profiles ?? {}).map((p) => p.provider).filter(Boolean));
|
|
96
|
+
if (config.github?.enabled && !config.github.owner && !config.github.repo && !profileProviders.has('github')) {
|
|
97
|
+
issues.push({
|
|
98
|
+
type: 'warning',
|
|
99
|
+
message: 'GitHub sync enabled but github.owner and github.repo are not configured.',
|
|
100
|
+
suggestedFix: 'Set sync.github.owner and sync.github.repo in config.json, or run /sw:sync-setup.',
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (config.jira?.enabled && !config.jira.domain && !profileProviders.has('jira')) {
|
|
104
|
+
issues.push({
|
|
105
|
+
type: 'warning',
|
|
106
|
+
message: 'JIRA sync enabled but jira.domain is not configured.',
|
|
107
|
+
suggestedFix: 'Set sync.jira.domain and sync.jira.projectKey in config.json.',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
if (config.ado?.enabled && !config.ado.organization && !profileProviders.has('ado')) {
|
|
111
|
+
issues.push({
|
|
112
|
+
type: 'warning',
|
|
113
|
+
message: 'ADO sync enabled but ado.organization is not configured.',
|
|
114
|
+
suggestedFix: 'Set sync.ado.organization and sync.ado.project in config.json.',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Check sync metadata for failures
|
|
119
|
+
if (syncMetadata) {
|
|
120
|
+
for (const [platform, meta] of Object.entries(syncMetadata)) {
|
|
121
|
+
if (meta.lastSyncResult === 'failed') {
|
|
122
|
+
issues.push({
|
|
123
|
+
type: 'failure',
|
|
124
|
+
message: `${platform} sync last result was "failed" with ${meta.lastImportCount ?? 0} imports.`,
|
|
125
|
+
suggestedFix: `Check ${platform} credentials and configuration. Run /sw:sync-setup to reconfigure.`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return issues;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/sync/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Router Service
|
|
3
|
+
*
|
|
4
|
+
* Routes sync operations to the correct external provider (GitHub, JIRA, ADO).
|
|
5
|
+
* Extracted from sync-coordinator.ts for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* @module sync/provider-router
|
|
8
|
+
* @since v1.0.115
|
|
9
|
+
*/
|
|
10
|
+
import { Logger } from '../utils/logger.js';
|
|
11
|
+
import { StatusMapper, SyncProvider } from './status-mapper.js';
|
|
12
|
+
import type { SpecWeaveConfig } from '../core/config/types.js';
|
|
13
|
+
/**
|
|
14
|
+
* GitHub repository configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface GitHubRepoConfig {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
owner?: string;
|
|
19
|
+
repo?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Repository information
|
|
23
|
+
*/
|
|
24
|
+
export interface RepoInfo {
|
|
25
|
+
owner: string;
|
|
26
|
+
repo: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Provider router options
|
|
30
|
+
*/
|
|
31
|
+
export interface ProviderRouterOptions {
|
|
32
|
+
projectRoot: string;
|
|
33
|
+
logger?: Logger;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Provider Router - Routes sync operations to the correct external provider
|
|
37
|
+
*/
|
|
38
|
+
export declare class ProviderRouter {
|
|
39
|
+
private projectRoot;
|
|
40
|
+
private logger;
|
|
41
|
+
constructor(options: ProviderRouterOptions);
|
|
42
|
+
/**
|
|
43
|
+
* Detect GitHub repository from config or git remote
|
|
44
|
+
*
|
|
45
|
+
* @param githubConfig - Optional GitHub config from config.json
|
|
46
|
+
* @returns Repository info or null if not detected
|
|
47
|
+
*/
|
|
48
|
+
detectGitHubRepo(githubConfig?: GitHubRepoConfig): Promise<RepoInfo | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Get the external provider for a user story
|
|
51
|
+
*
|
|
52
|
+
* Determines which external provider to use based on the user story's
|
|
53
|
+
* external_source field.
|
|
54
|
+
*
|
|
55
|
+
* @param externalSource - The external source from user story (github, jira, ado, azure-devops)
|
|
56
|
+
* @returns Normalized provider name
|
|
57
|
+
*/
|
|
58
|
+
normalizeProvider(externalSource: string | undefined): SyncProvider | null;
|
|
59
|
+
/**
|
|
60
|
+
* Check which providers are available for sync
|
|
61
|
+
*
|
|
62
|
+
* @param config - Project configuration
|
|
63
|
+
* @returns Object with provider availability
|
|
64
|
+
*/
|
|
65
|
+
getAvailableProviders(config: SpecWeaveConfig): Record<SyncProvider, boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Load project configuration
|
|
68
|
+
*
|
|
69
|
+
* @returns Project configuration or empty object
|
|
70
|
+
*/
|
|
71
|
+
loadConfig(): Promise<SpecWeaveConfig>;
|
|
72
|
+
/**
|
|
73
|
+
* Get status mapper instance for the current config
|
|
74
|
+
*
|
|
75
|
+
* @param config - Project configuration
|
|
76
|
+
* @returns StatusMapper instance
|
|
77
|
+
*/
|
|
78
|
+
getStatusMapper(config: SpecWeaveConfig): StatusMapper;
|
|
79
|
+
/**
|
|
80
|
+
* Log provider availability for debugging
|
|
81
|
+
*
|
|
82
|
+
* @param config - Project configuration
|
|
83
|
+
*/
|
|
84
|
+
logProviderStatus(config: SpecWeaveConfig): void;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=provider-router.d.ts.map
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Router Service
|
|
3
|
+
*
|
|
4
|
+
* Routes sync operations to the correct external provider (GitHub, JIRA, ADO).
|
|
5
|
+
* Extracted from sync-coordinator.ts for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* @module sync/provider-router
|
|
8
|
+
* @since v1.0.115
|
|
9
|
+
*/
|
|
10
|
+
import { promises as fs, existsSync } from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { consoleLogger } from '../utils/logger.js';
|
|
13
|
+
import { StatusMapper, isProviderEnabled } from './status-mapper.js';
|
|
14
|
+
/**
|
|
15
|
+
* Provider Router - Routes sync operations to the correct external provider
|
|
16
|
+
*/
|
|
17
|
+
export class ProviderRouter {
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.projectRoot = options.projectRoot;
|
|
20
|
+
this.logger = options.logger ?? consoleLogger;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Detect GitHub repository from config or git remote
|
|
24
|
+
*
|
|
25
|
+
* @param githubConfig - Optional GitHub config from config.json
|
|
26
|
+
* @returns Repository info or null if not detected
|
|
27
|
+
*/
|
|
28
|
+
async detectGitHubRepo(githubConfig = {}) {
|
|
29
|
+
// Check config first
|
|
30
|
+
if (githubConfig.owner && githubConfig.repo) {
|
|
31
|
+
return { owner: githubConfig.owner, repo: githubConfig.repo };
|
|
32
|
+
}
|
|
33
|
+
// Try to detect from git remote
|
|
34
|
+
try {
|
|
35
|
+
const { execSync } = await import('child_process');
|
|
36
|
+
const remote = execSync('git remote get-url origin', {
|
|
37
|
+
cwd: this.projectRoot,
|
|
38
|
+
encoding: 'utf-8',
|
|
39
|
+
stdio: 'pipe'
|
|
40
|
+
}).trim();
|
|
41
|
+
// Parse GitHub URL: git@github.com:owner/repo.git or https://github.com/owner/repo.git
|
|
42
|
+
const match = remote.match(/github\.com[:/]([^/]+)\/([^.]+)/);
|
|
43
|
+
if (match) {
|
|
44
|
+
return { owner: match[1], repo: match[2].replace('.git', '') };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Ignore git errors
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the external provider for a user story
|
|
54
|
+
*
|
|
55
|
+
* Determines which external provider to use based on the user story's
|
|
56
|
+
* external_source field.
|
|
57
|
+
*
|
|
58
|
+
* @param externalSource - The external source from user story (github, jira, ado, azure-devops)
|
|
59
|
+
* @returns Normalized provider name
|
|
60
|
+
*/
|
|
61
|
+
normalizeProvider(externalSource) {
|
|
62
|
+
if (!externalSource) {
|
|
63
|
+
return 'github'; // Default to GitHub
|
|
64
|
+
}
|
|
65
|
+
const source = externalSource.toLowerCase();
|
|
66
|
+
if (source === 'github') {
|
|
67
|
+
return 'github';
|
|
68
|
+
}
|
|
69
|
+
if (source === 'jira') {
|
|
70
|
+
return 'jira';
|
|
71
|
+
}
|
|
72
|
+
if (source === 'ado' || source === 'azure-devops' || source === 'azuredevops') {
|
|
73
|
+
return 'ado';
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check which providers are available for sync
|
|
79
|
+
*
|
|
80
|
+
* @param config - Project configuration
|
|
81
|
+
* @returns Object with provider availability
|
|
82
|
+
*/
|
|
83
|
+
getAvailableProviders(config) {
|
|
84
|
+
return {
|
|
85
|
+
github: isProviderEnabled(config, 'github'),
|
|
86
|
+
jira: isProviderEnabled(config, 'jira'),
|
|
87
|
+
ado: isProviderEnabled(config, 'ado')
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Load project configuration
|
|
92
|
+
*
|
|
93
|
+
* @returns Project configuration or empty object
|
|
94
|
+
*/
|
|
95
|
+
async loadConfig() {
|
|
96
|
+
const configPath = path.join(this.projectRoot, '.specweave/config.json');
|
|
97
|
+
if (!existsSync(configPath)) {
|
|
98
|
+
return {};
|
|
99
|
+
}
|
|
100
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
101
|
+
return JSON.parse(content);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get status mapper instance for the current config
|
|
105
|
+
*
|
|
106
|
+
* @param config - Project configuration
|
|
107
|
+
* @returns StatusMapper instance
|
|
108
|
+
*/
|
|
109
|
+
getStatusMapper(config) {
|
|
110
|
+
return new StatusMapper(config);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Log provider availability for debugging
|
|
114
|
+
*
|
|
115
|
+
* @param config - Project configuration
|
|
116
|
+
*/
|
|
117
|
+
logProviderStatus(config) {
|
|
118
|
+
const providers = this.getAvailableProviders(config);
|
|
119
|
+
const statusMapper = this.getStatusMapper(config);
|
|
120
|
+
this.logger.log('📊 Provider Status:');
|
|
121
|
+
if (providers.github) {
|
|
122
|
+
this.logger.log(' ✅ GitHub: enabled');
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
this.logger.log(' ⬜ GitHub: disabled');
|
|
126
|
+
}
|
|
127
|
+
if (providers.jira) {
|
|
128
|
+
this.logger.log(` ✅ JIRA: enabled (completion status: ${statusMapper.getJiraCompletedStatus()})`);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
this.logger.log(' ⬜ JIRA: disabled');
|
|
132
|
+
}
|
|
133
|
+
if (providers.ado) {
|
|
134
|
+
this.logger.log(` ✅ ADO: enabled (completion state: ${statusMapper.getAdoCompletedState()})`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this.logger.log(' ⬜ ADO: disabled');
|
|
138
|
+
}
|
|
139
|
+
this.logger.log('');
|
|
140
|
+
this.logger.log('📋 Sync Settings:');
|
|
141
|
+
this.logger.log(` canUpdateExternalItems: ${statusMapper.canUpdateExternal()}`);
|
|
142
|
+
this.logger.log(` canUpdateStatus: ${statusMapper.canUpdateStatus()}`);
|
|
143
|
+
this.logger.log(` autoSyncOnCompletion: ${statusMapper.isAutoSyncEnabled()}`);
|
|
144
|
+
this.logger.log(` canUpsertInternalItems: ${statusMapper.canUpsertInternal()}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=provider-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-router.js","sourceRoot":"","sources":["../../../src/sync/provider-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Mapper Service
|
|
3
|
+
*
|
|
4
|
+
* Handles status mapping between SpecWeave increment statuses and external tool statuses.
|
|
5
|
+
* Extracted from sync-coordinator.ts for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* @module sync/status-mapper
|
|
8
|
+
* @since v1.0.115
|
|
9
|
+
*/
|
|
10
|
+
import type { SpecWeaveConfig, SyncConfiguration } from '../core/config/types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Status sync mapping configuration (runtime config, not in core types)
|
|
13
|
+
*/
|
|
14
|
+
export interface StatusSyncMappings {
|
|
15
|
+
jira?: {
|
|
16
|
+
completed?: string;
|
|
17
|
+
};
|
|
18
|
+
ado?: {
|
|
19
|
+
completed?: string | {
|
|
20
|
+
state: string;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Extended sync configuration with runtime statusSync field
|
|
26
|
+
*/
|
|
27
|
+
export interface SyncConfigurationExtended extends SyncConfiguration {
|
|
28
|
+
statusSync?: {
|
|
29
|
+
mappings?: StatusSyncMappings;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Supported external providers
|
|
34
|
+
*/
|
|
35
|
+
export type SyncProvider = 'github' | 'jira' | 'ado';
|
|
36
|
+
/**
|
|
37
|
+
* Provider configuration result
|
|
38
|
+
*/
|
|
39
|
+
export interface ProviderStatus {
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
source: 'profile' | 'legacy' | 'none';
|
|
42
|
+
profileId?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Check if a provider is enabled in config (supports BOTH formats)
|
|
46
|
+
*
|
|
47
|
+
* v1.0.46 FIX: Supports two config formats:
|
|
48
|
+
* 1. PROFILES format: sync.profiles[name].provider === provider
|
|
49
|
+
* 2. LEGACY format: sync.[provider].enabled === true
|
|
50
|
+
*
|
|
51
|
+
* @param config - Project config object
|
|
52
|
+
* @param provider - Provider to check ('github', 'jira', 'ado')
|
|
53
|
+
* @returns true if provider is enabled in either format
|
|
54
|
+
*/
|
|
55
|
+
export declare function isProviderEnabled(config: SpecWeaveConfig, provider: SyncProvider): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Get detailed provider status including source of configuration
|
|
58
|
+
*
|
|
59
|
+
* @param config - Project config object
|
|
60
|
+
* @param provider - Provider to check
|
|
61
|
+
* @returns Detailed provider status
|
|
62
|
+
*/
|
|
63
|
+
export declare function getProviderStatus(config: SpecWeaveConfig, provider: SyncProvider): ProviderStatus;
|
|
64
|
+
/**
|
|
65
|
+
* Get all enabled providers from config
|
|
66
|
+
*
|
|
67
|
+
* @param config - Project config object
|
|
68
|
+
* @returns Array of enabled providers
|
|
69
|
+
*/
|
|
70
|
+
export declare function getEnabledProviders(config: SpecWeaveConfig): SyncProvider[];
|
|
71
|
+
/**
|
|
72
|
+
* Status Mapper class for handling status transitions
|
|
73
|
+
*/
|
|
74
|
+
export declare class StatusMapper {
|
|
75
|
+
private config;
|
|
76
|
+
constructor(config: SpecWeaveConfig);
|
|
77
|
+
/**
|
|
78
|
+
* Check if a provider is enabled
|
|
79
|
+
*/
|
|
80
|
+
isProviderEnabled(provider: SyncProvider): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Get provider status details
|
|
83
|
+
*/
|
|
84
|
+
getProviderStatus(provider: SyncProvider): ProviderStatus;
|
|
85
|
+
/**
|
|
86
|
+
* Get all enabled providers
|
|
87
|
+
*/
|
|
88
|
+
getEnabledProviders(): SyncProvider[];
|
|
89
|
+
/**
|
|
90
|
+
* Get the target status for a completed increment in JIRA
|
|
91
|
+
*
|
|
92
|
+
* @returns Target JIRA status (default: 'Done')
|
|
93
|
+
*/
|
|
94
|
+
getJiraCompletedStatus(): string;
|
|
95
|
+
/**
|
|
96
|
+
* Get the target state for a completed increment in ADO
|
|
97
|
+
*
|
|
98
|
+
* @returns Target ADO state (default: 'Closed')
|
|
99
|
+
*/
|
|
100
|
+
getAdoCompletedState(): string;
|
|
101
|
+
/**
|
|
102
|
+
* Check if external sync is allowed.
|
|
103
|
+
* Aligns with SyncCoordinator: explicit setting wins, otherwise falls back
|
|
104
|
+
* to resolvePermissions(preset).canUpsert (not a hard-coded false).
|
|
105
|
+
*/
|
|
106
|
+
canUpdateExternal(): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Check if status updates are allowed
|
|
109
|
+
*/
|
|
110
|
+
canUpdateStatus(): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Check if auto sync on completion is enabled
|
|
113
|
+
*/
|
|
114
|
+
isAutoSyncEnabled(): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Check if living docs sync is allowed
|
|
117
|
+
*/
|
|
118
|
+
canUpsertInternal(): boolean;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=status-mapper.d.ts.map
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Mapper Service
|
|
3
|
+
*
|
|
4
|
+
* Handles status mapping between SpecWeave increment statuses and external tool statuses.
|
|
5
|
+
* Extracted from sync-coordinator.ts for better separation of concerns.
|
|
6
|
+
*
|
|
7
|
+
* @module sync/status-mapper
|
|
8
|
+
* @since v1.0.115
|
|
9
|
+
*/
|
|
10
|
+
import { resolvePermissions } from './config.js';
|
|
11
|
+
/**
|
|
12
|
+
* Check if a provider is enabled in config (supports BOTH formats)
|
|
13
|
+
*
|
|
14
|
+
* v1.0.46 FIX: Supports two config formats:
|
|
15
|
+
* 1. PROFILES format: sync.profiles[name].provider === provider
|
|
16
|
+
* 2. LEGACY format: sync.[provider].enabled === true
|
|
17
|
+
*
|
|
18
|
+
* @param config - Project config object
|
|
19
|
+
* @param provider - Provider to check ('github', 'jira', 'ado')
|
|
20
|
+
* @returns true if provider is enabled in either format
|
|
21
|
+
*/
|
|
22
|
+
export function isProviderEnabled(config, provider) {
|
|
23
|
+
const syncConfig = config.sync;
|
|
24
|
+
if (!syncConfig) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
// Check LEGACY format first (sync.github.enabled, sync.jira.enabled, sync.ado.enabled)
|
|
28
|
+
const providerConfig = syncConfig[provider];
|
|
29
|
+
if (providerConfig?.enabled === true) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
// Check PROFILES format (sync.profiles with provider field)
|
|
33
|
+
if (syncConfig.profiles) {
|
|
34
|
+
for (const profile of Object.values(syncConfig.profiles)) {
|
|
35
|
+
if (profile?.provider === provider) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get detailed provider status including source of configuration
|
|
44
|
+
*
|
|
45
|
+
* @param config - Project config object
|
|
46
|
+
* @param provider - Provider to check
|
|
47
|
+
* @returns Detailed provider status
|
|
48
|
+
*/
|
|
49
|
+
export function getProviderStatus(config, provider) {
|
|
50
|
+
const syncConfig = config.sync;
|
|
51
|
+
if (!syncConfig) {
|
|
52
|
+
return { enabled: false, source: 'none' };
|
|
53
|
+
}
|
|
54
|
+
// Check LEGACY format first
|
|
55
|
+
const providerConfig = syncConfig[provider];
|
|
56
|
+
if (providerConfig?.enabled === true) {
|
|
57
|
+
return { enabled: true, source: 'legacy' };
|
|
58
|
+
}
|
|
59
|
+
// Check PROFILES format
|
|
60
|
+
if (syncConfig.profiles) {
|
|
61
|
+
for (const [profileId, profile] of Object.entries(syncConfig.profiles)) {
|
|
62
|
+
if (profile?.provider === provider) {
|
|
63
|
+
return { enabled: true, source: 'profile', profileId };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { enabled: false, source: 'none' };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get all enabled providers from config
|
|
71
|
+
*
|
|
72
|
+
* @param config - Project config object
|
|
73
|
+
* @returns Array of enabled providers
|
|
74
|
+
*/
|
|
75
|
+
export function getEnabledProviders(config) {
|
|
76
|
+
const providers = [];
|
|
77
|
+
if (isProviderEnabled(config, 'github')) {
|
|
78
|
+
providers.push('github');
|
|
79
|
+
}
|
|
80
|
+
if (isProviderEnabled(config, 'jira')) {
|
|
81
|
+
providers.push('jira');
|
|
82
|
+
}
|
|
83
|
+
if (isProviderEnabled(config, 'ado')) {
|
|
84
|
+
providers.push('ado');
|
|
85
|
+
}
|
|
86
|
+
return providers;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Status Mapper class for handling status transitions
|
|
90
|
+
*/
|
|
91
|
+
export class StatusMapper {
|
|
92
|
+
constructor(config) {
|
|
93
|
+
this.config = config;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if a provider is enabled
|
|
97
|
+
*/
|
|
98
|
+
isProviderEnabled(provider) {
|
|
99
|
+
return isProviderEnabled(this.config, provider);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get provider status details
|
|
103
|
+
*/
|
|
104
|
+
getProviderStatus(provider) {
|
|
105
|
+
return getProviderStatus(this.config, provider);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Get all enabled providers
|
|
109
|
+
*/
|
|
110
|
+
getEnabledProviders() {
|
|
111
|
+
return getEnabledProviders(this.config);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Get the target status for a completed increment in JIRA
|
|
115
|
+
*
|
|
116
|
+
* @returns Target JIRA status (default: 'Done')
|
|
117
|
+
*/
|
|
118
|
+
getJiraCompletedStatus() {
|
|
119
|
+
const syncConfigExt = this.config.sync;
|
|
120
|
+
return syncConfigExt?.statusSync?.mappings?.jira?.completed || 'Done';
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the target state for a completed increment in ADO
|
|
124
|
+
*
|
|
125
|
+
* @returns Target ADO state (default: 'Closed')
|
|
126
|
+
*/
|
|
127
|
+
getAdoCompletedState() {
|
|
128
|
+
const syncConfigExt = this.config.sync;
|
|
129
|
+
const targetStateConfig = syncConfigExt?.statusSync?.mappings?.ado?.completed || { state: 'Closed' };
|
|
130
|
+
return typeof targetStateConfig === 'string' ? targetStateConfig : targetStateConfig.state;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Check if external sync is allowed.
|
|
134
|
+
* Aligns with SyncCoordinator: explicit setting wins, otherwise falls back
|
|
135
|
+
* to resolvePermissions(preset).canUpsert (not a hard-coded false).
|
|
136
|
+
*/
|
|
137
|
+
canUpdateExternal() {
|
|
138
|
+
if (this.config.sync?.settings?.canUpdateExternalItems !== undefined) {
|
|
139
|
+
return this.config.sync.settings.canUpdateExternalItems;
|
|
140
|
+
}
|
|
141
|
+
const syncAny = this.config.sync;
|
|
142
|
+
const permissions = resolvePermissions(syncAny?.preset, undefined, this.config.sync?.settings);
|
|
143
|
+
return permissions.canUpsert;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Check if status updates are allowed
|
|
147
|
+
*/
|
|
148
|
+
canUpdateStatus() {
|
|
149
|
+
return this.config.sync?.settings?.canUpdateStatus ?? false;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Check if auto sync on completion is enabled
|
|
153
|
+
*/
|
|
154
|
+
isAutoSyncEnabled() {
|
|
155
|
+
return this.config.sync?.settings?.autoSyncOnCompletion ?? true;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Check if living docs sync is allowed
|
|
159
|
+
*/
|
|
160
|
+
canUpsertInternal() {
|
|
161
|
+
return this.config.sync?.settings?.canUpsertInternalItems ?? true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=status-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-mapper.js","sourceRoot":"","sources":["../../../src/sync/status-mapper.ts"],"names":[],"mappings":"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"}
|