Skip to content

Commit 64c1ad5

Browse files
devversionmmalerba
authored andcommitted
refactor: setup esbuild and update-tool in mdc-migration schematic
Sets up ESBuild and the update-tool in the MDC migration schematic. This allows us to have a clear separation of some parts of the migration / rely on the TypeScript AST etc. We use ESBuild so that we can bring in e.g. Sass AST without requiring a dependency on the Material NPM package.
1 parent 8e41f26 commit 64c1ad5

File tree

10 files changed

+209
-12
lines changed

10 files changed

+209
-12
lines changed

integration/mdc-migration/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ node_integration_test(
2020
# See: https://github.com/yarnpkg/yarn/issues/2165.
2121
# TODO(devversion): determine if a solution/workaround could live in the test runner.
2222
"yarn install --cache-folder .yarn_cache_folder/",
23-
"yarn ng generate @angular/material:mdc-migration -c all",
23+
"yarn ng generate @angular/material:mdc-migration -c all --tsconfig tsconfig.app.json",
2424
"yarn test",
2525
],
2626
npm_packages = npmPackageMappings,

src/cdk/schematics/ng-update/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ export * from './typescript/base-types';
1616
export * from './typescript/imports';
1717
export * from './typescript/literal';
1818
export * from './typescript/module-specifiers';
19+
export * from './find-stylesheets';
1920
export * from './upgrade-data';

