Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

refactor: update Android project path to support next runtime #310

Merged
merged 5 commits into from
Nov 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const path = require("path");
const { existsSync } = require("fs");

const { getPackageJson, getProjectDir, isAngular } = require("./projectHelpers");
const { getPackageJson, getProjectDir, isAngular, resolveAndroidAppPath } = require("./projectHelpers");

const PROJECT_DIR = getProjectDir({ nestingLvl: 2 });
const APP_DIR = path.join(PROJECT_DIR, "app");

Object.assign(exports, require('./plugins'));

if (isAngular({projectDir: PROJECT_DIR})) {
if (isAngular({ projectDir: PROJECT_DIR })) {
Object.assign(exports, require('./plugins/angular'));
}

Expand All @@ -31,7 +31,7 @@ exports.getAppPath = platform => {

return `platforms/ios/${sanitizedName}/app`;
} else if (/android/i.test(platform)) {
return path.join(PROJECT_DIR, "platforms/android/src/main/assets/app");
return resolveAndroidAppPath(PROJECT_DIR);
} else {
throw new Error(`Invalid platform: ${platform}`);
}
Expand Down
7 changes: 4 additions & 3 deletions plugins/NativeScriptSnapshotPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { resolve, join } = require("path");
const { closeSync, openSync } = require("fs");

const ProjectSnapshotGenerator = require("../snapshot/android/project-snapshot-generator");
const { resolveAndroidAppPath } = require("../projectHelpers");

exports.NativeScriptSnapshotPlugin = (function() {
function NativeScriptSnapshotPlugin(options) {
Expand Down Expand Up @@ -43,16 +44,16 @@ exports.NativeScriptSnapshotPlugin = (function() {

console.log(`\n Snapshotting bundle at ${inputFile}`);

const preparedAppRootPath = join(options.projectRoot, "platforms/android/src/main/assets");
const preprocessedInputFile = join(preparedAppRootPath, "app/_embedded_script_.js");
const preparedAppRootPath = resolveAndroidAppPath(this.options.projectRoot);
const preprocessedInputFile = join(preparedAppRootPath, "_embedded_script_.js");

return ProjectSnapshotGenerator.prototype.generate.call(this, {
inputFile,
preprocessedInputFile,
targetArchs: options.targetArchs,
useLibs: options.useLibs,
androidNdkPath: options.androidNdkPath,
tnsJavaClassesPath: join(preparedAppRootPath, "app/tns-java-classes.js")
tnsJavaClassesPath: join(preparedAppRootPath, "tns-java-classes.js")
}).then(() => {
// Make the original file empty
if (inputFile !== preprocessedInputFile) {
Expand Down
62 changes: 56 additions & 6 deletions projectHelpers.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,37 @@
const path = require("path");
const fs = require("fs");
const semver = require("semver");

const isTypeScript = ({projectDir, packageJson} = {}) => {
const isTypeScript = ({ projectDir, packageJson } = {}) => {
packageJson = packageJson || getPackageJson(projectDir);

return (
packageJson.dependencies &&
packageJson.dependencies.hasOwnProperty("typescript")
) || (
packageJson.devDependencies &&
packageJson.devDependencies.hasOwnProperty("typescript")
) || isAngular({packageJson});
packageJson.devDependencies &&
packageJson.devDependencies.hasOwnProperty("typescript")
) || isAngular({ packageJson });
};

const isAngular = ({projectDir, packageJson} = {}) => {
const isAngular = ({ projectDir, packageJson } = {}) => {
packageJson = packageJson || getPackageJson(projectDir);

return packageJson.dependencies && Object.keys(packageJson.dependencies)
.some(dependency => /^@angular\b/.test(dependency));
};

const getAndroidRuntimeVersion = (projectDir) => {
try {
const projectPackageJSON = getPackageJson(projectDir);

const version = projectPackageJSON["nativescript"]["tns-android"]["version"];
return version && toReleaseVersion(version);
} catch (e) {
return null;
}
}

const getPackageJson = projectDir => {
const packageJsonPath = getPackageJsonPath(projectDir);
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
Expand All @@ -29,7 +41,6 @@ const writePackageJson = (content, projectDir) => {
const packageJsonPath = getPackageJsonPath(projectDir);
fs.writeFileSync(packageJsonPath, JSON.stringify(content, null, 2))
}

const getProjectDir = ({ nestingLvl } = { nestingLvl: 0 }) => {
// INIT_CWD is available since npm 5.4
const initCwd = process.env.INIT_CWD;
Expand All @@ -54,6 +65,41 @@ const getProjectDir = ({ nestingLvl } = { nestingLvl: 0 }) => {
.reduce(dir => path.dirname(dir), __dirname);
};

const toReleaseVersion = version =>
version.replace(/-.*/, "");

const getAndroidProjectPath = ({androidPackageVersion, projectRoot}) => {
const ANDROID_PROJECT_PATH = "platforms/android";
if (projectRoot) {
androidPackageVersion = getAndroidRuntimeVersion(projectRoot);
}

return semver.lt(androidPackageVersion, "3.4.0") ?
ANDROID_PROJECT_PATH :
path.join(ANDROID_PROJECT_PATH, "app");
};


const resolveAndroidAppPath = projectDir => {
const RESOURCES_PATH = "src/main/assets/app";
const androidPackageVersion = getAndroidRuntimeVersion(projectDir);
const androidProjectPath = getAndroidProjectPath({androidPackageVersion});

return path.join(projectDir, androidProjectPath, RESOURCES_PATH);
};

const resolveAndroidConfigurationsPath = projectDir => {
const CONFIGURATIONS_DIR = "configurations";
const androidPackageVersion = getAndroidRuntimeVersion(projectDir);
const androidProjectPath = getAndroidProjectPath({androidPackageVersion});

const configurationsPath = semver.lt(androidPackageVersion, "3.3.0") ?
path.join(androidProjectPath, CONFIGURATIONS_DIR):
path.join(androidProjectPath, "build", CONFIGURATIONS_DIR);

return path.join(projectDir, configurationsPath);
};

const getPackageJsonPath = projectDir => path.resolve(projectDir, "package.json");

module.exports = {
Expand All @@ -62,4 +108,8 @@ module.exports = {
writePackageJson,
getPackageJson,
getProjectDir,
getAndroidRuntimeVersion,
getAndroidProjectPath,
resolveAndroidAppPath,
resolveAndroidConfigurationsPath,
};
88 changes: 48 additions & 40 deletions snapshot/android/project-snapshot-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ const {
createDirectory,
getJsonFile,
} = require("./utils");
const { getPackageJson } = require("../../projectHelpers");
const {
getPackageJson,
getAndroidRuntimeVersion,
getAndroidProjectPath,
resolveAndroidAppPath,
resolveAndroidConfigurationsPath,
} = require("../../projectHelpers");

const MIN_ANDROID_RUNTIME_VERSION = "3.0.0";
const VALID_ANDROID_RUNTIME_TAGS = Object.freeze(["next", "rc"]);
Expand All @@ -25,10 +31,9 @@ const resolveRelativePath = (path) => {
return null;
};

function ProjectSnapshotGenerator (options) {
function ProjectSnapshotGenerator(options) {
this.options = options = options || {};

options.projectRoot = resolveRelativePath(options.projectRoot) || process.cwd();
options.projectRoot = resolveRelativePath(options.projectRoot) || process.cwd();

console.log("Project root: " + options.projectRoot);
console.log("Snapshots build directory: " + this.getBuildPath());
Expand All @@ -37,29 +42,45 @@ function ProjectSnapshotGenerator (options) {
}
module.exports = ProjectSnapshotGenerator;

ProjectSnapshotGenerator.calculateBuildPath = function(projectRoot) {
return join(projectRoot, "platforms/android/snapshot-build/build");
ProjectSnapshotGenerator.calculateBuildPath = function (projectRoot) {
return join(
ProjectSnapshotGenerator.calculateProjectPath(projectRoot),
"snapshot-build",
"build"
);
}

ProjectSnapshotGenerator.prototype.getBuildPath = function() {
ProjectSnapshotGenerator.prototype.getBuildPath = function () {
return ProjectSnapshotGenerator.calculateBuildPath(this.options.projectRoot);
}

ProjectSnapshotGenerator.cleanSnapshotArtefacts = function(projectRoot) {
const platformPath = join(projectRoot, "platforms/android");
ProjectSnapshotGenerator.calculateProjectPath = function (projectRoot) {
const projectPath = getAndroidProjectPath({projectRoot});
return join(projectRoot, projectPath);
}

ProjectSnapshotGenerator.prototype.getProjectPath = function () {
return ProjectSnapshotGenerator.calculateProjectPath(this.options.projectRoot);
}

ProjectSnapshotGenerator.cleanSnapshotArtefacts = function (projectRoot) {
const platformPath = ProjectSnapshotGenerator.calculateProjectPath(projectRoot);

// Remove blob files from prepared folder
shelljs.rm("-rf", join(platformPath, "src/main/assets/snapshots"));

// Remove prepared include.gradle configurations
shelljs.rm("-rf", join(platformPath, "configurations/", SnapshotGenerator.SNAPSHOT_PACKAGE_NANE));
const configurationsPath = resolveAndroidConfigurationsPath(projectRoot);
shelljs.rm("-rf", join(configurationsPath, SnapshotGenerator.SNAPSHOT_PACKAGE_NANE));
}

ProjectSnapshotGenerator.installSnapshotArtefacts = function(projectRoot) {
ProjectSnapshotGenerator.installSnapshotArtefacts = function (projectRoot) {
const buildPath = ProjectSnapshotGenerator.calculateBuildPath(projectRoot);
const platformPath = join(projectRoot, "platforms/android");
const assetsPath = join(platformPath, "src/main/assets");
const configDestinationPath = join(platformPath, "configurations", SnapshotGenerator.SNAPSHOT_PACKAGE_NANE);
const platformPath = ProjectSnapshotGenerator.calculateProjectPath(projectRoot);

const appPath = resolveAndroidAppPath(projectRoot);
const configurationsPath = resolveAndroidConfigurationsPath(projectRoot);
const configDestinationPath = join(configurationsPath, SnapshotGenerator.SNAPSHOT_PACKAGE_NANE);

// Remove build folder to make sure that the apk will be fully rebuild
shelljs.rm("-rf", join(platformPath, "build"));
Expand All @@ -70,7 +91,7 @@ ProjectSnapshotGenerator.installSnapshotArtefacts = function(projectRoot) {

// Copy tns-java-classes.js
if (shelljs.test("-e", join(buildPath, "tns-java-classes.js"))) {
shelljs.cp(join(buildPath, "tns-java-classes.js"), join(assetsPath, "app/tns-java-classes.js"));
shelljs.cp(join(buildPath, "tns-java-classes.js"), join(appPath, "tns-java-classes.js"));
}

if (shelljs.test("-e", join(buildPath, "ndk-build/libs"))) {
Expand All @@ -84,11 +105,11 @@ ProjectSnapshotGenerator.installSnapshotArtefacts = function(projectRoot) {
else {
// useLibs = false
const blobsSrcPath = join(buildPath, "snapshots/blobs");
const blobsDestinationPath = join(assetsPath, "snapshots");
const appPackageJsonPath = join(assetsPath, "app/package.json");
const blobsDestinationPath = resolve(appPath, "../snapshots");
const appPackageJsonPath = join(appPath, "package.json");

// Copy the blobs in the prepared app folder
shelljs.cp("-R", blobsSrcPath + "/", join(assetsPath, "snapshots"));
shelljs.cp("-R", blobsSrcPath + "/", resolve(appPath, "../snapshots"));

/*
Rename TNSSnapshot.blob files to snapshot.blob files. The xxd tool uses the file name for the name of the static array. This is why the *.blob files are initially named TNSSnapshot.blob. After the xxd step, they must be renamed to snapshot.blob, because this is the filename that the Android runtime is looking for.
Expand Down Expand Up @@ -120,9 +141,8 @@ const fetchV8VersionsFile = () =>
});

const findV8Version = (runtimeVersion, v8VersionsMap) => {
const runtimeReleaseVersion = runtimeVersion.replace(/-.*/, "");
const runtimeRange = Object.keys(v8VersionsMap)
.find(range => semver.satisfies(runtimeReleaseVersion, range));
.find(range => semver.satisfies(runtimeVersion, range));

return v8VersionsMap[runtimeRange];
}
Expand All @@ -139,16 +159,16 @@ const getV8VersionsMap = runtimeVersion =>
}
});

ProjectSnapshotGenerator.prototype.getV8Version = function(generationOptions) {
ProjectSnapshotGenerator.prototype.getV8Version = function (generationOptions) {
return new Promise((resolve, reject) => {
const maybeV8Version = generationOptions.v8Version;
if (maybeV8Version) {
return resolve(maybeV8Version);
}

const runtimeVersion = this.getAndroidRuntimeVersion();
const runtimeVersion = getAndroidRuntimeVersion(this.options.projectRoot);
getV8VersionsMap(runtimeVersion)
.then(({ versionsMap, latest}) => {
.then(({ versionsMap, latest }) => {
const v8Version = findV8Version(runtimeVersion, versionsMap);

if (!v8Version && !latest) {
Expand All @@ -165,12 +185,10 @@ ProjectSnapshotGenerator.prototype.getV8Version = function(generationOptions) {
});
}

ProjectSnapshotGenerator.prototype.validateAndroidRuntimeVersion = function() {
const currentRuntimeVersion = this.getAndroidRuntimeVersion();

if (!currentRuntimeVersion ||
!existsSync(join(this.options.projectRoot, "platforms/android"))) {
ProjectSnapshotGenerator.prototype.validateAndroidRuntimeVersion = function () {
const currentRuntimeVersion = getAndroidRuntimeVersion(this.options.projectRoot);

if (!currentRuntimeVersion || !this.getProjectPath()) {
throw new Error("In order to generate a V8 snapshot you must have the \"android\" platform installed - to do so please run \"tns platform add android\".");
}

Expand All @@ -182,17 +200,7 @@ ProjectSnapshotGenerator.prototype.validateAndroidRuntimeVersion = function() {
}
}

ProjectSnapshotGenerator.prototype.getAndroidRuntimeVersion = function() {
try {
const projectPackageJSON = getPackageJson(this.options.projectRoot);

return projectPackageJSON["nativescript"]["tns-android"]["version"];
} catch(e) {
return null;
}
}

ProjectSnapshotGenerator.prototype.generateTnsJavaClassesFile = function(generationOptions) {
ProjectSnapshotGenerator.prototype.generateTnsJavaClassesFile = function (generationOptions) {
const tnsJavaClassesGenerator = new TnsJavaClassesGenerator();
return tnsJavaClassesGenerator.generate({
projectRoot: this.options.projectRoot,
Expand All @@ -201,7 +209,7 @@ ProjectSnapshotGenerator.prototype.generateTnsJavaClassesFile = function(generat
});
}

ProjectSnapshotGenerator.prototype.generate = function(generationOptions) {
ProjectSnapshotGenerator.prototype.generate = function (generationOptions) {
generationOptions = generationOptions || {};

console.log("Running snapshot generation with the following arguments: ");
Expand Down