From e7f0dd8f2b3c0fe3286ff950ee243727659ff45b Mon Sep 17 00:00:00 2001 From: Brandon Stirnaman Date: Sat, 3 Jun 2017 18:44:31 -0500 Subject: [PATCH] Add support for named export guards --- lib/sky-pages-route-generator.js | 32 ++++++++++++++++-- test/sky-pages-route-generator.spec.js | 47 +++++++++++++++++++++++--- 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/lib/sky-pages-route-generator.js b/lib/sky-pages-route-generator.js index d0ebdb04..46b59682 100644 --- a/lib/sky-pages-route-generator.js +++ b/lib/sky-pages-route-generator.js @@ -59,6 +59,13 @@ function parseFileIntoEntity(skyAppConfig, file, index) { // Make no assumptions on extension used to create route, just remove // it and append .guard.ts (ex: index.html -> index.guard.ts) let guardPath = path.join(parsedPath.dir, `${parsedPath.name}.guard.ts`); + let guardName; + + if (fs.existsSync(guardPath)) { + guardName = extractGuardName(guardPath); + } else { + guardPath = undefined; + } // Removes srcPath + filename // glob always uses '/' for path separator! @@ -92,7 +99,8 @@ function parseFileIntoEntity(skyAppConfig, file, index) { componentDefinition: componentDefinition, routePath: routePath.join('/'), routeParams: routeParams, - guardPath: fs.existsSync(guardPath) ? guardPath : undefined + guardPath: guardPath, + guardName: guardName }; } @@ -122,7 +130,7 @@ function generateDeclarations(routes) { const p = indent(1); const declarations = routes .map(r => { - let guard = r.guardPath ? `require('${r.guardPath}').default` : ''; + let guard = r.guardPath && r.guardName ? `require('${r.guardPath}').${r.guardName}` : ''; let declaration = `${p}{ path: '${r.routePath}', @@ -139,7 +147,7 @@ function generateDeclarations(routes) { function generateProviders(routes) { const providers = routes - .map(r => r.guardPath ? `require('${r.guardPath}').default` : undefined) + .map(r => r.guardPath ? `require('${r.guardPath}').${r.guardName}` : undefined) .filter(p => p); return `[\n${providers}\n]`; @@ -169,6 +177,24 @@ function getRoutes(skyAppConfig) { }; } +function extractGuardName(file) { + const matchRegexp = /@Injectable\s*\(\s*\)\s*export\s*(default)*\s*class\s(\w+)/g; + const content = fs.readFileSync(file, { encoding: 'utf8' }); + + let result; + let match; + while ((match = matchRegexp.exec(content))) { + if (result !== undefined) { + throw new Error(`As a best practice, only export one guard per file in ${file}`); + } + + // If its a default export, use that value instead of guard component name + result = match[1] || match[2]; + } + + return result; +} + module.exports = { getRoutes: getRoutes }; diff --git a/test/sky-pages-route-generator.spec.js b/test/sky-pages-route-generator.spec.js index c16e4303..04cd07cb 100644 --- a/test/sky-pages-route-generator.spec.js +++ b/test/sky-pages-route-generator.spec.js @@ -105,11 +105,33 @@ describe('SKY UX Builder route generator', () => { }); it('should support guards with custom routesPattern', () => { - let suppliedPattern; - spyOn(glob, 'sync').and.callFake((p) => { - suppliedPattern = p; - return ['my-custom-src/my-custom-route/index.html']; + spyOn(glob, 'sync').and.callFake(() => ['my-custom-src/my-custom-route/index.html']); + spyOn(fs, 'readFileSync').and.returnValue('@Injectable() export class Guard {}'); + spyOn(fs, 'existsSync').and.returnValue(true); + + let routes = generator.getRoutes({ + runtime: { + srcPath: 'my-custom-src/', + routesPattern: 'my-custom-pattern', + } }); + + expect(routes.declarations).toContain( + `canActivate: [require(\'my-custom-src/my-custom-route/index.guard.ts\').Guard]` + ); + + expect(routes.declarations).toContain( + `canDeactivate: [require(\'my-custom-src/my-custom-route/index.guard.ts\').Guard]` + ); + + expect(routes.providers).toContain( + `require(\'my-custom-src/my-custom-route/index.guard.ts\').Guard` + ); + }); + + it('should support default export guards', () => { + spyOn(glob, 'sync').and.callFake(() => ['my-custom-src/my-custom-route/index.html']); + spyOn(fs, 'readFileSync').and.returnValue('@Injectable() export default class Guard {}'); spyOn(fs, 'existsSync').and.returnValue(true); let routes = generator.getRoutes({ @@ -131,4 +153,21 @@ describe('SKY UX Builder route generator', () => { `require(\'my-custom-src/my-custom-route/index.guard.ts\').default` ); }); + + it('should throw when a file has multiple guards', () => { + spyOn(glob, 'sync').and.callFake(() => ['my-custom-src/my-custom-route/index.html']); + spyOn(fs, 'existsSync').and.returnValue(true); + spyOn(fs, 'readFileSync').and.returnValue(` + @Injectable() export default class Guard {} + @Injectable() export class Guard2 {} + `); + + let file = 'my-custom-src/my-custom-route/index.guard.ts'; + expect(() => generator.getRoutes({ + runtime: { + srcPath: 'my-custom-src/', + routesPattern: 'my-custom-pattern', + } + })).toThrow(new Error(`As a best practice, only export one guard per file in ${file}`)); + }); });