Skip to content

Commit a66ecb2

Browse files
committed
ci: Add patch for events
1 parent 7f61484 commit a66ecb2

File tree

1 file changed

+228
-0
lines changed

1 file changed

+228
-0
lines changed

.github/mock-firebolt/events.patch

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
diff --git a/server/src/config.mjs b/server/src/config.mjs
2+
index 4ed4866..970e379 100644
3+
--- a/server/src/config.mjs
4+
+++ b/server/src/config.mjs
5+
@@ -37,7 +37,7 @@ const config = {
6+
multiUserConnections: "warn",
7+
8+
app: {
9+
- caseInsensitiveModules: true,
10+
+ caseInsensitiveModules: false,
11+
socketPort: 9998,
12+
httpPort: 3333,
13+
wsSessionServerPort: 9999,
14+
diff --git a/server/src/configureAPI.mjs b/server/src/configureAPI.mjs
15+
index 7113253..1292396 100644
16+
--- a/server/src/configureAPI.mjs
17+
+++ b/server/src/configureAPI.mjs
18+
@@ -20,6 +20,7 @@
19+
20+
'use strict';
21+
22+
+import * as rawApi from './routes/api/raw.mjs'
23+
import * as healthApi from './routes/api/health.mjs';
24+
import * as metaApi from './routes/api/meta.mjs';
25+
import * as stateApi from './routes/api/state.mjs';
26+
@@ -40,6 +41,10 @@ function configureAPI(app) {
27+
// Get all OpenRPC metadata
28+
app.get('/api/v1/meta', metaApi.getMeta);
29+
30+
+ // ============================ Raw Test Routes ===========================
31+
+
32+
+ app.post('/api/v1/raw', rawApi.rawPayload);
33+
+
34+
// ======================= State-Related API Routes =======================
35+
36+
// Set latency min and max, either globally or per method
37+
diff --git a/server/src/events.mjs b/server/src/events.mjs
38+
index 3c2930e..8b43f92 100644
39+
--- a/server/src/events.mjs
40+
+++ b/server/src/events.mjs
41+
@@ -280,9 +280,8 @@ function sendBroadcastEvent(ws, userId, method, result, msg, fSuccess, fErr, fFa
42+
* @returns {Object} - The formatted JSON-RPC 2.0 payload.
43+
*/
44+
45+
-function createBidirectionalPayload(method, params) {
46+
+function createBidirectionalEventPayload(method, params) {
47+
return {
48+
- id: id++, // Increment and return `id` in one step
49+
jsonrpc: "2.0",
50+
method,
51+
params
52+
@@ -355,8 +354,7 @@ function emitResponse(finalResult, msg, userId, method) {
53+
54+
// Check if bidirectional mode is enabled
55+
if (config.dotConfig.bidirectional) {
56+
- const bidirectionalMethod = unidirectionalEventToBiDirectional(method);
57+
- let payload = createBidirectionalPayload(bidirectionalMethod, finalResult);
58+
+ let payload = createBidirectionalEventPayload(method, finalResult);
59+
60+
wsArr.forEach((ws) => {
61+
ws.send(JSON.stringify(payload)); // Send bidirectional event
62+
@@ -464,8 +462,13 @@ function coreSendEvent(isBroadcast, ws, userId, method, result, msg, fSuccess, f
63+
const finalResult = ( postResult ? postResult : result );
64+
// Error to be logged in "novalidate mode" if result validation failed
65+
if( config.validate.includes("events") ) {
66+
- const resultErrors = fireboltOpenRpc.validateMethodResult(finalResult, method);
67+
+ let resultToValidate = finalResult;
68+
+ if ( typeof finalResult === 'object' && finalResult !== null && Object.keys(finalResult).length === 1 && ('value' in finalResult) ) {
69+
+ resultToValidate = finalResult.value;
70+
+ }
71+
+ const resultErrors = fireboltOpenRpc.validateMethodResult(resultToValidate, method);
72+
if ( resultErrors && resultErrors.length > 0 ) {
73+
+ logger.error(`${method} validation error for ${method} with ${JSON.stringify(resultToValidate)}, err: ${JSON.stringify(resultErrors)}`);
74+
fErr.call(null, 'validationError', method);
75+
return
76+
}
77+
diff --git a/server/src/fireboltOpenRpc.mjs b/server/src/fireboltOpenRpc.mjs
78+
index ddb4fe2..ed5e5c5 100644
79+
--- a/server/src/fireboltOpenRpc.mjs
80+
+++ b/server/src/fireboltOpenRpc.mjs
81+
@@ -61,16 +61,22 @@ function getMeta() {
82+
return meta;
83+
}
84+
85+
-function getMethod(methodName) {
86+
+function getMethod(methodName, sdk = undefined) {
87+
if (config.app.caseInsensitiveModules) {
88+
methodName = createCaseAgnosticMethod(methodName);
89+
}
90+
91+
const sources = getOpenRPCSources();
92+
93+
- for (const { name: sdkName } of sources) {
94+
- if (methodMaps[sdkName]?.[methodName]) {
95+
- return methodMaps[sdkName][methodName];
96+
+ if (sdk === undefined) {
97+
+ for (const { name: sdkName } of sources) {
98+
+ if (methodMaps[sdkName]?.[methodName]) {
99+
+ return methodMaps[sdkName][methodName];
100+
+ }
101+
+ }
102+
+ } else {
103+
+ if (methodMaps[sdk]?.[methodName]) {
104+
+ return methodMaps[sdk][methodName];
105+
}
106+
}
107+
return undefined;
108+
@@ -158,7 +164,7 @@ function validateMethodCall(methodName, params) {
109+
logger.error('Method:');
110+
logger.error(methodName);
111+
logger.error('Params:');
112+
- logger.error(params);
113+
+ logger.error(JSON.stringify(params));
114+
logger.error('Exception:');
115+
logger.error(ex);
116+
errors.push(`ERROR: Could not validate call to method ${methodName} with params ${JSON.stringify(params)}`);
117+
@@ -180,8 +186,27 @@ function validateMethodResult(val, methodName) {
118+
if ( typeof val === 'string' && val.trimStart().startsWith('function') ) { return errors; }
119+
120+
try {
121+
- const oMethod = getMethod(methodName);
122+
- const oResult = oMethod.result;
123+
+ let oMethod = undefined;
124+
+ let oResult = undefined;
125+
+ if (config.dotConfig.bidirectional && methodName.includes('.on')) {
126+
+ let oMethod = getMethod(methodName, "coreToApp");
127+
+ if (oMethod && oMethod.tags) {
128+
+ const notifierTag = oMethod.tags.find(oTag => oTag['x-notifier-for']);
129+
+ if (notifierTag && notifierTag['x-notifier-for']) {
130+
+ methodName = notifierTag['x-notifier-for'];
131+
+ oMethod = getMethod(methodName);
132+
+ oResult = oMethod.result;
133+
+ } else {
134+
+ oResult = oMethod.params[0];
135+
+ }
136+
+ }
137+
+ }
138+
+ if (!oMethod) {
139+
+ oMethod = getMethod(methodName);
140+
+ }
141+
+ if (!oResult) {
142+
+ oResult = oMethod.result;
143+
+ }
144+
let oSchema = oResult.schema;
145+
if ( '$ref' in oSchema ) {
146+
const ref = oSchema['$ref'];
147+
@@ -199,12 +224,12 @@ function validateMethodResult(val, methodName) {
148+
} catch ( ex ) {
149+
logger.error('ERROR: Could not validate value:');
150+
logger.error('Value:');
151+
- logger.error(val);
152+
+ logger.error(JSON.stringify(val));
153+
logger.error('Method:');
154+
logger.error(methodName);
155+
logger.error('Exception:');
156+
logger.error(ex);
157+
- errors.push(`ERROR: Could not validate value ${val} for method ${methodName}`);
158+
+ errors.push(`ERROR: Could not validate value ${JSON.stringify(val)} for method ${methodName}`);
159+
160+
return errors; // Treat as invalid
161+
}
162+
diff --git a/server/src/routes/api/raw.mjs b/server/src/routes/api/raw.mjs
163+
new file mode 100644
164+
index 0000000..e6b20bd
165+
--- /dev/null
166+
+++ b/server/src/routes/api/raw.mjs
167+
@@ -0,0 +1,61 @@
168+
+/*
169+
+ * If not stated otherwise in this file or this component's LICENSE file the
170+
+ * following copyright and licenses apply:
171+
+ *
172+
+ * Copyright 2025 Sky UK
173+
+ *
174+
+ * Licensed under the Apache License, Version 2.0 (the "License");
175+
+ * you may not use this file except in compliance with the License.
176+
+ * You may obtain a copy of the License at
177+
+ *
178+
+ * http://www.apache.org/licenses/LICENSE-2.0
179+
+ *
180+
+ * Unless required by applicable law or agreed to in writing, software
181+
+ * distributed under the License is distributed on an "AS IS" BASIS,
182+
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
183+
+ * See the License for the specific language governing permissions and
184+
+ * limitations under the License.
185+
+ */
186+
+
187+
+// HTTP-based API routes: Raw, without any validation, just "jsonrpc": "2.0" field is being added to the paload
188+
+
189+
+'use strict';
190+
+
191+
+import { getUserIdFromReq } from '../../util.mjs';
192+
+import * as userManagement from '../../userManagement.mjs'
193+
+
194+
+// --- Route Handlers ---
195+
+
196+
+// POST /api/v1/raw
197+
+// Expected body: Any
198+
+function rawPayload(req, res) {
199+
+ try {
200+
+ const userId = getUserIdFromReq(req);
201+
+ const ws = userManagement.getWsForUser(userId)
202+
+
203+
+ const payload = {
204+
+ jsonrpc: "2.0",
205+
+ ...req.body
206+
+ };
207+
+
208+
+ console.log(`Sending raw payload: ${JSON.stringify(payload)}`);
209+
+
210+
+ ws.send(JSON.stringify(payload));
211+
+
212+
+ res.status(200).send({
213+
+ status: "Sent payload"
214+
+ })
215+
+ } catch (error) {
216+
+ console.error(error)
217+
+ res.status(500).send({
218+
+ status: "Cannot send payload",
219+
+ error
220+
+ })
221+
+ }
222+
+}
223+
+
224+
+// --- Exports ---
225+
+
226+
+export {
227+
+ rawPayload,
228+
+};

0 commit comments

Comments
 (0)