@usebruno/filestore 0.11.0 → 0.12.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 (65) 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 +1 -1
  6. package/dist/constants.d.ts.map +1 -1
  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/bru/utils/redact-large-text-blocks.d.ts.map +1 -1
  12. package/dist/formats/yml/index.d.ts +3 -1
  13. package/dist/formats/yml/index.d.ts.map +1 -1
  14. package/dist/formats/yml/items/parseGraphQLRequest.d.ts.map +1 -1
  15. package/dist/formats/yml/items/parseHttpRequest.d.ts.map +1 -1
  16. package/dist/formats/yml/items/stringifyGraphQLRequest.d.ts.map +1 -1
  17. package/dist/formats/yml/items/stringifyHttpRequest.d.ts.map +1 -1
  18. package/dist/formats/yml/mockServerTypes.d.ts +95 -0
  19. package/dist/formats/yml/mockServerTypes.d.ts.map +1 -0
  20. package/dist/formats/yml/parseCollection.d.ts.map +1 -1
  21. package/dist/formats/yml/parseFolder.d.ts.map +1 -1
  22. package/dist/formats/yml/parseMockServer.d.ts +4 -0
  23. package/dist/formats/yml/parseMockServer.d.ts.map +1 -0
  24. package/dist/formats/yml/stringifyCollection.d.ts.map +1 -1
  25. package/dist/formats/yml/stringifyFolder.d.ts.map +1 -1
  26. package/dist/formats/yml/stringifyMockServer.d.ts +4 -0
  27. package/dist/formats/yml/stringifyMockServer.d.ts.map +1 -0
  28. package/dist/index.d.ts +14 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/types.d.ts +1 -0
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/workers/WorkerQueue/index.d.ts +3 -2
  33. package/dist/workers/WorkerQueue/index.d.ts.map +1 -1
  34. package/dist/workers/index.d.ts +4 -0
  35. package/dist/workers/index.d.ts.map +1 -1
  36. package/package.json +5 -5
  37. package/src/constants.ts +5 -1
  38. package/src/formats/bru/tests/redact-large-text-blocks.spec.js +160 -1
  39. package/src/formats/bru/utils/redact-large-text-blocks.ts +42 -1
  40. package/src/formats/yml/index.ts +5 -1
  41. package/src/formats/yml/items/parseGraphQLRequest.ts +6 -16
  42. package/src/formats/yml/items/parseHttpRequest.ts +6 -16
  43. package/src/formats/yml/items/stringifyGraphQLRequest.ts +4 -6
  44. package/src/formats/yml/items/stringifyHttpRequest.ts +4 -6
  45. package/src/formats/yml/mockServerTypes.ts +95 -0
  46. package/src/formats/yml/parseCollection.spec.ts +123 -0
  47. package/src/formats/yml/parseCollection.ts +18 -5
  48. package/src/formats/yml/parseFolder.spec.ts +18 -0
  49. package/src/formats/yml/parseFolder.ts +5 -1
  50. package/src/formats/yml/parseMockServer.spec.ts +180 -0
  51. package/src/formats/yml/parseMockServer.ts +113 -0
  52. package/src/formats/yml/stringifyCollection.spec.ts +146 -0
  53. package/src/formats/yml/stringifyCollection.ts +22 -9
  54. package/src/formats/yml/stringifyFolder.spec.ts +23 -0
  55. package/src/formats/yml/stringifyFolder.ts +7 -2
  56. package/src/formats/yml/stringifyMockServer.spec.ts +177 -0
  57. package/src/formats/yml/stringifyMockServer.ts +129 -0
  58. package/src/formats/yml/tests/defaultEnvironment.spec.js +50 -0
  59. package/src/formats/yml/tests/stringifyEnvironment.spec.ts +26 -0
  60. package/src/formats/yml/utils.ts +1 -1
  61. package/src/index.ts +34 -1
  62. package/src/types.ts +1 -0
  63. package/src/workers/WorkerQueue/index.ts +10 -2
  64. package/src/workers/index.ts +25 -1
  65. package/src/workers/worker-script.ts +45 -21
