Skip to content

Commit 8a73866

Browse files
committed
fix(core): polish tags-operations output modes
- Use kebab-case for operation filenames (consistent with mock filenames) - Pass oneMore: true to all generateMutatorImports calls so relative mutator paths resolve correctly from the tag subdirectory - Filter helper imports per-operation to only names used in that operation's implementation, eliminating TS6133 unused-import errors - Write a root barrel (dirname/index.ts) re-exporting per-tag barrels, and restrict workspace index re-exports to that root barrel + global schemas to eliminate TS2308 ambiguous-re-export errors
1 parent c4c0e16 commit 8a73866

5 files changed

Lines changed: 106 additions & 22 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,4 @@
124124
}
125125
},
126126
"namespace": "@orval"
127-
}
127+
}

packages/core/src/writers/tags-operations-mode.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,7 @@ export async function writeTagsOperationsMode({
168168

169169
const operationFilePaths = await Promise.all(
170170
operations.map(async (operation) => {
171-
const operationFilename = conventionName(
172-
operation.operationName,
173-
output.namingConvention,
174-
);
171+
const operationFilename = kebab(operation.operationName);
175172
const implementationPath = path.join(
176173
tagDir,
177174
`${operationFilename}${extension}`,
@@ -197,7 +194,11 @@ export async function writeTagsOperationsMode({
197194
let data = header;
198195

199196
if (hasHelpers) {
200-
data += buildTagHelpersImport(helpers, helperImportPath);
197+
data += buildTagHelpersImport(
198+
helpers,
199+
helperImportPath,
200+
operation.implementation,
201+
);
201202
}
202203

203204
data += builder.imports({
@@ -221,40 +222,49 @@ export async function writeTagsOperationsMode({
221222
data += generateMutatorImports({
222223
mutators: operation.mutators,
223224
implementation: operation.implementation,
225+
oneMore: true,
224226
});
225227
}
226228

227229
if (operation.clientMutators) {
228230
data += generateMutatorImports({
229231
mutators: operation.clientMutators,
232+
oneMore: true,
230233
});
231234
}
232235

233236
if (operation.formData) {
234-
data += generateMutatorImports({ mutators: operation.formData });
237+
data += generateMutatorImports({
238+
mutators: operation.formData,
239+
oneMore: true,
240+
});
235241
}
236242

237243
if (operation.formUrlEncoded) {
238244
data += generateMutatorImports({
239245
mutators: operation.formUrlEncoded,
246+
oneMore: true,
240247
});
241248
}
242249

243250
if (operation.paramsSerializer) {
244251
data += generateMutatorImports({
245252
mutators: operation.paramsSerializer,
253+
oneMore: true,
246254
});
247255
}
248256

249257
if (operation.paramsFilter) {
250258
data += generateMutatorImports({
251259
mutators: operation.paramsFilter,
260+
oneMore: true,
252261
});
253262
}
254263

255264
if (operation.fetchReviver) {
256265
data += generateMutatorImports({
257266
mutators: operation.fetchReviver,
267+
oneMore: true,
258268
});
259269
}
260270

@@ -439,8 +449,21 @@ export async function writeTagsOperationsMode({
439449
}),
440450
);
441451

452+
const allGeneratedPaths = generatedFilePathsArray.flat();
453+
454+
let rootIndexPath: string | undefined;
455+
if (output.indexFiles) {
456+
const importExtension = getImportExtension(extension, output.tsconfig);
457+
const rootBarrelContent = tagEntries
458+
.map(([tag]) => `export * from './${tag}/index${importExtension}';\n`)
459+
.join('');
460+
rootIndexPath = path.join(dirname, `index${extension}`);
461+
await writeGeneratedFile(rootIndexPath, rootBarrelContent);
462+
}
463+
442464
return [
443465
...(schemasPath ? [schemasPath] : []),
444-
...generatedFilePathsArray.flat(),
466+
...(rootIndexPath ? [rootIndexPath] : []),
467+
...allGeneratedPaths,
445468
];
446469
}

packages/core/src/writers/tags-operations-split-mode.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,7 @@ export async function writeTagsOperationsSplitMode({
143143

144144
const operationFilePaths = await Promise.all(
145145
operations.map(async (operation) => {
146-
const operationFilename = conventionName(
147-
operation.operationName,
148-
output.namingConvention,
149-
);
146+
const operationFilename = kebab(operation.operationName);
150147
const implementationPath = path.join(
151148
tagDir,
152149
`${operationFilename}${extension}`,
@@ -211,7 +208,11 @@ export async function writeTagsOperationsSplitMode({
211208
let data = header;
212209

213210
if (hasHelpers) {
214-
data += buildTagHelpersImport(helpers, helperImportPath);
211+
data += buildTagHelpersImport(
212+
helpers,
213+
helperImportPath,
214+
operation.implementation,
215+
);
215216
}
216217

217218
data += builder.imports({
@@ -235,40 +236,49 @@ export async function writeTagsOperationsSplitMode({
235236
data += generateMutatorImports({
236237
mutators: operation.mutators,
237238
implementation: operation.implementation,
239+
oneMore: true,
238240
});
239241
}
240242

241243
if (operation.clientMutators) {
242244
data += generateMutatorImports({
243245
mutators: operation.clientMutators,
246+
oneMore: true,
244247
});
245248
}
246249

247250
if (operation.formData) {
248-
data += generateMutatorImports({ mutators: operation.formData });
251+
data += generateMutatorImports({
252+
mutators: operation.formData,
253+
oneMore: true,
254+
});
249255
}
250256

251257
if (operation.formUrlEncoded) {
252258
data += generateMutatorImports({
253259
mutators: operation.formUrlEncoded,
260+
oneMore: true,
254261
});
255262
}
256263

257264
if (operation.paramsSerializer) {
258265
data += generateMutatorImports({
259266
mutators: operation.paramsSerializer,
267+
oneMore: true,
260268
});
261269
}
262270

263271
if (operation.paramsFilter) {
264272
data += generateMutatorImports({
265273
mutators: operation.paramsFilter,
274+
oneMore: true,
266275
});
267276
}
268277

269278
if (operation.fetchReviver) {
270279
data += generateMutatorImports({
271280
mutators: operation.fetchReviver,
281+
oneMore: true,
272282
});
273283
}
274284

@@ -466,8 +476,21 @@ export async function writeTagsOperationsSplitMode({
466476
}),
467477
);
468478

479+
const allGeneratedPaths = generatedFilePathsArray.flat();
480+
481+
let rootIndexPath: string | undefined;
482+
if (output.indexFiles) {
483+
const importExtension = getImportExtension(extension, output.tsconfig);
484+
const rootBarrelContent = tagEntries
485+
.map(([tag]) => `export * from './${tag}/index${importExtension}';\n`)
486+
.join('');
487+
rootIndexPath = path.join(dirname, `index${extension}`);
488+
await writeGeneratedFile(rootIndexPath, rootBarrelContent);
489+
}
490+
469491
return [
470492
...(globalSchemasPath ? [globalSchemasPath] : []),
471-
...generatedFilePathsArray.flat(),
493+
...(rootIndexPath ? [rootIndexPath] : []),
494+
...allGeneratedPaths,
472495
];
473496
}

packages/core/src/writers/target-tags-operations.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,20 @@ function extractDeclaredNames(implementation: string): {
103103
export function buildTagHelpersImport(
104104
helpers: GeneratorTagHelpers,
105105
helperImportPath: string,
106+
usedIn?: string,
106107
): string {
108+
const used = (name: string) =>
109+
!usedIn || new RegExp(String.raw`\b${name}\b`).test(usedIn);
110+
111+
const typeNames = helpers.typeNames.filter(used);
112+
const valueNames = helpers.valueNames.filter(used);
113+
107114
let result = '';
108-
if (helpers.typeNames.length > 0) {
109-
result += `import type { ${helpers.typeNames.join(', ')} } from '${helperImportPath}';\n`;
115+
if (typeNames.length > 0) {
116+
result += `import type { ${typeNames.join(', ')} } from '${helperImportPath}';\n`;
110117
}
111-
if (helpers.valueNames.length > 0) {
112-
result += `import { ${helpers.valueNames.join(', ')} } from '${helperImportPath}';\n`;
118+
if (valueNames.length > 0) {
119+
result += `import { ${valueNames.join(', ')} } from '${helperImportPath}';\n`;
113120
}
114121
return result;
115122
}

packages/orval/src/write-specs.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -422,19 +422,50 @@ function getImplementationPathsForIndex(
422422
output.mode === OutputMode.SPLIT &&
423423
getComparableFilePath(output.target) === getComparableFilePath(indexFile);
424424

425-
if (!isSplitModeWithColocatedTarget) {
425+
if (isSplitModeWithColocatedTarget) {
426+
const targetInfo = getFileInfo(output.target, {
427+
extension: output.fileExtension,
428+
});
429+
const defaultSiblingSchemas = path.join(
430+
targetInfo.dirname,
431+
`${targetInfo.filename}.schemas${output.fileExtension}`,
432+
);
433+
return excludeFilePath(paths, defaultSiblingSchemas);
434+
}
435+
436+
// tags-operations and tags-operations-split produce a root barrel
437+
// (dirname/index<ext>) plus per-tag barrels and individual operation files.
438+
// The workspace index must only re-export the root barrel (and the global
439+
// schemas file when present) — re-exporting individual operation files,
440+
// per-tag barrels, helper files, and per-operation schema files causes
441+
// TS2308 ambiguous-re-export errors because many types appear in multiple
442+
// files simultaneously (shared helpers across tags; shared schemas across
443+
// operations).
444+
const isTagsOperationsMode =
445+
output.mode === OutputMode.TAGS_OPERATIONS ||
446+
output.mode === OutputMode.TAGS_OPERATIONS_SPLIT;
447+
448+
if (!isTagsOperationsMode || !shouldExcludeSelf) {
426449
return paths;
427450
}
428451

429452
const targetInfo = getFileInfo(output.target, {
430453
extension: output.fileExtension,
431454
});
432-
const defaultSiblingSchemas = path.join(
455+
const rootBarrel = path.join(
456+
targetInfo.dirname,
457+
`index${output.fileExtension}`,
458+
);
459+
const globalSchemas = path.join(
433460
targetInfo.dirname,
434461
`${targetInfo.filename}.schemas${output.fileExtension}`,
435462
);
436463

437-
return excludeFilePath(paths, defaultSiblingSchemas);
464+
return paths.filter(
465+
(p) =>
466+
getComparableFilePath(p) === getComparableFilePath(rootBarrel) ||
467+
getComparableFilePath(p) === getComparableFilePath(globalSchemas),
468+
);
438469
}
439470

440471
export async function writeSpecs(

0 commit comments

Comments
 (0)