Skip to content
Closed
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
10 changes: 9 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ module.exports = {
/**
* @type {typeof import('./lib/adapters/Memory')}
*/
Memory: "./lib/adapters/Memory"
Memory: "./lib/adapters/Memory",
/**
* @type {typeof import('./lib/adapters/ZipArchive')}
*/
ZipArchive: "./lib/adapters/ZipArchive"
},
/**
* @public
Expand Down Expand Up @@ -65,6 +69,10 @@ module.exports = {
* @type {typeof import('./lib/Resource')}
*/
Resource: "./lib/Resource",
/**
* @type {typeof import('./lib/ProjectResource')}
*/
ProjectResource: "./lib/ProjectResource",
/**
* @type {typeof import('./lib/ResourceTagCollection')}
*/
Expand Down
13 changes: 13 additions & 0 deletions lib/AbstractReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@ class AbstractReader {
callback
});
}
/**
* Create a [Link-Reader]{@link module:@ui5/fs.readers.Link} from the current reader
*
* @public
* @returns {module:@ui5/fs.reader.Link} Link instance
*/
link(pathMapping) {
const Link = require("./readers/Link");
return new Link({
reader: this,
pathMapping
});
}

/**
* Locates resources by one or more glob patterns.
Expand Down
64 changes: 64 additions & 0 deletions lib/ProjectResource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const Resource = require("./Resource");

/**
* Project Resource
*
* @public
* @memberof module:@ui5/fs
*/
class ProjectResource extends Resource {
/**
* Function for dynamic creation of content streams
*
* @public
* @callback module:@ui5/fs.Resource~createStream
* @returns {stream.Readable} A readable stream of a resources content
*/

/**
* The constructor.
*
* @public
* @param {object} parameters Parameters
* @param {string} parameters.path Virtual path
* @param {fs.Stats|object} [parameters.statInfo] File information. Instance of
* [fs.Stats]{@link https://nodejs.org/api/fs.html#fs_class_fs_stats} or similar object
* @param {Buffer} [parameters.buffer] Content of this resources as a Buffer instance
* (cannot be used in conjunction with parameters string, stream or createStream)
* @param {string} [parameters.string] Content of this resources as a string
* (cannot be used in conjunction with parameters buffer, stream or createStream)
* @param {Stream} [parameters.stream] Readable stream of the content of this resource
* (cannot be used in conjunction with parameters buffer, string or createStream)
* @param {module:@ui5/fs.Resource~createStream} [parameters.createStream] Function callback that returns a readable
* stream of the content of this resource (cannot be used in conjunction with parameters buffer,
* string or stream).
* In some cases this is the most memory-efficient way to supply resource content
* @param {module:@ui5/project.specifications.Project} parameters.project Project this resource belongs to
* @param {object} parameters.source TODO
*/
constructor({path, statInfo, buffer, string, createStream, stream, project, source}) {
super({path, statInfo, buffer, string, createStream, stream, source});
if (!project) {
throw new Error("Cannot create ProjectResource: 'project' parameters missing");
}
if (!source) {
throw new Error("Cannot create ProjectResource: 'source' parameters missing");
}
this.__project = project; // Two underscores since "_project" was widely used in UI5 Tooling 2.0
}

getProject() {
return this.__project;
}

getSource() {
return this._source;
}

_createClone(options) {
options.project = this.__project;
return new ProjectResource(options);
}
}

