Skip to content

Commit 28c3a60

Browse files
committed
feat: find and use import alias
1 parent c5af460 commit 28c3a60

File tree

4 files changed

+49
-11
lines changed

4 files changed

+49
-11
lines changed

packages/openapi-code-generator/src/core/schemas/tsconfig.schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export const tsconfigSchema = z.object({
3535
noPropertyAccessFromIndexSignature: z.boolean(),
3636
allowUnusedLabels: z.boolean(),
3737
allowUnreachableCode: z.boolean(),
38+
paths: z.record(z.array(z.string())),
3839
})
3940
.partial(),
4041
})

packages/openapi-code-generator/src/core/utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ export function isDefined<T>(it: T | undefined): it is T {
44
return it !== undefined
55
}
66

7+
export function isTruthy<T>(it: T | undefined | null | "" | 0): it is T {
8+
return Boolean(it)
9+
}
10+
711
export function hasSingleElement<T>(it: T[]): it is [T] {
812
return it.length === 1
913
}

packages/openapi-code-generator/src/typescript/common/import-builder.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ export class ImportBuilder {
55
private readonly imports: Record<string, Set<string>> = {}
66
private readonly importAll: Record<string, string> = {}
77

8-
constructor(private readonly unit?: {filename: string}) {}
8+
constructor(
9+
private readonly unit?: {filename: string},
10+
private readonly importAlias?: string,
11+
) {}
912

1013
from(from: string) {
1114
return {
@@ -76,7 +79,7 @@ export class ImportBuilder {
7679

7780
private add(name: string, from: string, isAll: boolean): void {
7881
// biome-ignore lint/style/noParameterAssign: <explanation>
79-
from = ImportBuilder.normalizeFrom(from, this.unit?.filename)
82+
from = this.normalizeFrom(from, this.unit?.filename)
8083
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
8184
const imports = (this.imports[from] =
8285
this.imports[from] ?? new Set<string>())
@@ -88,14 +91,18 @@ export class ImportBuilder {
8891
}
8992
}
9093

91-
public static normalizeFrom(from: string, filename?: string) {
94+
public normalizeFrom(from: string, filename?: string) {
9295
if (from.endsWith(".ts")) {
9396
// biome-ignore lint/style/noParameterAssign: <explanation>
9497
from = from.substring(0, from.length - ".ts".length)
9598
}
9699

97100
// TODO: does this work on windows?
98101
if (filename && from.startsWith("./")) {
102+
if (this.importAlias) {
103+
return this.importAlias + from.split(path.sep).slice(1).join(path.sep)
104+
}
105+
99106
const unitDirname = path.dirname(filename)
100107
const fromDirname = path.dirname(from)
101108

packages/openapi-code-generator/src/typescript/typescript-nextjs/typescript-nextjs.generator.ts

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,20 @@ import {
88
SyntaxKind,
99
VariableDeclarationKind,
1010
} from "ts-morph"
11+
import {CompilerOptions} from "../../core/file-loader"
1112
import {Input} from "../../core/input"
1213
import {
1314
IRModelObject,
1415
IROperation,
1516
IRParameter,
1617
} from "../../core/openapi-types-normalized"
17-
import {HttpMethod, isDefined, isHttpMethod, titleCase} from "../../core/utils"
18+
import {
19+
HttpMethod,
20+
isDefined,
21+
isHttpMethod,
22+
isTruthy,
23+
titleCase,
24+
} from "../../core/utils"
1825
import {OpenapiGeneratorConfig} from "../../templates.types"
1926
import {CompilationUnit, ICompilable} from "../common/compilation-units"
2027
import {ImportBuilder} from "../common/import-builder"
@@ -315,6 +322,7 @@ ${routes.join("\n\n")}
315322
export class NextJSAppRouterBuilder implements ICompilable {
316323
constructor(
317324
public readonly filename: string,
325+
private readonly imports: ImportBuilder,
318326
private readonly companionFilename: string,
319327
private readonly sourceFile: SourceFile,
320328
) {}
@@ -388,7 +396,7 @@ export class NextJSAppRouterBuilder implements ICompilable {
388396
toCompilationUnit(): CompilationUnit {
389397
// Reconcile imports - attempt to find an existing one and replace it with correct one
390398
const imports = this.sourceFile.getImportDeclarations()
391-
const from = ImportBuilder.normalizeFrom(
399+
const from = this.imports.normalizeFrom(
392400
"./" + this.companionFilename,
393401
"./" + this.filename,
394402
)
@@ -412,25 +420,39 @@ export class NextJSAppRouterBuilder implements ICompilable {
412420

413421
return new CompilationUnit(
414422
this.filename,
415-
new ImportBuilder(),
423+
this.imports,
416424
this.toString(),
417425
false,
418426
)
419427
}
420428
}
421429

430+
function findImportAlias(dest: string, compilerOptions: CompilerOptions) {
431+
const relative = "./" + path.relative(process.cwd(), dest) + "/*"
432+
433+
const alias = Object.entries(compilerOptions.paths || {}).find(([, paths]) =>
434+
paths.includes(relative),
435+
)
436+
437+
return alias ? alias[0].replace("*", "") : undefined
438+
}
439+
422440
export async function generateTypescriptNextJS(
423441
config: OpenapiGeneratorConfig,
424442
): Promise<void> {
425443
const input = config.input
426444

445+
const importAlias = findImportAlias(config.dest, config.compilerOptions)
446+
427447
const subDirectory = process.env["OPENAPI_INTEGRATION_TESTS"]
428448
? path.basename(config.input.loader.entryPointKey)
429449
: ""
430450

431-
const appDirectory = ["./app", subDirectory].filter(isDefined).join(path.sep)
432-
const generatedDirectory = ["./generated", subDirectory]
433-
.filter(isDefined)
451+
const appDirectory = [".", "app", subDirectory]
452+
.filter(isTruthy)
453+
.join(path.sep)
454+
const generatedDirectory = [".", "generated", subDirectory]
455+
.filter(isTruthy)
434456
.join(path.sep)
435457

436458
const rootTypeBuilder = await TypeBuilder.fromInput(
@@ -455,7 +477,7 @@ export async function generateTypescriptNextJS(
455477
routeToNextJSFilepath(group.name),
456478
)
457479

458-
const imports = new ImportBuilder({filename})
480+
const imports = new ImportBuilder({filename}, importAlias)
459481

460482
const routerBuilder = new ServerRouterBuilder(
461483
filename,
@@ -488,6 +510,7 @@ export async function generateTypescriptNextJS(
488510

489511
const nextJSAppRouterBuilder = new NextJSAppRouterBuilder(
490512
nextJsAppRouterPath,
513+
imports,
491514
filename,
492515
sourceFile,
493516
)
@@ -508,7 +531,10 @@ export async function generateTypescriptNextJS(
508531
const clientOutputPath = [generatedDirectory, "clients", "client.ts"].join(
509532
path.sep,
510533
)
511-
const clientImportBuilder = new ImportBuilder({filename: clientOutputPath})
534+
const clientImportBuilder = new ImportBuilder(
535+
{filename: clientOutputPath},
536+
importAlias,
537+
)
512538

513539
const fetchClientBuilder = new TypescriptFetchClientBuilder(
514540
clientOutputPath,

0 commit comments

Comments
 (0)