Skip to content

Commit 3033f06

Browse files
committed
feat: find and use import alias
1 parent d8c47c9 commit 3033f06

File tree

6 files changed

+52
-12
lines changed

6 files changed

+52
-12
lines changed

packages/openapi-code-generator/src/core/file-loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export function isRemote(location: string): boolean {
7272

7373
export type CompilerOptions = Pick<
7474
TsCompilerOptions,
75-
"exactOptionalPropertyTypes"
75+
"exactOptionalPropertyTypes" | "paths"
7676
>
7777

7878
export function loadTsConfigCompilerOptions(

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
@@ -4,7 +4,10 @@ export class ImportBuilder {
44
private readonly imports: Record<string, Set<string>> = {}
55
private readonly importAll: Record<string, string> = {}
66

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

912
from(from: string) {
1013
return {
@@ -68,7 +71,7 @@ export class ImportBuilder {
6871
}
6972

7073
private add(name: string, from: string, isAll: boolean): void {
71-
from = ImportBuilder.normalizeFrom(from, this.unit?.filename)
74+
from = this.normalizeFrom(from, this.unit?.filename)
7275
const imports = (this.imports[from] =
7376
this.imports[from] ?? new Set<string>())
7477

@@ -79,13 +82,17 @@ export class ImportBuilder {
7982
}
8083
}
8184

82-
public static normalizeFrom(from: string, filename?: string) {
85+
public normalizeFrom(from: string, filename?: string) {
8386
if (from.endsWith(".ts")) {
8487
from = from.substring(0, from.length - ".ts".length)
8588
}
8689

8790
// TODO: does this work on windows?
8891
if (filename && from.startsWith("./")) {
92+
if (this.importAlias) {
93+
return this.importAlias + from.split(path.sep).slice(1).join(path.sep)
94+
}
95+
8996
const unitDirname = path.dirname(filename)
9097
const fromDirname = path.dirname(from)
9198

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,

scripts/generate.single.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ if [[ "$template" == "typescript-nextjs" ]]; then
1515
output="integration-tests/$template/src"
1616
fi
1717

18+
# TODO: pushd to project directory for correct tsconfig.json finding, adjust paths to be relative to project.
19+
1820
node ./packages/openapi-code-generator/dist/index.js \
1921
--input="$path" \
2022
--output="$output" \

0 commit comments

Comments
 (0)