Skip to content

Commit

Permalink
[FIX] ApplicationFormatter: detect the namespace from component contr…
Browse files Browse the repository at this point in the history
…oller

When the manifest.json contains a Maven placeholder the namespace cannot
be detected properly. As a fallback the namespace will now be derived
from the component controller.
  • Loading branch information
petermuessig committed Apr 21, 2019
1 parent 87fd85e commit 04e8ddb
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 8 deletions.
39 changes: 33 additions & 6 deletions lib/types/application/ApplicationFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,60 @@ class ApplicationFormatter extends AbstractFormatter {
};

return this.readManifest(project).then(function(manifest) {
if (!manifest["sap.app"] || !manifest["sap.app"].id) {
// check for a proper sap.app/id in manifest.json to determine namespace
const appId = manifest["sap.app"] && manifest["sap.app"].id;
if (!appId) {
log.warn(`No "sap.app" ID configuration found in manifest of project ${project.metadata.name}`);
return;
}
project.metadata.namespace = manifest["sap.app"].id.replace(/\./g, "/");
}).catch((err) => {
// check app id for placeholder and try to guess namespace from component controller
const parts = appId.match(/^\$\{(.*)\}$/);
if (parts) {
log.warn(`No valid "sap.app" ID found in manifest of project ${project.metadata.name}. Guessing from Component.js...`);
return this.readComponentController(project).then((code) => {
// use regex to determine namespace from component controller
const namespaceParts = code.match(/\.(?:\s+)?extend(?:\s+)?\((?:\s+)?["'](.*)\.Component["'](?:\s+)?,/);
if (namespaceParts) {
project.metadata.namespace = namespaceParts[1].replace(/\./g, "/");
}
});
}
project.metadata.namespace = appId.replace(/\./g, "/");
}.bind(this)).catch((err) => {
log.verbose(`No manifest found for project ${project.metadata.name}.`);
});
});
}

/**
* Reads the manifest
*
*
* @param {Object} project
* @returns {Promise<Object>} resolves with the json object
*/
readManifest(project) {
return readFile(path.join(project.path, project.resources.pathMappings["/"], "manifest.json"))
return readFile(path.join(project.path, project.resources.pathMappings["/"], "manifest.json"), "utf-8")
.then((file) => {
return JSON.parse(file);
});
}

/**
* Reads the Component Controller
*
* @param {Object} project
* @returns {Promise<Object>} resolves with the code of the Component Controller
*/
readComponentController(project) {
return readFile(path.join(project.path, project.resources.pathMappings["/"], "Component.js"), "utf-8")
.then((file) => {
return file;
});
}

/**
* Validates a project
*
*
* @param {Object} project
* @returns {Promise} resolves if successfully validated
* @throws {Error} if validation fails
Expand Down
2 changes: 1 addition & 1 deletion test/expected/build/application.h/dest/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"_version": "1.1.0",
"sap.app": {
"_version": "1.1.0",
"id": "application.g",
"id": "${project.artifactId}",
"type": "application",
"applicationVersion": {
"version": "1.2.2"
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/application.h/webapp/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"_version": "1.1.0",
"sap.app": {
"_version": "1.1.0",
"id": "application.g",
"id": "${project.artifactId}",
"type": "application",
"applicationVersion": {
"version": "1.2.2"
Expand Down
32 changes: 32 additions & 0 deletions test/lib/types/application/ApplicationFormatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,35 @@ test("format: set namespace to id", async (t) => {
t.deepEqual(project.metadata.namespace, "my/id",
"namespace was successfully set since readManifest provides the correct object structure");
});

const applicationHPath = path.join(__dirname, "..", "..", "..", "fixtures", "application.h");
const applicationHTree = {
id: "application.h",
version: "1.0.0",
path: applicationHPath,
dependencies: [],
_level: 0,
specVersion: "0.1",
type: "application",
metadata: {
name: "application.h"
},
resources: {
configuration: {
paths: {
webapp: "webapp"
}
}
}
};


test("namespace: detect namespace from component", async (t) => {
const myProject = clone(applicationHTree);
const applicationFormatter = new ApplicationFormatter();

await applicationFormatter.format(myProject);
t.deepEqual(myProject.metadata.namespace, "application/h",
"namespace was successfully set since readManifest provides the correct object structure");
});

0 comments on commit 04e8ddb

Please sign in to comment.