From ea781615091243d9129429a37b3ff6b5bcaf1580 Mon Sep 17 00:00:00 2001
From: Alan Agius <alan.agius4@gmail.com>
Date: Sun, 15 Sep 2019 17:58:45 +0200
Subject: [PATCH] feat(@schematics/angular): remove dependency on tsickle

With this change we remove the requirement  to add tsickle as a dependency when having a workspace library.

Since the CTOR downlevel transformer which was previously provided via tsickle  is now in ng-packagr version 5.5.1+ We migrate existing libraries to remove the need for tsickle.
---
 .../library/files/tsconfig.lib.json.template  |  1 -
 packages/schematics/angular/library/index.ts  |  5 --
 .../update-8/update-dependencies.ts           |  2 +-
 .../angular/migrations/update-9/index.ts      |  2 +
 .../migrations/update-9/remove-tsickle.ts     | 53 ++++++++++++
 .../update-9/remove-tsickle_spec.ts           | 84 +++++++++++++++++++
 .../update-9/update-dependencies.ts           |  1 -
 .../angular/utility/latest-versions.ts        |  3 +-
 8 files changed, 141 insertions(+), 10 deletions(-)
 create mode 100644 packages/schematics/angular/migrations/update-9/remove-tsickle.ts
 create mode 100644 packages/schematics/angular/migrations/update-9/remove-tsickle_spec.ts

