@ondc/automation-mock-runner 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/public/node-worker.js +225 -0
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ondc/automation-mock-runner",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "A TypeScript library for ONDC automation mock runner",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
9
|
"README.md",
|
|
10
|
-
"LICENSE"
|
|
10
|
+
"LICENSE",
|
|
11
|
+
"public"
|
|
11
12
|
],
|
|
12
13
|
"scripts": {
|
|
13
14
|
"build": "npm run clean && tsc",
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
const { parentPort } = require("worker_threads");
|
|
2
|
+
const vm = require("vm");
|
|
3
|
+
|
|
4
|
+
// Create a secure sandbox context
|
|
5
|
+
function createSandbox() {
|
|
6
|
+
const logs = [];
|
|
7
|
+
|
|
8
|
+
// Safe console implementation that captures logs
|
|
9
|
+
const safeConsole = {
|
|
10
|
+
log: (...args) => {
|
|
11
|
+
logs.push({
|
|
12
|
+
type: "log",
|
|
13
|
+
message: args
|
|
14
|
+
.map((arg) => {
|
|
15
|
+
try {
|
|
16
|
+
return typeof arg === "object"
|
|
17
|
+
? JSON.stringify(arg)
|
|
18
|
+
: String(arg);
|
|
19
|
+
} catch {
|
|
20
|
+
return "[Circular or Non-Serializable]";
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
.join(" "),
|
|
24
|
+
timestamp: Date.now(),
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
error: (...args) => {
|
|
28
|
+
logs.push({
|
|
29
|
+
type: "error",
|
|
30
|
+
message: args
|
|
31
|
+
.map((arg) => {
|
|
32
|
+
try {
|
|
33
|
+
return typeof arg === "object"
|
|
34
|
+
? JSON.stringify(arg)
|
|
35
|
+
: String(arg);
|
|
36
|
+
} catch {
|
|
37
|
+
return "[Circular or Non-Serializable]";
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
.join(" "),
|
|
41
|
+
timestamp: Date.now(),
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
warn: (...args) => {
|
|
45
|
+
logs.push({
|
|
46
|
+
type: "warn",
|
|
47
|
+
message: args
|
|
48
|
+
.map((arg) => {
|
|
49
|
+
try {
|
|
50
|
+
return typeof arg === "object"
|
|
51
|
+
? JSON.stringify(arg)
|
|
52
|
+
: String(arg);
|
|
53
|
+
} catch {
|
|
54
|
+
return "[Circular or Non-Serializable]";
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
.join(" "),
|
|
58
|
+
timestamp: Date.now(),
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
info: (...args) => {
|
|
62
|
+
logs.push({
|
|
63
|
+
type: "log",
|
|
64
|
+
message: args
|
|
65
|
+
.map((arg) => {
|
|
66
|
+
try {
|
|
67
|
+
return typeof arg === "object"
|
|
68
|
+
? JSON.stringify(arg)
|
|
69
|
+
: String(arg);
|
|
70
|
+
} catch {
|
|
71
|
+
return "[Circular or Non-Serializable]";
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.join(" "),
|
|
75
|
+
timestamp: Date.now(),
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Whitelist of safe global functions
|
|
81
|
+
const sandbox = {
|
|
82
|
+
console: safeConsole,
|
|
83
|
+
// Safe globals
|
|
84
|
+
Array,
|
|
85
|
+
Boolean,
|
|
86
|
+
Date,
|
|
87
|
+
Error,
|
|
88
|
+
// Function, // Removed - should not be accessible
|
|
89
|
+
JSON,
|
|
90
|
+
Math,
|
|
91
|
+
Number,
|
|
92
|
+
Object,
|
|
93
|
+
Promise,
|
|
94
|
+
RegExp,
|
|
95
|
+
String,
|
|
96
|
+
Symbol,
|
|
97
|
+
Map,
|
|
98
|
+
Set,
|
|
99
|
+
WeakMap,
|
|
100
|
+
WeakSet,
|
|
101
|
+
parseInt,
|
|
102
|
+
parseFloat,
|
|
103
|
+
isNaN,
|
|
104
|
+
isFinite,
|
|
105
|
+
encodeURI,
|
|
106
|
+
encodeURIComponent,
|
|
107
|
+
decodeURI,
|
|
108
|
+
decodeURIComponent,
|
|
109
|
+
// Utility functions for ONDC operations
|
|
110
|
+
setTimeout: (fn, delay) => {
|
|
111
|
+
if (delay < 1 || delay > 1000) {
|
|
112
|
+
throw new Error("Timeout must be between 1-1000ms");
|
|
113
|
+
}
|
|
114
|
+
return setTimeout(fn, delay);
|
|
115
|
+
},
|
|
116
|
+
clearTimeout,
|
|
117
|
+
// Blocked globals
|
|
118
|
+
require: undefined,
|
|
119
|
+
process: undefined,
|
|
120
|
+
global: undefined,
|
|
121
|
+
globalThis: undefined,
|
|
122
|
+
Buffer: undefined,
|
|
123
|
+
__dirname: undefined,
|
|
124
|
+
__filename: undefined,
|
|
125
|
+
module: undefined,
|
|
126
|
+
exports: undefined,
|
|
127
|
+
eval: undefined,
|
|
128
|
+
Function: undefined,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return { sandbox, logs };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Handle messages from main thread
|
|
135
|
+
parentPort?.on("message", async (message) => {
|
|
136
|
+
const { id, code, functionName, args, timeout } = message;
|
|
137
|
+
const startTime = Date.now();
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
// Create fresh sandbox for each execution
|
|
141
|
+
const { sandbox, logs } = createSandbox();
|
|
142
|
+
|
|
143
|
+
// Create VM context with timeout
|
|
144
|
+
const context = vm.createContext(sandbox);
|
|
145
|
+
|
|
146
|
+
// Compile and run the code with timeout
|
|
147
|
+
const script = new vm.Script(code, {
|
|
148
|
+
filename: `user-function-${id}.js`,
|
|
149
|
+
timeout: timeout || 5000,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
// Execute the script
|
|
153
|
+
script.runInContext(context, {
|
|
154
|
+
timeout: timeout || 5000,
|
|
155
|
+
breakOnSigint: true,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Get the function from the context
|
|
159
|
+
const userFunction = context[functionName];
|
|
160
|
+
|
|
161
|
+
if (typeof userFunction !== "function") {
|
|
162
|
+
throw new Error(`${functionName} is not a function`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Execute the function
|
|
166
|
+
const result = await Promise.race([
|
|
167
|
+
Promise.resolve(userFunction(...args)),
|
|
168
|
+
new Promise((_, reject) =>
|
|
169
|
+
setTimeout(
|
|
170
|
+
() => reject(new Error("Function execution timeout")),
|
|
171
|
+
timeout || 5000
|
|
172
|
+
)
|
|
173
|
+
),
|
|
174
|
+
]);
|
|
175
|
+
|
|
176
|
+
const executionTime = Date.now() - startTime;
|
|
177
|
+
|
|
178
|
+
// Serialize result safely
|
|
179
|
+
let serializedResult;
|
|
180
|
+
try {
|
|
181
|
+
serializedResult = JSON.parse(JSON.stringify(result));
|
|
182
|
+
} catch {
|
|
183
|
+
serializedResult = String(result);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
parentPort?.postMessage({
|
|
187
|
+
id,
|
|
188
|
+
success: true,
|
|
189
|
+
result: serializedResult,
|
|
190
|
+
logs,
|
|
191
|
+
executionTime,
|
|
192
|
+
});
|
|
193
|
+
} catch (error) {
|
|
194
|
+
const executionTime = Date.now() - startTime;
|
|
195
|
+
|
|
196
|
+
parentPort?.postMessage({
|
|
197
|
+
id,
|
|
198
|
+
success: false,
|
|
199
|
+
error: {
|
|
200
|
+
message: error.message || "Unknown error",
|
|
201
|
+
name: error.name || "Error",
|
|
202
|
+
stack: error.stack,
|
|
203
|
+
},
|
|
204
|
+
logs: [
|
|
205
|
+
{
|
|
206
|
+
type: "error",
|
|
207
|
+
message: error.message || "Unknown error",
|
|
208
|
+
timestamp: Date.now(),
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
executionTime,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Handle uncaught errors
|
|
217
|
+
process.on("uncaughtException", (error) => {
|
|
218
|
+
console.error("Uncaught exception in worker:", error);
|
|
219
|
+
process.exit(1);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
process.on("unhandledRejection", (reason, promise) => {
|
|
223
|
+
console.error("Unhandled rejection in worker:", reason);
|
|
224
|
+
process.exit(1);
|
|
225
|
+
});
|