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

fix: Allow using the plugin via symlink #501

Merged
merged 4 commits into from
Apr 23, 2018
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
35 changes: 23 additions & 12 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@ const path = require("path");
const { existsSync } = require("fs");

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

const PROJECT_DIR = getProjectDir();
const APP_PATH = path.join(PROJECT_DIR, APP_DIR);

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

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

exports.getAotEntryModule = function (appDirectory = APP_PATH) {
exports.getAotEntryModule = function (appDirectory) {
verifyEntryModuleDirectory(appDirectory);

const entry = getPackageJsonEntry(appDirectory);
const aotEntry = `${entry}.aot.ts`;

Expand All @@ -36,7 +35,9 @@ exports.getAotEntryModule = function (appDirectory = APP_PATH) {
// Exported for backwards compatibility with {N} 3
exports.uglifyMangleExcludes = require("./mangle-excludes");

exports.getEntryModule = function (appDirectory = APP_PATH) {
exports.getEntryModule = function (appDirectory) {
verifyEntryModuleDirectory(appDirectory);

const entry = getPackageJsonEntry(appDirectory);

const tsEntryPath = path.resolve(appDirectory, `${entry}.ts`);
Expand All @@ -49,14 +50,14 @@ exports.getEntryModule = function (appDirectory = APP_PATH) {
return entry;
};

exports.getAppPath = platform => {
exports.getAppPath = (platform, projectDir) => {
if (isIos(platform)) {
const appName = path.basename(PROJECT_DIR);
const appName = path.basename(projectDir);
const sanitizedName = sanitize(appName);

return `platforms/ios/${sanitizedName}/app`;
} else if (isAndroid(platform)) {
return resolveAndroidAppPath(PROJECT_DIR);
return resolveAndroidAppPath(projectDir);
} else {
throw new Error(`Invalid platform: ${platform}`);
}
Expand All @@ -77,3 +78,13 @@ function getPackageJsonEntry(appDirectory) {

return entry.replace(/\.js$/i, "");
}

function verifyEntryModuleDirectory(appDirectory) {
if (!appDirectory) {
throw new Error("Path to app directory is not specified. Unable to find entry module.");
}

if (!existsSync(appDirectory)) {
throw new Error(`The specified path to app directory ${appDirectory} does not exist. Unable to find entry module.`);
}
}
167 changes: 85 additions & 82 deletions plugins/NativeScriptAngularCompilerPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,104 @@
import * as path from "path";
import { PlatformFSPlugin, PlatformFSPluginOptions, mapFileSystem } from "./PlatformFSPlugin";
import * as hook from "nativescript-hook";
import * as ngToolsWebpack from "@ngtools/webpack";
module.exports = (projectDir) => {
// During development the nativescript-dev-webpack plugin may have @ngtools/webpack installed locally as dev-dependency,
// we want to make sure we are using the one installed in the actual app
const ngToolsWebpackDir = path.join(projectDir, "node_modules", "@ngtools", "webpack");
const appNgToolsWebpack: typeof ngToolsWebpack = require(ngToolsWebpackDir);
const AngularCompilerPlugin: typeof ngToolsWebpack.AngularCompilerPlugin = appNgToolsWebpack.AngularCompilerPlugin;

// During development the nativescript-dev-webpack plugin may have @ngtools/webpack installed locally as dev-dependency,
// we want to make sure we are using the one installed in the actual app
const projectDir = hook(path.join(__dirname, "..")).findProjectDir();
const ngToolsWebpackDir = path.join(projectDir, "node_modules", "@ngtools", "webpack");
const appNgToolsWebpack: typeof ngToolsWebpack = require(ngToolsWebpackDir);
class NativeScriptAngularCompilerPlugin extends AngularCompilerPlugin {
readonly options: NativeScriptAngularCompilerPluginOptions;
readonly platform: string;

export const AngularCompilerPlugin: typeof ngToolsWebpack.AngularCompilerPlugin = appNgToolsWebpack.AngularCompilerPlugin;

export interface NativeScriptAngularCompilerPluginOptions extends ngToolsWebpack.AngularCompilerPluginOptions {
platformOptions?: PlatformFSPluginOptions;
}

export interface CompiledFile {
outputText: string;
sourceMap: string;
errorDependencies: string[];
}

export class NativeScriptAngularCompilerPlugin extends AngularCompilerPlugin {
readonly options: NativeScriptAngularCompilerPluginOptions;
readonly platform: string;

get __compilerHost() {
// Accessing private API of the AngularCompilerPlugin
// We need this to augment at least the "resourceNameToFileName" so we can map
// component.css to component.android.css etc. for platform specific css and html resources.
return (<any>this)._compilerHost;
}
get __compilerHost() {
// Accessing private API of the AngularCompilerPlugin
// We need this to augment at least the "resourceNameToFileName" so we can map
// component.css to component.android.css etc. for platform specific css and html resources.
return (<any>this)._compilerHost;
}

constructor(options: NativeScriptAngularCompilerPluginOptions) {
super(options);
constructor(options: NativeScriptAngularCompilerPluginOptions) {
super(options);

this.platform = (this.options.platformOptions && this.options.platformOptions.platform) || undefined;
const platform = this.platform;
this.platform = (this.options.platformOptions && this.options.platformOptions.platform) || undefined;
const platform = this.platform;

if (platform) {
// https://github.com/angular/angular/blob/7bfeac746e717d02e062fe4a65c008060b8b662c/packages/compiler-cli/src/transformers/api.ts
const resourceNameToFileName = this.__compilerHost.resourceNameToFileName || function(file, relativeTo) {
const resolved = path.resolve(path.dirname(relativeTo), file);
if (this.fileExists(resolved)) {
if (platform) {
// https://github.com/angular/angular/blob/7bfeac746e717d02e062fe4a65c008060b8b662c/packages/compiler-cli/src/transformers/api.ts
const resourceNameToFileName = this.__compilerHost.resourceNameToFileName || function (file, relativeTo) {
const resolved = path.resolve(path.dirname(relativeTo), file);
if (this.fileExists(resolved)) {
return resolved;
} else {
return null;
}
};
this.__compilerHost.resourceNameToFileName = function (file, relativeTo) {
const parsed = path.parse(file);
const platformFile = parsed.name + "." + platform + parsed.ext;
let resolved;
try {
resolved = resourceNameToFileName.call(this, platformFile, relativeTo);
} catch (e) {
}
resolved = resolved || resourceNameToFileName.call(this, file, relativeTo);
resolved = resolved && resolved.replace(/\\/g, "/");
return resolved;
} else {
return null;
}
};
this.__compilerHost.resourceNameToFileName = function(file, relativeTo) {
const parsed = path.parse(file);
const platformFile = parsed.name + "." + platform + parsed.ext;
let resolved;
try {
resolved = resourceNameToFileName.call(this, platformFile, relativeTo);
} catch(e) {
}
resolved = resolved || resourceNameToFileName.call(this, file, relativeTo);
resolved = resolved && resolved.replace(/\\/g, "/");
return resolved;
};
};
}
}
}

getCompiledFile(this: NativeScriptAngularCompilerPlugin, file: string): CompiledFile {
try {
if (this.platform) {
const parsed = path.parse(file);
const platformFile = parsed.dir + path.sep + parsed.name + "." + this.platform + parsed.ext;
const result = super.getCompiledFile(platformFile);
return result;
getCompiledFile(this: NativeScriptAngularCompilerPlugin, file: string): CompiledFile {
try {
if (this.platform) {
const parsed = path.parse(file);
const platformFile = parsed.dir + path.sep + parsed.name + "." + this.platform + parsed.ext;
const result = super.getCompiledFile(platformFile);
return result;
}
} catch (e) {
}
} catch(e) {
return super.getCompiledFile(file);
}
return super.getCompiledFile(file);
}

apply(compiler) {
super.apply(compiler);
if (this.options.platformOptions && this.options.platformOptions.platform && this.options.platformOptions.platforms) {
compiler.plugin('environment', () => {
compiler.inputFileSystem = mapFileSystem({
fs: compiler.inputFileSystem,
context: compiler.context,
platform: this.options.platformOptions.platform,
platforms: this.options.platformOptions.platforms,
ignore: this.options.platformOptions.ignore
});
apply(compiler) {
super.apply(compiler);
if (this.options.platformOptions && this.options.platformOptions.platform && this.options.platformOptions.platforms) {
compiler.plugin('environment', () => {
compiler.inputFileSystem = mapFileSystem({
fs: compiler.inputFileSystem,
context: compiler.context,
platform: this.options.platformOptions.platform,
platforms: this.options.platformOptions.platforms,
ignore: this.options.platformOptions.ignore
});

compiler.watchFileSystem = mapFileSystem({
fs: compiler.watchFileSystem,
context: compiler.context,
platform: this.options.platformOptions.platform,
platforms: this.options.platformOptions.platforms,
ignore: this.options.platformOptions.ignore
compiler.watchFileSystem = mapFileSystem({
fs: compiler.watchFileSystem,
context: compiler.context,
platform: this.options.platformOptions.platform,
platforms: this.options.platformOptions.platforms,
ignore: this.options.platformOptions.ignore
});
});
});
}
}
}

return {
AngularCompilerPlugin,
NativeScriptAngularCompilerPlugin
};
}

export interface NativeScriptAngularCompilerPluginOptions extends ngToolsWebpack.AngularCompilerPluginOptions {
platformOptions?: PlatformFSPluginOptions;
}

export interface CompiledFile {
outputText: string;
sourceMap: string;
errorDependencies: string[];
}
4 changes: 2 additions & 2 deletions plugins/angular.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = Object.assign({},
require("./NativeScriptAngularCompilerPlugin")
module.exports = (projectDir) => Object.assign({},
require("./NativeScriptAngularCompilerPlugin")(projectDir)
);
4 changes: 3 additions & 1 deletion templates/webpack.angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ module.exports = env => {

const platforms = ["ios", "android"];
const projectRoot = __dirname;
nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });

// Default destination inside platforms/<platform>/...
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform));
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";

const {
Expand Down
4 changes: 3 additions & 1 deletion templates/webpack.javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ module.exports = env => {

const platforms = ["ios", "android"];
const projectRoot = __dirname;
nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });

// Default destination inside platforms/<platform>/...
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform));
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";

const {
Expand Down
4 changes: 3 additions & 1 deletion templates/webpack.typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ module.exports = env => {

const platforms = ["ios", "android"];
const projectRoot = __dirname;
nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });

// Default destination inside platforms/<platform>/...
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform));
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";

const {
Expand Down