@mondaydotcomorg/atp-server 0.17.14
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 +489 -0
- package/dist/aggregator/index.d.ts +59 -0
- package/dist/aggregator/index.d.ts.map +1 -0
- package/dist/aggregator/index.js +171 -0
- package/dist/aggregator/index.js.map +1 -0
- package/dist/callback/index.d.ts +98 -0
- package/dist/callback/index.d.ts.map +1 -0
- package/dist/callback/index.js +136 -0
- package/dist/callback/index.js.map +1 -0
- package/dist/client-sessions.d.ts +82 -0
- package/dist/client-sessions.d.ts.map +1 -0
- package/dist/client-sessions.js +174 -0
- package/dist/client-sessions.js.map +1 -0
- package/dist/controllers/definitions.controller.d.ts +4 -0
- package/dist/controllers/definitions.controller.d.ts.map +1 -0
- package/dist/controllers/definitions.controller.js +11 -0
- package/dist/controllers/definitions.controller.js.map +1 -0
- package/dist/controllers/execute.controller.d.ts +18 -0
- package/dist/controllers/execute.controller.d.ts.map +1 -0
- package/dist/controllers/execute.controller.js +122 -0
- package/dist/controllers/execute.controller.js.map +1 -0
- package/dist/controllers/info.controller.d.ts +3 -0
- package/dist/controllers/info.controller.d.ts.map +1 -0
- package/dist/controllers/info.controller.js +13 -0
- package/dist/controllers/info.controller.js.map +1 -0
- package/dist/controllers/resume.controller.d.ts +11 -0
- package/dist/controllers/resume.controller.d.ts.map +1 -0
- package/dist/controllers/resume.controller.js +61 -0
- package/dist/controllers/resume.controller.js.map +1 -0
- package/dist/controllers/search.controller.d.ts +4 -0
- package/dist/controllers/search.controller.d.ts.map +1 -0
- package/dist/controllers/search.controller.js +7 -0
- package/dist/controllers/search.controller.js.map +1 -0
- package/dist/controllers/stream.controller.d.ts +19 -0
- package/dist/controllers/stream.controller.d.ts.map +1 -0
- package/dist/controllers/stream.controller.js +141 -0
- package/dist/controllers/stream.controller.js.map +1 -0
- package/dist/core/config.d.ts +161 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +7 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/http.d.ts +4 -0
- package/dist/core/http.d.ts.map +1 -0
- package/dist/core/http.js +17 -0
- package/dist/core/http.js.map +1 -0
- package/dist/create-server.d.ts +120 -0
- package/dist/create-server.d.ts.map +1 -0
- package/dist/create-server.js +423 -0
- package/dist/create-server.js.map +1 -0
- package/dist/execution-state/index.d.ts +95 -0
- package/dist/execution-state/index.d.ts.map +1 -0
- package/dist/execution-state/index.js +128 -0
- package/dist/execution-state/index.js.map +1 -0
- package/dist/executor/ast-provenance-bridge.d.ts +12 -0
- package/dist/executor/ast-provenance-bridge.d.ts.map +1 -0
- package/dist/executor/ast-provenance-bridge.js +66 -0
- package/dist/executor/ast-provenance-bridge.js.map +1 -0
- package/dist/executor/ast-tracking-runtime.d.ts +7 -0
- package/dist/executor/ast-tracking-runtime.d.ts.map +1 -0
- package/dist/executor/ast-tracking-runtime.js +559 -0
- package/dist/executor/ast-tracking-runtime.js.map +1 -0
- package/dist/executor/bootstrap-generated.d.ts +32 -0
- package/dist/executor/bootstrap-generated.d.ts.map +1 -0
- package/dist/executor/bootstrap-generated.js +90 -0
- package/dist/executor/bootstrap-generated.js.map +1 -0
- package/dist/executor/compiler-config.d.ts +32 -0
- package/dist/executor/compiler-config.d.ts.map +1 -0
- package/dist/executor/compiler-config.js +99 -0
- package/dist/executor/compiler-config.js.map +1 -0
- package/dist/executor/constants.d.ts +4 -0
- package/dist/executor/constants.d.ts.map +1 -0
- package/dist/executor/constants.js +4 -0
- package/dist/executor/constants.js.map +1 -0
- package/dist/executor/error-handler.d.ts +9 -0
- package/dist/executor/error-handler.d.ts.map +1 -0
- package/dist/executor/error-handler.js +95 -0
- package/dist/executor/error-handler.js.map +1 -0
- package/dist/executor/execution-error-handler.d.ts +7 -0
- package/dist/executor/execution-error-handler.d.ts.map +1 -0
- package/dist/executor/execution-error-handler.js +136 -0
- package/dist/executor/execution-error-handler.js.map +1 -0
- package/dist/executor/executor.d.ts +20 -0
- package/dist/executor/executor.d.ts.map +1 -0
- package/dist/executor/executor.js +452 -0
- package/dist/executor/executor.js.map +1 -0
- package/dist/executor/index.d.ts +4 -0
- package/dist/executor/index.d.ts.map +1 -0
- package/dist/executor/index.js +3 -0
- package/dist/executor/index.js.map +1 -0
- package/dist/executor/resume-handler.d.ts +9 -0
- package/dist/executor/resume-handler.d.ts.map +1 -0
- package/dist/executor/resume-handler.js +22 -0
- package/dist/executor/resume-handler.js.map +1 -0
- package/dist/executor/sandbox-builder.d.ts +29 -0
- package/dist/executor/sandbox-builder.d.ts.map +1 -0
- package/dist/executor/sandbox-builder.js +538 -0
- package/dist/executor/sandbox-builder.js.map +1 -0
- package/dist/executor/sandbox-injector.d.ts +7 -0
- package/dist/executor/sandbox-injector.d.ts.map +1 -0
- package/dist/executor/sandbox-injector.js +293 -0
- package/dist/executor/sandbox-injector.js.map +1 -0
- package/dist/executor/types.d.ts +21 -0
- package/dist/executor/types.d.ts.map +1 -0
- package/dist/executor/types.js +2 -0
- package/dist/executor/types.js.map +1 -0
- package/dist/explorer/index.d.ts +69 -0
- package/dist/explorer/index.d.ts.map +1 -0
- package/dist/explorer/index.js +228 -0
- package/dist/explorer/index.js.map +1 -0
- package/dist/handlers/definitions.handler.d.ts +3 -0
- package/dist/handlers/definitions.handler.d.ts.map +1 -0
- package/dist/handlers/definitions.handler.js +11 -0
- package/dist/handlers/definitions.handler.js.map +1 -0
- package/dist/handlers/execute.handler.d.ts +7 -0
- package/dist/handlers/execute.handler.d.ts.map +1 -0
- package/dist/handlers/execute.handler.js +225 -0
- package/dist/handlers/execute.handler.js.map +1 -0
- package/dist/handlers/explorer.handler.d.ts +4 -0
- package/dist/handlers/explorer.handler.d.ts.map +1 -0
- package/dist/handlers/explorer.handler.js +10 -0
- package/dist/handlers/explorer.handler.js.map +1 -0
- package/dist/handlers/init.handler.d.ts +5 -0
- package/dist/handlers/init.handler.d.ts.map +1 -0
- package/dist/handlers/init.handler.js +41 -0
- package/dist/handlers/init.handler.js.map +1 -0
- package/dist/handlers/resume.handler.d.ts +6 -0
- package/dist/handlers/resume.handler.d.ts.map +1 -0
- package/dist/handlers/resume.handler.js +256 -0
- package/dist/handlers/resume.handler.js.map +1 -0
- package/dist/handlers/search.handler.d.ts +5 -0
- package/dist/handlers/search.handler.d.ts.map +1 -0
- package/dist/handlers/search.handler.js +11 -0
- package/dist/handlers/search.handler.js.map +1 -0
- package/dist/http/request-handler.d.ts +15 -0
- package/dist/http/request-handler.d.ts.map +1 -0
- package/dist/http/request-handler.js +94 -0
- package/dist/http/request-handler.js.map +1 -0
- package/dist/http/router.d.ts +4 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +32 -0
- package/dist/http/router.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/instrumentation/index.d.ts +5 -0
- package/dist/instrumentation/index.d.ts.map +1 -0
- package/dist/instrumentation/index.js +5 -0
- package/dist/instrumentation/index.js.map +1 -0
- package/dist/instrumentation/serializer.d.ts +61 -0
- package/dist/instrumentation/serializer.d.ts.map +1 -0
- package/dist/instrumentation/serializer.js +334 -0
- package/dist/instrumentation/serializer.js.map +1 -0
- package/dist/instrumentation/state-manager.d.ts +61 -0
- package/dist/instrumentation/state-manager.d.ts.map +1 -0
- package/dist/instrumentation/state-manager.js +205 -0
- package/dist/instrumentation/state-manager.js.map +1 -0
- package/dist/instrumentation/transformer.d.ts +9 -0
- package/dist/instrumentation/transformer.d.ts.map +1 -0
- package/dist/instrumentation/transformer.js +70 -0
- package/dist/instrumentation/transformer.js.map +1 -0
- package/dist/instrumentation/types.d.ts +59 -0
- package/dist/instrumentation/types.d.ts.map +1 -0
- package/dist/instrumentation/types.js +5 -0
- package/dist/instrumentation/types.js.map +1 -0
- package/dist/middleware/audit.d.ts +18 -0
- package/dist/middleware/audit.d.ts.map +1 -0
- package/dist/middleware/audit.js +76 -0
- package/dist/middleware/audit.js.map +1 -0
- package/dist/openapi/index.d.ts +133 -0
- package/dist/openapi/index.d.ts.map +1 -0
- package/dist/openapi/index.js +235 -0
- package/dist/openapi/index.js.map +1 -0
- package/dist/openapi-loader.d.ts +87 -0
- package/dist/openapi-loader.d.ts.map +1 -0
- package/dist/openapi-loader.js +491 -0
- package/dist/openapi-loader.js.map +1 -0
- package/dist/routes/index.d.ts +21 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +47 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/search/index.d.ts +48 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +156 -0
- package/dist/search/index.js.map +1 -0
- package/dist/security/index.d.ts +2 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +2 -0
- package/dist/security/index.js.map +1 -0
- package/dist/shutdown.d.ts +19 -0
- package/dist/shutdown.d.ts.map +1 -0
- package/dist/shutdown.js +87 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/utils/banner.d.ts +12 -0
- package/dist/utils/banner.d.ts.map +1 -0
- package/dist/utils/banner.js +18 -0
- package/dist/utils/banner.js.map +1 -0
- package/dist/utils/context.d.ts +16 -0
- package/dist/utils/context.d.ts.map +1 -0
- package/dist/utils/context.js +44 -0
- package/dist/utils/context.js.map +1 -0
- package/dist/utils/error.d.ts +8 -0
- package/dist/utils/error.d.ts.map +1 -0
- package/dist/utils/error.js +17 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/hint-based-instrumentation.d.ts +14 -0
- package/dist/utils/hint-based-instrumentation.d.ts.map +1 -0
- package/dist/utils/hint-based-instrumentation.js +84 -0
- package/dist/utils/hint-based-instrumentation.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/info.d.ts +20 -0
- package/dist/utils/info.d.ts.map +1 -0
- package/dist/utils/info.js +15 -0
- package/dist/utils/info.js.map +1 -0
- package/dist/utils/provenance-reattachment.d.ts +32 -0
- package/dist/utils/provenance-reattachment.d.ts.map +1 -0
- package/dist/utils/provenance-reattachment.js +115 -0
- package/dist/utils/provenance-reattachment.js.map +1 -0
- package/dist/utils/request.d.ts +21 -0
- package/dist/utils/request.d.ts.map +1 -0
- package/dist/utils/request.js +44 -0
- package/dist/utils/request.js.map +1 -0
- package/dist/utils/response.d.ts +30 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +53 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/runtime-types.d.ts +6 -0
- package/dist/utils/runtime-types.d.ts.map +1 -0
- package/dist/utils/runtime-types.js +14 -0
- package/dist/utils/runtime-types.js.map +1 -0
- package/dist/utils/schema.d.ts +9 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +13 -0
- package/dist/utils/schema.js.map +1 -0
- package/dist/utils/token-emitter.d.ts +21 -0
- package/dist/utils/token-emitter.d.ts.map +1 -0
- package/dist/utils/token-emitter.js +129 -0
- package/dist/utils/token-emitter.js.map +1 -0
- package/dist/validator/index.d.ts +36 -0
- package/dist/validator/index.d.ts.map +1 -0
- package/dist/validator/index.js +224 -0
- package/dist/validator/index.js.map +1 -0
- package/package.json +68 -0
- package/src/aggregator/index.ts +207 -0
- package/src/callback/index.ts +191 -0
- package/src/client-sessions.ts +234 -0
- package/src/controllers/definitions.controller.ts +19 -0
- package/src/controllers/execute.controller.ts +166 -0
- package/src/controllers/info.controller.ts +14 -0
- package/src/controllers/resume.controller.ts +92 -0
- package/src/controllers/search.controller.ts +16 -0
- package/src/controllers/stream.controller.ts +190 -0
- package/src/core/config.ts +180 -0
- package/src/core/http.ts +21 -0
- package/src/create-server.ts +536 -0
- package/src/execution-state/index.ts +204 -0
- package/src/executor/ast-provenance-bridge.ts +80 -0
- package/src/executor/ast-tracking-runtime.ts +558 -0
- package/src/executor/bootstrap-generated.ts +90 -0
- package/src/executor/compiler-config.ts +146 -0
- package/src/executor/constants.ts +5 -0
- package/src/executor/error-handler.ts +118 -0
- package/src/executor/execution-error-handler.ts +178 -0
- package/src/executor/executor.ts +631 -0
- package/src/executor/index.ts +3 -0
- package/src/executor/resume-handler.ts +39 -0
- package/src/executor/sandbox-builder.ts +684 -0
- package/src/executor/sandbox-injector.ts +345 -0
- package/src/executor/types.ts +22 -0
- package/src/explorer/index.ts +297 -0
- package/src/handlers/definitions.handler.ts +13 -0
- package/src/handlers/execute.handler.ts +286 -0
- package/src/handlers/explorer.handler.ts +18 -0
- package/src/handlers/init.handler.ts +53 -0
- package/src/handlers/resume.handler.ts +316 -0
- package/src/handlers/search.handler.ts +32 -0
- package/src/http/request-handler.ts +117 -0
- package/src/http/router.ts +29 -0
- package/src/index.ts +60 -0
- package/src/instrumentation/index.ts +4 -0
- package/src/instrumentation/serializer.ts +421 -0
- package/src/instrumentation/state-manager.ts +237 -0
- package/src/instrumentation/transformer.ts +84 -0
- package/src/instrumentation/types.ts +76 -0
- package/src/middleware/audit.ts +101 -0
- package/src/openapi/index.ts +378 -0
- package/src/openapi-loader.ts +744 -0
- package/src/routes/index.ts +93 -0
- package/src/search/index.ts +216 -0
- package/src/security/index.ts +1 -0
- package/src/shutdown.ts +108 -0
- package/src/utils/banner.ts +25 -0
- package/src/utils/context.ts +58 -0
- package/src/utils/error.ts +25 -0
- package/src/utils/hint-based-instrumentation.ts +99 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/info.ts +31 -0
- package/src/utils/provenance-reattachment.ts +144 -0
- package/src/utils/request.ts +53 -0
- package/src/utils/response.ts +69 -0
- package/src/utils/runtime-types.ts +14 -0
- package/src/utils/schema.ts +18 -0
- package/src/utils/token-emitter.ts +182 -0
- package/src/validator/index.ts +253 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { sanitizeInput, MAX_CODE_SIZE } from '@mondaydotcomorg/atp-protocol';
|
|
2
|
+
import * as acorn from 'acorn';
|
|
3
|
+
/**
|
|
4
|
+
* CodeValidator validates user code before execution using a whitelist approach.
|
|
5
|
+
* Only explicitly allowed operations and patterns are permitted.
|
|
6
|
+
*/
|
|
7
|
+
export class CodeValidator {
|
|
8
|
+
allowedGlobalObjects = new Set([
|
|
9
|
+
'Array',
|
|
10
|
+
'Object',
|
|
11
|
+
'String',
|
|
12
|
+
'Number',
|
|
13
|
+
'Boolean',
|
|
14
|
+
'Date',
|
|
15
|
+
'Math',
|
|
16
|
+
'JSON',
|
|
17
|
+
'Promise',
|
|
18
|
+
'Map',
|
|
19
|
+
'Set',
|
|
20
|
+
'WeakMap',
|
|
21
|
+
'WeakSet',
|
|
22
|
+
'Error',
|
|
23
|
+
'TypeError',
|
|
24
|
+
'RangeError',
|
|
25
|
+
'console',
|
|
26
|
+
]);
|
|
27
|
+
forbiddenPatterns = [
|
|
28
|
+
/\beval\s*\(/,
|
|
29
|
+
/\bnew\s+Function\s*\(/,
|
|
30
|
+
/\bnew\s+AsyncFunction\s*\(/,
|
|
31
|
+
/\bnew\s+GeneratorFunction\s*\(/,
|
|
32
|
+
/\brequire\s*\(/,
|
|
33
|
+
/\bprocess\b/,
|
|
34
|
+
/\bglobal\b/,
|
|
35
|
+
/\bglobalThis\.process\b/,
|
|
36
|
+
/\bglobalThis\.global\b/,
|
|
37
|
+
/\b__dirname\b/,
|
|
38
|
+
/\b__filename\b/,
|
|
39
|
+
/\bmodule\b/,
|
|
40
|
+
/\bexports\b/,
|
|
41
|
+
/\bBuffer\b/,
|
|
42
|
+
// Constructor chain exploits - CRITICAL security issue
|
|
43
|
+
/constructor\s*\[\s*['"`]constructor['"`]\s*\]/,
|
|
44
|
+
/constructor\.constructor/,
|
|
45
|
+
/\['constructor'\]\s*\[\s*['"`]constructor['"`]\s*\]/,
|
|
46
|
+
/\["constructor"\]\s*\[\s*['"`]constructor['"`]\s*\]/,
|
|
47
|
+
/\[`constructor`\]\s*\[\s*['"`]constructor['"`]\s*\]/,
|
|
48
|
+
// Prototype chain manipulation - sandbox escape vectors
|
|
49
|
+
/__proto__/,
|
|
50
|
+
/Object\.getPrototypeOf/,
|
|
51
|
+
/Object\.setPrototypeOf/,
|
|
52
|
+
/Reflect\.construct/,
|
|
53
|
+
/Reflect\.get/,
|
|
54
|
+
/Reflect\.set/,
|
|
55
|
+
// Indirect eval patterns
|
|
56
|
+
/\['eval'\]/,
|
|
57
|
+
/\["eval"\]/,
|
|
58
|
+
/\[`eval`\]/,
|
|
59
|
+
/window\['eval'\]/,
|
|
60
|
+
/this\['eval'\]/,
|
|
61
|
+
];
|
|
62
|
+
/**
|
|
63
|
+
* Validates code for security and syntax issues.
|
|
64
|
+
* @param code - The code to validate
|
|
65
|
+
* @param config - Execution configuration
|
|
66
|
+
* @returns Validation result with any errors or security issues
|
|
67
|
+
*/
|
|
68
|
+
async validate(code, config) {
|
|
69
|
+
const errors = [];
|
|
70
|
+
const warnings = [];
|
|
71
|
+
const securityIssues = [];
|
|
72
|
+
code = sanitizeInput(code, MAX_CODE_SIZE);
|
|
73
|
+
for (const pattern of this.forbiddenPatterns) {
|
|
74
|
+
if (pattern.test(code)) {
|
|
75
|
+
securityIssues.push({
|
|
76
|
+
line: 0,
|
|
77
|
+
issue: `Forbidden pattern detected: ${pattern.source}`,
|
|
78
|
+
risk: 'high',
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
this.checkGlobalAccess(code, securityIssues);
|
|
83
|
+
this.validateImports(code, securityIssues);
|
|
84
|
+
this.validateSyntax(code, errors);
|
|
85
|
+
const hasHighRiskIssues = securityIssues.some((issue) => issue.risk === 'high');
|
|
86
|
+
return {
|
|
87
|
+
valid: errors.length === 0 && !hasHighRiskIssues,
|
|
88
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
89
|
+
warnings: warnings.length > 0 ? warnings : undefined,
|
|
90
|
+
securityIssues: securityIssues.length > 0 ? securityIssues : undefined,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Validates JavaScript syntax using acorn parser.
|
|
95
|
+
* @param code - Code to validate
|
|
96
|
+
* @param errors - Array to append syntax errors to
|
|
97
|
+
*/
|
|
98
|
+
validateSyntax(code, errors) {
|
|
99
|
+
try {
|
|
100
|
+
acorn.parse(code, {
|
|
101
|
+
ecmaVersion: 2022,
|
|
102
|
+
sourceType: 'script',
|
|
103
|
+
allowAwaitOutsideFunction: true,
|
|
104
|
+
allowReturnOutsideFunction: true,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (scriptError) {
|
|
108
|
+
try {
|
|
109
|
+
acorn.parse(code, {
|
|
110
|
+
ecmaVersion: 2022,
|
|
111
|
+
sourceType: 'module',
|
|
112
|
+
allowAwaitOutsideFunction: true,
|
|
113
|
+
allowReturnOutsideFunction: false,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (moduleError) {
|
|
117
|
+
errors.push({
|
|
118
|
+
line: moduleError.loc?.line ?? 0,
|
|
119
|
+
message: `Syntax error: ${moduleError.message}`,
|
|
120
|
+
severity: 'error',
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Checks for unauthorized global object access.
|
|
127
|
+
* @param code - Code to check
|
|
128
|
+
* @param securityIssues - Array to append issues to
|
|
129
|
+
*/
|
|
130
|
+
checkGlobalAccess(code, securityIssues) {
|
|
131
|
+
const globalAccessPattern = /\b([A-Z][a-zA-Z0-9]*)\./g;
|
|
132
|
+
let match;
|
|
133
|
+
while ((match = globalAccessPattern.exec(code)) !== null) {
|
|
134
|
+
const globalName = match[1];
|
|
135
|
+
if (globalName &&
|
|
136
|
+
!this.allowedGlobalObjects.has(globalName) &&
|
|
137
|
+
globalName !== 'atp' &&
|
|
138
|
+
globalName !== 'api') {
|
|
139
|
+
securityIssues.push({
|
|
140
|
+
line: 0,
|
|
141
|
+
issue: `Unauthorized global access: ${globalName}`,
|
|
142
|
+
risk: 'medium',
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Validates import statements to ensure NO imports are allowed.
|
|
149
|
+
* ALL imports are blocked for security - use injected sandbox globals instead.
|
|
150
|
+
* @param code - Code to validate
|
|
151
|
+
* @param securityIssues - Array to append issues to
|
|
152
|
+
*/
|
|
153
|
+
validateImports(code, securityIssues) {
|
|
154
|
+
try {
|
|
155
|
+
const ast = acorn.parse(code, {
|
|
156
|
+
ecmaVersion: 2022,
|
|
157
|
+
sourceType: 'module',
|
|
158
|
+
allowAwaitOutsideFunction: true,
|
|
159
|
+
allowReturnOutsideFunction: true,
|
|
160
|
+
});
|
|
161
|
+
const walk = (node) => {
|
|
162
|
+
if (!node || typeof node !== 'object')
|
|
163
|
+
return;
|
|
164
|
+
if (node.type === 'ImportDeclaration') {
|
|
165
|
+
const importSource = node.source?.value;
|
|
166
|
+
securityIssues.push({
|
|
167
|
+
line: node.loc?.start?.line ?? 0,
|
|
168
|
+
issue: `All imports are blocked for security. Import attempted: ${importSource}. Use injected sandbox globals (api, atp) instead.`,
|
|
169
|
+
risk: 'high',
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (node.type === 'ImportExpression') {
|
|
173
|
+
securityIssues.push({
|
|
174
|
+
line: node.loc?.start?.line ?? 0,
|
|
175
|
+
issue: `Dynamic import() is not allowed. All imports are blocked for security.`,
|
|
176
|
+
risk: 'high',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (node.type === 'ExportNamedDeclaration' || node.type === 'ExportAllDeclaration') {
|
|
180
|
+
if (node.source?.value) {
|
|
181
|
+
const exportSource = node.source.value;
|
|
182
|
+
securityIssues.push({
|
|
183
|
+
line: node.loc?.start?.line ?? 0,
|
|
184
|
+
issue: `Re-exports are not allowed. Attempted re-export from: ${exportSource}.`,
|
|
185
|
+
risk: 'high',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
for (const key in node) {
|
|
190
|
+
if (key === 'loc' || key === 'range' || key === 'start' || key === 'end')
|
|
191
|
+
continue;
|
|
192
|
+
const child = node[key];
|
|
193
|
+
if (Array.isArray(child)) {
|
|
194
|
+
child.forEach(walk);
|
|
195
|
+
}
|
|
196
|
+
else if (child && typeof child === 'object') {
|
|
197
|
+
walk(child);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
walk(ast);
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
const importPattern = /^\s*import\s+.*?\s+from\s+['"](.+?)['"]/gm;
|
|
205
|
+
let match;
|
|
206
|
+
while ((match = importPattern.exec(code)) !== null) {
|
|
207
|
+
const importSource = match[1];
|
|
208
|
+
securityIssues.push({
|
|
209
|
+
line: 0,
|
|
210
|
+
issue: `All imports are blocked for security. Import detected: ${importSource}.`,
|
|
211
|
+
risk: 'high',
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
if (/import\s*\(/.test(code)) {
|
|
215
|
+
securityIssues.push({
|
|
216
|
+
line: 0,
|
|
217
|
+
issue: `Dynamic import() is not allowed. All imports are blocked for security.`,
|
|
218
|
+
risk: 'high',
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validator/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mondaydotcomorg/atp-server",
|
|
3
|
+
"version": "0.17.14",
|
|
4
|
+
"description": "Server implementation for Agent Tool Protocol",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "npm run generate:bootstrap && tsc -p tsconfig.json",
|
|
20
|
+
"generate:bootstrap": "tsx scripts/generate-bootstrap.ts",
|
|
21
|
+
"dev": "tsc -p tsconfig.json --watch",
|
|
22
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"lint": "tsc --noEmit"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"agent",
|
|
28
|
+
"protocol",
|
|
29
|
+
"server",
|
|
30
|
+
"ai",
|
|
31
|
+
"llm"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@babel/generator": "^7.26.0",
|
|
36
|
+
"@babel/parser": "^7.26.0",
|
|
37
|
+
"@babel/traverse": "^7.26.0",
|
|
38
|
+
"@babel/types": "^7.26.0",
|
|
39
|
+
"@mondaydotcomorg/atp-compiler": "0.17.14",
|
|
40
|
+
"@mondaydotcomorg/atp-protocol": "0.17.14",
|
|
41
|
+
"@mondaydotcomorg/atp-provenance": "0.17.14",
|
|
42
|
+
"@mondaydotcomorg/atp-runtime": "0.17.14",
|
|
43
|
+
"@opentelemetry/api": "^1.9.0",
|
|
44
|
+
"@opentelemetry/auto-instrumentations-node": "^0.66.0",
|
|
45
|
+
"@opentelemetry/core": "^2.2.0",
|
|
46
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.207.0",
|
|
47
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.207.0",
|
|
48
|
+
"@opentelemetry/resources": "^2.2.0",
|
|
49
|
+
"@opentelemetry/sdk-node": "^0.207.0",
|
|
50
|
+
"@opentelemetry/semantic-conventions": "^1.37.0",
|
|
51
|
+
"@types/acorn": "^6.0.4",
|
|
52
|
+
"isolated-vm": "5.0.4",
|
|
53
|
+
"js-yaml": "^4.1.0",
|
|
54
|
+
"jsonwebtoken": "^9.0.2",
|
|
55
|
+
"nanoid": "^5.1.6",
|
|
56
|
+
"rate-limiter-flexible": "*"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/babel__generator": "^7.6.8",
|
|
60
|
+
"@types/babel__traverse": "^7.20.5",
|
|
61
|
+
"@types/escodegen": "^0.0.10",
|
|
62
|
+
"@types/js-yaml": "^4.0.9",
|
|
63
|
+
"@types/jsonwebtoken": "^9.0.5",
|
|
64
|
+
"@types/node": "^20.11.5",
|
|
65
|
+
"typescript": "^5.3.3",
|
|
66
|
+
"vitest": "^1.2.1"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { APIGroupConfig, CustomFunctionDef } from '@mondaydotcomorg/atp-protocol';
|
|
2
|
+
import { generateRuntimeTypes } from '../utils/runtime-types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* APIAggregator generates TypeScript type definitions from API configurations.
|
|
6
|
+
* Converts API group definitions into TypeScript declarations for use in code generation.
|
|
7
|
+
*/
|
|
8
|
+
export class APIAggregator {
|
|
9
|
+
private apiGroups: APIGroupConfig[];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new APIAggregator instance.
|
|
13
|
+
* @param apiGroups - Array of API group configurations
|
|
14
|
+
*/
|
|
15
|
+
constructor(apiGroups: APIGroupConfig[]) {
|
|
16
|
+
this.apiGroups = apiGroups;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generates TypeScript type definitions for selected API groups.
|
|
21
|
+
* @param selectedGroups - Optional array of group names to include
|
|
22
|
+
* @returns TypeScript definition string
|
|
23
|
+
*/
|
|
24
|
+
async generateTypeScript(selectedGroups?: string[]): Promise<string> {
|
|
25
|
+
const groups = selectedGroups
|
|
26
|
+
? this.apiGroups.filter((g) => selectedGroups.includes(g.name))
|
|
27
|
+
: this.apiGroups;
|
|
28
|
+
|
|
29
|
+
let typescript = `// Agent Tool Protocol Runtime SDK v1.0.0\n\n`;
|
|
30
|
+
|
|
31
|
+
typescript += this.generateRuntimeTypes();
|
|
32
|
+
|
|
33
|
+
for (const group of groups) {
|
|
34
|
+
typescript += `\n// API Group: ${group.name}\n`;
|
|
35
|
+
if (group.functions) {
|
|
36
|
+
for (const func of group.functions) {
|
|
37
|
+
typescript += this.generateFunctionTypes(func, group.name);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
typescript += this.generateAPINamespace(groups);
|
|
43
|
+
|
|
44
|
+
return typescript;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Generates TypeScript definitions for the runtime SDK.
|
|
49
|
+
* @returns TypeScript definition string
|
|
50
|
+
*/
|
|
51
|
+
private generateRuntimeTypes(): string {
|
|
52
|
+
return generateRuntimeTypes();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Generates TypeScript types for a single function.
|
|
57
|
+
* @param func - Function definition
|
|
58
|
+
* @param groupName - API group name
|
|
59
|
+
* @returns TypeScript definition string
|
|
60
|
+
*/
|
|
61
|
+
private generateFunctionTypes(func: CustomFunctionDef, groupName: string): string {
|
|
62
|
+
const inputTypeName = `${func.name}_Input`;
|
|
63
|
+
const outputTypeName = `${func.name}_Output`;
|
|
64
|
+
|
|
65
|
+
let typescript = `\ninterface ${inputTypeName} {\n`;
|
|
66
|
+
if (func.inputSchema?.properties) {
|
|
67
|
+
const required = func.inputSchema.required || [];
|
|
68
|
+
for (const [key, value] of Object.entries(func.inputSchema.properties)) {
|
|
69
|
+
const prop = value as { type?: string; description?: string };
|
|
70
|
+
const tsType = this.jsonSchemaTypeToTS(prop.type ?? 'any');
|
|
71
|
+
const comment = prop.description ? ` // ${prop.description}` : '';
|
|
72
|
+
const optional = required.includes(key) ? '' : '?';
|
|
73
|
+
typescript += ` ${key}${optional}: ${tsType};${comment}\n`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
typescript += `}\n`;
|
|
77
|
+
|
|
78
|
+
typescript += `\ninterface ${outputTypeName} {\n`;
|
|
79
|
+
typescript += ` [key: string]: unknown;\n`;
|
|
80
|
+
typescript += `}\n`;
|
|
81
|
+
|
|
82
|
+
return typescript;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Converts JSON Schema type to TypeScript type.
|
|
87
|
+
* @param type - JSON Schema type string
|
|
88
|
+
* @returns TypeScript type string
|
|
89
|
+
*/
|
|
90
|
+
private jsonSchemaTypeToTS(type: string): string {
|
|
91
|
+
switch (type) {
|
|
92
|
+
case 'string':
|
|
93
|
+
return 'string';
|
|
94
|
+
case 'number':
|
|
95
|
+
case 'integer':
|
|
96
|
+
return 'number';
|
|
97
|
+
case 'boolean':
|
|
98
|
+
return 'boolean';
|
|
99
|
+
case 'array':
|
|
100
|
+
return 'unknown[]';
|
|
101
|
+
case 'object':
|
|
102
|
+
return 'Record<string, unknown>';
|
|
103
|
+
default:
|
|
104
|
+
return 'unknown';
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Helper to check if a string is a valid JavaScript identifier
|
|
110
|
+
*/
|
|
111
|
+
private isValidIdentifier(name: string): boolean {
|
|
112
|
+
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Helper to safely format a property name for TypeScript type definitions
|
|
117
|
+
* Returns the property name with quotes if needed, or just the name if valid
|
|
118
|
+
*/
|
|
119
|
+
private formatPropertyName(name: string): string {
|
|
120
|
+
if (!this.isValidIdentifier(name)) {
|
|
121
|
+
return `'${name}'`;
|
|
122
|
+
}
|
|
123
|
+
return name;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Generates the API namespace with all function declarations.
|
|
128
|
+
* Handles hierarchical group names (e.g., "github/readOnly" -> api.github.readOnly)
|
|
129
|
+
* @param groups - API groups to include
|
|
130
|
+
* @returns TypeScript definition string
|
|
131
|
+
*/
|
|
132
|
+
private generateAPINamespace(groups: APIGroupConfig[]): string {
|
|
133
|
+
interface NestedGroup {
|
|
134
|
+
functions: CustomFunctionDef[];
|
|
135
|
+
subgroups: Map<string, NestedGroup>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const rootGroups = new Map<string, NestedGroup>();
|
|
139
|
+
|
|
140
|
+
for (const group of groups) {
|
|
141
|
+
if (!group.functions || group.functions.length === 0) continue;
|
|
142
|
+
|
|
143
|
+
const parts = group.name.split('/');
|
|
144
|
+
let current = rootGroups;
|
|
145
|
+
|
|
146
|
+
for (let i = 0; i < parts.length; i++) {
|
|
147
|
+
const part = parts[i]!;
|
|
148
|
+
|
|
149
|
+
if (!current.has(part)) {
|
|
150
|
+
current.set(part, { functions: [], subgroups: new Map() });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const node = current.get(part)!;
|
|
154
|
+
|
|
155
|
+
if (i === parts.length - 1) {
|
|
156
|
+
node.functions.push(...group.functions);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
current = node.subgroups;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const generateLevel = (groups: Map<string, NestedGroup>, indent: string): string => {
|
|
164
|
+
let ts = '';
|
|
165
|
+
|
|
166
|
+
for (const [name, node] of groups.entries()) {
|
|
167
|
+
if (!name) continue;
|
|
168
|
+
const formattedName = this.formatPropertyName(name);
|
|
169
|
+
ts += `${indent}${formattedName}: {\n`;
|
|
170
|
+
|
|
171
|
+
for (const func of node.functions) {
|
|
172
|
+
if (!func.name) continue;
|
|
173
|
+
const funcName = this.formatPropertyName(func.name);
|
|
174
|
+
const description =
|
|
175
|
+
func.description && typeof func.description === 'string'
|
|
176
|
+
? func.description.replace(/\n/g, ' ').substring(0, 200)
|
|
177
|
+
: '';
|
|
178
|
+
ts += `${indent} /**\n${indent} * ${description}\n${indent} */\n`;
|
|
179
|
+
ts += `${indent} ${funcName}(params: ${func.name}_Input): Promise<${func.name}_Output>;\n`;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (node.subgroups.size > 0) {
|
|
183
|
+
ts += generateLevel(node.subgroups, indent + ' ');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
ts += `${indent}};\n`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return ts;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
let typescript = `\ndeclare const api: {\n`;
|
|
193
|
+
typescript += generateLevel(rootGroups, ' ');
|
|
194
|
+
typescript += `};\n`;
|
|
195
|
+
typescript += `\nexport { api };\n`;
|
|
196
|
+
|
|
197
|
+
return typescript;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Gets the list of available API group names.
|
|
202
|
+
* @returns Array of API group names
|
|
203
|
+
*/
|
|
204
|
+
getApiGroups(): string[] {
|
|
205
|
+
return this.apiGroups.map((g) => g.name);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client Callback Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles callbacks to clients for LLM, approval, and embedding requests
|
|
5
|
+
*/
|
|
6
|
+
import type { ClientServices } from '@mondaydotcomorg/atp-protocol';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Callback request types
|
|
10
|
+
*/
|
|
11
|
+
export type CallbackType = 'llm' | 'approval' | 'embedding';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Callback request payload
|
|
15
|
+
*/
|
|
16
|
+
export interface CallbackRequest {
|
|
17
|
+
type: CallbackType;
|
|
18
|
+
operation: string;
|
|
19
|
+
payload: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Registered client information
|
|
24
|
+
*/
|
|
25
|
+
interface ClientInfo {
|
|
26
|
+
clientId: string;
|
|
27
|
+
services: ClientServices;
|
|
28
|
+
callbackUrl?: string;
|
|
29
|
+
lastSeen: Date;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Callback handler function
|
|
34
|
+
*/
|
|
35
|
+
export type CallbackHandler = (clientId: string, request: CallbackRequest) => Promise<unknown>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Manages client callbacks for provided services
|
|
39
|
+
*/
|
|
40
|
+
export class ClientCallbackManager {
|
|
41
|
+
private clients: Map<string, ClientInfo> = new Map();
|
|
42
|
+
private callbackHandler?: CallbackHandler;
|
|
43
|
+
private cleanupInterval?: NodeJS.Timeout;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Registers a callback handler for client requests
|
|
47
|
+
* @param handler - Function to handle callbacks
|
|
48
|
+
*/
|
|
49
|
+
setCallbackHandler(handler: CallbackHandler): void {
|
|
50
|
+
this.callbackHandler = handler;
|
|
51
|
+
|
|
52
|
+
if (!this.cleanupInterval) {
|
|
53
|
+
this.cleanupInterval = setInterval(
|
|
54
|
+
() => {
|
|
55
|
+
const cleaned = this.cleanupStaleClients();
|
|
56
|
+
if (cleaned > 0) {
|
|
57
|
+
console.log(`[ClientCallback] Cleaned up ${cleaned} stale clients`);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
5 * 60 * 1000
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Registers a client with their provided services
|
|
67
|
+
* @param clientId - Unique client identifier
|
|
68
|
+
* @param services - Services provided by client
|
|
69
|
+
* @param callbackUrl - Optional webhook URL for callbacks
|
|
70
|
+
*/
|
|
71
|
+
registerClient(clientId: string, services: ClientServices, callbackUrl?: string): void {
|
|
72
|
+
this.clients.set(clientId, {
|
|
73
|
+
clientId,
|
|
74
|
+
services,
|
|
75
|
+
callbackUrl,
|
|
76
|
+
lastSeen: new Date(),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Updates client's last seen timestamp
|
|
82
|
+
* @param clientId - Client identifier
|
|
83
|
+
*/
|
|
84
|
+
updateClientActivity(clientId: string): void {
|
|
85
|
+
const client = this.clients.get(clientId);
|
|
86
|
+
if (client) {
|
|
87
|
+
client.lastSeen = new Date();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Checks if client has a specific service
|
|
93
|
+
* @param clientId - Client identifier
|
|
94
|
+
* @param serviceType - Type of service
|
|
95
|
+
* @returns Whether client provides this service
|
|
96
|
+
*/
|
|
97
|
+
hasClientService(clientId: string, serviceType: 'llm' | 'approval' | 'embedding'): boolean {
|
|
98
|
+
const client = this.clients.get(clientId);
|
|
99
|
+
if (!client) return false;
|
|
100
|
+
|
|
101
|
+
switch (serviceType) {
|
|
102
|
+
case 'llm':
|
|
103
|
+
return client.services.hasLLM;
|
|
104
|
+
case 'approval':
|
|
105
|
+
return client.services.hasApproval;
|
|
106
|
+
case 'embedding':
|
|
107
|
+
return client.services.hasEmbedding;
|
|
108
|
+
default:
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gets client information
|
|
115
|
+
* @param clientId - Client identifier
|
|
116
|
+
* @returns Client info or undefined
|
|
117
|
+
*/
|
|
118
|
+
getClient(clientId: string): ClientInfo | undefined {
|
|
119
|
+
return this.clients.get(clientId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Sends a callback request to a client
|
|
124
|
+
* @param clientId - Client identifier
|
|
125
|
+
* @param request - Callback request
|
|
126
|
+
* @returns Response from client
|
|
127
|
+
*/
|
|
128
|
+
async sendCallback(clientId: string, request: CallbackRequest): Promise<unknown> {
|
|
129
|
+
const client = this.clients.get(clientId);
|
|
130
|
+
if (!client) {
|
|
131
|
+
throw new Error(`Client ${clientId} not registered`);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!this.hasClientService(clientId, request.type)) {
|
|
135
|
+
throw new Error(`Client ${clientId} does not provide ${request.type} service`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!this.callbackHandler) {
|
|
139
|
+
throw new Error('No callback handler registered');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return await this.callbackHandler(clientId, request);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Cleans up stale clients (not seen in specified duration)
|
|
147
|
+
* @param maxAge - Maximum age in milliseconds (default: 5 minutes)
|
|
148
|
+
*/
|
|
149
|
+
cleanupStaleClients(maxAge: number = 5 * 60 * 1000): number {
|
|
150
|
+
const now = Date.now();
|
|
151
|
+
let cleaned = 0;
|
|
152
|
+
|
|
153
|
+
for (const [clientId, client] of this.clients.entries()) {
|
|
154
|
+
if (now - client.lastSeen.getTime() > maxAge) {
|
|
155
|
+
this.clients.delete(clientId);
|
|
156
|
+
cleaned++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return cleaned;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Gets all registered clients
|
|
165
|
+
* @returns Array of client information
|
|
166
|
+
*/
|
|
167
|
+
getAllClients(): ClientInfo[] {
|
|
168
|
+
return Array.from(this.clients.values());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Removes a client
|
|
173
|
+
* @param clientId - Client identifier
|
|
174
|
+
*/
|
|
175
|
+
unregisterClient(clientId: string): void {
|
|
176
|
+
this.clients.delete(clientId);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Stops automatic cleanup and clears resources
|
|
181
|
+
*/
|
|
182
|
+
destroy(): void {
|
|
183
|
+
if (this.cleanupInterval) {
|
|
184
|
+
clearInterval(this.cleanupInterval);
|
|
185
|
+
this.cleanupInterval = undefined;
|
|
186
|
+
}
|
|
187
|
+
this.clients.clear();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const clientCallbackManager = new ClientCallbackManager();
|