@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
@@ -0,0 +1,64 @@
1
+ import type { Environment as BrunoEnvironment, EnvironmentVariable as BrunoEnvironmentVariable } from '@usebruno/schema-types/collection/environment';
2
+ import type { Environment } from '@opencollection/types/config/environments';
3
+ import type { Variable, SecretVariable } from '@opencollection/types/common/variables';
4
+ import { stringifyYml } from './utils';
5
+
6
+ const toOpenCollectionEnvironmentVariables = (variables: BrunoEnvironmentVariable[]): (Variable | SecretVariable)[] | undefined => {
7
+ if (!variables?.length) {
8
+ return undefined;
9
+ }
10
+
11
+ const ocVariables: (Variable | SecretVariable)[] = variables
12
+ .filter((v: BrunoEnvironmentVariable) => {
13
+ // todo: currently neither bru lang nor bruno app supports non-string values
14
+ // update this when bruno app supports non-string values
15
+ return typeof v.value === 'string';
16
+ })
17
+ .map((v: BrunoEnvironmentVariable): Variable | SecretVariable => {
18
+ if (v.secret === true) {
19
+ const secretVar: SecretVariable = {
20
+ secret: true,
21
+ name: v.name || ''
22
+ };
23
+ if (v.enabled === false) {
24
+ secretVar.disabled = true;
25
+ }
26
+ return secretVar;
27
+ }
28
+
29
+ const variable: Variable = {
30
+ name: v.name || '',
31
+ value: v.value as string
32
+ };
33
+
34
+ if (v.enabled === false) {
35
+ variable.disabled = true;
36
+ }
37
+
38
+ return variable;
39
+ });
40
+
41
+ return ocVariables.length > 0 ? ocVariables : undefined;
42
+ };
43
+
44
+ const stringifyEnvironment = (environment: BrunoEnvironment): string => {
45
+ try {
46
+ const ocEnvironment: Environment = {
47
+ name: environment.name
48
+ };
49
+
50
+ // Convert variables if they exist
51
+ if (environment.variables?.length) {
52
+ const ocVariables = toOpenCollectionEnvironmentVariables(environment.variables);
53
+ if (ocVariables) {
54
+ ocEnvironment.variables = ocVariables;
55
+ }
56
+ }
57
+
58
+ return stringifyYml(ocEnvironment);
59
+ } catch (error) {
60
+ console.error('Error stringifying environment:', error);
61
+ throw error;
62
+ }
63
+ };
64
+ export default stringifyEnvironment;
@@ -0,0 +1,96 @@
1
+ import type { FolderRoot } from '@usebruno/schema-types/collection/folder';
2
+ import type { Folder, FolderInfo } from '@opencollection/types/collection/item';
3
+ import type { Variable } from '@opencollection/types/common/variables';
4
+ import type { Scripts } from '@opencollection/types/common/scripts';
5
+ import type { Auth } from '@opencollection/types/common/auth';
6
+ import type { HttpRequestHeader } from '@opencollection/types/requests/http';
7
+ import type { RequestDefaults } from '@opencollection/types/common/request-defaults';
8
+ import { toOpenCollectionAuth } from './common/auth';
9
+ import { toOpenCollectionHttpHeaders } from './common/headers';
10
+ import { toOpenCollectionVariables } from './common/variables';
11
+ import { toOpenCollectionScripts } from './common/scripts';
12
+ import { stringifyYml } from './utils';
13
+
14
+ const hasRequestDefaults = (folderRoot: FolderRoot): boolean => {
15
+ const requestDefaults = folderRoot?.request;
16
+
17
+ return Boolean((requestDefaults?.headers?.length)
18
+ || (requestDefaults?.vars?.req?.length)
19
+ || hasRequestScripts(folderRoot)
20
+ || hasRequestAuth(folderRoot));
21
+ };
22
+
23
+ const hasRequestAuth = (folderRoot: FolderRoot): boolean => {
24
+ return Boolean((folderRoot.request?.auth?.mode !== 'none'));
25
+ };
26
+
27
+ const hasRequestScripts = (folderRoot: FolderRoot): boolean => {
28
+ return Boolean((folderRoot.request?.script?.req)
29
+ || (folderRoot.request?.script?.res)
30
+ || (folderRoot.request?.tests));
31
+ };
32
+
33
+ const stringifyFolder = (folderRoot: FolderRoot): string => {
34
+ try {
35
+ const ocFolder: Folder = {};
36
+
37
+ // info block
38
+ const info: FolderInfo = {
39
+ name: folderRoot.meta?.name || 'Untitled Folder',
40
+ type: 'folder',
41
+ seq: folderRoot.meta?.seq || 1
42
+ };
43
+ ocFolder.info = info;
44
+
45
+ // request defaults
46
+ if (hasRequestDefaults(folderRoot)) {
47
+ ocFolder.request = {} as RequestDefaults;
48
+
49
+ // headers
50
+ if (folderRoot.request?.headers?.length) {
51
+ const ocHeaders: HttpRequestHeader[] | undefined = toOpenCollectionHttpHeaders(folderRoot.request?.headers);
52
+ if (ocHeaders) {
53
+ ocFolder.request.headers = ocHeaders;
54
+ }
55
+ }
56
+
57
+ // auth
58
+ if (hasRequestAuth(folderRoot)) {
59
+ const ocAuth: Auth | undefined = toOpenCollectionAuth(folderRoot.request?.auth);
60
+ if (ocAuth) {
61
+ ocFolder.request.auth = ocAuth;
62
+ }
63
+ }
64
+
65
+ // variables
66
+ if (folderRoot.request?.vars?.req?.length) {
67
+ const ocVariables: Variable[] | undefined = toOpenCollectionVariables(folderRoot.request?.vars);
68
+ if (ocVariables) {
69
+ ocFolder.request.variables = ocVariables;
70
+ }
71
+ }
72
+
73
+ // scripts
74
+ if (hasRequestScripts(folderRoot)) {
75
+ const ocScripts: Scripts | undefined = toOpenCollectionScripts(folderRoot?.request);
76
+ if (ocScripts) {
77
+ ocFolder.request.scripts = ocScripts;
78
+ }
79
+ }
80
+ }
81
+
82
+ // docs
83
+ if (folderRoot.docs?.trim().length) {
84
+ ocFolder.docs = {
85
+ content: folderRoot.docs,
86
+ type: 'text/markdown'
87
+ };
88
+ }
89
+
90
+ return stringifyYml(ocFolder);
91
+ } catch (error) {
92
+ console.error('Error stringifying folder.yml:', error);
93
+ throw error;
94
+ }
95
+ };
96
+ export default stringifyFolder;
@@ -0,0 +1,37 @@
1
+ import type { Item as BrunoItem } from '@usebruno/schema-types/collection/item';
2
+ import stringifyHttpRequest from './items/stringifyHttpRequest';
3
+ import stringifyGraphqlRequest from './items/stringifyGraphQLRequest';
4
+ import stringifyGrpcRequest from './items/stringifyGrpcRequest';
5
+ import stringifyWebsocketRequest from './items/stringifyWebsocketRequest';
6
+ import stringifyScript from './items/stringifyScript';
7
+
8
+ const stringifyItem = (item: BrunoItem): string => {
9
+ try {
10
+ switch (item.type) {
11
+ case 'http-request':
12
+ return stringifyHttpRequest(item);
13
+
14
+ case 'graphql-request':
15
+ return stringifyGraphqlRequest(item);
16
+
17
+ case 'grpc-request':
18
+ return stringifyGrpcRequest(item);
19
+
20
+ case 'ws-request':
21
+ return stringifyWebsocketRequest(item);
22
+
23
+ case 'js':
24
+ return stringifyScript(item);
25
+
26
+ case 'folder':
27
+ throw new Error('Folder items should be handled separately using stringifyFolder');
28
+
29
+ default:
30
+ throw new Error(`Unsupported item type: ${item.type}`);
31
+ }
32
+ } catch (error) {
33
+ console.error('Error stringifying item:', error);
34
+ throw error;
35
+ }
36
+ };
37
+ export default stringifyItem;
@@ -0,0 +1,38 @@
1
+ import * as YAML from 'yaml';
2
+
3
+ // Top-level keys that should have a blank line before them
4
+ const BLOCK_KEYS = ['info', 'http', 'graphql', 'grpc', 'websocket', 'runtime', 'settings', 'examples', 'docs', 'items', 'request'];
5
+
6
+ export const stringifyYml = (obj: any): string => {
7
+ const yamlStr = YAML.stringify(obj, {
8
+ lineWidth: 0,
9
+ indent: 2,
10
+ minContentWidth: 0,
11
+ defaultStringType: 'PLAIN'
12
+ });
13
+
14
+ // Add blank lines before major blocks (only at the top level, not indented)
15
+ const lines = yamlStr.split('\n');
16
+ const result: string[] = [];
17
+
18
+ for (let i = 0; i < lines.length; i++) {
19
+ const line = lines[i];
20
+ // Check if this is a top-level key (no leading whitespace) that should have a blank line
21
+ if (i > 0 && !line.startsWith(' ') && !line.startsWith('\t')) {
22
+ const key = line.split(':')[0];
23
+ if (BLOCK_KEYS.includes(key)) {
24
+ // Add blank line before this block (if previous line isn't already blank)
25
+ if (result.length > 0 && result[result.length - 1].trim() !== '') {
26
+ result.push('');
27
+ }
28
+ }
29
+ }
30
+ result.push(line);
31
+ }
32
+
33
+ return result.join('\n');
34
+ };
35
+
36
+ export const parseYml = (ymlString: string): any => {
37
+ return YAML.parse(ymlString);
38
+ };
package/src/index.ts CHANGED
@@ -1,25 +1,38 @@
1
+ import type { BrunoCollection, BrunoItem, BrunoEnvironment } from '@usebruno/schema-types';
2
+
1
3
  import {
2
- bruRequestToJson,
3
- jsonRequestToBru,
4
- bruCollectionToJson,
5
- jsonCollectionToBru,
6
- bruEnvironmentToJson,
7
- jsonEnvironmentToBru
4
+ parseBruRequest,
5
+ parseBruCollection,
6
+ parseBruEnvironment,
7
+ stringifyBruRequest,
8
+ stringifyBruCollection,
9
+ stringifyBruEnvironment
8
10
  } from './formats/bru';
