You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

@ui5/fs

Package Overview
Dependencies
Maintainers
3
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.0-beta.4 to 3.0.0-rc.0

18

CHANGELOG.md

@@ -5,6 +5,19 @@ # Changelog

A list of unreleased changes can be found [here](https://github.com/SAP/ui5-fs/compare/v3.0.0-beta.4...HEAD).
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-fs/compare/v3.0.0-rc.0...HEAD).
<a name="v3.0.0-rc.0"></a>
## [v3.0.0-rc.0] - 2022-12-23
### Breaking Changes
- Throw an error on write of a resource when path does not starts with virBasePath of the respective adapter ([#453](https://github.com/SAP/ui5-fs/issues/453)) [`d76575f`](https://github.com/SAP/ui5-fs/commit/d76575f8f05a0b6695285200ba595e532620daed)
- Clone resources when writing in and reading from the Memory ([#448](https://github.com/SAP/ui5-fs/issues/448)) [`3454bc1`](https://github.com/SAP/ui5-fs/commit/3454bc15be8a6ecd455b49607cb289e69b41d0f0)
### BREAKING CHANGE
An error is thrown when a resource shall be written to an adapter where the path of the resource does not starts with the virtual base path defined in the adapter.
Resources stored in the adapters can not be modified by reference anymore. All modifications need to be persisted by using the #write method in order to be reflected in the adapter.
<a name="v3.0.0-beta.4"></a>
## [v3.0.0-beta.4] - 2022-11-30
## [v3.0.0-beta.4] - 2022-12-01

@@ -204,2 +217,3 @@ <a name="v3.0.0-beta.3"></a>

[v3.0.0-rc.0]: https://github.com/SAP/ui5-fs/compare/v3.0.0-beta.4...v3.0.0-rc.0
[v3.0.0-beta.4]: https://github.com/SAP/ui5-fs/compare/v3.0.0-beta.3...v3.0.0-beta.4

@@ -206,0 +220,0 @@ [v3.0.0-beta.3]: https://github.com/SAP/ui5-fs/compare/v3.0.0-beta.2...v3.0.0-beta.3

2

jsdoc.json

@@ -30,3 +30,3 @@ {

"type": "website",
"image": "https://sap.github.io/ui5-tooling/docs/images/UI5_logo_wide.png",
"image": "https://sap.github.io/ui5-tooling/v3/images/UI5_logo_wide.png",
"site_name": "UI5 Tooling - API Reference",

@@ -33,0 +33,0 @@ "url": "https://sap.github.io/ui5-tooling/"

@@ -212,2 +212,7 @@ import logger from "@ui5/logger";

_write(resource) {
if (!resource.getPath().startsWith(this._virBasePath)) {
throw new Error(`The path of the resource '${resource.getPath()}' does not start with ` +
`the configured virtual base path of the adapter '${this._virBasePath}'`);
}
if (this._project) {

@@ -214,0 +219,0 @@ // Assign project to resource if necessary

@@ -8,4 +8,4 @@ import logger from "@ui5/logger";

const chmod = promisify(fs.chmod);
const mkdir = promisify(fs.mkdir);
import {globby} from "globby";
import makeDir from "make-dir";
import {PassThrough} from "node:stream";

@@ -224,3 +224,3 @@ import AbstractAdapter from "./AbstractAdapter.js";

await makeDir(dirPath, {fs});
await mkdir(dirPath, {recursive: true});

@@ -232,5 +232,5 @@ const resourceSource = resource.getSource();

if (resourceSource.fsPath === fsPath) {
log.silly("Skip writing to %s (Resource hasn't been modified)", fsPath);
log.silly(`Skip writing to ${fsPath} (Resource hasn't been modified)`);
} else {
log.silly("Copying resource from %s to %s", resourceSource.fsPath, fsPath);
log.silly(`Copying resource from ${resourceSource.fsPath} to ${fsPath}`);
await copyFile(resourceSource.fsPath, fsPath);

@@ -244,3 +244,3 @@ if (readOnly) {

log.silly("Writing to %s", fsPath);
log.silly(`Writing to ${fsPath}`);

@@ -247,0 +247,0 @@ return new Promise((resolve, reject) => {

@@ -31,2 +31,31 @@ import logger from "@ui5/logger";

/**
* Matches and returns resources from a given map (either _virFiles or _virDirs).
*
* @private
* @param {string[]} patterns
* @param {object} resourceMap
* @returns {Promise<module:@ui5/fs.Resource[]>}
*/
async _matchPatterns(patterns, resourceMap) {
const resourcePaths = Object.keys(resourceMap);
const matchedPaths = micromatch(resourcePaths, patterns, {
dot: true
});
return await Promise.all(matchedPaths.map((virPath) => {
const resource = resourceMap[virPath];
if (resource) {
return this._cloneResource(resource);
}
}));
}
async _cloneResource(resource) {
const clonedResource = await resource.clone();
if (this._project) {
clonedResource.setProject(this._project);
}
return clonedResource;
}
/**
* Locate resources by glob.

@@ -59,18 +88,7 @@ *

const filePaths = Object.keys(this._virFiles);
const matchedFilePaths = micromatch(filePaths, patterns, {
dot: true
});
let matchedResources = matchedFilePaths.map((virPath) => {
return this._virFiles[virPath];
});
let matchedResources = await this._matchPatterns(patterns, this._virFiles);
if (!options.nodir) {
const dirPaths = Object.keys(this._virDirs);
const matchedDirs = micromatch(dirPaths, patterns, {
dot: true
});
matchedResources = matchedResources.concat(matchedDirs.map((virPath) => {
return this._virDirs[virPath];
}));
const matchedDirs = await this._matchPatterns(patterns, this._virDirs);
matchedResources = matchedResources.concat(matchedDirs);
}

@@ -90,24 +108,21 @@

*/
_byPath(virPath, options, trace) {
async _byPath(virPath, options, trace) {
if (this.isPathExcluded(virPath)) {
return Promise.resolve(null);
return null;
}
return new Promise((resolve, reject) => {
if (!virPath.startsWith(this._virBasePath) && virPath !== this._virBaseDir) {
// Neither starts with basePath, nor equals baseDirectory
resolve(null);
return;
}
if (!virPath.startsWith(this._virBasePath) && virPath !== this._virBaseDir) {
// Neither starts with basePath, nor equals baseDirectory
return null;
}
const relPath = virPath.substr(this._virBasePath.length);
trace.pathCall();
const relPath = virPath.substr(this._virBasePath.length);
trace.pathCall();
const resource = this._virFiles[relPath];
const resource = this._virFiles[relPath];
if (!resource || (options.nodir && resource.getStatInfo().isDirectory())) {
resolve(null);
} else {
resolve(resource);
}
});
if (!resource || (options.nodir && resource.getStatInfo().isDirectory())) {
return null;
} else {
return await this._cloneResource(resource);
}
}

@@ -125,38 +140,35 @@

super._write(resource);
return new Promise((resolve, reject) => {
const relPath = resource.getPath().substr(this._virBasePath.length);
log.silly("Writing to virtual path %s", resource.getPath());
this._virFiles[relPath] = resource;
const relPath = resource.getPath().substr(this._virBasePath.length);
log.silly(`Writing to virtual path ${resource.getPath()}`);
this._virFiles[relPath] = await resource.clone();
// 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
// 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) => {
if (i >= 1) {
segment = pathSegments[i - 1] + "/" + segment;
}
pathSegments[i] = segment;
});
pathSegments.forEach((segment, i) => {
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] = this._createResource({
project: this._project,
source: {
adapter: "Memory"
},
statInfo: { // TODO: make closer to fs stat info
isDirectory: function() {
return true;
}
},
path: this._virBasePath + segment
});
}
for (let i = pathSegments.length - 1; i >= 0; i--) {
const segment = pathSegments[i];
if (!this._virDirs[segment]) {
this._virDirs[segment] = this._createResource({
project: this._project,
source: {
adapter: "Memory"
},
statInfo: { // TODO: make closer to fs stat info
isDirectory: function() {
return true;
}
},
path: this._virBasePath + segment
});
}
resolve();
});
}
}

@@ -163,0 +175,0 @@ }

@@ -24,2 +24,10 @@ import AbstractReaderWriter from "./AbstractReaderWriter.js";

super(name);
if (!reader) {
throw new Error(`Cannot create DuplexCollection ${this._name}: No reader provided`);
}
if (!writer) {
throw new Error(`Cannot create DuplexCollection ${this._name}: No writer provided`);
}
this._reader = reader;

@@ -77,3 +85,4 @@ this._writer = writer;

* @param {@ui5/fs/tracing.Trace} trace Trace instance
* @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
* @returns {Promise<@ui5/fs/Resource|null>}
* Promise resolving to a single resource or <code>null</code> if no resource is found
*/

@@ -80,0 +89,0 @@ _byPath(virPath, options, trace) {

@@ -17,7 +17,11 @@ import AbstractReader from "./AbstractReader.js";

* @param {string} parameters.name The collection name
* @param {@ui5/fs/AbstractReader[]} parameters.readers List of resource readers (all tried in parallel)
* @param {@ui5/fs/AbstractReader[]} [parameters.readers]
* List of resource readers (all tried in parallel).
* If none are provided, the collection will never return any results.
*/
constructor({name, readers}) {
super(name);
this._readers = readers;
// Remove any undefined (empty) readers from array
this._readers = readers.filter(($) => $);
}

@@ -51,3 +55,4 @@

* @param {@ui5/fs/tracing.Trace} trace Trace instance
* @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
* @returns {Promise<@ui5/fs/Resource|null>}
* Promise resolving to a single resource or <code>null</code> if no resource is found
*/

@@ -59,10 +64,9 @@ _byPath(virPath, options, trace) {

if (this._readers.length === 0) {
// Promise.race doesn't resolve for empty arrays
return Promise.resolve();
if (resourceLocatorCount === 0) {
// Short-circuit if there are no readers (Promise.race does not settle for empty arrays)
trace.collection(that._name);
return Promise.resolve(null);
}
/* Promise.race to cover the following (self defined) requirement:
Deliver files that can be found fast at the cost of slower response times for files that cannot be found.
*/
// Using Promise.race to deliver files that can be found as fast as possible
return Promise.race(this._readers.map(function(resourceLocator) {

@@ -69,0 +73,0 @@ return resourceLocator._byPath(virPath, options, trace).then(function(resource) {

@@ -17,8 +17,11 @@ import AbstractReader from "./AbstractReader.js";

* @param {string} parameters.name The collection name
* @param {@ui5/fs/AbstractReader[]} parameters.readers Prioritized list of resource readers
* (first is tried first)
* @param {@ui5/fs/AbstractReader[]} [parameters.readers]
* Prioritized list of resource readers (tried in the order provided).
* If none are provided, the collection will never return any results.
*/
constructor({readers, name}) {
super(name);
this._readers = readers;
// Remove any undefined (empty) readers from array
this._readers = readers.filter(($) => $);
}

@@ -66,3 +69,4 @@

* @param {@ui5/fs/tracing.Trace} trace Trace instance
* @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
* @returns {Promise<@ui5/fs/Resource|null>}
* Promise resolving to a single resource or <code>null</code> if no resource is found
*/

@@ -69,0 +73,0 @@ _byPath(virPath, options, trace) {

@@ -61,3 +61,3 @@ import stream from "node:stream";

// Indicator for adapters like FileSystem to detect whether a resource has been changed
this._source.modified = false;
this._source.modified = this._source.modified || false;
}

@@ -318,3 +318,3 @@ this.__project = project; // Two underscores since "_project" was widely used in UI5 Tooling 2.0

statInfo: clone(this._statInfo),
source: this._source
source: clone(this._source)
};

@@ -335,2 +335,9 @@

* Retrieve the project assigned to the resource
* <br/>
* <b>Note for UI5 Tooling extensions (i.e. custom tasks, custom middleware):</b>
* In order to ensure compatibility across UI5 Tooling versions, consider using the
* <code>getProject(resource)</code> method provided by
* [TaskUtil]{@link module:@ui5/project/build/helpers/TaskUtil} and
* [MiddlewareUtil]{@link module:@ui5/server.middleware.MiddlewareUtil}, which will
* return a Specification Version-compatible Project interface.
*

@@ -337,0 +344,0 @@ * @public

@@ -190,2 +190,9 @@ import Resource from "./Resource.js";

* Retrieve the project assigned to the resource
* <br/>
* <b>Note for UI5 Tooling extensions (i.e. custom tasks, custom middleware):</b>
* In order to ensure compatibility across UI5 Tooling versions, consider using the
* <code>getProject(resource)</code> method provided by
* [TaskUtil]{@link module:@ui5/project/build/helpers/TaskUtil} and
* [MiddlewareUtil]{@link module:@ui5/server.middleware.MiddlewareUtil}, which will
* return a Specification Version-compatible Project interface.
*

@@ -192,0 +199,0 @@ * @public

@@ -35,7 +35,7 @@ import AbstractReaderWriter from "./AbstractReaderWriter.js";

if (!writerMapping) {
throw new Error("Missing parameter 'writerMapping'");
throw new Error(`Cannot create WriterCollection ${this._name}: Missing parameter 'writerMapping'`);
}
const basePaths = Object.keys(writerMapping);
if (!basePaths.length) {
throw new Error("Empty parameter 'writerMapping'");
throw new Error(`Cannot create WriterCollection ${this._name}: Empty parameter 'writerMapping'`);
}

@@ -42,0 +42,0 @@

{
"name": "@ui5/fs",
"version": "3.0.0-beta.4",
"version": "3.0.0-rc.0",
"description": "UI5 Tooling - File System Abstraction",

@@ -124,10 +124,9 @@ "author": {

"dependencies": {
"@ui5/logger": "^3.0.1-beta.1",
"@ui5/logger": "^3.0.1-rc.0",
"clone": "^2.1.2",
"escape-string-regexp": "^5.0.0",
"globby": "^13.1.2",
"globby": "^13.1.3",
"graceful-fs": "^4.2.10",
"make-dir": "^3.1.0",
"micromatch": "^4.0.5",
"minimatch": "^5.1.0",
"minimatch": "^5.1.1",
"pretty-hrtime": "^1.0.3",

@@ -145,7 +144,7 @@ "random-int": "^3.0.0"

"docdash": "^2.0.0",
"eslint": "^8.28.0",
"eslint": "^8.30.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-ava": "^13.2.0",
"eslint-plugin-jsdoc": "^37.9.7",
"esmock": "^2.0.9",
"eslint-plugin-jsdoc": "^39.6.4",
"esmock": "^2.1.0",
"jsdoc": "^3.6.11",

@@ -155,3 +154,3 @@ "nyc": "^15.1.0",

"rimraf": "^3.0.2",
"sinon": "^14.0.2",
"sinon": "^15.0.1",
"tap-nyan": "^1.1.0",

@@ -158,0 +157,0 @@ "tap-xunit": "^2.4.1"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc