diff --git a/lib/resourceFactory.js b/lib/resourceFactory.js index dde39407..cddd3247 100644 --- a/lib/resourceFactory.js +++ b/lib/resourceFactory.js @@ -1,13 +1,3 @@ -const log = require("@ui5/logger").getLogger("resources:resourceFactory"); -const path = require("path"); -const FsAdapter = require("./adapters/FileSystem"); -const MemAdapter = require("./adapters/Memory"); -const ReaderCollection = require("./ReaderCollection"); -const ReaderCollectionPrioritized = require("./ReaderCollectionPrioritized"); -const DuplexCollection = require("./DuplexCollection"); -const Resource = require("./Resource"); -const hasOwnProperty = Object.prototype.hasOwnProperty; - /** * Resource Factory * @@ -16,207 +6,6 @@ const hasOwnProperty = Object.prototype.hasOwnProperty; * @alias module:@ui5/fs.resourceFactory */ const resourceFactory = { - /** - * Callback to retrieve excludes for a given project - * - * @public - * @callback module:@ui5/fs.resourceFactory~getProjectExcludes - * @param {object} Project - * @returns {string[]} List of glob patterns to exclude - */ - - /** - * Callback to retrieve a prefix to use for a given virtual base path of a project - * - * @public - * @callback module:@ui5/fs.resourceFactory~getVirtualBasePathPrefix - * @param {object} parameters Parameters - * @param {object} parameters.project Project - * @param {object} parameters.virBasePath virtual base path to prefix - * @returns {string} Prefix for the virtual base path - */ - - /** - * Creates resource reader collections for a (sub-)tree. Returns an object of resource readers: - *
- * { - * source: Resource reader for source resources - * dependencies: Resource readers for dependency resources - * } - *- * - * @public - * @param {object} tree A (sub-)tree - * @param {object} [parameters] Parameters - * @param {module:@ui5/fs.resourceFactory~getProjectExcludes} [parameters.getProjectExcludes] - * Callback to retrieve the exclude globs of a project - * @param {module:@ui5/fs.resourceFactory~getVirtualBasePathPrefix} [parameters.getVirtualBasePathPrefix] - * Callback to retrieve a prefix for a given virtual base path of a project if required - * @param {object} [parameters.virtualReaders] Experimental, internal parameter. Do not use - * @returns {object} Object containing
source
and dependencies
resource readers
- */
- createCollectionsForTree(tree, {
- getProjectExcludes, getVirtualBasePathPrefix, virtualReaders={}
- } = {}) {
- // TODO 3.0: virtualReaders is private API. The virtual reader of a project should be stored on the
- // project itself. This requires projects to become objects independent from the dependency tree.
- // Also see: https://github.com/SAP/ui5-project/issues/122
-
- const dependencyCollection = [];
- const dependencyPathIndex = {};
- const virtualReaderIndex = {};
- const sourceResourceLocators = [];
-
- function processDependencies(project) {
- if (project.resources && project.resources.pathMappings) {
- const fsAdapters = [];
- for (const virBasePath in project.resources.pathMappings) {
- if (hasOwnProperty.call(project.resources.pathMappings, virBasePath)) {
- // Prevent duplicate dependency resource locators
- const fsPath = project.resources.pathMappings[virBasePath];
- const fsBasePath = path.join(project.path, fsPath);
- const key = virBasePath + fsBasePath;
- if (dependencyPathIndex[key]) {
- continue;
- }
- dependencyPathIndex[key] = true;
-
- // Create an fs adapter for every path mapping
- const fsAdapter = resourceFactory._createFsAdapterForVirtualBasePath({
- project,
- virBasePath,
- getProjectExcludes,
- getVirtualBasePathPrefix
- });
- fsAdapters.push(fsAdapter);
- }
- }
-
- if (!virtualReaderIndex[project.metadata.name] && virtualReaders[project.metadata.name]) {
- // Mix-in virtual reader of dependency if available and not already added
- virtualReaderIndex[project.metadata.name] = true;
- const virtualReader = virtualReaders[project.metadata.name];
- const readerCollection = new ReaderCollectionPrioritized({
- name: `fs & vir reader collection for project ${project.metadata.name}`,
- readers: [virtualReader, ...fsAdapters]
- });
- dependencyCollection.push(readerCollection);
- } else {
- dependencyCollection.push(...fsAdapters);
- }
- }
-
- project.dependencies.forEach(function(depProject) {
- processDependencies(depProject);
- });
- }
-
- if (tree.resources && tree.resources.pathMappings) {
- for (const virBasePath in tree.resources.pathMappings) {
- if (hasOwnProperty.call(tree.resources.pathMappings, virBasePath)) {
- // Create an fs adapter for every path mapping
- const fsAdapter = resourceFactory._createFsAdapterForVirtualBasePath({
- project: tree,
- virBasePath,
- getProjectExcludes,
- getVirtualBasePathPrefix
- });
- sourceResourceLocators.push(fsAdapter);
- }
- }
- }
-
- tree.dependencies.forEach(function(project) {
- processDependencies(project);
- });
-
- const source = new ReaderCollection({
- name: "source of " + tree.metadata.name,
- readers: sourceResourceLocators
- });
- const dependencies = new ReaderCollection({
- name: "dependencies of " + tree.metadata.name,
- readers: dependencyCollection
- });
- return {
- source,
- dependencies
- };
- },
-
- /**
- * Creates a FileSystem adapter mapping to the given virtual base path based on the given projects
- * configuration.
- *
- * @param {object} parameters Parameters
- * @param {Project} parameters.project A project
- * @param {string} parameters.virBasePath Virtual base path to create the adapter for
- * @param {module:@ui5/fs.resourceFactory~getProjectExcludes} [parameters.getProjectExcludes]
- * Callback to retrieve the exclude glob of a project
- * @param {module:@ui5/fs.resourceFactory~getVirtualBasePathPrefix} [parameters.getVirtualBasePathPrefix]
- * Callback to retrieve the exclude glob of a project
- * @returns {PromiseReaderWriter
.
*
@@ -233,8 +22,10 @@ const resourceFactory = {
*/
createAdapter({fsBasePath, virBasePath, project, excludes}) {
if (fsBasePath) {
+ const FsAdapter = require("./adapters/FileSystem");
return new FsAdapter({fsBasePath, virBasePath, project, excludes});
} else {
+ const MemAdapter = require("./adapters/Memory");
return new MemAdapter({virBasePath, project, excludes});
}
},
@@ -299,6 +90,7 @@ const resourceFactory = {
* @returns {module:@ui5/fs.Resource} Resource
*/
createResource(parameters) {
+ const Resource = require("./Resource");
return new Resource(parameters);
},
@@ -319,7 +111,10 @@ const resourceFactory = {
* @returns {module:@ui5/fs.DuplexCollection} DuplexCollection which wraps the provided resource locators
*/
createWorkspace({reader, writer, virBasePath = "/", name = "vir & fs source"}) {
+ const DuplexCollection = require("./DuplexCollection");
+
if (!writer) {
+ const MemAdapter = require("./adapters/Memory");
writer = new MemAdapter({
virBasePath
});
diff --git a/test/lib/resources.js b/test/lib/resources.js
index 8ccb50e6..ec8b5442 100644
--- a/test/lib/resources.js
+++ b/test/lib/resources.js
@@ -47,267 +47,7 @@ test("Get resource from application.a (/index.html) and write it to /dest/ using
}));
});
-test("createCollectionsForTree: high level test", (t) => {
- // Creates resource reader collections for a given tree
- const resourceReaders = ui5Fs.resourceFactory.createCollectionsForTree(applicationBTree);
-
- // Check whether resulting object contains both,
- // resource readers for the application source itself and for its dependencies.
- t.true(hasOwnProperty.call(resourceReaders, "source"),
- "Contains readers for the application code");
- t.true(hasOwnProperty.call(resourceReaders, "dependencies"),
- "Contains readers for the application's dependencies");
-
- t.true(resourceReaders.source._readers.length === 1, "One reader for the application code");
- t.true(resourceReaders.dependencies._readers.length === 8, "Eight readers for the application's dependencies");
-});
-
-test.serial("createCollectionsForTree", (t) => {
- const createFsAdapterForVirtualBasePathSpy = sinon.spy(ui5Fs.resourceFactory, "_createFsAdapterForVirtualBasePath");
-
- const getVirtualBasePathPrefixCallback = function() {};
- const getProjectExcludesCallback = function() {};
-
- const libraryDMemoryAdapter = ui5Fs.resourceFactory.createAdapter({
- virBasePath: "/"
- });
- // Creates resource reader collections for a given tree
- const resourceReaders = ui5Fs.resourceFactory.createCollectionsForTree(applicationBTree, {
- getVirtualBasePathPrefix: getVirtualBasePathPrefixCallback,
- getProjectExcludes: getProjectExcludesCallback,
- virtualReaders: {
- "library.d": libraryDMemoryAdapter
- }
- });
-
- t.deepEqual(createFsAdapterForVirtualBasePathSpy.callCount, 9,
- "createFsAdapterForVirtualBasePath got called nine times");
-
- t.deepEqual(resourceReaders.source._readers.length, 1, "One reader for the application code");
- t.deepEqual(resourceReaders.dependencies._readers.length, 7,
- "Seven readers for the application's dependencies on top level");
- t.deepEqual(resourceReaders.dependencies._readers[0]._readers.length, 3,
- "First dependency reader is a (prioritized) collection of three readers");
- t.is(resourceReaders.dependencies._readers[0]._readers[0], libraryDMemoryAdapter,
- "First reader of that collection is the supplied memory reader");
-
- const firstCall = createFsAdapterForVirtualBasePathSpy.getCall(0).args[0];
- t.is(firstCall.project, applicationBTree,
- "First createAdapter call: Correct project supplied");
- t.deepEqual(firstCall.virBasePath, "/",
- "First createAdapter call: Correct virBasePath supplied");
- t.is(firstCall.getProjectExcludes, getProjectExcludesCallback,
- "First createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(firstCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "First createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const secondCall = createFsAdapterForVirtualBasePathSpy.getCall(1).args[0];
- t.is(secondCall.project, applicationBTree.dependencies[0],
- "second createAdapter call: Correct project supplied");
- t.deepEqual(secondCall.virBasePath, "/resources/",
- "second createAdapter call: Correct virBasePath supplied");
- t.is(secondCall.getProjectExcludes, getProjectExcludesCallback,
- "second createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(secondCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "second createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const thirdCall = createFsAdapterForVirtualBasePathSpy.getCall(2).args[0];
- t.is(thirdCall.project, applicationBTree.dependencies[0],
- "third createAdapter call: Correct project supplied");
- t.deepEqual(thirdCall.virBasePath, "/test-resources/",
- "third createAdapter call: Correct virBasePath supplied");
- t.is(thirdCall.getProjectExcludes, getProjectExcludesCallback,
- "third createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(thirdCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "third createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const fourthCall = createFsAdapterForVirtualBasePathSpy.getCall(3).args[0];
- t.is(fourthCall.project, applicationBTree.dependencies[1],
- "fourth createAdapter call: Correct project supplied");
- t.deepEqual(fourthCall.virBasePath, "/resources/",
- "fourth createAdapter call: Correct virBasePath supplied");
- t.is(fourthCall.getProjectExcludes, getProjectExcludesCallback,
- "fourth createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(fourthCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "fourth createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const fifthCall = createFsAdapterForVirtualBasePathSpy.getCall(4).args[0];
- t.is(fifthCall.project, applicationBTree.dependencies[1],
- "fifth createAdapter call: Correct project supplied");
- t.deepEqual(fifthCall.virBasePath, "/test-resources/",
- "fifth createAdapter call: Correct virBasePath supplied");
- t.is(fifthCall.getProjectExcludes, getProjectExcludesCallback,
- "fifth createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(fifthCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "fifth createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const sixthCall = createFsAdapterForVirtualBasePathSpy.getCall(5).args[0];
- t.is(sixthCall.project, applicationBTree.dependencies[2],
- "sixth createAdapter call: Correct project supplied");
- t.deepEqual(sixthCall.virBasePath, "/resources/",
- "sixth createAdapter call: Correct virBasePath supplied");
- t.is(sixthCall.getProjectExcludes, getProjectExcludesCallback,
- "sixth createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(sixthCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "sixth createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const seventhCall = createFsAdapterForVirtualBasePathSpy.getCall(6).args[0];
- t.is(seventhCall.project, applicationBTree.dependencies[2],
- "seventh createAdapter call: Correct project supplied");
- t.deepEqual(seventhCall.virBasePath, "/test-resources/",
- "seventh createAdapter call: Correct virBasePath supplied");
- t.is(seventhCall.getProjectExcludes, getProjectExcludesCallback,
- "seventh createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(seventhCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "seventh createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const eightCall = createFsAdapterForVirtualBasePathSpy.getCall(7).args[0];
- t.is(eightCall.project, applicationBTree.dependencies[3],
- "eight createAdapter call: Correct project supplied");
- t.deepEqual(eightCall.virBasePath, "/resources/",
- "eight createAdapter call: Correct virBasePath supplied");
- t.is(eightCall.getProjectExcludes, getProjectExcludesCallback,
- "eight createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(eightCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "eight createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-
- const ninthCall = createFsAdapterForVirtualBasePathSpy.getCall(8).args[0];
- t.is(ninthCall.project, applicationBTree.dependencies[3],
- "ninth createAdapter call: Correct project supplied");
- t.deepEqual(ninthCall.virBasePath, "/test-resources/",
- "ninth createAdapter call: Correct virBasePath supplied");
- t.is(ninthCall.getProjectExcludes, getProjectExcludesCallback,
- "ninth createAdapter call: Correct getProjectExcludes parameter supplied");
- t.is(ninthCall.getVirtualBasePathPrefix, getVirtualBasePathPrefixCallback,
- "ninth createAdapter call: Correct getVirtualBasePathPrefix parameter supplied");
-});
-
-test.serial("createCollectionsForTree/createFsAdapterForVirtualBasePath with excludes", (t) => {
- const createAdapterSpy = sinon.spy(ui5Fs.resourceFactory, "createAdapter");
- ui5Fs.resourceFactory.createCollectionsForTree(applicationBTreeWithExcludes, {
- getProjectExcludes: (proj) => {
- return proj.pony.excludes;
- }
- });
-
- t.deepEqual(createAdapterSpy.callCount, 5, "createAdapter got called three times");
-
- const firstCall = createAdapterSpy.getCall(0).args[0];
- t.deepEqual(firstCall.fsBasePath, path.join(applicationBPath, "webapp"),
- "First createAdapter call: Correct base path supplied");
- t.deepEqual(firstCall.excludes, ["/pony-path/*"],
- "First createAdapter call: Correct exclude patterns supplied");
-
- const secondCall = createAdapterSpy.getCall(1).args[0];
- t.deepEqual(secondCall.fsBasePath,
- path.join(applicationBPath, "..", "library.d", "main", "src"),
- "Second createAdapter call: Correct base path supplied");
- t.deepEqual(secondCall.excludes, [
- "/unicorn-path/*",
- "/duck-path/*"
- ],
- "Second createAdapter call: Correct exclude patterns supplied");
-
- const thirdCall = createAdapterSpy.getCall(2).args[0];
- t.deepEqual(thirdCall.fsBasePath,
- path.join(applicationBPath, "..", "library.d", "main", "test"),
- "Third createAdapter call: Correct base path supplied");
- t.deepEqual(thirdCall.excludes, [
- "/unicorn-path/*",
- "/duck-path/*"
- ],
- "Third createAdapter call: Correct exclude patterns supplied");
-
- const fourthCall = createAdapterSpy.getCall(3).args[0];
- t.deepEqual(fourthCall.fsBasePath,
- path.join(applicationBPath, "..", "collection", "library.a", "src"),
- "Fourth createAdapter call: Correct base path supplied");
- t.deepEqual(fourthCall.excludes, ["/duck-path/*"],
- "Fourth createAdapter call: Correct exclude patterns supplied");
-
- const fifthCall = createAdapterSpy.getCall(4).args[0];
- t.deepEqual(fifthCall.fsBasePath,
- path.join(applicationBPath, "..", "collection", "library.a", "test"),
- "Fifth createAdapter call: Correct base path supplied");
- t.deepEqual(fifthCall.excludes, ["/duck-path/*"],
- "Fifth createAdapter call: Correct exclude patterns supplied");
-});
-
-test.serial("_createFsAdapterForVirtualBasePath: application with virtual base path prefixing", (t) => {
- const getVirtualBasePathPrefixStub = sinon.stub().returns("/pony/path");
- const createAdapterSpy = sinon.spy(ui5Fs.resourceFactory, "createAdapter");
-
- const fsAdapter = ui5Fs.resourceFactory._createFsAdapterForVirtualBasePath({
- project: applicationBTreeWithExcludes,
- virBasePath: "/",
- getVirtualBasePathPrefix: getVirtualBasePathPrefixStub,
- getProjectExcludes: () => {
- return [
- "{/sub-directory-1/,/sub-directory-2/}**",
- "/pony-path/**",
- "!/duck*path/**",
- "!**.json"
- ];
- }
- });
-
- t.deepEqual(getVirtualBasePathPrefixStub.callCount, 1,
- "getVirtualBasePathPrefix callback called once");
- t.deepEqual(getVirtualBasePathPrefixStub.getCall(0).args[0].project.id, "application.b",
- "getVirtualBasePathPrefix callback called with correct project");
- t.deepEqual(getVirtualBasePathPrefixStub.getCall(0).args[0].virBasePath, "/",
- "getVirtualBasePathPrefix callback called with correct virtual base path");
-
- t.deepEqual(createAdapterSpy.callCount, 1, "createAdapter got called one time");
- const firstCall = createAdapterSpy.getCall(0).args[0];
- t.deepEqual(firstCall.fsBasePath, path.join(applicationBPath, "webapp"),
- "First createAdapter call: Correct base path supplied");
- t.deepEqual(firstCall.excludes, [
- "/pony/path/sub-directory-1/**",
- "/pony/path/sub-directory-2/**",
- "/pony/path/pony-path/**",
- "!/pony/path/duck*path/**",
- "!/pony/path/**.json"
- ],
- "First createAdapter call: Correct exclude patterns supplied");
-
- t.deepEqual(fsAdapter._fsBasePath, path.join(applicationBPath, "webapp"), "Returned an FS adapter");
-});
-
-test.serial("_createFsAdapterForVirtualBasePath: library", (t) => {
- const createAdapterSpy = sinon.spy(ui5Fs.resourceFactory, "createAdapter");
-
- const fsAdapter = ui5Fs.resourceFactory._createFsAdapterForVirtualBasePath({
- project: libraryDTree,
- virBasePath: "/resources/",
- getProjectExcludes: () => {
- return [
- "/resources/library/d/{sub-directory-1/,sub-directory-2/}**",
- "/resources/library/d/pony-path/**",
- "!/resources/library/d/duck*path/**",
- "!/resources/library/d/**.json"
- ];
- }
- });
-
- t.deepEqual(createAdapterSpy.callCount, 1, "createAdapter got called one time");
- const firstCall = createAdapterSpy.getCall(0).args[0];
- t.deepEqual(firstCall.fsBasePath, path.join(libraryDTree.path, "main/src"),
- "First createAdapter call: Correct base path supplied");
- t.deepEqual(firstCall.excludes, [
- // Since no virtual base path prefixing was done, no special processing
- // of exclude patterns was necessary
- "/resources/library/d/{sub-directory-1/,sub-directory-2/}**",
- "/resources/library/d/pony-path/**",
- "!/resources/library/d/duck*path/**",
- "!/resources/library/d/**.json"
- ],
- "First createAdapter call: Correct exclude patterns supplied");
-
- t.deepEqual(fsAdapter._fsBasePath, path.join(libraryDTree.path, "main/src"), "Returned an FS adapter");
-});
-
-test("_prefixGlobPattern", (t) => {
+test("prefixGlobPattern", (t) => {
t.deepEqual(
ui5Fs.resourceFactory.prefixGlobPattern("{/sub-directory-1/,/sub-directory-2/}**", "/pony/path/a"),
[