forked from angular/angular
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
98 lines (88 loc) · 3.25 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
* @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
*
* @fileoverview Schematics for bazel-workspace
*/
import {strings} from '@angular-devkit/core';
import {Rule, SchematicContext, SchematicsException, Tree, apply, applyTemplates, mergeWith, move, url} from '@angular-devkit/schematics';
import {getWorkspace} from '@schematics/angular/utility/config';
import {latestVersions} from '@schematics/angular/utility/latest-versions';
import {validateProjectName} from '@schematics/angular/utility/validation';
import {Schema as BazelWorkspaceOptions} from './schema';
/**
* Look for package.json file for package with `packageName` in node_modules and
* extract its version.
*/
function findVersion(projectName: string, packageName: string, host: Tree): string|null {
// Need to look in multiple locations because we could be working in a subtree.
const candidates = [
`node_modules/${packageName}/package.json`,
`${projectName}/node_modules/${packageName}/package.json`,
];
for (const candidate of candidates) {
if (host.exists(candidate)) {
try {
const packageJson = JSON.parse(host.read(candidate).toString());
if (packageJson.name === packageName && packageJson.version) {
return packageJson.version;
}
} catch {
}
}
}
return null;
}
/**
* Clean the version string and return version in the form "1.2.3". Return
* null if version string is invalid. This is similar to semver.clean() but
* takes characters like '^' and '~' into account.
*/
export function clean(version: string): string|null {
const matches = version.match(/(\d+\.\d+\.\d+)/);
return matches && matches.pop() || null;
}
export default function(options: BazelWorkspaceOptions): Rule {
return (host: Tree, context: SchematicContext) => {
if (!options.name) {
throw new SchematicsException(`Invalid options, "name" is required.`);
}
validateProjectName(options.name);
let newProjectRoot = '';
try {
const workspace = getWorkspace(host);
newProjectRoot = workspace.newProjectRoot || '';
} catch {
}
const appDir = `${newProjectRoot}/${options.name}`;
// If the project already has some deps installed, Bazel should use existing
// versions.
const existingVersions = {
Angular: findVersion(options.name, '@angular/core', host),
RxJs: findVersion(options.name, 'rxjs', host),
};
Object.keys(existingVersions).forEach((name: 'Angular' | 'RxJs') => {
const version = existingVersions[name] as string;
if (version) {
context.logger.info(`Bazel will reuse existing version for ${name}: ${version}`);
}
});
const workspaceVersions = {
'ANGULAR_VERSION': existingVersions.Angular || clean(latestVersions.Angular),
'RXJS_VERSION': existingVersions.RxJs || clean(latestVersions.RxJs),
// TODO(kyliau): Consider moving this to latest-versions.ts
'RULES_SASS_VERSION': '1.15.1',
};
return mergeWith(apply(url('./files'), [
applyTemplates({
utils: strings,
...options,
'dot': '.', ...workspaceVersions,
}),
move(appDir),
]));
};
}