Skip to content

Commit

Permalink
Merge pull request #341 from SuperITMan/feature/copy-webpack-files
Browse files Browse the repository at this point in the history
feat(build) feat(test) Add support and requirement for .angular-cli.json
  • Loading branch information
dsebastien committed Apr 27, 2018
2 parents d28003b + 6973fbd commit 5a4445e
Show file tree
Hide file tree
Showing 15 changed files with 347 additions and 73 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@angular/core": "5.2.10",
"@commitlint/cli": "6.1.3",
"@commitlint/config-conventional": "6.1.3",
"@ngtools/json-schema": "1.1.0",
"codelyzer": "4.3.0",
"conventional-changelog-cli": "1.3.22",
"commitizen": "2.9.6",
Expand Down Expand Up @@ -59,8 +60,8 @@
"clean:modules:all": "npm run clean:modules && npm run clean:modules:stark-build && npm run clean:modules:stark-core && npm run clean:modules:stark-testing && npm run clean:modules:starter",
"clean:modules:stark-build": "cd packages/stark-build && npm run clean:modules && cd ../..",
"clean:modules:stark-core": "cd packages/stark-core && npm run clean:modules && cd ../..",
"clean:modules:stark-testing": "cd packages/stark-testing && npm run clean:modules dist && cd ../..",
"clean:modules:starter": "cd starter && npm run clean:modules dist && cd ..",
"clean:modules:stark-testing": "cd packages/stark-testing && npm run clean:modules && cd ../..",
"clean:modules:starter": "cd starter && npm run clean:modules && cd ..",
"commit": "./node_modules/.bin/git-cz",
"commitmsg": "commitlint -e $GIT_PARAMS",
"generate:changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
Expand All @@ -80,6 +81,7 @@
"install:ci:starter": "cd starter && npm ci && cd ..",
"install:travis:all": "npm run install:stark-build && npm run install:stark-testing && npm run install:stark-core && npm run build:trace && npm run update:starter",
"ngc": "ngc",
"prebuild": "node ./packages/validate-packages.js",
"precommit": "lint-staged",
"prettier-check": "prettier **/*.{css,js,json,pcss,scss,ts} --write",
"preupdate:starter": "npm run clean:starter",
Expand Down
167 changes: 143 additions & 24 deletions packages/stark-build/config/build-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const ts = require("typescript");
const path = require("path");
const fs = require("fs");
const helpers = require("./helpers");
const ngCliUtils = require("./ng-cli-utils");