11
+ import {
12
+ parseYmlItem,
13
+ parseYmlCollection,
14
+ parseYmlFolder,
15
+ parseYmlEnvironment,
16
+ stringifyYmlItem,
17
+ stringifyYmlFolder,
18
+ stringifyYmlCollection,
19
+ stringifyYmlEnvironment
20
+ } from './formats/yml';
9
21
  import { dotenvToJson } from '@usebruno/lang';
10
22
  import BruParserWorker from './workers';
11
23
  import {
12
24
  ParseOptions,
13
25
  StringifyOptions,
14
- ParsedRequest,
15
- ParsedCollection,
16
- ParsedEnvironment
26
+ CollectionFormat
17
27
  } from './types';
18
28
  import { bruRequestParseAndRedactBodyData } from './formats/bru/utils/request-parse-and-redact-body-data';
19
29
 
30
+ // request
20
31
  export const parseRequest = (content: string, options: ParseOptions = { format: 'bru' }): any => {
21
32
  if (options.format === 'bru') {
22
- return bruRequestToJson(content);
33
+ return parseBruRequest(content);
34
+ } else if (options.format === 'yml') {
35
+ return parseYmlItem(content);
23
36
  }
24
37
  throw new Error(`Unsupported format: ${options.format}`);
25
38
  };
