Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"stylelint": "./node_modules/.bin/stylelint 'src/**/*.scss' '!**/assets/**' --config stylelint.config.js --syntax scss",
"webdriver-update": "bash ./node_modules/.bin/webdriver-manager update",
"test": "ng test ui-platform --code-coverage --source-map=false --watch=false",
"test:schematics": "tsc -p src/lib/schematics/tsconfig.spec.json && jasmine src/lib/schematics/**/*.spec.js",
"coveralls": "cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js",
"build:lib": "bash scripts/build-release && gulp version-placeholder",
"release:start": "bash scripts/start-release",
Expand Down
21 changes: 21 additions & 0 deletions scripts/test-schematics.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Run test and linter
npm run test:schematics
npm run tslint

# Link project
cd ../src/lib
npm link

# Create Angular base project
cd /tmp
rm -rf testxyz
ng new testxyz

# Run covalent schematics
cd testxyz
npm link @td-vantage/ui-platform
ng g @td-vantage/ui-platform:ng-add

# Check generated files
git status
npm i
1 change: 1 addition & 0 deletions src/lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"license": "MIT",
"author": "Teradata UI Team",
"schematics": "./schematics/collection.json",
"peerDependencies": {
"@angular/common": "^0.0.0-NG",
"@angular/core": "^0.0.0-NG",
Expand Down
4 changes: 4 additions & 0 deletions src/lib/schematics/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Outputs
**/*.js
**/*.js.map
**/*.d.ts
11 changes: 11 additions & 0 deletions src/lib/schematics/collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"ng-add": {
"description": "Adds vantage ui platform to the application without affecting any templates",
"factory": "./ng-add/index#addDependenciesAndFiles",
"schema": "./ng-add/schema.json",
"aliases": ["vantage-shell", "install"]
}
}
}
26 changes: 26 additions & 0 deletions src/lib/schematics/ng-add/files/proxy.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const vantageLoginProxyConfig = require('./src/lib/auth/config/vantageLoginProxyConfig');

/* * * * * * * * * * * */
/* Edit these variables to point to your */
/* Vantage and local development environments */
/* * * * * * * * * * * */

const serverUrl = 'https://vantage.url.io'; // REPLACE WITH VANTAGE BASE URL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be interpolated with the ssoServerURL options?

Suggested change
const serverUrl = 'https://vantage.url.io'; // REPLACE WITH VANTAGE BASE URL
const serverUrl = '<%= ssoServerURL %>'; // VANTAGE BASE URL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if the quotes would be needed

const localUrl = "localhost:4200";
const localProto = "http"; // http or https

/* * * * * * * * * * * */
/* This section contains the routes proxied through */
/* your local development environment and the Vantage deployment */
/* * * * * * * * * * * */

const PROXY_CONFIG = {
...vantageLoginProxyConfig({ serverUrl, localUrl, localProto }),
'/api': {
target: serverUrl,
secure: false,
changeOrigin: true,
},
};

module.exports = PROXY_CONFIG;
18 changes: 18 additions & 0 deletions src/lib/schematics/ng-add/files/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Routes, RouterModule } from '@angular/router';

import { VantageAuthenticationGuard } from '@td-vantage/ui-platform/auth';

const routes: Routes = [
{
path: '',
canActivate: [VantageAuthenticationGuard],
children: [],
},
{ path: '**', redirectTo: '/' },
];

export const appRoutingProviders: any[] = [
VantageAuthenticationGuard,
];

export const appRoutes: any = RouterModule.forRoot(routes);
84 changes: 84 additions & 0 deletions src/lib/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { getFileContent } from '@schematics/angular/utility/test';
import { Tree } from '@angular-devkit/schematics';
import { uiPlatformVersion } from '../version-names';
import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
import { Schema as WorkspaceOptions } from '@schematics/angular/workspace/schema';
import { Schema as ApplicationOptions } from '@schematics/angular/application/schema';

const collectionPath: string = require.resolve('../collection.json');

