arcvision 0.2.12 → 0.2.15

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 (134) hide show
  1. package/ARCVISION_DIRECTORY_STRUCTURE.md +104 -0
  2. package/CLI_STRUCTURE.md +110 -0
  3. package/CONFIGURATION.md +119 -0
  4. package/IMPLEMENTATION_SUMMARY.md +99 -0
  5. package/README.md +149 -89
  6. package/architecture.authority.ledger.json +46 -0
  7. package/arcvision-0.2.3.tgz +0 -0
  8. package/arcvision-0.2.4.tgz +0 -0
  9. package/arcvision-0.2.5.tgz +0 -0
  10. package/arcvision.context.diff.json +2181 -0
  11. package/arcvision.context.json +1021 -0
  12. package/arcvision.context.v1.json +2163 -0
  13. package/arcvision.context.v2.json +2173 -0
  14. package/arcvision_context/README.md +93 -0
  15. package/arcvision_context/architecture.authority.ledger.json +83 -0
  16. package/arcvision_context/arcvision.context.json +6884 -0
  17. package/debug-cycle-detection.js +56 -0
  18. package/dist/index.js +1626 -25
  19. package/docs/ENHANCED_ACCURACY_SAFETY_PROTOCOL.md +172 -0
  20. package/docs/accuracy-enhancement-artifacts/enhanced-validation-config.json +98 -0
  21. package/docs/acig-robustness-guide.md +164 -0
  22. package/docs/authoritative-gate-implementation.md +168 -0
  23. package/docs/cli-strengthening-summary.md +232 -0
  24. package/docs/invariant-system-summary.md +100 -0
  25. package/docs/invariant-system.md +112 -0
  26. package/generate_large_test.js +42 -0
  27. package/large_test_repo.json +1 -0
  28. package/output1.json +2163 -0
  29. package/output2.json +2163 -0
  30. package/package.json +46 -36
  31. package/scan_calcom_report.txt +0 -0
  32. package/scan_leafmint_report.txt +0 -0
  33. package/scan_output.txt +0 -0
  34. package/scan_trigger_report.txt +0 -0
  35. package/schema/arcvision_context_schema_v1.json +136 -1
  36. package/src/arcvision-guard.js +433 -0
  37. package/src/core/authority-core-detector.js +382 -0
  38. package/src/core/authority-ledger.js +300 -0
  39. package/src/core/blastRadius.js +299 -0
  40. package/src/core/call-resolver.js +196 -0
  41. package/src/core/change-evaluator.js +509 -0
  42. package/src/core/change-evaluator.js.backup +424 -0
  43. package/src/core/change-evaluator.ts +285 -0
  44. package/src/core/chunked-uploader.js +180 -0
  45. package/src/core/circular-dependency-detector.js +404 -0
  46. package/src/core/cli-error-handler.js +458 -0
  47. package/src/core/cli-validator.js +458 -0
  48. package/src/core/compression.js +64 -0
  49. package/src/core/context_builder.js +741 -0
  50. package/src/core/dependency-manager.js +134 -0
  51. package/src/core/di-detector.js +202 -0
  52. package/src/core/diff-analyzer.js +76 -0
  53. package/src/core/example-invariants.js +135 -0
  54. package/src/core/failure-mode-synthesizer.js +341 -0
  55. package/src/core/invariant-analyzer.js +294 -0
  56. package/src/core/invariant-detector.js +548 -0
  57. package/src/core/invariant-enforcer.js +171 -0
  58. package/src/core/invariant-evaluation-utils.js +172 -0
  59. package/src/core/invariant-hooks.js +152 -0
  60. package/src/core/invariant-integration-example.js +186 -0
  61. package/src/core/invariant-registry.js +298 -0
  62. package/src/core/invariant-registry.ts +100 -0
  63. package/src/core/invariant-types.js +66 -0
  64. package/src/core/invariants-index.js +88 -0
  65. package/src/core/method-tracker.js +170 -0
  66. package/src/core/override-handler.js +304 -0
  67. package/src/core/ownership-resolver.js +227 -0
  68. package/src/core/parser-enhanced.js +80 -0
  69. package/src/core/parser.js +610 -0
  70. package/src/core/path-resolver.js +240 -0
  71. package/src/core/pattern-matcher.js +246 -0
  72. package/src/core/progress-tracker.js +71 -0
  73. package/src/core/react-nextjs-detector.js +245 -0
  74. package/src/core/readme-generator.js +167 -0
  75. package/src/core/retry-handler.js +57 -0
  76. package/src/core/scanner.js +289 -0
  77. package/src/core/semantic-analyzer.js +204 -0
  78. package/src/core/structural-context-owner.js +442 -0
  79. package/src/core/symbol-indexer.js +164 -0
  80. package/src/core/tsconfig-utils.js +73 -0
  81. package/src/core/type-analyzer.js +272 -0
  82. package/src/core/watcher.js +18 -0
  83. package/src/core/workspace-scanner.js +88 -0
  84. package/src/engine/context_builder.js +280 -0
  85. package/src/engine/context_sorter.js +59 -0
  86. package/src/engine/context_validator.js +200 -0
  87. package/src/engine/id-generator.js +16 -0
  88. package/src/engine/pass1_facts.js +260 -0
  89. package/src/engine/pass2_semantics.js +333 -0
  90. package/src/engine/pass3_lifter.js +99 -0
  91. package/src/engine/pass4_signals.js +201 -0
  92. package/src/index.js +830 -0
  93. package/src/plugins/express-plugin.js +48 -0
  94. package/src/plugins/plugin-manager.js +58 -0
  95. package/src/plugins/react-plugin.js +54 -0
  96. package/temp_original.js +0 -0
  97. package/test/determinism-test.js +83 -0
  98. package/test-authoritative-context.js +53 -0
  99. package/test-real-authoritative-context.js +118 -0
  100. package/test-upload-enhancements.js +111 -0
  101. package/test_repos/allowed-clean-architecture/.arcvision/invariants.json +57 -0
  102. package/test_repos/allowed-clean-architecture/adapters/controllers/UserController.js +95 -0
  103. package/test_repos/allowed-clean-architecture/adapters/http/HttpServer.js +78 -0
  104. package/test_repos/allowed-clean-architecture/application/dtos/CreateUserRequest.js +37 -0
  105. package/test_repos/allowed-clean-architecture/application/services/UserService.js +61 -0
  106. package/test_repos/allowed-clean-architecture/arcvision_context/README.md +93 -0
  107. package/test_repos/allowed-clean-architecture/arcvision_context/arcvision.context.json +2796 -0
  108. package/test_repos/allowed-clean-architecture/domain/interfaces/UserRepository.js +25 -0
  109. package/test_repos/allowed-clean-architecture/domain/models/User.js +39 -0
  110. package/test_repos/allowed-clean-architecture/index.js +45 -0
  111. package/test_repos/allowed-clean-architecture/infrastructure/database/DatabaseConnection.js +56 -0
  112. package/test_repos/allowed-clean-architecture/infrastructure/repositories/InMemoryUserRepository.js +61 -0
  113. package/test_repos/allowed-clean-architecture/package.json +15 -0
  114. package/test_repos/blocked-legacy-monolith/.arcvision/invariants.json +78 -0
  115. package/test_repos/blocked-legacy-monolith/arcvision_context/README.md +93 -0
  116. package/test_repos/blocked-legacy-monolith/arcvision_context/arcvision.context.json +2882 -0
  117. package/test_repos/blocked-legacy-monolith/database/dbConnection.js +35 -0
  118. package/test_repos/blocked-legacy-monolith/index.js +38 -0
  119. package/test_repos/blocked-legacy-monolith/modules/emailService.js +31 -0
  120. package/test_repos/blocked-legacy-monolith/modules/paymentProcessor.js +37 -0
  121. package/test_repos/blocked-legacy-monolith/package.json +15 -0
  122. package/test_repos/blocked-legacy-monolith/shared/utils.js +19 -0
  123. package/test_repos/blocked-legacy-monolith/utils/helpers.js +23 -0
  124. package/test_repos/risky-microservices-concerns/.arcvision/invariants.json +69 -0
  125. package/test_repos/risky-microservices-concerns/arcvision_context/README.md +93 -0
  126. package/test_repos/risky-microservices-concerns/arcvision_context/arcvision.context.json +3070 -0
  127. package/test_repos/risky-microservices-concerns/common/utils.js +77 -0
  128. package/test_repos/risky-microservices-concerns/gateways/apiGateway.js +84 -0
  129. package/test_repos/risky-microservices-concerns/index.js +20 -0
  130. package/test_repos/risky-microservices-concerns/libs/deprecatedHelper.js +36 -0
  131. package/test_repos/risky-microservices-concerns/package.json +15 -0
  132. package/test_repos/risky-microservices-concerns/services/orderService.js +42 -0
  133. package/test_repos/risky-microservices-concerns/services/userService.js +48 -0
  134. package/verify_engine.js +116 -0
