runner-runtime 1.0.14 → 1.0.17

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/events/api.js CHANGED
@@ -10,6 +10,8 @@ const FileType = require("file-type"),
10
10
  Buffer = require("buffer/").Buffer,
11
11
  isImage = require("is-image");
12
12
  const { getAPIFromCollection, smartUrlJoin, replace2RegExp, getParentTargetIDs, base64toCacheFile, getInsideVariables, getCaseInsensitive, camelCaseToSnakeCase } = require('../libs/utils'),
13
+ { generateHarFromRequest } = require('../libs/2har'),
14
+
13
15
  _ = require('lodash');
14
16
  const sdk = require("postman-collection"),
15
17
  Url = sdk.Url,
@@ -2172,7 +2174,15 @@ module.exports = (event, option, callback, eventRuntimeData, eventResultList) =>
2172
2174
  }
2173
2175
  }
2174
2176
 
2175
- _.set(eventRuntimeData, [event?.event_id, "request"], convert2EchoRequest(request, requestJson, postmanJSON, history));
2177
+ const requestOptions = convert2EchoRequest(request, requestJson, postmanJSON, history);
2178
+ _.set(eventRuntimeData, [event?.event_id, "request"], requestOptions);
2179
+
2180
+ if (_.includes(['get_parsed_request'], scene)) {
2181
+ resolve(generateHarFromRequest(request));
2182
+ try {
2183
+ run.abort();
2184
+ } catch (e) { }
2185
+ }
2176
2186
  },
2177
2187
 
2178
2188
  beforeTest(err, cursor, events, item) {
@@ -2254,21 +2264,27 @@ module.exports = (event, option, callback, eventRuntimeData, eventResultList) =>
2254
2264
  }
2255
2265
 
2256
2266
  // 写入到自动化测试结果
2267
+ const finalRequestResult = _.assign({
2268
+ action: 'httpRequestCompleted',
2269
+ data: camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)),
2270
+ error: _.get(eventRuntimeData, [event?.event_id, 'error', 'message']) || null,
2271
+ event_id: event?.event_id,
2272
+ iteration_id: _.get(eventRuntimeData, [event?.event_id, 'iteration_id'])
2273
+ }, _.pick(requestJson, ['parent_id', 'project_id', 'test_id', 'target_id']));
2274
+
2257
2275
  if (scene === 'auto_test' && _.includes(['assert', 'assert_visual', 'api', 'sample'], event?.type)) {
2258
- eventResultList.push(_.assign(camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)), _.pick(event, ['type', 'event_id', 'test_id']), {
2259
- iteration_id: aTools.snowflakeId()
2260
- }))
2276
+ eventResultList.push(_.assign(camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)), _.pick(event, ['type', 'event_id', 'test_id', 'iteration_id'])));
2277
+
2278
+ resolve({
2279
+ action: 'request',
2280
+ data: _.assign(finalRequestResult, {
2281
+ type: 'request'
2282
+ })
2283
+ })
2284
+ } else {
2285
+ resolve(finalRequestResult)
2261
2286
  }
2262
2287
  }
2263
-
2264
- resolve(_.assign({
2265
- action: 'httpRequestCompleted',
2266
- data: camelCaseToSnakeCase(_.get(eventRuntimeData, event?.event_id)),
2267
- error: _.get(eventRuntimeData, [event?.event_id, 'error', 'message']) || null,
2268
- event_id: event?.event_id,
2269
- iteration_id: aTools.snowflakeId(),
2270
- type: 'request'
2271
- }, _.pick(requestJson, ['parent_id', 'project_id', 'test_id', 'target_id'])))
2272
2288
  }
2273
2289
  })
2274
2290
  }
package/events/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const atomicSleep = require("atomic-sleep"),
2
2
  jsonpath = require("jsonpath"),
3
+ aTools = require("apipost-tools"),
3
4
  JSON5 = require('json5'),
4
5
  _ = require('lodash'),
5
6
  { returnBoolean, variableReplace } = require('../libs/utils');
