return (host: Tree, context: SchematicContext) => { context.logger.debug('updating project configuration.'); // Add worker glob exclusion to tsconfig.app.json. const workerGlob = 'src/**/*.worker.ts'; const buffer = host.read(tsConfigPath); if (buffer) { const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose); if (tsCfgAst.kind != 'object') { throw new SchematicsException('Invalid tsconfig. Was expecting an object'); } const filesAstNode = findPropertyInAstObject(tsCfgAst, 'exclude'); if (filesAstNode && filesAstNode.kind != 'array') { throw new SchematicsException('Invalid tsconfig "exclude" property; expected an array.'); } if (filesAstNode && !filesAstNode.value.includes(workerGlob)) { const recorder = host.beginUpdate(tsConfigPath); appendValueInAstArray(recorder, filesAstNode, workerGlob); host.commitUpdate(recorder); } } return mergeWith( apply(url('./files/worker-tsconfig'), [ applyTemplates({ ...options, relativePathToWorkspaceRoot: relativePathToWorkspaceRoot(root), }), move(root), ]), ); };
return (host: Tree) => { const tsLintPath = '/tslint.json'; const buffer = host.read(tsLintPath); if (!buffer) { return host; } const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose); if (tsCfgAst.kind != 'object') { return host; } const rulesNode = findPropertyInAstObject(tsCfgAst, 'rules'); if (!rulesNode || rulesNode.kind != 'object') { return host; } const recorder = host.beginUpdate(tsLintPath); rulesNode.properties.forEach(prop => { const mapping = ruleMapping[prop.key.value]; if (mapping) { recorder.remove(prop.key.start.offset + 1, prop.key.value.length); recorder.insertLeft(prop.key.start.offset + 1, mapping); } }); host.commitUpdate(recorder); return host; };
return (host: Tree, context: SchematicContext) => { const packageJson = 'package.json'; if (!host.exists(packageJson)) { throw new Error(`Could not find ${packageJson}`); } const content = host.read(packageJson).toString(); const jsonAst = parseJsonAst(content); if (!isJsonAstObject(jsonAst)) { throw new Error(`Failed to parse JSON for ${packageJson}`); } const deps = findPropertyInAstObject(jsonAst, 'dependencies'); if (!isJsonAstObject(deps)) { throw new Error(`Failed to find dependencies in ${packageJson}`); } const rxjs = findPropertyInAstObject(deps, 'rxjs'); if (!rxjs) { throw new Error(`Failed to find rxjs in dependencies of ${packageJson}`); } const value = rxjs.value as string; // value can be version or range const match = value.match(/(\d)+\.(\d)+.(\d)+$/); if (match) { const [_, major, minor] = match; if (major < '6' || (major === '6' && minor < '4')) { const recorder = host.beginUpdate(packageJson); replacePropertyInAstObject(recorder, deps, 'rxjs', '~6.4.0'); host.commitUpdate(recorder); } } else { context.logger.info( 'Could not determine version of rxjs. \n' + 'Please make sure that version is at least 6.4.0.'); } return host; };
return (host: Tree) => { const packageJson = `${options.name}/package.json`; if (!host.exists(packageJson)) { throw new Error(`Could not find ${packageJson}`); } const packageJsonContent = host.read(packageJson); if (!packageJsonContent) { throw new Error('Failed to read package.json content'); } const jsonAst = parseJsonAst(packageJsonContent.toString()) as JsonAstObject; const deps = findPropertyInAstObject(jsonAst, 'dependencies') as JsonAstObject; const devDeps = findPropertyInAstObject(jsonAst, 'devDependencies') as JsonAstObject; const angularCoreNode = findPropertyInAstObject(deps, '@angular/core'); const angularCoreVersion = angularCoreNode !.value as string; const devDependencies: {[k: string]: string} = { '@angular/bazel': angularCoreVersion, // TODO(kyliau): Consider moving this to latest-versions.ts '@bazel/karma': '^0.22.0', '@bazel/typescript': '^0.22.0', }; const recorder = host.beginUpdate(packageJson); for (const packageName of Object.keys(devDependencies)) { const version = devDependencies[packageName]; const indent = 4; insertPropertyInAstObjectInOrder(recorder, devDeps, packageName, version, indent); } host.commitUpdate(recorder); return host; };
return (host: Tree, context: SchematicContext) => { const tsconfigPath = 'tsconfig.json'; if (!host.exists(tsconfigPath)) { return host; } const contentRaw = host.read(tsconfigPath) !.toString(); if (!contentRaw) { return host; } const content = contentRaw.toString(); const ast = parseJsonAst(content); if (!isJsonAstObject(ast)) { return host; } const compilerOptions = findPropertyInAstObject(ast, 'compilerOptions'); if (!isJsonAstObject(compilerOptions)) { return host; } const recorder = host.beginUpdate(tsconfigPath); // target and module are controlled by downstream dependencies, such as // ts_devserver removeKeyValueInAstObject(recorder, content, compilerOptions, 'target'); removeKeyValueInAstObject(recorder, content, compilerOptions, 'module'); // typeRoots is always set to the @types subdirectory of the node_modules // attribute removeKeyValueInAstObject(recorder, content, compilerOptions, 'typeRoots'); // rootDir and baseUrl are always the workspace root directory removeKeyValueInAstObject(recorder, content, compilerOptions, 'rootDir'); removeKeyValueInAstObject(recorder, content, compilerOptions, 'baseUrl'); host.commitUpdate(recorder); return host; };
return (host: Tree) => { const tsConfigPath = '/tsconfig.json'; const buffer = host.read(tsConfigPath); if (!buffer) { return host; } const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose); if (tsCfgAst.kind !== 'object') { return host; } const compilerOptions = findPropertyInAstObject(tsCfgAst, 'compilerOptions'); if (!compilerOptions || compilerOptions.kind !== 'object') { return host; } const importHelpers = findPropertyInAstObject(compilerOptions, 'importHelpers'); if (importHelpers && importHelpers.value === true) { return host; } const recorder = host.beginUpdate(tsConfigPath); if (importHelpers) { const { start, end } = importHelpers; recorder.remove(start.offset, end.offset - start.offset); recorder.insertLeft(start.offset, 'true'); } else { insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'importHelpers', true, 4); } host.commitUpdate(recorder); return host; };
return (tree: Tree) => { const collectionJsonContent = tree.read(collectionPath); if (!collectionJsonContent) { throw new Error('Invalid collection path: ' + collectionPath); } const collectionJsonAst = parseJsonAst(collectionJsonContent.toString('utf-8')); if (collectionJsonAst.kind !== 'object') { throw new Error('Invalid collection content.'); } for (const property of collectionJsonAst.properties) { if (property.key.value == 'schematics') { if (property.value.kind !== 'object') { throw new Error('Invalid collection.json; schematics needs to be an object.'); } const recorder = tree.beginUpdate(collectionPath); appendPropertyInAstObject(recorder, property.value, schematicName, description); tree.commitUpdate(recorder); return tree; } } throw new Error('Could not find the "schematics" property in collection.json.'); };
return (host: Tree) => { const pkgJsonPath = '/package.json'; const buffer = host.read(pkgJsonPath); if (!buffer) { throw new SchematicsException('Could not read package.json.'); } const packageJsonAst = parseJsonAst(buffer.toString(), JsonParseMode.Strict); if (packageJsonAst.kind !== 'object') { throw new SchematicsException('Invalid package.json. Was expecting an object.'); } const scriptsNode = findPropertyInAstObject(packageJsonAst, 'scripts'); if (scriptsNode && scriptsNode.kind === 'object') { const recorder = host.beginUpdate(pkgJsonPath); const postInstall = findPropertyInAstObject(scriptsNode, 'postinstall'); if (!postInstall) { // postinstall script not found, add it. insertPropertyInAstObjectInOrder( recorder, scriptsNode, 'postinstall', 'ivy-ngcc', 4, ); } host.commitUpdate(recorder); } };
return (tree: Tree) => { const collectionJsonContent = tree.read('/.monorepo.json'); if (!collectionJsonContent) { throw new Error('Could not find monorepo.json'); } const collectionJsonAst = parseJsonAst(collectionJsonContent.toString('utf-8')); if (collectionJsonAst.kind !== 'object') { throw new Error('Invalid monorepo content.'); } const packages = collectionJsonAst.properties.find(x => x.key.value == 'packages'); if (!packages) { throw new Error('Cannot find packages key in monorepo.'); } if (packages.value.kind != 'object') { throw new Error('Invalid packages key.'); } const readmeUrl = `https://github.com/angular/devkit/blob/master/${path}/README.md`; const recorder = tree.beginUpdate('/.monorepo.json'); appendPropertyInAstObject( recorder, packages.value, options.name, { name: options.displayName, links: [{ label: 'README', url: readmeUrl }], version: '0.0.1', hash: '', }, ); tree.commitUpdate(recorder); };
export function getWorkspaceRaw( level: 'local' | 'global' = 'local', ): [JsonAstObject | null, string | null] { let configPath = level === 'local' ? projectFilePath() : globalFilePath(); if (!configPath) { if (level === 'global') { configPath = createGlobalSettings(); } else { return [null, null]; } } let content = ''; new NodeJsSyncHost().read(normalize(configPath)) .subscribe(data => content = virtualFs.fileBufferToString(data)); const ast = parseJsonAst(content, JsonParseMode.Loose); if (ast.kind != 'object') { throw new Error('Invalid JSON'); } return [ast, configPath]; }