@@ -0,0 +1,245 @@
1
+ /**
2
+ * React/Next.js Pattern Detector
3
+ *
4
+ * Detects framework-specific patterns including:
5
+ * - Component composition (JSX usage)
6
+ * - Server/Client component boundaries
7
+ * - API route dependencies
8
+ * - Middleware dependencies
9
+ * - Next.js specific imports (Image, Link, etc.)
10
+ */
11
+
12
+ const traverse = require('@babel/traverse').default;
13
+
14
+ /**
15
+ * Detect JSX component usage
16
+ * @param {Object} ast - Babel AST
17
+ * @returns {Array} Array of component usages
18
+ */
19
+ function detectComponentUsage(ast) {
20
+ const componentUsages = [];
21
+
22
+ if (!ast) return componentUsages;
23
+
24
+ traverse(ast, {
25
+ JSXElement(path) {
26
+ const openingElement = path.node.openingElement;
27
+ let componentName = null;
28
+
29
+ // Simple component: <Button />
30
+ if (openingElement.name.type === 'JSXIdentifier') {
31
+ componentName = openingElement.name.name;
32
+
33
+ // Only track components (start with uppercase)
34
+ if (/^[A-Z]/.test(componentName)) {
35
+ componentUsages.push({
36
+ component: componentName,
37
+ type: 'jsx_component',
38
+ loc: path.node.loc
39
+ });
40
+ }
41
+ }
42
+
43
+ // Member expression: <Icons.Check />
44
+ else if (openingElement.name.type === 'JSXMemberExpression') {
45
+ const object = openingElement.name.object.name;
46
+ const property = openingElement.name.property.name;
47
+ componentName = `${object}.${property}`;
48
+
49
+ componentUsages.push({
50
+ component: componentName,
51
+ type: 'jsx_member_component',
52
+ loc: path.node.loc
53
+ });
54
+ }
55
+ }
56
+ });
57
+
58
+ return componentUsages;
59
+ }
60
+
61
+ /**
62
+ * Detect server/client component boundaries
63
+ * @param {string} content - File content as string
64
+ * @returns {Object} Boundary markers
65
+ */
66
+ function detectServerClientBoundaries(content) {
67
+ const boundaries = {
68
+ isClientComponent: false,
69
+ isServerComponent: false,
70
+ isServerAction: false
71
+ };
72
+
73
+ if (!content) return boundaries;
74
+
75
+ // Check for 'use client' directive
76
+ if (/['"]use client['"]/.test(content)) {
77
+ boundaries.isClientComponent = true;
78
+ }
79
+
80
+ // Check for 'use server' directive
81
+ if (/['"]use server['"]/.test(content)) {
82
+ boundaries.isServerAction = true;
83
+ }
84
+
85
+ // Server components are the default in Next.js App Router
86
+ // If no 'use client', it's a server component
87
+ if (!boundaries.isClientComponent && !boundaries.isServerAction) {
88
+ boundaries.isServerComponent = true;
89
+ }
90
+
91
+ return boundaries;
92
+ }
93
+
94
+ /**
95
+ * Detect API route dependencies
96
+ * @param {Object} ast - Babel AST
97
+ * @returns {Array} Array of API route dependencies
98
+ */
99
+ function detectAPIRouteDependencies(ast) {
100
+ const apiDeps = [];
101
+
102
+ if (!ast) return apiDeps;
103
+
104
+ traverse(ast, {
105
+ // Detect Next.js API route handlers: export async function GET/POST/etc
106
+ ExportNamedDeclaration(path) {
107
+ const node = path.node;
108
+
109
+ if (node.declaration && node.declaration.type === 'FunctionDeclaration') {
110
+ const funcName = node.declaration.id ? node.declaration.id.name : null;
111
+
112
+ // Check if it's a Next.js route handler
113
+ if (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'].includes(funcName)) {
114
+ apiDeps.push({
115
+ handler: funcName,
116
+ type: 'api_route_handler',
117
+ loc: node.loc
118
+ });
119
+ }
120
+ }
121
+ },
122
+
123
+ // Detect fetch calls and database queries within API routes
124
+ CallExpression(path) {
125
+ const callee = path.node.callee;
126
+
127
+ // Database queries
128
+ if (callee.type === 'MemberExpression') {
129
+ const objectName = callee.object.name;
130
+ const methodName = callee.property.name || callee.property.value;
131
+
132
+ // Supabase queries
133
+ if (objectName === 'supabase' || /supabase/i.test(objectName)) {
134
+ apiDeps.push({
135
+ service: 'supabase',
136
+ method: methodName,
137
+ type: 'database_query',
138
+ loc: path.node.loc
139
+ });
140
+ }
141
+
142
+ // Prisma queries
143
+ if (objectName === 'prisma' || /prisma/i.test(objectName)) {
144
+ apiDeps.push({
145
+ service: 'prisma',
146
+ method: methodName,
147
+ type: 'database_query',
148
+ loc: path.node.loc
149
+ });
150
+ }
151
+ }
152
+ }
153
+ });
154
+
155
+ return apiDeps;
156
+ }
157
+
158
+ /**
159
+ * Detect middleware dependencies
160
+ * @param {Object} ast - Babel AST
161
+ * @param {string} filePath - File path to check if it's middleware
162
+ * @returns {Array} Array of middleware dependencies
163
+ */
164
+ function detectMiddlewareDependencies(ast, filePath = '') {
165
+ const middlewareDeps = [];
166
+
167
+ // Check if this is a middleware file
168
+ const isMiddleware = /middleware\.(ts|js)$/.test(filePath);
169
+
170
+ if (!isMiddleware || !ast) return middlewareDeps;
171
+
172
+ traverse(ast, {
173
+ // Detect middleware function export
174
+ ExportNamedDeclaration(path) {
175
+ const node = path.node;
176
+
177
+ if (node.declaration && node.declaration.type === 'FunctionDeclaration') {
178
+ const funcName = node.declaration.id ? node.declaration.id.name : null;
179
+
180
+ if (funcName === 'middleware') {
181
+ middlewareDeps.push({
182
+ function: funcName,
183
+ type: 'middleware_function',
184
+ loc: node.loc
185
+ });
186
+ }
187
+ }
188
+ },
189
+
190
+ // Detect auth checks and redirects
191
+ CallExpression(path) {
192
+ const callee = path.node.callee;
193
+
194
+ if (callee.type === 'MemberExpression') {
195
+ const methodName = callee.property.name || callee.property.value;
196
+
197
+ // Auth verification
198
+ if (methodName === 'getUser' || methodName === 'getSession') {
199
+ middlewareDeps.push({
200
+ service: 'auth',
201
+ method: methodName,
202
+ type: 'auth_check',
203
+ loc: path.node.loc
204
+ });
205
+ }
206
+
207
+ // Redirects
208
+ if (methodName === 'redirect' || methodName === 'rewrite') {
209
+ middlewareDeps.push({
210
+ service: 'next',
211
+ method: methodName,
212
+ type: 'middleware_action',
213
+ loc: path.node.loc
214
+ });
215
+ }
216
+ }
217
+ }
218
+ });
219
+
220
+ return middlewareDeps;
221
+ }
222
+
223
+ /**
224
+ * Detect all React/Next.js patterns
225
+ * @param {Object} ast - Babel AST
226
+ * @param {string} content - File content
227
+ * @param {string} filePath - File path
228
+ * @returns {Object} All detected patterns
229
+ */
230
+ function detectReactNextJSPatterns(ast, content = '', filePath = '') {
231
+ return {
232
+ componentUsages: detectComponentUsage(ast),
233
+ boundaries: detectServerClientBoundaries(content),
234
+ apiDependencies: detectAPIRouteDependencies(ast),
235
+ middlewareDependencies: detectMiddlewareDependencies(ast, filePath)
236
+ };
237
+ }
238
+
239
+ module.exports = {
240
+ detectComponentUsage,
241
+ detectServerClientBoundaries,
242
+ detectAPIRouteDependencies,
243
+ detectMiddlewareDependencies,
244
+ detectReactNextJSPatterns
245
+ };
@@ -0,0 +1,167 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { spawnSync } = require('child_process');
4
+
5
+ /**
6
+ * Get the current git commit hash
7
+ * @returns {string} Commit hash or 'unknown' if git is not available
8
+ */
9
+ function getCommitHash() {
10
+ try {
11
+ const result = spawnSync('git', ['rev-parse', 'HEAD'], {
12
+ stdio: ['pipe', 'pipe', 'pipe']
13
+ });
14
+
15
+ if (result.status === 0) {
16
+ return result.stdout.toString().trim();
17
+ }
18
+ return 'unknown';
19
+ } catch (error) {
20
+ return 'unknown';
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Generate the README content for the ArcVision system context artifact
26
+ * @param {string} commitHash - Git commit hash
27
+ * @param {string} timestamp - Generation timestamp
28
+ * @param {string} toolVersion - ArcVision tool version
29
+ * @param {Object} blastRadiusData - Blast radius analysis data
30
+ * @returns {string} Formatted README content
31
+ */
32
+ function generateReadmeContent(commitHash, timestamp, toolVersion, blastRadiusData = null) {
33
+ let content = `# ArcVision System Context Artifact
34
+
35
+
36
+ ## What This Is [arcvision.context.json](./arcvision.context.json)
37
+
38
+ This file is the **canonical structural context** of this codebase.
39
+ It represents how the system actually works — not how it is described.
40
+
41
+ It is generated directly from source code by ArcVision.
42
+
43
+ ## What This Replaces
44
+
45
+ This artifact replaces:
46
+ - Manual repository scanning
47
+ - Tribal knowledge held by senior engineers
48
+ - Re-explaining the system to new developers
49
+ - Re-prompting LLMs with partial or incorrect context
50
+ - Guessing blast radius of changes
51
+
52
+ ## When You Must Use This
53
+
54
+ Use this artifact when:
55
+ - Onboarding a new developer
56
+ - Prompting an AI assistant about this codebase
57
+ - Making architectural changes
58
+ - Investigating unexpected behavior
59
+ - Assessing risk before modifying core modules
60
+
61
+ ## What This Artifact Contains
62
+
63
+ - Canonical module and dependency graph
64
+ - Execution and data flow relationships
65
+ - Structural roles (service, store, boundary, etc.)
66
+ - Invariants inferred from the system
67
+ - Impact metrics (blast radius, coupling)
68
+ - Authority core identification
69
+ - Hidden coupling detection
70
+ - Architectural archetype classification
71
+ - Analysis completeness metrics
72
+
73
+ ## Determinism & Trust
74
+
75
+ - Generated from commit: ${commitHash}
76
+ - Generation timestamp: ${timestamp}
77
+ - Tool version: ${toolVersion}
78
+ - Deterministic: same input → same output
79
+ - Explicit assumptions listed inside the artifact
80
+
81
+ If this artifact conflicts with human memory, **trust the artifact**.`;
82
+
83
+ // Add blast radius information if available
84
+ if (blastRadiusData && blastRadiusData.topFiles && blastRadiusData.topFiles.length > 0) {
85
+ content += `
86
+
87
+ ## Structural Context Hubs
88
+
89
+ The following files have the highest blast radius and represent critical structural hubs in the system:
90
+
91
+ `;
92
+
93
+ blastRadiusData.topFiles.forEach((item, index) => {
94
+ let warningMessage = '';
95
+ if (index === 0) {
96
+ warningMessage = 'Changes here may silently propagate across the system.';
97
+ } else if (index === 1) {
98
+ warningMessage = 'Acts as a coordination layer between components.';
99
+ } else {
100
+ warningMessage = 'Modifications can cause widespread inconsistencies.';
101
+ }
102
+
103
+ content += `- **${item.file}**
104
+ - Blast Radius: ${item.blastRadius} files (${item.percentOfGraph}% of codebase)
105
+ - Risk: ${warningMessage}
106
+
107
+ `;
108
+ });
109
+ } else {
110
+ content += `
111
+
112
+ ## Structural Context Hubs
113
+
114
+ No high-structure files detected based on import dependencies.`;
115
+ }
116
+
117
+ content += `
118
+
119
+ ## How to Use With AI
120
+
121
+ When prompting AI tools, include this file as system context.
122
+ Do not ask the AI to infer architecture without it.
123
+
124
+ ## When to Regenerate
125
+
126
+ Regenerate this artifact when:
127
+ - Core modules change
128
+ - New services are added
129
+ - Dependency structure shifts
130
+
131
+ Run:
132
+
133
+ \`\`\`
134
+ arcvision scan --upload
135
+ \`\`\`
136
+
137
+ ## Source of Truth
138
+
139
+ This artifact is the **source of truth** for system structure.
140
+ All explanations, decisions, and AI reasoning should reference it.
141
+
142
+ Some execution script invocations are dynamically assembled at runtime and may not be statically traceable; such scripts are included
143
+ as execution boundaries without guaranteed call-site resolution`;
144
+
145
+ return content;
146
+ }
147
+
148
+ /**
149
+ * Generate and save the README file
150
+ * @param {string} outputDir - Directory to save the README
151
+ * @param {string} toolVersion - ArcVision tool version
152
+ * @param {Object} blastRadiusData - Blast radius analysis data
153
+ */
154
+ function generateReadme(outputDir, toolVersion, blastRadiusData = null) {
155
+ const commitHash = getCommitHash();
156
+ const timestamp = new Date().toISOString();
157
+ const readmeContent = generateReadmeContent(commitHash, timestamp, toolVersion, blastRadiusData);
158
+
159
+ const readmePath = path.join(outputDir, 'README.md');
160
+ fs.writeFileSync(readmePath, readmeContent);
161
+
162
+ console.log(`✅ System context README generated at ${readmePath}`);
163
+ }
164
+
165
+ module.exports = { generateReadme, generateReadmeContent, getCommitHash };
166
+
167
+
@@ -0,0 +1,57 @@
1
+ const chalk = require('chalk');
2
+
3
+ class RetryHandler {
4
+ constructor(maxRetries = 3, baseDelay = 1000, backoffMultiplier = 2) {
5
+ this.maxRetries = maxRetries;
6
+ this.baseDelay = baseDelay;
7
+ this.backoffMultiplier = backoffMultiplier;
8
+ }
9
+
10
+ async executeWithRetry(operation, context = '') {
11
+ let lastError;
12
+
13
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
14
+ try {
15
+ if (attempt > 0) {
16
+ const delay = this.baseDelay * Math.pow(this.backoffMultiplier, attempt - 1);
17
+ console.log(chalk.yellow(`Retry attempt ${attempt}/${this.maxRetries} for ${context} after ${delay}ms delay...`));
18
+
19
+ // Wait before retrying
20
+ await this.sleep(delay);
21
+ }
22
+
23
+ const result = await operation(attempt);
24
+ return { success: true, result, attempts: attempt + 1 };
25
+ } catch (error) {
26
+ lastError = error;
27
+
28
+ // Don't log error on final attempt since caller will handle it
29
+ if (attempt < this.maxRetries) {
30
+ console.log(chalk.red(`Attempt ${attempt + 1} failed for ${context}: ${error.message}`));
31
+ }
32
+ }
33
+ }
34
+
35
+ return { success: false, error: lastError, attempts: this.maxRetries + 1 };
36
+ }
37
+
38
+ sleep(ms) {
39
+ return new Promise(resolve => setTimeout(resolve, ms));
40
+ }
41
+
42
+ // Specific retry for network requests
43
+ async executeNetworkRequest(url, options, context = 'network request') {
44
+ return this.executeWithRetry(async (attempt) => {
45
+ const response = await fetch(url, options);
46
+
47
+ if (!response.ok) {
48
+ const errorText = await response.text().catch(() => 'Unknown error');
49
+ throw new Error(`HTTP ${response.status}: ${errorText}`);
50
+ }
51
+
52
+ return await response.json();
53
+ }, context);
54
+ }
55
+ }
56
+
57
+ module.exports = RetryHandler;