claude-autopm 2.7.0 → 2.8.2
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/README.md +307 -56
- package/autopm/.claude/.env +158 -0
- package/autopm/.claude/settings.local.json +9 -0
- package/bin/autopm.js +11 -2
- package/bin/commands/epic.js +23 -3
- package/bin/commands/plugin.js +395 -0
- package/bin/commands/team.js +184 -10
- package/install/install.js +223 -4
- package/lib/cli/commands/issue.js +360 -20
- package/lib/plugins/PluginManager.js +1328 -0
- package/lib/plugins/PluginManager.old.js +400 -0
- package/lib/providers/AzureDevOpsProvider.js +575 -0
- package/lib/providers/GitHubProvider.js +475 -0
- package/lib/services/EpicService.js +1092 -3
- package/lib/services/IssueService.js +991 -0
- package/package.json +9 -1
- package/scripts/publish-plugins.sh +166 -0
- package/autopm/.claude/agents/cloud/README.md +0 -55
- package/autopm/.claude/agents/cloud/aws-cloud-architect.md +0 -521
- package/autopm/.claude/agents/cloud/azure-cloud-architect.md +0 -436
- package/autopm/.claude/agents/cloud/gcp-cloud-architect.md +0 -385
- package/autopm/.claude/agents/cloud/gcp-cloud-functions-engineer.md +0 -306
- package/autopm/.claude/agents/cloud/gemini-api-expert.md +0 -880
- package/autopm/.claude/agents/cloud/kubernetes-orchestrator.md +0 -566
- package/autopm/.claude/agents/cloud/openai-python-expert.md +0 -1087
- package/autopm/.claude/agents/cloud/terraform-infrastructure-expert.md +0 -454
- package/autopm/.claude/agents/core/agent-manager.md +0 -296
- package/autopm/.claude/agents/core/code-analyzer.md +0 -131
- package/autopm/.claude/agents/core/file-analyzer.md +0 -162
- package/autopm/.claude/agents/core/test-runner.md +0 -200
- package/autopm/.claude/agents/data/airflow-orchestration-expert.md +0 -52
- package/autopm/.claude/agents/data/kedro-pipeline-expert.md +0 -50
- package/autopm/.claude/agents/data/langgraph-workflow-expert.md +0 -520
- package/autopm/.claude/agents/databases/README.md +0 -50
- package/autopm/.claude/agents/databases/bigquery-expert.md +0 -392
- package/autopm/.claude/agents/databases/cosmosdb-expert.md +0 -368
- package/autopm/.claude/agents/databases/mongodb-expert.md +0 -398
- package/autopm/.claude/agents/databases/postgresql-expert.md +0 -321
- package/autopm/.claude/agents/databases/redis-expert.md +0 -52
- package/autopm/.claude/agents/devops/README.md +0 -52
- package/autopm/.claude/agents/devops/azure-devops-specialist.md +0 -308
- package/autopm/.claude/agents/devops/docker-containerization-expert.md +0 -298
- package/autopm/.claude/agents/devops/github-operations-specialist.md +0 -335
- package/autopm/.claude/agents/devops/mcp-context-manager.md +0 -319
- package/autopm/.claude/agents/devops/observability-engineer.md +0 -574
- package/autopm/.claude/agents/devops/ssh-operations-expert.md +0 -1093
- package/autopm/.claude/agents/devops/traefik-proxy-expert.md +0 -444
- package/autopm/.claude/agents/frameworks/README.md +0 -64
- package/autopm/.claude/agents/frameworks/e2e-test-engineer.md +0 -360
- package/autopm/.claude/agents/frameworks/nats-messaging-expert.md +0 -254
- package/autopm/.claude/agents/frameworks/react-frontend-engineer.md +0 -217
- package/autopm/.claude/agents/frameworks/react-ui-expert.md +0 -226
- package/autopm/.claude/agents/frameworks/tailwindcss-expert.md +0 -770
- package/autopm/.claude/agents/frameworks/ux-design-expert.md +0 -244
- package/autopm/.claude/agents/integration/message-queue-engineer.md +0 -794
- package/autopm/.claude/agents/languages/README.md +0 -50
- package/autopm/.claude/agents/languages/bash-scripting-expert.md +0 -541
- package/autopm/.claude/agents/languages/javascript-frontend-engineer.md +0 -197
- package/autopm/.claude/agents/languages/nodejs-backend-engineer.md +0 -226
- package/autopm/.claude/agents/languages/python-backend-engineer.md +0 -214
- package/autopm/.claude/agents/languages/python-backend-expert.md +0 -289
- package/autopm/.claude/agents/testing/frontend-testing-engineer.md +0 -395
- package/autopm/.claude/commands/ai/langgraph-workflow.md +0 -65
- package/autopm/.claude/commands/ai/openai-chat.md +0 -65
- package/autopm/.claude/commands/azure/COMMANDS.md +0 -107
- package/autopm/.claude/commands/azure/COMMAND_MAPPING.md +0 -252
- package/autopm/.claude/commands/azure/INTEGRATION_FIX.md +0 -103
- package/autopm/.claude/commands/azure/README.md +0 -246
- package/autopm/.claude/commands/azure/active-work.md +0 -198
- package/autopm/.claude/commands/azure/aliases.md +0 -143
- package/autopm/.claude/commands/azure/blocked-items.md +0 -287
- package/autopm/.claude/commands/azure/clean.md +0 -93
- package/autopm/.claude/commands/azure/docs-query.md +0 -48
- package/autopm/.claude/commands/azure/feature-decompose.md +0 -380
- package/autopm/.claude/commands/azure/feature-list.md +0 -61
- package/autopm/.claude/commands/azure/feature-new.md +0 -115
- package/autopm/.claude/commands/azure/feature-show.md +0 -205
- package/autopm/.claude/commands/azure/feature-start.md +0 -130
- package/autopm/.claude/commands/azure/fix-integration-example.md +0 -93
- package/autopm/.claude/commands/azure/help.md +0 -150
- package/autopm/.claude/commands/azure/import-us.md +0 -269
- package/autopm/.claude/commands/azure/init.md +0 -211
- package/autopm/.claude/commands/azure/next-task.md +0 -262
- package/autopm/.claude/commands/azure/search.md +0 -160
- package/autopm/.claude/commands/azure/sprint-status.md +0 -235
- package/autopm/.claude/commands/azure/standup.md +0 -260
- package/autopm/.claude/commands/azure/sync-all.md +0 -99
- package/autopm/.claude/commands/azure/task-analyze.md +0 -186
- package/autopm/.claude/commands/azure/task-close.md +0 -329
- package/autopm/.claude/commands/azure/task-edit.md +0 -145
- package/autopm/.claude/commands/azure/task-list.md +0 -263
- package/autopm/.claude/commands/azure/task-new.md +0 -84
- package/autopm/.claude/commands/azure/task-reopen.md +0 -79
- package/autopm/.claude/commands/azure/task-show.md +0 -126
- package/autopm/.claude/commands/azure/task-start.md +0 -301
- package/autopm/.claude/commands/azure/task-status.md +0 -65
- package/autopm/.claude/commands/azure/task-sync.md +0 -67
- package/autopm/.claude/commands/azure/us-edit.md +0 -164
- package/autopm/.claude/commands/azure/us-list.md +0 -202
- package/autopm/.claude/commands/azure/us-new.md +0 -265
- package/autopm/.claude/commands/azure/us-parse.md +0 -253
- package/autopm/.claude/commands/azure/us-show.md +0 -188
- package/autopm/.claude/commands/azure/us-status.md +0 -320
- package/autopm/.claude/commands/azure/validate.md +0 -86
- package/autopm/.claude/commands/azure/work-item-sync.md +0 -47
- package/autopm/.claude/commands/cloud/infra-deploy.md +0 -38
- package/autopm/.claude/commands/github/workflow-create.md +0 -42
- package/autopm/.claude/commands/infrastructure/ssh-security.md +0 -65
- package/autopm/.claude/commands/infrastructure/traefik-setup.md +0 -65
- package/autopm/.claude/commands/kubernetes/deploy.md +0 -37
- package/autopm/.claude/commands/playwright/test-scaffold.md +0 -38
- package/autopm/.claude/commands/pm/blocked.md +0 -28
- package/autopm/.claude/commands/pm/clean.md +0 -119
- package/autopm/.claude/commands/pm/context-create.md +0 -136
- package/autopm/.claude/commands/pm/context-prime.md +0 -170
- package/autopm/.claude/commands/pm/context-update.md +0 -292
- package/autopm/.claude/commands/pm/context.md +0 -28
- package/autopm/.claude/commands/pm/epic-close.md +0 -86
- package/autopm/.claude/commands/pm/epic-decompose.md +0 -370
- package/autopm/.claude/commands/pm/epic-edit.md +0 -83
- package/autopm/.claude/commands/pm/epic-list.md +0 -30
- package/autopm/.claude/commands/pm/epic-merge.md +0 -222
- package/autopm/.claude/commands/pm/epic-oneshot.md +0 -119
- package/autopm/.claude/commands/pm/epic-refresh.md +0 -119
- package/autopm/.claude/commands/pm/epic-show.md +0 -28
- package/autopm/.claude/commands/pm/epic-split.md +0 -120
- package/autopm/.claude/commands/pm/epic-start.md +0 -195
- package/autopm/.claude/commands/pm/epic-status.md +0 -28
- package/autopm/.claude/commands/pm/epic-sync-modular.md +0 -338
- package/autopm/.claude/commands/pm/epic-sync-original.md +0 -473
- package/autopm/.claude/commands/pm/epic-sync.md +0 -486
- package/autopm/.claude/commands/pm/help.md +0 -28
- package/autopm/.claude/commands/pm/import.md +0 -115
- package/autopm/.claude/commands/pm/in-progress.md +0 -28
- package/autopm/.claude/commands/pm/init.md +0 -28
- package/autopm/.claude/commands/pm/issue-analyze.md +0 -202
- package/autopm/.claude/commands/pm/issue-close.md +0 -119
- package/autopm/.claude/commands/pm/issue-edit.md +0 -93
- package/autopm/.claude/commands/pm/issue-reopen.md +0 -87
- package/autopm/.claude/commands/pm/issue-show.md +0 -41
- package/autopm/.claude/commands/pm/issue-start.md +0 -234
- package/autopm/.claude/commands/pm/issue-status.md +0 -95
- package/autopm/.claude/commands/pm/issue-sync.md +0 -411
- package/autopm/.claude/commands/pm/next.md +0 -28
- package/autopm/.claude/commands/pm/prd-edit.md +0 -82
- package/autopm/.claude/commands/pm/prd-list.md +0 -28
- package/autopm/.claude/commands/pm/prd-new.md +0 -55
- package/autopm/.claude/commands/pm/prd-parse.md +0 -42
- package/autopm/.claude/commands/pm/prd-status.md +0 -28
- package/autopm/.claude/commands/pm/search.md +0 -28
- package/autopm/.claude/commands/pm/standup.md +0 -28
- package/autopm/.claude/commands/pm/status.md +0 -28
- package/autopm/.claude/commands/pm/sync.md +0 -99
- package/autopm/.claude/commands/pm/test-reference-update.md +0 -151
- package/autopm/.claude/commands/pm/validate.md +0 -28
- package/autopm/.claude/commands/pm/what-next.md +0 -28
- package/autopm/.claude/commands/python/api-scaffold.md +0 -50
- package/autopm/.claude/commands/python/docs-query.md +0 -48
- package/autopm/.claude/commands/react/app-scaffold.md +0 -50
- package/autopm/.claude/commands/testing/prime.md +0 -314
- package/autopm/.claude/commands/testing/run.md +0 -125
- package/autopm/.claude/commands/ui/bootstrap-scaffold.md +0 -65
- package/autopm/.claude/commands/ui/tailwind-system.md +0 -64
- package/autopm/.claude/rules/ai-integration-patterns.md +0 -219
- package/autopm/.claude/rules/ci-cd-kubernetes-strategy.md +0 -25
- package/autopm/.claude/rules/database-management-strategy.md +0 -17
- package/autopm/.claude/rules/database-pipeline.md +0 -94
- package/autopm/.claude/rules/devops-troubleshooting-playbook.md +0 -450
- package/autopm/.claude/rules/docker-first-development.md +0 -404
- package/autopm/.claude/rules/infrastructure-pipeline.md +0 -128
- package/autopm/.claude/rules/performance-guidelines.md +0 -403
- package/autopm/.claude/rules/ui-development-standards.md +0 -281
- package/autopm/.claude/rules/ui-framework-rules.md +0 -151
- package/autopm/.claude/rules/ux-design-rules.md +0 -209
- package/autopm/.claude/rules/visual-testing.md +0 -223
- package/autopm/.claude/scripts/azure/README.md +0 -192
- package/autopm/.claude/scripts/azure/active-work.js +0 -524
- package/autopm/.claude/scripts/azure/active-work.sh +0 -20
- package/autopm/.claude/scripts/azure/blocked.js +0 -520
- package/autopm/.claude/scripts/azure/blocked.sh +0 -20
- package/autopm/.claude/scripts/azure/daily.js +0 -533
- package/autopm/.claude/scripts/azure/daily.sh +0 -20
- package/autopm/.claude/scripts/azure/dashboard.js +0 -970
- package/autopm/.claude/scripts/azure/dashboard.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-list.js +0 -254
- package/autopm/.claude/scripts/azure/feature-list.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-show.js +0 -7
- package/autopm/.claude/scripts/azure/feature-show.sh +0 -20
- package/autopm/.claude/scripts/azure/feature-status.js +0 -604
- package/autopm/.claude/scripts/azure/feature-status.sh +0 -20
- package/autopm/.claude/scripts/azure/help.js +0 -342
- package/autopm/.claude/scripts/azure/help.sh +0 -20
- package/autopm/.claude/scripts/azure/next-task.js +0 -508
- package/autopm/.claude/scripts/azure/next-task.sh +0 -20
- package/autopm/.claude/scripts/azure/search.js +0 -469
- package/autopm/.claude/scripts/azure/search.sh +0 -20
- package/autopm/.claude/scripts/azure/setup.js +0 -745
- package/autopm/.claude/scripts/azure/setup.sh +0 -20
- package/autopm/.claude/scripts/azure/sprint-report.js +0 -1012
- package/autopm/.claude/scripts/azure/sprint-report.sh +0 -20
- package/autopm/.claude/scripts/azure/sync.js +0 -563
- package/autopm/.claude/scripts/azure/sync.sh +0 -20
- package/autopm/.claude/scripts/azure/us-list.js +0 -210
- package/autopm/.claude/scripts/azure/us-list.sh +0 -20
- package/autopm/.claude/scripts/azure/us-status.js +0 -238
- package/autopm/.claude/scripts/azure/us-status.sh +0 -20
- package/autopm/.claude/scripts/azure/validate.js +0 -626
- package/autopm/.claude/scripts/azure/validate.sh +0 -20
- package/autopm/.claude/scripts/azure/wrapper-template.sh +0 -20
- package/autopm/.claude/scripts/github/dependency-tracker.js +0 -554
- package/autopm/.claude/scripts/github/dependency-validator.js +0 -545
- package/autopm/.claude/scripts/github/dependency-visualizer.js +0 -477
- package/autopm/.claude/scripts/pm/analytics.js +0 -425
- package/autopm/.claude/scripts/pm/blocked.js +0 -164
- package/autopm/.claude/scripts/pm/blocked.sh +0 -78
- package/autopm/.claude/scripts/pm/clean.js +0 -464
- package/autopm/.claude/scripts/pm/context-create.js +0 -216
- package/autopm/.claude/scripts/pm/context-prime.js +0 -335
- package/autopm/.claude/scripts/pm/context-update.js +0 -344
- package/autopm/.claude/scripts/pm/context.js +0 -338
- package/autopm/.claude/scripts/pm/epic-close.js +0 -347
- package/autopm/.claude/scripts/pm/epic-edit.js +0 -382
- package/autopm/.claude/scripts/pm/epic-list.js +0 -273
- package/autopm/.claude/scripts/pm/epic-list.sh +0 -109
- package/autopm/.claude/scripts/pm/epic-show.js +0 -291
- package/autopm/.claude/scripts/pm/epic-show.sh +0 -105
- package/autopm/.claude/scripts/pm/epic-split.js +0 -522
- package/autopm/.claude/scripts/pm/epic-start/epic-start.js +0 -183
- package/autopm/.claude/scripts/pm/epic-start/epic-start.sh +0 -94
- package/autopm/.claude/scripts/pm/epic-status.js +0 -291
- package/autopm/.claude/scripts/pm/epic-status.sh +0 -104
- package/autopm/.claude/scripts/pm/epic-sync/README.md +0 -208
- package/autopm/.claude/scripts/pm/epic-sync/create-epic-issue.sh +0 -77
- package/autopm/.claude/scripts/pm/epic-sync/create-task-issues.sh +0 -86
- package/autopm/.claude/scripts/pm/epic-sync/update-epic-file.sh +0 -79
- package/autopm/.claude/scripts/pm/epic-sync/update-references.sh +0 -89
- package/autopm/.claude/scripts/pm/epic-sync.sh +0 -137
- package/autopm/.claude/scripts/pm/help.js +0 -92
- package/autopm/.claude/scripts/pm/help.sh +0 -90
- package/autopm/.claude/scripts/pm/in-progress.js +0 -178
- package/autopm/.claude/scripts/pm/in-progress.sh +0 -93
- package/autopm/.claude/scripts/pm/init.js +0 -321
- package/autopm/.claude/scripts/pm/init.sh +0 -178
- package/autopm/.claude/scripts/pm/issue-close.js +0 -232
- package/autopm/.claude/scripts/pm/issue-edit.js +0 -310
- package/autopm/.claude/scripts/pm/issue-show.js +0 -272
- package/autopm/.claude/scripts/pm/issue-start.js +0 -181
- package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +0 -468
- package/autopm/.claude/scripts/pm/issue-sync/gather-updates.sh +0 -460
- package/autopm/.claude/scripts/pm/issue-sync/post-comment.sh +0 -330
- package/autopm/.claude/scripts/pm/issue-sync/preflight-validation.sh +0 -348
- package/autopm/.claude/scripts/pm/issue-sync/update-frontmatter.sh +0 -387
- package/autopm/.claude/scripts/pm/lib/README.md +0 -85
- package/autopm/.claude/scripts/pm/lib/epic-discovery.js +0 -119
- package/autopm/.claude/scripts/pm/lib/logger.js +0 -78
- package/autopm/.claude/scripts/pm/next.js +0 -189
- package/autopm/.claude/scripts/pm/next.sh +0 -72
- package/autopm/.claude/scripts/pm/optimize.js +0 -407
- package/autopm/.claude/scripts/pm/pr-create.js +0 -337
- package/autopm/.claude/scripts/pm/pr-list.js +0 -257
- package/autopm/.claude/scripts/pm/prd-list.js +0 -242
- package/autopm/.claude/scripts/pm/prd-list.sh +0 -103
- package/autopm/.claude/scripts/pm/prd-new.js +0 -684
- package/autopm/.claude/scripts/pm/prd-parse.js +0 -547
- package/autopm/.claude/scripts/pm/prd-status.js +0 -152
- package/autopm/.claude/scripts/pm/prd-status.sh +0 -63
- package/autopm/.claude/scripts/pm/release.js +0 -460
- package/autopm/.claude/scripts/pm/search.js +0 -192
- package/autopm/.claude/scripts/pm/search.sh +0 -89
- package/autopm/.claude/scripts/pm/standup.js +0 -362
- package/autopm/.claude/scripts/pm/standup.sh +0 -95
- package/autopm/.claude/scripts/pm/status.js +0 -148
- package/autopm/.claude/scripts/pm/status.sh +0 -59
- package/autopm/.claude/scripts/pm/sync-batch.js +0 -337
- package/autopm/.claude/scripts/pm/sync.js +0 -343
- package/autopm/.claude/scripts/pm/template-list.js +0 -141
- package/autopm/.claude/scripts/pm/template-new.js +0 -366
- package/autopm/.claude/scripts/pm/validate.js +0 -274
- package/autopm/.claude/scripts/pm/validate.sh +0 -106
- package/autopm/.claude/scripts/pm/what-next.js +0 -660
- package/bin/node/azure-feature-show.js +0 -7
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Azure Script - Wrapper for Node.js implementation
|
|
4
|
-
# This wrapper maintains backward compatibility while delegating to the Node.js version
|
|
5
|
-
|
|
6
|
-
# Get the directory of this script
|
|
7
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
-
SCRIPT_NAME="$(basename "$0" .sh)"
|
|
9
|
-
|
|
10
|
-
# Check if Node.js is available and the .js file exists
|
|
11
|
-
if command -v node >/dev/null 2>&1 && [ -f "$SCRIPT_DIR/$SCRIPT_NAME.js" ]; then
|
|
12
|
-
# Use the Node.js implementation
|
|
13
|
-
node "$SCRIPT_DIR/$SCRIPT_NAME.js" "$@"
|
|
14
|
-
exit $?
|
|
15
|
-
else
|
|
16
|
-
# Fallback message
|
|
17
|
-
echo "⚠️ Node.js not found or $SCRIPT_NAME.js missing"
|
|
18
|
-
echo "Please ensure Node.js is installed and all files are present"
|
|
19
|
-
exit 1
|
|
20
|
-
fi
|
|
@@ -1,563 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Azure DevOps Sync Tool
|
|
5
|
-
* Synchronizes work items between Azure DevOps and local tracking
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const fs = require('fs').promises;
|
|
10
|
-
const AzureDevOpsClient = require('../../providers/azure/lib/client');
|
|
11
|
-
|
|
12
|
-
// Simple chalk replacement for stub
|
|
13
|
-
const chalk = {
|
|
14
|
-
red: (str) => str,
|
|
15
|
-
green: (str) => str,
|
|
16
|
-
blue: (str) => str,
|
|
17
|
-
yellow: (str) => str,
|
|
18
|
-
cyan: (str) => str,
|
|
19
|
-
magenta: (str) => str,
|
|
20
|
-
gray: (str) => str,
|
|
21
|
-
white: (str) => str,
|
|
22
|
-
bold: (str) => str,
|
|
23
|
-
dim: (str) => str
|
|
24
|
-
};
|
|
25
|
-
chalk.red.bold = (str) => str;
|
|
26
|
-
chalk.green.bold = (str) => str;
|
|
27
|
-
chalk.blue.bold = (str) => str;
|
|
28
|
-
chalk.blue.underline = (str) => str;
|
|
29
|
-
chalk.yellow.bold = (str) => str;
|
|
30
|
-
chalk.cyan.bold = (str) => str;
|
|
31
|
-
chalk.magenta.bold = (str) => str;
|
|
32
|
-
chalk.gray.bold = (str) => str;
|
|
33
|
-
|
|
34
|
-
class AzureSync {
|
|
35
|
-
constructor(options = {}) {
|
|
36
|
-
this.options = options;
|
|
37
|
-
this.silent = options.silent || false;
|
|
38
|
-
this.format = options.format || 'table'; // table, json
|
|
39
|
-
this.direction = options.direction || 'both'; // pull, push, both
|
|
40
|
-
this.dryRun = options.dryRun || false;
|
|
41
|
-
this.projectPath = options.projectPath || process.cwd();
|
|
42
|
-
this.options.mode = options.mode || 'quick'; // quick or full
|
|
43
|
-
|
|
44
|
-
// Set cache paths
|
|
45
|
-
this.cachePath = path.join(this.projectPath, '.claude', 'azure', 'cache');
|
|
46
|
-
this.envPath = path.join(this.projectPath, '.claude', '.env');
|
|
47
|
-
|
|
48
|
-
// Initialize credentials placeholder
|
|
49
|
-
this.credentials = {};
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// Load environment variables from .env file if it exists
|
|
53
|
-
const envPath = path.join(this.projectPath, '.env');
|
|
54
|
-
if (fs.existsSync(envPath)) {
|
|
55
|
-
require('dotenv').config({ path: envPath });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Also check .claude/.env
|
|
59
|
-
const claudeEnvPath = path.join(this.projectPath, '.claude', '.env');
|
|
60
|
-
if (fs.existsSync(claudeEnvPath)) {
|
|
61
|
-
require('dotenv').config({ path: claudeEnvPath });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Initialize Azure DevOps client
|
|
65
|
-
try {
|
|
66
|
-
this.client = new AzureDevOpsClient();
|
|
67
|
-
} catch (error) {
|
|
68
|
-
// In test mode or when credentials are missing
|
|
69
|
-
if (options.testMode || error.message.includes('Missing required environment variables')) {
|
|
70
|
-
this.client = null;
|
|
71
|
-
} else {
|
|
72
|
-
throw error;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if (!options.testMode) {
|
|
77
|
-
this.handleInitError(error);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
handleInitError(error) {
|
|
83
|
-
if (error.message.includes('Missing required environment variables')) {
|
|
84
|
-
console.error('❌ Azure DevOps configuration missing!\n');
|
|
85
|
-
console.error('Please set the following environment variables:');
|
|
86
|
-
console.error(' - AZURE_DEVOPS_ORG: Your Azure DevOps organization');
|
|
87
|
-
console.error(' - AZURE_DEVOPS_PROJECT: Your project name');
|
|
88
|
-
console.error(' - AZURE_DEVOPS_PAT: Your Personal Access Token\n');
|
|
89
|
-
console.error('You can set these in .env or .claude/.env file\n');
|
|
90
|
-
process.exit(1);
|
|
91
|
-
}
|
|
92
|
-
throw error;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async loadEnvironment() {
|
|
96
|
-
// Load environment variables from .claude/.env file
|
|
97
|
-
const envFilePath = this.envPath;
|
|
98
|
-
|
|
99
|
-
if (!await fs.pathExists(envFilePath)) {
|
|
100
|
-
throw new Error('Azure DevOps credentials not configured. Please create .claude/.env file.');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const envContent = await fs.readFile(envFilePath, 'utf8');
|
|
104
|
-
const lines = envContent.split('\n');
|
|
105
|
-
|
|
106
|
-
lines.forEach(line => {
|
|
107
|
-
const trimmedLine = line.trim();
|
|
108
|
-
if (trimmedLine && !trimmedLine.startsWith('#')) {
|
|
109
|
-
const [key, ...valueParts] = trimmedLine.split('=');
|
|
110
|
-
if (key) {
|
|
111
|
-
const value = valueParts.join('=').trim();
|
|
112
|
-
this.credentials[key.trim()] = value;
|
|
113
|
-
process.env[key.trim()] = value;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Check for required credentials
|
|
119
|
-
const required = ['AZURE_DEVOPS_PAT', 'AZURE_DEVOPS_ORG', 'AZURE_DEVOPS_PROJECT'];
|
|
120
|
-
const missing = required.filter(key => !this.credentials[key]);
|
|
121
|
-
|
|
122
|
-
if (missing.length > 0) {
|
|
123
|
-
throw new Error(`Azure DevOps credentials not configured. Missing: ${missing.join(', ')}`);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return this.credentials;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async createCacheDirectories() {
|
|
130
|
-
const azurePath = path.join(this.projectPath, '.claude', 'azure');
|
|
131
|
-
const dirs = [
|
|
132
|
-
azurePath,
|
|
133
|
-
this.cachePath,
|
|
134
|
-
path.join(this.cachePath, 'features'),
|
|
135
|
-
path.join(this.cachePath, 'stories'),
|
|
136
|
-
path.join(this.cachePath, 'tasks'),
|
|
137
|
-
path.join(this.cachePath, 'sync'),
|
|
138
|
-
path.join(azurePath, 'sync') // Sync directory outside cache
|
|
139
|
-
];
|
|
140
|
-
|
|
141
|
-
for (const dir of dirs) {
|
|
142
|
-
await fs.mkdir(dir, { recursive: true });
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return dirs;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async callAzureAPI(endpoint, options = {}) {
|
|
149
|
-
if (!this.client) {
|
|
150
|
-
throw new Error('Azure DevOps client not initialized');
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// This would make actual API calls through the client
|
|
154
|
-
// For now, return mock data for testing
|
|
155
|
-
return { workItems: [] };
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async syncWorkItemType(workItemType, cacheDir) {
|
|
159
|
-
const syncStart = Date.now();
|
|
160
|
-
let itemCount = 0;
|
|
161
|
-
|
|
162
|
-
if (!this.silent) {
|
|
163
|
-
console.log(`Syncing ${workItemType}...`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
// Query for work items
|
|
168
|
-
const query = this.buildWIQLQuery(workItemType);
|
|
169
|
-
const result = await this.executeQuery(query);
|
|
170
|
-
|
|
171
|
-
// For testing, if no client, create mock data
|
|
172
|
-
if (!this.client && workItemType === 'features') {
|
|
173
|
-
// Create mock items for testing
|
|
174
|
-
const mockItems = [
|
|
175
|
-
{ id: 123, fields: { 'System.Title': 'Test Feature', 'System.State': 'Active' } },
|
|
176
|
-
{ id: 456, fields: { 'System.Title': 'Another Feature', 'System.State': 'New' } }
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
itemCount = mockItems.length;
|
|
180
|
-
for (const item of mockItems) {
|
|
181
|
-
await this.saveToCache(item, cacheDir);
|
|
182
|
-
}
|
|
183
|
-
} else if (result && result.workItems) {
|
|
184
|
-
itemCount = result.workItems.length;
|
|
185
|
-
|
|
186
|
-
// Save each work item to cache
|
|
187
|
-
for (const item of result.workItems) {
|
|
188
|
-
const itemDetails = await this.getWorkItemDetails(item.id);
|
|
189
|
-
await this.saveToCache(itemDetails, cacheDir);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const duration = Date.now() - syncStart;
|
|
194
|
-
|
|
195
|
-
return {
|
|
196
|
-
type: workItemType,
|
|
197
|
-
count: itemCount,
|
|
198
|
-
duration,
|
|
199
|
-
cacheDir
|
|
200
|
-
};
|
|
201
|
-
} catch (error) {
|
|
202
|
-
throw new Error(`Failed to sync ${workItemType}: ${error.message}`);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
buildWIQLQuery(workItemType) {
|
|
207
|
-
const typeMapping = {
|
|
208
|
-
'features': 'Feature',
|
|
209
|
-
'stories': 'User Story',
|
|
210
|
-
'tasks': 'Task'
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const type = typeMapping[workItemType] || workItemType;
|
|
214
|
-
|
|
215
|
-
if (this.options.mode === 'quick') {
|
|
216
|
-
// Query for recent changes (last 7 days)
|
|
217
|
-
return `
|
|
218
|
-
SELECT [System.Id], [System.Title], [System.State]
|
|
219
|
-
FROM workitems
|
|
220
|
-
WHERE [System.WorkItemType] = '${type}'
|
|
221
|
-
AND [System.ChangedDate] > @today - 7
|
|
222
|
-
ORDER BY [System.ChangedDate] DESC
|
|
223
|
-
`;
|
|
224
|
-
} else {
|
|
225
|
-
// Full sync - all items
|
|
226
|
-
return `
|
|
227
|
-
SELECT [System.Id], [System.Title], [System.State]
|
|
228
|
-
FROM workitems
|
|
229
|
-
WHERE [System.WorkItemType] = '${type}'
|
|
230
|
-
ORDER BY [System.Id] DESC
|
|
231
|
-
`;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
async executeQuery(query) {
|
|
236
|
-
if (!this.client) {
|
|
237
|
-
return { workItems: [] };
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
try {
|
|
241
|
-
return await this.client.executeWiql(query);
|
|
242
|
-
} catch (error) {
|
|
243
|
-
throw new Error(`Query execution failed: ${error.message}`);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
async getWorkItemDetails(id) {
|
|
248
|
-
if (!this.client) {
|
|
249
|
-
return { id, fields: {} };
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
const items = await this.client.getWorkItems([id]);
|
|
254
|
-
return items[0] || { id, fields: {} };
|
|
255
|
-
} catch (error) {
|
|
256
|
-
throw new Error(`Failed to get work item ${id}: ${error.message}`);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
async saveToCache(item, cacheDir) {
|
|
261
|
-
const fileName = `${item.id}.json`;
|
|
262
|
-
const filePath = path.join(cacheDir, fileName);
|
|
263
|
-
|
|
264
|
-
await fs.writeFile(filePath, JSON.stringify(item, null, 2));
|
|
265
|
-
|
|
266
|
-
return filePath;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
async updateSyncMetadata(data) {
|
|
270
|
-
const syncPath = path.join(this.projectPath, '.claude', 'azure', 'sync');
|
|
271
|
-
await fs.mkdir(syncPath, { recursive: true });
|
|
272
|
-
|
|
273
|
-
const metadataPath = path.join(syncPath, 'last-sync.json');
|
|
274
|
-
|
|
275
|
-
// Calculate cache size
|
|
276
|
-
let cacheSize = '0';
|
|
277
|
-
try {
|
|
278
|
-
const cachePath = path.join(this.projectPath, '.claude', 'azure', 'cache');
|
|
279
|
-
try {
|
|
280
|
-
await fs.access(cachePath);
|
|
281
|
-
const stats = await this.getDirectorySize(cachePath);
|
|
282
|
-
cacheSize = this.formatBytes(stats);
|
|
283
|
-
} catch (err) {
|
|
284
|
-
// File doesn't exist, ignore
|
|
285
|
-
}
|
|
286
|
-
} catch (error) {
|
|
287
|
-
// Ignore size calculation errors
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const metadata = {
|
|
291
|
-
timestamp: new Date().toISOString(),
|
|
292
|
-
mode: data.mode || this.options.mode,
|
|
293
|
-
items_synced: data.itemsSynced || {},
|
|
294
|
-
cache_size: cacheSize,
|
|
295
|
-
...data
|
|
296
|
-
};
|
|
297
|
-
|
|
298
|
-
await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2));
|
|
299
|
-
|
|
300
|
-
return metadata;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
async getDirectorySize(dirPath) {
|
|
304
|
-
let totalSize = 0;
|
|
305
|
-
|
|
306
|
-
const files = await fs.readdir(dirPath, { withFileTypes: true });
|
|
307
|
-
|
|
308
|
-
for (const file of files) {
|
|
309
|
-
const fullPath = path.join(dirPath, file.name);
|
|
310
|
-
|
|
311
|
-
if (file.isDirectory()) {
|
|
312
|
-
totalSize += await this.getDirectorySize(fullPath);
|
|
313
|
-
} else {
|
|
314
|
-
const stats = await fs.stat(fullPath);
|
|
315
|
-
totalSize += stats.size;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
return totalSize;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
formatBytes(bytes) {
|
|
323
|
-
if (bytes === 0) return '0 Bytes';
|
|
324
|
-
|
|
325
|
-
const k = 1024;
|
|
326
|
-
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
327
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
328
|
-
|
|
329
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
async run() {
|
|
333
|
-
const startTime = Date.now();
|
|
334
|
-
const results = [];
|
|
335
|
-
|
|
336
|
-
try {
|
|
337
|
-
// Load environment
|
|
338
|
-
await this.loadEnvironment();
|
|
339
|
-
|
|
340
|
-
// Create cache directories
|
|
341
|
-
await this.createCacheDirectories();
|
|
342
|
-
|
|
343
|
-
if (!this.silent) {
|
|
344
|
-
console.log(chalk.cyan.bold('\n🔄 Starting Azure DevOps Sync\n'));
|
|
345
|
-
console.log(`Mode: ${this.options.mode}`);
|
|
346
|
-
console.log(`Cache path: ${this.cachePath}\n`);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// Sync each work item type
|
|
350
|
-
const workItemTypes = ['features', 'stories', 'tasks'];
|
|
351
|
-
|
|
352
|
-
for (const type of workItemTypes) {
|
|
353
|
-
const cacheDir = path.join(this.cachePath, type);
|
|
354
|
-
const result = await this.syncWorkItemType(type, cacheDir);
|
|
355
|
-
results.push(result);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// Update metadata
|
|
359
|
-
const totalItems = results.reduce((sum, r) => sum + r.count, 0);
|
|
360
|
-
const duration = Date.now() - startTime;
|
|
361
|
-
|
|
362
|
-
await this.updateSyncMetadata({
|
|
363
|
-
results,
|
|
364
|
-
totalItems,
|
|
365
|
-
duration
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
if (!this.silent) {
|
|
369
|
-
console.log(chalk.green.bold('\n✅ Sync completed successfully!'));
|
|
370
|
-
console.log(`Total items: ${totalItems}`);
|
|
371
|
-
console.log(`Duration: ${(duration / 1000).toFixed(2)}s\n`);
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return {
|
|
375
|
-
success: true,
|
|
376
|
-
results,
|
|
377
|
-
totalItems,
|
|
378
|
-
duration,
|
|
379
|
-
mode: this.options.mode
|
|
380
|
-
};
|
|
381
|
-
} catch (error) {
|
|
382
|
-
if (!this.silent) {
|
|
383
|
-
console.error(chalk.red.bold(`\n❌ Sync failed: ${error.message}\n`));
|
|
384
|
-
}
|
|
385
|
-
throw error;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Main entry point for backward compatibility
|
|
390
|
-
async syncWorkItems(workItemType, cacheDir) {
|
|
391
|
-
// If called with parameters, sync specific type
|
|
392
|
-
if (workItemType && cacheDir) {
|
|
393
|
-
// Ensure cache directories exist
|
|
394
|
-
await this.createCacheDirectories();
|
|
395
|
-
|
|
396
|
-
const fullCacheDir = path.join(this.cachePath, cacheDir);
|
|
397
|
-
await fs.mkdir(fullCacheDir, { recursive: true });
|
|
398
|
-
|
|
399
|
-
const result = await this.syncWorkItemType(cacheDir, fullCacheDir);
|
|
400
|
-
result.success = true;
|
|
401
|
-
return result;
|
|
402
|
-
}
|
|
403
|
-
// Otherwise run full sync
|
|
404
|
-
return this.run();
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
displaySyncResult(result) {
|
|
409
|
-
switch (this.format) {
|
|
410
|
-
case 'json':
|
|
411
|
-
console.log(JSON.stringify(result, null, 2));
|
|
412
|
-
break;
|
|
413
|
-
default:
|
|
414
|
-
this.displayTable(result);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
displayTable(result) {
|
|
419
|
-
// Header
|
|
420
|
-
console.log(chalk.cyan.bold('Sync Summary'));
|
|
421
|
-
console.log('─'.repeat(50));
|
|
422
|
-
console.log(`Timestamp: ${new Date(result.timestamp).toLocaleString()}`);
|
|
423
|
-
console.log(`Direction: ${result.direction}`);
|
|
424
|
-
console.log(`Mode: ${result.dryRun ? 'Dry Run' : 'Live'}\n`);
|
|
425
|
-
|
|
426
|
-
// State comparison
|
|
427
|
-
console.log(chalk.blue.bold('📊 State Comparison'));
|
|
428
|
-
console.log(`Local: ${result.localState.totalItems} items (last sync: ${new Date(result.localState.lastSync).toLocaleString()})`);
|
|
429
|
-
console.log(`Remote: ${result.remoteState.totalItems} items (modified: ${new Date(result.remoteState.lastModified).toLocaleString()})\n`);
|
|
430
|
-
|
|
431
|
-
// Downloads
|
|
432
|
-
if (result.changes.toDownload.length > 0) {
|
|
433
|
-
console.log(chalk.green.bold('⬇️ Changes to Download'));
|
|
434
|
-
result.changes.toDownload.forEach(item => {
|
|
435
|
-
const icon = item.action === 'create' ? '✨' : '📝';
|
|
436
|
-
console.log(` ${icon} [${item.id}] ${item.title}`);
|
|
437
|
-
console.log(` Type: ${item.type} | Action: ${item.action} | State: ${item.state}`);
|
|
438
|
-
if (item.changes) {
|
|
439
|
-
item.changes.forEach(change => {
|
|
440
|
-
console.log(` • ${change}`);
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
});
|
|
444
|
-
console.log('');
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
// Uploads
|
|
448
|
-
if (result.changes.toUpload.length > 0) {
|
|
449
|
-
console.log(chalk.blue.bold('⬆️ Changes to Upload'));
|
|
450
|
-
result.changes.toUpload.forEach(item => {
|
|
451
|
-
const icon = item.action === 'create' ? '✨' : '📝';
|
|
452
|
-
console.log(` ${icon} [${item.id}] ${item.title}`);
|
|
453
|
-
console.log(` Type: ${item.type} | Action: ${item.action}`);
|
|
454
|
-
if (item.changes) {
|
|
455
|
-
item.changes.forEach(change => {
|
|
456
|
-
console.log(` • ${change}`);
|
|
457
|
-
});
|
|
458
|
-
}
|
|
459
|
-
});
|
|
460
|
-
console.log('');
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
// Conflicts
|
|
464
|
-
if (result.changes.conflicts.length > 0) {
|
|
465
|
-
console.log(chalk.red.bold('⚠️ Conflicts'));
|
|
466
|
-
result.changes.conflicts.forEach(conflict => {
|
|
467
|
-
console.log(` [${conflict.id}] ${conflict.title}`);
|
|
468
|
-
console.log(` Local: ${conflict.localChange}`);
|
|
469
|
-
console.log(` Remote: ${conflict.remoteChange}`);
|
|
470
|
-
console.log(` Resolution: ${conflict.resolution}`);
|
|
471
|
-
});
|
|
472
|
-
console.log('');
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// Summary statistics
|
|
476
|
-
console.log(chalk.cyan.bold('📈 Statistics'));
|
|
477
|
-
console.log('─'.repeat(50));
|
|
478
|
-
const summary = result.summary;
|
|
479
|
-
console.log(`Downloaded: ${chalk.green(summary.downloaded)} items`);
|
|
480
|
-
console.log(`Uploaded: ${chalk.blue(summary.uploaded)} items`);
|
|
481
|
-
if (summary.conflicts > 0) {
|
|
482
|
-
console.log(`Conflicts: ${chalk.red(summary.conflicts)} items`);
|
|
483
|
-
}
|
|
484
|
-
if (summary.errors > 0) {
|
|
485
|
-
console.log(`Errors: ${chalk.red(summary.errors)} items`);
|
|
486
|
-
}
|
|
487
|
-
if (summary.skipped > 0) {
|
|
488
|
-
console.log(`Skipped: ${chalk.yellow(summary.skipped)} items`);
|
|
489
|
-
}
|
|
490
|
-
console.log('');
|
|
491
|
-
|
|
492
|
-
// Synced files
|
|
493
|
-
if (result.syncedFiles && result.syncedFiles.length > 0) {
|
|
494
|
-
console.log(chalk.gray.bold('📁 Synced Files'));
|
|
495
|
-
result.syncedFiles.forEach(file => {
|
|
496
|
-
console.log(` • ${file}`);
|
|
497
|
-
});
|
|
498
|
-
console.log('');
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// Action required
|
|
502
|
-
if (result.changes.conflicts.length > 0) {
|
|
503
|
-
console.log(chalk.yellow.bold('⚡ Action Required'));
|
|
504
|
-
console.log('Please resolve conflicts manually before next sync.');
|
|
505
|
-
console.log('Run with --resolve-conflicts to see resolution options.\n');
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
// Footer
|
|
509
|
-
if (result.dryRun) {
|
|
510
|
-
console.log(chalk.yellow('This was a dry run. Use --apply to perform actual sync.'));
|
|
511
|
-
} else {
|
|
512
|
-
console.log(chalk.green('✅ Sync completed successfully!'));
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
static parseArguments(args = process.argv) {
|
|
517
|
-
const options = {};
|
|
518
|
-
|
|
519
|
-
args.forEach((arg, index) => {
|
|
520
|
-
if (arg === '--direction' && args[index + 1]) {
|
|
521
|
-
options.direction = args[index + 1];
|
|
522
|
-
} else if (arg === '--format' && args[index + 1]) {
|
|
523
|
-
options.format = args[index + 1];
|
|
524
|
-
} else if (arg === '--dry-run') {
|
|
525
|
-
options.dryRun = true;
|
|
526
|
-
} else if (arg === '--apply') {
|
|
527
|
-
options.dryRun = false;
|
|
528
|
-
} else if (arg === '--pull') {
|
|
529
|
-
options.direction = 'pull';
|
|
530
|
-
} else if (arg === '--push') {
|
|
531
|
-
options.direction = 'push';
|
|
532
|
-
} else if (arg === '--json') {
|
|
533
|
-
options.format = 'json';
|
|
534
|
-
} else if (arg === '--silent' || arg === '-s') {
|
|
535
|
-
options.silent = true;
|
|
536
|
-
}
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
return options;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// Run if called directly
|
|
544
|
-
if (require.main === module) {
|
|
545
|
-
const options = AzureSync.parseArguments();
|
|
546
|
-
const sync = new AzureSync(options);
|
|
547
|
-
|
|
548
|
-
sync.syncWorkItems()
|
|
549
|
-
.then(() => {
|
|
550
|
-
if (sync.client) {
|
|
551
|
-
const stats = sync.client.getCacheStats();
|
|
552
|
-
if (!options.silent && process.env.DEBUG) {
|
|
553
|
-
console.log(chalk.dim(`\nCache stats: ${JSON.stringify(stats)}`));
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
})
|
|
557
|
-
.catch(error => {
|
|
558
|
-
console.error('Error:', error.message);
|
|
559
|
-
process.exit(1);
|
|
560
|
-
});
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
module.exports = AzureSync;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# Azure Script - Wrapper for Node.js implementation
|
|
4
|
-
# This wrapper maintains backward compatibility while delegating to the Node.js version
|
|
5
|
-
|
|
6
|
-
# Get the directory of this script
|
|
7
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
-
SCRIPT_NAME="$(basename "$0" .sh)"
|
|
9
|
-
|
|
10
|
-
# Check if Node.js is available and the .js file exists
|
|
11
|
-
if command -v node >/dev/null 2>&1 && [ -f "$SCRIPT_DIR/$SCRIPT_NAME.js" ]; then
|
|
12
|
-
# Use the Node.js implementation
|
|
13
|
-
node "$SCRIPT_DIR/$SCRIPT_NAME.js" "$@"
|
|
14
|
-
exit $?
|
|
15
|
-
else
|
|
16
|
-
# Fallback message
|
|
17
|
-
echo "⚠️ Node.js not found or $SCRIPT_NAME.js missing"
|
|
18
|
-
echo "Please ensure Node.js is installed and all files are present"
|
|
19
|
-
exit 1
|
|
20
|
-
fi
|