@contractkit/plugin-bruno 1.5.0 → 1.5.2

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.
@@ -173,19 +173,33 @@ export function generateOpenCollectionIncremental(
173
173
  });
174
174
 
175
175
  const units: IncrementalUnit[] = [];
176
- for (let rootIdx = 0; rootIdx < sortedRoots.length; rootIdx++) {
177
- const root = sortedRoots[rootIdx]!;
176
+ // Track which folder.yml paths we've already emitted so multiple roots sharing
177
+ // an area (the area's own root + its subarea roots) don't each push the
178
+ // area-level folder.yml — that produced N near-duplicate emits per area, only
179
+ // the last of which survived on disk.
180
+ const emittedFolders = new Set<string>();
181
+ let areaSeq = 0;
182
+ for (const root of sortedRoots) {
178
183
  const folder = root.meta['area'] ? slugifyName(root.meta['area']) : deriveFolderName(root.file);
179
- const displayName = (root.meta['area'] ?? folder).charAt(0).toUpperCase() + (root.meta['area'] ?? folder).slice(1);
180
- globalFiles.push({ relativePath: `${folder}/folder.yml`, content: generateFolderFile(displayName, rootIdx + 1) });
184
+ const folderRel = `${folder}/folder.yml`;
185
+ if (!emittedFolders.has(folderRel)) {
186
+ const displayName = (root.meta['area'] ?? folder).charAt(0).toUpperCase() + (root.meta['area'] ?? folder).slice(1);
187
+ areaSeq++;
188
+ globalFiles.push({ relativePath: folderRel, content: generateFolderFile(displayName, areaSeq) });
189
+ emittedFolders.add(folderRel);
190
+ }
181
191
 
182
192
  const subarea = root.meta['subarea'];
183
193
  const subareaSlug = subarea ? slugifyName(subarea) : undefined;
184
194
  const requestDir = subareaSlug ? `${folder}/${subareaSlug}` : folder;
185
195
 
186
196
  if (subareaSlug) {
187
- const subareaDisplayName = subarea!.charAt(0).toUpperCase() + subarea!.slice(1);
188
- globalFiles.push({ relativePath: `${requestDir}/folder.yml`, content: generateFolderFile(subareaDisplayName, 1) });
197
+ const subareaRel = `${requestDir}/folder.yml`;
198
+ if (!emittedFolders.has(subareaRel)) {
199
+ const subareaDisplayName = subarea!.charAt(0).toUpperCase() + subarea!.slice(1);
200
+ globalFiles.push({ relativePath: subareaRel, content: generateFolderFile(subareaDisplayName, 1) });
201
+ emittedFolders.add(subareaRel);
202
+ }
189
203
  }
190
204
 
191
205
  for (const entry of buildOpEntries(root, requestDir, includeInternal)) {
@@ -170,6 +170,24 @@ describe('generateOpenCollection', () => {
170
170
  expect(files.some(f => f.relativePath === 'capital/folder.yml')).toBe(true);
171
171
  });
172
172
 
173
+ it('emits the area-level folder.yml exactly once even when many roots share the area', () => {
174
+ const top = opRoot([opRoute('/identity', [opOperation('get')])], 'identity.op', { area: 'identity' });
175
+ const a = opRoot([opRoute('/businesses', [opOperation('get')])], 'identity-businesses.op', { area: 'identity', subarea: 'businesses' });
176
+ const b = opRoot([opRoute('/persons', [opOperation('get')])], 'identity-persons.op', { area: 'identity', subarea: 'persons' });
177
+ const files = generateOpenCollection([top, a, b], { collectionName: 'API' });
178
+ const areaFolders = files.filter(f => f.relativePath === 'identity/folder.yml');
179
+ expect(areaFolders.length).toBe(1);
180
+ });
181
+
182
+ it('numbers area folder.yml seq by area position, not by root index', () => {
183
+ const aTop = opRoot([opRoute('/a', [opOperation('get')])], 'a.op', { area: 'a' });
184
+ const bTop = opRoot([opRoute('/b', [opOperation('get')])], 'b.op', { area: 'b' });
185
+ const bSub = opRoot([opRoute('/x', [opOperation('get')])], 'b-sub.op', { area: 'b', subarea: 'sub' });
186
+ const files = generateOpenCollection([aTop, bTop, bSub], { collectionName: 'API' });
187
+ expect(files.find(f => f.relativePath === 'a/folder.yml')!.content).toContain('seq: 1');
188
+ expect(files.find(f => f.relativePath === 'b/folder.yml')!.content).toContain('seq: 2');
189
+ });
190
+
173
191
  it('slugifies subarea for the folder path', () => {
174
192
  const root = opRoot([opRoute('/offers', [opOperation('get')])], 'capital.op', { subarea: 'Expansion Capital' });
175
193
  const files = generateOpenCollection([root], { collectionName: 'API' });