@@ -196,7 +197,9 @@ const events = {
196
197
  const executeEvent = (event, option, callback, eventRuntimeData, eventResultList) => {
197
198
  return new Promise((resolve, reject) => {
198
199
  if (_.isUndefined(_.get(eventRuntimeData, event.event_id))) {
199
- _.set(eventRuntimeData, event.event_id, {});
200
+ _.set(eventRuntimeData, event.event_id, {
201
+ iteration_id: aTools.snowflakeId()
202
+ });
200
203
  }
201
204
  const eventCall = _.get(events, `${event?.type}`);
202
205
 
@@ -208,10 +211,13 @@ const executeEvent = (event, option, callback, eventRuntimeData, eventResultList
208
211
  const { total, scene } = option;
209
212
  if (scene == 'auto_test' && _.isInteger(event?.progress)) {
210
213
  callback({
211
- action: 'inProcess',
212
- progress: event?.progress + 1,
213
- total,
214
- current_event_id: event?.event_id
214
+ action: 'process',
215
+ data: {
216
+ processCurrentCount: event?.progress + 1,
217
+ processTotalCount: total,
218
+ event_id: event?.event_id,
219
+ testing_id: event?.test_id,
220
+ }
215
221
  })
216
222
  }
217
223
  })
package/index.js CHANGED
@@ -19,21 +19,6 @@ const run = async (events, option, callback) => {
19
19
  if (scene == 'http_request') {
20
20
  const event = _.first(tempEvents);
21
21
 
22
- if (_.isObject(event) && _.has(event, 'type')) {
23
- try {
24
- const data = await executeEvent(event, _.assign(eventOptions, { iterationData: {} }), callback, eventRuntimeData, eventResultList);
25
- callback(data)
26
- } catch (e) {
27
- callback(e);
28
-
29
- if (_.includes(ABORT_RECURSION_ERROR, e?.action)) {
30
- throw new Error(String(e?.message));
31
- }
32
- }
33
- }
34
- } else if (scene == 'get_parsed_request') {
35
- const event = _.first(tempEvents);
36
-
37
22
  if (_.isObject(event) && _.has(event, 'type')) {
38
23
  try {
39
24
  const data = await executeEvent(event, _.assign(eventOptions, { iterationData: {} }), callback, eventRuntimeData, eventResultList);
@@ -72,4 +57,23 @@ const run = async (events, option, callback) => {
72
57
  })
73
58
  }
74
59
  }
75
- module.exports = { run }
60
+
61
+ const request2HAR = async (events, option) => {
62
+ const eventOptions = _.pick(option, ["scene", "lang", "project", "env", "globals", "cookies", "system_configs", "custom_functions", "collection", "database_configs", "enable_sandbox", "sleep", "name", "testing_id"]);
63
+ const eventRuntimeData = {
64
+ variables: {}
65
+ };
66
+ const eventResultList = [];
67
+ const event = _.first(events);
68
+
69
+ if (_.isObject(event) && _.has(event, 'type')) {
70
+ try {
71
+ return await executeEvent(event, _.assign(eventOptions, { scene: 'get_parsed_request' }), () => { }, eventRuntimeData, eventResultList);
72
+ } catch (e) {
73
+ if (_.includes(ABORT_RECURSION_ERROR, e?.action)) {
74
+ throw new Error(String(e?.message));
75
+ }
76
+ }
77
+ }
78
+ }
79
+ module.exports = { run, request2HAR }
package/libs/2har.js ADDED
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Converts a Postman-style request configuration into HAR format JSON.
3
+ *
4
+ * @param {Object} options - Request options based on Postman format.
5
+ * {
6
+ * url: string,
7
+ * method: string,
8
+ * headers: array,
9
+ * queryParams: array,
10
+ * body: {
11
+ * mode: string, // none | urlencoded | formdata | raw | json
12
+ * [urlencoded]: array, // For urlencoded form data
13
+ * [formdata]: array, // For multipart/form-data
14
+ * [raw]: string, // For raw (text or binary)
15
+ * [json]: object // For JSON body
16
+ * }
17
+ * }
18
+ * @returns {Object} HAR format JSON object.
19
+ */
20
+ function generateHarFromRequest(options) {
21
+ const {
22
+ url,
23
+ method = 'GET',
24
+ headers = [], // Array of { key, value }
25
+ queryParams = [], // Array of { key, value }
26
+ body = { mode: 'none' }, // Body in Postman format
27
+ } = options;
28
+
29
+ const har = {
30
+ log: {
31
+ version: '1.2',
32
+ creator: {
33
+ name: 'Custom Node Request to HAR Converter',
34
+ version: '1.0',
35
+ },
36
+ entries: [
37
+ {
38
+ request: {
39
+ method: method.toUpperCase(),
40
+ url: appendQueryParams(url, queryParams),
41
+ headers: processHeaders(headers),
42
+ queryString: processQueryString(queryParams),
43
+ postData: processBody(body),
44
+ headersSize: -1, // Optional, usually auto-calculated
45
+ bodySize: -1, // Optional, usually auto-calculated
46
+ },
47
+ startedDateTime: new Date().toISOString(),
48
+ time: 0, // Mock timing data (replace with actual timing if needed)
49
+ },
50
+ ],
51
+ },
52
+ };
53
+
54
+ return har;
55
+ }
56
+
57
+ /**
58
+ * Appends query parameters to a URL.
59
+ * @param {string} url - The base URL.
60
+ * @param {Array} queryParams - Array of { key: string, value: string }.
61
+ * @returns {string} URL with query parameters appended.
62
+ */
63
+ function appendQueryParams(url, queryParams) {
64
+ if (!queryParams || queryParams.length === 0) return url;
65
+
66
+ const searchParams = new URLSearchParams();
67
+ queryParams.forEach(({ key, value }) => {
68
+ searchParams.append(key, value);
69
+ });
70
+
71
+ return `${url}?${searchParams.toString()}`;
72
+ }
73
+
74
+ /**
75
+ * Converts Postman-style headers into HAR format.
76
+ * @param {Array} headers - Array of { key: string, value: string }.
77
+ * @returns {Array} Array of HAR headers.
78
+ */
79
+ function processHeaders(headers) {
80
+ return (headers || []).map(({ key, value }) => ({
81
+ name: key,
82
+ value: value,
83
+ }));
84
+ }
85
+
86
+ /**
87
+ * Converts Postman-style query parameters into HAR format.
88
+ * @param {Array} queryParams - Array of { key: string, value: string }.
89
+ * @returns {Array} Array of HAR query parameters.
90
+ */
91
+ function processQueryString(queryParams) {
92
+ return (queryParams || []).map(({ key, value }) => ({
93
+ name: key,
94
+ value: String(value),
95
+ }));
96
+ }
97
+
98
+ /**
99
+ * Processes the body into HAR format based on its mode.
100
+ * @param {Object} body - Postman-style body object with a defined mode.
101
+ * @returns {Object|undefined} HAR postData object.
102
+ */
103
+ function processBody(body) {
104
+ const { mode } = body;
105
+
106
+ if (mode === 'none') {
107
+ return undefined; // No body
108
+ }
109
+
110
+ if (mode === 'urlencoded') {
111
+ return {
112
+ mimeType: 'application/x-www-form-urlencoded',
113
+ params: (body.urlencoded || []).map(({ key, value }) => ({
114
+ name: key,
115
+ value: String(value),
116
+ })),
117
+ };
118
+ }
119
+
120
+ if (mode === 'formdata') {
121
+ return {
122
+ mimeType: 'multipart/form-data',
123
+ params: (body.formdata || []).map(({ key, value, type = 'text' }) => {
124
+ const param = { name: key, value: String(value) };
125
+ if (type === 'file') param.fileName = value; // File handling
126
+ return param;
127
+ }),
128
+ };
129
+ }
130
+
131
+ if (mode === 'raw') {
132
+ return {
133
+ mimeType: 'text/plain',
134
+ text: String(body.raw),
135
+ };
136
+ }
137
+
138
+ if (mode === 'json') {
139
+ return {
140
+ mimeType: 'application/json',
141
+ text: JSON.stringify(body.json || {}),
142
+ };
143
+ }
144
+
145
+ return undefined; // No body
146
+ }
147
+
148
+ module.exports = { generateHarFromRequest };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "runner-runtime",
3
- "version": "1.0.14",
4
- "description": "Processing data returned by AI.",
3
+ "version": "1.0.17",
4
+ "description": "runner-runtime.",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -11,7 +11,7 @@
11
11
  "url": "git+https://github.com/Apipost-Team/runner-runtime.git"
12
12
  },
13
13
  "keywords": [
14
- "auto-json-faker"
14
+ "runner-runtime"
15
15
  ],
16
16
  "author": "Daniel Anderson <support@echoapi.com> (https://github.com/Apipost-Team)",
17
17
  "license": "MIT",
@@ -24,6 +24,7 @@
24
24
  "apipost-tools": "^0.0.38",
25
25
  "atomic-sleep": "^1.0.0",
26
26
  "content-disposition": "^0.5.4",
27
+ "database-query": "^1.1.12",
27
28
  "exp-mock": "^2.0.15",
28
29
  "file-type": "^16.5.4",
29
30
  "is-image": "^3.0.0",
@@ -39,6 +40,7 @@
39
40
  "net": "^1.0.2",
40
41
  "postman-collection": "^5.0.2",
41
42
  "postman-runtime-pro": "^7.43.13",
43
+ "request-har": "^1.0.0",
42
44
  "strip-json-comments": "^5.0.1",
43
45
  "tough": "^0.6.0",
44
46
  "tough-cookie": "^5.1.2",
package/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const _ =require('lodash');
2
- const { run } = require('./index');
2
+ const { request2HAR } = require('./index');
3
3
 
4
4
  // 以下为调用示例
5
5
  const callback = (res) => {
@@ -121,4 +121,4 @@ const callback = (res) => {
121
121
  })();
122
122
  //pip end
123
123
  const { option, test_events } = require('./tmp/request'); // tmp todo...
124
- run(test_events, option, callback);
124
+ request2HAR(test_events, option, callback);
package/tmp/request.js CHANGED
@@ -192,7 +192,7 @@ module.exports = {
192
192
  "parents": [],
193
193
  "method": "POST",
194
194
  "protocol": "http/1.1",
195
- "url": "http://cc.apipost.cc:6002/sse",
195
+ "url": "https://echo.apipost.cn/userlogin.php",
196
196
  "pre_url": "1"
197
197
  }
198
198
  ],