From 6a29923ebf3d74b38b9a2dd203b11bac6eaa0a31 Mon Sep 17 00:00:00 2001 From: Marian Theisen Date: Mon, 30 Mar 2020 18:35:16 +0200 Subject: [PATCH] fix relative imports --- ...{get-response.ts => get-users.response.ts} | 2 +- .../{users-gateway.ts => users.gateway.ts} | 8 ++-- examples/generated/tsconfig.json | 24 ++++++++++++ src/defaults.ts | 8 ++-- src/generators/index.ts | 8 ++-- src/index.ts | 14 ++++--- src/util/paths.ts | 16 +++++++- test/unit/util/paths.test.ts | 38 ++++++++++++++++++- 8 files changed, 96 insertions(+), 22 deletions(-) rename examples/generated/simple-endpoint-without-refs/users/{get-response.ts => get-users.response.ts} (52%) rename examples/generated/simple-endpoint-without-refs/users/{users-gateway.ts => users.gateway.ts} (58%) create mode 100644 examples/generated/tsconfig.json diff --git a/examples/generated/simple-endpoint-without-refs/users/get-response.ts b/examples/generated/simple-endpoint-without-refs/users/get-users.response.ts similarity index 52% rename from examples/generated/simple-endpoint-without-refs/users/get-response.ts rename to examples/generated/simple-endpoint-without-refs/users/get-users.response.ts index 6dbb2f1..9d9cc2f 100644 --- a/examples/generated/simple-endpoint-without-refs/users/get-response.ts +++ b/examples/generated/simple-endpoint-without-refs/users/get-users.response.ts @@ -1,4 +1,4 @@ -export type GetResponse = { +export type GetUsersResponse = { id?: number; name: string; }[]; diff --git a/examples/generated/simple-endpoint-without-refs/users/users-gateway.ts b/examples/generated/simple-endpoint-without-refs/users/users.gateway.ts similarity index 58% rename from examples/generated/simple-endpoint-without-refs/users/users-gateway.ts rename to examples/generated/simple-endpoint-without-refs/users/users.gateway.ts index 97e2960..c58cd92 100644 --- a/examples/generated/simple-endpoint-without-refs/users/users-gateway.ts +++ b/examples/generated/simple-endpoint-without-refs/users/users.gateway.ts @@ -3,13 +3,13 @@ import { HttpClient } from '@angular/common/http'; import { HttpResponse } from '@angular/common/http'; import { Inject } from '@angular/core'; import { Injectable } from '@angular/core'; -import { API_HOST } from './api-host'; -import { GetResponse } from './users/get-response'; +import { API_HOST } from '../api-host'; +import { GetUsersResponse } from './get-users.response'; @Injectable() export class UsersGateway { constructor(private readonly _httpClient: HttpClient, @Inject(API_HOST) private readonly _apiHost: string) {} - get(options?: Parameters[2]): Observable> { - return this._httpClient.request('get', '/users', options); + getUsers(options?: Parameters[2]): Observable> { + return this._httpClient.request('getUsers', '/users', options); } } diff --git a/examples/generated/tsconfig.json b/examples/generated/tsconfig.json new file mode 100644 index 0000000..1f1753e --- /dev/null +++ b/examples/generated/tsconfig.json @@ -0,0 +1,24 @@ +{ + "include": [ + "**/*.ts" + ], + + "compilerOptions": { + "experimentalDecorators": true, + "strict": true, + "target": "es2015", + "module": "CommonJS", + "moduleResolution": "node", + "outDir": "dist", + "declaration": true, + "typeRoots": [ + "../../node_modules/@types" + ], + "lib": [ + "ES2015" + ], + "types": [ + "node" + ] + } +} diff --git a/src/defaults.ts b/src/defaults.ts index 0da0d9d..3c24af9 100644 --- a/src/defaults.ts +++ b/src/defaults.ts @@ -28,12 +28,12 @@ export function httpVerbAndHrefBasedMethodName( const prefix = method.toLocaleLowerCase(); const localHref = stripCommonPath(href, commonHref); - return [prefix, ...pathToCapitalizedNameParts(localHref)].join(); + return [prefix, ...pathToCapitalizedNameParts(localHref)].join(''); } export function commonHrefBasedClassName(resource: HyperSchemaResource4): string { const commonHref = getCommonHref(resource); - const typeName = pathToCapitalizedNameParts(commonHref).join(); + const typeName = pathToCapitalizedNameParts(commonHref).join(''); if (typeName === '') { throw `can't build type-name for href ${commonHref}`; } @@ -78,7 +78,7 @@ export function methodNameBasedQueryParamsTypeName( } export function kebapizedClassName(nameOfClass: string): string { - return paramCase(nameOfClass); + return paramCase(nameOfClass).replace(/-(gateway|response|request)/, '.$1'); } export function allInRoot(generated: GeneratedCode): string[] { @@ -91,7 +91,7 @@ export function scopeByResource(generated: GeneratedCode): string[] { return []; case 'transfer-object': case 'gateway': - return [kebapizedClassName(commonHrefBasedClassName(generated.source.resource)).replace('-gateway', '')]; + return [kebapizedClassName(commonHrefBasedClassName(generated.source.resource)).replace('.gateway', '')]; } } diff --git a/src/generators/index.ts b/src/generators/index.ts index 3f5d45d..52e8ec4 100644 --- a/src/generators/index.ts +++ b/src/generators/index.ts @@ -1,6 +1,7 @@ import {compile, Options} from 'json-schema-to-typescript'; import {GeneratorOptions} from '../options'; import {GatewayClass, GatewayOperation, ResponseTypeDescriptor} from '../type-model'; +import {relativePath} from '../util/paths'; export interface GeneratedType { readonly dependencies: Dependency[]; @@ -65,10 +66,11 @@ export function getImport(options: GeneratorOptions, dependency: Dependency, tar return [dependency.name, dependency.source]; case 'code': case 'transfer-object': - const path = options.getTargetPath(dependency); + const localPath = targetPath.join('/'); const fileName = options.buildFileName(dependency.nameOfClass); - const fullPath = ['.', ...path, fileName].join('/'); - // TODO: relativize + const dependencyPath = [...options.getTargetPath(dependency), fileName].join('/'); + let fullPath = relativePath(localPath, dependencyPath); + return [dependency.nameOfClass, fullPath]; } } diff --git a/src/index.ts b/src/index.ts index 46d923a..4a23ac9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,8 +5,7 @@ import {defaultOptions} from './defaults'; import { Dependency, generateApiHostInjectionToken, - GeneratedAdditional, GeneratedCode, - GeneratedGatewayClass, + GeneratedCode, GeneratedType, generateGatewayTypeSource, generateImports, @@ -108,7 +107,7 @@ export async function generateGateways( generatedClasses.push(gatewayTypeDef); for (let operation of gatewayClass.operations) { - if(operation.response) { + if (operation.response) { const responseTypeDef = await generateResponseType(operation.response, options.json2ts); generatedClasses.push(responseTypeDef); gatewayTypeDef.dependencies.push(responseTypeDef); @@ -116,11 +115,14 @@ export async function generateGateways( } } - return Array.from(buildFileSet(options, generatedClasses)); } -export function generateAllImports(options: GeneratorOptions, dependencies: Dependency[], targetPath: string[]): string { +export function generateAllImports( + options: GeneratorOptions, + dependencies: Dependency[], + targetPath: string[], +): string { return generateImports( dependencies.map((dep) => getImport(options, dep, targetPath)), ); @@ -147,6 +149,6 @@ export function* buildFileSet( path: targetPath, name: options.buildFileName(gateway.nameOfClass), content: combine(options, gateway, targetPath), - } + }; } } diff --git a/src/util/paths.ts b/src/util/paths.ts index 7ba3582..10c758f 100644 --- a/src/util/paths.ts +++ b/src/util/paths.ts @@ -19,9 +19,21 @@ export function getCommonPath(paths: string[]) { } export function stripCommonPath(path: string, commonPath: string): string { - if(path.startsWith(commonPath)) { - return path.slice(commonPath.length); + if(path.startsWith(commonPath + '/')) { + return path.slice(commonPath.length + 1); } return path; } + + +export function relativePath(from: string, to: string): string { + from = from + '/'; + const commonPath = getCommonPath([from, to]); + const fromLevel = stripCommonPath(from, commonPath).split('/').length - 1; + const dives = Array(fromLevel).fill('..'); + to = [...dives, stripCommonPath(to, commonPath)].join('/'); + + + return to.startsWith('../') ? to : './' + to; +} diff --git a/test/unit/util/paths.test.ts b/test/unit/util/paths.test.ts index 88ab99d..e729e89 100644 --- a/test/unit/util/paths.test.ts +++ b/test/unit/util/paths.test.ts @@ -1,4 +1,4 @@ -import {getCommonPath, stripCommonPath} from '../../../src/util/paths'; +import {getCommonPath, relativePath, stripCommonPath} from '../../../src/util/paths'; describe('getCommonPath', () => { test('simple case', () => { @@ -43,7 +43,41 @@ describe('stripCommonPath', () => { test('simple case', () => { const stripped = stripCommonPath('/foo/bar/blub', '/foo/bar'); - expect(stripped).toEqual('/blub'); + expect(stripped).toEqual('blub'); }); +}); + +describe('relativePath', () => { + test('root', () => { + const result = relativePath( + 'faa', + 'bum' + ); + + expect(result).toEqual('../bum') + }); + test('unrelated', () => { + const result = relativePath( + 'faa', + 'foo/baz/bum' + ); + + expect(result).toEqual('../foo/baz/bum') + }); + test('nephew', () => { + const result = relativePath( + 'foo', + 'foo/baz/bum' + ); + + expect(result).toEqual('./baz/bum') + }); + test('siblings', () => { + const result = relativePath( + 'foo', + 'foo/baz' + ); + expect(result).toEqual('./baz') + }); });