@usebruno/filestore 0.5.0 → 0.7.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/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- 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/{cjs/workers/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/{esm/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/index.d.ts +24 -0
- 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 +6 -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/constants.ts +3 -0
- package/src/formats/bru/index.ts +9 -9
- 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 +107 -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 +222 -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 +220 -0
- package/src/formats/yml/parseEnvironment.ts +57 -0
- package/src/formats/yml/parseFolder.ts +93 -0
- package/src/formats/yml/parseItem.ts +102 -0
- package/src/formats/yml/stringifyCollection.ts +264 -0
- package/src/formats/yml/stringifyEnvironment.ts +67 -0
- package/src/formats/yml/stringifyFolder.ts +107 -0
- package/src/formats/yml/stringifyItem.ts +37 -0
- package/src/formats/yml/utils.ts +38 -0
- package/src/index.ts +64 -32
- package/src/types/bruno-lang.d.ts +1 -1
- package/src/types.ts +5 -124
- package/src/utils/index.ts +25 -0
- package/src/workers/WorkerQueue/index.ts +10 -10
- package/src/workers/index.ts +21 -20
- package/src/workers/worker-script.ts +21 -6
- package/dist/cjs/formats/bru/index.d.ts +0 -19
- 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 -19
- package/dist/cjs/workers/formats/bru/utils/request-parse-and-redact-body-data.d.ts +0 -9
- package/dist/cjs/workers/index.d.ts +0 -16
- 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 -19
- package/dist/esm/formats/bru/utils/oauth2-additional-params.d.ts +0 -38
- 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 -19
- 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,264 @@
|
|
|
1
|
+
import type { OpenCollection } from '@opencollection/types';
|
|
2
|
+
import type { ProtoFileItem, ProtoFileImportPath } from '@opencollection/types/config/protobuf';
|
|
3
|
+
import type { HttpRequestHeader } from '@opencollection/types/requests/http';
|
|
4
|
+
import type { ClientCertificate, PemCertificate, Pkcs12Certificate } from '@opencollection/types/config/certificates';
|
|
5
|
+
import type { Variable } from '@opencollection/types/common/variables';
|
|
6
|
+
import type { Action } from '@opencollection/types/common/actions';
|
|
7
|
+
import type { Scripts } from '@opencollection/types/common/scripts';
|
|
8
|
+
import { stringifyYml } from './utils';
|
|
9
|
+
import { toOpenCollectionAuth } from './common/auth';
|
|
10
|
+
import { toOpenCollectionHttpHeaders } from './common/headers';
|
|
11
|
+
import { toOpenCollectionVariables } from './common/variables';
|
|
12
|
+
import { toOpenCollectionActions } from './common/actions';
|
|
13
|
+
import { toOpenCollectionScripts } from './common/scripts';
|
|
14
|
+
import type { Auth } from '@opencollection/types/common/auth';
|
|
15
|
+
|
|
16
|
+
const hasCollectionConfig = (brunoConfig: any): boolean => {
|
|
17
|
+
// protobuf
|
|
18
|
+
const hasProtobuf = (
|
|
19
|
+
brunoConfig.protobuf?.protofFiles?.length > 0
|
|
20
|
+
|| brunoConfig.protobuf?.importPaths?.length > 0
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// proxy - check if proxy is configured in newer format
|
|
24
|
+
// Valid newer format: has 'inherit' property and 'config' object
|
|
25
|
+
const isValidProxyFormat = brunoConfig.proxy
|
|
26
|
+
&& typeof brunoConfig.proxy === 'object'
|
|
27
|
+
&& 'inherit' in brunoConfig.proxy
|
|
28
|
+
&& brunoConfig.proxy.config
|
|
29
|
+
&& typeof brunoConfig.proxy.config === 'object';
|
|
30
|
+
|
|
31
|
+
const hasProxy = isValidProxyFormat;
|
|
32
|
+
|
|
33
|
+
// client certificates
|
|
34
|
+
const hasClientCertificates = brunoConfig.clientCertificates?.certs?.length > 0;
|
|
35
|
+
|
|
36
|
+
return hasProtobuf || hasProxy || hasClientCertificates;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const hasRequestDefaults = (collectionRoot: any): boolean => {
|
|
40
|
+
const requestRoot = collectionRoot?.request;
|
|
41
|
+
|
|
42
|
+
return Boolean((requestRoot?.headers?.length)
|
|
43
|
+
|| (requestRoot?.vars?.req?.length)
|
|
44
|
+
|| (requestRoot?.vars?.res?.length)
|
|
45
|
+
|| hasRequestScripts(collectionRoot)
|
|
46
|
+
|| hasRequestAuth(collectionRoot));
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const hasRequestAuth = (collectionRoot: any): boolean => {
|
|
50
|
+
const reqAuthMode = collectionRoot?.request?.auth?.mode;
|
|
51
|
+
return Boolean(reqAuthMode && reqAuthMode !== 'none');
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const hasRequestScripts = (collectionRoot: any): boolean => {
|
|
55
|
+
if (!collectionRoot?.request) return false;
|
|
56
|
+
|
|
57
|
+
return (collectionRoot.request.script?.req)
|
|
58
|
+
|| (collectionRoot.request.script?.res)
|
|
59
|
+
|| (collectionRoot.request.tests);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const hasPresets = (brunoConfig: any): boolean => {
|
|
63
|
+
return brunoConfig?.presets?.requestType?.length
|
|
64
|
+
|| brunoConfig?.presets?.requestUrl?.length;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
|
|
68
|
+
try {
|
|
69
|
+
const oc: OpenCollection = {};
|
|
70
|
+
|
|
71
|
+
oc.opencollection = '1.0.0';
|
|
72
|
+
oc.info = {
|
|
73
|
+
name: brunoConfig.name || 'Untitled Collection'
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// collection config
|
|
77
|
+
if (hasCollectionConfig(brunoConfig)) {
|
|
78
|
+
oc.config = {};
|
|
79
|
+
|
|
80
|
+
if (brunoConfig.protobuf?.protofFiles?.length) {
|
|
81
|
+
oc.config.protobuf = {
|
|
82
|
+
protoFiles: brunoConfig.protobuf.protofFiles.map((protoFile: any): ProtoFileItem => ({
|
|
83
|
+
type: 'file' as const,
|
|
84
|
+
path: protoFile.path
|
|
85
|
+
})),
|
|
86
|
+
importPaths: brunoConfig.protobuf.importPaths.map((importPath: any): ProtoFileImportPath => ({
|
|
87
|
+
path: importPath.path,
|
|
88
|
+
disabled: importPath.disabled
|
|
89
|
+
}))
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// proxy - only write newer format
|
|
94
|
+
// Validate that brunoConfig.proxy is in newer format before writing
|
|
95
|
+
const isValidProxyFormat = brunoConfig.proxy
|
|
96
|
+
&& typeof brunoConfig.proxy === 'object'
|
|
97
|
+
&& 'inherit' in brunoConfig.proxy
|
|
98
|
+
&& brunoConfig.proxy.config
|
|
99
|
+
&& typeof brunoConfig.proxy.config === 'object';
|
|
100
|
+
|
|
101
|
+
if (isValidProxyFormat) {
|
|
102
|
+
oc.config.proxy = {
|
|
103
|
+
inherit: brunoConfig.proxy.inherit,
|
|
104
|
+
config: {
|
|
105
|
+
protocol: brunoConfig.proxy.config.protocol || 'http',
|
|
106
|
+
hostname: brunoConfig.proxy.config.hostname || '',
|
|
107
|
+
port: brunoConfig.proxy.config.port || '',
|
|
108
|
+
auth: {
|
|
109
|
+
username: brunoConfig.proxy.config.auth?.username || '',
|
|
110
|
+
password: brunoConfig.proxy.config.auth?.password || ''
|
|
111
|
+
},
|
|
112
|
+
bypassProxy: brunoConfig.proxy.config.bypassProxy || ''
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Add optional disabled field if true
|
|
117
|
+
if (brunoConfig.proxy.disabled === true) {
|
|
118
|
+
oc.config.proxy.disabled = true;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Add optional auth.disabled field if true
|
|
122
|
+
if (brunoConfig.proxy.config?.auth?.disabled === true) {
|
|
123
|
+
if (oc.config.proxy.config && oc.config.proxy.config.auth) {
|
|
124
|
+
oc.config.proxy.config.auth.disabled = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// client certificates
|
|
130
|
+
if (brunoConfig.clientCertificates?.certs?.length) {
|
|
131
|
+
oc.config.clientCertificates = brunoConfig.clientCertificates.certs
|
|
132
|
+
.map((cert: any): ClientCertificate | null => {
|
|
133
|
+
if (cert.type === 'cert') {
|
|
134
|
+
const pemCert: PemCertificate = {
|
|
135
|
+
domain: cert.domain,
|
|
136
|
+
type: 'pem',
|
|
137
|
+
certificateFilePath: cert.certFilePath,
|
|
138
|
+
privateKeyFilePath: cert.keyFilePath,
|
|
139
|
+
...(cert.passphrase && { passphrase: cert.passphrase })
|
|
140
|
+
};
|
|
141
|
+
return pemCert;
|
|
142
|
+
} else if (cert.type === 'pfx') {
|
|
143
|
+
const pkcs12Cert: Pkcs12Certificate = {
|
|
144
|
+
domain: cert.domain,
|
|
145
|
+
type: 'pkcs12',
|
|
146
|
+
pkcs12FilePath: cert.pfxFilePath,
|
|
147
|
+
...(cert.passphrase && { passphrase: cert.passphrase })
|
|
148
|
+
};
|
|
149
|
+
return pkcs12Cert;
|
|
150
|
+
} else {
|
|
151
|
+
// Unsupported certificate type - ignore silently
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
.filter((cert: ClientCertificate | null): cert is ClientCertificate => cert !== null);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// request defaults
|
|
160
|
+
if (hasRequestDefaults(collectionRoot)) {
|
|
161
|
+
oc.request = {};
|
|
162
|
+
|
|
163
|
+
// headers
|
|
164
|
+
if (collectionRoot.request?.headers?.length) {
|
|
165
|
+
const ocHeaders: HttpRequestHeader[] | undefined = toOpenCollectionHttpHeaders(collectionRoot.request?.headers);
|
|
166
|
+
if (ocHeaders) {
|
|
167
|
+
oc.request.headers = ocHeaders;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// auth
|
|
172
|
+
if (hasRequestAuth(collectionRoot)) {
|
|
173
|
+
const ocAuth: Auth | undefined = toOpenCollectionAuth(collectionRoot.request?.auth);
|
|
174
|
+
if (ocAuth) {
|
|
175
|
+
oc.request.auth = ocAuth;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// variables
|
|
180
|
+
if (collectionRoot.request?.vars?.req?.length) {
|
|
181
|
+
const ocVariables: Variable[] | undefined = toOpenCollectionVariables(collectionRoot.request?.vars);
|
|
182
|
+
if (ocVariables) {
|
|
183
|
+
oc.request.variables = ocVariables;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// actions (post-response variables)
|
|
188
|
+
if (collectionRoot.request?.vars?.res?.length) {
|
|
189
|
+
const ocActions: Action[] | undefined = toOpenCollectionActions(collectionRoot.request?.vars?.res);
|
|
190
|
+
if (ocActions) {
|
|
191
|
+
(oc.request as any).actions = ocActions;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// scripts
|
|
196
|
+
if (hasRequestScripts(collectionRoot)) {
|
|
197
|
+
const ocScripts: Scripts | undefined = toOpenCollectionScripts(collectionRoot.request);
|
|
198
|
+
if (ocScripts) {
|
|
199
|
+
oc.request.scripts = ocScripts;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// docs
|
|
205
|
+
if (collectionRoot?.docs?.trim().length) {
|
|
206
|
+
oc.docs = {
|
|
207
|
+
content: collectionRoot.docs,
|
|
208
|
+
type: 'text/markdown'
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// bundled
|
|
213
|
+
oc.bundled = false;
|
|
214
|
+
|
|
215
|
+
// extensions
|
|
216
|
+
oc.extensions = {};
|
|
217
|
+
|
|
218
|
+
const hasBrunoExtensions = brunoConfig.ignore?.length || hasPresets(brunoConfig);
|
|
219
|
+
|
|
220
|
+
if (hasBrunoExtensions) {
|
|
221
|
+
const brunoExtension: any = {};
|
|
222
|
+
|
|
223
|
+
if (brunoConfig.ignore?.length) {
|
|
224
|
+
const ignoreList: string[] = [];
|
|
225
|
+
brunoConfig.ignore.forEach((ignore: string) => {
|
|
226
|
+
ignoreList.push(ignore);
|
|
227
|
+
});
|
|
228
|
+
brunoExtension.ignore = ignoreList;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (hasPresets(brunoConfig)) {
|
|
232
|
+
const presetsRequest: any = {};
|
|
233
|
+
if (brunoConfig.presets.requestType?.length) {
|
|
234
|
+
presetsRequest.type = brunoConfig.presets.requestType;
|
|
235
|
+
}
|
|
236
|
+
if (brunoConfig.presets.requestUrl?.length) {
|
|
237
|
+
presetsRequest.url = brunoConfig.presets.requestUrl;
|
|
238
|
+
}
|
|
239
|
+
brunoExtension.presets = {
|
|
240
|
+
request: presetsRequest
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
oc.extensions.bruno = brunoExtension;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// bruno-specific script extensions
|
|
248
|
+
if (brunoConfig.scripts?.additionalContextRoots?.length) {
|
|
249
|
+
if (!oc.extensions.bruno) {
|
|
250
|
+
oc.extensions.bruno = {};
|
|
251
|
+
}
|
|
252
|
+
(oc.extensions.bruno as any).scripts = {
|
|
253
|
+
additionalContextRoots: brunoConfig.scripts.additionalContextRoots
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return stringifyYml(oc);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
console.error('Error stringifying opencollection.yml:', error);
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
export default stringifyCollection;
|
|
@@ -0,0 +1,67 @@
|
|
|
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
|
+
if (environment.color) {
|
|
51
|
+
ocEnvironment.color = environment.color;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (environment.variables?.length) {
|
|
55
|
+
const ocVariables = toOpenCollectionEnvironmentVariables(environment.variables);
|
|
56
|
+
if (ocVariables) {
|
|
57
|
+
ocEnvironment.variables = ocVariables;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return stringifyYml(ocEnvironment);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Error stringifying environment:', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
export default stringifyEnvironment;
|
|
@@ -0,0 +1,107 @@
|
|
|
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 { Action } from '@opencollection/types/common/actions';
|
|
5
|
+
import type { Scripts } from '@opencollection/types/common/scripts';
|
|
6
|
+
import type { Auth } from '@opencollection/types/common/auth';
|
|
7
|
+
import type { HttpRequestHeader } from '@opencollection/types/requests/http';
|
|
8
|
+
import type { RequestDefaults } from '@opencollection/types/common/request-defaults';
|
|
9
|
+
import { toOpenCollectionAuth } from './common/auth';
|
|
10
|
+
import { toOpenCollectionHttpHeaders } from './common/headers';
|
|
11
|
+
import { toOpenCollectionVariables } from './common/variables';
|
|
12
|
+
import { toOpenCollectionActions } from './common/actions';
|
|
13
|
+
import { toOpenCollectionScripts } from './common/scripts';
|
|
14
|
+
import { stringifyYml } from './utils';
|
|
15
|
+
|
|
16
|
+
const hasRequestDefaults = (folderRoot: FolderRoot): boolean => {
|
|
17
|
+
const requestDefaults = folderRoot?.request;
|
|
18
|
+
|
|
19
|
+
return Boolean((requestDefaults?.headers?.length)
|
|
20
|
+
|| (requestDefaults?.vars?.req?.length)
|
|
21
|
+
|| (requestDefaults?.vars?.res?.length)
|
|
22
|
+
|| hasRequestScripts(folderRoot)
|
|
23
|
+
|| hasRequestAuth(folderRoot));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const hasRequestAuth = (folderRoot: FolderRoot): boolean => {
|
|
27
|
+
return Boolean((folderRoot.request?.auth?.mode !== 'none'));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const hasRequestScripts = (folderRoot: FolderRoot): boolean => {
|
|
31
|
+
return Boolean((folderRoot.request?.script?.req)
|
|
32
|
+
|| (folderRoot.request?.script?.res)
|
|
33
|
+
|| (folderRoot.request?.tests));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const stringifyFolder = (folderRoot: FolderRoot): string => {
|
|
37
|
+
try {
|
|
38
|
+
const ocFolder: Folder = {};
|
|
39
|
+
|
|
40
|
+
// info block
|
|
41
|
+
const info: FolderInfo = {
|
|
42
|
+
name: folderRoot.meta?.name || 'Untitled Folder',
|
|
43
|
+
type: 'folder',
|
|
44
|
+
seq: folderRoot.meta?.seq || 1
|
|
45
|
+
};
|
|
46
|
+
ocFolder.info = info;
|
|
47
|
+
|
|
48
|
+
// request defaults
|
|
49
|
+
if (hasRequestDefaults(folderRoot)) {
|
|
50
|
+
ocFolder.request = {} as RequestDefaults;
|
|
51
|
+
|
|
52
|
+
// headers
|
|
53
|
+
if (folderRoot.request?.headers?.length) {
|
|
54
|
+
const ocHeaders: HttpRequestHeader[] | undefined = toOpenCollectionHttpHeaders(folderRoot.request?.headers);
|
|
55
|
+
if (ocHeaders) {
|
|
56
|
+
ocFolder.request.headers = ocHeaders;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// auth
|
|
61
|
+
if (hasRequestAuth(folderRoot)) {
|
|
62
|
+
const ocAuth: Auth | undefined = toOpenCollectionAuth(folderRoot.request?.auth);
|
|
63
|
+
if (ocAuth) {
|
|
64
|
+
ocFolder.request.auth = ocAuth;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// variables
|
|
69
|
+
if (folderRoot.request?.vars?.req?.length) {
|
|
70
|
+
const ocVariables: Variable[] | undefined = toOpenCollectionVariables(folderRoot.request?.vars);
|
|
71
|
+
if (ocVariables) {
|
|
72
|
+
ocFolder.request.variables = ocVariables;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// actions (post-response variables)
|
|
77
|
+
if (folderRoot.request?.vars?.res?.length) {
|
|
78
|
+
const ocActions: Action[] | undefined = toOpenCollectionActions(folderRoot.request?.vars?.res);
|
|
79
|
+
if (ocActions) {
|
|
80
|
+
(ocFolder.request as any).actions = ocActions;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// scripts
|
|
85
|
+
if (hasRequestScripts(folderRoot)) {
|
|
86
|
+
const ocScripts: Scripts | undefined = toOpenCollectionScripts(folderRoot?.request);
|
|
87
|
+
if (ocScripts) {
|
|
88
|
+
ocFolder.request.scripts = ocScripts;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// docs
|
|
94
|
+
if (folderRoot.docs?.trim().length) {
|
|
95
|
+
ocFolder.docs = {
|
|
96
|
+
content: folderRoot.docs,
|
|
97
|
+
type: 'text/markdown'
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return stringifyYml(ocFolder);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('Error stringifying folder.yml:', error);
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
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,39 @@
|
|
|
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';
|
|
28
|
+
import { DEFAULT_COLLECTION_FORMAT } from './constants';
|
|
18
29
|
import { bruRequestParseAndRedactBodyData } from './formats/bru/utils/request-parse-and-redact-body-data';
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
// request
|
|
32
|
+
export const parseRequest = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
|
|
21
33
|
if (options.format === 'bru') {
|
|
22
|
-
return
|
|
34
|
+
return parseBruRequest(content);
|
|
35
|
+
} else if (options.format === 'yml') {
|
|
36
|
+
return parseYmlItem(content);
|
|
23
37
|
}
|
|
24
38
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
25
39
|
};
|
|
@@ -31,15 +45,17 @@ export const parseRequestAndRedactBody = (content: string, options: ParseOptions
|
|
|
31
45
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
32
46
|
};
|
|
33
47
|
|
|
34
|
-
export const stringifyRequest = (requestObj:
|
|
48
|
+
export const stringifyRequest = (requestObj: BrunoItem, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
|
|
35
49
|
if (options.format === 'bru') {
|
|
36
|
-
return
|
|
50
|
+
return stringifyBruRequest(requestObj);
|
|
51
|
+
} else if (options.format === 'yml') {
|
|
52
|
+
return stringifyYmlItem(requestObj);
|
|
37
53
|
}
|
|
38
54
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
39
55
|
};
|
|
40
56
|
|
|
57
|
+
// request via worker
|
|
41
58
|
let globalWorkerInstance: BruParserWorker | null = null;
|
|
42
|
-
|
|
43
59
|
const getWorkerInstance = (): BruParserWorker => {
|
|
44
60
|
if (!globalWorkerInstance) {
|
|
45
61
|
globalWorkerInstance = new BruParserWorker();
|
|
@@ -47,62 +63,78 @@ const getWorkerInstance = (): BruParserWorker => {
|
|
|
47
63
|
return globalWorkerInstance;
|
|
48
64
|
};
|
|
49
65
|
|
|
50
|
-
export const parseRequestViaWorker = async (content: string): Promise<any> => {
|
|
66
|
+
export const parseRequestViaWorker = async (content: string, options: { format: CollectionFormat; filename?: string }): Promise<any> => {
|
|
51
67
|
const fileParserWorker = getWorkerInstance();
|
|
52
|
-
|
|
68
|
+
|
|
69
|
+
return await fileParserWorker.parseRequest(content, options.format);
|
|
53
70
|
};
|
|
54
71
|
|
|
55
|
-
export const stringifyRequestViaWorker = async (requestObj: any): Promise<string> => {
|
|
72
|
+
export const stringifyRequestViaWorker = async (requestObj: any, options: { format: CollectionFormat }): Promise<string> => {
|
|
56
73
|
const fileParserWorker = getWorkerInstance();
|
|
57
|
-
return await fileParserWorker.stringifyRequest(requestObj);
|
|
74
|
+
return await fileParserWorker.stringifyRequest(requestObj, options.format);
|
|
58
75
|
};
|
|
59
76
|
|
|
60
|
-
|
|
77
|
+
// collection
|
|
78
|
+
export const parseCollection = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
|
|
61
79
|
if (options.format === 'bru') {
|
|
62
|
-
return
|
|
80
|
+
return parseBruCollection(content);
|
|
81
|
+
} else if (options.format === 'yml') {
|
|
82
|
+
return parseYmlCollection(content);
|
|
63
83
|
}
|
|
64
84
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
65
85
|
};
|
|
66
86
|
|
|
67
|
-
export const stringifyCollection = (collectionObj:
|
|
87
|
+
export const stringifyCollection = (collectionObj: BrunoCollection, brunoConfig: any, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
|
|
68
88
|
if (options.format === 'bru') {
|
|
69
|
-
return
|
|
89
|
+
return stringifyBruCollection(collectionObj, false);
|
|
90
|
+
} else if (options.format === 'yml') {
|
|
91
|
+
return stringifyYmlCollection(collectionObj, brunoConfig);
|
|
70
92
|
}
|
|
71
93
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
72
94
|
};
|
|
73
95
|
|
|
74
|
-
|
|
96
|
+
// folder
|
|
97
|
+
export const parseFolder = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
|
|
75
98
|
if (options.format === 'bru') {
|
|
76
|
-
return
|
|
99
|
+
return parseBruCollection(content);
|
|
100
|
+
} else if (options.format === 'yml') {
|
|
101
|
+
return parseYmlFolder(content);
|
|
77
102
|
}
|
|
78
103
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
79
104
|
};
|
|
80
105
|
|
|
81
|
-
export const stringifyFolder = (folderObj: any, options: StringifyOptions = { format:
|
|
106
|
+
export const stringifyFolder = (folderObj: any, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
|
|
82
107
|
if (options.format === 'bru') {
|
|
83
|
-
return
|
|
108
|
+
return stringifyBruCollection(folderObj, true);
|
|
109
|
+
} else if (options.format === 'yml') {
|
|
110
|
+
return stringifyYmlFolder(folderObj);
|
|
84
111
|
}
|
|
85
112
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
86
113
|
};
|
|
87
114
|
|
|
88
|
-
|
|
115
|
+
// environment
|
|
116
|
+
export const parseEnvironment = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
|
|
89
117
|
if (options.format === 'bru') {
|
|
90
|
-
return
|
|
118
|
+
return parseBruEnvironment(content);
|
|
119
|
+
} else if (options.format === 'yml') {
|
|
120
|
+
return parseYmlEnvironment(content);
|
|
91
121
|
}
|
|
92
122
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
93
123
|
};
|
|
94
124
|
|
|
95
|
-
export const stringifyEnvironment = (envObj:
|
|
125
|
+
export const stringifyEnvironment = (envObj: BrunoEnvironment, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
|
|
96
126
|
if (options.format === 'bru') {
|
|
97
|
-
return
|
|
127
|
+
return stringifyBruEnvironment(envObj);
|
|
128
|
+
} else if (options.format === 'yml') {
|
|
129
|
+
return stringifyYmlEnvironment(envObj);
|
|
98
130
|
}
|
|
99
131
|
throw new Error(`Unsupported format: ${options.format}`);
|
|
100
132
|
};
|
|
101
133
|
|
|
102
|
-
|
|
103
134
|
export const parseDotEnv = (content: string): Record<string, string> => {
|
|
104
135
|
return dotenvToJson(content);
|
|
105
136
|
};
|
|
106
137
|
|
|
107
138
|
export { BruParserWorker };
|
|
108
|
-
export * from './types';
|
|
139
|
+
export * from './types';
|
|
140
|
+
export * from './constants';
|