specweave 0.22.13 → 0.23.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.
- package/.claude-plugin/README.md +2 -2
- package/CLAUDE.md +447 -52
- package/README.md +33 -10
- package/dist/plugins/specweave-github/lib/ThreeLayerSyncManager.d.ts +1 -1
- package/dist/plugins/specweave-github/lib/ThreeLayerSyncManager.js +1 -1
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js +1 -1
- package/dist/plugins/specweave-github/lib/enhanced-github-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +4 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-spec-sync.d.ts +1 -1
- package/dist/plugins/specweave-github/lib/github-spec-sync.js +1 -1
- package/dist/plugins/specweave-github/lib/github-sync-bidirectional.d.ts +9 -0
- package/dist/plugins/specweave-github/lib/github-sync-bidirectional.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-sync-bidirectional.js +10 -1
- package/dist/plugins/specweave-github/lib/github-sync-bidirectional.js.map +1 -1
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js +2 -2
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +1 -1
- package/dist/plugins/specweave-github/lib/types.d.ts +1 -1
- package/dist/src/cli/commands/import-external.d.ts +22 -0
- package/dist/src/cli/commands/import-external.d.ts.map +1 -0
- package/dist/src/cli/commands/import-external.js +282 -0
- package/dist/src/cli/commands/import-external.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +359 -1
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/helpers/github-repo-selector.d.ts +59 -0
- package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -0
- package/dist/src/cli/helpers/github-repo-selector.js +265 -0
- package/dist/src/cli/helpers/github-repo-selector.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +41 -24
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/config/import-config.d.ts +69 -0
- package/dist/src/config/import-config.d.ts.map +1 -0
- package/dist/src/config/import-config.js +136 -0
- package/dist/src/config/import-config.js.map +1 -0
- package/dist/src/config/types.d.ts +26 -26
- package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
- package/dist/src/core/increment/ac-status-manager.js +4 -2
- package/dist/src/core/increment/ac-status-manager.js.map +1 -1
- package/dist/src/core/increment/completion-validator.d.ts +30 -1
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +151 -3
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +25 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +130 -3
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.d.ts +37 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.js +262 -18
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.d.ts +17 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +25 -0
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.d.ts +16 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +56 -1
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts +2 -2
- package/dist/src/core/living-docs/task-project-specific-generator.js +2 -2
- package/dist/src/core/repo-structure/prompt-consolidator.d.ts +2 -2
- package/dist/src/core/repo-structure/prompt-consolidator.d.ts.map +1 -1
- package/dist/src/core/repo-structure/prompt-consolidator.js +3 -15
- package/dist/src/core/repo-structure/prompt-consolidator.js.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.d.ts.map +1 -1
- package/dist/src/core/repo-structure/repo-structure-manager.js +3 -6
- package/dist/src/core/repo-structure/repo-structure-manager.js.map +1 -1
- package/dist/src/core/spec-content-sync.d.ts +4 -1
- package/dist/src/core/spec-content-sync.d.ts.map +1 -1
- package/dist/src/core/spec-content-sync.js +139 -4
- package/dist/src/core/spec-content-sync.js.map +1 -1
- package/dist/src/core/spec-task-mapper.d.ts.map +1 -1
- package/dist/src/core/spec-task-mapper.js +9 -8
- package/dist/src/core/spec-task-mapper.js.map +1 -1
- package/dist/src/core/status-line-validator.d.ts +63 -0
- package/dist/src/core/status-line-validator.d.ts.map +1 -0
- package/dist/src/core/status-line-validator.js +253 -0
- package/dist/src/core/status-line-validator.js.map +1 -0
- package/dist/src/core/sync/bidirectional-engine.d.ts +10 -1
- package/dist/src/core/sync/bidirectional-engine.d.ts.map +1 -1
- package/dist/src/core/sync/bidirectional-engine.js +10 -1
- package/dist/src/core/sync/bidirectional-engine.js.map +1 -1
- package/dist/src/core/sync/profile-manager.d.ts.map +1 -1
- package/dist/src/core/sync/profile-manager.js +3 -0
- package/dist/src/core/sync/profile-manager.js.map +1 -1
- package/dist/src/core/sync/project-context.d.ts.map +1 -1
- package/dist/src/core/sync/project-context.js +3 -0
- package/dist/src/core/sync/project-context.js.map +1 -1
- package/dist/src/core/sync/status-sync-engine.d.ts +1 -1
- package/dist/src/core/sync/status-sync-engine.js +1 -1
- package/dist/src/core/sync/sync-event-logger.d.ts +15 -1
- package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -1
- package/dist/src/core/sync/sync-event-logger.js +39 -1
- package/dist/src/core/sync/sync-event-logger.js.map +1 -1
- package/dist/src/core/types/origin-metadata.d.ts +153 -0
- package/dist/src/core/types/origin-metadata.d.ts.map +1 -0
- package/dist/src/core/types/origin-metadata.js +166 -0
- package/dist/src/core/types/origin-metadata.js.map +1 -0
- package/dist/src/core/types/sync-config-validator.d.ts +57 -0
- package/dist/src/core/types/sync-config-validator.d.ts.map +1 -0
- package/dist/src/core/types/sync-config-validator.js +116 -0
- package/dist/src/core/types/sync-config-validator.js.map +1 -0
- package/dist/src/core/types/sync-profile.d.ts +8 -2
- package/dist/src/core/types/sync-profile.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.js.map +1 -1
- package/dist/src/core/types/sync-settings.d.ts +73 -0
- package/dist/src/core/types/sync-settings.d.ts.map +1 -0
- package/dist/src/core/types/sync-settings.js +90 -0
- package/dist/src/core/types/sync-settings.js.map +1 -0
- package/dist/src/core/utils/permission-checker.d.ts +100 -0
- package/dist/src/core/utils/permission-checker.d.ts.map +1 -0
- package/dist/src/core/utils/permission-checker.js +166 -0
- package/dist/src/core/utils/permission-checker.js.map +1 -0
- package/dist/src/generators/spec/spec-parser.js +3 -3
- package/dist/src/generators/spec/spec-parser.js.map +1 -1
- package/dist/src/generators/spec/task-parser.js +4 -4
- package/dist/src/generators/spec/task-parser.js.map +1 -1
- package/dist/src/id-generators/task-id-generator.d.ts +96 -0
- package/dist/src/id-generators/task-id-generator.d.ts.map +1 -0
- package/dist/src/id-generators/task-id-generator.js +143 -0
- package/dist/src/id-generators/task-id-generator.js.map +1 -0
- package/dist/src/id-generators/us-id-generator.d.ts +96 -0
- package/dist/src/id-generators/us-id-generator.d.ts.map +1 -0
- package/dist/src/id-generators/us-id-generator.js +143 -0
- package/dist/src/id-generators/us-id-generator.js.map +1 -0
- package/dist/src/importers/ado-importer.d.ts +43 -0
- package/dist/src/importers/ado-importer.d.ts.map +1 -0
- package/dist/src/importers/ado-importer.js +234 -0
- package/dist/src/importers/ado-importer.js.map +1 -0
- package/dist/src/importers/duplicate-detector.d.ts +107 -0
- package/dist/src/importers/duplicate-detector.d.ts.map +1 -0
- package/dist/src/importers/duplicate-detector.js +189 -0
- package/dist/src/importers/duplicate-detector.js.map +1 -0
- package/dist/src/importers/external-importer.d.ts +96 -0
- package/dist/src/importers/external-importer.d.ts.map +1 -0
- package/dist/src/importers/external-importer.js +13 -0
- package/dist/src/importers/external-importer.js.map +1 -0
- package/dist/src/importers/github-importer.d.ts +37 -0
- package/dist/src/importers/github-importer.d.ts.map +1 -0
- package/dist/src/importers/github-importer.js +161 -0
- package/dist/src/importers/github-importer.js.map +1 -0
- package/dist/src/importers/import-coordinator.d.ts +105 -0
- package/dist/src/importers/import-coordinator.d.ts.map +1 -0
- package/dist/src/importers/import-coordinator.js +224 -0
- package/dist/src/importers/import-coordinator.js.map +1 -0
- package/dist/src/importers/item-converter.d.ts +96 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -0
- package/dist/src/importers/item-converter.js +246 -0
- package/dist/src/importers/item-converter.js.map +1 -0
- package/dist/src/importers/jira-importer.d.ts +42 -0
- package/dist/src/importers/jira-importer.d.ts.map +1 -0
- package/dist/src/importers/jira-importer.js +221 -0
- package/dist/src/importers/jira-importer.js.map +1 -0
- package/dist/src/importers/rate-limiter.d.ts +128 -0
- package/dist/src/importers/rate-limiter.d.ts.map +1 -0
- package/dist/src/importers/rate-limiter.js +200 -0
- package/dist/src/importers/rate-limiter.js.map +1 -0
- package/dist/src/init/compliance/types.d.ts +2 -2
- package/dist/src/init/repo/types.d.ts +2 -2
- package/dist/src/integrations/ado/ado-client.d.ts +6 -0
- package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
- package/dist/src/integrations/ado/ado-client.js +23 -0
- package/dist/src/integrations/ado/ado-client.js.map +1 -1
- package/dist/src/integrations/jira/jira-client.d.ts +6 -0
- package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-client.js +38 -0
- package/dist/src/integrations/jira/jira-client.js.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.d.ts +1 -1
- package/dist/src/integrations/jira/jira-mapper.js +1 -1
- package/dist/src/living-docs/fs-id-allocator.d.ts +149 -0
- package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -0
- package/dist/src/living-docs/fs-id-allocator.js +325 -0
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -0
- package/dist/src/living-docs/id-registry.d.ts +124 -0
- package/dist/src/living-docs/id-registry.d.ts.map +1 -0
- package/dist/src/living-docs/id-registry.js +230 -0
- package/dist/src/living-docs/id-registry.js.map +1 -0
- package/dist/src/progress/us-progress-tracker.d.ts +68 -0
- package/dist/src/progress/us-progress-tracker.d.ts.map +1 -0
- package/dist/src/progress/us-progress-tracker.js +120 -0
- package/dist/src/progress/us-progress-tracker.js.map +1 -0
- package/dist/src/sync/external-item-sync-service.d.ts +150 -0
- package/dist/src/sync/external-item-sync-service.d.ts.map +1 -0
- package/dist/src/sync/external-item-sync-service.js +241 -0
- package/dist/src/sync/external-item-sync-service.js.map +1 -0
- package/dist/src/sync/format-preservation-sync.d.ts +90 -0
- package/dist/src/sync/format-preservation-sync.d.ts.map +1 -0
- package/dist/src/sync/format-preservation-sync.js +173 -0
- package/dist/src/sync/format-preservation-sync.js.map +1 -0
- package/dist/src/sync/index.d.ts +8 -0
- package/dist/src/sync/index.d.ts.map +1 -0
- package/dist/src/sync/index.js +6 -0
- package/dist/src/sync/index.js.map +1 -0
- package/dist/src/sync/sync-coordinator.d.ts +49 -0
- package/dist/src/sync/sync-coordinator.d.ts.map +1 -0
- package/dist/src/sync/sync-coordinator.js +248 -0
- package/dist/src/sync/sync-coordinator.js.map +1 -0
- package/dist/src/sync/sync-metadata.d.ts +75 -0
- package/dist/src/sync/sync-metadata.d.ts.map +1 -0
- package/dist/src/sync/sync-metadata.js +100 -0
- package/dist/src/sync/sync-metadata.js.map +1 -0
- package/dist/src/types/living-docs-us-file.d.ts +63 -0
- package/dist/src/types/living-docs-us-file.d.ts.map +1 -0
- package/dist/src/types/living-docs-us-file.js +27 -0
- package/dist/src/types/living-docs-us-file.js.map +1 -0
- package/dist/src/validators/format-preservation-validator.d.ts +127 -0
- package/dist/src/validators/format-preservation-validator.d.ts.map +1 -0
- package/dist/src/validators/format-preservation-validator.js +187 -0
- package/dist/src/validators/format-preservation-validator.js.map +1 -0
- package/package.json +3 -2
- package/plugins/specweave/.claude-plugin/plugin.json +36 -2
- package/plugins/specweave/agents/architect/AGENT.md +11 -2
- package/plugins/specweave/agents/test-aware-planner/AGENT.md +81 -25
- package/plugins/specweave/commands/specweave-archive-features.md +11 -1
- package/plugins/specweave/commands/specweave-import-external.md +407 -0
- package/plugins/specweave/commands/specweave-progress.md +45 -97
- package/plugins/specweave/hooks/post-edit-spec.sh +41 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +168 -26
- package/plugins/specweave/hooks/post-increment-planning.sh +148 -4
- package/plugins/specweave/hooks/post-spec-update.sh +0 -0
- package/plugins/specweave/hooks/post-task-completion.sh +75 -5
- package/plugins/specweave/hooks/post-write-spec.sh +37 -0
- package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
- package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
- package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
- package/plugins/specweave/lib/hooks/sync-cache.js +294 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.js +67 -2
- package/plugins/specweave/lib/hooks/sync-us-tasks.js +200 -14
- package/plugins/specweave/lib/hooks/translate-file.js +1 -1
- package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
- package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +345 -0
- package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +106 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +220 -0
- package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +60 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +192 -0
- package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +276 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +163 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +541 -0
- package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +157 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.js +191 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +301 -0
- package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/logger.d.ts +48 -0
- package/plugins/specweave/lib/vendor/utils/logger.js +53 -0
- package/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
- package/plugins/specweave/lib/vendor/utils/translation.js +414 -0
- package/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
- package/plugins/specweave-ado/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
- package/plugins/specweave-ado/lib/conflict-resolver.ts +1 -1
- package/plugins/specweave-alternatives/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-backend/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-confluent/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-cost-optimizer/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-docs/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-docs-preview/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-figma/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-frontend/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-github/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
- package/plugins/specweave-github/hooks/post-task-completion.sh +37 -22
- package/plugins/specweave-github/lib/ThreeLayerSyncManager.ts +1 -1
- package/plugins/specweave-github/lib/enhanced-github-sync.js +1 -1
- package/plugins/specweave-github/lib/enhanced-github-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-spec-content-sync.js +2 -1
- package/plugins/specweave-github/lib/github-spec-content-sync.ts +4 -1
- package/plugins/specweave-github/lib/github-spec-sync.js +1 -1
- package/plugins/specweave-github/lib/github-spec-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-sync-bidirectional.js +1 -1
- package/plugins/specweave-github/lib/github-sync-bidirectional.ts +10 -1
- package/plugins/specweave-github/lib/progress-comment-builder.js +1 -1
- package/plugins/specweave-github/lib/progress-comment-builder.ts +2 -2
- package/plugins/specweave-github/lib/types.ts +1 -1
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +1 -1
- package/plugins/specweave-infrastructure/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-kafka/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-kubernetes/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-ml/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-mobile/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-n8n/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-payments/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-release/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-testing/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-tooling/.claude-plugin/plugin.json +1 -1
- package/plugins/specweave-ui/.claude-plugin/plugin.json +1 -1
- package/src/templates/.env.example +5 -0
- package/src/templates/config-permissions-guide.md +413 -0
- package/src/templates/config.json.template +68 -0
- package/src/templates/tasks.md.template +180 -201
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -5442
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Story ID Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates unique User Story IDs with support for both internal and external origins.
|
|
5
|
+
* - Internal IDs: US-001, US-002, US-003 (no suffix)
|
|
6
|
+
* - External IDs: US-001E, US-002E, US-003E (E suffix)
|
|
7
|
+
*
|
|
8
|
+
* ID generation strategy:
|
|
9
|
+
* 1. Extract numeric part from all existing IDs (ignoring suffix)
|
|
10
|
+
* 2. Find maximum number across both internal and external IDs
|
|
11
|
+
* 3. Increment to get next sequential number
|
|
12
|
+
* 4. Add E suffix for external origin, no suffix for internal
|
|
13
|
+
*/
|
|
14
|
+
export type Origin = 'internal' | 'external';
|
|
15
|
+
export interface ParsedUsId {
|
|
16
|
+
/** Full ID string (e.g., "US-003E") */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Numeric part (e.g., 3) */
|
|
19
|
+
number: number;
|
|
20
|
+
/** Origin type */
|
|
21
|
+
origin: Origin;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse User Story ID to extract components
|
|
25
|
+
*
|
|
26
|
+
* @param id - User Story ID (e.g., "US-001", "US-002E")
|
|
27
|
+
* @returns Parsed ID components
|
|
28
|
+
* @throws Error if ID format is invalid
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseUsId(id: string): ParsedUsId;
|
|
31
|
+
/**
|
|
32
|
+
* Get next sequential User Story ID
|
|
33
|
+
*
|
|
34
|
+
* Finds maximum numeric ID across all existing IDs (internal + external)
|
|
35
|
+
* and generates next sequential ID with appropriate suffix.
|
|
36
|
+
*
|
|
37
|
+
* @param existingIds - Array of existing User Story IDs
|
|
38
|
+
* @param origin - Origin type for new ID
|
|
39
|
+
* @returns Next sequential User Story ID
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* getNextUsId(['US-001', 'US-002E', 'US-003'], 'internal')
|
|
43
|
+
* // Returns: 'US-004'
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* getNextUsId(['US-001', 'US-002E', 'US-003'], 'external')
|
|
47
|
+
* // Returns: 'US-004E'
|
|
48
|
+
*/
|
|
49
|
+
export declare function getNextUsId(existingIds: string[], origin: Origin): string;
|
|
50
|
+
/**
|
|
51
|
+
* Validate ID uniqueness
|
|
52
|
+
*
|
|
53
|
+
* @param id - User Story ID to check
|
|
54
|
+
* @param existingIds - Array of existing User Story IDs
|
|
55
|
+
* @throws Error if ID already exists
|
|
56
|
+
*/
|
|
57
|
+
export declare function validateUsIdUniqueness(id: string, existingIds: string[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Detect origin from User Story ID
|
|
60
|
+
*
|
|
61
|
+
* @param id - User Story ID
|
|
62
|
+
* @returns Origin type ('internal' or 'external')
|
|
63
|
+
*/
|
|
64
|
+
export declare function getUsIdOrigin(id: string): Origin;
|
|
65
|
+
/**
|
|
66
|
+
* Extract numeric part from User Story ID
|
|
67
|
+
*
|
|
68
|
+
* @param id - User Story ID
|
|
69
|
+
* @returns Numeric part
|
|
70
|
+
*/
|
|
71
|
+
export declare function getUsIdNumber(id: string): number;
|
|
72
|
+
/**
|
|
73
|
+
* Check if ID is external (has E suffix)
|
|
74
|
+
*
|
|
75
|
+
* @param id - User Story ID
|
|
76
|
+
* @returns true if external, false if internal
|
|
77
|
+
*/
|
|
78
|
+
export declare function isExternalUsId(id: string): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Generate range of User Story IDs
|
|
81
|
+
*
|
|
82
|
+
* @param start - Starting number
|
|
83
|
+
* @param count - Number of IDs to generate
|
|
84
|
+
* @param origin - Origin type
|
|
85
|
+
* @returns Array of User Story IDs
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* generateUsIdRange(1, 3, 'internal')
|
|
89
|
+
* // Returns: ['US-001', 'US-002', 'US-003']
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* generateUsIdRange(5, 2, 'external')
|
|
93
|
+
* // Returns: ['US-005E', 'US-006E']
|
|
94
|
+
*/
|
|
95
|
+
export declare function generateUsIdRange(start: number, count: number, origin: Origin): string[];
|
|
96
|
+
//# sourceMappingURL=us-id-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"us-id-generator.d.ts","sourceRoot":"","sources":["../../../src/id-generators/us-id-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;AAE7C,MAAM,WAAW,UAAU;IACzB,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IAEX,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;IAEf,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,CAgBhD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA0BzE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI,CAI9E;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAWxF"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Story ID Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates unique User Story IDs with support for both internal and external origins.
|
|
5
|
+
* - Internal IDs: US-001, US-002, US-003 (no suffix)
|
|
6
|
+
* - External IDs: US-001E, US-002E, US-003E (E suffix)
|
|
7
|
+
*
|
|
8
|
+
* ID generation strategy:
|
|
9
|
+
* 1. Extract numeric part from all existing IDs (ignoring suffix)
|
|
10
|
+
* 2. Find maximum number across both internal and external IDs
|
|
11
|
+
* 3. Increment to get next sequential number
|
|
12
|
+
* 4. Add E suffix for external origin, no suffix for internal
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Parse User Story ID to extract components
|
|
16
|
+
*
|
|
17
|
+
* @param id - User Story ID (e.g., "US-001", "US-002E")
|
|
18
|
+
* @returns Parsed ID components
|
|
19
|
+
* @throws Error if ID format is invalid
|
|
20
|
+
*/
|
|
21
|
+
export function parseUsId(id) {
|
|
22
|
+
// Match: US-001 or US-001E
|
|
23
|
+
const match = id.match(/^US-(\d+)(E)?$/);
|
|
24
|
+
if (!match) {
|
|
25
|
+
throw new Error(`Invalid User Story ID format: ${id}. Expected format: US-XXX or US-XXXE`);
|
|
26
|
+
}
|
|
27
|
+
const number = parseInt(match[1], 10);
|
|
28
|
+
const origin = match[2] === 'E' ? 'external' : 'internal';
|
|
29
|
+
return {
|
|
30
|
+
id,
|
|
31
|
+
number,
|
|
32
|
+
origin
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get next sequential User Story ID
|
|
37
|
+
*
|
|
38
|
+
* Finds maximum numeric ID across all existing IDs (internal + external)
|
|
39
|
+
* and generates next sequential ID with appropriate suffix.
|
|
40
|
+
*
|
|
41
|
+
* @param existingIds - Array of existing User Story IDs
|
|
42
|
+
* @param origin - Origin type for new ID
|
|
43
|
+
* @returns Next sequential User Story ID
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* getNextUsId(['US-001', 'US-002E', 'US-003'], 'internal')
|
|
47
|
+
* // Returns: 'US-004'
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* getNextUsId(['US-001', 'US-002E', 'US-003'], 'external')
|
|
51
|
+
* // Returns: 'US-004E'
|
|
52
|
+
*/
|
|
53
|
+
export function getNextUsId(existingIds, origin) {
|
|
54
|
+
if (existingIds.length === 0) {
|
|
55
|
+
return origin === 'external' ? 'US-001E' : 'US-001';
|
|
56
|
+
}
|
|
57
|
+
// Extract numeric parts from all IDs
|
|
58
|
+
const numbers = [];
|
|
59
|
+
for (const id of existingIds) {
|
|
60
|
+
try {
|
|
61
|
+
const parsed = parseUsId(id);
|
|
62
|
+
numbers.push(parsed.number);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// Skip invalid IDs (they'll be caught by validation elsewhere)
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Find maximum number
|
|
70
|
+
const maxNumber = numbers.length > 0 ? Math.max(...numbers) : 0;
|
|
71
|
+
// Generate next ID
|
|
72
|
+
const nextNumber = maxNumber + 1;
|
|
73
|
+
const formattedNumber = String(nextNumber).padStart(3, '0');
|
|
74
|
+
return origin === 'external' ? `US-${formattedNumber}E` : `US-${formattedNumber}`;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Validate ID uniqueness
|
|
78
|
+
*
|
|
79
|
+
* @param id - User Story ID to check
|
|
80
|
+
* @param existingIds - Array of existing User Story IDs
|
|
81
|
+
* @throws Error if ID already exists
|
|
82
|
+
*/
|
|
83
|
+
export function validateUsIdUniqueness(id, existingIds) {
|
|
84
|
+
if (existingIds.includes(id)) {
|
|
85
|
+
throw new Error(`ID collision detected: ${id} already exists`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Detect origin from User Story ID
|
|
90
|
+
*
|
|
91
|
+
* @param id - User Story ID
|
|
92
|
+
* @returns Origin type ('internal' or 'external')
|
|
93
|
+
*/
|
|
94
|
+
export function getUsIdOrigin(id) {
|
|
95
|
+
const parsed = parseUsId(id);
|
|
96
|
+
return parsed.origin;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Extract numeric part from User Story ID
|
|
100
|
+
*
|
|
101
|
+
* @param id - User Story ID
|
|
102
|
+
* @returns Numeric part
|
|
103
|
+
*/
|
|
104
|
+
export function getUsIdNumber(id) {
|
|
105
|
+
const parsed = parseUsId(id);
|
|
106
|
+
return parsed.number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if ID is external (has E suffix)
|
|
110
|
+
*
|
|
111
|
+
* @param id - User Story ID
|
|
112
|
+
* @returns true if external, false if internal
|
|
113
|
+
*/
|
|
114
|
+
export function isExternalUsId(id) {
|
|
115
|
+
return getUsIdOrigin(id) === 'external';
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generate range of User Story IDs
|
|
119
|
+
*
|
|
120
|
+
* @param start - Starting number
|
|
121
|
+
* @param count - Number of IDs to generate
|
|
122
|
+
* @param origin - Origin type
|
|
123
|
+
* @returns Array of User Story IDs
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* generateUsIdRange(1, 3, 'internal')
|
|
127
|
+
* // Returns: ['US-001', 'US-002', 'US-003']
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* generateUsIdRange(5, 2, 'external')
|
|
131
|
+
* // Returns: ['US-005E', 'US-006E']
|
|
132
|
+
*/
|
|
133
|
+
export function generateUsIdRange(start, count, origin) {
|
|
134
|
+
const ids = [];
|
|
135
|
+
for (let i = 0; i < count; i++) {
|
|
136
|
+
const number = start + i;
|
|
137
|
+
const formattedNumber = String(number).padStart(3, '0');
|
|
138
|
+
const id = origin === 'external' ? `US-${formattedNumber}E` : `US-${formattedNumber}`;
|
|
139
|
+
ids.push(id);
|
|
140
|
+
}
|
|
141
|
+
return ids;
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=us-id-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"us-id-generator.js","sourceRoot":"","sources":["../../../src/id-generators/us-id-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure DevOps Importer
|
|
3
|
+
*
|
|
4
|
+
* Imports Azure DevOps work items as External Items with WIQL support and pagination.
|
|
5
|
+
* Handles PAT authentication and converts ADO-specific data to platform-agnostic format.
|
|
6
|
+
*/
|
|
7
|
+
import type { Importer, ExternalItem, ImportConfig } from './external-importer.js';
|
|
8
|
+
/**
|
|
9
|
+
* Azure DevOps Importer Implementation
|
|
10
|
+
*/
|
|
11
|
+
export declare class ADOImporter implements Importer {
|
|
12
|
+
readonly platform: "ado";
|
|
13
|
+
private orgUrl;
|
|
14
|
+
private project;
|
|
15
|
+
private pat;
|
|
16
|
+
constructor(orgUrl: string, project: string, pat?: string);
|
|
17
|
+
/**
|
|
18
|
+
* Import all work items matching config
|
|
19
|
+
*/
|
|
20
|
+
import(config?: ImportConfig): Promise<ExternalItem[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Paginate through work items using WIQL (200 per page)
|
|
23
|
+
*/
|
|
24
|
+
paginate(config?: ImportConfig): AsyncGenerator<ExternalItem[], void, unknown>;
|
|
25
|
+
/**
|
|
26
|
+
* Fetch work items in batch (up to 200 IDs)
|
|
27
|
+
*/
|
|
28
|
+
private getWorkItemsBatch;
|
|
29
|
+
/**
|
|
30
|
+
* Make authenticated ADO API request
|
|
31
|
+
*/
|
|
32
|
+
private makeADORequest;
|
|
33
|
+
/**
|
|
34
|
+
* Convert ADO work item to ExternalItem
|
|
35
|
+
*/
|
|
36
|
+
private convertToExternalItem;
|
|
37
|
+
/**
|
|
38
|
+
* Parse acceptance criteria from ADO HTML format
|
|
39
|
+
* ADO stores ACs as HTML, needs to extract plain text
|
|
40
|
+
*/
|
|
41
|
+
private parseAcceptanceCriteria;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ado-importer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ado-importer.d.ts","sourceRoot":"","sources":["../../../src/importers/ado-importer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAmCnF;;GAEG;AACH,qBAAa,WAAY,YAAW,QAAQ;IAC1C,QAAQ,CAAC,QAAQ,EAAG,KAAK,CAAU;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,GAAG,CAAS;gBAER,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAYzD;;OAEG;IACG,MAAM,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAUhE;;OAEG;IACI,QAAQ,CAAC,MAAM,GAAE,YAAiB,GAAG,cAAc,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC;IAoFzF;;OAEG;YACW,iBAAiB;IA2B/B;;OAEG;YACW,cAAc;IA8B5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiE7B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;CAkBhC"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure DevOps Importer
|
|
3
|
+
*
|
|
4
|
+
* Imports Azure DevOps work items as External Items with WIQL support and pagination.
|
|
5
|
+
* Handles PAT authentication and converts ADO-specific data to platform-agnostic format.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Azure DevOps Importer Implementation
|
|
9
|
+
*/
|
|
10
|
+
export class ADOImporter {
|
|
11
|
+
constructor(orgUrl, project, pat) {
|
|
12
|
+
this.platform = 'ado';
|
|
13
|
+
this.orgUrl = orgUrl.replace(/\/+$/, ''); // Remove trailing slashes
|
|
14
|
+
this.project = project;
|
|
15
|
+
this.pat = pat || process.env.ADO_PAT || process.env.AZURE_DEVOPS_PAT || '';
|
|
16
|
+
if (!this.pat) {
|
|
17
|
+
throw new Error('Azure DevOps authentication required: Set ADO_PAT or AZURE_DEVOPS_PAT environment variable');
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Import all work items matching config
|
|
22
|
+
*/
|
|
23
|
+
async import(config = {}) {
|
|
24
|
+
const items = [];
|
|
25
|
+
for await (const page of this.paginate(config)) {
|
|
26
|
+
items.push(...page);
|
|
27
|
+
}
|
|
28
|
+
return items;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Paginate through work items using WIQL (200 per page)
|
|
32
|
+
*/
|
|
33
|
+
async *paginate(config = {}) {
|
|
34
|
+
const { timeRangeMonths = 3, includeClosed = false, labels = [], maxItems = Infinity, } = config;
|
|
35
|
+
// Build WIQL query
|
|
36
|
+
const since = new Date();
|
|
37
|
+
since.setMonth(since.getMonth() - timeRangeMonths);
|
|
38
|
+
const sinceStr = since.toISOString().split('T')[0];
|
|
39
|
+
const wiqlParts = [
|
|
40
|
+
`SELECT [System.Id], [System.Title], [System.WorkItemType], [System.State]`,
|
|
41
|
+
`FROM WorkItems`,
|
|
42
|
+
`WHERE [System.TeamProject] = '${this.project}'`,
|
|
43
|
+
`AND [System.CreatedDate] >= '${sinceStr}'`,
|
|
44
|
+
];
|
|
45
|
+
// Status filter
|
|
46
|
+
if (!includeClosed) {
|
|
47
|
+
wiqlParts.push(`AND [System.State] <> 'Closed' AND [System.State] <> 'Removed'`);
|
|
48
|
+
}
|
|
49
|
+
// Tags filter (ADO uses semicolon-separated tags)
|
|
50
|
+
if (labels.length > 0) {
|
|
51
|
+
const tagsCondition = labels.map((tag) => `[System.Tags] CONTAINS '${tag}'`).join(' OR ');
|
|
52
|
+
wiqlParts.push(`AND (${tagsCondition})`);
|
|
53
|
+
}
|
|
54
|
+
wiqlParts.push(`ORDER BY [System.CreatedDate] DESC`);
|
|
55
|
+
const wiql = wiqlParts.join(' ');
|
|
56
|
+
try {
|
|
57
|
+
// Step 1: Execute WIQL query ONCE to get all work item IDs
|
|
58
|
+
const queryResult = await this.makeADORequest(`/_apis/wit/wiql?api-version=7.0`, {
|
|
59
|
+
method: 'POST',
|
|
60
|
+
body: JSON.stringify({ query: wiql }),
|
|
61
|
+
});
|
|
62
|
+
const allWorkItemIds = queryResult.workItems.map((wi) => wi.id);
|
|
63
|
+
// Step 2: Paginate through work item IDs
|
|
64
|
+
let skip = 0;
|
|
65
|
+
const top = 200; // ADO pagination size (max 200)
|
|
66
|
+
let totalFetched = 0;
|
|
67
|
+
while (skip < allWorkItemIds.length && totalFetched < maxItems) {
|
|
68
|
+
// Get IDs for this page
|
|
69
|
+
const ids = allWorkItemIds.slice(skip, skip + top);
|
|
70
|
+
if (ids.length === 0) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
// Fetch full work item details
|
|
74
|
+
const workItems = await this.getWorkItemsBatch(ids);
|
|
75
|
+
// Convert to ExternalItems
|
|
76
|
+
const items = workItems.map((wi) => this.convertToExternalItem(wi));
|
|
77
|
+
// Yield page
|
|
78
|
+
if (items.length > 0) {
|
|
79
|
+
yield items.slice(0, maxItems - totalFetched);
|
|
80
|
+
totalFetched += items.length;
|
|
81
|
+
}
|
|
82
|
+
skip += top;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (error.status === 401) {
|
|
87
|
+
throw new Error(`Azure DevOps authentication failed: ${error.message}`);
|
|
88
|
+
}
|
|
89
|
+
else if (error.status === 403) {
|
|
90
|
+
throw new Error(`Azure DevOps access forbidden: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Fetch work items in batch (up to 200 IDs)
|
|
97
|
+
*/
|
|
98
|
+
async getWorkItemsBatch(ids) {
|
|
99
|
+
if (ids.length === 0) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
const idsParam = ids.join(',');
|
|
103
|
+
const fields = [
|
|
104
|
+
'System.Id',
|
|
105
|
+
'System.Title',
|
|
106
|
+
'System.Description',
|
|
107
|
+
'System.WorkItemType',
|
|
108
|
+
'System.State',
|
|
109
|
+
'System.CreatedDate',
|
|
110
|
+
'System.ChangedDate',
|
|
111
|
+
'System.Tags',
|
|
112
|
+
'Microsoft.VSTS.Common.Priority',
|
|
113
|
+
'Microsoft.VSTS.Common.AcceptanceCriteria',
|
|
114
|
+
'System.Parent',
|
|
115
|
+
].join(',');
|
|
116
|
+
const response = await this.makeADORequest(`/_apis/wit/workitems?ids=${idsParam}&fields=${fields}&$expand=Links&api-version=7.0`);
|
|
117
|
+
return response.value;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Make authenticated ADO API request
|
|
121
|
+
*/
|
|
122
|
+
async makeADORequest(endpoint, options = {}) {
|
|
123
|
+
const url = `${this.orgUrl}/${this.project}${endpoint}`;
|
|
124
|
+
// Create Basic Auth header (PAT as username, empty password)
|
|
125
|
+
const auth = Buffer.from(`:${this.pat}`).toString('base64');
|
|
126
|
+
const response = await fetch(url, {
|
|
127
|
+
method: options.method || 'GET',
|
|
128
|
+
headers: {
|
|
129
|
+
'Authorization': `Basic ${auth}`,
|
|
130
|
+
'Accept': 'application/json',
|
|
131
|
+
'Content-Type': 'application/json',
|
|
132
|
+
...options.headers,
|
|
133
|
+
},
|
|
134
|
+
body: options.body,
|
|
135
|
+
});
|
|
136
|
+
if (!response.ok) {
|
|
137
|
+
const errorText = await response.text();
|
|
138
|
+
const error = new Error(`ADO API error: ${response.statusText} - ${errorText}`);
|
|
139
|
+
error.status = response.status;
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
return response.json();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Convert ADO work item to ExternalItem
|
|
146
|
+
*/
|
|
147
|
+
convertToExternalItem(workItem) {
|
|
148
|
+
// Map ADO work item type to ExternalItem type
|
|
149
|
+
let type = 'task';
|
|
150
|
+
const witType = workItem.fields['System.WorkItemType'].toLowerCase();
|
|
151
|
+
if (witType === 'user story' || witType === 'product backlog item') {
|
|
152
|
+
type = 'user-story';
|
|
153
|
+
}
|
|
154
|
+
else if (witType === 'epic') {
|
|
155
|
+
type = 'epic';
|
|
156
|
+
}
|
|
157
|
+
else if (witType === 'bug') {
|
|
158
|
+
type = 'bug';
|
|
159
|
+
}
|
|
160
|
+
else if (witType === 'feature') {
|
|
161
|
+
type = 'feature';
|
|
162
|
+
}
|
|
163
|
+
// Map ADO priority to ExternalItem priority
|
|
164
|
+
const priorityValue = workItem.fields['Microsoft.VSTS.Common.Priority'];
|
|
165
|
+
let priority;
|
|
166
|
+
if (priorityValue !== undefined) {
|
|
167
|
+
if (priorityValue === 1)
|
|
168
|
+
priority = 'P0';
|
|
169
|
+
else if (priorityValue === 2)
|
|
170
|
+
priority = 'P1';
|
|
171
|
+
else if (priorityValue === 3)
|
|
172
|
+
priority = 'P2';
|
|
173
|
+
else if (priorityValue === 4)
|
|
174
|
+
priority = 'P3';
|
|
175
|
+
else
|
|
176
|
+
priority = 'P4';
|
|
177
|
+
}
|
|
178
|
+
// Extract acceptance criteria (ADO has dedicated field)
|
|
179
|
+
const acceptanceCriteria = workItem.fields['Microsoft.VSTS.Common.AcceptanceCriteria']
|
|
180
|
+
? this.parseAcceptanceCriteria(workItem.fields['Microsoft.VSTS.Common.AcceptanceCriteria'])
|
|
181
|
+
: undefined;
|
|
182
|
+
// Map ADO state to ExternalItem status
|
|
183
|
+
let status = 'open';
|
|
184
|
+
const state = workItem.fields['System.State'].toLowerCase();
|
|
185
|
+
if (state === 'active' || state === 'in progress' || state === 'committed') {
|
|
186
|
+
status = 'in-progress';
|
|
187
|
+
}
|
|
188
|
+
else if (state === 'closed' || state === 'done' || state === 'resolved') {
|
|
189
|
+
status = 'completed';
|
|
190
|
+
}
|
|
191
|
+
// Parse tags (semicolon-separated)
|
|
192
|
+
const tags = workItem.fields['System.Tags']
|
|
193
|
+
? workItem.fields['System.Tags'].split(';').map((t) => t.trim()).filter(Boolean)
|
|
194
|
+
: [];
|
|
195
|
+
return {
|
|
196
|
+
id: `ADO-${workItem.fields['System.Id']}`,
|
|
197
|
+
type,
|
|
198
|
+
title: workItem.fields['System.Title'],
|
|
199
|
+
description: workItem.fields['System.Description'] || '',
|
|
200
|
+
status,
|
|
201
|
+
priority,
|
|
202
|
+
createdAt: new Date(workItem.fields['System.CreatedDate']),
|
|
203
|
+
updatedAt: new Date(workItem.fields['System.ChangedDate']),
|
|
204
|
+
url: workItem._links.html.href,
|
|
205
|
+
labels: tags,
|
|
206
|
+
acceptanceCriteria,
|
|
207
|
+
parentId: workItem.fields['System.Parent']
|
|
208
|
+
? `ADO-${workItem.fields['System.Parent'].id}`
|
|
209
|
+
: undefined,
|
|
210
|
+
platform: 'ado',
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Parse acceptance criteria from ADO HTML format
|
|
215
|
+
* ADO stores ACs as HTML, needs to extract plain text
|
|
216
|
+
*/
|
|
217
|
+
parseAcceptanceCriteria(html) {
|
|
218
|
+
// Strip HTML tags and extract bullet points
|
|
219
|
+
const text = html
|
|
220
|
+
.replace(/<[^>]*>/g, '') // Remove HTML tags
|
|
221
|
+
.replace(/ /g, ' ')
|
|
222
|
+
.replace(/&/g, '&')
|
|
223
|
+
.replace(/</g, '<')
|
|
224
|
+
.replace(/>/g, '>')
|
|
225
|
+
.replace(/"/g, '"');
|
|
226
|
+
// Split by newlines and filter empty lines
|
|
227
|
+
const lines = text
|
|
228
|
+
.split('\n')
|
|
229
|
+
.map((line) => line.trim())
|
|
230
|
+
.filter(Boolean);
|
|
231
|
+
return lines.length > 0 ? lines : undefined;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=ado-importer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ado-importer.js","sourceRoot":"","sources":["../../../src/importers/ado-importer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqCH;;GAEG;AACH,MAAM,OAAO,WAAW;IAMtB,YAAY,MAAc,EAAE,OAAe,EAAE,GAAY;QALhD,aAAQ,GAAG,KAAc,CAAC;QAMjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,0BAA0B;QACpE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;QAE5E,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CACb,4FAA4F,CAC7F,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,SAAuB,EAAE;QACpC,MAAM,KAAK,GAAmB,EAAE,CAAC;QAEjC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/C,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,CAAC,QAAQ,CAAC,SAAuB,EAAE;QACvC,MAAM,EACJ,eAAe,GAAG,CAAC,EACnB,aAAa,GAAG,KAAK,EACrB,MAAM,GAAG,EAAE,EACX,QAAQ,GAAG,QAAQ,GACpB,GAAG,MAAM,CAAC;QAEX,mBAAmB;QACnB,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,eAAe,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnD,MAAM,SAAS,GAAa;YAC1B,2EAA2E;YAC3E,gBAAgB;YAChB,iCAAiC,IAAI,CAAC,OAAO,GAAG;YAChD,gCAAgC,QAAQ,GAAG;SAC5C,CAAC;QAEF,gBAAgB;QAChB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,SAAS,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;QACnF,CAAC;QAED,kDAAkD;QAClD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,2BAA2B,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1F,SAAS,CAAC,IAAI,CAAC,QAAQ,aAAa,GAAG,CAAC,CAAC;QAC3C,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAErD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEjC,IAAI,CAAC;YACH,2DAA2D;YAC3D,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAC3C,iCAAiC,EACjC;gBACE,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aACtC,CACF,CAAC;YAEF,MAAM,cAAc,GAAG,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;YAEhE,yCAAyC;YACzC,IAAI,IAAI,GAAG,CAAC,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,gCAAgC;YACjD,IAAI,YAAY,GAAG,CAAC,CAAC;YAErB,OAAO,IAAI,GAAG,cAAc,CAAC,MAAM,IAAI,YAAY,GAAG,QAAQ,EAAE,CAAC;gBAC/D,wBAAwB;gBACxB,MAAM,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;gBAEnD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACrB,MAAM;gBACR,CAAC;gBAED,+BAA+B;gBAC/B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBAEpD,2BAA2B;gBAC3B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC;gBAEpE,aAAa;gBACb,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACrB,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,GAAG,YAAY,CAAC,CAAC;oBAC9C,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC;gBAC/B,CAAC;gBAED,IAAI,IAAI,GAAG,CAAC;YACd,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1E,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACrE,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,GAAa;QAC3C,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG;YACb,WAAW;YACX,cAAc;YACd,oBAAoB;YACpB,qBAAqB;YACrB,cAAc;YACd,oBAAoB;YACpB,oBAAoB;YACpB,aAAa;YACb,gCAAgC;YAChC,0CAA0C;YAC1C,eAAe;SAChB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEZ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CACxC,4BAA4B,QAAQ,WAAW,MAAM,gCAAgC,CACtF,CAAC;QAEF,OAAO,QAAQ,CAAC,KAAK,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAC1B,QAAgB,EAChB,UAAuB,EAAE;QAEzB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;QAExD,6DAA6D;QAC7D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE5D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;YAC/B,OAAO,EAAE;gBACP,eAAe,EAAE,SAAS,IAAI,EAAE;gBAChC,QAAQ,EAAE,kBAAkB;gBAC5B,cAAc,EAAE,kBAAkB;gBAClC,GAAG,OAAO,CAAC,OAAO;aACnB;YACD,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACxC,MAAM,KAAK,GAAQ,IAAI,KAAK,CAAC,kBAAkB,QAAQ,CAAC,UAAU,MAAM,SAAS,EAAE,CAAC,CAAC;YACrF,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC/B,MAAM,KAAK,CAAC;QACd,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,QAAqB;QACjD,8CAA8C;QAC9C,IAAI,IAAI,GAAyB,MAAM,CAAC;QACxC,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,WAAW,EAAE,CAAC;QAErE,IAAI,OAAO,KAAK,YAAY,IAAI,OAAO,KAAK,sBAAsB,EAAE,CAAC;YACnE,IAAI,GAAG,YAAY,CAAC;QACtB,CAAC;aAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YAC9B,IAAI,GAAG,MAAM,CAAC;QAChB,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,EAAE,CAAC;YAC7B,IAAI,GAAG,KAAK,CAAC;QACf,CAAC;aAAM,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,GAAG,SAAS,CAAC;QACnB,CAAC;QAED,4CAA4C;QAC5C,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;QACxE,IAAI,QAA8C,CAAC;QACnD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;YAChC,IAAI,aAAa,KAAK,CAAC;gBAAE,QAAQ,GAAG,IAAI,CAAC;iBACpC,IAAI,aAAa,KAAK,CAAC;gBAAE,QAAQ,GAAG,IAAI,CAAC;iBACzC,IAAI,aAAa,KAAK,CAAC;gBAAE,QAAQ,GAAG,IAAI,CAAC;iBACzC,IAAI,aAAa,KAAK,CAAC;gBAAE,QAAQ,GAAG,IAAI,CAAC;;gBACzC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;QAED,wDAAwD;QACxD,MAAM,kBAAkB,GAAG,QAAQ,CAAC,MAAM,CAAC,0CAA0C,CAAC;YACpF,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,MAAM,CAAC,0CAA0C,CAAC,CAAC;YAC3F,CAAC,CAAC,SAAS,CAAC;QAEd,uCAAuC;QACvC,IAAI,MAAM,GAA2B,MAAM,CAAC;QAC5C,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;QAE5D,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;YAC3E,MAAM,GAAG,aAAa,CAAC;QACzB,CAAC;aAAM,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;YAC1E,MAAM,GAAG,WAAW,CAAC;QACvB,CAAC;QAED,mCAAmC;QACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC;YACzC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;YAChF,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,EAAE,EAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE;YACzC,IAAI;YACJ,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC;YACtC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE;YACxD,MAAM;YACN,QAAQ;YACR,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC1D,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YAC1D,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;YAC9B,MAAM,EAAE,IAAI;YACZ,kBAAkB;YAClB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC;gBACxC,CAAC,CAAC,OAAO,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,EAAE,EAAE;gBAC9C,CAAC,CAAC,SAAS;YACb,QAAQ,EAAE,KAAK;SAChB,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,uBAAuB,CAAC,IAAY;QAC1C,4CAA4C;QAC5C,MAAM,IAAI,GAAG,IAAI;aACd,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,mBAAmB;aAC3C,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;aACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;aACtB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;aACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;aACrB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAE3B,2CAA2C;QAC3C,MAAM,KAAK,GAAG,IAAI;aACf,KAAK,CAAC,IAAI,CAAC;aACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,OAAO,CAAC,CAAC;QAEnB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9C,CAAC;CACF"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Duplicate Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects duplicate external items by scanning living docs for existing external IDs.
|
|
5
|
+
* Prevents re-importing items that have already been imported.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* External ID reference found in living docs
|
|
9
|
+
*/
|
|
10
|
+
export interface ExternalIdReference {
|
|
11
|
+
/** User Story ID (e.g., US-001E) */
|
|
12
|
+
usId: string;
|
|
13
|
+
/** File path where external ID was found */
|
|
14
|
+
filePath: string;
|
|
15
|
+
/** External ID value */
|
|
16
|
+
externalId: string;
|
|
17
|
+
/** External platform (github, jira, ado) */
|
|
18
|
+
platform?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Options for duplicate detection
|
|
22
|
+
*/
|
|
23
|
+
export interface DuplicateDetectorOptions {
|
|
24
|
+
/** Living docs specs directory to scan */
|
|
25
|
+
specsDir: string;
|
|
26
|
+
/** Cache scan results (default: true) */
|
|
27
|
+
enableCache?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Duplicate Detector
|
|
31
|
+
*
|
|
32
|
+
* Scans living docs US files for external_id metadata and provides
|
|
33
|
+
* duplicate detection functionality.
|
|
34
|
+
*/
|
|
35
|
+
export declare class DuplicateDetector {
|
|
36
|
+
private options;
|
|
37
|
+
private cache;
|
|
38
|
+
constructor(options: DuplicateDetectorOptions);
|
|
39
|
+
/**
|
|
40
|
+
* Check if an external ID already exists in living docs
|
|
41
|
+
*
|
|
42
|
+
* @param externalId - External ID to check (e.g., "GH-#638", "JIRA-PROJ-123")
|
|
43
|
+
* @returns True if external ID exists (duplicate), false otherwise
|
|
44
|
+
*/
|
|
45
|
+
checkExistingExternalId(externalId: string): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Find the User Story that contains a specific external ID
|
|
48
|
+
*
|
|
49
|
+
* @param externalId - External ID to search for
|
|
50
|
+
* @returns External ID reference if found, null otherwise
|
|
51
|
+
*/
|
|
52
|
+
findExternalIdReference(externalId: string): Promise<ExternalIdReference | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Get all external IDs currently in living docs
|
|
55
|
+
*
|
|
56
|
+
* @returns Map of external ID to reference
|
|
57
|
+
*/
|
|
58
|
+
getAllExternalIds(): Promise<Map<string, ExternalIdReference>>;
|
|
59
|
+
/**
|
|
60
|
+
* Build map of external IDs to User Story references
|
|
61
|
+
*/
|
|
62
|
+
private buildExternalIdMap;
|
|
63
|
+
/**
|
|
64
|
+
* Find all User Story markdown files in specs directory
|
|
65
|
+
*/
|
|
66
|
+
private findUserStoryFiles;
|
|
67
|
+
/**
|
|
68
|
+
* Extract external_id from a User Story file
|
|
69
|
+
*
|
|
70
|
+
* @param filePath - Path to User Story markdown file
|
|
71
|
+
* @returns External ID reference if found, null otherwise
|
|
72
|
+
*/
|
|
73
|
+
private extractExternalIdFromFile;
|
|
74
|
+
/**
|
|
75
|
+
* Extract US-ID from file name or content
|
|
76
|
+
*/
|
|
77
|
+
private extractUsIdFromFile;
|
|
78
|
+
/**
|
|
79
|
+
* Normalize external ID for consistent comparison
|
|
80
|
+
*
|
|
81
|
+
* Examples:
|
|
82
|
+
* - "GH-#638" → "gh-638"
|
|
83
|
+
* - "GITHUB-638" → "gh-638"
|
|
84
|
+
* - "JIRA-PROJ-123" → "jira-proj-123"
|
|
85
|
+
*/
|
|
86
|
+
private normalizeExternalId;
|
|
87
|
+
/**
|
|
88
|
+
* Clear the cache (useful for testing or after imports)
|
|
89
|
+
*/
|
|
90
|
+
clearCache(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Get cache statistics
|
|
93
|
+
*/
|
|
94
|
+
getCacheStats(): {
|
|
95
|
+
enabled: boolean;
|
|
96
|
+
size: number;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if an external ID exists (convenience function)
|
|
101
|
+
*
|
|
102
|
+
* @param externalId - External ID to check
|
|
103
|
+
* @param specsDir - Living docs specs directory
|
|
104
|
+
* @returns True if duplicate exists
|
|
105
|
+
*/
|
|
106
|
+
export declare function checkExistingExternalId(externalId: string, specsDir: string): Promise<boolean>;
|
|
107
|
+
//# sourceMappingURL=duplicate-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duplicate-detector.d.ts","sourceRoot":"","sources":["../../../src/importers/duplicate-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IAEb,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;IAEjB,wBAAwB;IACxB,UAAU,EAAE,MAAM,CAAC;IAEnB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IAEjB,yCAAyC;IACzC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,KAAK,CAAiD;gBAElD,OAAO,EAAE,wBAAwB;IAO7C;;;;;OAKG;IACG,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKnE;;;;;OAKG;IACG,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAUtF;;;;OAIG;IACG,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAIpE;;OAEG;YACW,kBAAkB;IA4BhC;;OAEG;YACW,kBAAkB;IAYhC;;;;;OAKG;YACW,yBAAyB;IAkCvC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;OAEG;IACH,UAAU,IAAI,IAAI;IAIlB;;OAEG;IACH,aAAa,IAAI;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;CAMpD;AAED;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAGlB"}
|