claude-autopm 1.18.0 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +159 -0
  2. package/autopm/.claude/agents/core/mcp-manager.md +1 -1
  3. package/autopm/.claude/commands/pm/context.md +11 -0
  4. package/autopm/.claude/commands/pm/epic-decompose.md +25 -2
  5. package/autopm/.claude/commands/pm/epic-oneshot.md +13 -0
  6. package/autopm/.claude/commands/pm/epic-start.md +19 -0
  7. package/autopm/.claude/commands/pm/epic-sync-modular.md +10 -10
  8. package/autopm/.claude/commands/pm/epic-sync.md +14 -14
  9. package/autopm/.claude/commands/pm/issue-start.md +50 -5
  10. package/autopm/.claude/commands/pm/issue-sync.md +15 -15
  11. package/autopm/.claude/commands/pm/what-next.md +11 -0
  12. package/autopm/.claude/mcp/MCP-REGISTRY.md +1 -1
  13. package/autopm/.claude/scripts/azure/active-work.js +2 -2
  14. package/autopm/.claude/scripts/azure/blocked.js +13 -13
  15. package/autopm/.claude/scripts/azure/daily.js +1 -1
  16. package/autopm/.claude/scripts/azure/dashboard.js +1 -1
  17. package/autopm/.claude/scripts/azure/feature-list.js +2 -2
  18. package/autopm/.claude/scripts/azure/feature-status.js +1 -1
  19. package/autopm/.claude/scripts/azure/next-task.js +1 -1
  20. package/autopm/.claude/scripts/azure/search.js +1 -1
  21. package/autopm/.claude/scripts/azure/setup.js +15 -15
  22. package/autopm/.claude/scripts/azure/sprint-report.js +2 -2
  23. package/autopm/.claude/scripts/azure/sync.js +1 -1
  24. package/autopm/.claude/scripts/azure/us-list.js +1 -1
  25. package/autopm/.claude/scripts/azure/us-status.js +1 -1
  26. package/autopm/.claude/scripts/azure/validate.js +13 -13
  27. package/autopm/.claude/scripts/lib/frontmatter-utils.sh +42 -7
  28. package/autopm/.claude/scripts/lib/logging-utils.sh +20 -16
  29. package/autopm/.claude/scripts/lib/validation-utils.sh +1 -1
  30. package/autopm/.claude/scripts/pm/context.js +338 -0
  31. package/autopm/.claude/scripts/pm/issue-sync/format-comment.sh +3 -3
  32. package/autopm/.claude/scripts/pm/lib/README.md +85 -0
  33. package/autopm/.claude/scripts/pm/lib/logger.js +78 -0
  34. package/autopm/.claude/scripts/pm/next.js +25 -1
  35. package/autopm/.claude/scripts/pm/what-next.js +660 -0
  36. package/bin/autopm.js +25 -0
  37. package/package.json +1 -1
  38. package/lib/agentExecutor.js.deprecated +0 -101
  39. package/lib/azure/cache.js +0 -80
  40. package/lib/azure/client.js +0 -77
  41. package/lib/azure/formatter.js +0 -177
  42. package/lib/commandHelpers.js +0 -177
  43. package/lib/context/manager.js +0 -290
  44. package/lib/documentation/manager.js +0 -528
  45. package/lib/github/workflow-manager.js +0 -546
  46. package/lib/helpers/azure-batch-api.js +0 -133
  47. package/lib/helpers/azure-cache-manager.js +0 -287
  48. package/lib/helpers/azure-parallel-processor.js +0 -158
  49. package/lib/helpers/azure-work-item-create.js +0 -278
  50. package/lib/helpers/gh-issue-create.js +0 -250
  51. package/lib/helpers/interactive-prompt.js +0 -336
  52. package/lib/helpers/output-manager.js +0 -335
  53. package/lib/helpers/progress-indicator.js +0 -258
  54. package/lib/performance/benchmarker.js +0 -429
  55. package/lib/pm/epic-decomposer.js +0 -273
  56. package/lib/pm/epic-syncer.js +0 -221
  57. package/lib/prdMetadata.js +0 -270
  58. package/lib/providers/azure/index.js +0 -234
  59. package/lib/providers/factory.js +0 -87
  60. package/lib/providers/github/index.js +0 -204
  61. package/lib/providers/interface.js +0 -73
  62. package/lib/python/scaffold-manager.js +0 -576
  63. package/lib/react/scaffold-manager.js +0 -745
  64. package/lib/regression/analyzer.js +0 -578
  65. package/lib/release/manager.js +0 -324
  66. package/lib/tailwind/manager.js +0 -486
  67. package/lib/traefik/manager.js +0 -484
  68. package/lib/utils/colors.js +0 -126
  69. package/lib/utils/config.js +0 -317
  70. package/lib/utils/filesystem.js +0 -316
  71. package/lib/utils/logger.js +0 -135
  72. package/lib/utils/prompts.js +0 -294
  73. package/lib/utils/shell.js +0 -237
  74. package/lib/validators/email-validator.js +0 -337
  75. package/lib/workflow/manager.js +0 -449