module.exports = ProjectResource;
20 changes: 12 additions & 8 deletions lib/Resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ class Resource {
* string or stream).
* In some cases this is the most memory-efficient way to supply resource content
* @param {object} [parameters.source] Experimental, internal parameter. Do not use
* @param {object} [parameters.project] Experimental, internal parameter. Do not use
*/
constructor({path, statInfo, buffer, string, createStream, stream, source, project}) {
constructor({path, statInfo, buffer, string, createStream, stream, source}) {
if (!path) {
throw new Error("Cannot create Resource: path parameter missing");
}
Expand All @@ -50,11 +49,11 @@ class Resource {
throw new Error("Cannot create Resource: Please set only one content parameter. " +
"Buffer, string, stream or createStream");
}

// TODO: Namespace?
this._path = path;
this._name = this._getNameFromPath(path);
this._project = project; // Experimental, internal parameter
this._source = source; // Experimental, internal parameter

this._source = source; // Experimental, internal parameter // TODO Move to ProjectResource?
if (this._source) {
// Indicator for adapters like FileSystem to detect whether a resource has been changed
this._source.modified = false;
Expand Down Expand Up @@ -292,10 +291,11 @@ class Resource {
* @public
* @returns {Promise<module:@ui5/fs.Resource>} Promise resolving with the clone
*/
clone() {
async clone() {
const options = {
path: this._path,
statInfo: clone(this._statInfo)
statInfo: clone(this._statInfo),
source: this._source
};

const addContentOption = () => {
Expand All @@ -314,10 +314,14 @@ class Resource {
};

return addContentOption().then(() => {
return new Resource(options);
return this._createClone(options);
});
}

_createClone(options) {
return new Resource(options);
}

/**
* Tracing: Get tree for printing out trace
*
Expand Down
179 changes: 179 additions & 0 deletions lib/ResourceFacade.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/**
* A [Resource]{module:@ui5/project.Resource} with a different path than it's original
*
* @public
* @memberof module:@ui5/fs
*/
class ResourceFacade {
/**
* The constructor.
*
* @public
* @param {object} parameters Parameters
* @param {string} parameters.path Virtual path
* @param {module:@ui5/fs.Resource} parameters.resource Resource to cover
*/
constructor({path, resource}) {
if (!path) {
throw new Error("Cannot create ResourceFacade: path parameter missing");
}
if (!resource) {
throw new Error("Cannot create ResourceFacade: resource parameter missing");
}
this._path = path;
this._resource = resource;
}

/**
* Gets the resources path
*
* @public
* @returns {string} (Virtual) path of the resource
*/
getPath() {
return this._path;
}

/**
* Sets the resources path
*
* @public
* @param {string} path (Virtual) path of the resource
*/
setPath(path) {
throw new Error(`The path of a ResourceFacade can't be changed at the moment`);
}

/**
* Returns a clone of the resource. The clones content is independent from that of the original resource.
* A ResourceFacade becomes a Resource
*
* @public
* @returns {Promise<module:@ui5/fs.Resource>} Promise resolving with the clone
*/
async clone() {
// Cloning resolves the facade
const resourceClone = await this._resource.clone();
resourceClone.setPath(this.getPath());
return resourceClone;
}

/**
* ======================================================================
* Call through functions to original resource
* ======================================================================
*/
/**
* Gets a buffer with the resource content.
*
* @public
* @returns {Promise<Buffer>} Promise resolving with a buffer of the resource content.
*/
async getBuffer() {
return this._resource.getBuffer();
}

/**
* Sets a Buffer as content.
*
* @public
* @param {Buffer} buffer Buffer instance
*/
setBuffer(buffer) {
return this._resource.setBuffer(buffer);
}

/**
* Gets a string with the resource content.
*
* @public
* @returns {Promise<string>} Promise resolving with the resource content.
*/
getString() {
return this._resource.getString();
}

/**
* Sets a String as content
*
* @public
* @param {string} string Resource content
*/
setString(string) {
return this._resource.setString(string);
}

/**
* Gets a readable stream for the resource content.
*
* Repetitive calls of this function are only possible if new content has been set in the meantime (through
* [setStream]{@link module:@ui5/fs.Resource#setStream}, [setBuffer]{@link module:@ui5/fs.Resource#setBuffer}
* or [setString]{@link module:@ui5/fs.Resource#setString}). This
* is to prevent consumers from accessing drained streams.
*
* @public
* @returns {stream.Readable} Readable stream for the resource content.
*/
getStream() {
return this._resource.getStream();
}

/**
* Sets a readable stream as content.
*
* @public
* @param {stream.Readable|module:@ui5/fs.Resource~createStream} stream Readable stream of the resource content or
callback for dynamic creation of a readable stream
*/
setStream(stream) {
return this._resource.setStream(stream);
}

/**
* Gets the resources stat info.
* Note that a resources stat information is not updated when the resource is being modified.
* Also, depending on the used adapter, some fields might be missing which would be present for a
* [fs.Stats]{@link https://nodejs.org/api/fs.html#fs_class_fs_stats} instance.
*
* @public
* @returns {fs.Stats|object} Instance of [fs.Stats]{@link https://nodejs.org/api/fs.html#fs_class_fs_stats}
* or similar object
*/
getStatInfo() {
return this._resource.getStatInfo();
}

/**
* Size in bytes allocated by the underlying buffer.
*
* @see {TypedArray#byteLength}
* @returns {Promise<number>} size in bytes, <code>0</code> if there is no content yet
*/
async getSize() {
return this._resource.getSize();
}

/**
* Adds a resource collection name that was involved in locating this resource.
*
* @param {string} name Resource collection name
*/
pushCollection(name) {
return this._resource.pushCollection(name);
}

/**
* Tracing: Get tree for printing out trace
*
* @returns {object} Trace tree
*/
getPathTree() {
return this._resource.getPathTree();
}

getSource() {
return this._resource.getSource();
}
}

module.exports = ResourceFacade;
19 changes: 18 additions & 1 deletion lib/adapters/AbstractAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class AbstractAdapter extends AbstractReaderWriter {
throw new TypeError("Class 'AbstractAdapter' is abstract");
}
super();
if (!virBasePath.endsWith("/")) {
throw new Error(`Virtual base path must end with a slash: ${virBasePath}`);
}
this._virBasePath = virBasePath;
this._virBaseDir = virBasePath.slice(0, -1);
this._excludes = excludes;
Expand Down Expand Up @@ -68,12 +71,15 @@ class AbstractAdapter extends AbstractReaderWriter {
const subPath = patterns[i];
return Promise.resolve([
new Resource({
project: this.project,
project: this._project,
statInfo: { // TODO: make closer to fs stat info
isDirectory: function() {
return true;
}
},
source: {
adapter: "Abstract"
},
path: subPath
})
]);
Expand Down Expand Up @@ -170,6 +176,17 @@ class AbstractAdapter extends AbstractReaderWriter {
return resultGlobs;
});
}

_createResource(parameters) {
let Resource;
if (this._project) {
Resource = require("../ProjectResource");
parameters.project = this._project;
} else {
Resource = require("../Resource");
}
return new Resource(parameters);
}
}

module.exports = AbstractAdapter;
Loading