@usebruno/filestore 0.6.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.
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 +28 -6
  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 +57 -23
  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,11 +3,13 @@ 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
 
@@ -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 => {
@@ -124,7 +130,7 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
124
130
  if (brunoConfig.clientCertificates?.certs?.length) {
125
131
  oc.config.clientCertificates = brunoConfig.clientCertificates.certs
126
132
  .map((cert: any): ClientCertificate | null => {
127
- if (cert.type === 'pem') {
133
+ if (cert.type === 'cert') {
128
134
  const pemCert: PemCertificate = {
129
135
  domain: cert.domain,
130
136
  type: 'pem',
@@ -133,7 +139,7 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
133
139
  ...(cert.passphrase && { passphrase: cert.passphrase })
134
140
  };
135
141
  return pemCert;
136
- } else if (cert.type === 'pkcs12') {
142
+ } else if (cert.type === 'pfx') {
137
143
  const pkcs12Cert: Pkcs12Certificate = {
138
144
  domain: cert.domain,
139
145
  type: 'pkcs12',
@@ -178,6 +184,14 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
178
184
  }
179
185
  }
180
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
+
181
195
  // scripts
182
196
  if (hasRequestScripts(collectionRoot)) {
183
197
  const ocScripts: Scripts | undefined = toOpenCollectionScripts(collectionRoot.request);
@@ -188,7 +202,7 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
188
202
  }
189
203
 
190
204
  // docs
191
- if (collectionRoot.docs?.trim().length) {
205
+ if (collectionRoot?.docs?.trim().length) {
192
206
  oc.docs = {
193
207
  content: collectionRoot.docs,
194
208
  type: 'text/markdown'
@@ -200,24 +214,44 @@ const stringifyCollection = (collectionRoot: any, brunoConfig: any): string => {
200
214
 
201
215
  // extensions
202
216
  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;
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;
214
229
  }
215
- if (brunoConfig.presets.requestUrl?.length) {
216
- presetsRequest.url = brunoConfig.presets.requestUrl;
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 = {};
217
251
  }
218
- oc.extensions.presets = {
219
- request: presetsRequest
220
- } as any;
252
+ (oc.extensions.bruno as any).scripts = {
253
+ additionalContextRoots: brunoConfig.scripts.additionalContextRoots
254
+ };
221
255
  }
222
256
 
223
257
  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') {