UNPKG

@tibco-tcstk/component-template

Version:

TIBCO Cloud Composer Component to create Schematics in your TIBCO Cloud Application

530 lines (498 loc) 22.7 kB
import { apply, chain, mergeWith, Rule, SchematicContext, SchematicsException, template, Tree, url } from "@angular-devkit/schematics"; import { getWorkspace, getProjectFromWorkspace, findModuleFromOptions, parseName, addEntryComponentToModule, buildRelativePath, InsertChange, ModuleOptions, addDeclarationToModule, addExportToModule, getSourceFile, addPackageJsonDependency, NodeDependency, addImportToModule, NodeDependencyType } from "schematics-utilities"; import {strings} from "@angular-devkit/core"; import {classify, dasherize} from "@angular-devkit/core/src/utils/strings"; // import {typescript} from "schematics-utilities/dist/cdk"; // import {addDeclarationToModule, addExportToModule} from "../schematics-angular-utils/ast-utils"; const stringUtils = {dasherize, classify}; export class AddToModuleContext { source: any; relativePath: string; classifiedName: string; } export interface MyModuleOptions extends ModuleOptions { module?: string; name: string; flat?: boolean; path?: string; skipImport?: boolean; formRegistry?: string; type?: string; formRef?: string; doAddRoutes?: boolean; doAddConfig?: boolean; doAddMapping?: boolean; } export function showHead(type: string, context: SchematicContext, options: any) { // Show the options for this Schematics. context.logger.info('-----------------------------------------------'); context.logger.info('--- ** TIBCO CLOUD COMPONENT GENERATOR ** ---'); context.logger.info('--- ** V3.3.0 ** ---'); context.logger.info('-----------------------------------------------'); context.logger.info('--- ** TYPE: ' + type.toUpperCase()); context.logger.info('-----------------------------------------------'); context.logger.info('Building TIBCO Cloud Component, with the following settings: ' + JSON.stringify(options)); } export function addDependencies(options: any, context: SchematicContext, host: Tree) { context.logger.log('info', "Name: " + options.name); context.logger.info('Adding dependencies...'); const workspace = getWorkspace(host); const project = getProjectFromWorkspace( workspace, // Takes the first project in case it's not provided by CLI options.project ? options.project : Object.keys(workspace['projects'])[0] ); const moduleName = options.name + 'Component'; const sourceLoc = './' + options.name + '/' + options.name + '.component'; context.logger.info('moduleName: ' + moduleName); context.logger.info('sourceLoc: ' + sourceLoc); context.logger.info('Project Root: ' + project.root); if (!options.project) { options.project = Object.keys(workspace.projects)[0]; } if (options.path === undefined) { const projectDirName = project.projectType === 'application' ? 'app' : 'lib'; options.path = `/${project.root}/src/${projectDirName}`; } options.module = findModuleFromOptions(host, options); const moduleNameNew = options.name; const parsedPath = parseName(options.path, moduleNameNew); options.name = parsedPath.name; context.logger.info('options.name: ' + options.name); options.path = parsedPath.path; context.logger.info('options.path: ' + options.path); options.export = false; context.logger.info('Installed Dependencies...'); return options; } // Function for form export function formChain(options: any, type: string) { return chain([ (_tree: Tree, context: SchematicContext) => { showHead('CUSTOM FORM: ' + type, context, options); }, // Adding dependencies (host: Tree, context: SchematicContext) => { context.logger.log('info', "Name: " + options.name); context.logger.info('Adding dependencies...'); const workspace = getWorkspace(host); const project = getProjectFromWorkspace( workspace, // Takes the first project in case it's not provided by CLI options.project ? options.project : Object.keys(workspace['projects'])[0] ); // updateFormRegistry(project, host, context); const moduleName = options.name + 'Component'; const sourceLoc = './custom-forms/' + options.name + '/' + options.name + '.component'; context.logger.info('moduleName: ' + moduleName); context.logger.info('sourceLoc: ' + sourceLoc); context.logger.info('Project Root: ' + project.root); if (!options.project) { options.project = Object.keys(workspace.projects)[0]; } if (options.path === undefined) { const projectDirName = project.projectType === 'application' ? 'app' : 'lib'; options.path = `/${project.root}/src/${projectDirName}`; } options.module = findModuleFromOptions(host, options); const moduleNameNew = options.name + '-' + type + '-form'; const parsedPath = parseName(options.path + '/custom-forms/', moduleNameNew); console.log('parsedPath: ', parsedPath); options.name = parsedPath.name; context.logger.info('options.name: ' + options.name); options.path = parsedPath.path; context.logger.info('options.path: ' + options.path); options.export = false; // context.logger.info('Adding declaration: ' + options.export); options.type = type; console.warn('Options: ', options); }, //Apply Template mergeWith(apply(url('./files'), [ template({ ...strings, INDEX: options.index, name: options.name, }), ])), addDeclarationToNgModule(options, false), addEntryPointToNgModule(options), () => { options.module = options.module.replace('.ts', '.dev'); // console.warn('Options (DEV): ',options); }, addDeclarationToNgModule(options, false), addEntryPointToNgModule(options), () => { options.module = options.module.replace('.dev', '.build'); // console.warn('Options (BUILD): ',options); }, addDeclarationToNgModule(options, false), addEntryPointToNgModule(options), () => { options.formRegistry = '/src/app/form.registry.ts'; // console.warn('Options (Form Registry): ',options); }, updateFormRegistry(options) ]); } // Function to update the form registry export function updateFormRegistry(options: MyModuleOptions) { return (host: Tree) => { console.log('Updating form registry: ', options); if (options.formRegistry && options.formRef && options.type && options.name) { var fRegBuffer = host.read(options.formRegistry); if (fRegBuffer) { var content = fRegBuffer.toString(); // console.warn('Form Registry: ', content); console.log('--- Updating Form Registry ---') const recorder = host.beginUpdate(options.formRegistry); console.log('- ID: ' + options.formRef); console.log('- TYPE: ' + options.type); console.log('- NAME: ' + options.name); const toInsert = "\n new FormRecord('" + options.formRef + "', '" + options.type + "', '" + options.name + "', '" + options.name + " " + options.type + " Form', " + classify(options.name) + "Component),"; console.log('- INSERTING: ' + toInsert); const searchString = 'FORM_REGISTRY = ['; recorder.insertRight(content.indexOf(searchString) + searchString.length, toInsert); // Add the import statement const importStatement = 'import {' + classify(options.name) + 'Component} from \'./custom-forms/' + dasherize(options.name) + '/' + dasherize(options.name) + '.component\';\n'; recorder.insertRight(0, importStatement); host.commitUpdate(recorder); } } return host; }; } // wrapper to create a rule export function addEntryPointToNgModule(options: ModuleOptions): Rule { return (host: Tree) => { addEntryPoint(host, options); return host; }; } // wrapper to create a rule export function addDeclarationToNgModule(options: ModuleOptions, exports: boolean): Rule { // console.log('addDeclarationToNgModule:' , options); return (host: Tree) => { addDeclaration(host, options); if (exports) { addExport(host, options); } return host; }; } // Function to add a declaration to a module function addDeclaration(host: Tree, options: ModuleOptions) { //console.log('Add Declaration', host); // console.log('Adding Declaration:' , options.module); const context = createAddToModuleContext(host, options); const modulePath = options.module || ''; //console.log('context.source:',context.source); //console.log('modulePath:',modulePath); //console.log('context.classifiedName:',context.classifiedName); //console.log('context.relativePath:',context.relativePath); const declarationChanges = addDeclarationToModule(context.source, modulePath, context.classifiedName, context.relativePath); // console.log('declarationChanges:',declarationChanges); const declarationRecorder = host.beginUpdate(modulePath); // console.log('mp: ',modulePath); for (const myChange of declarationChanges) { // FIXED FOR ANGULAR 10; ADDED A CAST TO InsertChange let newChange: InsertChange = <InsertChange>myChange; //if (myChange instanceof InsertChange) { declarationRecorder.insertLeft(newChange.pos, newChange.toAdd); //console.log('change.pos:',newChange.pos , ' change.toAdd:',newChange.toAdd); //} } // console.log('Commit Update: ' , declarationRecorder); host.commitUpdate(declarationRecorder); } // Function to add an export to a module function addExport(host: Tree, options: ModuleOptions) { const context = createAddToModuleContext(host, options); const modulePath = options.module || ''; const exportChanges = addExportToModule(context.source, modulePath, context.classifiedName, context.relativePath); const exportRecorder = host.beginUpdate(modulePath); for (const change of exportChanges) { // FIXED FOR ANGULAR 10; ADDED A CAST TO InsertChange let newChange: InsertChange = <InsertChange>change; //if (change instanceof InsertChange) { exportRecorder.insertLeft(newChange.pos, newChange.toAdd); //} } host.commitUpdate(exportRecorder); } // Function to add an Entry point to the module function addEntryPoint(host: Tree, options: MyModuleOptions) { const context = createAddToModuleContext(host, options); const modulePath = options.module || ''; console.log('Adding Entry Point: ', modulePath); // console.log('AE]context.source:',context.source); // console.log('AE]modulePath:',modulePath); // console.log('AE]context.classifiedName:',context.classifiedName); // console.log('AE]context.relativePath:',context.relativePath); const declarationChanges = addEntryComponentToModule(context.source, modulePath, context.classifiedName, context.relativePath); //console.log('declarationChanges:',declarationChanges); const declarationRecorder = host.beginUpdate(modulePath); // console.log('mp:',modulePath); for (const change of declarationChanges) { // FIXED FOR ANGULAR 10; ADDED A CAST TO InsertChange let newChange: InsertChange = <InsertChange>change; //if (change instanceof InsertChange) { declarationRecorder.insertLeft(newChange.pos, newChange.toAdd); // console.log('AE]change.pos:',change.pos , ' change.toAdd:',change.toAdd); //} } host.commitUpdate(declarationRecorder); } //Function to build up the AddToModule Context class function createAddToModuleContext(host: Tree, options: ModuleOptions): AddToModuleContext { console.log('Create Add to Module Context: ', options.module); const result = new AddToModuleContext(); console.log('options.module: ', options.module); if (!options.module) { throw new SchematicsException(`Module not found.`); } const text = host.read(options.module); if (text === null) { throw new SchematicsException(`File ${options.module} does not exist!`); } result.source = getSourceFile(host, options.module); const componentPath = `${options.path}/` + stringUtils.dasherize(options.name) + '/' + stringUtils.dasherize(options.name) + '.component'; result.relativePath = buildRelativePath(options.module, componentPath); result.classifiedName = stringUtils.classify(`${options.name}Component`); return result; } export function addPackageDependencies(host: Tree, dependencies: NodeDependency[]): Tree { //const dependencies: NodeDependency[] = [{ type: NodeDependencyType.Default, version: '4.17.10', name: 'lodash-es' }]; dependencies.forEach(dependency => addPackageJsonDependency(host, dependency)); return host; } // Function to import a library to node modules function addImport(host: Tree, options: ModuleOptions, lib: string, importPath: string) { if (!options.module) { throw new SchematicsException(`Module not found.`); } const modulePath = options.module || ''; console.log('Adding Import to Point: ', modulePath); console.log('Library to Import: ' + lib) console.log(' Import Path: ' + importPath); // @ts-ignore const importChanges = addImportToModule(getSourceFile(host, options.module), modulePath, lib, importPath); // TODO: Fix this to update to (schematics-utilities - 2.0.1) /* //const sourceFile:typescript.SourceFile = getSourceFile(host, options.module); const sourceFile:any = getSourceFile(host, options.module); console.log('ADDING SOURCE FILE: ' , sourceFile); const importChanges = addImportToModule(sourceFile, modulePath, lib, importPath ); console.log('DONE ADDING SOURCE FILE: ' , importChanges);*/ const declarationRecorder = host.beginUpdate(modulePath); for (const change of importChanges) { // FIXED FOR ANGULAR 10; ADDED A CAST TO InsertChange let newChange: InsertChange = <InsertChange>change; //if (change instanceof InsertChange) { declarationRecorder.insertLeft(newChange.pos, newChange.toAdd); //console.log('change.pos:',change.pos , ' change.toAdd:',change.toAdd); //} } host.commitUpdate(declarationRecorder); } export function addImportToNgModule(options: ModuleOptions, lib: string, importPath: string): Rule { return (host: Tree) => { addImport(host, options, lib, importPath); return host; }; } export function addSpotfireLibs(): Rule { return (host: Tree) => { //console.log(' ' + host + ' ' + context); console.log('Adding Spotfire Libraries...'); const dependencies: NodeDependency[] = [ //TODO: make versions configurable {type: NodeDependencyType.Default, version: '^0.16.0', name: '@tibco/spotfire-wrapper'}, {type: NodeDependencyType.Default, version: '^3.3.0', name: '@tibco-tcstk/tc-spotfire-lib'}]; addPackageDependencies(host, dependencies); console.log('Spotfire Libraries, added to package.json. Please run "npm install" to install them...'); return host; } } export class routeConfig { path: string; component: string; configResolverName: string; resolver: string; useClaimsResolver: boolean } /* */ const sFSettingImport = "import {SettingsSpotfireComponent, SpotfireConfigResolver} from \"@tibco-tcstk/tc-spotfire-lib\";\n"; const sFSettingsString = " {\n" + " path: 'spotfire-settings',\n" + " component: SettingsSpotfireComponent,\n" + " resolve: {\n" + " spotfireConfigHolder: SpotfireConfigResolver,\n" + " claimsHolder: ClaimsResolver\n" + " }\n" + " },"; const sFMappingImport = "import {\n" + " SettingsSpotfireCreateCaseMappingComponent,\n" + " SpotfireMarkingLiveappsConfigResolver\n" + "} from \"@tibco-tcstk/tc-spotfire-lib\";\n"; const sFMappingString = "\n" + " {\n" + " path: 'spotfire-create-live-apps-case-mapping',\n" + " component: SettingsSpotfireCreateCaseMappingComponent,\n" + " resolve: {\n" + " spotfireMappingConfigHolder: SpotfireMarkingLiveappsConfigResolver,\n" + " claimsHolder: ClaimsResolver\n" + " }\n" + " },"; const sfConfigResolver = "\n SpotfireConfigResolver,"; const sfConfigResolverDef = "\n ,spotfireConfigHolder: SpotfireConfigResolver"; const sfMarkingResolver = "\n SpotfireMarkingLiveappsConfigResolver,"; const sfMarkingResolverDef = "\n ,spotfireMappingConfigHolder: SpotfireMarkingLiveappsConfigResolver"; // import {SpotfireConfigResolver} from '@tibco-tcstk/tc-spotfire-lib'; const sFSettingResolverImport = "import {SpotfireConfigResolver} from '@tibco-tcstk/tc-spotfire-lib';\n"; // import {SpotfireMarkingLiveappsConfigResolver} from '@tibco-tcstk/tc-spotfire-lib'; const sFSettingMappingImport = "import {SpotfireMarkingLiveappsConfigResolver} from '@tibco-tcstk/tc-spotfire-lib';\n"; // Function to update the route configuration export function addSFRoutes(options: MyModuleOptions) { console.log('Spotfire Routes:'); return (host: Tree) => { if (options.doAddRoutes) { console.log('Adding Spotfire Routes...'); const doSFMapping = options.doAddMapping; // Adding the configuration route const configST = 'CONFIGURATION_ROUTE_CONFIG = ['; const routeLocation = 'src/app/route-config/starter-app-route-config/configuration-route-config/configuration-route-config.ts'; host = insertIntoFile(host, routeLocation, [''], sFSettingImport, 0); host = insertIntoFile(host, routeLocation, [configST], sFSettingsString, 0); if (doSFMapping) { host = insertIntoFile(host, routeLocation, [''], sFMappingImport, 0); host = insertIntoFile(host, routeLocation, [configST], sFMappingString, 0); } const providersST = 'CONFIGURATION_ROUTE_PROVIDERS = ['; host = insertIntoFile(host, routeLocation, [providersST], sfConfigResolver, 0); if (doSFMapping) { host = insertIntoFile(host, routeLocation, [providersST], sfMarkingResolver, 0); } const routeHomeLocation = 'src/app/route-config/starter-app-route-config/starter-app-route-config.ts'; const pathST = ["path: 'home',", "resolve: {", '}']; host = insertIntoFile(host, routeHomeLocation, [''], sFSettingResolverImport, 0); host = insertIntoFile(host, routeHomeLocation, pathST, sfConfigResolverDef, -1); if (doSFMapping) { host = insertIntoFile(host, routeHomeLocation, [''], sFSettingMappingImport, 0); host = insertIntoFile(host, routeHomeLocation, pathST, sfMarkingResolverDef, -1); } } else { console.log('Skipping Adding of Spotfire Routes......'); } return host; }; } const sFMenuConfig = " ,{\n" + " \"entry\": \"Spotfire\",\n" + " \"icon\": \"tcs-spotfire-icon\",\n" + " \"options\": [\n" + " \"Settings\"\n" + " ]\n" + " }"; const sFMenuConfigMapping = ",{\n" + " \"entry\": \"Spotfire\",\n" + " \"icon\": \"tcs-spotfire-icon\",\n" + " \"options\": [\n" + " \"Settings\",\n" + " \"Create Live Apps Case Mapping\"\n" + " ]\n" + " }\n"; // Function to update the MENU configuration export function addSFMenuConfig(options: MyModuleOptions) { console.log('Spotfire Menu Configurations:'); return (host: Tree) => { if (options.doAddConfig) { console.log('Adding Spotfire Menu Configurations'); const doSFMapping = options.doAddMapping; const configMenuLocation = 'src/assets/config/configurationMenuConfig.json'; var fRegBuffer = host.read(configMenuLocation); if (fRegBuffer) { let content = fRegBuffer.toString(); let location = content.lastIndexOf("]") - 1; const recorder = host.beginUpdate(configMenuLocation); let toInsertAfter = sFMenuConfig; if (doSFMapping) { toInsertAfter = sFMenuConfigMapping; } recorder.insertRight(location, toInsertAfter); host.commitUpdate(recorder); } } else { console.log('Skipping Adding of Spotfire Menu Configurations...'); } return host; }; } // Function to insert into a file // Leave search string blank ("") to add to the beginning of the file function insertIntoFile(host: Tree, fileName: string, searchString: string[], toInsertAfter: string, offset: number) { var fRegBuffer = host.read(fileName); if (fRegBuffer) { var content = fRegBuffer.toString(); console.log('--- INSERTING INTO FILE (' + fileName + ') ---'); console.log('- SEARCH STRING: ' + searchString); const recorder = host.beginUpdate(fileName); console.log('- INSERTING: ' + toInsertAfter); if (searchString[0] === "") { recorder.insertRight(0, toInsertAfter); } else { let insertAt = offset; let tempSearchString = content; for (let st of searchString) { console.log(st); let tempLoc = tempSearchString.indexOf(st) + st.length; tempSearchString = tempSearchString.substring(tempLoc); insertAt += tempLoc; } recorder.insertRight(insertAt, toInsertAfter); } host.commitUpdate(recorder); } return host; } export function createFile(path: string, content: string): Rule { return (tree: Tree, _context: SchematicContext) => { tree.create(path, content); return tree; }; }