angular-cn/aio/tools/examples/example-boilerplate.js
Pete Bacon Darwin bdcbd9ed4b fix(ivy): ngcc - teach Esm5ReflectionHost about aliased variables (#29092)
Sometimes, in ESM5 code, aliases to exported variables are used internally
to refer to the exported value. This prevented some analysis from being
able to match up a reference to an export to the actual export itself.

For example in the following code:

```
var HttpClientXsrfModule = /** @class */ (function () {
  function HttpClientXsrfModule() {
  }
  HttpClientXsrfModule_1 = HttpClientXsrfModule;
  HttpClientXsrfModule.withOptions = function (options) {
      if (options === void 0) { options = {}; }
      return {
          ngModule: HttpClientXsrfModule_1,
          providers: [],
      };
  };
  var HttpClientXsrfModule_1;
  HttpClientXsrfModule = HttpClientXsrfModule_1 = tslib_1.__decorate([
      NgModule({
          providers: [],
      })
  ], HttpClientXsrfModule);
  return HttpClientXsrfModule;
}());
```

We were not able to tell that the `ngModule: HttpClientXsrfModule_1` property
assignment was actually meant to refer to the `function HttpClientXrsfModule()`
declaration.  This caused the `ModuleWithProviders` processing to fail.

This commit ensures that we can compile typings files using the ESM5
format, so we can now update the examples boilerplate tool so that it
does not need to compile the ESM2015 format at all.

PR Close #29092
2019-03-20 14:45:55 -04:00

148 lines
5.7 KiB
JavaScript

const fs = require('fs-extra');
const glob = require('glob');
const path = require('canonical-path');
const shelljs = require('shelljs');
const yargs = require('yargs');
const SHARED_PATH = path.resolve(__dirname, 'shared');
const SHARED_NODE_MODULES_PATH = path.resolve(SHARED_PATH, 'node_modules');
const BOILERPLATE_BASE_PATH = path.resolve(SHARED_PATH, 'boilerplate');
const BOILERPLATE_COMMON_BASE_PATH = path.resolve(BOILERPLATE_BASE_PATH, 'common');
const EXAMPLES_BASE_PATH = path.resolve(__dirname, '../../content/examples');
const BOILERPLATE_PATHS = {
cli: [
'src/environments/environment.prod.ts', 'src/environments/environment.ts',
'src/assets/.gitkeep', 'src/browserslist', 'src/favicon.ico', 'src/karma.conf.js',
'src/polyfills.ts', 'src/test.ts', 'src/tsconfig.app.json', 'src/tsconfig.spec.json',
'src/tslint.json', 'e2e/src/app.po.ts', 'e2e/protractor.conf.js', 'e2e/tsconfig.e2e.json',
'.editorconfig', 'angular.json', 'package.json', 'tsconfig.json', 'tslint.json'
],
systemjs: [
'src/systemjs-angular-loader.js', 'src/systemjs.config.js', 'src/tsconfig.json',
'bs-config.json', 'bs-config.e2e.json', 'package.json', 'tslint.json'
],
common: ['src/styles.css']
};
// All paths in this tool are relative to the current boilerplate folder, i.e boilerplate/i18n
// This maps the CLI files that exists in a parent folder
const cliRelativePath = BOILERPLATE_PATHS.cli.map(file => `../cli/${file}`);
BOILERPLATE_PATHS.elements = [...cliRelativePath, 'tsconfig.json'];
BOILERPLATE_PATHS.i18n = [...cliRelativePath, 'angular.json', 'package.json'];
BOILERPLATE_PATHS['service-worker'] = [...cliRelativePath, 'angular.json', 'package.json'];
BOILERPLATE_PATHS.testing = [...cliRelativePath, 'angular.json'];
BOILERPLATE_PATHS.universal = [...cliRelativePath, 'angular.json', 'package.json'];
BOILERPLATE_PATHS.ivy = {
systemjs: ['rollup-config.js', 'tsconfig-aot.json'],
cli: ['src/tsconfig.app.json']
};
BOILERPLATE_PATHS.schematics = [
...cliRelativePath,
'angular.json'
];
const EXAMPLE_CONFIG_FILENAME = 'example-config.json';
class ExampleBoilerPlate {
/**
* Add boilerplate files to all the examples
*/
add(ivy = false) {
// Get all the examples folders, indicated by those that contain a `example-config.json` file
const exampleFolders =
this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules');
if (!fs.existsSync(SHARED_NODE_MODULES_PATH)) {
throw new Error(
`The shared node_modules folder for the examples (${SHARED_NODE_MODULES_PATH}) is missing.\n` +
`Perhaps you need to run "yarn example-use-npm" or "yarn example-use-local" to install the dependencies?`);
}
if (ivy) {
// We only need the "fesm5" bundles as the CLI webpack build does not need
// any other formats for building and serving.
shelljs.exec(`yarn --cwd ${SHARED_PATH} ivy-ngcc --properties module`);
}
exampleFolders.forEach(exampleFolder => {
const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME));
// Link the node modules - requires admin access (on Windows) because it adds symlinks
const destinationNodeModules = path.resolve(exampleFolder, 'node_modules');
fs.ensureSymlinkSync(SHARED_NODE_MODULES_PATH, destinationNodeModules);
const boilerPlateType = exampleConfig.projectType || 'cli';
const boilerPlateBasePath = path.resolve(BOILERPLATE_BASE_PATH, boilerPlateType);
// Copy the boilerplate specific files
BOILERPLATE_PATHS[boilerPlateType].forEach(
filePath => this.copyFile(boilerPlateBasePath, exampleFolder, filePath));
// Copy the boilerplate common files
BOILERPLATE_PATHS.common.forEach(
filePath => this.copyFile(BOILERPLATE_COMMON_BASE_PATH, exampleFolder, filePath));
// Copy Ivy specific files
if (ivy) {
const ivyBoilerPlateType = boilerPlateType === 'systemjs' ? 'systemjs' : 'cli';
const ivyBoilerPlateBasePath =
path.resolve(BOILERPLATE_BASE_PATH, 'ivy', ivyBoilerPlateType);
BOILERPLATE_PATHS.ivy[ivyBoilerPlateType].forEach(
filePath => this.copyFile(ivyBoilerPlateBasePath, exampleFolder, filePath));
}
});
}
/**
* Remove all the boilerplate files from all the examples
*/
remove() { shelljs.exec('git clean -xdfq', {cwd: EXAMPLES_BASE_PATH}); }
main() {
yargs.usage('$0 <cmd> [args]')
.command('add', 'add the boilerplate to each example', (yrgs) => this.add(yrgs.argv.ivy))
.command('remove', 'remove the boilerplate from each example', () => this.remove())
.demandCommand(1, 'Please supply a command from the list above')
.argv;
}
getFoldersContaining(basePath, filename, ignore) {
const pattern = path.resolve(basePath, '**', filename);
const ignorePattern = path.resolve(basePath, '**', ignore, '**');
return glob.sync(pattern, {ignore: [ignorePattern]}).map(file => path.dirname(file));
}
copyFile(sourceFolder, destinationFolder, filePath) {
const sourcePath = path.resolve(sourceFolder, filePath);
// normalize path if needed
filePath = this.normalizePath(filePath);
const destinationPath = path.resolve(destinationFolder, filePath);
fs.copySync(sourcePath, destinationPath, {overwrite: true});
fs.chmodSync(destinationPath, 444);
}
loadJsonFile(filePath) { return fs.readJsonSync(filePath, {throws: false}) || {}; }
normalizePath(filePath) {
// transform for example ../cli/src/tsconfig.app.json to src/tsconfig.app.json
return filePath.replace(/\.{2}\/\w+\//, '');
}
}
module.exports = new ExampleBoilerPlate();
// If this file was run directly then run the main function,
if (require.main === module) {
module.exports.main();
}