diff --git a/package.json b/package.json index 1b061d08..0b9de652 100644 --- a/package.json +++ b/package.json @@ -41,9 +41,10 @@ }, "dependencies": { "minimatch": "^3.0.4", + "nativescript-hook": "0.2.2", + "schema-utils": "^0.4.3", "semver": "^5.4.1", - "shelljs": "^0.6.0", - "nativescript-hook": "0.2.2" + "shelljs": "^0.6.0" }, "devDependencies": { "@ngtools/webpack": "^1.8.0", diff --git a/plugins/NativeScriptSnapshotPlugin.js b/plugins/NativeScriptSnapshotPlugin/index.js similarity index 62% rename from plugins/NativeScriptSnapshotPlugin.js rename to plugins/NativeScriptSnapshotPlugin/index.js index e0570247..54d17047 100644 --- a/plugins/NativeScriptSnapshotPlugin.js +++ b/plugins/NativeScriptSnapshotPlugin/index.js @@ -1,18 +1,16 @@ const { resolve, join } = require("path"); const { closeSync, openSync } = require("fs"); +const validateOptions = require("schema-utils"); -const ProjectSnapshotGenerator = require("../snapshot/android/project-snapshot-generator"); -const { resolveAndroidAppPath } = require("../projectHelpers"); +const ProjectSnapshotGenerator = require("../../snapshot/android/project-snapshot-generator"); +const { resolveAndroidAppPath } = require("../../projectHelpers"); +const schema = require("./options.json"); exports.NativeScriptSnapshotPlugin = (function() { function NativeScriptSnapshotPlugin(options) { - ProjectSnapshotGenerator.call(this, options); // Call the parent constructor - - if (!this.options.chunk) { - throw new Error("No chunk specified."); - } + NativeScriptSnapshotPlugin.validateSchema(options); - console.dir() + ProjectSnapshotGenerator.call(this, options); // Call the parent constructor if (this.options.webpackConfig) { if (this.options.webpackConfig.output && this.options.webpackConfig.output.libraryTarget) { @@ -29,15 +27,28 @@ exports.NativeScriptSnapshotPlugin = (function() { } } + NativeScriptSnapshotPlugin.validateSchema = function(options) { + if (!options.chunk) { + const error = NativeScriptSnapshotPlugin.extendError({ message: `No chunk specified!` }); + throw error; + } + + try { + validateOptions(schema, options, "NativeScriptSnapshotPlugin"); + } catch (error) { + throw new Error(error.message); + } + } + // inherit ProjectSnapshotGenerator NativeScriptSnapshotPlugin.prototype = Object.create(ProjectSnapshotGenerator.prototype); NativeScriptSnapshotPlugin.prototype.constructor = NativeScriptSnapshotPlugin; - NativeScriptSnapshotPlugin.prototype.getTnsJavaClassesBuildPath = function() { + NativeScriptSnapshotPlugin.prototype.getTnsJavaClassesBuildPath = function () { return resolve(this.getBuildPath(), "../tns-java-classes.js"); } - NativeScriptSnapshotPlugin.prototype.generate = function(webpackChunk) { + NativeScriptSnapshotPlugin.prototype.generate = function (webpackChunk) { const options = this.options; const inputFile = join(options.webpackConfig.output.path, webpackChunk.files[0]); @@ -62,7 +73,7 @@ exports.NativeScriptSnapshotPlugin = (function() { }); } - NativeScriptSnapshotPlugin.prototype.apply = function(compiler) { + NativeScriptSnapshotPlugin.prototype.apply = function (compiler) { const options = this.options; // Generate tns-java-classes.js file @@ -73,26 +84,38 @@ exports.NativeScriptSnapshotPlugin = (function() { }); // Generate snapshots - compiler.plugin("after-emit", function(compilation, callback) { + compiler.plugin("after-emit", function (compilation, callback) { debugger; const chunkToSnapshot = compilation.chunks.find(chunk => chunk.name == options.chunk); if (!chunkToSnapshot) { - throw new Error(`No chunk named '${options.chunk}' found.`); + const error = NativeScriptSnapshotPlugin.extendError({ message: `No chunk named '${options.chunk}' found.` }); + compilation.errors.push(error); + return callback(); } this.generate(chunkToSnapshot) .then(() => { console.log("Successfully generated snapshots!"); - callback(); + return callback(); }) .catch((error) => { - console.error("Snapshot generation failed with the following error:"); - console.error(error); - callback(); + const extendedError = NativeScriptSnapshotPlugin.extendError({ originalError: error }); + compilation.errors.push(extendedError); + return callback(); }); - }.bind(this)); } + NativeScriptSnapshotPlugin.extendError = function ({ originalError, message } = {}) { + const header = `NativeScriptSnapshot. Snapshot generation failed!\n`; + if (originalError) { + originalError.message = `${header}${originalError.message}`; + return originalError; + } + + const newMessage = message ? `${header}${message}` : header; + return new Error(newMessage); + }; + return NativeScriptSnapshotPlugin; })(); diff --git a/plugins/NativeScriptSnapshotPlugin/options.json b/plugins/NativeScriptSnapshotPlugin/options.json new file mode 100644 index 00000000..fb1b0560 --- /dev/null +++ b/plugins/NativeScriptSnapshotPlugin/options.json @@ -0,0 +1,31 @@ +{ + "type": "object", + "properties": { + "chunk": { + "type": "string" + }, + "projectRoot": { + "type": "string" + }, + "webpackConfig": {}, + "targetArchs": { + "type": "array" + }, + "tnsJavaClassesOptions": { + "additionalProperties": false, + "type": "object", + "properties": { + "modules": { + "type": "array" + }, + "packages": { + "type": "array" + } + } + }, + "useLibs": { + "type": "boolean" + } + }, + "additionalProperties": false +} diff --git a/snapshot/android/project-snapshot-generator.js b/snapshot/android/project-snapshot-generator.js index 9a4ca6ef..a856e0fa 100644 --- a/snapshot/android/project-snapshot-generator.js +++ b/snapshot/android/project-snapshot-generator.js @@ -238,7 +238,14 @@ ProjectSnapshotGenerator.prototype.generate = function (generationOptions) { // Generate snapshots const generator = new SnapshotGenerator({ buildPath: this.getBuildPath() }); + const noV8VersionFoundMessage = `Cannot find suitable v8 version!`; + let shouldRethrow = false; return this.getV8Version(generationOptions).then(v8Version => { + shouldRethrow = true; + if (!v8Version) { + throw new Error(noV8VersionFoundMessage); + } + return generator.generate({ snapshotToolsPath, inputFile: generationOptions.inputFile || join(this.options.projectRoot, "__snapshot.js"), @@ -259,6 +266,8 @@ ProjectSnapshotGenerator.prototype.generate = function (generationOptions) { } }); }).catch(error => { - throw new Error(`Cannot find suitable v8 version! Original error: ${error.message || error}`); + throw shouldRethrow ? + error : + new Error(`${noV8VersionFoundMessage} Original error: ${error.message || error}`); }); } diff --git a/snapshot/android/snapshot-generator.js b/snapshot/android/snapshot-generator.js index 8aa7d4a3..a318c583 100644 --- a/snapshot/android/snapshot-generator.js +++ b/snapshot/android/snapshot-generator.js @@ -100,16 +100,18 @@ SnapshotGenerator.prototype.runMksnapshotTool = function(snapshotToolsPath, inpu return new Promise((resolve, reject) => { const child = child_process.exec(command, {encoding: "utf8"}, (error, stdout, stderr) => { - console.log(`${stdout}`); + const errorHeader = `Target architecture: ${androidArch}\n`; + if (stderr.length) { - console.error("***** SNAPSHOT GENERATION FOR " + androidArch + " FAILED! *****"); - console.error(stderr); - return reject(stderr); - } - if (error) { - return reject(error); + const message = `${errorHeader}${stderr}`; + reject(new Error(message)); + } else if (error) { + error.message = `${errorHeader}${error.message}`; + reject(error); + } else { + console.log(stdout); + resolve(); } - return resolve(); }) }).then(() => { // Generate .c file