describe('ng-add schematic', () => {
const testRunner: SchematicTestRunner = new SchematicTestRunner('rocket', collectionPath);

const workspaceOptions: WorkspaceOptions = {
name: 'workspace',
newProjectRoot: 'projects',
version: '1.0.0',
};

const appOptions: ApplicationOptions = {
name: 'ui-platform-workspace',
};

let appTree: UnitTestTree;

beforeEach(async () => {
const workspaceTree: UnitTestTree = await testRunner
.runExternalSchematicAsync('@schematics/angular', 'workspace', workspaceOptions)
.toPromise();
appTree = await testRunner
.runExternalSchematicAsync('@schematics/angular', 'application', appOptions, workspaceTree)
.toPromise();
});

it('should update package.json', async () => {
const tree: Tree = await testRunner.runSchematicAsync('ng-add', undefined, appTree).toPromise();
const packageJson: any = JSON.parse(getFileContent(tree, '/package.json'));
const dependencies: any = packageJson.dependencies;

const expectedUIPlatformVersion: string = `${uiPlatformVersion}`;

expectVersionToBe(dependencies, '@td-vantage/ui-platform', expectedUIPlatformVersion);
});

it('should create proxy.conf.js when sso option is selected by user', async () => {
const dependencyOptions: any = { ssoServerURL: 'https://vantage.url.io' };
const tree: Tree = await testRunner.runSchematicAsync('ng-add', dependencyOptions, appTree).toPromise();
expect(tree.exists('proxy.conf.js')).toBe(true);
const fileContent: string = getFileContent(tree, 'proxy.conf.js');
expect(fileContent).toContain('https://vantage.url.io');
});

it('should import Vantage Auth modules to app.module.ts when sso option is selected by user', async () => {
const dependencyOptions: any = { ssoServerURL: 'https://vantage.url.io' };
const tree: Tree = await testRunner.runSchematicAsync('ng-add', dependencyOptions, appTree).toPromise();
const fileContent: string = getFileContent(tree, 'projects/ui-platform-workspace/src/app/app.module.ts');
expect(fileContent).toContain('VantageAuthenticationModule');
expect(fileContent).toContain('VantageAuthenticationInterceptor');
expect(fileContent).toContain('VantageUserModule');
expect(fileContent).toContain('CovalentHttpModule');
});

it('should create app.routes.ts when sso option is selected by user', async () => {
const dependencyOptions: any = { ssoServerURL: 'https://vantage.url.io' };
const tree: Tree = await testRunner.runSchematicAsync('ng-add', dependencyOptions, appTree).toPromise();
expect(tree.exists('src/app/app.routes.ts')).toBe(true);
const fileContent: string = getFileContent(tree, 'src/app/app.routes.ts');
expect(fileContent).toContain('VantageAuthenticationGuard');
});

it('should import route provider to app.module.ts when sso option is selected by user', async () => {
const dependencyOptions: any = { ssoServerURL: 'https://vantage.url.io' };
const tree: Tree = await testRunner.runSchematicAsync('ng-add', dependencyOptions, appTree).toPromise();
const fileContent: string = getFileContent(tree, 'projects/ui-platform-workspace/src/app/app.module.ts');
expect(fileContent).toContain('appRoutes');
expect(fileContent).toContain('appRoutingProviders');
});

function expectVersionToBe(dependencies: any, name: string, expectedVersion: string): void {
expect(dependencies[name]).toBe(
expectedVersion,
'Expected ' + name + ' package to have ' + `${expectedVersion}` + ' version.',
);
}
});
87 changes: 87 additions & 0 deletions src/lib/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Rule, chain, Tree, mergeWith, url, apply, branchAndMerge, SchematicsException, template, UpdateRecorder } from '@angular-devkit/schematics';
import { addPackageToPackageJson } from '@angular/material/schematics/ng-add/package-config';
import { uiPlatformVersion } from '../version-names';
import { ISchema } from './schema';
import { strings } from '@angular-devkit/core';

import { getProjectFromWorkspace, addModuleImportToRootModule } from '@angular/cdk/schematics';
import { addProviderToModule } from '@schematics/angular/utility/ast-utils';
import { InsertChange } from '@schematics/angular/utility/change';
import { getAppModulePath } from '@schematics/angular/utility/ng-ast-utils';
import { getWorkspace } from '@schematics/angular/utility/config';
import { experimental } from '@angular-devkit/core';
import { getSourceFile, getProjectMainFile } from '@angular/cdk/schematics/utils';
import { SourceFile } from 'typescript';
import { Change } from '@schematics/angular/utility/change';

export function addDependenciesAndFiles(options: ISchema): Rule {
let addVantagePacakgeRule: Rule = (host: Tree) => {
addPackageToPackageJson(host, '@td-vantage/ui-platform', `${uiPlatformVersion}`);
};

let ruleSet: Rule[] = [addVantagePacakgeRule];

if (options.ssoServerURL && options.ssoServerURL.trim().length) { // enable SSO
ruleSet.push(mergeFiles(options));
ruleSet.push(addSSOImports);
}
return chain(ruleSet);
}