src/material/schematics/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ ts_library(
4747
pkg_npm(
4848
name = "npm_package",
4949
srcs = ["package.json"],
50+
nested_packages = [
51+
"//src/material/schematics/ng-generate/mdc-migration:npm_package",
52+
],
5053
deps = [
5154
":schematics",
5255
":schematics_assets",

src/material/schematics/collection.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
},
4646
"mdcMigration": {
4747
"description": "Migrate to MDC-based Angular Material components",
48-
"factory": "./ng-generate/mdc-migration/index",
48+
"factory": "./ng-generate/mdc-migration/index_bundled",
4949
"schema": "./ng-generate/mdc-migration/schema.json",
5050
"aliases": ["mdc-migration"]
5151
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
load("@build_bazel_rules_nodejs//:index.bzl", "copy_to_bin")
2+
load("//tools:defaults.bzl", "esbuild", "jasmine_node_test", "pkg_npm", "spec_bundle", "ts_library")
3+
4+
package(default_visibility = ["//visibility:public"])
5+
6+
STATIC_ASSETS = [
7+
"schema.json",
8+
]
9+
10+
ts_library(
11+
name = "mdc_migration_lib",
12+
srcs = glob(
13+
["**/*.ts"],
14+
exclude = ["**/*.spec.ts"],
15+
),
16+
deps = [
17+
"//src/cdk/schematics",
18+
"@npm//@angular-devkit/schematics",
19+
"@npm//@types/node",
20+
],
21+
)
22+
23+
esbuild(
24+
name = "mdc_migration_bundle",
25+
entry_point = ":index.ts",
26+
external = [
27+
"@angular/cdk/schematics",
28+
"@angular-devkit/schematics",
29+
"@angular-devkit/core",
30+
],
31+
format = "cjs",
32+
output = "index_bundled.js",
33+
platform = "node",
34+
target = "es2015",
35+
deps = [":mdc_migration_lib"],
36+
)
37+
38+
pkg_npm(
39+
name = "npm_package",
40+
srcs = STATIC_ASSETS,
41+
deps = [":mdc_migration_bundle"],
42+
)
43+
44+
########################################
45+
# Testing configuration #
46+
########################################
47+
48+
ts_library(
49+
name = "unit_tests_lib",
50+
testonly = True,
51+
srcs = glob(["**/*.spec.ts"]),
52+
deps = [
53+
":mdc_migration_lib",
54+
"//src/cdk/schematics/testing",
55+
"@npm//@angular-devkit/core",
56+
"@npm//@angular-devkit/schematics",
57+
"@npm//@bazel/runfiles",
58+
"@npm//@types/jasmine",
59+
"@npm//@types/node",
60+
],
61+
)
62+
63+
spec_bundle(
64+
name = "unit_tests_bundle",
65+
platform = "node",
66+
deps = [":unit_tests_lib"],
67+
)
68+
69+
copy_to_bin(
70+
name = "unit_tests_assets",
71+
testonly = True,
72+
srcs = STATIC_ASSETS,
73+
)
74+
75+
jasmine_node_test(
76+
name = "unit_tests",
77+
data = [
78+
":mdc_migration_bundle",
79+
":unit_tests_assets",
80+
"//src/material/schematics:schematics_assets",
81+
],
82+
deps = [
83+
":unit_tests_bundle",
84+
# Runtime dependencies needed by the test and actual migration sources. These need
85+
# to be specified explicitly here because they are not captured by the bundling.
86+
"//src/cdk/schematics",
87+
"@npm//@schematics/angular",
88+
],
89+
)

src/material/schematics/ng-generate/mdc-migration/index.ts

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
*/
88

99
import {Rule, SchematicContext, Tree} from '@angular-devkit/schematics';
10-
import * as path from 'path';
1110
import {Schema} from './schema';
11+
import {DevkitFileSystem, UpdateProject, findStylesheetFiles} from '@angular/cdk/schematics';
12+
import {ThemingStylesMigration} from './rules/theming-styles';
13+
import {dirname} from 'path';
1214

1315
/** Groups of components that must be migrated together. */
1416
const migrationGroups = [
@@ -51,10 +53,39 @@ function getComponentsToMigrate(requested: string[]): Set<string> {
5153

5254
export default function (options: Schema): Rule {
5355
const componentsToMigrate = getComponentsToMigrate(options.components);
54-
// TOOD(mmalerba): Use a workspace-releative rather than absolute path.
55-
const pathToMigrate = path.resolve(options.path ?? process.cwd());
56+
const tsconfigPath = options.tsconfig;
57+
const migrationDir = options.directory ?? dirname(tsconfigPath);
5658

57-
console.log('Will migrate', [...componentsToMigrate], 'for', pathToMigrate);
59+
console.log('Migrating:', [...componentsToMigrate]);
60+
console.log('Directory:', migrationDir);
5861

59-
return (tree: Tree, context: SchematicContext) => tree;
62+
return (tree: Tree, context: SchematicContext) => {
63+
const fileSystem = new DevkitFileSystem(tree);
64+
const program = UpdateProject.createProgramFromTsconfig(
65+
fileSystem.resolve(tsconfigPath),
66+
fileSystem,
67+
);
68+
69+
const additionalStylesheetPaths = findStylesheetFiles(tree, migrationDir);
70+
const project = new UpdateProject(context, program, fileSystem, new Set(), context.logger);
71+
const {hasFailures} = project.migrate(
72+
[ThemingStylesMigration],
73+
null,
74+
null,
75+
additionalStylesheetPaths,
76+
);
77+
78+
// Commit all recorded edits in the update recorder. We apply the edits after all
79+
// migrations ran because otherwise offsets in the TypeScript program would be
80+
// shifted and individual migrations could no longer update the same source file.
81+
fileSystem.commitEdits();
82+
83+
if (hasFailures) {
84+
context.logger.error('Unable to migrate project. See errors above.');
85+
} else {
86+
context.logger.info('Successfully migrated the project.');
87+
}
88+
89+
return tree;
90+
};
6091
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {createTestApp, patchDevkitTreeToExposeTypeScript} from '@angular/cdk/schematics/testing';
2+
import {SchematicTestRunner, UnitTestTree} from '@angular-devkit/schematics/testing';
3+
import {Schema} from '../schema';
4+
import {runfiles} from '@bazel/runfiles';
5+
6+
describe('theming styles', () => {
7+
let runner: SchematicTestRunner;
8+
let cliAppTree: UnitTestTree;
9+
10+
beforeEach(async () => {
11+
runner = new SchematicTestRunner(
12+
'@angular/material',
13+
runfiles.resolveWorkspaceRelative('src/material/schematics/collection.json'),
14+
);
15+
cliAppTree = patchDevkitTreeToExposeTypeScript(await createTestApp(runner));
16+
});
17+
18+
async function migrate(options: Schema): Promise<UnitTestTree> {
19+
return await runner.runSchematicAsync('mdcMigration', options, cliAppTree).toPromise();
20+
}
21+
22+
it('should work', async () => {
23+
cliAppTree.create(
24+
'/projects/material/src/theme.scss',
25+
`
26+
@use '@angular/material' as mat;
27+
28+
$my-theme: ();
29+
@include mat.all-component-themes($my-theme);
30+
`,
31+
);
32+
33+
const result = await migrate({
34+
tsconfig: '/projects/material/tsconfig.app.json',
35+
components: ['all'],
36+
});
37+
38+
expect(result.readContent('/projects/material/src/theme.scss')).toContain('$some-var:');
39+
});
40+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Migration, ResolvedResource} from '@angular/cdk/schematics';
10+
import {SchematicContext} from '@angular-devkit/schematics';
11+
12+
export class ThemingStylesMigration extends Migration<null, SchematicContext> {
13+
enabled = true;
14+
15+
override visitStylesheet(stylesheet: ResolvedResource) {
16+
// TODO: Implement this migration. This is just a placeholder currently.
17+
this.fileSystem.edit(stylesheet.filePath).insertRight(0, '$some-var: #fff;');
18+
}
19+
}

src/material/schematics/ng-generate/mdc-migration/schema.d.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,18 @@
88

99
export interface Schema {
1010
/**
11-
* The path to migrate.
11+
* Workspace-relative path to the TypeScript project that should be migrated.
1212
*/
13-
path?: string;
13+
tsconfig: string;
14+
/**
15+
* Workspace-relative path to a directory which will be migrated.
16+
*
17+
* Source files determined outside of this directory will be ignored,
18+
* allowing for an incremental migration.
19+
*
20+
* If not set, the directory is determined based on the specified tsconfig.
21+
*/
22+
directory?: string;
1423

1524
/**
1625
* The components to migrate.

src/material/schematics/ng-generate/mdc-migration/schema.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
"title": "Material MDC Migration Schema",
55
"type": "object",
66
"properties": {
7-
"path": {
7+
"tsconfig": {
88
"type": "string",
99
"format": "path",
10-
"description": "The path to migrate. (Defaults to the current working directory)",
11-
"alias": "p",
10+
"description": "Workspace-relative path to the TypeScript project that should be migrated."
11+
},
12+
"directory": {
13+
"type": "string",
14+
"format": "path",
15+
"description": "Workspace-relative path to a directory which will be migrated.",
16+
"alias": "d",
1217
"default": ""
1318
},
1419
"components": {

0 commit comments

Comments
 (0)