@usebruno/filestore 0.4.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.
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/workers/worker-script.js +1 -1
- package/dist/cjs/workers/worker-script.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/workers/worker-script.js +1 -1
- package/dist/esm/workers/worker-script.js.map +1 -1
- package/dist/formats/bru/index.d.ts +20 -0
- package/dist/formats/bru/index.d.ts.map +1 -0
- package/dist/formats/bru/tests/fixtures/oauth2-additional-params.d.ts +57 -0
- package/dist/formats/bru/tests/fixtures/oauth2-additional-params.d.ts.map +1 -0
- package/dist/formats/bru/tests/oauth2-additional-params.spec.d.ts +2 -0
- package/dist/formats/bru/tests/oauth2-additional-params.spec.d.ts.map +1 -0
- package/dist/formats/bru/tests/request-parse-and-redact-body-data.spec.d.ts +2 -0
- package/dist/formats/bru/tests/request-parse-and-redact-body-data.spec.d.ts.map +1 -0
- package/dist/{esm/formats → formats}/bru/utils/oauth2-additional-params.d.ts +1 -0
- package/dist/formats/bru/utils/oauth2-additional-params.d.ts.map +1 -0
- package/dist/{cjs/workers/formats → formats}/bru/utils/request-parse-and-redact-body-data.d.ts +1 -0
- package/dist/formats/bru/utils/request-parse-and-redact-body-data.d.ts.map +1 -0
- package/dist/formats/yml/common/actions.d.ts +14 -0
- package/dist/formats/yml/common/actions.d.ts.map +1 -0
- package/dist/formats/yml/common/assertions.d.ts +5 -0
- package/dist/formats/yml/common/assertions.d.ts.map +1 -0
- package/dist/formats/yml/common/auth-oauth2.d.ts +5 -0
- package/dist/formats/yml/common/auth-oauth2.d.ts.map +1 -0
- package/dist/formats/yml/common/auth.d.ts +5 -0
- package/dist/formats/yml/common/auth.d.ts.map +1 -0
- package/dist/formats/yml/common/body.d.ts +5 -0
- package/dist/formats/yml/common/body.d.ts.map +1 -0
- package/dist/formats/yml/common/headers.d.ts +7 -0
- package/dist/formats/yml/common/headers.d.ts.map +1 -0
- package/dist/formats/yml/common/params.d.ts +5 -0
- package/dist/formats/yml/common/params.d.ts.map +1 -0
- package/dist/formats/yml/common/scripts.d.ts +14 -0
- package/dist/formats/yml/common/scripts.d.ts.map +1 -0
- package/dist/formats/yml/common/variables.d.ts +17 -0
- package/dist/formats/yml/common/variables.d.ts.map +1 -0
- package/dist/formats/yml/index.d.ts +10 -0
- package/dist/formats/yml/index.d.ts.map +1 -0
- package/dist/formats/yml/items/parseGraphQLRequest.d.ts +5 -0
- package/dist/formats/yml/items/parseGraphQLRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/parseGrpcRequest.d.ts +5 -0
- package/dist/formats/yml/items/parseGrpcRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/parseHttpRequest.d.ts +5 -0
- package/dist/formats/yml/items/parseHttpRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/parseScript.d.ts +5 -0
- package/dist/formats/yml/items/parseScript.d.ts.map +1 -0
- package/dist/formats/yml/items/parseWebsocketRequest.d.ts +5 -0
- package/dist/formats/yml/items/parseWebsocketRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/stringifyGraphQLRequest.d.ts +4 -0
- package/dist/formats/yml/items/stringifyGraphQLRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/stringifyGrpcRequest.d.ts +4 -0
- package/dist/formats/yml/items/stringifyGrpcRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/stringifyHttpRequest.d.ts +4 -0
- package/dist/formats/yml/items/stringifyHttpRequest.d.ts.map +1 -0
- package/dist/formats/yml/items/stringifyScript.d.ts +4 -0
- package/dist/formats/yml/items/stringifyScript.d.ts.map +1 -0
- package/dist/formats/yml/items/stringifyWebsocketRequest.d.ts +4 -0
- package/dist/formats/yml/items/stringifyWebsocketRequest.d.ts.map +1 -0
- package/dist/formats/yml/parseCollection.d.ts +8 -0
- package/dist/formats/yml/parseCollection.d.ts.map +1 -0
- package/dist/formats/yml/parseEnvironment.d.ts +4 -0
- package/dist/formats/yml/parseEnvironment.d.ts.map +1 -0
- package/dist/formats/yml/parseFolder.d.ts +4 -0
- package/dist/formats/yml/parseFolder.d.ts.map +1 -0
- package/dist/formats/yml/parseItem.d.ts +4 -0
- package/dist/formats/yml/parseItem.d.ts.map +1 -0
- package/dist/formats/yml/stringifyCollection.d.ts +3 -0
- package/dist/formats/yml/stringifyCollection.d.ts.map +1 -0
- package/dist/formats/yml/stringifyEnvironment.d.ts +4 -0
- package/dist/formats/yml/stringifyEnvironment.d.ts.map +1 -0
- package/dist/formats/yml/stringifyFolder.d.ts +4 -0
- package/dist/formats/yml/stringifyFolder.d.ts.map +1 -0
- package/dist/formats/yml/stringifyItem.d.ts +4 -0
- package/dist/formats/yml/stringifyItem.d.ts.map +1 -0
- package/dist/formats/yml/utils.d.ts +3 -0
- package/dist/formats/yml/utils.d.ts.map +1 -0
- package/dist/{cjs/workers/index.d.ts → index.d.ts} +13 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{esm/workers → workers}/WorkerQueue/index.d.ts +1 -0
- package/dist/workers/WorkerQueue/index.d.ts.map +1 -0
- package/dist/workers/index.d.ts +12 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/worker-script.d.ts +2 -0
- package/dist/workers/worker-script.d.ts.map +1 -0
- package/package.json +12 -6
- package/src/formats/bru/index.ts +103 -11
- package/src/formats/bru/tests/oauth2-additional-params.spec.js +1 -1
- package/src/formats/bru/utils/oauth2-additional-params.ts +17 -18
- package/src/formats/bru/utils/request-parse-and-redact-body-data.ts +13 -13
- package/src/formats/yml/common/actions.ts +78 -0
- package/src/formats/yml/common/assertions.ts +146 -0
- package/src/formats/yml/common/auth-oauth2.ts +555 -0
- package/src/formats/yml/common/auth.ts +245 -0
- package/src/formats/yml/common/body.ts +238 -0
- package/src/formats/yml/common/headers.ts +58 -0
- package/src/formats/yml/common/params.ts +57 -0
- package/src/formats/yml/common/scripts.ts +64 -0
- package/src/formats/yml/common/variables.ts +68 -0
- package/src/formats/yml/index.ts +20 -0
- package/src/formats/yml/items/parseGraphQLRequest.ts +137 -0
- package/src/formats/yml/items/parseGrpcRequest.ts +116 -0
- package/src/formats/yml/items/parseHttpRequest.ts +195 -0
- package/src/formats/yml/items/parseScript.ts +25 -0
- package/src/formats/yml/items/parseWebsocketRequest.ts +106 -0
- package/src/formats/yml/items/stringifyGraphQLRequest.ts +168 -0
- package/src/formats/yml/items/stringifyGrpcRequest.ts +137 -0
- package/src/formats/yml/items/stringifyHttpRequest.ts +221 -0
- package/src/formats/yml/items/stringifyScript.ts +22 -0
- package/src/formats/yml/items/stringifyWebsocketRequest.ts +114 -0
- package/src/formats/yml/parseCollection.ts +198 -0
- package/src/formats/yml/parseEnvironment.ts +56 -0
- package/src/formats/yml/parseFolder.ts +88 -0
- package/src/formats/yml/parseItem.ts +102 -0
- package/src/formats/yml/stringifyCollection.ts +230 -0
- package/src/formats/yml/stringifyEnvironment.ts +64 -0
- package/src/formats/yml/stringifyFolder.ts +96 -0
- package/src/formats/yml/stringifyItem.ts +37 -0
- package/src/formats/yml/utils.ts +38 -0
- package/src/index.ts +57 -27
- package/src/types/bruno-lang.d.ts +1 -1
- package/src/types.ts +5 -124
- package/src/utils/index.ts +15 -0
- package/src/workers/WorkerQueue/index.ts +10 -10
- package/src/workers/index.ts +20 -20
- package/src/workers/worker-script.ts +20 -6
- package/dist/cjs/formats/bru/index.d.ts +0 -6
- package/dist/cjs/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
- package/dist/cjs/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
- package/dist/cjs/index.d.ts +0 -16
- package/dist/cjs/types.d.ts +0 -142
- package/dist/cjs/workers/WorkerQueue/index.d.ts +0 -26
- package/dist/cjs/workers/formats/bru/index.d.ts +0 -6
- package/dist/cjs/workers/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
- package/dist/cjs/workers/types.d.ts +0 -142
- package/dist/cjs/workers/worker-script.d.ts +0 -1
- package/dist/cjs/workers/workers/WorkerQueue/index.d.ts +0 -26
- package/dist/cjs/workers/workers/index.d.ts +0 -10
- package/dist/cjs/workers/workers/worker-script.d.ts +0 -1
- package/dist/esm/formats/bru/index.d.ts +0 -6
- package/dist/esm/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
- package/dist/esm/index.d.ts +0 -16
- package/dist/esm/types.d.ts +0 -142
- package/dist/esm/workers/formats/bru/index.d.ts +0 -6
- package/dist/esm/workers/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
- package/dist/esm/workers/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
- package/dist/esm/workers/index.d.ts +0 -16
- package/dist/esm/workers/types.d.ts +0 -142
- package/dist/esm/workers/worker-script.d.ts +0 -1
- package/dist/esm/workers/workers/WorkerQueue/index.d.ts +0 -26
- package/dist/esm/workers/workers/index.d.ts +0 -10
- 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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
47
|
+
export const stringifyRequest = (requestObj: BrunoItem, options: StringifyOptions = { format: 'bru' }): string => {
|
|
35
48
|
if (options.format === 'bru') {
|
|
36
|
-
return
|
|
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
|
-
|
|
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
|
|
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:
|
|
86
|
+
export const stringifyCollection = (collectionObj: BrunoCollection, brunoConfig: any, options: StringifyOptions = { format: 'bru' }): string => {
|
|
68
87
|
if (options.format === 'bru') {
|
|
69
|
-
return
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
124
|
+
export const stringifyEnvironment = (envObj: BrunoEnvironment, options: StringifyOptions = { format: 'bru' }): string => {
|
|
96
125
|
if (options.format === 'bru') {
|
|
97
|
-
return
|
|
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';
|
package/src/types.ts
CHANGED
|
@@ -1,130 +1,11 @@
|
|
|
1
|
+
export type CollectionFormat = 'bru' | 'yml';
|
|
2
|
+
|
|
1
3
|
export interface ParseOptions {
|
|
2
|
-
format?:
|
|
4
|
+
format?: CollectionFormat;
|
|
3
5
|
}
|
|
4
6
|
|
|
5
7
|
export interface StringifyOptions {
|
|
6
|
-
format?:
|
|
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;
|