@usebruno/filestore 0.5.0 → 0.6.0

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.
Files changed (157) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/workers/worker-script.js +1 -1
  4. package/dist/cjs/workers/worker-script.js.map +1 -1
  5. package/dist/esm/index.js +1 -1
  6. package/dist/esm/index.js.map +1 -1
  7. package/dist/esm/workers/worker-script.js +1 -1
  8. package/dist/esm/workers/worker-script.js.map +1 -1
  9. package/dist/formats/bru/index.d.ts +20 -0
  10. package/dist/formats/bru/index.d.ts.map +1 -0
  11. package/dist/formats/bru/tests/fixtures/oauth2-additional-params.d.ts +57 -0
  12. package/dist/formats/bru/tests/fixtures/oauth2-additional-params.d.ts.map +1 -0
  13. package/dist/formats/bru/tests/oauth2-additional-params.spec.d.ts +2 -0
  14. package/dist/formats/bru/tests/oauth2-additional-params.spec.d.ts.map +1 -0
  15. package/dist/formats/bru/tests/request-parse-and-redact-body-data.spec.d.ts +2 -0
  16. package/dist/formats/bru/tests/request-parse-and-redact-body-data.spec.d.ts.map +1 -0
  17. package/dist/{cjs/workers/formats → formats}/bru/utils/oauth2-additional-params.d.ts +1 -0
  18. package/dist/formats/bru/utils/oauth2-additional-params.d.ts.map +1 -0
  19. package/dist/{esm/formats → formats}/bru/utils/request-parse-and-redact-body-data.d.ts +1 -0
  20. package/dist/formats/bru/utils/request-parse-and-redact-body-data.d.ts.map +1 -0
  21. package/dist/formats/yml/common/actions.d.ts +14 -0
  22. package/dist/formats/yml/common/actions.d.ts.map +1 -0
  23. package/dist/formats/yml/common/assertions.d.ts +5 -0
  24. package/dist/formats/yml/common/assertions.d.ts.map +1 -0
  25. package/dist/formats/yml/common/auth-oauth2.d.ts +5 -0
  26. package/dist/formats/yml/common/auth-oauth2.d.ts.map +1 -0
  27. package/dist/formats/yml/common/auth.d.ts +5 -0
  28. package/dist/formats/yml/common/auth.d.ts.map +1 -0
  29. package/dist/formats/yml/common/body.d.ts +5 -0
  30. package/dist/formats/yml/common/body.d.ts.map +1 -0
  31. package/dist/formats/yml/common/headers.d.ts +7 -0
  32. package/dist/formats/yml/common/headers.d.ts.map +1 -0
  33. package/dist/formats/yml/common/params.d.ts +5 -0
  34. package/dist/formats/yml/common/params.d.ts.map +1 -0
  35. package/dist/formats/yml/common/scripts.d.ts +14 -0
  36. package/dist/formats/yml/common/scripts.d.ts.map +1 -0
  37. package/dist/formats/yml/common/variables.d.ts +17 -0
  38. package/dist/formats/yml/common/variables.d.ts.map +1 -0
  39. package/dist/formats/yml/index.d.ts +10 -0
  40. package/dist/formats/yml/index.d.ts.map +1 -0
  41. package/dist/formats/yml/items/parseGraphQLRequest.d.ts +5 -0
  42. package/dist/formats/yml/items/parseGraphQLRequest.d.ts.map +1 -0
  43. package/dist/formats/yml/items/parseGrpcRequest.d.ts +5 -0
  44. package/dist/formats/yml/items/parseGrpcRequest.d.ts.map +1 -0
  45. package/dist/formats/yml/items/parseHttpRequest.d.ts +5 -0
  46. package/dist/formats/yml/items/parseHttpRequest.d.ts.map +1 -0
  47. package/dist/formats/yml/items/parseScript.d.ts +5 -0
  48. package/dist/formats/yml/items/parseScript.d.ts.map +1 -0
  49. package/dist/formats/yml/items/parseWebsocketRequest.d.ts +5 -0
  50. package/dist/formats/yml/items/parseWebsocketRequest.d.ts.map +1 -0
  51. package/dist/formats/yml/items/stringifyGraphQLRequest.d.ts +4 -0
  52. package/dist/formats/yml/items/stringifyGraphQLRequest.d.ts.map +1 -0
  53. package/dist/formats/yml/items/stringifyGrpcRequest.d.ts +4 -0
  54. package/dist/formats/yml/items/stringifyGrpcRequest.d.ts.map +1 -0
  55. package/dist/formats/yml/items/stringifyHttpRequest.d.ts +4 -0
  56. package/dist/formats/yml/items/stringifyHttpRequest.d.ts.map +1 -0
  57. package/dist/formats/yml/items/stringifyScript.d.ts +4 -0
  58. package/dist/formats/yml/items/stringifyScript.d.ts.map +1 -0
  59. package/dist/formats/yml/items/stringifyWebsocketRequest.d.ts +4 -0
  60. package/dist/formats/yml/items/stringifyWebsocketRequest.d.ts.map +1 -0
  61. package/dist/formats/yml/parseCollection.d.ts +8 -0
  62. package/dist/formats/yml/parseCollection.d.ts.map +1 -0
  63. package/dist/formats/yml/parseEnvironment.d.ts +4 -0
  64. package/dist/formats/yml/parseEnvironment.d.ts.map +1 -0
  65. package/dist/formats/yml/parseFolder.d.ts +4 -0
  66. package/dist/formats/yml/parseFolder.d.ts.map +1 -0
  67. package/dist/formats/yml/parseItem.d.ts +4 -0
  68. package/dist/formats/yml/parseItem.d.ts.map +1 -0
  69. package/dist/formats/yml/stringifyCollection.d.ts +3 -0
  70. package/dist/formats/yml/stringifyCollection.d.ts.map +1 -0
  71. package/dist/formats/yml/stringifyEnvironment.d.ts +4 -0
  72. package/dist/formats/yml/stringifyEnvironment.d.ts.map +1 -0
  73. package/dist/formats/yml/stringifyFolder.d.ts +4 -0
  74. package/dist/formats/yml/stringifyFolder.d.ts.map +1 -0
  75. package/dist/formats/yml/stringifyItem.d.ts +4 -0
  76. package/dist/formats/yml/stringifyItem.d.ts.map +1 -0
  77. package/dist/formats/yml/utils.d.ts +3 -0
  78. package/dist/formats/yml/utils.d.ts.map +1 -0
  79. package/dist/{cjs/workers/index.d.ts → index.d.ts} +13 -6
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/types.d.ts +19 -0
  82. package/dist/types.d.ts.map +1 -0
  83. package/dist/utils/index.d.ts +5 -0
  84. package/dist/utils/index.d.ts.map +1 -0
  85. package/dist/{esm/workers → workers}/WorkerQueue/index.d.ts +1 -0
  86. package/dist/workers/WorkerQueue/index.d.ts.map +1 -0
  87. package/dist/workers/index.d.ts +12 -0
  88. package/dist/workers/index.d.ts.map +1 -0
  89. package/dist/workers/worker-script.d.ts +2 -0
  90. package/dist/workers/worker-script.d.ts.map +1 -0
  91. package/package.json +12 -6
  92. package/src/formats/bru/index.ts +9 -9
  93. package/src/formats/bru/tests/oauth2-additional-params.spec.js +1 -1
  94. package/src/formats/bru/utils/oauth2-additional-params.ts +17 -18
  95. package/src/formats/bru/utils/request-parse-and-redact-body-data.ts +13 -13
  96. package/src/formats/yml/common/actions.ts +78 -0
  97. package/src/formats/yml/common/assertions.ts +146 -0
  98. package/src/formats/yml/common/auth-oauth2.ts +555 -0
  99. package/src/formats/yml/common/auth.ts +245 -0
  100. package/src/formats/yml/common/body.ts +238 -0
  101. package/src/formats/yml/common/headers.ts +58 -0
  102. package/src/formats/yml/common/params.ts +57 -0
  103. package/src/formats/yml/common/scripts.ts +64 -0
  104. package/src/formats/yml/common/variables.ts +68 -0
  105. package/src/formats/yml/index.ts +20 -0
  106. package/src/formats/yml/items/parseGraphQLRequest.ts +137 -0
  107. package/src/formats/yml/items/parseGrpcRequest.ts +116 -0
  108. package/src/formats/yml/items/parseHttpRequest.ts +195 -0
  109. package/src/formats/yml/items/parseScript.ts +25 -0
  110. package/src/formats/yml/items/parseWebsocketRequest.ts +106 -0
  111. package/src/formats/yml/items/stringifyGraphQLRequest.ts +168 -0
  112. package/src/formats/yml/items/stringifyGrpcRequest.ts +137 -0
  113. package/src/formats/yml/items/stringifyHttpRequest.ts +221 -0
  114. package/src/formats/yml/items/stringifyScript.ts +22 -0
  115. package/src/formats/yml/items/stringifyWebsocketRequest.ts +114 -0
  116. package/src/formats/yml/parseCollection.ts +198 -0
  117. package/src/formats/yml/parseEnvironment.ts +56 -0
  118. package/src/formats/yml/parseFolder.ts +88 -0
  119. package/src/formats/yml/parseItem.ts +102 -0
  120. package/src/formats/yml/stringifyCollection.ts +230 -0
  121. package/src/formats/yml/stringifyEnvironment.ts +64 -0
  122. package/src/formats/yml/stringifyFolder.ts +96 -0
  123. package/src/formats/yml/stringifyItem.ts +37 -0
  124. package/src/formats/yml/utils.ts +38 -0
  125. package/src/index.ts +57 -27
  126. package/src/types/bruno-lang.d.ts +1 -1
  127. package/src/types.ts +5 -124
  128. package/src/utils/index.ts +15 -0
  129. package/src/workers/WorkerQueue/index.ts +10 -10
  130. package/src/workers/index.ts +20 -20
  131. package/src/workers/worker-script.ts +20 -6
  132. package/dist/cjs/formats/bru/index.d.ts +0 -19
  133. package/dist/cjs/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
  134. package/dist/cjs/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
  135. package/dist/cjs/index.d.ts +0 -16
  136. package/dist/cjs/types.d.ts +0 -142
  137. package/dist/cjs/workers/WorkerQueue/index.d.ts +0 -26
  138. package/dist/cjs/workers/formats/bru/index.d.ts +0 -19
  139. package/dist/cjs/workers/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
  140. package/dist/cjs/workers/types.d.ts +0 -142
  141. package/dist/cjs/workers/worker-script.d.ts +0 -1
  142. package/dist/cjs/workers/workers/WorkerQueue/index.d.ts +0 -26
  143. package/dist/cjs/workers/workers/index.d.ts +0 -10
  144. package/dist/cjs/workers/workers/worker-script.d.ts +0 -1
  145. package/dist/esm/formats/bru/index.d.ts +0 -19
  146. package/dist/esm/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
  147. package/dist/esm/index.d.ts +0 -16
  148. package/dist/esm/types.d.ts +0 -142
  149. package/dist/esm/workers/formats/bru/index.d.ts +0 -19
  150. package/dist/esm/workers/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
  151. package/dist/esm/workers/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
  152. package/dist/esm/workers/index.d.ts +0 -16
  153. package/dist/esm/workers/types.d.ts +0 -142
  154. package/dist/esm/workers/worker-script.d.ts +0 -1
  155. package/dist/esm/workers/workers/WorkerQueue/index.d.ts +0 -26
  156. package/dist/esm/workers/workers/index.d.ts +0 -10
  157. package/dist/esm/workers/workers/worker-script.d.ts +0 -1
