@ui5/fs
Version:
UI5 Build and Development Tooling - File System Abstraction
147 lines (132 loc) • 4.08 kB
JavaScript
const log = require("@ui5/logger").getLogger("resources:adapters:Memory");
const micromatch = require("micromatch");
const Resource = require("../Resource");
const AbstractAdapter = require("./AbstractAdapter");
/**
* Virtual resource Adapter
*
* @public
* @memberof module:@ui5/fs.adapters
* @augments module:@ui5/fs.adapters.AbstractAdapter
*/
class Memory extends AbstractAdapter {
/**
* The constructor.
*
* @public
* @param {Object} parameters Parameters
* @param {string} parameters.virBasePath Virtual base path
*/
constructor({virBasePath, project}) {
super({virBasePath, project});
this._virFiles = {}; // map full of files
this._virDirs = {}; // map full of directories
}
/**
* Locate resources by GLOB.
*
* @private
* @param {Array} patterns array of GLOB patterns
* @param {Object} [options={}] GLOB options
* @param {boolean} [options.nodir=true] Do not match directories
* @param {module:@ui5/fs.tracing.Trace} trace Trace instance
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving to list of resources
*/
_runGlob(patterns, options = {nodir: true}, trace) {
if (patterns[0] === "" && !options.nodir) { // Match virtual root directory
return Promise.resolve([
new Resource({
project: this.project,
statInfo: { // TODO: make closer to fs stat info
isDirectory: function() {
return true;
}
},
path: this._virBasePath.slice(0, -1)
})
]);
}
const filePaths = Object.keys(this._virFiles);
let matchedResources = micromatch(filePaths, patterns, {
dot: true
});
if (!options.nodir) {
// TODO: Add tests for all this
const dirPaths = Object.keys(this._virDirs);
const matchedDirs = micromatch(dirPaths, patterns, {
dot: true
});
matchedResources = matchedResources.concat(matchedDirs);
}
return Promise.resolve(matchedResources.map((virPath) => {
return this._virFiles[virPath];
}));
}
/**
* Locates resources by path.
*
* @private
* @param {string} virPath Virtual path
* @param {Object} options Options
* @param {module:@ui5/fs.tracing.Trace} trace Trace instance
* @returns {Promise<module:@ui5/fs.Resource>} Promise resolving to a single resource
*/
_byPath(virPath, options, trace) {
return new Promise((resolve, reject) => {
if (!virPath.startsWith(this._virBasePath) && virPath !== this._virBaseDir) {
// Neither starts with basePath, nor equals baseDirectory
resolve(null);
return;
}
const relPath = virPath.substr(this._virBasePath.length);
trace.pathCall();
const resource = this._virFiles[relPath];
if (!resource || (options.nodir && resource.getStatInfo().isDirectory())) {
resolve(null);
} else {
resolve(resource);
}
});
}
/**
* Writes the content of a resource to a path.
*
* @private
* @param {module:@ui5/fs.Resource} resource The Resource to write
* @returns {Promise<undefined>} Promise resolving once data has been written
*/
_write(resource) {
return new Promise((resolve, reject) => {
const relPath = resource.getPath().substr(this._virBasePath.length);
log.verbose("Writing to virtual path %s", resource.getPath());
this._virFiles[relPath] = resource;
// Add virtual directories for all path segments of the written resource
// TODO: Add tests for all this
const pathSegments = relPath.split("/");
pathSegments.pop(); // Remove last segment representing the resource itself
pathSegments.forEach((segment, i) => {
segment = "/" + segment;
if (i > 1) {
segment = pathSegments[i - 1] + segment;
}
pathSegments[i] = segment;
});
for (let i = pathSegments.length - 1; i >= 0; i--) {
const segment = pathSegments[i];
if (!this._virDirs[segment]) {
this._virDirs[segment] = new Resource({
project: this.project,
statInfo: { // TODO: make closer to fs stat info
isDirectory: function() {
return true;
}
},
path: segment
});
}
}
resolve();
});
}
}
module.exports = Memory;