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

Commit a7acb4d

Browse files
rosen-vladimirovmanoldonev
authored andcommitted
fix: allow using the plugin via symlink (#501)
* fix: Allow using the plugin via symlink Currently when the plugin is used with symlink, the execution fails as the project dir is calculated incorrectly. Instead of trying to find the project dir, pass it wherever it is required. This leads to changes in the way NativeScriptAngularCompilerPlugin is loaded - currently it uses the projectDir directly when the plugin is loaded. However, at this point we do no know the exact location of the project directory. So change the require of the NativeScriptAngularCompilerPlugin to return a function, which accepts projectDir as argument. Expose the loading through a new method in the nativescript-dev-webpack plugin - `loadAdditionalPlugins`. BREAKING CHANGE: The current code changes the way NativeScriptAngularCompilerPlugin is loaded. This means that all projects that already have webpack.config.js and just upgrade the version of nativescript-dev-webpack, will not be able to use the plugin (NativeScriptAngularCompilerPlugin). They will have to modify their webpack.config.js files. * fix: webpack getAppPath with projectRoot * refactor: verify entry module directory
1 parent 075c445 commit a7acb4d

6 files changed

+119
-99
lines changed

Diff for: index.js

+23-12
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,24 @@ const path = require("path");
22
const { existsSync } = require("fs");
33

44
const {
5-
APP_DIR,
65
getPackageJson,
7-
getProjectDir,
86
isAngular,
97
isAndroid,
108
isIos,
119
resolveAndroidAppPath,
1210
} = require("./projectHelpers");
1311

14-
const PROJECT_DIR = getProjectDir();
15-
const APP_PATH = path.join(PROJECT_DIR, APP_DIR);
16-
1712
Object.assign(exports, require('./plugins'));
1813

19-
if (isAngular({ projectDir: PROJECT_DIR })) {
20-
Object.assign(exports, require('./plugins/angular'));
14+
exports.loadAdditionalPlugins = function (projectSettings) {
15+
if (isAngular(projectSettings)) {
16+
Object.assign(exports, require('./plugins/angular')(projectSettings.projectDir));
17+
}
2118
}
2219

23-
exports.getAotEntryModule = function (appDirectory = APP_PATH) {
20+
exports.getAotEntryModule = function (appDirectory) {
21+
verifyEntryModuleDirectory(appDirectory);
22+
2423
const entry = getPackageJsonEntry(appDirectory);
2524
const aotEntry = `${entry}.aot.ts`;
2625

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

39-
exports.getEntryModule = function (appDirectory = APP_PATH) {
38+
exports.getEntryModule = function (appDirectory) {
39+
verifyEntryModuleDirectory(appDirectory);
40+
4041
const entry = getPackageJsonEntry(appDirectory);
4142

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

52-
exports.getAppPath = platform => {
53+
exports.getAppPath = (platform, projectDir) => {
5354
if (isIos(platform)) {
54-
const appName = path.basename(PROJECT_DIR);
55+
const appName = path.basename(projectDir);
5556
const sanitizedName = sanitize(appName);
5657

5758
return `platforms/ios/${sanitizedName}/app`;
5859
} else if (isAndroid(platform)) {
59-
return resolveAndroidAppPath(PROJECT_DIR);
60+
return resolveAndroidAppPath(projectDir);
6061
} else {
6162
throw new Error(`Invalid platform: ${platform}`);
6263
}
@@ -77,3 +78,13 @@ function getPackageJsonEntry(appDirectory) {
7778

7879
return entry.replace(/\.js$/i, "");
7980
}
81+
82+
function verifyEntryModuleDirectory(appDirectory) {
83+
if (!appDirectory) {
84+
throw new Error("Path to app directory is not specified. Unable to find entry module.");
85+
}
86+
87+
if (!existsSync(appDirectory)) {
88+
throw new Error(`The specified path to app directory ${appDirectory} does not exist. Unable to find entry module.`);
89+
}
90+
}

Diff for: plugins/NativeScriptAngularCompilerPlugin.ts

+85-82
Original file line numberDiff line numberDiff line change
@@ -1,101 +1,104 @@
11
import * as path from "path";
22
import { PlatformFSPlugin, PlatformFSPluginOptions, mapFileSystem } from "./PlatformFSPlugin";
3-
import * as hook from "nativescript-hook";
43
import * as ngToolsWebpack from "@ngtools/webpack";
4+
module.exports = (projectDir) => {
5+
// During development the nativescript-dev-webpack plugin may have @ngtools/webpack installed locally as dev-dependency,
6+
// we want to make sure we are using the one installed in the actual app
7+
const ngToolsWebpackDir = path.join(projectDir, "node_modules", "@ngtools", "webpack");
8+
const appNgToolsWebpack: typeof ngToolsWebpack = require(ngToolsWebpackDir);
9+
const AngularCompilerPlugin: typeof ngToolsWebpack.AngularCompilerPlugin = appNgToolsWebpack.AngularCompilerPlugin;
510

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

12-
export const AngularCompilerPlugin: typeof ngToolsWebpack.AngularCompilerPlugin = appNgToolsWebpack.AngularCompilerPlugin;
13-
14-
export interface NativeScriptAngularCompilerPluginOptions extends ngToolsWebpack.AngularCompilerPluginOptions {
15-
platformOptions?: PlatformFSPluginOptions;
16-
}
17-
18-
export interface CompiledFile {
19-
outputText: string;
20-
sourceMap: string;
21-
errorDependencies: string[];
22-
}
23-
24-
export class NativeScriptAngularCompilerPlugin extends AngularCompilerPlugin {
25-
readonly options: NativeScriptAngularCompilerPluginOptions;
26-
readonly platform: string;
27-
28-
get __compilerHost() {
29-
// Accessing private API of the AngularCompilerPlugin
30-
// We need this to augment at least the "resourceNameToFileName" so we can map
31-
// component.css to component.android.css etc. for platform specific css and html resources.
32-
return (<any>this)._compilerHost;
33-
}
15+
get __compilerHost() {
16+
// Accessing private API of the AngularCompilerPlugin
17+
// We need this to augment at least the "resourceNameToFileName" so we can map
18+
// component.css to component.android.css etc. for platform specific css and html resources.
19+
return (<any>this)._compilerHost;
20+
}
3421

35-
constructor(options: NativeScriptAngularCompilerPluginOptions) {
36-
super(options);
22+
constructor(options: NativeScriptAngularCompilerPluginOptions) {
23+
super(options);
3724

38-
this.platform = (this.options.platformOptions && this.options.platformOptions.platform) || undefined;
39-
const platform = this.platform;
25+
this.platform = (this.options.platformOptions && this.options.platformOptions.platform) || undefined;
26+
const platform = this.platform;
4027

41-
if (platform) {
42-
// https://github.com/angular/angular/blob/7bfeac746e717d02e062fe4a65c008060b8b662c/packages/compiler-cli/src/transformers/api.ts
43-
const resourceNameToFileName = this.__compilerHost.resourceNameToFileName || function(file, relativeTo) {
44-
const resolved = path.resolve(path.dirname(relativeTo), file);
45-
if (this.fileExists(resolved)) {
28+
if (platform) {
29+
// https://github.com/angular/angular/blob/7bfeac746e717d02e062fe4a65c008060b8b662c/packages/compiler-cli/src/transformers/api.ts
30+
const resourceNameToFileName = this.__compilerHost.resourceNameToFileName || function (file, relativeTo) {
31+
const resolved = path.resolve(path.dirname(relativeTo), file);
32+
if (this.fileExists(resolved)) {
33+
return resolved;
34+
} else {
35+
return null;
36+
}
37+
};
38+
this.__compilerHost.resourceNameToFileName = function (file, relativeTo) {
39+
const parsed = path.parse(file);
40+
const platformFile = parsed.name + "." + platform + parsed.ext;
41+
let resolved;
42+
try {
43+
resolved = resourceNameToFileName.call(this, platformFile, relativeTo);
44+
} catch (e) {
45+
}
46+
resolved = resolved || resourceNameToFileName.call(this, file, relativeTo);
47+
resolved = resolved && resolved.replace(/\\/g, "/");
4648
return resolved;
47-
} else {
48-
return null;
49-
}
50-
};
51-
this.__compilerHost.resourceNameToFileName = function(file, relativeTo) {
52-
const parsed = path.parse(file);
53-
const platformFile = parsed.name + "." + platform + parsed.ext;
54-
let resolved;
55-
try {
56-
resolved = resourceNameToFileName.call(this, platformFile, relativeTo);
57-
} catch(e) {
58-
}
59-
resolved = resolved || resourceNameToFileName.call(this, file, relativeTo);
60-
resolved = resolved && resolved.replace(/\\/g, "/");
61-
return resolved;
62-
};
49+
};
50+
}
6351
}
64-
}
6552

66-
getCompiledFile(this: NativeScriptAngularCompilerPlugin, file: string): CompiledFile {
67-
try {
68-
if (this.platform) {
69-
const parsed = path.parse(file);
70-
const platformFile = parsed.dir + path.sep + parsed.name + "." + this.platform + parsed.ext;
71-
const result = super.getCompiledFile(platformFile);
72-
return result;
53+
getCompiledFile(this: NativeScriptAngularCompilerPlugin, file: string): CompiledFile {
54+
try {
55+
if (this.platform) {
56+
const parsed = path.parse(file);
57+
const platformFile = parsed.dir + path.sep + parsed.name + "." + this.platform + parsed.ext;
58+
const result = super.getCompiledFile(platformFile);
59+
return result;
60+
}
61+
} catch (e) {
7362
}
74-
} catch(e) {
63+
return super.getCompiledFile(file);
7564
}
76-
return super.getCompiledFile(file);
77-
}
7865

79-
apply(compiler) {
80-
super.apply(compiler);
81-
if (this.options.platformOptions && this.options.platformOptions.platform && this.options.platformOptions.platforms) {
82-
compiler.plugin('environment', () => {
83-
compiler.inputFileSystem = mapFileSystem({
84-
fs: compiler.inputFileSystem,
85-
context: compiler.context,
86-
platform: this.options.platformOptions.platform,
87-
platforms: this.options.platformOptions.platforms,
88-
ignore: this.options.platformOptions.ignore
89-
});
66+
apply(compiler) {
67+
super.apply(compiler);
68+
if (this.options.platformOptions && this.options.platformOptions.platform && this.options.platformOptions.platforms) {
69+
compiler.plugin('environment', () => {
70+
compiler.inputFileSystem = mapFileSystem({
71+
fs: compiler.inputFileSystem,
72+
context: compiler.context,
73+
platform: this.options.platformOptions.platform,
74+
platforms: this.options.platformOptions.platforms,
75+
ignore: this.options.platformOptions.ignore
76+
});
9077

91-
compiler.watchFileSystem = mapFileSystem({
92-
fs: compiler.watchFileSystem,
93-
context: compiler.context,
94-
platform: this.options.platformOptions.platform,
95-
platforms: this.options.platformOptions.platforms,
96-
ignore: this.options.platformOptions.ignore
78+
compiler.watchFileSystem = mapFileSystem({
79+
fs: compiler.watchFileSystem,
80+
context: compiler.context,
81+
platform: this.options.platformOptions.platform,
82+
platforms: this.options.platformOptions.platforms,
83+
ignore: this.options.platformOptions.ignore
84+
});
9785
});
98-
});
86+
}
9987
}
10088
}
89+
90+
return {
91+
AngularCompilerPlugin,
92+
NativeScriptAngularCompilerPlugin
93+
};
94+
}
95+
96+
export interface NativeScriptAngularCompilerPluginOptions extends ngToolsWebpack.AngularCompilerPluginOptions {
97+
platformOptions?: PlatformFSPluginOptions;
98+
}
99+
100+
export interface CompiledFile {
101+
outputText: string;
102+
sourceMap: string;
103+
errorDependencies: string[];
101104
}

Diff for: plugins/angular.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
module.exports = Object.assign({},
2-
require("./NativeScriptAngularCompilerPlugin")
1+
module.exports = (projectDir) => Object.assign({},
2+
require("./NativeScriptAngularCompilerPlugin")(projectDir)
33
);

Diff for: templates/webpack.angular.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ module.exports = env => {
1717

1818
const platforms = ["ios", "android"];
1919
const projectRoot = __dirname;
20+
nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });
21+
2022
// Default destination inside platforms/<platform>/...
21-
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform));
23+
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
2224
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";
2325

2426
const {

Diff for: templates/webpack.javascript.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ module.exports = env => {
1717

1818
const platforms = ["ios", "android"];
1919
const projectRoot = __dirname;
20+
nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });
21+
2022
// Default destination inside platforms/<platform>/...
21-
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform));
23+
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
2224
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";
2325

2426
const {

Diff for: templates/webpack.typescript.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ module.exports = env => {
1717

1818
const platforms = ["ios", "android"];
1919
const projectRoot = __dirname;
20+
nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });
21+
2022
// Default destination inside platforms/<platform>/...
21-
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform));
23+
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
2224
const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";
2325

2426
const {

0 commit comments

Comments
 (0)