From 325cb90fa7c0d7c431a6ceb45337212d9909768b Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Wed, 8 Feb 2017 13:31:00 +0200 Subject: [PATCH 1/6] fix: run `tns-xml-loader` before `@ngtools` loader (#66) This is needed due to changes in the behaviour of `@ngtools/webpack` v1.2.4 fixes #64 --- tns-xml-loader.js | 5 ++++- webpack.common.js.angular.template | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tns-xml-loader.js b/tns-xml-loader.js index f3671760..a580a395 100644 --- a/tns-xml-loader.js +++ b/tns-xml-loader.js @@ -61,7 +61,10 @@ function getTemplateSource(path, source) { return source; } else if (isComponent(path)) { const templateMatcher = /template\s*:\s*([`'"])((.|\n)*?)\1/; - return templateMatcher.test(source) ? source.replace(templateMatcher, "$2") : ""; + let match = templateMatcher.exec(source); + + return match ? match[2] : ""; + } else { throw new Error(`The NativeScript XML loader must be used with HTML, XML or TypeScript files`); } diff --git a/webpack.common.js.angular.template b/webpack.common.js.angular.template index 550163c3..266bcc3e 100644 --- a/webpack.common.js.angular.template +++ b/webpack.common.js.angular.template @@ -135,9 +135,9 @@ module.exports = function (platform, destinationApp) { { test: /\.ts$/, loaders: [ - "nativescript-dev-webpack/tns-xml-loader", "nativescript-dev-webpack/tns-aot-loader", "@ngtools/webpack", + "nativescript-dev-webpack/tns-xml-loader", ] }, // SASS support From e80cbdc925343d5802b447422224f55972a88b5f Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Wed, 8 Feb 2017 13:31:32 +0200 Subject: [PATCH 2/6] feat(scripts): add ns-bundle and verify-bundle (#69) --- bin/install-ns-webpack | 1 + bin/ns-bundle | 108 +++++++++++++++++++++++++++++++++++++++ bin/ns-bundle.cmd | 1 + bin/ns-verify-bundle | 101 ++++++++++++++++++++++++++++++++++++ bin/ns-verify-bundle.cmd | 1 + bin/remove-ns-webpack | 1 + installer.js | 34 ++++++++---- package.json | 4 +- postinstall.js | 1 + 9 files changed, 241 insertions(+), 11 deletions(-) create mode 100644 bin/ns-bundle create mode 100644 bin/ns-bundle.cmd create mode 100644 bin/ns-verify-bundle create mode 100644 bin/ns-verify-bundle.cmd diff --git a/bin/install-ns-webpack b/bin/install-ns-webpack index 01adbf50..7b330b80 100644 --- a/bin/install-ns-webpack +++ b/bin/install-ns-webpack @@ -2,5 +2,6 @@ var installer = require("../installer"); installer.addProjectFiles(); +installer.removeDeprecatedNpmScripts(); installer.addNpmScripts(); installer.addProjectDependencies(); diff --git a/bin/ns-bundle b/bin/ns-bundle new file mode 100644 index 00000000..1f8241bd --- /dev/null +++ b/bin/ns-bundle @@ -0,0 +1,108 @@ +#!/usr/bin/env node + +const spawn = require("child_process").spawn; +const path = require("path"); + +const PROJECT_DIR = path.resolve(__dirname, "../../../"); + +if (!process.env.npm_config_argv) { + throwError({message: "No flags provided."}); +} + +const npmArgs = JSON.parse(process.env.npm_config_argv).original; +const flags = npmArgs.filter(a => a.startsWith("--")).map(a => a.substring(2)); +const options = getOptions(flags); + +execute(options); + +function execute(options) { + let commands = [ + () => runTns(options.command, options.platform), + ]; + + if (options.bundle) { + commands.unshift(() => webpack(options.platform)); + } + + return commands.reduce((current, next) => current.then(next), Promise.resolve()); +} + +function webpack(platform) { + return new Promise(function (resolve, reject) { + console.log(`Running webpack for ${platform}...`); + + spawnChildProcess("tns", "clean-app", platform) + .then(() => spawnChildProcess("webpack", `--config=webpack.${platform}.js`, "--progress")) + .then(resolve) + .catch(throwError); + }); +} + +function runTns(command, platform) { + console.log(`Running tns ${command}...`); + return new Promise((resolve, reject) => { + spawnChildProcess("tns", command, platform, "--bundle", "--disable-npm-install") + .then(resolve) + .catch(throwError); + }); +} + +function getOptions(flags) { + let options = {}; + options.platform = getPlatform(flags); + options.command = getCommand(flags); + options.bundle = !flags.includes("nobundle"); + + return options; +} + +function getPlatform(flags) { + if (flags.includes("android") && flags.includes("ios")) { + throwError({message: "You cannot use both --android and --ios flags!"}); + } + + if (flags.includes("android")) { + return "android"; + } else if (flags.includes("ios")) { + return "ios"; + } else { + throwError({message: "You must provide a target platform! Use either --android, or --ios flag."}); + } +} + +function getCommand(flags) { + if (flags.includes("start-app") && flags.includes("build-app")) { + throwError({message: "You cannot use both --start-app and --build-app flags!"}); + } + + if (flags.includes("start-app")) { + return "run"; + } else if (flags.includes("build-app")) { + return "build"; + } else { + throwError({message: "You must provide either --start-app, or --build-app flag!"}); + } +} + +function spawnChildProcess(command, ...args) { + return new Promise((resolve, reject) => { + const childProcess = spawn(command, args, { stdio: "inherit", pwd: PROJECT_DIR }); + + childProcess.on("close", (code) => { + if (code === 0) { + resolve(); + } else { + reject({ + code, + message: `child process exited with code ${code}`, + }); + } + }); + }); +} + +function throwError(error) { + console.error(error.message); + process.exit(error.code || 1); +} + diff --git a/bin/ns-bundle.cmd b/bin/ns-bundle.cmd new file mode 100644 index 00000000..78076684 --- /dev/null +++ b/bin/ns-bundle.cmd @@ -0,0 +1 @@ +@node %~dp0\ns-bundle %* diff --git a/bin/ns-verify-bundle b/bin/ns-verify-bundle new file mode 100644 index 00000000..c423e746 --- /dev/null +++ b/bin/ns-verify-bundle @@ -0,0 +1,101 @@ +#!/usr/bin/env node + +const path = require("path"); +const fs = require("fs"); + +const PROJECT_DIR = path.resolve(__dirname, "../../../"); +console.log(PROJECT_DIR); +const APP_ID = require(path.resolve(PROJECT_DIR, "./package.json")).nativescript.id; +const APP_NAME = APP_ID.substring(APP_ID.lastIndexOf(".") + 1); +const PROJECT_PATHS = { + android: path.resolve(PROJECT_DIR, "platforms/android/src/main/assets/app"), + ios: path.resolve(PROJECT_DIR, `platforms/ios/build/emulator/${APP_NAME}.app/app`), +}; + +const npmArgs = JSON.parse(process.env.npm_config_argv).original; +const flags = npmArgs.filter(a => a.startsWith("--")).map(a => a.substring(2)); +const file = getTargetFile(flags); +const platform = getPlatform(flags); + +const filePath = path.resolve(PROJECT_PATHS[platform], file); + +console.log(`Checking ${filePath} exists`); +if (!fs.existsSync(filePath)) { + throwError({message: `${filePath} doesn not exist!`}); +} + +const maxSize = getMaxSize(flags); +if (maxSize) { + checkFileSizeIsUnder(filePath, maxSize).then().catch(throwError); +} + +function getTargetFile(flags) { + let fileFlags = flags.filter(f => f.startsWith("file=")); + + if (fileFlags.length != 1) { + throwError({message: "You must provide a target file!"}); + } + + fileFlags = fileFlags[0]; + return fileFlags.substring(fileFlags.indexOf("=") + 1); +} + +function getMaxSize(flags) { + let sizeFlags = flags.filter(f => f.startsWith("maxSize=")); + + if (sizeFlags.length == 0) { + return; + } else if (sizeFlags.length > 1) { + throwError({message: "You must provide 0 or 1 maxSize flags!"}); + } + + sizeFlags = sizeFlags[0]; + return sizeFlags.substring(sizeFlags.indexOf("=") + 1); +} + +function getPlatform(flags) { + if (flags.includes("android") && flags.includes("ios")) { + throwError({message: "You cannot use both --android and --ios flags!"}); + } + + if (flags.includes("android")) { + return "android"; + } else if (flags.includes("ios")) { + return "ios"; + } else { + throwError({message: "You must provide a target platform! Use either --android, or --ios flag."}); + } +} + +function checkFileSizeIsUnder(fileName, sizeInBytes) { + console.log(`Checking ${fileName} size is under ${sizeInBytes}`); + + return new Promise((resolve, reject) => { + readFile(fileName) + .then(content => { + if (content.length <= sizeInBytes) { + resolve(); + } else { + reject({message: `File "${fileName}" exceeded file size of "${sizeInBytes}".`}); + } + }); + }); +} + +function readFile(fileName) { + return new Promise((resolve, reject) => { + fs.readFile(fileName, "utf-8", (err, data) => { + if (err) { + reject(err); + } else { + resolve(data); + } + }); + }); +} + +function throwError(error) { + console.error(error.message); + process.exit(error.code || 1); +} + diff --git a/bin/ns-verify-bundle.cmd b/bin/ns-verify-bundle.cmd new file mode 100644 index 00000000..0a479f43 --- /dev/null +++ b/bin/ns-verify-bundle.cmd @@ -0,0 +1 @@ +@node %~dp0\ns-verify-bundle %* diff --git a/bin/remove-ns-webpack b/bin/remove-ns-webpack index d3daba03..b7677950 100644 --- a/bin/remove-ns-webpack +++ b/bin/remove-ns-webpack @@ -2,5 +2,6 @@ var installer = require("../installer"); installer.removeProjectFiles(); +installer.removeDeprecatedNpmScripts(); installer.removeNpmScripts(); installer.removeProjectDependencies(); diff --git a/installer.js b/installer.js index ebf97ea6..912b427d 100644 --- a/installer.js +++ b/installer.js @@ -78,16 +78,24 @@ exports.removeProjectFiles = removeProjectFiles; function getScriptTemplates() { return { - "clean-[PLATFORM]": "tns clean-app [PLATFORM]", - "prewebpack-[PLATFORM]": "npm run clean-[PLATFORM]", - "webpack-[PLATFORM]": "webpack --config=webpack.[PLATFORM].js --progress", - "prestart-[PLATFORM]-bundle": "npm run webpack-[PLATFORM]", - "start-[PLATFORM]-bundle": "tns run [PLATFORM] --bundle --disable-npm-install", - "prebuild-[PLATFORM]-bundle": "npm run webpack-[PLATFORM]", - "build-[PLATFORM]-bundle": "tns build [PLATFORM] --bundle --disable-npm-install", + "ns-bundle": "ns-bundle", + "start-[PLATFORM]-bundle": "npm run ns-bundle --[PLATFORM] --start-app", + "build-[PLATFORM]-bundle": "npm run ns-bundle --[PLATFORM] --build-app", }; } +function getDeprecatedScriptTemplates() { + return [ + "clean-[PLATFORM]", + "prewebpack-[PLATFORM]", + "webpack-[PLATFORM]", + "prestart-[PLATFORM]-bundle", + "start-[PLATFORM]-bundle", + "prebuild-[PLATFORM]-bundle", + "build-[PLATFORM]-bundle", + ] +} + function addNpmScripts() { var scriptTemplates = getScriptTemplates(); Object.keys(scriptTemplates).forEach(function(templateName) { @@ -96,9 +104,15 @@ function addNpmScripts() { } exports.addNpmScripts = addNpmScripts; -function removeNpmScripts() { - var scriptTemplates = getScriptTemplates(); - Object.keys(scriptTemplates).forEach(function(templateName) { +function removeDeprecatedNpmScripts() { + removeNpmScripts(getDeprecatedScriptTemplates()); +} + +exports.removeDeprecatedNpmScripts = removeDeprecatedNpmScripts; + +function removeNpmScripts(scriptTemplates) { + var scriptTemplates = scriptTemplates || Object.keys(getScriptTemplates()); + scriptTemplates.forEach(function(templateName) { removePlatformScripts(packageJson, templateName); }); } diff --git a/package.json b/package.json index 862e4bc8..4adf30bd 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,9 @@ }, "bin": { "install-ns-webpack": "./bin/install-ns-webpack", - "remove-ns-webpack": "./bin/remove-ns-webpack" + "remove-ns-webpack": "./bin/remove-ns-webpack", + "ns-bundle": "./bin/ns-bundle", + "ns-verify-bundle": "./bin/ns-verify-bundle" }, "dependencies": {}, "devDependencies": {} diff --git a/postinstall.js b/postinstall.js index d92ae7b4..e252b2b6 100644 --- a/postinstall.js +++ b/postinstall.js @@ -1,5 +1,6 @@ var installer = require("./installer"); installer.addProjectFiles(); +installer.removeDeprecatedNpmScripts(); installer.addNpmScripts(); installer.addProjectDependencies(); From 17b9d8215d1e2003137300259c5b0b31916ee786 Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Thu, 9 Feb 2017 10:50:06 +0200 Subject: [PATCH 3/6] fix(scripts): respect tns build/run args passed to ns-bundle (#71) --- bin/ns-bundle | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/bin/ns-bundle b/bin/ns-bundle index 1f8241bd..e2973b2c 100644 --- a/bin/ns-bundle +++ b/bin/ns-bundle @@ -10,9 +10,25 @@ if (!process.env.npm_config_argv) { } const npmArgs = JSON.parse(process.env.npm_config_argv).original; +const tnsArgs = getTnsArgs(npmArgs); const flags = npmArgs.filter(a => a.startsWith("--")).map(a => a.substring(2)); const options = getOptions(flags); +function getTnsArgs(args) { + let other = [ + "run", + "ns-bundle", + "--android", + "--ios", + "--build-app", + "--start-app", + "--uglify", + "--nobundle", + ]; + + return args.filter(a => !other.includes(a)); +} + execute(options); function execute(options) { @@ -41,7 +57,7 @@ function webpack(platform) { function runTns(command, platform) { console.log(`Running tns ${command}...`); return new Promise((resolve, reject) => { - spawnChildProcess("tns", command, platform, "--bundle", "--disable-npm-install") + spawnChildProcess("tns", command, platform, "--bundle", "--disable-npm-install", ...tnsArgs) .then(resolve) .catch(throwError); }); From b9d6a3fbb76482f375cedade374cf9acf52ba6c0 Mon Sep 17 00:00:00 2001 From: Stanimira Vlaeva Date: Thu, 9 Feb 2017 14:07:07 +0200 Subject: [PATCH 4/6] fix(uglify): exclude tns 3.0 listeners from mangling (#72) --- index.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/index.js b/index.js index 92c44433..900e88fb 100644 --- a/index.js +++ b/index.js @@ -182,6 +182,27 @@ exports.uglifyMangleExcludes = [ "TapAndDoubleTapGestureListener", "WebViewClientClassInner", + // tns 3.0 + "CheckedChangeListener", + "ClickListener", + "CloseListener", + "DateChangedListener", + "DisableUserInteractionListener", + "EditorActionListener", + "FocusChangeListener", + "Formatter", + "ImageLoadedListener", + "ItemClickListener", + "MenuItemClickListener", + "QueryTextListener", + "SeekBarChangeListener", + "TabChangeListener", + "TabContentFactory", + "TextWatcher", + "TimeChangedListener", + "TouchListener", + "ValueChangeListener", + //iOS native class extenders "AnimatedTransitioning", "AnimationDelegateImpl", From f9ed21887dc0bf2ec0ceda30fe7d8a8da2a19bb3 Mon Sep 17 00:00:00 2001 From: Hristo Deshev Date: Thu, 16 Feb 2017 17:57:11 +0200 Subject: [PATCH 5/6] Extend existing tsconfig. Avoid duplication, don't force TS lib selection. --- tsconfig.aot.json.template | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/tsconfig.aot.json.template b/tsconfig.aot.json.template index af686844..b1221e9a 100644 --- a/tsconfig.aot.json.template +++ b/tsconfig.aot.json.template @@ -1,15 +1,6 @@ { + "extend": "./tsconfig", "compilerOptions": { - "target": "es5", - "module": "es2015", - "moduleResolution": "node", - "sourceMap": true, - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "removeComments": false, - "noImplicitAny": false, - "suppressImplicitAnyIndexErrors": true, - "types": [], "baseUrl": ".", "paths": { "ui/*": ["node_modules/tns-core-modules/ui/*"], @@ -35,13 +26,8 @@ "image-asset": ["node_modules/tns-core-modules/image-asset"], "connectivity": ["node_modules/tns-core-modules/connectivity"], "globals": ["node_modules/tns-core-modules/globals"] - } - }, - "exclude": [ - "node_modules", - "platforms" - ], + }, "angularCompilerOptions": { "skipMetadataEmit": true, "genDir": "./" From 347e8ca1084ac577c8a7c656735ba19f59b20af6 Mon Sep 17 00:00:00 2001 From: Hristo Deshev Date: Thu, 16 Feb 2017 17:57:47 +0200 Subject: [PATCH 6/6] 0.3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4adf30bd..a48482e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nativescript-dev-webpack", - "version": "0.3.3", + "version": "0.3.4", "main": "index", "description": "", "homepage": "http://www.telerik.com",