function mergeFiles(options: ISchema): Rule {
const templateSource: any = apply(url('./files'), [
template({
...strings,
...options,
}),
]);
return branchAndMerge(mergeWith(templateSource));
}

function addSSOImports(): Rule {
return (host: Tree) => {
const workspace: experimental.workspace.WorkspaceSchema = getWorkspace(host);
const project: experimental.workspace.WorkspaceProject = getProjectFromWorkspace(workspace);
const replacementString: string = `CovalentHttpModule.forRoot({
interceptors: [{
interceptor: VantageAuthenticationInterceptor, paths: ['**'],
}],
})`;

addModuleImportToRootModule(host, 'VantageAuthenticationModule', '@td-vantage/ui-platform/auth', project);
addModuleImportToRootModule(host, 'VantageUserModule', '@td-vantage/ui-platform/user', project);
addModuleImportToRootModule(host, `CovalentHttpModule.forRoot()`, '@covalent/http', project);
replaceContentInAppModule(host, `CovalentHttpModule.forRoot()`, replacementString);
addModuleImportToRootModule(host, 'appRoutes', './app.routes', project);

addProvider(host, `VantageAuthenticationInterceptor`, '@td-vantage/ui-platform/auth');
addProvider(host, `appRoutingProviders`, './app.routes');
};
}

function addProvider(host: Tree, classifiedName: string, importPath: string): void {
const workspace: experimental.workspace.WorkspaceSchema = getWorkspace(host);
const project: experimental.workspace.WorkspaceProject = getProjectFromWorkspace(workspace);
const modulePath: string = getAppModulePath(host, getProjectMainFile(project));
const moduleSource: SourceFile = getSourceFile(host, modulePath);
const changes: Change[] = addProviderToModule(moduleSource, modulePath, classifiedName, importPath);
applyChanges(host, modulePath, changes);
}

function applyChanges(tree: Tree, path: string, changes: Change[]): void {
const recorder: UpdateRecorder = tree.beginUpdate(path);
for (const change of changes) {
if (change instanceof InsertChange) {
recorder.insertLeft(change.pos, change.toAdd);
}
}
tree.commitUpdate(recorder);
}

function replaceContentInAppModule(host: Tree, match: string, replacement: string): void {
const workspace: experimental.workspace.WorkspaceSchema = getWorkspace(host);
const project: experimental.workspace.WorkspaceProject = getProjectFromWorkspace(workspace);
const modulePath: string = getAppModulePath(host, getProjectMainFile(project));
const content: string = host.get(modulePath).content.toString();
host.overwrite(modulePath, content.replace(match, replacement));
}
14 changes: 14 additions & 0 deletions src/lib/schematics/ng-add/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "http://json-schema.org/schema",
"id": "vantage-ui-platform-ng-add",
"title": "Vantage UI Platform ng-add schematic",
"type": "object",
"properties": {
"ssoServerURL": {
"type": "string",
"description": "Add SSO if user provides SSO server URL",
"x-prompt": "Add SSO server url to setup SSO or press enter to skip"
}
},
"required": []
}
5 changes: 5 additions & 0 deletions src/lib/schematics/ng-add/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface ISchema {
/** Whether SSO should be set up. */
ssoServerURL: string;

}
24 changes: 24 additions & 0 deletions src/lib/schematics/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": "./",
"baseUrl": "./",
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"outDir": "../../../../deploy/ui-platform/schematics",
"lib": ["es2017", "dom"],
"moduleResolution": "node",
"sourceMap": true,
"target": "es5",
"typeRoots": ["./../../../../node_modules/@types"],
"noUnusedParameters": false,
"noUnusedLocals": false,
"allowUnreachableCode": false,
"pretty": true,
"importHelpers": true
},
"include": ["**/*"],
"exclude": ["**/*.spec.ts", "**/files/**/*"]
}

13 changes: 13 additions & 0 deletions src/lib/schematics/tsconfig.spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"outDir": "./",
"lib": ["es6", "dom"],
"module": "commonjs",
"types": ["jasmine", "hammerjs", "node"]
},
"include": ["**/*", "**/*.spec.ts"],
"exclude": ["*/files/**/*", "*/files/**/**/*"]
}

1 change: 1 addition & 0 deletions src/lib/schematics/version-names.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const uiPlatformVersion: string = '1.0.0-beta.0';
2 changes: 1 addition & 1 deletion src/lib/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Then we find all the tests.
const context: any = require.context('./', true, /\.spec\.ts$/);
const context: any = require.context('./', true, /^(?!.*(\/schematics\/)).*\.spec\.ts$/);
// And load the modules.
context.keys().map(context);