@@ -1,546 +0,0 @@
1
- /**
2
- * GitHub Workflow Manager
3
- * Centralized GitHub Actions workflow management functionality
4
- */
5
-
6
- const fs = require('fs').promises;
7
- const path = require('path');
8
-
9
- /**
10
- * Configuration
11
- */
12
- const CONFIG = {
13
- directories: {
14
- workflows: '.github/workflows'
15
- },
16
- defaults: {
17
- os: 'ubuntu-latest',
18
- nodeVersion: '18.x'
19
- },
20
- fileExtensions: ['.yml', '.yaml']
21
- };
22
-
23
- /**
24
- * Workflow templates
25
- */
26
- const TEMPLATES = {
27
- node: {
28
- name: 'Node.js CI',
29
- content: `name: Node.js CI
30
-
31
- on:
32
- push:
33
- branches: [ main, develop ]
34
- pull_request:
35
- branches: [ main ]
36
-
37
- jobs:
38
- test:
39
- runs-on: ubuntu-latest
40
-
41
- strategy:
42
- matrix:
43
- node-version: [16.x, 18.x, 20.x]
44
-
45
- steps:
46
- - uses: actions/checkout@v3
47
- - name: Use Node.js \${{ matrix.node-version }}
48
- uses: actions/setup-node@v3
49
- with:
50
- node-version: \${{ matrix.node-version }}
51
- cache: 'npm'
52
- - run: npm ci
53
- - run: npm test
54
- - run: npm run build --if-present`
55
- },
56
- python: {
57
- name: 'Python CI',
58
- content: `name: Python CI
59
-
60
- on:
61
- push:
62
- branches: [ main, develop ]
63
- pull_request:
64
- branches: [ main ]
65
-
66
- jobs:
67
- test:
68
- runs-on: ubuntu-latest
69
-
70
- strategy:
71
- matrix:
72
- python-version: ["3.8", "3.9", "3.10", "3.11"]
73
-
74
- steps:
75
- - uses: actions/checkout@v3
76
- - name: Set up Python \${{ matrix.python-version }}
77
- uses: actions/setup-python@v4
78
- with:
79
- python-version: \${{ matrix.python-version }}
80
- - name: Install dependencies
81
- run: |
82
- python -m pip install --upgrade pip
83
- pip install pytest
84
- if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
85
- - name: Test with pytest
86
- run: |
87
- pytest`
88
- },
89
- docker: {
90
- name: 'Docker Build',
91
- content: `name: Docker Build
92
-
93
- on:
94
- push:
95
- branches: [ main ]
96
- tags: [ 'v*' ]
97
-
98
- jobs:
99
- docker:
100
- runs-on: ubuntu-latest
101
-
102
- steps:
103
- - uses: actions/checkout@v3
104
-
105
- - name: Set up Docker Buildx
106
- uses: docker/setup-buildx-action@v2
107
-
108
- - name: Log in to Docker Hub
109
- uses: docker/login-action@v2
110
- with:
111
- username: \${{ secrets.DOCKER_USERNAME }}
112
- password: \${{ secrets.DOCKER_TOKEN }}
113
-
114
- - name: Build and push
115
- uses: docker/build-push-action@v4
116
- with:
117
- context: .
118
- push: true
119
- tags: user/app:latest`
120
- }
121
- };
122
-
123
- class GitHubWorkflowManager {
124
- constructor(projectRoot = process.cwd()) {
125
- this.projectRoot = projectRoot;
126
- this.workflowsDir = path.join(projectRoot, CONFIG.directories.workflows);
127
- }
128
-
129
- /**
130
- * Creates a new workflow
131
- */
132
- async createWorkflow(name, options = {}) {
133
- await fs.mkdir(this.workflowsDir, { recursive: true });
134
-
135
- const workflow = {
136
- name: name.charAt(0).toUpperCase() + name.slice(1),
137
- on: options.trigger || ['push', 'pull_request'],
138
- jobs: {
139
- build: {
140
- 'runs-on': options.os || CONFIG.defaults.os,
141
- steps: [
142
- { uses: 'actions/checkout@v3' },
143
- { name: 'Setup', run: 'echo "Setting up..."' },
144
- { name: 'Build', run: 'echo "Building..."' },
145
- { name: 'Test', run: 'echo "Testing..."' }
146
- ]
147
- }
148
- }
149
- };
150
-
151
- const workflowPath = path.join(this.workflowsDir, `${name}.yml`);
152
- await fs.writeFile(workflowPath, this.generateYAML(workflow));
153
-
154
- return {
155
- path: workflowPath,
156
- name: workflow.name,
157
- triggers: Array.isArray(workflow.on) ? workflow.on : [workflow.on]
158
- };
159
- }
160
-
161
- /**
162
- * Creates a test workflow
163
- */
164
- async createTestWorkflow(options = {}) {
165
- await fs.mkdir(this.workflowsDir, { recursive: true });
166
-
167
- const testWorkflow = {
168
- name: 'Tests',
169
- on: {
170
- push: {
171
- branches: ['main', 'develop']
172
- },
173
- pull_request: {
174
- branches: ['main']
175
- }
176
- },
177
- jobs: {
178
- test: {
179
- 'runs-on': options.os || CONFIG.defaults.os,
180
- steps: [
181
- { uses: 'actions/checkout@v3' },
182
- {
183
- name: 'Setup Node.js',
184
- uses: 'actions/setup-node@v3',
185
- with: {
186
- 'node-version': options.nodeVersion || CONFIG.defaults.nodeVersion,
187
- cache: 'npm'
188
- }
189
- },
190
- { name: 'Install dependencies', run: 'npm ci' },
191
- { name: 'Run tests', run: 'npm test' },
192
- {
193
- name: 'Upload coverage',
194
- if: 'success()',
195
- uses: 'codecov/codecov-action@v3'
196
- }
197
- ]
198
- }
199
- }
200
- };
201
-
202
- const workflowPath = path.join(this.workflowsDir, 'test.yml');
203
- await fs.writeFile(workflowPath, this.generateYAML(testWorkflow));
204
-
205
- return {
206
- path: workflowPath,
207
- name: testWorkflow.name
208
- };
209
- }
210
-
211
- /**
212
- * Creates a release workflow
213
- */
214
- async createReleaseWorkflow(options = {}) {
215
- await fs.mkdir(this.workflowsDir, { recursive: true });
216
-
217
- let trigger = {};
218
- if (options.trigger === 'tag') {
219
- trigger = {
220
- push: {
221
- tags: ['v*']
222
- }
223
- };
224
- } else {
225
- trigger = {
226
- release: {
227
- types: ['created']
228
- }
229
- };
230
- }
231
-
232
- const releaseWorkflow = {
233
- name: 'Release',
234
- on: trigger,
235
- jobs: {
236
- release: {
237
- 'runs-on': CONFIG.defaults.os,
238
- steps: [
239
- { uses: 'actions/checkout@v3' },
240
- {
241
- name: 'Setup Node.js',
242
- uses: 'actions/setup-node@v3',
243
- with: {
244
- 'node-version': CONFIG.defaults.nodeVersion,
245
- 'registry-url': 'https://registry.npmjs.org/'
246
- }
247
- },
248
- { name: 'Install dependencies', run: 'npm ci' },
249
- { name: 'Build', run: 'npm run build --if-present' },
250
- { name: 'Test', run: 'npm test' },
251
- {
252
- name: 'Publish to npm',
253
- if: options.publish !== false,
254
- run: 'npm publish',
255
- env: {
256
- NODE_AUTH_TOKEN: '${{ secrets.NPM_TOKEN }}'
257
- }
258
- },
259
- {
260
- name: 'Create GitHub Release',
261
- uses: 'softprops/action-gh-release@v1',
262
- if: "startsWith(github.ref, 'refs/tags/')",
263
- with: {
264
- files: 'dist/*'
265
- }
266
- }
267
- ]
268
- }
269
- }
270
- };
271
-
272
- const workflowPath = path.join(this.workflowsDir, 'release.yml');
273
- await fs.writeFile(workflowPath, this.generateYAML(releaseWorkflow));
274
-
275
- return {
276
- path: workflowPath,
277
- name: releaseWorkflow.name,
278
- trigger: options.trigger
279
- };
280
- }
281
-
282
- /**
283
- * Applies a template
284
- */
285
- async applyTemplate(templateName) {
286
- const template = TEMPLATES[templateName];
287
-
288
- if (!template) {
289
- throw new Error(`Unknown template: ${templateName}`);
290
- }
291
-
292
- await fs.mkdir(this.workflowsDir, { recursive: true });
293
-
294
- const filename = `${templateName}.yml`;
295
- const workflowPath = path.join(this.workflowsDir, filename);
296
- await fs.writeFile(workflowPath, template.content);
297
-
298
- return {
299
- path: workflowPath,
300
- template: templateName,
301
- name: template.name
302
- };
303
- }
304
-
305
- /**
306
- * Lists available templates
307
- */
308
- getTemplates() {
309
- return Object.entries(TEMPLATES).map(([key, template]) => ({
310
- key,
311
- name: template.name,
312
- description: this.getTemplateDescription(key)
313
- }));
314
- }
315
-
316
- /**
317
- * Lists existing workflows
318
- */
319
- async listWorkflows() {
320
- try {
321
- const files = await fs.readdir(this.workflowsDir);
322
- const workflows = [];
323
-
324
- for (const file of files) {
325
- if (CONFIG.fileExtensions.some(ext => file.endsWith(ext))) {
326
- const content = await fs.readFile(path.join(this.workflowsDir, file), 'utf8');
327
- workflows.push({
328
- file,
329
- name: this.extractWorkflowName(content),
330
- triggers: this.extractTriggers(content)
331
- });
332
- }
333
- }
334
-
335
- return workflows;
336
- } catch (error) {
337
- return [];
338
- }
339
- }
340
-
341
- /**
342
- * Validates workflows
343
- */
344
- async validateWorkflows() {
345
- try {
346
- const files = await fs.readdir(this.workflowsDir);
347
- const results = [];
348
-
349
- for (const file of files) {
350
- if (CONFIG.fileExtensions.some(ext => file.endsWith(ext))) {
351
- const content = await fs.readFile(path.join(this.workflowsDir, file), 'utf8');
352
- const issues = this.validateWorkflow(content);
353
- results.push({
354
- file,
355
- valid: issues.length === 0,
356
- issues
357
- });
358
- }
359
- }
360
-
361
- return results;
362
- } catch (error) {
363
- return [];
364
- }
365
- }
366
-
367
- /**
368
- * Updates a workflow
369
- */
370
- async updateWorkflow(workflowName, updates = {}) {
371
- const workflowPath = path.join(this.workflowsDir, `${workflowName}.yml`);
372
- let content = await fs.readFile(workflowPath, 'utf8');
373
-
374
- // Add job if requested
375
- if (updates.addJob) {
376
- const jobName = updates.addJob;
377
- const jobDefinition = `
378
- ${jobName}:
379
- runs-on: ubuntu-latest
380
- steps:
381
- - uses: actions/checkout@v3
382
- - name: ${jobName}
383
- run: echo "Running ${jobName}"`;
384
-
385
- // Add before the last line
386
- const lines = content.split('\n');
387
- const jobsIndex = lines.findIndex(l => l.startsWith('jobs:'));
388
- if (jobsIndex >= 0) {
389
- // Find the end of jobs section
390
- let insertIndex = lines.length;
391
- for (let i = jobsIndex + 1; i < lines.length; i++) {
392
- if (!lines[i].startsWith(' ')) {
393
- insertIndex = i;
394
- break;
395
- }
396
- }
397
- lines.splice(insertIndex, 0, jobDefinition);
398
- content = lines.join('\n');
399
- }
400
- }
401
-
402
- await fs.writeFile(workflowPath, content);
403
-
404
- return {
405
- path: workflowPath,
406
- updated: true,
407
- changes: updates
408
- };
409
- }
410
-
411
- /**
412
- * Validates workflow content
413
- */
414
- validateWorkflow(content) {
415
- const issues = [];
416
- const lines = content.split('\n');
417
-
418
- // Check for required fields
419
- if (!content.includes('name:')) {
420
- issues.push('Missing workflow name');
421
- }
422
-
423
- if (!content.includes('on:')) {
424
- issues.push('Missing trigger events (on:)');
425
- }
426
-
427
- if (!content.includes('jobs:')) {
428
- issues.push('Missing jobs section');
429
- }
430
-
431
- // Check each job has runs-on
432
- const jobsIndex = lines.findIndex(l => l.trim().startsWith('jobs:'));
433
- if (jobsIndex >= 0) {
434
- let currentJob = null;
435
- let hasRunsOn = false;
436
-
437
- for (let i = jobsIndex + 1; i < lines.length; i++) {
438
- const line = lines[i];
439
- const trimmed = line.trim();
440
-
441
- // New job starts
442
- if (line.match(/^ \w+:/)) {
443
- if (currentJob && !hasRunsOn) {
444
- issues.push(`Job '${currentJob}' missing runs-on`);
445
- }
446
- currentJob = trimmed.replace(':', '');
447
- hasRunsOn = false;
448
- }
449
-
450
- // Check for runs-on
451
- if (trimmed.startsWith('runs-on:')) {
452
- hasRunsOn = true;
453
- }
454
-
455
- // End of jobs section
456
- if (line.length > 0 && !line.startsWith(' ')) {
457
- break;
458
- }
459
- }
460
-
461
- // Check last job
462
- if (currentJob && !hasRunsOn) {
463
- issues.push(`Job '${currentJob}' missing runs-on`);
464
- }
465
- }
466
-
467
- return issues;
468
- }
469
-
470
- /**
471
- * Extracts workflow name from content
472
- */
473
- extractWorkflowName(content) {
474
- const match = content.match(/name:\s*(.+)/);
475
- return match ? match[1].trim() : 'Unnamed';
476
- }
477
-
478
- /**
479
- * Extracts triggers from workflow content
480
- */
481
- extractTriggers(content) {
482
- const match = content.match(/on:\s*(.+)/);
483
- if (!match) return 'None';
484
-
485
- const triggerLine = match[1].trim();
486
- if (triggerLine.startsWith('[')) {
487
- return triggerLine.slice(1, -1);
488
- }
489
- return triggerLine;
490
- }
491
-
492
- /**
493
- * Gets template description
494
- */
495
- getTemplateDescription(name) {
496
- const descriptions = {
497
- node: 'Node.js CI/CD with matrix testing',
498
- python: 'Python testing with pytest',
499
- docker: 'Docker build and push to registry'
500
- };
501
- return descriptions[name] || 'Workflow template';
502
- }
503
-
504
- /**
505
- * Generates simple YAML
506
- */
507
- generateYAML(obj, indent = 0) {
508
- let yaml = '';
509
- const spaces = ' '.repeat(indent);
510
-
511
- for (const [key, value] of Object.entries(obj)) {
512
- if (value === null || value === undefined) {
513
- yaml += `${spaces}${key}:\n`;
514
- } else if (typeof value === 'string') {
515
- // Handle multi-line strings
516
- if (value.includes('\n')) {
517
- yaml += `${spaces}${key}: |\n`;
518
- value.split('\n').forEach(line => {
519
- yaml += `${spaces} ${line}\n`;
520
- });
521
- } else {
522
- yaml += `${spaces}${key}: ${value}\n`;
523
- }
524
- } else if (typeof value === 'boolean') {
525
- yaml += `${spaces}${key}: ${value}\n`;
526
- } else if (typeof value === 'object' && !Array.isArray(value)) {
527
- yaml += `${spaces}${key}:\n${this.generateYAML(value, indent + 1)}`;
528
- } else if (Array.isArray(value)) {
529
- yaml += `${spaces}${key}:\n`;
530
- for (const item of value) {
531
- if (typeof item === 'object') {
532
- yaml += `${spaces}- ${this.generateYAML(item, indent + 1).trim()}\n`;
533
- } else {
534
- yaml += `${spaces} - ${item}\n`;
535
- }
536
- }
537
- } else {
538
- yaml += `${spaces}${key}: ${value}\n`;
539
- }
540
- }
541
-
542
- return yaml;
543
- }
544
- }
545
-
546
- module.exports = GitHubWorkflowManager;
@@ -1,133 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Azure DevOps Batch API Helper
4
- * Optimizes API calls by batching multiple requests
5
- */
6
-
7
- const https = require('https');
8
-
9
- class AzureBatchAPI {
10
- constructor(org, project, pat) {
11
- this.org = org;
12
- this.project = project;
13
- this.pat = pat;
14
- this.baseUrl = `dev.azure.com/${org}/${project}/_apis`;
15
- this.batchSize = 200; // Azure DevOps batch limit
16
- }
17
-
18
- /**
19
- * Execute batch API requests
20
- * @param {Array} requests - Array of request objects
21
- * @returns {Promise<Array>} Array of responses
22
- */
23
- async executeBatch(requests) {
24
- if (!requests || requests.length === 0) {
25
- return [];
26
- }
27
-
28
- // Split into chunks if needed
29
- const chunks = this.chunkRequests(requests, this.batchSize);
30
- const results = [];
31
-
32
- for (const chunk of chunks) {
33
- const batchResults = await this.executeBatchChunk(chunk);
34
- results.push(...batchResults);
35
- }
36
-
37
- return results;
38
- }
39
-
40
- /**
41
- * Execute a single batch chunk
42
- * @private
43
- */
44
- async executeBatchChunk(requests) {
45
- const batchRequest = {
46
- requests: requests.map((req, index) => ({
47
- id: index.toString(),
48
- method: req.method || 'GET',
49
- url: `/${this.baseUrl}/${req.endpoint}?api-version=7.0`,
50
- headers: req.headers || {},
51
- body: req.body
52
- }))
53
- };
54
-
55
- return new Promise((resolve, reject) => {
56
- const options = {
57
- hostname: 'dev.azure.com',
58
- path: `/${this.org}/_apis/$batch?api-version=7.0`,
59
- method: 'POST',
60
- headers: {
61
- 'Authorization': `Basic ${Buffer.from(`:${this.pat}`).toString('base64')}`,
62
- 'Content-Type': 'application/json'
63
- }
64
- };
65
-
66
- const req = https.request(options, (res) => {
67
- let data = '';
68
- res.on('data', chunk => data += chunk);
69
- res.on('end', () => {
70
- try {
71
- const batchResponse = JSON.parse(data);
72
- const results = batchResponse.responses.map(r => {
73
- try {
74
- return JSON.parse(r.body);
75
- } catch {
76
- return r.body;
77
- }
78
- });
79
- resolve(results);
80
- } catch (error) {
81
- reject(error);
82
- }
83
- });
84
- });
85
-
86
- req.on('error', reject);
87
- req.write(JSON.stringify(batchRequest));
88
- req.end();
89
- });
90
- }
91
-
92
- /**
93
- * Chunk requests into batches
94
- * @private
95
- */
96
- chunkRequests(requests, size) {
97
- const chunks = [];
98
- for (let i = 0; i < requests.length; i += size) {
99
- chunks.push(requests.slice(i, i + size));
100
- }
101
- return chunks;
102
- }
103
-
104
- /**
105
- * Batch fetch work items
106
- */
107
- async batchFetchWorkItems(ids) {
108
- const requests = ids.map(id => ({
109
- endpoint: `wit/workitems/${id}`,
110
- method: 'GET'
111
- }));
112
-
113
- return this.executeBatch(requests);
114
- }
115
-
116
- /**
117
- * Batch update work items
118
- */
119
- async batchUpdateWorkItems(updates) {
120
- const requests = updates.map(update => ({
121
- endpoint: `wit/workitems/${update.id}`,
122
- method: 'PATCH',
123
- headers: {
124
- 'Content-Type': 'application/json-patch+json'
125
- },
126
- body: update.operations
127
- }));
128
-
129
- return this.executeBatch(requests);
130
- }
131
- }
132
-
133
- module.exports = AzureBatchAPI;