@@ -31,15 +44,17 @@ export const parseRequestAndRedactBody = (content: string, options: ParseOptions
31
44
  throw new Error(`Unsupported format: ${options.format}`);
32
45
  };
33
46
 
34
- export const stringifyRequest = (requestObj: ParsedRequest, options: StringifyOptions = { format: 'bru' }): string => {
47
+ export const stringifyRequest = (requestObj: BrunoItem, options: StringifyOptions = { format: 'bru' }): string => {
35
48
  if (options.format === 'bru') {
36
- return jsonRequestToBru(requestObj);
49
+ return stringifyBruRequest(requestObj);
50
+ } else if (options.format === 'yml') {
51
+ return stringifyYmlItem(requestObj);
37
52
  }
38
53
  throw new Error(`Unsupported format: ${options.format}`);
39
54
  };
40
55
 
56
+ // request via worker
41
57
  let globalWorkerInstance: BruParserWorker | null = null;
42
-
43
58
  const getWorkerInstance = (): BruParserWorker => {
44
59
  if (!globalWorkerInstance) {
45
60
  globalWorkerInstance = new BruParserWorker();
@@ -47,62 +62,77 @@ const getWorkerInstance = (): BruParserWorker => {
47
62
  return globalWorkerInstance;
48
63
  };
49
64
 
50
- export const parseRequestViaWorker = async (content: string): Promise<any> => {
65
+ export const parseRequestViaWorker = async (content: string, options: { format: CollectionFormat; filename?: string }): Promise<any> => {
51
66
  const fileParserWorker = getWorkerInstance();
52
- return await fileParserWorker.parseRequest(content);
67
+
68
+ return await fileParserWorker.parseRequest(content, options.format);
53
69
  };
54
70
 
55
- export const stringifyRequestViaWorker = async (requestObj: any): Promise<string> => {
71
+ export const stringifyRequestViaWorker = async (requestObj: any, options: { format: CollectionFormat }): Promise<string> => {
56
72
  const fileParserWorker = getWorkerInstance();
57
- return await fileParserWorker.stringifyRequest(requestObj);
73
+ return await fileParserWorker.stringifyRequest(requestObj, options.format);
58
74
  };
59
75
 
76
+ // collection
60
77
  export const parseCollection = (content: string, options: ParseOptions = { format: 'bru' }): any => {
61
78
  if (options.format === 'bru') {
62
- return bruCollectionToJson(content);
79
+ return parseBruCollection(content);
80
+ } else if (options.format === 'yml') {
81
+ return parseYmlCollection(content);
63
82
  }
64
83
  throw new Error(`Unsupported format: ${options.format}`);
65
84
  };
66
85
 
67
- export const stringifyCollection = (collectionObj: ParsedCollection, options: StringifyOptions = { format: 'bru' }): string => {
86
+ export const stringifyCollection = (collectionObj: BrunoCollection, brunoConfig: any, options: StringifyOptions = { format: 'bru' }): string => {
68
87
  if (options.format === 'bru') {
69
- return jsonCollectionToBru(collectionObj, false);
88
+ return stringifyBruCollection(collectionObj, false);
89
+ } else if (options.format === 'yml') {
90
+ return stringifyYmlCollection(collectionObj, brunoConfig);
70
91
  }
71
92
  throw new Error(`Unsupported format: ${options.format}`);
72
93
  };
73
94
 
95
+ // folder
74
96
  export const parseFolder = (content: string, options: ParseOptions = { format: 'bru' }): any => {
75
97
  if (options.format === 'bru') {
76
- return bruCollectionToJson(content);
98
+ return parseBruCollection(content);
99
+ } else if (options.format === 'yml') {
100
+ return parseYmlFolder(content);
77
101
  }
78
102
  throw new Error(`Unsupported format: ${options.format}`);
79
103
  };
80
104
 
81
105
  export const stringifyFolder = (folderObj: any, options: StringifyOptions = { format: 'bru' }): string => {
82
106
  if (options.format === 'bru') {
83
- return jsonCollectionToBru(folderObj, true);
107
+ return stringifyBruCollection(folderObj, true);
108
+ } else if (options.format === 'yml') {
109
+ return stringifyYmlFolder(folderObj);
84
110
  }
85
111
  throw new Error(`Unsupported format: ${options.format}`);
86
112
  };
87
113
 
114
+ // environment
88
115
  export const parseEnvironment = (content: string, options: ParseOptions = { format: 'bru' }): any => {
89
116
  if (options.format === 'bru') {
90
- return bruEnvironmentToJson(content);
117
+ return parseBruEnvironment(content);
118
+ } else if (options.format === 'yml') {
119
+ return parseYmlEnvironment(content);
91
120
  }
92
121
  throw new Error(`Unsupported format: ${options.format}`);
93
122
  };
94
123
 
95
- export const stringifyEnvironment = (envObj: ParsedEnvironment, options: StringifyOptions = { format: 'bru' }): string => {
124
+ export const stringifyEnvironment = (envObj: BrunoEnvironment, options: StringifyOptions = { format: 'bru' }): string => {
96
125
  if (options.format === 'bru') {
97
- return jsonEnvironmentToBru(envObj);
126
+ return stringifyBruEnvironment(envObj);
127
+ } else if (options.format === 'yml') {
128
+ return stringifyYmlEnvironment(envObj);
98
129
  }
99
130
  throw new Error(`Unsupported format: ${options.format}`);
100
131
  };
101
132
 
102
-
103
133
  export const parseDotEnv = (content: string): Record<string, string> => {
104
134
  return dotenvToJson(content);
105
135
  };
106
136
 
107
137
  export { BruParserWorker };
108
- export * from './types';
138
+ export * from './types';
@@ -6,4 +6,4 @@ declare module '@usebruno/lang' {
6
6
  export function collectionBruToJson(bruContent: string): any;
7
7
  export function jsonToCollectionBru(jsonData: any): string;
8
8
  export function dotenvToJson(envContent: string): Record<string, string>;
9
- }
9
+ }
package/src/types.ts CHANGED
@@ -1,130 +1,11 @@
1
+ export type CollectionFormat = 'bru' | 'yml';
2
+
1
3
  export interface ParseOptions {
2
- format?: 'bru' | 'yaml';
4
+ format?: CollectionFormat;
3
5
  }
4
6
 
5
7
  export interface StringifyOptions {
6
- format?: 'bru' | 'yaml';
7
- }
8
-
9
- export interface RequestBody {
10
- mode?: string;
11
- raw?: string;
12
- formUrlEncoded?: Array<{ name: string; value: string; enabled: boolean }>;
13
- multipartForm?: Array<{ name: string; value: string; type: string; enabled: boolean }>;
14
- json?: string;
15
- xml?: string;
16
- sparql?: string;
17
- graphql?: {
18
- query?: string;
19
- variables?: string;
20
- };
21
- }
22
-
23
- export interface AuthConfig {
24
- mode?: string;
25
- basic?: {
26
- username?: string;
27
- password?: string;
28
- };
29
- bearer?: {
30
- token?: string;
31
- };
32
- apikey?: {
33
- key?: string;
34
- value?: string;
35
- placement?: string;
36
- };
37
- awsv4?: {
38
- accessKeyId?: string;
39
- secretAccessKey?: string;
40
- sessionToken?: string;
41
- service?: string;
42
- region?: string;
43
- profileName?: string;
44
- };
45
- oauth2?: {
46
- grantType?: string;
47
- callbackUrl?: string;
48
- authorizationUrl?: string;
49
- accessTokenUrl?: string;
50
- clientId?: string;
51
- clientSecret?: string;
52
- scope?: string;
53
- state?: string;
54
- pkce?: boolean;
55
- };
56
- }
57
-
58
- export interface RequestParam {
59
- name: string;
60
- value: string;
61
- enabled: boolean;
62
- }
63
-
64
- export interface RequestHeader {
65
- name: string;
66
- value: string;
67
- enabled: boolean;
68
- }
69
-
70
- export interface RequestAssertion {
71
- name: string;
72
- value: string;
73
- enabled: boolean;
74
- }
75
-
76
- export interface RequestVars {
77
- req?: Array<{ name: string; value: string; enabled: boolean }>;
78
- res?: Array<{ name: string; value: string; enabled: boolean }>;
79
- }
80
-
81
- export interface RequestScript {
82
- req?: string;
83
- res?: string;
84
- }
85
-
86
- export interface RequestSettings {
87
- [key: string]: any;
88
- }
89
-
90
- export interface RequestData {
91
- method: string;
92
- url: string;
93
- params: RequestParam[];
94
- headers: RequestHeader[];
95
- auth: AuthConfig;
96
- body: RequestBody;
97
- script: RequestScript;
98
- vars: RequestVars;
99
- assertions: RequestAssertion[];
100
- tests: string;
101
- docs: string;
102
- }
103
-
104
- export interface ParsedRequest {
105
- type: 'http-request' | 'graphql-request';
106
- name: string;
107
- seq: number;
108
- settings: RequestSettings;
109
- tags: string[];
110
- request: RequestData;
111
- }
112
-
113
- export interface ParsedCollection {
114
- name: string;
115
- type?: string;
116
- version?: string;
117
- [key: string]: any;
118
- }
119
-
120
- export interface EnvironmentVariable {
121
- name: string;
122
- value: string;
123
- enabled: boolean;
124
- }
125
-
126
- export interface ParsedEnvironment {
127
- variables: EnvironmentVariable[];
8
+ format?: CollectionFormat;
128
9
  }
129
10
 
130
11
  export interface WorkerTask {
@@ -138,4 +19,4 @@ export interface WorkerTask {
138
19
 
139
20
  export interface Lane {
140
21
  maxSize: number;
141
- }
22
+ }
@@ -0,0 +1,15 @@
1
+ const { customAlphabet } = require('nanoid');
2
+
3
+ export const isString = (value: unknown): value is string => typeof value === 'string';
4
+
5
+ export const isNumber = (value: unknown): value is number => typeof value === 'number';
6
+
7
+ export const isNonEmptyString = (value: unknown): value is string => isString(value) && value.trim().length > 0;
8
+
9
+ export const uuid = () => {
10
+ // https://github.com/ai/nanoid/blob/main/url-alphabet/index.js
11
+ const urlAlphabet = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict';
12
+ const customNanoId = customAlphabet(urlAlphabet, 21);
13
+
14
+ return customNanoId();
15
+ };
@@ -21,14 +21,14 @@ class WorkerQueue {
21
21
  }
22
22
 
23
23
  async getWorkerForScriptPath(scriptPath: string) {
24
- if (!this.workers) this.workers = {};
24
+ if (!this.workers) this.workers = {};
25
25
  let worker = this.workers[scriptPath];
26
26
  if (!worker || worker.threadId === -1) {
27
27
  this.workers[scriptPath] = worker = new Worker(scriptPath);
28
28
  }
29
29
  return worker;
30
30
  }
31
-
31
+
32
32
  async enqueue(task: QueuedTask) {
33
33
  const { priority, scriptPath, data, taskType } = task;
34
34
 
@@ -40,9 +40,9 @@ class WorkerQueue {
40
40
  }
41
41
 
42
42
  async processQueue() {
43
- if (this.isProcessing || this.queue.length === 0){
43
+ if (this.isProcessing || this.queue.length === 0) {
44
44
  return;
45
- }
45
+ }
46
46
 
47
47
  this.isProcessing = true;
48
48
  const { scriptPath, data, taskType, resolve, reject } = this.queue.shift() as QueuedTask;
@@ -61,12 +61,12 @@ class WorkerQueue {
61
61
  async runWorker({ scriptPath, data, taskType }: { scriptPath: string; data: any; taskType: 'parse' | 'stringify' }) {
62
62
  return new Promise(async (resolve, reject) => {
63
63
  let worker = await this.getWorkerForScriptPath(scriptPath);
64
-
64
+
65
65
  const messageHandler = (data: any) => {
66
66
  worker.off('message', messageHandler);
67
67
  worker.off('error', errorHandler);
68
68
  worker.off('exit', exitHandler);
69
-
69
+
70
70
  if (data?.error) {
71
71
  reject(new Error(data?.error));
72
72
  } else {
@@ -89,7 +89,7 @@ class WorkerQueue {
89
89
  delete this.workers[scriptPath];
90
90
  reject(new Error(`Worker stopped with exit code ${code}`));
91
91
  };
92
-
92
+
93
93
  worker.on('message', messageHandler);
94
94
  worker.on('error', errorHandler);
95
95
  worker.on('exit', exitHandler);
@@ -99,16 +99,16 @@ class WorkerQueue {
99
99
  }
100
100
 
101
101
  async cleanup() {
102
- const promises = Object.values(this.workers).map(worker => {
102
+ const promises = Object.values(this.workers).map((worker) => {
103
103
  if (worker.threadId !== -1) {
104
104
  return worker.terminate();
105
105
  }
106
106
  return Promise.resolve();
107
107
  });
108
-
108
+
109
109
  await Promise.allSettled(promises);
110
110
  this.workers = {};
111
111
  }
112
112
  }
113
113
 
114
- export default WorkerQueue;
114
+ export default WorkerQueue;