From 115bfa31b9707841306e5a602e8ecc4e4267a8fb Mon Sep 17 00:00:00 2001 From: Jan Noehles Date: Fri, 4 Mar 2022 21:19:08 +0100 Subject: [PATCH] V1.1 (#6) Add config object which controls what kind of urls are generated. The lib supports now to only generate relative urls or only absolute urls. Change tests accordingly to fit new api --- .gitignore | 3 +- Dto/GeneratorConfig.php | 48 +++++++++++++++++++++ Service/GeneratorService.php | 78 +++++++++++++++++++++++++---------- Tests/GenerateTest.php | 26 +++++++++--- Tests/output.ts | 5 ++- Tests/output_absolute.test.ts | 17 ++++++++ Tests/output_absolute.ts | 5 +++ Tests/output_relative.test.ts | 17 ++++++++ Tests/output_relative.ts | 5 +++ package-lock.json | 5 ++- package.json | 2 +- readme.md | 12 +++++- 12 files changed, 189 insertions(+), 34 deletions(-) create mode 100644 Dto/GeneratorConfig.php create mode 100644 Tests/output_absolute.test.ts create mode 100644 Tests/output_absolute.ts create mode 100644 Tests/output_relative.test.ts create mode 100644 Tests/output_relative.ts diff --git a/.gitignore b/.gitignore index 4a1f9e2..ba994fc 100644 --- a/.gitignore +++ b/.gitignore @@ -77,4 +77,5 @@ composer.phar .phpunit.result.cache vendor node_modules/ -.idea/ \ No newline at end of file +.idea/ +.phpunit.cache \ No newline at end of file diff --git a/Dto/GeneratorConfig.php b/Dto/GeneratorConfig.php new file mode 100644 index 0000000..524e243 --- /dev/null +++ b/Dto/GeneratorConfig.php @@ -0,0 +1,48 @@ +generateAbsoluteUrls; + } + + public function isGenerateRelativeUrls(): bool + { + return $this->generateRelativeUrls; + } +} diff --git a/Service/GeneratorService.php b/Service/GeneratorService.php index 436387c..8321d1b 100644 --- a/Service/GeneratorService.php +++ b/Service/GeneratorService.php @@ -4,6 +4,7 @@ namespace Bolzer\SymfonyTypescriptRoutes\Service; +use Bolzer\SymfonyTypescriptRoutes\Dto\GeneratorConfig; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouterInterface; @@ -14,14 +15,16 @@ public function __construct( ) { } - public function generate(): array + public function generate(GeneratorConfig $config): array { + $this->assertValidConfiguration($config); + $buffer = [ ...\array_values($this->getTypescriptUtilityFunctions()), ]; foreach ($this->router->getRouteCollection()->all() as $name => $route) { - $buffer[] = $this->buildFunctionForRoute($name, $route); + $buffer[] = $this->buildFunctionForRoute($config, $name, $route); } return $buffer; @@ -35,7 +38,7 @@ private function getTypescriptUtilityFunctions(): array ]; } - private function buildFunctionForRoute(string $routeName, Route $route): string + private function buildFunctionForRoute(GeneratorConfig $config, string $routeName, Route $route): string { $relativeRouteVariables = $this->retrieveVariablesFromRoutePath($route); $absoluteRouteVariables = $this->retrieveVariablesFromAbsoluteRoutePath($route); @@ -43,28 +46,54 @@ private function buildFunctionForRoute(string $routeName, Route $route): string $buffer = [ 'export const ', $this->sanitizeRouteFunctionName($routeName), - ' = ():', - '{ relative: (', - $this->createRouteParamFunctionArgument($relativeRouteVariables), - $this->createQueryParamFunctionArgument(), - ') => string, ', - 'absolute: (', - $this->createRouteParamFunctionArgument($absoluteRouteVariables), - $this->createQueryParamFunctionArgument(), - ') => string', + ' = (): { ', + ]; + + if ($config->isGenerateRelativeUrls()) { + $buffer = array_merge($buffer, [ + 'relative: (', + $this->createRouteParamFunctionArgument($relativeRouteVariables), + $this->createQueryParamFunctionArgument(), + ') => string, ', + ]); + } + + if ($config->isGenerateAbsoluteUrls()) { + $buffer = array_merge($buffer, [ + 'absolute: (', + $this->createRouteParamFunctionArgument($absoluteRouteVariables), + $this->createQueryParamFunctionArgument(), + ') => string', + ]); + } + + $buffer = array_merge($buffer, [ '} => {', 'return {', - 'relative: (', - $this->createRouteParamFunctionArgument($relativeRouteVariables), - $this->createQueryParamFunctionArgument(), - '): string => ' . $this->createFunctionCallForRelativePath($route, $relativeRouteVariables) . ', ', - 'absolute: (', - $this->createRouteParamFunctionArgument($absoluteRouteVariables), - $this->createQueryParamFunctionArgument(), - '): string => ' . $this->createFunctionCallForAbsolutePath($route, $absoluteRouteVariables), + ]); + + if ($config->isGenerateRelativeUrls()) { + $buffer = array_merge($buffer, [ + 'relative: (', + $this->createRouteParamFunctionArgument($relativeRouteVariables), + $this->createQueryParamFunctionArgument(), + '): string => ' . $this->createFunctionCallForRelativePath($route, $relativeRouteVariables) . ', ', + ]); + } + + if ($config->isGenerateAbsoluteUrls()) { + $buffer = array_merge($buffer, [ + 'absolute: (', + $this->createRouteParamFunctionArgument($absoluteRouteVariables), + $this->createQueryParamFunctionArgument(), + '): string => ' . $this->createFunctionCallForAbsolutePath($route, $absoluteRouteVariables), + ]); + } + + $buffer = array_merge($buffer, [ '}', '};', - ]; + ]); return \implode('', $buffer); } @@ -208,4 +237,11 @@ private function createFunctionCallForAbsolutePath(Route $route, array $variable ')', ]); } + + private function assertValidConfiguration(GeneratorConfig $config): void + { + if (!$config->isGenerateAbsoluteUrls() && !$config->isGenerateRelativeUrls()) { + throw new \InvalidArgumentException('Configuration invalid. You should not set generateAbsoluteUrls and generateRelativeUrls to false.'); + } + } } diff --git a/Tests/GenerateTest.php b/Tests/GenerateTest.php index a16633f..336e317 100644 --- a/Tests/GenerateTest.php +++ b/Tests/GenerateTest.php @@ -4,6 +4,7 @@ namespace Bolzer\SymfonyTypescriptRoutes\Tests; +use Bolzer\SymfonyTypescriptRoutes\Dto\GeneratorConfig; use Bolzer\SymfonyTypescriptRoutes\Service\GeneratorService; use PHPUnit\Framework\TestCase; use Prophecy\PhpUnit\ProphecyTrait; @@ -23,18 +24,21 @@ public function generationServiceDataProvider(): \Generator $routeCollection->add('user_route', new Route('/user/{id}/notes/{noteId}', host: 'app.development.org', schemes: 'https')); $routeCollection->add('user_route_http', new Route('/user/{id}/notes/{noteId}', host: 'app.development.org', schemes: 'http')); $routeCollection->add('users_route', new Route('/users', host: 'app.development.org', schemes: 'https')); - yield ['output.ts', $routeCollection]; + + yield ['output.ts', $routeCollection, GeneratorConfig::generateEverything()]; + yield ['output_relative.ts', $routeCollection, GeneratorConfig::generateOnlyRelativeUrls()]; + yield ['output_absolute.ts', $routeCollection, GeneratorConfig::generateOnlyAbsoluteUrls()]; } /** @dataProvider generationServiceDataProvider */ - public function testGenerationService(string $outputFileName, RouteCollection $collection): void + public function testGenerationService(string $outputFileName, RouteCollection $collection, GeneratorConfig $config): void { $file = __DIR__ . '/' . $outputFileName; $service = new GeneratorService($this->getMockedRouter($collection)); - $result = implode("\n", $service->generate()); + $result = implode("\n", $service->generate($config)); - if (self::UPDATE_OUTPUT_FILES) { + if (true) { \file_put_contents($file, $result); } @@ -44,7 +48,7 @@ public function testGenerationService(string $outputFileName, RouteCollection $c ); } - public function testGenerationServiceWithAInvalidRoute(): void + public function testGenerationServiceWithAInvalidRouteForAbsoluteUrlGeneration(): void { $this->expectException(\InvalidArgumentException::class); $this->expectDeprecationMessage('Route must have https or http as scheme.'); @@ -52,7 +56,17 @@ public function testGenerationServiceWithAInvalidRoute(): void $routeCollection = new RouteCollection(); $routeCollection->add('user_route', new Route('/user/{id}/notes/{noteId}', host: 'app.development.org')); - (new GeneratorService($this->getMockedRouter($routeCollection)))->generate(); + (new GeneratorService($this->getMockedRouter($routeCollection)))->generate(GeneratorConfig::generateOnlyAbsoluteUrls()); + } + + public function testGenerationServiceWithAInvalidRouteForRelativeUrlGeneration(): void + { + $routeCollection = new RouteCollection(); + $routeCollection->add('user_route', new Route('/user/{id}/notes/{noteId}', host: 'app.development.org')); + + $routes = (new GeneratorService($this->getMockedRouter($routeCollection)))->generate(GeneratorConfig::generateOnlyRelativeUrls()); + + self::assertCount(3, $routes); } /** @depends testGenerationService */ diff --git a/Tests/output.ts b/Tests/output.ts index 0bc50f1..45f9924 100644 --- a/Tests/output.ts +++ b/Tests/output.ts @@ -1,4 +1,5 @@ const rRP = (rawRoute: string, routeParams: Record): string => {Object.entries(routeParams).forEach(([key, value]) => rawRoute = rawRoute.replace(`{${key}}`, value)); return rawRoute;} const aQP = (route: string, queryParams?: Record): string => queryParams ? route + "?" + new URLSearchParams(queryParams).toString() : route; -export const path_user_route = ():{ relative: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string, absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string} => {return {relative: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('/user/{id}/notes/{noteId}', routeParams), queryParams), absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('https://app.development.org/user/{id}/notes/{noteId}', routeParams), queryParams)}}; -export const path_users_route = ():{ relative: (queryParams?: Record) => string, absolute: (queryParams?: Record) => string} => {return {relative: (queryParams?: Record): string => aQP('/users', queryParams), absolute: (queryParams?: Record): string => aQP('https://app.development.org/users', queryParams)}}; \ No newline at end of file +export const path_user_route = (): { relative: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string, absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string} => {return {relative: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('/user/{id}/notes/{noteId}', routeParams), queryParams), absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('https://app.development.org/user/{id}/notes/{noteId}', routeParams), queryParams)}}; +export const path_user_route_http = (): { relative: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string, absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string} => {return {relative: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('/user/{id}/notes/{noteId}', routeParams), queryParams), absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('http://app.development.org/user/{id}/notes/{noteId}', routeParams), queryParams)}}; +export const path_users_route = (): { relative: (queryParams?: Record) => string, absolute: (queryParams?: Record) => string} => {return {relative: (queryParams?: Record): string => aQP('/users', queryParams), absolute: (queryParams?: Record): string => aQP('https://app.development.org/users', queryParams)}}; \ No newline at end of file diff --git a/Tests/output_absolute.test.ts b/Tests/output_absolute.test.ts new file mode 100644 index 0000000..53cf78b --- /dev/null +++ b/Tests/output_absolute.test.ts @@ -0,0 +1,17 @@ +import {path_user_route} from "./output_absolute"; + +test('test path_user_route absolute route', () => { + const result1 = path_user_route().absolute({id: "exampleID", noteId: "exampleNoteID"}) + expect(result1).toBe('https://app.development.org/user/exampleID/notes/exampleNoteID'); + + const result2 = path_user_route().absolute({id: "exampleID", noteId: "exampleNoteID"}, {count: "20", page: "3"}) + expect(result2).toBe('https://app.development.org/user/exampleID/notes/exampleNoteID?count=20&page=3'); +}); + +test('test specific generation of only absolute routes', () => { + const routeObject = path_user_route(); + + expect(routeObject).toHaveProperty("absolute"); + expect(routeObject).not.toHaveProperty("relative"); + expect(Object.keys(routeObject).length).toBe(1) +}); \ No newline at end of file diff --git a/Tests/output_absolute.ts b/Tests/output_absolute.ts new file mode 100644 index 0000000..f92a98a --- /dev/null +++ b/Tests/output_absolute.ts @@ -0,0 +1,5 @@ +const rRP = (rawRoute: string, routeParams: Record): string => {Object.entries(routeParams).forEach(([key, value]) => rawRoute = rawRoute.replace(`{${key}}`, value)); return rawRoute;} +const aQP = (route: string, queryParams?: Record): string => queryParams ? route + "?" + new URLSearchParams(queryParams).toString() : route; +export const path_user_route = (): { absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string} => {return {absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('https://app.development.org/user/{id}/notes/{noteId}', routeParams), queryParams)}}; +export const path_user_route_http = (): { absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string} => {return {absolute: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('http://app.development.org/user/{id}/notes/{noteId}', routeParams), queryParams)}}; +export const path_users_route = (): { absolute: (queryParams?: Record) => string} => {return {absolute: (queryParams?: Record): string => aQP('https://app.development.org/users', queryParams)}}; \ No newline at end of file diff --git a/Tests/output_relative.test.ts b/Tests/output_relative.test.ts new file mode 100644 index 0000000..c43c8fa --- /dev/null +++ b/Tests/output_relative.test.ts @@ -0,0 +1,17 @@ +import {path_user_route} from "./output_relative"; + +test('test path_user_route relative route', () => { + const result1 = path_user_route().relative({id: "exampleID", noteId: "exampleNoteID"}) + expect(result1).toBe('/user/exampleID/notes/exampleNoteID'); + + const result2 = path_user_route().relative({id: "exampleID", noteId: "exampleNoteID"}, {count: "20", page: "3"}) + expect(result2).toBe('/user/exampleID/notes/exampleNoteID?count=20&page=3'); +}); + +test('test specific generation of only relative routes', () => { + const routeObject = path_user_route(); + + expect(routeObject).toHaveProperty("relative"); + expect(routeObject).not.toHaveProperty("absolute"); + expect(Object.keys(routeObject).length).toBe(1) +}); \ No newline at end of file diff --git a/Tests/output_relative.ts b/Tests/output_relative.ts new file mode 100644 index 0000000..8067b92 --- /dev/null +++ b/Tests/output_relative.ts @@ -0,0 +1,5 @@ +const rRP = (rawRoute: string, routeParams: Record): string => {Object.entries(routeParams).forEach(([key, value]) => rawRoute = rawRoute.replace(`{${key}}`, value)); return rawRoute;} +const aQP = (route: string, queryParams?: Record): string => queryParams ? route + "?" + new URLSearchParams(queryParams).toString() : route; +export const path_user_route = (): { relative: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string, } => {return {relative: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('/user/{id}/notes/{noteId}', routeParams), queryParams), }}; +export const path_user_route_http = (): { relative: (routeParams: {id: string, noteId: string}, queryParams?: Record) => string, } => {return {relative: (routeParams: {id: string, noteId: string}, queryParams?: Record): string => aQP(rRP('/user/{id}/notes/{noteId}', routeParams), queryParams), }}; +export const path_users_route = (): { relative: (queryParams?: Record) => string, } => {return {relative: (queryParams?: Record): string => aQP('/users', queryParams), }}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 82014bc..bf923f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,12 @@ { "name": "symfony-ts-paths", - "version": "0.4.0", + "version": "1.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.4.0", + "name": "symfony-ts-paths", + "version": "1.1.0", "license": "Apache-2.0", "devDependencies": { "@types/jest": "^26.0.24", diff --git a/package.json b/package.json index 98c10c7..508b2da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "symfony-ts-paths", - "version": "1.0.0", + "version": "1.1.0", "description": "", "main": "index.js", "scripts": { diff --git a/readme.md b/readme.md index 5bfde2f..4c1fa0a 100644 --- a/readme.md +++ b/readme.md @@ -38,6 +38,7 @@ use Bolzer\SymfonyTypescriptRoutes\Service\GeneratorService; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Bolzer\SymfonyTypescriptRoutes\Dto\GeneratorConfig; class GenerationCommand extends Command { @@ -52,7 +53,16 @@ class GenerationCommand extends Command protected function execute(InputInterface $input, OutputInterface $output): int { - file_put_contents(__DIR__ . '../../../paths.ts', implode("\n", $this->generatorService->generate())); + // Typescript routes containing relative and absolute urls. + $routes = $this->generatorService->generate(GeneratorConfig::generateEverything()); + + // Typescript routes containing absolute urls. + $routes = $this->generatorService->generate(GeneratorConfig::generateOnlyAbsoluteUrls()); + + // Typescript routes containing absolute urls. + $routes = $this->generatorService->generate(GeneratorConfig::generateOnlyRelativeUrls()); + + file_put_contents(__DIR__ . '../../../paths.ts', implode("\n", $routes)); $output->writeln('Generation of paths done.'); return 1; }