const DEFAULT_METADATA = {
title: "Stark Application by @NationalBankBelgium",
Expand All @@ -11,13 +12,8 @@ const DEFAULT_METADATA = {
AOT: process.env.BUILD_AOT || helpers.hasNpmFlag("aot"),
E2E: !!process.env.BUILD_E2E,
WATCH: helpers.hasProcessFlag("watch"),
tsConfigPath: "tsconfig.app.json",

/**
* This suffix is added to the environment.ts file, if not set the default environment file is loaded (development)
* To disable environment files set this to null
*/
envFileSuffix: ""
tsConfigPath: getAngularCliAppConfig().tsconfig,
environment: ""
};

function supportES2015(tsConfigPath) {
Expand All @@ -33,23 +29,18 @@ function readTsConfig(tsConfigPath) {
return ts.parseJsonConfigFileContent(configResult.config, ts.sys, path.dirname(tsConfigPath), undefined, tsConfigPath);
}

function getEnvFile(suffix) {
if (suffix && suffix[0] !== ".") {
suffix = "." + suffix;
}

if (suffix === null) {
return;
}
function getEnvironmentFile(environment) {
if (typeof environment === "string") {
let fileName = helpers.root("src/" + getAngularCliAppConfig().environments[environment]);

let fileName = helpers.root(`src/environments/environment${suffix}.ts`);
if (fs.existsSync(fileName)) {
return fileName;
} else if (fs.existsSync((fileName = helpers.root("src/environments/environment.ts")))) {
console.warn(`Could not find environment file with suffix ${suffix}, loading default environment file`);
return fileName;
} else {
throw new Error("Environment file not found.");
if (fs.existsSync(fileName)) {
return fileName;
} else if (fs.existsSync((fileName = helpers.root("src/" + getAngularCliAppConfig().environmentSource)))) {
console.warn(`Could not find environment file for ${environment}, loading default environment file`);
return fileName;
} else {
throw new Error("Environment file not found.");
}
}
}

Expand All @@ -70,8 +61,136 @@ function rxjsAlias(supportES2015) {
}
}

/**
* Foreach installed NationalBankBelgium packages, read assets.json file in the root of the module.
* Based on assets.json file, fill an array with the needed assets for the module.
* Then return those to be read by CopyWebpackPlugin.
*/
function getNbbAssetsConfig() {
let customAssets = [];

const NBB_MODULES_PATH = "node_modules/@nationalbankbelgium";
const nbbPackages = ngCliUtils.getDirectoriesNames(helpers.root(NBB_MODULES_PATH));

for (const nbbPackage of nbbPackages) {
const ngCliConfigPath = helpers.root(NBB_MODULES_PATH + "/" + nbbPackage + "/" + ".ng-cli-config.json");

if (fs.existsSync(ngCliConfigPath)) {
const packageCliConfig = require(ngCliConfigPath);
const cliConfig = ngCliUtils.validateAngularCLIConfig(packageCliConfig);
if (cliConfig) {
if (cliConfig["apps"] && cliConfig["apps"][0] && cliConfig["apps"][0].assets) {
customAssets = [...customAssets, ...getCopyWebpackPluginConfig(cliConfig["apps"][0].assets)];
}
}
}
}

return customAssets;
}

/**
* Returns assets set in .angular-cli.json file of the project.
*/
function getApplicationAssetsConfig() {
const appConfig = getAngularCliAppConfig();

if (appConfig.assets) {
return getCopyWebpackPluginConfig(appConfig.assets);
}

return [];
}

function getAngularCliAppConfig() {
const applicationAngularCliConfigPath = helpers.root(".angular-cli.json");
if (fs.existsSync(applicationAngularCliConfigPath)) {
const angularCliConfig = require(applicationAngularCliConfigPath);
const cliConfig = ngCliUtils.validateAngularCLIConfig(angularCliConfig);
if (cliConfig) {
if (cliConfig["apps"] && cliConfig["apps"][0]) {
return cliConfig["apps"][0];
} else {
throw new Error("Angular-cli config apps is wrong. Please adapt it to follow Angular CLI way.");
}
} else {
throw new Error("Parsing " + applicationAngularCliConfigPath + " failed. Ensure the file is valid JSON.");
}
} else {
throw new Error(".angular-cli.json is not present. Please add this at the root your project because stark-build needs this.");
}
}

/**
* Return copyWebpack config based on angular cli assets declaration
*
* This code is coming from @angular/cli/models/webpack-configs/common.js
*/
function getCopyWebpackPluginConfig(assets) {
const appConfig = getAngularCliAppConfig();

const projectRoot = helpers.root("");
const appRoot = helpers.root(appConfig.root);

return assets.map(asset => {
// Convert all string assets to object notation.
asset = typeof asset === "string" ? { glob: asset } : asset;
// Add defaults.
// Input is always resolved relative to the appRoot.
asset.input = path.resolve(appRoot, asset.input || "").replace(/\\/g, "/");
asset.output = asset.output || "";
asset.glob = asset.glob || "";
// Prevent asset configurations from writing outside of the output path, except if the user
// specify a configuration flag.
// Also prevent writing outside the project path. That is not overridable.
// For info: Comparing to implementation of Angular, "buildOptions.outputPath" has been replaced by "appConfig.outDir"
const absoluteOutputPath = path.resolve(projectRoot, appConfig.outDir);
const absoluteAssetOutput = path.resolve(absoluteOutputPath, asset.output);
const outputRelativeOutput = path.relative(absoluteOutputPath, absoluteAssetOutput);
if (outputRelativeOutput.startsWith("..") || path.isAbsolute(outputRelativeOutput)) {
const projectRelativeOutput = path.relative(projectRoot, absoluteAssetOutput);
if (projectRelativeOutput.startsWith("..") || path.isAbsolute(projectRelativeOutput)) {
const message = "An asset cannot be written to a location outside the project.";
throw new Error(message);
}
if (!asset.allowOutsideOutDir) {
const message =
"An asset cannot be written to a location outside of the output path. " +
"You can override this message by setting the `allowOutsideOutDir` " +
"property on the asset to true in the CLI configuration.";
throw new Error(message);
}
}
// Prevent asset configurations from reading files outside of the project.
const projectRelativeInput = path.relative(projectRoot, asset.input);
if (projectRelativeInput.startsWith("..") || path.isAbsolute(projectRelativeInput)) {
const message = "An asset cannot be read from a location outside the project.";
throw new Error(message);
}
// Ensure trailing slash.
if (ngCliUtils.isDirectory(path.resolve(asset.input))) {
asset.input += "/";
}
// Convert dir patterns to globs.
if (ngCliUtils.isDirectory(path.resolve(asset.input, asset.glob))) {
asset.glob = asset.glob + "/**/*";
}
return {
context: asset.input,
to: asset.output,
from: {
glob: asset.glob,
dot: true
}
};
});
}

exports.DEFAULT_METADATA = DEFAULT_METADATA;
exports.supportES2015 = supportES2015;
exports.readTsConfig = readTsConfig;
exports.getEnvFile = getEnvFile;
exports.getEnvironmentFile = getEnvironmentFile;
exports.rxjsAlias = rxjsAlias;
exports.getNbbAssetsConfig = getNbbAssetsConfig;
exports.getApplicationAssetsConfig = getApplicationAssetsConfig;
exports.getAngularCliAppConfig = getAngularCliAppConfig;
39 changes: 39 additions & 0 deletions packages/stark-build/config/ng-cli-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const path = require("path");
const fs = require("fs");

function isDirectory(path) {
try {
return fs.statSync(path).isDirectory();
} catch (_) {
return false;
}
}

function getDirectoriesNames(source) {
return fs.readdirSync(source).filter(name => isDirectory(path.join(source, name)));
}

/**
* Validate passed angular cli config based on schema: @angular/cli/lib/config/schema.json
* If the serialized file is equal to the passed json, return the serialized config.
* Otherwise, it returns false.
*
* @param jsonConfig
* @returns {*}
*/
function validateAngularCLIConfig(jsonConfig) {
const SchemaClassFactory = require("@ngtools/json-schema").SchemaClassFactory;
const schema = require("@angular/cli/lib/config/schema.json");

const config = new (SchemaClassFactory(schema))(jsonConfig);
try {
const serializedConfig = JSON.parse(config.$$serialize("application/json"));
return serializedConfig;
} catch(error) {
return false;
}
}

exports.getDirectoriesNames = getDirectoriesNames;
exports.isDirectory = isDirectory;
exports.validateAngularCLIConfig = validateAngularCLIConfig;
34 changes: 10 additions & 24 deletions packages/stark-build/config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,16 @@ module.exports = function(options) {

const appNgcOptions = Object.assign({}, defaultNgcOptions, tsConfigApp.raw.angularCompilerOptions);

const environment = buildUtils.getEnvFile(METADATA.envFileSuffix);
const environment = buildUtils.getEnvironmentFile(METADATA.environment);

const buildOptimizerLoader = {
loader: "@angular-devkit/build-optimizer/webpack-loader",
options: {
sourceMap: true // TODO: apply based on tsConfig value?
}
};

const rootDir = buildUtils.getAngularCliAppConfig().root;

return {
/**
Expand Down Expand Up @@ -124,7 +126,7 @@ module.exports = function(options) {
/**
* An array of directory names to be resolved to the current directory
*/
modules: [helpers.root("src"), helpers.root("node_modules")],
modules: [helpers.root(rootDir), helpers.root("node_modules")],

/**
* Add support for pipeable operators.
Expand Down Expand Up @@ -203,7 +205,7 @@ module.exports = function(options) {
{
test: /\.css$/,
use: ["to-string-loader", "css-loader"],
exclude: [helpers.root("src", "styles")]
exclude: [helpers.root(rootDir, "styles")]
},

/**
Expand All @@ -215,7 +217,7 @@ module.exports = function(options) {
{
test: /\.scss$/,
use: ["to-string-loader", "css-loader", "sass-loader"],
exclude: [helpers.root("src", "styles")]
exclude: [helpers.root(rootDir, "styles")]
},

/**
Expand Down Expand Up @@ -247,7 +249,7 @@ module.exports = function(options) {
}
}
],
exclude: [helpers.root("src", "styles")]
exclude: [helpers.root(rootDir, "styles")]
},

/**
Expand Down Expand Up @@ -356,6 +358,9 @@ module.exports = function(options) {
*/
new CopyWebpackPlugin(
[
...buildUtils.getNbbAssetsConfig(),

...buildUtils.getApplicationAssetsConfig(),
// TODO uncomment this when is part of Stark
// // Stark assets
// {
Expand All @@ -367,25 +372,6 @@ module.exports = function(options) {
// from: helpers.rootStark("assets-base"),
// to: ""
// },

// Mdi svg file
{
from: "node_modules/@mdi/angular-material/mdi.svg",
to: "assets/icons/mdi.svg"
},

// Application assets
{
from: helpers.root("assets"),
to: "assets",
force: "true" // overwrite files already copied from Stark
},
// those assets are copied to the root of the target folder
{
from: helpers.root("assets-base"),
to: "",
force: "true" // overwrite files already copied from Stark
}
],
{
ignore: [
Expand Down
Loading

0 comments on commit 5a4445e

Please sign in to comment.