@usebruno/filestore 0.6.0 → 0.7.1

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 (46) 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/constants.d.ts +3 -0
  6. package/dist/constants.d.ts.map +1 -0
  7. package/dist/esm/index.js +1 -1
  8. package/dist/esm/index.js.map +1 -1
  9. package/dist/esm/workers/worker-script.js +1 -1
  10. package/dist/esm/workers/worker-script.js.map +1 -1
  11. package/dist/formats/yml/items/parseWebsocketRequest.d.ts.map +1 -1
  12. package/dist/formats/yml/items/stringifyHttpRequest.d.ts.map +1 -1
  13. package/dist/formats/yml/parseCollection.d.ts.map +1 -1
  14. package/dist/formats/yml/parseEnvironment.d.ts.map +1 -1
  15. package/dist/formats/yml/parseFolder.d.ts.map +1 -1
  16. package/dist/formats/yml/stringifyCollection.d.ts.map +1 -1
  17. package/dist/formats/yml/stringifyEnvironment.d.ts.map +1 -1
  18. package/dist/formats/yml/stringifyFolder.d.ts.map +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/utils/index.d.ts +1 -0
  22. package/dist/utils/index.d.ts.map +1 -1
  23. package/dist/workers/index.d.ts.map +1 -1
  24. package/package.json +3 -3
  25. package/src/constants.ts +3 -0
  26. package/src/formats/yml/common/actions.ts +3 -3
  27. package/src/formats/yml/common/assertions.ts +4 -4
  28. package/src/formats/yml/common/body.ts +5 -5
  29. package/src/formats/yml/common/headers.ts +3 -3
  30. package/src/formats/yml/common/params.ts +3 -3
  31. package/src/formats/yml/common/variables.ts +3 -3
  32. package/src/formats/yml/items/parseGraphQLRequest.ts +4 -4
  33. package/src/formats/yml/items/parseGrpcRequest.ts +6 -6
  34. package/src/formats/yml/items/parseHttpRequest.ts +7 -7
  35. package/src/formats/yml/items/parseWebsocketRequest.ts +6 -5
  36. package/src/formats/yml/items/stringifyHttpRequest.ts +3 -2
  37. package/src/formats/yml/parseCollection.ts +30 -8
  38. package/src/formats/yml/parseEnvironment.ts +7 -6
  39. package/src/formats/yml/parseFolder.ts +8 -3
  40. package/src/formats/yml/stringifyCollection.ts +75 -33
  41. package/src/formats/yml/stringifyEnvironment.ts +4 -1
  42. package/src/formats/yml/stringifyFolder.ts +11 -0
  43. package/src/index.ts +10 -8
  44. package/src/utils/index.ts +10 -0
  45. package/src/workers/index.ts +4 -3
  46. package/src/workers/worker-script.ts +2 -1
@@ -3,18 +3,20 @@ import type { ProtoFileItem, ProtoFileImportPath } from '@opencollection/types/c
3
3
  import type { HttpRequestHeader } from '@opencollection/types/requests/http';
4
4
  import type { ClientCertificate, PemCertificate, Pkcs12Certificate } from '@opencollection/types/config/certificates';
5
5
  import type { Variable } from '@opencollection/types/common/variables';
6
+ import type { Action } from '@opencollection/types/common/actions';
6
7
  import type { Scripts } from '@opencollection/types/common/scripts';
7
8
  import { stringifyYml } from './utils';
8
9
  import { toOpenCollectionAuth } from './common/auth';
9
10
  import { toOpenCollectionHttpHeaders } from './common/headers';
10
11
  import { toOpenCollectionVariables } from './common/variables';
12
+ import { toOpenCollectionActions } from './common/actions';
11
13
  import { toOpenCollectionScripts } from './common/scripts';
12
14
  import type { Auth } from '@opencollection/types/common/auth';
13
15
 