@@ -9,7 +9,7 @@ import {
9
9
  } from '@usebruno/lang';
10
10
  import { getOauth2AdditionalParameters } from './utils/oauth2-additional-params';
11
11
 
12
- export const bruRequestToJson = (data: string | any, parsed: boolean = false): any => {
12
+ export const parseBruRequest = (data: string | any, parsed: boolean = false): any => {
13
13
  try {
14
14
  const json = parsed ? data : bruToJsonV2(data);
15
15
 
@@ -109,12 +109,12 @@ export const bruRequestToJson = (data: string | any, parsed: boolean = false): a
109
109
  }
110
110
  return transformedJson;
111
111
  } catch (error) {
112
- console.log('bruRequestToJson error', error);
112
+ console.log('parseBruRequest error', error);
113
113
  throw error;
114
114
  }
115
115
  };
116
116
 
117
- export const jsonRequestToBru = (json: any): string => {
117
+ export const stringifyBruRequest = (json: any): string => {
118
118
  try {
119
119
  let type = _.get(json, 'type');
120
120
  switch (type) {
@@ -160,8 +160,8 @@ export const jsonRequestToBru = (json: any): string => {
160
160
  mode: 'json',
161
161
  json: '{}'
162
162
  });
163
- } // For gRPC, add gRPC-specific structure but maintain field names
164
- else if (type === 'grpc') {
163
+ } else if (type === 'grpc') {
164
+ // For gRPC, add gRPC-specific structure but maintain field names
165
165
  bruJson.grpc = {
166
166
  url: _.get(json, 'request.url'),
167
167
  auth: _.get(json, 'request.auth.mode', 'none'),
@@ -227,7 +227,7 @@ export const jsonRequestToBru = (json: any): string => {
227
227
  }
228
228
  };
229
229
 
230
- export const bruCollectionToJson = (data: string | any, parsed: boolean = false): any => {
230
+ export const parseBruCollection = (data: string | any, parsed: boolean = false): any => {
231
231
  try {
232
232
  const json = parsed ? data : _collectionBruToJson(data);
233
233
 
@@ -273,7 +273,7 @@ export const bruCollectionToJson = (data: string | any, parsed: boolean = false)
273
273
  }
274
274
  };
275
275
 
276
- export const jsonCollectionToBru = (json: any, isFolder?: boolean): string => {
276
+ export const stringifyBruCollection = (json: any, isFolder?: boolean): string => {
277
277
  try {
278
278
  const collectionBruJson: any = {
279
279
  headers: _.get(json, 'request.headers', []),
@@ -314,7 +314,7 @@ export const jsonCollectionToBru = (json: any, isFolder?: boolean): string => {
314
314
  }
315
315
  };
316
316
 
317
- export const bruEnvironmentToJson = (bru: string): any => {
317
+ export const parseBruEnvironment = (bru: string): any => {
318
318
  try {
319
319
  const json = bruToEnvJsonV2(bru);
320
320
 
@@ -331,7 +331,7 @@ export const bruEnvironmentToJson = (bru: string): any => {
331
331
  }
332
332
  };
333
333
 
334
- export const jsonEnvironmentToBru = (json: any): string => {
334
+ export const stringifyBruEnvironment = (json: any): string => {
335
335
  try {
336
336
  const bru = envJsonToBruV2(json);
337
337
  return bru;
@@ -1,5 +1,5 @@
1
1
  const { getOauth2AdditionalParameters } = require('../utils/oauth2-additional-params');
2
- const { bruRequestToJson, bruCollectionToJson } = require('../index');
2
+ const { parseBruRequest, parseBruCollection } = require('../index');
3
3
  const { getBruJsonWithAdditionalParams } = require('./fixtures/oauth2-additional-params');
4
4
 
5
5
  describe('getOauth2AdditionalParameters', () => {
@@ -5,7 +5,7 @@ export interface T_OAuth2AdditionalParam {
5
5
  name: string;
6
6
  value: string;
7
7
  enabled: boolean;
8
- sendIn: T_Oauth2ParameterSendInType
8
+ sendIn: T_Oauth2ParameterSendInType;
9
9
  }
10
10
 
11
11
  export interface T_OAuth2AdditionalParameters {
@@ -43,16 +43,16 @@ const PARAMETER_MAPPINGS: T_Oauth2ParameterMapping[] = [
43
43
  // Authorization parameters (only for authorization_code grant type)
44
44
  { type: 'authorization', sendIn: 'headers', source: 'oauth2_additional_parameters_auth_req_headers' },
45
45
  { type: 'authorization', sendIn: 'queryparams', source: 'oauth2_additional_parameters_auth_req_queryparams' },
46
-
46
+
47
47
  // Token parameters (for all grant types)
48
48
  { type: 'token', sendIn: 'headers', source: 'oauth2_additional_parameters_access_token_req_headers' },
49
49
  { type: 'token', sendIn: 'queryparams', source: 'oauth2_additional_parameters_access_token_req_queryparams' },
50
50
  { type: 'token', sendIn: 'body', source: 'oauth2_additional_parameters_access_token_req_bodyvalues' },
51
-
51
+
52
52
  // Refresh parameters (for grant types that support refresh)
53
53
  { type: 'refresh', sendIn: 'headers', source: 'oauth2_additional_parameters_refresh_token_req_headers' },
54
54
  { type: 'refresh', sendIn: 'queryparams', source: 'oauth2_additional_parameters_refresh_token_req_queryparams' },
55
- { type: 'refresh', sendIn: 'body', source: 'oauth2_additional_parameters_refresh_token_req_bodyvalues' },
55
+ { type: 'refresh', sendIn: 'body', source: 'oauth2_additional_parameters_refresh_token_req_bodyvalues' }
56
56
  ];
57
57
 
58
58
  /**
@@ -62,8 +62,8 @@ const mapParametersFromSource = (sourceParams: any[], sendIn: T_Oauth2ParameterS
62
62
  if (!sourceParams?.length) {
63
63
  return [];
64
64
  }
65
-
66
- return sourceParams.map(param => ({
65
+
66
+ return sourceParams.map((param) => ({
67
67
  ...param,
68
68
  sendIn
69
69
  }));
@@ -81,7 +81,7 @@ const shouldIncludeParameterType = (type: T_Oauth2ParameterType, grantType: stri
81
81
  if (type === 'token' || type === 'refresh') {
82
82
  return grantType !== 'implicit';
83
83
  }
84
-
84
+
85
85
  // Token and refresh parameters are valid for all grant types
86
86
  return true;
87
87
  };
@@ -90,15 +90,15 @@ const shouldIncludeParameterType = (type: T_Oauth2ParameterType, grantType: stri
90
90
  * Collects all parameters for a specific type (authorization, token, or refresh)
91
91
  */
92
92
  const collectParametersForType = (
93
- json: T_BruJson,
94
- type: T_Oauth2ParameterType,
93
+ json: T_BruJson,
94
+ type: T_Oauth2ParameterType,
95
95
  grantType: string
96
96
  ): T_OAuth2AdditionalParam[] => {
97
97
  if (!shouldIncludeParameterType(type, grantType)) {
98
98
  return [];
99
99
  }
100
100
 
101
- const relevantMappings = PARAMETER_MAPPINGS.filter(mapping => mapping.type === type);
101
+ const relevantMappings = PARAMETER_MAPPINGS.filter((mapping) => mapping.type === type);
102
102
  const allParams: T_OAuth2AdditionalParam[] = [];
103
103
 
104
104
  for (const mapping of relevantMappings) {
@@ -113,29 +113,28 @@ const collectParametersForType = (
113
113
  /**
114
114
  * This function extracts OAuth2 additional parameters from various sources in the bru json data and organizes
115
115
  * them into a structured format based on their usage context (authorization, token, refresh).
116
- *
116
+ *
117
117
  * @param json - json object containing OAuth2 configuration and additional parameters
118
118
  * @returns OAuth2 additional parameters
119
119
  */
120
- export const getOauth2AdditionalParameters = (json: T_BruJson): T_OAuth2AdditionalParameters => {
120
+ export const getOauth2AdditionalParameters = (json: T_BruJson): T_OAuth2AdditionalParameters => {
121
121
  const grantType = json.auth.oauth2.grantType;
122
122
  const additionalParameters: T_OAuth2AdditionalParameters = {};
123
123
 
124
124
  try {
125
125
  // Collect parameters for each type
126
126
  const parameterTypes: T_Oauth2ParameterType[] = ['authorization', 'token', 'refresh'];
127
-
127
+
128
128
  for (const type of parameterTypes) {
129
129
  const params = collectParametersForType(json, type, grantType);
130
130
  if (params.length > 0) {
131
131
  additionalParameters[type] = params;
132
132
  }
133
133
  }
134
- }
135
- catch(error) {
134
+ } catch (error) {
136
135
  console.error(error);
137
- console.error("Error while getting the oauth2 additional parameters!");
136
+ console.error('Error while getting the oauth2 additional parameters!');
138
137
  }
139
-
138
+
140
139
  return additionalParameters;
141
- };
140
+ };
@@ -7,11 +7,11 @@ export const bruRequestParseAndRedactBodyData = (bruFileContent: string) => {
7
7
  try {
8
8
  // Define the patterns that indicate the start of different body types
9
9
  const bodyTypePatterns = [
10
- "body:json {",
11
- "body:text {",
12
- "body:xml {",
13
- "body:sparql {",
14
- "body:graphql {"
10
+ 'body:json {',
11
+ 'body:text {',
12
+ 'body:xml {',
13
+ 'body:sparql {',
14
+ 'body:graphql {'
15
15
  ];
16
16
 
17
17
  // Normalize line endings to LF
@@ -37,30 +37,30 @@ export const bruRequestParseAndRedactBodyData = (bruFileContent: string) => {
37
37
 
38
38
  // Split the file content into blocks
39
39
  let fileContentBlocks = bruFileContent.split(`${EOL}}${EOL}`);
40
- fileContentBlocks = fileContentBlocks.filter(Boolean).map(_ => _.trim());
40
+ fileContentBlocks = fileContentBlocks.filter(Boolean).map((_) => _.trim());
41
41
 
42
42
  // Extract body blocks and their content
43
43
  const extractedBodyBlocks = fileContentBlocks
44
- .filter(block => bodyTypePatterns.some(pattern => block.startsWith(pattern)))
44
+ .filter((block) => bodyTypePatterns.some((pattern) => block.startsWith(pattern)))
45
45
  .reduce((bodyContentMap: Record<string, string>, bodyBlock) => {
46
46
  // Extract the body type (json, text, xml, etc.) from the first line
47
47
  const firstLine = bodyBlock.split(EOL)[0];
48
48
  const bodyType = firstLine.split(`body:`)[1].split(/\s/)[0];
49
-
49
+
50
50
  // Extract the body content (everything between the opening and closing braces)
51
51
  const bodyContentLines = bodyBlock.split(EOL).slice(1);
52
52
  const rawBodyContent = bodyContentLines.join(EOL);
53
-
53
+
54
54
  // Remove indentation from the body content
55
55
  const cleanBodyContent = removeLeadingIndentation(rawBodyContent);
56
-
56
+
57
57
  bodyContentMap[bodyType] = cleanBodyContent;
58
58
  return bodyContentMap;
59
59
  }, {});
60
60
 
61
61
  // Filter out body blocks to get the remaining file content
62
- const fileContentWithoutBodyBlocks = fileContentBlocks.filter(block =>
63
- !bodyTypePatterns.some(pattern => block.startsWith(pattern))
62
+ const fileContentWithoutBodyBlocks = fileContentBlocks.filter((block) =>
63
+ !bodyTypePatterns.some((pattern) => block.startsWith(pattern))
64
64
  );
65
65
 
66
66
  return {
@@ -74,4 +74,4 @@ export const bruRequestParseAndRedactBodyData = (bruFileContent: string) => {
74
74
  extractedBodyContent: {}
75
75
  };
76
76
  }
77
- };
77
+ };
@@ -0,0 +1,78 @@
1
+ import type { Action, ActionSetVariable, ActionVariableScope } from '@opencollection/types/common/actions';
2
+ import type { Variable as BrunoVariable, Variables as BrunoVariables } from '@usebruno/schema-types/common/variables';
3
+ import { uuid } from '../../../utils';
4
+
5
+ /**
6
+ * Convert Bruno post-response variables to OpenCollection actions.
7
+ * Post-response variables in Bruno are converted to 'set-variable' actions
8
+ * with phase 'after-response'.
9
+ */
10
+ export const toOpenCollectionActions = (resVariables: BrunoVariables | null | undefined): Action[] | undefined => {
11
+ if (!resVariables?.length) {
12
+ return undefined;
13
+ }
14
+
15
+ const actions: Action[] = resVariables.map((v: BrunoVariable): ActionSetVariable => {
16
+ const action: ActionSetVariable = {
17
+ type: 'set-variable',
18
+ phase: 'after-response',
19
+ selector: {
20
+ expression: v.value || '',
21
+ method: 'jsonq'
22
+ },
23
+ variable: {
24
+ name: v.name || '',
25
+ scope: v.local ? 'request' : 'runtime' as ActionVariableScope
26
+ }
27
+ };
28
+
29
+ if (v.description?.trim().length) {
30
+ action.description = v.description;
31
+ }
32
+
33
+ if (v.enabled === false) {
34
+ action.disabled = true;
35
+ }
36
+
37
+ return action;
38
+ });
39
+
40
+ return actions.length > 0 ? actions : undefined;
41
+ };
42
+
43
+ /**
44
+ * Convert OpenCollection actions to Bruno post-response variables.
45
+ * Only 'set-variable' actions with phase 'after-response' are converted.
46
+ */
47
+ export const toBrunoPostResponseVariables = (actions: Action[] | null | undefined): BrunoVariables => {
48
+ if (!actions?.length) {
49
+ return [];
50
+ }
51
+
52
+ const resVars: BrunoVariables = [];
53
+
54
+ actions.forEach((action: Action) => {
55
+ // Only process 'set-variable' actions with 'after-response' phase
56
+ if (action.type === 'set-variable' && action.phase === 'after-response') {
57
+ const setVarAction = action as ActionSetVariable;
58
+
59
+ const variable: BrunoVariable = {
60
+ uid: uuid(),
61
+ name: setVarAction.variable?.name || '',
62
+ value: setVarAction.selector?.expression || '',
63
+ enabled: setVarAction.disabled !== true,
64
+ local: false
65
+ };
66
+
67
+ if (setVarAction.description) {
68
+ variable.description = typeof setVarAction.description === 'string'
69
+ ? setVarAction.description
70
+ : (setVarAction.description as any)?.content || '';
71
+ }
72
+
73
+ resVars.push(variable);
74
+ }
75
+ });
76
+
77
+ return resVars;
78
+ };
@@ -0,0 +1,146 @@
1
+ import type { KeyValue as BrunoKeyValue } from '@usebruno/schema-types/common/key-value';
2
+ import type { Assertion } from '@opencollection/types/common/assertions';
3
+ import { uuid } from '../../../utils';
4
+
5
+ const OPERATORS = [
6
+ 'eq',
7
+ 'neq',
8
+ 'gt',
9
+ 'gte',
10
+ 'lt',
11
+ 'lte',
12
+ 'in',
13
+ 'notIn',
14
+ 'contains',
15
+ 'notContains',
16
+ 'length',
17
+ 'matches',
18
+ 'notMatches',
19
+ 'startsWith',
20
+ 'endsWith',
21
+ 'between',
22
+ 'isEmpty',
23
+ 'isNotEmpty',
24
+ 'isNull',
25
+ 'isUndefined',
26
+ 'isDefined',
27
+ 'isTruthy',
28
+ 'isFalsy',
29
+ 'isJson',
30
+ 'isNumber',
31
+ 'isString',
32
+ 'isBoolean',
33
+ 'isArray'
34
+ ] as const;
35
+
36
+ const UNARY_OPERATORS = [
37
+ 'isEmpty',
38
+ 'isNotEmpty',
39
+ 'isNull',
40
+ 'isUndefined',
41
+ 'isDefined',
42
+ 'isTruthy',
43
+ 'isFalsy',
44
+ 'isJson',
45
+ 'isNumber',
46
+ 'isString',
47
+ 'isBoolean',
48
+ 'isArray'
49
+ ] as const;
50
+
51
+ type Operator = typeof OPERATORS[number];
52
+
53
+ const parseAssertionOperator = (str: string = ''): { operator: Operator; value: string | undefined } => {
54
+ if (!str || typeof str !== 'string' || !str.length) {
55
+ return {
56
+ operator: 'eq',
57
+ value: str
58
+ };
59
+ }
60
+
61
+ const [firstWord, ...rest] = str.trim().split(' ');
62
+ const remainingValue = rest.join(' ');
63
+
64
+ // Check if first word is a unary operator
65
+ if (UNARY_OPERATORS.includes(firstWord as any)) {
66
+ return {
67
+ operator: firstWord as Operator,
68
+ value: undefined
69
+ };
70
+ }
71
+
72
+ // Check if first word is any recognized operator
73
+ if (OPERATORS.includes(firstWord as any)) {
74
+ return {
75
+ operator: firstWord as Operator,
76
+ value: remainingValue
77
+ };
78
+ }
79
+
80
+ // If not a recognized operator, treat the whole string as value with 'eq' operator
81
+ return {
82
+ operator: 'eq',
83
+ value: str
84
+ };
85
+ };
86
+
87
+ export const toOpenCollectionAssertions = (assertions: BrunoKeyValue[] | null | undefined): Assertion[] | undefined => {
88
+ if (!assertions?.length) {
89
+ return undefined;
90
+ }
91
+
92
+ const ocAssertions: Assertion[] = assertions.map((assertion: BrunoKeyValue): Assertion => {
93
+ const { operator, value } = parseAssertionOperator(assertion.value || '');
94
+
95
+ const ocAssertion: Assertion = {
96
+ expression: assertion.name || '',
97
+ operator,
98
+ ...(value !== undefined && { value })
99
+ };
100
+
101
+ if (assertion?.description?.trim().length) {
102
+ ocAssertion.description = assertion.description;
103
+ }
104
+
105
+ if (assertion.enabled === false) {
106
+ ocAssertion.disabled = true;
107
+ }
108
+
109
+ return ocAssertion;
110
+ });
111
+
112
+ return ocAssertions.length > 0 ? ocAssertions : undefined;
113
+ };
114
+
115
+ export const toBrunoAssertions = (assertions: Assertion[] | null | undefined): BrunoKeyValue[] | undefined => {
116
+ if (!assertions?.length) {
117
+ return undefined;
118
+ }
119
+
120
+ const brunoAssertions: BrunoKeyValue[] = assertions.map((assertion: Assertion): BrunoKeyValue => {
121
+ // Reconstruct the "operator value" format that Bruno uses
122
+ let valueString = assertion.operator;
123
+ if (assertion.value !== undefined && assertion.value !== null) {
124
+ valueString = `${assertion.operator} ${assertion.value}`;
125
+ }
126
+
127
+ const brunoAssertion: BrunoKeyValue = {
128
+ uid: uuid(),
129
+ name: assertion.expression || '',
130
+ value: valueString,
131
+ enabled: assertion.disabled !== true
132
+ };
133
+
134
+ if (assertion.description) {
135
+ if (typeof assertion.description === 'string' && assertion.description.trim().length) {
136
+ brunoAssertion.description = assertion.description;
137
+ } else if (typeof assertion.description === 'object' && assertion.description.content?.trim().length) {
138
+ brunoAssertion.description = assertion.description.content;
139
+ }
140
+ }
141
+
142
+ return brunoAssertion;
143
+ });
144
+
145
+ return brunoAssertions.length > 0 ? brunoAssertions : undefined;
146
+ };