@@ -0,0 +1,50 @@
1
+ import parseCollection from '../parseCollection';
2
+ import stringifyCollection from '../stringifyCollection';
3
+
4
+ const collectionRoot = { meta: null, request: null, docs: null };
5
+
6
+ describe('yml collection - presets.defaultEnvironment round-trip', () => {
7
+ it('writes and reads back defaultEnvironment via extensions.bruno.presets', () => {
8
+ const brunoConfig = {
9
+ name: 'My API',
10
+ type: 'collection',
11
+ ignore: ['node_modules'],
12
+ presets: { requestType: 'http', requestUrl: 'https://example.com', defaultEnvironment: 'prod' }
13
+ };
14
+
15
+ const yml = stringifyCollection(collectionRoot, brunoConfig);
16
+ expect(yml).toContain('defaultEnvironment: prod');
17
+
18
+ const { brunoConfig: parsed } = parseCollection(yml);
19
+ expect(parsed.presets).toEqual({
20
+ requestType: 'http',
21
+ requestUrl: 'https://example.com',
22
+ defaultEnvironment: 'prod'
23
+ });
24
+ });
25
+
26
+ it('persists defaultEnvironment even when no request presets are set', () => {
27
+ const brunoConfig = {
28
+ name: 'My API',
29
+ type: 'collection',
30
+ ignore: [],
31
+ presets: { defaultEnvironment: 'staging' }
32
+ };
33
+
34
+ const yml = stringifyCollection(collectionRoot, brunoConfig);
35
+ expect(yml).toContain('defaultEnvironment: staging');
36
+
37
+ const { brunoConfig: parsed } = parseCollection(yml);
38
+ expect(parsed.presets.defaultEnvironment).toBe('staging');
39
+ });
40
+
41
+ it('does not emit defaultEnvironment when it is not configured', () => {
42
+ const brunoConfig = { name: 'My API', type: 'collection', ignore: [] };
43
+
44
+ const yml = stringifyCollection(collectionRoot, brunoConfig);
45
+ expect(yml).not.toContain('defaultEnvironment');
46
+
47
+ const { brunoConfig: parsed } = parseCollection(yml);
48
+ expect(parsed.presets).toBeUndefined();
49
+ });
50
+ });
@@ -128,6 +128,32 @@ externalSecrets:
128
128
  `);
129
129
  });
130
130
 
131
+ it('should stringify a gcp-secrets-manager provider block, one row per project', () => {
132
+ const output = stringifyEnvironment({
133
+ uid: 'env1',
134
+ name: 'test',
135
+ variables: [],
136
+ externalSecrets: {
137
+ type: 'gcp-secrets-manager',
138
+ variables: [
139
+ { uid: 'e1', name: 'staging', projectId: 'my-staging-project', enabled: true },
140
+ { uid: 'e2', name: 'prod', projectId: 'my-prod-project', enabled: true }
141
+ ]
142
+ },
143
+ color: null
144
+ } as any);
145
+
146
+ expect(output).toBe(`name: test
147
+ externalSecrets:
148
+ type: gcp-secrets-manager
149
+ variables:
150
+ - name: staging
151
+ projectId: my-staging-project
152
+ - name: prod
153
+ projectId: my-prod-project
154
+ `);
155
+ });
156
+
131
157
  it('should keep a half-filled row (a name with an empty identifier)', () => {
132
158
  const output = stringifyEnvironment({
133
159
  uid: 'env1',
@@ -1,7 +1,7 @@
1
1
  import * as YAML from 'yaml';
2
2
 
3
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'];
4
+ const BLOCK_KEYS = ['info', 'http', 'graphql', 'grpc', 'websocket', 'mock', 'routes', 'runtime', 'settings', 'examples', 'docs', 'items', 'request'];
5
5
 
6
6
  export const stringifyYml = (obj: any): string => {
7
7
  const yamlStr = YAML.stringify(obj, {
package/src/index.ts CHANGED
@@ -13,10 +13,12 @@ import {
13
13
  parseYmlCollection,
14
14
  parseYmlFolder,
15
15
  parseYmlEnvironment,
16
+ parseYmlMockServer,
16
17
  stringifyYmlItem,
17
18
  stringifyYmlFolder,
18
19
  stringifyYmlCollection,
19
- stringifyYmlEnvironment
20
+ stringifyYmlEnvironment,
21
+ stringifyYmlMockServer
20
22
  } from './formats/yml';
21
23
  import { dotenvToJson } from '@usebruno/lang';
22
24
  import BruParserWorker from './workers';
@@ -75,6 +77,22 @@ export const stringifyRequestViaWorker = async (requestObj: any, options: { form
75
77
  return await fileParserWorker.stringifyRequest(requestObj, options.format);
76
78
  };
77
79
 
80
+ export const parseFolderViaWorker = async (content: string, options: { format: CollectionFormat }): Promise<any> => {
81
+ return await getWorkerInstance().parseFolder(content, options.format);
82
+ };
83
+
84
+ export const stringifyFolderViaWorker = async (folderObj: any, options: { format: CollectionFormat }): Promise<string> => {
85
+ return await getWorkerInstance().stringifyFolder(folderObj, options.format);
86
+ };
87
+
88
+ export const parseEnvironmentViaWorker = async (content: string, options: { format: CollectionFormat }): Promise<any> => {
89
+ return await getWorkerInstance().parseEnvironment(content, options.format);
90
+ };
91
+
92
+ export const stringifyEnvironmentViaWorker = async (envObj: any, options: { format: CollectionFormat }): Promise<string> => {
93
+ return await getWorkerInstance().stringifyEnvironment(envObj, options.format);
94
+ };
95
+
78
96
  // collection
79
97
  export const parseCollection = (content: string, options: ParseOptions = { format: DEFAULT_COLLECTION_FORMAT }): any => {
80
98
  if (options.format === 'bru') {
@@ -132,6 +150,21 @@ export const stringifyEnvironment = (envObj: BrunoEnvironment, options: Stringif
132
150
  throw new Error(`Unsupported format: ${options.format}`);
133
151
  };
134
152
 
153
+ // mock server — workspace-level entity, opencollection yml only
154
+ export const parseMockServer = (content: string, options: ParseOptions = { format: 'yml' }): any => {
155
+ if (options.format === 'yml') {
156
+ return parseYmlMockServer(content);
157
+ }
158
+ throw new Error(`Unsupported format: ${options.format}`);
159
+ };
160
+
161
+ export const stringifyMockServer = (mockServerObj: any, options: StringifyOptions = { format: 'yml' }): string => {
162
+ if (options.format === 'yml') {
163
+ return stringifyYmlMockServer(mockServerObj);
164
+ }
165
+ throw new Error(`Unsupported format: ${options.format}`);
166
+ };
167
+
135
168
  export const parseDotEnv = (content: string): Record<string, string> => {
136
169
  return dotenvToJson(content);
137
170
  };
package/src/types.ts CHANGED
@@ -26,4 +26,5 @@ export interface BrunoPresetsExtension {
26
26
  type?: string;
27
27
  url?: string;
28
28
  };
29
+ defaultEnvironment?: string;
29
30
  }
@@ -1,10 +1,18 @@
1
1
  import { Worker } from 'node:worker_threads';
2
2
 
3
+ type WorkerTaskType
4
+ = | 'parse'
5
+ | 'stringify'
6
+ | 'parseFolder'
7
+ | 'stringifyFolder'
8
+ | 'parseEnvironment'
9
+ | 'stringifyEnvironment';
10
+
3
11
  interface QueuedTask {
4
12
  priority: number;
5
13
  scriptPath: string;
6
14
  data: any;
7
- taskType: 'parse' | 'stringify';
15
+ taskType: WorkerTaskType;
8
16
  resolve?: (value: any) => void;
9
17
  reject?: (reason?: any) => void;
10
18
  }
@@ -58,7 +66,7 @@ class WorkerQueue {
58
66
  }
59
67
  }
60
68
 
61
- async runWorker({ scriptPath, data, taskType }: { scriptPath: string; data: any; taskType: 'parse' | 'stringify' }) {
69
+ async runWorker({ scriptPath, data, taskType }: { scriptPath: string; data: any; taskType: WorkerTaskType }) {
62
70
  return new Promise(async (resolve, reject) => {
63
71
  let worker = await this.getWorkerForScriptPath(scriptPath);
64
72
 
@@ -55,7 +55,15 @@ class BruParserWorker {
55
55
  return queueForSize?.workerQueue ?? this.workerQueues[this.workerQueues.length - 1].workerQueue;
56
56
  }
57
57
 
58
- private async enqueueTask({ data, taskType, format = DEFAULT_COLLECTION_FORMAT }: { data: any; taskType: 'parse' | 'stringify'; format?: CollectionFormat }): Promise<any> {
58
+ private async enqueueTask({
59
+ data,
60
+ taskType,
61
+ format = DEFAULT_COLLECTION_FORMAT
62
+ }: {
63
+ data: any;
64
+ taskType: 'parse' | 'stringify' | 'parseFolder' | 'stringifyFolder' | 'parseEnvironment' | 'stringifyEnvironment';
65
+ format?: CollectionFormat;
66
+ }): Promise<any> {
59
67
  const size = getSize(data);
60
68
  const workerQueue = this.getWorkerQueue(size);
61
69
  const workerScriptPath = path.join(__dirname, './workers/worker-script.js');
@@ -76,6 +84,22 @@ class BruParserWorker {
76
84
  return this.enqueueTask({ data, taskType: 'stringify', format });
77
85
  }
78
86
 
87
+ async parseFolder(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
88
+ return this.enqueueTask({ data, taskType: 'parseFolder', format });
89
+ }
90
+
91
+ async stringifyFolder(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
92
+ return this.enqueueTask({ data, taskType: 'stringifyFolder', format });
93
+ }
94
+
95
+ async parseEnvironment(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
96
+ return this.enqueueTask({ data, taskType: 'parseEnvironment', format });
97
+ }
98
+
99
+ async stringifyEnvironment(data: any, format: CollectionFormat = DEFAULT_COLLECTION_FORMAT): Promise<any> {
100
+ return this.enqueueTask({ data, taskType: 'stringifyEnvironment', format });
101
+ }
102
+
79
103
  async cleanup(): Promise<void> {
80
104
  const cleanupPromises = this.workerQueues.map(({ workerQueue }) =>
81
105
  workerQueue.cleanup()
@@ -1,39 +1,63 @@
1
1
  import { parentPort } from 'node:worker_threads';
2
- import { parseBruRequest, stringifyBruRequest } from '../formats/bru';
3
- import { parseYmlItem, stringifyYmlItem } from '../formats/yml';
2
+ import {
3
+ parseBruRequest,
4
+ parseBruCollection,
5
+ parseBruEnvironment,
6
+ stringifyBruRequest,
7
+ stringifyBruCollection,
8
+ stringifyBruEnvironment
9
+ } from '../formats/bru';
10
+ import {
11
+ parseYmlItem,
12
+ parseYmlFolder,
13
+ parseYmlEnvironment,
14
+ stringifyYmlItem,
15
+ stringifyYmlFolder,
16
+ stringifyYmlEnvironment
17
+ } from '../formats/yml';
4
18
  import { CollectionFormat } from '../types';
5
19
  import { DEFAULT_COLLECTION_FORMAT } from '../constants';
6
20
 
21
+ type TaskType
22
+ = | 'parse'
23
+ | 'stringify'
24
+ | 'parseFolder'
25
+ | 'stringifyFolder'
26
+ | 'parseEnvironment'
27
+ | 'stringifyEnvironment';
28
+
7
29
  interface WorkerMessage {
8
- taskType: 'parse' | 'stringify';
30
+ taskType: TaskType;
9
31
  data: {
10
32
  data: any;
11
33
  format?: CollectionFormat;
12
34
  };
13
35
  }
14
36
 
37
+ const runTask = (taskType: TaskType, data: any, format: CollectionFormat): any => {
38
+ switch (taskType) {
39
+ case 'parse':
40
+ return format === 'yml' ? parseYmlItem(data) : parseBruRequest(data);
41
+ case 'stringify':
42
+ return format === 'yml' ? stringifyYmlItem(data) : stringifyBruRequest(data);
43
+ case 'parseFolder':
44
+ return format === 'yml' ? parseYmlFolder(data) : parseBruCollection(data);
45
+ case 'stringifyFolder':
46
+ return format === 'yml' ? stringifyYmlFolder(data) : stringifyBruCollection(data, true);
47
+ case 'parseEnvironment':
48
+ return format === 'yml' ? parseYmlEnvironment(data) : parseBruEnvironment(data);
49
+ case 'stringifyEnvironment':
50
+ return format === 'yml' ? stringifyYmlEnvironment(data) : stringifyBruEnvironment(data);
51
+ default:
52
+ throw new Error(`Unknown task type: ${taskType}`);
53
+ }
54
+ };
55
+
15
56
  parentPort?.on('message', async (message: WorkerMessage) => {
16
57
  try {
17
58
  const { taskType, data: messageData } = message;
18
59
  const { data, format = DEFAULT_COLLECTION_FORMAT } = messageData;
19
- let result: any;
20
-
21
- if (taskType === 'parse') {
22
- if (format === 'yml') {
23
- result = parseYmlItem(data);
24
- } else {
25
- result = parseBruRequest(data);
26
- }
27
- } else if (taskType === 'stringify') {
28
- if (format === 'yml') {
29
- result = stringifyYmlItem(data);
30
- } else {
31
- result = stringifyBruRequest(data);
32
- }
33
- } else {
34
- throw new Error(`Unknown task type: ${taskType}`);
35
- }
36
-
60
+ const result = runTask(taskType, data, format);
37
61
  parentPort?.postMessage(result);
38
62
  } catch (error: any) {
39
63
  console.error('Worker error:', error);