@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 CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@ondc/automation-mock-runner",
3
- "version": "0.0.1",
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
+ });