diff --git a/packages/schematics/angular/library/files/tsconfig.lib.json.template b/packages/schematics/angular/library/files/tsconfig.lib.json.template
index a7e7b5665f58..7518a4c87974 100644
--- a/packages/schematics/angular/library/files/tsconfig.lib.json.template
+++ b/packages/schematics/angular/library/files/tsconfig.lib.json.template
@@ -12,7 +12,6 @@
     ]
   },
   "angularCompilerOptions": {
-    "annotateForClosureCompiler": true,
     "skipTemplateCodegen": true,
     "strictMetadataEmit": true,
     "enableResourceInlining": true
diff --git a/packages/schematics/angular/library/index.ts b/packages/schematics/angular/library/index.ts
index 01ce622698c9..8d33a1870d38 100644
--- a/packages/schematics/angular/library/index.ts
+++ b/packages/schematics/angular/library/index.ts
@@ -103,11 +103,6 @@ function addDependenciesToPackageJson() {
         name: 'ng-packagr',
         version: latestVersions.ngPackagr,
       },
-      {
-        type: NodeDependencyType.Dev,
-        name: 'tsickle',
-        version: latestVersions.tsickle,
-      },
       {
         type: NodeDependencyType.Default,
         name: 'tslib',
diff --git a/packages/schematics/angular/migrations/update-8/update-dependencies.ts b/packages/schematics/angular/migrations/update-8/update-dependencies.ts
index 00b891ab4718..144b613a5818 100644
--- a/packages/schematics/angular/migrations/update-8/update-dependencies.ts
+++ b/packages/schematics/angular/migrations/update-8/update-dependencies.ts
@@ -17,7 +17,7 @@ export function updateDependencies() {
       '@angular-devkit/build-ng-packagr': latestVersions.DevkitBuildNgPackagr,
       '@angular-devkit/build-webpack': latestVersions.DevkitBuildWebpack,
       'zone.js': latestVersions.ZoneJs,
-      tsickle: latestVersions.tsickle,
+      tsickle: '^0.37.0',
       'ng-packagr': latestVersions.ngPackagr,
       'web-animations-js': '^2.3.2',
     };
diff --git a/packages/schematics/angular/migrations/update-9/index.ts b/packages/schematics/angular/migrations/update-9/index.ts
index 33205818be75..0d3690a23295 100644
--- a/packages/schematics/angular/migrations/update-9/index.ts
+++ b/packages/schematics/angular/migrations/update-9/index.ts
@@ -10,6 +10,7 @@ import { Rule, chain } from '@angular-devkit/schematics';
 import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
 import { updateLibraries } from './ivy-libraries';
 import { updateNGSWConfig } from './ngsw-config';
+import { removeTsickle } from './remove-tsickle';
 import { updateApplicationTsConfigs } from './update-app-tsconfigs';
 import { updateDependencies } from './update-dependencies';
 import { updateServerMainFile } from './update-server-main-file';
@@ -24,6 +25,7 @@ export default function(): Rule {
       updateApplicationTsConfigs(),
       updateDependencies(),
       updateServerMainFile(),
+      removeTsickle(),
       (tree, context) => {
         const packageChanges = tree.actions.some(a => a.path.endsWith('/package.json'));
         if (packageChanges) {
diff --git a/packages/schematics/angular/migrations/update-9/remove-tsickle.ts b/packages/schematics/angular/migrations/update-9/remove-tsickle.ts
new file mode 100644
index 000000000000..283cb9c3162e
--- /dev/null
+++ b/packages/schematics/angular/migrations/update-9/remove-tsickle.ts
@@ -0,0 +1,53 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+import { JsonParseMode, parseJsonAst } from '@angular-devkit/core';
+import { Rule, Tree } from '@angular-devkit/schematics';
+import { removePackageJsonDependency } from '../../utility/dependencies';
+import { findPropertyInAstObject, removePropertyInAstObject } from '../../utility/json-utils';
+import { Builders } from '../../utility/workspace-models';
+import { getAllOptions, getTargets, getWorkspace } from './utils';
+
+/**
+ * Remove tsickle from libraries
+ */
+export function removeTsickle(): Rule {
+  return (tree: Tree) => {
+    removePackageJsonDependency(tree, 'tsickle');
+
+    const workspace = getWorkspace(tree);
+
+    for (const { target } of getTargets(workspace, 'build', Builders.NgPackagr)) {
+      for (const options of getAllOptions(target)) {
+        const tsConfigOption = findPropertyInAstObject(options, 'tsConfig');
+        if (!tsConfigOption || tsConfigOption.kind !== 'string') {
+          continue;
+        }
+
+        const tsConfigContent = tree.read(tsConfigOption.value);
+        if (!tsConfigContent) {
+          continue;
+        }
+
+        const tsConfigAst = parseJsonAst(tsConfigContent.toString(), JsonParseMode.Loose);
+        if (!tsConfigAst || tsConfigAst.kind !== 'object') {
+          continue;
+        }
+
+        const ngCompilerOptions = findPropertyInAstObject(tsConfigAst, 'angularCompilerOptions');
+        if (ngCompilerOptions && ngCompilerOptions.kind === 'object') {
+          // remove annotateForClosureCompiler option
+          const recorder = tree.beginUpdate(tsConfigOption.value);
+          removePropertyInAstObject(recorder, ngCompilerOptions, 'annotateForClosureCompiler');
+          tree.commitUpdate(recorder);
+        }
+      }
+    }
+
+    return tree;
+  };
+}
diff --git a/packages/schematics/angular/migrations/update-9/remove-tsickle_spec.ts b/packages/schematics/angular/migrations/update-9/remove-tsickle_spec.ts
new file mode 100644
index 000000000000..c71cf5816d5f
--- /dev/null
+++ b/packages/schematics/angular/migrations/update-9/remove-tsickle_spec.ts
@@ -0,0 +1,84 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import { EmptyTree } from '@angular-devkit/schematics';
+import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing';
+
+// tslint:disable:no-big-function
+describe('Migration to version 9', () => {
+  describe('Remove tsickle and annotateForClosureCompiler', () => {
+    const schematicRunner = new SchematicTestRunner(
+      'migrations',
+      require.resolve('../migration-collection.json'),
+    );
+
+    let tree: UnitTestTree;
+
+    beforeEach(async () => {
+      tree = new UnitTestTree(new EmptyTree());
+      tree = await schematicRunner
+        .runExternalSchematicAsync(
+          require.resolve('../../collection.json'),
+          'workspace',
+          {
+            name: 'migration-test',
+            version: '1.2.3',
+            directory: '.',
+          },
+          tree,
+        )
+        .toPromise();
+      tree = await schematicRunner
+        .runExternalSchematicAsync(
+          require.resolve('../../collection.json'),
+          'library',
+          {
+            name: 'migration-lib',
+          },
+          tree,
+        )
+        .toPromise();
+    });
+
+    it(`should remove 'annotateForClosureCompiler' from library tsconfig`, async () => {
+      const libTsConfig = 'migration-lib/tsconfig.lib.json';
+
+      const tsconfig = {
+        compilerOptions: {},
+        angularCompilerOptions: {
+          enableIvy: false,
+          skipTemplateCodegen: true,
+          annotateForClosureCompiler: true,
+        },
+      };
+
+      tree.overwrite(libTsConfig, JSON.stringify(tsconfig, undefined, 2));
+
+      const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
+      const { angularCompilerOptions } = JSON.parse(tree2.readContent(libTsConfig));
+      expect(angularCompilerOptions).toEqual({ enableIvy: false, skipTemplateCodegen: true });
+    });
+
+    it('should remove all dependencies on tsickle', async () => {
+      const packageJson = {
+        dependencies: {
+          'tsickle': '0.0.0',
+        },
+        devDependencies: {
+          'tsickle': '0.0.0',
+        },
+      };
+
+      tree.overwrite('/package.json', JSON.stringify(packageJson, undefined, 2));
+      const tree2 = await schematicRunner.runSchematicAsync('migration-09', {}, tree.branch()).toPromise();
+      const { dependencies, devDependencies } = JSON.parse(tree2.readContent('/package.json'));
+      expect(dependencies['tsickle']).toBeUndefined();
+      expect(devDependencies['tsickle']).toBeUndefined();
+    });
+  });
+});
diff --git a/packages/schematics/angular/migrations/update-9/update-dependencies.ts b/packages/schematics/angular/migrations/update-9/update-dependencies.ts
index 00b891ab4718..301511f653b3 100644
--- a/packages/schematics/angular/migrations/update-9/update-dependencies.ts
+++ b/packages/schematics/angular/migrations/update-9/update-dependencies.ts
@@ -17,7 +17,6 @@ export function updateDependencies() {
       '@angular-devkit/build-ng-packagr': latestVersions.DevkitBuildNgPackagr,
       '@angular-devkit/build-webpack': latestVersions.DevkitBuildWebpack,
       'zone.js': latestVersions.ZoneJs,
-      tsickle: latestVersions.tsickle,
       'ng-packagr': latestVersions.ngPackagr,
       'web-animations-js': '^2.3.2',
     };
diff --git a/packages/schematics/angular/utility/latest-versions.ts b/packages/schematics/angular/utility/latest-versions.ts
index 9cbafc9c6977..8d48546c1905 100644
--- a/packages/schematics/angular/utility/latest-versions.ts
+++ b/packages/schematics/angular/utility/latest-versions.ts
@@ -20,6 +20,5 @@ export const latestVersions = {
   DevkitBuildWebpack: '~0.900.0-next.4',
   AngularPWA: '~0.900.0-next.4',
 
-  tsickle: '^0.37.0',
-  ngPackagr: '^5.4.0',
+  ngPackagr: '^5.5.1',
 };