mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 11:03:53 +08:00
357 lines
10 KiB
TypeScript
357 lines
10 KiB
TypeScript
/**
|
|
* @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 {
|
|
JsonAstObject,
|
|
JsonObject,
|
|
JsonParseMode,
|
|
experimental,
|
|
normalize,
|
|
parseJson,
|
|
parseJsonAst,
|
|
virtualFs,
|
|
} from '@angular-devkit/core';
|
|
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
|
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
|
import * as os from 'os';
|
|
import * as path from 'path';
|
|
import { findUp } from './find-up';
|
|
|
|
function getSchemaLocation(): string {
|
|
return path.join(__dirname, '../lib/config/schema.json');
|
|
}
|
|
|
|
export const workspaceSchemaPath = getSchemaLocation();
|
|
|
|
const configNames = [ 'angular.json', '.angular.json' ];
|
|
const globalFileName = '.angular-config.json';
|
|
|
|
function projectFilePath(projectPath?: string): string | null {
|
|
// Find the configuration, either where specified, in the Angular CLI project
|
|
// (if it's in node_modules) or from the current process.
|
|
return (projectPath && findUp(configNames, projectPath))
|
|
|| findUp(configNames, process.cwd())
|
|
|| findUp(configNames, __dirname);
|
|
}
|
|
|
|
function globalFilePath(): string | null {
|
|
const home = os.homedir();
|
|
if (!home) {
|
|
return null;
|
|
}
|
|
|
|
const p = path.join(home, globalFileName);
|
|
if (existsSync(p)) {
|
|
return p;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
const cachedWorkspaces = new Map<string, experimental.workspace.Workspace | null>();
|
|
|
|
export function getWorkspace(
|
|
level: 'local' | 'global' = 'local',
|
|
): experimental.workspace.Workspace | null {
|
|
const cached = cachedWorkspaces.get(level);
|
|
if (cached != undefined) {
|
|
return cached;
|
|
}
|
|
|
|
const configPath = level === 'local' ? projectFilePath() : globalFilePath();
|
|
|
|
if (!configPath) {
|
|
cachedWorkspaces.set(level, null);
|
|
|
|
return null;
|
|
}
|
|
|
|
const root = normalize(path.dirname(configPath));
|
|
const file = normalize(path.basename(configPath));
|
|
const workspace = new experimental.workspace.Workspace(
|
|
root,
|
|
new NodeJsSyncHost(),
|
|
);
|
|
|
|
workspace.loadWorkspaceFromHost(file).subscribe();
|
|
cachedWorkspaces.set(level, workspace);
|
|
|
|
return workspace;
|
|
}
|
|
|
|
export function createGlobalSettings(): string {
|
|
const home = os.homedir();
|
|
if (!home) {
|
|
throw new Error('No home directory found.');
|
|
}
|
|
|
|
const globalPath = path.join(home, globalFileName);
|
|
writeFileSync(globalPath, JSON.stringify({ version: 1 }));
|
|
|
|
return globalPath;
|
|
}
|
|
|
|
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];
|
|
}
|
|
|
|
export function validateWorkspace(json: JsonObject) {
|
|
const workspace = new experimental.workspace.Workspace(
|
|
normalize('.'),
|
|
new NodeJsSyncHost(),
|
|
);
|
|
|
|
let error;
|
|
workspace.loadWorkspaceFromJson(json).subscribe({
|
|
error: e => error = e,
|
|
});
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
export function getProjectByCwd(workspace: experimental.workspace.Workspace): string | null {
|
|
try {
|
|
return workspace.getProjectByPath(normalize(process.cwd()));
|
|
} catch (e) {
|
|
if (e instanceof experimental.workspace.AmbiguousProjectPathException) {
|
|
return workspace.getDefaultProjectName();
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
export function getPackageManager(): string {
|
|
let workspace = getWorkspace('local');
|
|
|
|
if (workspace) {
|
|
const project = getProjectByCwd(workspace);
|
|
if (project && workspace.getProjectCli(project)) {
|
|
const value = workspace.getProjectCli(project)['packageManager'];
|
|
if (typeof value == 'string') {
|
|
return value;
|
|
}
|
|
}
|
|
if (workspace.getCli()) {
|
|
const value = workspace.getCli()['packageManager'];
|
|
if (typeof value == 'string') {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
workspace = getWorkspace('global');
|
|
if (workspace && workspace.getCli()) {
|
|
const value = workspace.getCli()['packageManager'];
|
|
if (typeof value == 'string') {
|
|
return value;
|
|
}
|
|
}
|
|
|
|
// Only check legacy if updated workspace is not found.
|
|
if (!workspace) {
|
|
const legacyPackageManager = getLegacyPackageManager();
|
|
if (legacyPackageManager !== null) {
|
|
return legacyPackageManager;
|
|
}
|
|
}
|
|
|
|
return 'npm';
|
|
}
|
|
|
|
export function migrateLegacyGlobalConfig(): boolean {
|
|
const homeDir = os.homedir();
|
|
if (homeDir) {
|
|
const legacyGlobalConfigPath = path.join(homeDir, '.angular-cli.json');
|
|
if (existsSync(legacyGlobalConfigPath)) {
|
|
const content = readFileSync(legacyGlobalConfigPath, 'utf-8');
|
|
const legacy = parseJson(content, JsonParseMode.Loose);
|
|
if (!legacy || typeof legacy != 'object' || Array.isArray(legacy)) {
|
|
return false;
|
|
}
|
|
|
|
const cli: JsonObject = {};
|
|
|
|
if (legacy.packageManager && typeof legacy.packageManager == 'string'
|
|
&& legacy.packageManager !== 'default') {
|
|
cli['packageManager'] = legacy.packageManager;
|
|
}
|
|
|
|
if (legacy.defaults && typeof legacy.defaults == 'object' && !Array.isArray(legacy.defaults)
|
|
&& legacy.defaults.schematics && typeof legacy.defaults.schematics == 'object'
|
|
&& !Array.isArray(legacy.defaults.schematics)
|
|
&& typeof legacy.defaults.schematics.collection == 'string') {
|
|
cli['defaultCollection'] = legacy.defaults.schematics.collection;
|
|
}
|
|
|
|
if (legacy.warnings && typeof legacy.warnings == 'object'
|
|
&& !Array.isArray(legacy.warnings)) {
|
|
|
|
const warnings: JsonObject = {};
|
|
if (typeof legacy.warnings.versionMismatch == 'boolean') {
|
|
warnings['versionMismatch'] = legacy.warnings.versionMismatch;
|
|
}
|
|
if (typeof legacy.warnings.typescriptMismatch == 'boolean') {
|
|
warnings['typescriptMismatch'] = legacy.warnings.typescriptMismatch;
|
|
}
|
|
|
|
if (Object.getOwnPropertyNames(warnings).length > 0) {
|
|
cli['warnings'] = warnings;
|
|
}
|
|
}
|
|
|
|
if (Object.getOwnPropertyNames(cli).length > 0) {
|
|
const globalPath = path.join(homeDir, globalFileName);
|
|
writeFileSync(globalPath, JSON.stringify({ version: 1, cli }, null, 2));
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Fallback, check for packageManager in config file in v1.* global config.
|
|
function getLegacyPackageManager(): string | null {
|
|
const homeDir = os.homedir();
|
|
if (homeDir) {
|
|
const legacyGlobalConfigPath = path.join(homeDir, '.angular-cli.json');
|
|
if (existsSync(legacyGlobalConfigPath)) {
|
|
const content = readFileSync(legacyGlobalConfigPath, 'utf-8');
|
|
|
|
const legacy = parseJson(content, JsonParseMode.Loose);
|
|
if (!legacy || typeof legacy != 'object' || Array.isArray(legacy)) {
|
|
return null;
|
|
}
|
|
|
|
if (legacy.packageManager && typeof legacy.packageManager === 'string'
|
|
&& legacy.packageManager !== 'default') {
|
|
return legacy.packageManager;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
export function getSchematicDefaults(
|
|
collection: string,
|
|
schematic: string,
|
|
project?: string | null,
|
|
): {} {
|
|
let result = {};
|
|
const fullName = `${collection}:${schematic}`;
|
|
|
|
let workspace = getWorkspace('global');
|
|
if (workspace && workspace.getSchematics()) {
|
|
const schematicObject = workspace.getSchematics()[fullName];
|
|
if (schematicObject) {
|
|
result = { ...result, ...(schematicObject as {}) };
|
|
}
|
|
const collectionObject = workspace.getSchematics()[collection];
|
|
if (typeof collectionObject == 'object' && !Array.isArray(collectionObject)) {
|
|
result = { ...result, ...(collectionObject[schematic] as {}) };
|
|
}
|
|
|
|
}
|
|
|
|
workspace = getWorkspace('local');
|
|
|
|
if (workspace) {
|
|
if (workspace.getSchematics()) {
|
|
const schematicObject = workspace.getSchematics()[fullName];
|
|
if (schematicObject) {
|
|
result = { ...result, ...(schematicObject as {}) };
|
|
}
|
|
const collectionObject = workspace.getSchematics()[collection];
|
|
if (typeof collectionObject == 'object' && !Array.isArray(collectionObject)) {
|
|
result = { ...result, ...(collectionObject[schematic] as {}) };
|
|
}
|
|
}
|
|
|
|
project = project || getProjectByCwd(workspace);
|
|
if (project && workspace.getProjectSchematics(project)) {
|
|
const schematicObject = workspace.getProjectSchematics(project)[fullName];
|
|
if (schematicObject) {
|
|
result = { ...result, ...(schematicObject as {}) };
|
|
}
|
|
const collectionObject = workspace.getProjectSchematics(project)[collection];
|
|
if (typeof collectionObject == 'object' && !Array.isArray(collectionObject)) {
|
|
result = { ...result, ...(collectionObject[schematic] as {}) };
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function isWarningEnabled(warning: string): boolean {
|
|
let workspace = getWorkspace('local');
|
|
|
|
if (workspace) {
|
|
const project = getProjectByCwd(workspace);
|
|
if (project && workspace.getProjectCli(project)) {
|
|
const warnings = workspace.getProjectCli(project)['warnings'];
|
|
if (typeof warnings == 'object' && !Array.isArray(warnings)) {
|
|
const value = warnings[warning];
|
|
if (typeof value == 'boolean') {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
if (workspace.getCli()) {
|
|
const warnings = workspace.getCli()['warnings'];
|
|
if (typeof warnings == 'object' && !Array.isArray(warnings)) {
|
|
const value = warnings[warning];
|
|
if (typeof value == 'boolean') {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
workspace = getWorkspace('global');
|
|
if (workspace && workspace.getCli()) {
|
|
const warnings = workspace.getCli()['warnings'];
|
|
if (typeof warnings == 'object' && !Array.isArray(warnings)) {
|
|
const value = warnings[warning];
|
|
if (typeof value == 'boolean') {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|