14
16
  const hasCollectionConfig = (brunoConfig: any): boolean => {
15
17
  // protobuf
16
18
  const hasProtobuf = (
17
- brunoConfig.protobuf?.protofFiles?.length > 0
19
+ brunoConfig.protobuf?.protoFiles?.length > 0
18
20
  || brunoConfig.protobuf?.importPaths?.length > 0
19
21
  );
20
22
 
@@ -39,18 +41,22 @@ const hasRequestDefaults = (collectionRoot: any): boolean => {
39
41
 
40
42
  return Boolean((requestRoot?.headers?.length)
41
43
  || (requestRoot?.vars?.req?.length)
44
+ || (requestRoot?.vars?.res?.length)
42
45
  || hasRequestScripts(collectionRoot)
43
46
  || hasRequestAuth(collectionRoot));
44
47
  };
45
48
 
46
49
  const hasRequestAuth = (collectionRoot: any): boolean => {
47
- return Boolean((collectionRoot.request?.auth?.mode !== 'none'));
50
+ const reqAuthMode = collectionRoot?.request?.auth?.mode;
51
+ return Boolean(reqAuthMode && reqAuthMode !== 'none');
48
52
  };
49
53
 
50
54
  const hasRequestScripts = (collectionRoot: any): boolean => {
51
- return (collectionRoot.request?.script?.req)
52
- || (collectionRoot.request?.script?.res)
53
- || (collectionRoot.request?.tests);
55
+ if (!collectionRoot?.request) return false;
56
+
57
+ return (collectionRoot.request.script?.req)
58
+ || (collectionRoot.request.script?.res)
59
+ || (collectionRoot.request.tests);
54
60
  };
55
61
 
56
62
  const hasPresets = (brunoConfig: any): boolean => {
@@ -71,17 +77,25 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
71
77
  if (hasCollectionConfig(brunoConfig)) {
72
78
  oc.config = {};
73
79
 
74
- if (brunoConfig.protobuf?.protofFiles?.length) {
75
- oc.config.protobuf = {
76
- protoFiles: brunoConfig.protobuf.protofFiles.map((protoFile: any): ProtoFileItem => ({
80
+ if (brunoConfig.protobuf?.protoFiles?.length || brunoConfig.protobuf?.importPaths?.length) {
81
+ oc.config.protobuf = {};
82
+
83
+ if (brunoConfig.protobuf.protoFiles?.length) {
84
+ oc.config.protobuf.protoFiles = brunoConfig.protobuf.protoFiles.map((protoFile: any): ProtoFileItem => ({
77
85
  type: 'file' as const,
78
86
  path: protoFile.path
79
- })),
80
- importPaths: brunoConfig.protobuf.importPaths.map((importPath: any): ProtoFileImportPath => ({
81
- path: importPath.path,
82
- disabled: importPath.disabled
83
- }))
84
- };
87
+ }));
88
+ }
89
+
90
+ if (brunoConfig.protobuf.importPaths?.length) {
91
+ oc.config.protobuf.importPaths = brunoConfig.protobuf.importPaths.map((importPath: any): ProtoFileImportPath => {
92
+ const item: ProtoFileImportPath = { path: importPath.path };
93
+ if (importPath.enabled === false) {
94
+ item.disabled = true;
95
+ }
96
+ return item;
97
+ });
98
+ }
85
99
  }
86
100
 
87
101
  // proxy - only write newer format
@@ -124,7 +138,7 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
124
138
  if (brunoConfig.clientCertificates?.certs?.length) {
125
139
  oc.config.clientCertificates = brunoConfig.clientCertificates.certs
126
140
  .map((cert: any): ClientCertificate | null => {
127
- if (cert.type === 'pem') {
141
+ if (cert.type === 'cert') {
128
142
  const pemCert: PemCertificate = {
129
143
  domain: cert.domain,
130
144
  type: 'pem',
@@ -133,7 +147,7 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
133
147
  ...(cert.passphrase && { passphrase: cert.passphrase })
134
148
  };
135
149
  return pemCert;
136
- } else if (cert.type === 'pkcs12') {
150
+ } else if (cert.type === 'pfx') {
137
151
  const pkcs12Cert: Pkcs12Certificate = {
138
152
  domain: cert.domain,
139
153
  type: 'pkcs12',
@@ -178,6 +192,14 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
178
192
  }
179
193
  }
180
194
 
195
+ // actions (post-response variables)
196
+ if (collectionRoot.request?.vars?.res?.length) {
197
+ const ocActions: Action[] | undefined = toOpenCollectionActions(collectionRoot.request?.vars?.res);
198
+ if (ocActions) {
199
+ (oc.request as any).actions = ocActions;
200
+ }
201
+ }
202
+
181
203
  // scripts
182
204
  if (hasRequestScripts(collectionRoot)) {
183
205
  const ocScripts: Scripts | undefined = toOpenCollectionScripts(collectionRoot.request);
@@ -188,7 +210,7 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
188
210
  }
189
211
 
190
212
  // docs
191
- if (collectionRoot.docs?.trim().length) {
213
+ if (collectionRoot?.docs?.trim().length) {
192
214
  oc.docs = {
193
215
  content: collectionRoot.docs,
194
216
  type: 'text/markdown'
@@ -200,24 +222,44 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
200
222
 
201
223
  // extensions
202
224
  oc.extensions = {};
203
- if (brunoConfig.ignore?.length) {
204
- const ignoreList: string[] = [];
205
- brunoConfig.ignore.forEach((ignore: string) => {
206
- ignoreList.push(ignore);
207
- });
208
- oc.extensions.ignore = ignoreList;
209
- }
210
- if (hasPresets(brunoConfig)) {
211
- const presetsRequest: any = {};
212
- if (brunoConfig.presets.requestType?.length) {
213
- presetsRequest.type = brunoConfig.presets.requestType;
225
+
226
+ const hasBrunoExtensions = brunoConfig.ignore?.length || hasPresets(brunoConfig);
227
+
228
+ if (hasBrunoExtensions) {
229
+ const brunoExtension: any = {};
230
+
231
+ if (brunoConfig.ignore?.length) {
232
+ const ignoreList: string[] = [];
233
+ brunoConfig.ignore.forEach((ignore: string) => {
234
+ ignoreList.push(ignore);
235
+ });
236
+ brunoExtension.ignore = ignoreList;
214
237
  }
215
- if (brunoConfig.presets.requestUrl?.length) {
216
- presetsRequest.url = brunoConfig.presets.requestUrl;
238
+
239
+ if (hasPresets(brunoConfig)) {
240
+ const presetsRequest: any = {};
241
+ if (brunoConfig.presets.requestType?.length) {
242
+ presetsRequest.type = brunoConfig.presets.requestType;
243
+ }
244
+ if (brunoConfig.presets.requestUrl?.length) {
245
+ presetsRequest.url = brunoConfig.presets.requestUrl;
246
+ }
247
+ brunoExtension.presets = {
248
+ request: presetsRequest
249
+ };
217
250
  }
218
- oc.extensions.presets = {
219
- request: presetsRequest
220
- } as any;
251
+
252
+ oc.extensions.bruno = brunoExtension;
253
+ }
254
+
255
+ // bruno-specific script extensions
256
+ if (brunoConfig.scripts?.additionalContextRoots?.length) {
257
+ if (!oc.extensions.bruno) {
258
+ oc.extensions.bruno = {};
259
+ }
260
+ (oc.extensions.bruno as any).scripts = {
261
+ additionalContextRoots: brunoConfig.scripts.additionalContextRoots
262
+ };
221
263
  }
222
264
 
223
265
  return stringifyYml(oc);
@@ -47,7 +47,10 @@ const stringifyEnvironment = (environment: BrunoEnvironment): string => {
47
47
  name: environment.name
48
48
  };
49
49
 
50
- // Convert variables if they exist
50
+ if (environment.color) {
51
+ ocEnvironment.color = environment.color;
52
+ }
53
+
51
54
  if (environment.variables?.length) {
52
55
  const ocVariables = toOpenCollectionEnvironmentVariables(environment.variables);
53
56
  if (ocVariables) {
@@ -1,6 +1,7 @@
1
1
  import type { FolderRoot } from '@usebruno/schema-types/collection/folder';
2
2
  import type { Folder, FolderInfo } from '@opencollection/types/collection/item';
3
3
  import type { Variable } from '@opencollection/types/common/variables';
4
+ import type { Action } from '@opencollection/types/common/actions';
4
5
  import type { Scripts } from '@opencollection/types/common/scripts';
5
6
  import type { Auth } from '@opencollection/types/common/auth';
6
7
  import type { HttpRequestHeader } from '@opencollection/types/requests/http';
@@ -8,6 +9,7 @@ import type { RequestDefaults } from '@opencollection/types/common/request-defau
8
9
  import { toOpenCollectionAuth } from './common/auth';
9
10
  import { toOpenCollectionHttpHeaders } from './common/headers';
10
11
  import { toOpenCollectionVariables } from './common/variables';
12
+ import { toOpenCollectionActions } from './common/actions';
11
13
  import { toOpenCollectionScripts } from './common/scripts';
12
14
  import { stringifyYml } from './utils';
13
15
 
@@ -16,6 +18,7 @@ const hasRequestDefaults = (folderRoot: FolderRoot): boolean => {
16
18
 
17
19
  return Boolean((requestDefaults?.headers?.length)
18
20
  || (requestDefaults?.vars?.req?.length)
21
+ || (requestDefaults?.vars?.res?.length)
19
22
  || hasRequestScripts(folderRoot)
20
23
  || hasRequestAuth(folderRoot));
21
24
  };
@@ -70,6 +73,14 @@ const stringifyFolder = (folderRoot: FolderRoot): string => {
70
73
  }
71
74
  }
72
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
+
73
84
  // scripts
74
85
  if (hasRequestScripts(folderRoot)) {
75
86
  const ocScripts: Scripts | undefined = toOpenCollectionScripts(folderRoot?.request);
package/src/index.ts CHANGED
@@ -25,10 +25,11 @@ import {
25
25
  StringifyOptions,
26
26
  CollectionFormat
27
27
  } from './types';
28
+ import { DEFAULT_COLLECTION_FORMAT } from './constants';
28
29
  import { bruRequestParseAndRedactBodyData } from './formats/bru/utils/request-parse-and-redact-body-data';
29
30
 
30
31
  // request
31
- export const parseRequest = (content: string, options: ParseOptions = { format: 'bru' }): any => {
32
+ export const parseRequest = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
32
33
  if (options.format === 'bru') {
33
34
  return parseBruRequest(content);
34
35
  } else if (options.format === 'yml') {
@@ -44,7 +45,7 @@ export const parseRequestAndRedactBody = (content: string, options: ParseOptions
44
45
  throw new Error(`Unsupported format: ${options.format}`);
45
46
  };
46
47
 
47
- export const stringifyRequest = (requestObj: BrunoItem, options: StringifyOptions = { format: 'bru' }): string => {
48
+ export const stringifyRequest = (requestObj: BrunoItem, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
48
49
  if (options.format === 'bru') {
49
50
  return stringifyBruRequest(requestObj);
50
51
  } else if (options.format === 'yml') {
@@ -74,7 +75,7 @@ export const stringifyRequestViaWorker = async (requestObj: any, options: { form
74
75
  };
75
76
 
76
77
  // collection
77
- export const parseCollection = (content: string, options: ParseOptions = { format: 'bru' }): any => {
78
+ export const parseCollection = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
78
79
  if (options.format === 'bru') {
79
80
  return parseBruCollection(content);
80
81
  } else if (options.format === 'yml') {
@@ -83,7 +84,7 @@ export const parseCollection = (content: string, options: ParseOptions = { forma
83
84
  throw new Error(`Unsupported format: ${options.format}`);
84
85
  };
85
86
 
86
- export const stringifyCollection = (collectionObj: BrunoCollection, brunoConfig: any, options: StringifyOptions = { format: 'bru' }): string => {
87
+ export const stringifyCollection = (collectionObj: BrunoCollection, brunoConfig: any, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
87
88
  if (options.format === 'bru') {
88
89
  return stringifyBruCollection(collectionObj, false);
89
90
  } else if (options.format === 'yml') {
@@ -93,7 +94,7 @@ export const stringifyCollection = (collectionObj: BrunoCollection, brunoConfig:
93
94
  };
94
95
 
95
96
  // folder
96
- export const parseFolder = (content: string, options: ParseOptions = { format: 'bru' }): any => {
97
+ export const parseFolder = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
97
98
  if (options.format === 'bru') {
98
99
  return parseBruCollection(content);
99
100
  } else if (options.format === 'yml') {
@@ -102,7 +103,7 @@ export const parseFolder = (content: string, options: ParseOptions = { format: '
102
103
  throw new Error(`Unsupported format: ${options.format}`);
103
104
  };
104
105
 
105
- export const stringifyFolder = (folderObj: any, options: StringifyOptions = { format: 'bru' }): string => {
106
+ export const stringifyFolder = (folderObj: any, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
106
107
  if (options.format === 'bru') {
107
108
  return stringifyBruCollection(folderObj, true);
108
109
  } else if (options.format === 'yml') {
@@ -112,7 +113,7 @@ export const stringifyFolder = (folderObj: any, options: StringifyOptions = { fo
112
113
  };
113
114
 
114
115
  // environment
115
- export const parseEnvironment = (content: string, options: ParseOptions = { format: 'bru' }): any => {
116
+ export const parseEnvironment = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
116
117
  if (options.format === 'bru') {
117
118
  return parseBruEnvironment(content);
118
119
  } else if (options.format === 'yml') {
@@ -121,7 +122,7 @@ export const parseEnvironment = (content: string, options: ParseOptions = { form
121
122
  throw new Error(`Unsupported format: ${options.format}`);
122
123
  };
123
124
 
124
- export const stringifyEnvironment = (envObj: BrunoEnvironment, options: StringifyOptions = { format: 'bru' }): string => {
125
+ export const stringifyEnvironment = (envObj: BrunoEnvironment, options: StringifyOptions = { format: DEFAULT_COLLECTION_FORMAT }): string => {
125
126
  if (options.format === 'bru') {
126
127
  return stringifyBruEnvironment(envObj);
127
128
  } else if (options.format === 'yml') {
@@ -136,3 +137,4 @@ export const parseDotEnv = (content: string): Record<string, string> => {
136
137
 
137
138
  export { BruParserWorker };
138
139
  export * from './types';
140
+ export * from './constants';
@@ -6,6 +6,16 @@ export const isNumber = (value: unknown): value is number => typeof value === 'n
6
6
 
7
7
  export const isNonEmptyString = (value: unknown): value is string => isString(value) && value.trim().length > 0;
8
8
 
9
+ export const ensureString = (value: unknown, fallback: string = ''): string => {
10
+ if (value === null || value === undefined) {
11
+ return fallback;
12
+ }
13
+ if (typeof value === 'string') {
14
+ return value;
15
+ }
16
+ return String(value);
17
+ };
18
+
9
19
  export const uuid = () => {
10
20
  // https://github.com/ai/nanoid/blob/main/url-alphabet/index.js
11
21
  const urlAlphabet = 'useandom26T198340PX75pxJACKVERYMINDBUSHWOLFGQZbfghjklqvwyzrict';
@@ -1,5 +1,6 @@
1
1
  import WorkerQueue from './WorkerQueue';
2
2
  import { Lane, CollectionFormat } from '../types';
3
+ import { DEFAULT_COLLECTION_FORMAT } from '../constants';
3
4
  import path from 'node:path';
4
5
 
5
6
  const sizeInMB = (size: number): number => {
@@ -54,7 +55,7 @@ class BruParserWorker {
54
55
  return queueForSize?.workerQueue ?? this.workerQueues[this.workerQueues.length - 1].workerQueue;
55
56
  }
56
57
 
57
- private async enqueueTask({ data, taskType, format = 'bru' }: { data: any; taskType: 'parse' | 'stringify'; format?: CollectionFormat }): Promise<any> {
58
+ private async enqueueTask({ data, taskType, format = DEFAULT_COLLECTION_FORMAT }: { data: any; taskType: 'parse' | 'stringify'; format?: CollectionFormat }): Promise<any> {
58
59
  const size = getSize(data);
59
60
  const workerQueue = this.getWorkerQueue(size);
60
61
  const workerScriptPath = path.join(__dirname, './workers/worker-script.js');
@@ -67,11 +68,11 @@ class BruParserWorker {
67
68
  });
68
69
  }
69
70
 
70
- async parseRequest(data: any, format: CollectionFormat = 'bru'): Promise<any> {
71
+ async parseRequest(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
71
72
  return this.enqueueTask({ data, taskType: 'parse', format });
72
73
  }
73
74
 
74
- async stringifyRequest(data: any, format: CollectionFormat = 'bru'): Promise<any> {
75
+ async stringifyRequest(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
75
76
  return this.enqueueTask({ data, taskType: 'stringify', format });
76
77
  }
77
78
 
@@ -2,6 +2,7 @@ import { parentPort } from 'node:worker_threads';
2
2
  import { parseBruRequest, stringifyBruRequest } from '../formats/bru';
3
3
  import { parseYmlItem, stringifyYmlItem } from '../formats/yml';
4
4
  import { CollectionFormat } from '../types';
5
+ import { DEFAULT_COLLECTION_FORMAT } from '../constants';
5
6
 
6
7
  interface WorkerMessage {
7
8
  taskType: 'parse' | 'stringify';
@@ -14,7 +15,7 @@ interface WorkerMessage {
14
15
  parentPort?.on('message', async (message: WorkerMessage) => {
15
16
  try {
16
17
  const { taskType, data: messageData } = message;
17
- const { data, format = 'bru' } = messageData;
18
+ const { data, format = DEFAULT_COLLECTION_FORMAT } = messageData;
18
19
  let result: any;
19
20
 
20
21
  if (taskType === 'parse') {