diff --git a/v3/api/@ui5_fs_AbstractReader.html b/v3/api/@ui5_fs_AbstractReader.html new file mode 100644 index 0000000000..93d4c7d47b --- /dev/null +++ b/v3/api/@ui5_fs_AbstractReader.html @@ -0,0 +1,830 @@ + + + + + + @ui5/fs/AbstractReader - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/AbstractReader

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/AbstractReader + +

+ +
Abstract resource locator implementing the general API for reading resources
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

(abstract) new @ui5/fs/AbstractReader(name)

+ + + + + + +
+ +
Description:
+
  • The constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + Name of the reader. Typically used for tracing purposes
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_AbstractReaderWriter.html b/v3/api/@ui5_fs_AbstractReaderWriter.html new file mode 100644 index 0000000000..dc86fa3880 --- /dev/null +++ b/v3/api/@ui5_fs_AbstractReaderWriter.html @@ -0,0 +1,1171 @@ + + + + + + @ui5/fs/AbstractReaderWriter - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/AbstractReaderWriter

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/AbstractReaderWriter + +

+ +
Abstract resource locator implementing the general API for reading and writing resources
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

(abstract) new @ui5/fs/AbstractReaderWriter(name)

+ + + + + + +
+ +
Description:
+
  • The constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + Name of the reader/writer. Typically used for tracing purposes
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

write(resource, optionsopt) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Writes the content of a resource to a path.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + Resource to write
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
readOnly + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be written read-only + Do not use in conjunction with the drain option. + The written file will be used as the new source of this resources content. + Therefore the written file should not be altered by any means. + Activating this option might improve overall memory consumption.
drain + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be emptied during the write process. + Do not use in conjunction with the readOnly option. + Activating this option might improve overall memory consumption. + This should be used in cases where this is the last access to the resource. + E.g. the final write of a resource after all processing is finished.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_DuplexCollection.html b/v3/api/@ui5_fs_DuplexCollection.html new file mode 100644 index 0000000000..c3ccc8d309 --- /dev/null +++ b/v3/api/@ui5_fs_DuplexCollection.html @@ -0,0 +1,1318 @@ + + + + + + @ui5/fs/DuplexCollection - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/DuplexCollection

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/DuplexCollection + +

+ +
Wrapper to keep readers and writers together
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/DuplexCollection(parameters)

+ + + + + + +
+ +
Description:
+
  • The Constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
reader + + +@ui5/fs/AbstractReader + + + + + + + + + + + + + Single reader or collection of readers
writer + + +@ui5/fs/AbstractReaderWriter + + + + + + + + + + + + + A ReaderWriter instance which is only used for writing files
name + + +string + + + + + + + <optional>
+ + + + + +
+ + "" + + The collection name
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

write(resource, optionsopt) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Writes the content of a resource to a path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + Resource to write
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
readOnly + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be written read-only + Do not use in conjunction with the drain option. + The written file will be used as the new source of this resources content. + Therefore the written file should not be altered by any means. + Activating this option might improve overall memory consumption.
drain + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be emptied during the write process. + Do not use in conjunction with the readOnly option. + Activating this option might improve overall memory consumption. + This should be used in cases where this is the last access to the resource. + E.g. the final write of a resource after all processing is finished.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_ReaderCollection.html b/v3/api/@ui5_fs_ReaderCollection.html new file mode 100644 index 0000000000..8e766a3b35 --- /dev/null +++ b/v3/api/@ui5_fs_ReaderCollection.html @@ -0,0 +1,946 @@ + + + + + + @ui5/fs/ReaderCollection - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/ReaderCollection

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/ReaderCollection + +

+ +
Resource Locator ReaderCollection
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/ReaderCollection(parameters)

+ + + + + + +
+ +
Description:
+
  • The constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
name + + +string + + + + + + + + + + + The collection name
readers + + +Array.<@ui5/fs/AbstractReader> + + + + + + + <optional>
+ + + + + +
List of resource readers (all tried in parallel). + If none are provided, the collection will never return any results.
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_ReaderCollectionPrioritized.html b/v3/api/@ui5_fs_ReaderCollectionPrioritized.html new file mode 100644 index 0000000000..79fbfcfb46 --- /dev/null +++ b/v3/api/@ui5_fs_ReaderCollectionPrioritized.html @@ -0,0 +1,946 @@ + + + + + + @ui5/fs/ReaderCollectionPrioritized - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/ReaderCollectionPrioritized

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/ReaderCollectionPrioritized + +

+ +
Prioritized Resource Locator Collection
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/ReaderCollectionPrioritized(parameters)

+ + + + + + +
+ +
Description:
+
  • The constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
name + + +string + + + + + + + + + + + The collection name
readers + + +Array.<@ui5/fs/AbstractReader> + + + + + + + <optional>
+ + + + + +
Prioritized list of resource readers (tried in the order provided). + If none are provided, the collection will never return any results.
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_Resource.html b/v3/api/@ui5_fs_Resource.html new file mode 100644 index 0000000000..193f4f1654 --- /dev/null +++ b/v3/api/@ui5_fs_Resource.html @@ -0,0 +1,2471 @@ + + + + + + @ui5/fs/Resource - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/Resource

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/Resource + +

+ +
Resource. UI5 Tooling specific representation of a file's content and metadata
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/Resource(parameters)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
path + + +string + + + + + + + + + + + Absolute virtual path of the resource
statInfo + + +fs.Stats +| + +object + + + + + + + <optional>
+ + + + + +
File information. Instance of + fs.Stats or similar object
buffer + + +Buffer + + + + + + + <optional>
+ + + + + +
Content of this resources as a Buffer instance + (cannot be used in conjunction with parameters string, stream or createStream)
string + + +string + + + + + + + <optional>
+ + + + + +
Content of this resources as a string + (cannot be used in conjunction with parameters buffer, stream or createStream)
stream + + +Stream + + + + + + + <optional>
+ + + + + +
Readable stream of the content of this resource + (cannot be used in conjunction with parameters buffer, string or createStream)
createStream + + +@ui5/fs/Resource~createStream + + + + + + + <optional>
+ + + + + +
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
project + + +@ui5/project/specifications/Project + + + + + + + <optional>
+ + + + + +
Project this resource is associated with
sourceMetadata + + +object + + + + + + + <optional>
+ + + + + +
Source metadata for UI5 Tooling internal use. + Typically set by an adapter to store information for later retrieval.
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) clone() → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Returns a clone of the resource. The clones content is independent from that of the original resource
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with the clone +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

(async) getBuffer() → {Promise.<Buffer>}

+ + + + + + +
+ +
Description:
+
  • Gets a buffer with the resource content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with a buffer of the resource content. +
+ + + +
+
+ Type +
+
+ +Promise.<Buffer> + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the resource name
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Name of the resource +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the virtual resources path
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Virtual path of the resource +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getProject() → {@ui5/project/specifications/Project}

+ + + + + + +
+ +
Description:
+
  • Retrieve the project assigned to the resource +
    +Note for UI5 Tooling extensions (i.e. custom tasks, custom middleware): +In order to ensure compatibility across UI5 Tooling versions, consider using the +getProject(resource) method provided by +TaskUtil and +MiddlewareUtil, which will +return a Specification Version-compatible Project interface.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project this resource is associated with +
+ + + +
+
+ Type +
+
+ +@ui5/project/specifications/Project + + + +
+
+ + + + + + + + + + +

getStatInfo() → {fs.Stats|object}

+ + + + + + +
+ +
Description:
+
  • 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 instance.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Instance of fs.Stats + or similar object +
+ + + +
+
+ Type +
+
+ +fs.Stats +| + +object + + + +
+
+ + + + + + + + + + +

getStream() → {stream.Readable}

+ + + + + + +
+ +
Description:
+
  • 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, setBuffer +or setString). This +is to prevent consumers from accessing drained streams.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Readable stream for the resource content. +
+ + + +
+
+ Type +
+
+ +stream.Readable + + + +
+
+ + + + + + + + + + +

getString() → {Promise.<string>}

+ + + + + + +
+ +
Description:
+
  • Gets a string with the resource content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with the resource content. +
+ + + +
+
+ Type +
+
+ +Promise.<string> + + + +
+
+ + + + + + + + + + +

hasProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether a project has been assigned to the resource
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the resource is associated with a project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

isModified() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the content of this resource has been changed during its life cycle
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the resource's content has been changed +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

setBuffer(buffer)

+ + + + + + +
+ +
Description:
+
  • Sets a Buffer as content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buffer + + +Buffer + + + + + Buffer instance
+ + + + + + + + + + + + + + + + + + + + + + + + +

setPath(path)

+ + + + + + +
+ +
Description:
+
  • Sets the virtual resources path
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + + + Absolute virtual path of the resource
+ + + + + + + + + + + + + + + + + + + + + + + + +

setProject(project)

+ + + + + + +
+ +
Description:
+
  • Assign a project to the resource
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
project + + +@ui5/project/specifications/Project + + + + + Project this resource is associated with
+ + + + + + + + + + + + + + + + + + + + + + + + +

setStream(stream)

+ + + + + + +
+ +
Description:
+
  • Sets a readable stream as content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
stream + + +stream.Readable +| + +@ui5/fs/Resource~createStream + + + + + Readable stream of the resource content or + callback for dynamic creation of a readable stream
+ + + + + + + + + + + + + + + + + + + + + + + + +

setString(string)

+ + + + + + +
+ +
Description:
+
  • Sets a String as content
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
string + + +string + + + + + Resource content
+ + + + + + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + + + + +

createStream() → {stream.Readable}

+ + + + + + +
+ +
Description:
+
  • Function for dynamic creation of content streams
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A readable stream of a resources content +
+ + + +
+
+ Type +
+
+ +stream.Readable + + + +
+
+ + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_ResourceFacade.html b/v3/api/@ui5_fs_ResourceFacade.html new file mode 100644 index 0000000000..c63da95e08 --- /dev/null +++ b/v3/api/@ui5_fs_ResourceFacade.html @@ -0,0 +1,2125 @@ + + + + + + @ui5/fs/ResourceFacade - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/ResourceFacade

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/ResourceFacade + +

+ +
A Resource with a different path than it's original
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/ResourceFacade(parameters)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + + + Virtual path of the facade resource
resource + + +@ui5/fs/Resource + + + + + Resource to conceal
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) clone() → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Returns a clone of the resource. The clones content is independent from that of the original resource. +A ResourceFacade becomes a Resource
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with the clone +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

(async) getBuffer() → {Promise.<Buffer>}

+ + + + + + +
+ +
Description:
+
  • Gets a buffer with the resource content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with a buffer of the resource content. +
+ + + +
+
+ Type +
+
+ +Promise.<Buffer> + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the resource name
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Name of the resource +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the resources path
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ (Virtual) path of the resource +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getProject() → {@ui5/project/specifications/Project}

+ + + + + + +
+ +
Description:
+
  • Retrieve the project assigned to the resource +
    +Note for UI5 Tooling extensions (i.e. custom tasks, custom middleware): +In order to ensure compatibility across UI5 Tooling versions, consider using the +getProject(resource) method provided by +TaskUtil and +MiddlewareUtil, which will +return a Specification Version-compatible Project interface.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project this resource is associated with +
+ + + +
+
+ Type +
+
+ +@ui5/project/specifications/Project + + + +
+
+ + + + + + + + + + +

getStatInfo() → {fs.Stats|object}

+ + + + + + +
+ +
Description:
+
  • 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 instance.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Instance of fs.Stats + or similar object +
+ + + +
+
+ Type +
+
+ +fs.Stats +| + +object + + + +
+
+ + + + + + + + + + +

getStream() → {stream.Readable}

+ + + + + + +
+ +
Description:
+
  • 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, setBuffer +or setString). This +is to prevent consumers from accessing drained streams.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Readable stream for the resource content. +
+ + + +
+
+ Type +
+
+ +stream.Readable + + + +
+
+ + + + + + + + + + +

getString() → {Promise.<string>}

+ + + + + + +
+ +
Description:
+
  • Gets a string with the resource content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with the resource content. +
+ + + +
+
+ Type +
+
+ +Promise.<string> + + + +
+
+ + + + + + + + + + +

hasProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether a project has been assigned to the resource
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the resource is associated with a project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

isModified() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the content of this resource has been changed during its life cycle
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the resource's content has been changed +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

setBuffer(buffer)

+ + + + + + +
+ +
Description:
+
  • Sets a Buffer as content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buffer + + +Buffer + + + + + Buffer instance
+ + + + + + + + + + + + + + + + + + + + + + + + +

setPath(path)

+ + + + + + +
+ +
Description:
+
  • Sets the resources path
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + + + (Virtual) path of the resource
+ + + + + + + + + + + + + + + + + + + + + + + + +

setProject(project)

+ + + + + + +
+ +
Description:
+
  • Assign a project to the resource
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
project + + +@ui5/project/specifications/Project + + + + + Project this resource is associated with
+ + + + + + + + + + + + + + + + + + + + + + + + +

setStream(stream)

+ + + + + + +
+ +
Description:
+
  • Sets a readable stream as content.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
stream + + +stream.Readable +| + +@ui5/fs/Resource~createStream + + + + + Readable stream of the resource content or + callback for dynamic creation of a readable stream
+ + + + + + + + + + + + + + + + + + + + + + + + +

setString(string)

+ + + + + + +
+ +
Description:
+
  • Sets a String as content
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
string + + +string + + + + + Resource content
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_WriterCollection.html b/v3/api/@ui5_fs_WriterCollection.html new file mode 100644 index 0000000000..504641f414 --- /dev/null +++ b/v3/api/@ui5_fs_WriterCollection.html @@ -0,0 +1,1261 @@ + + + + + + @ui5/fs/WriterCollection - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/WriterCollection

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/WriterCollection + +

+ +
Resource Locator WriterCollection
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/WriterCollection(parameters)

+ + + + + + +
+ +
Description:
+
  • The constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
new WriterCollection({
+    name: "Writer Collection",
+    writerMapping: {
+	       "/": writerA,
+	       "/my/path/": writerB,
+    }
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + The collection name
writerMapping + + +object.<string, @ui5/fs/AbstractReaderWriter> + + + + + Mapping of virtual base paths to writers. Path are matched greedy
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

write(resource, optionsopt) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Writes the content of a resource to a path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + Resource to write
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
readOnly + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be written read-only + Do not use in conjunction with the drain option. + The written file will be used as the new source of this resources content. + Therefore the written file should not be altered by any means. + Activating this option might improve overall memory consumption.
drain + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be emptied during the write process. + Do not use in conjunction with the readOnly option. + Activating this option might improve overall memory consumption. + This should be used in cases where this is the last access to the resource. + E.g. the final write of a resource after all processing is finished.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_adapters_AbstractAdapter.html b/v3/api/@ui5_fs_adapters_AbstractAdapter.html new file mode 100644 index 0000000000..d63156984a --- /dev/null +++ b/v3/api/@ui5_fs_adapters_AbstractAdapter.html @@ -0,0 +1,1304 @@ + + + + + + @ui5/fs/adapters/AbstractAdapter - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/adapters/AbstractAdapter

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/adapters/AbstractAdapter + +

+ +
Abstract Resource Adapter
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

(abstract) new @ui5/fs/adapters/AbstractAdapter(parameters)

+ + + + + + +
+ +
Description:
+
  • The constructor
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virBasePath + + +string + + + + + + + + + + + Virtual base path. Must be absolute, POSIX-style, and must end with a slash
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
List of glob patterns to exclude
project + + +object + + + + + + + <optional>
+ + + + + +
Experimental, internal parameter. Do not use
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

write(resource, optionsopt) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Writes the content of a resource to a path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + Resource to write
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
readOnly + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be written read-only + Do not use in conjunction with the drain option. + The written file will be used as the new source of this resources content. + Therefore the written file should not be altered by any means. + Activating this option might improve overall memory consumption.
drain + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be emptied during the write process. + Do not use in conjunction with the readOnly option. + Activating this option might improve overall memory consumption. + This should be used in cases where this is the last access to the resource. + E.g. the final write of a resource after all processing is finished.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_adapters_FileSystem.html b/v3/api/@ui5_fs_adapters_FileSystem.html new file mode 100644 index 0000000000..852dd13f56 --- /dev/null +++ b/v3/api/@ui5_fs_adapters_FileSystem.html @@ -0,0 +1,1394 @@ + + + + + + @ui5/fs/adapters/FileSystem - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/adapters/FileSystem

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/adapters/FileSystem + +

+ +
File system resource adapter
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/adapters/FileSystem(parameters)

+ + + + + + +
+ +
Description:
+
  • The Constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
virBasePath + + +string + + + + + + + + + + + + + Virtual base path. Must be absolute, POSIX-style, and must end with a slash
fsBasePath + + +string + + + + + + + + + + + + + File System base path. Must be absolute and must use platform-specific path segment separators
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + List of glob patterns to exclude
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + false + + Whether to apply any excludes defined in an optional .gitignore in the given fsBasePath directory
project + + +@ui5/project/specifications/Project + + + + + + + <optional>
+ + + + + +
+ + Project this adapter belongs to (if any)
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

write(resource, optionsopt) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Writes the content of a resource to a path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + Resource to write
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
readOnly + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be written read-only + Do not use in conjunction with the drain option. + The written file will be used as the new source of this resources content. + Therefore the written file should not be altered by any means. + Activating this option might improve overall memory consumption.
drain + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be emptied during the write process. + Do not use in conjunction with the readOnly option. + Activating this option might improve overall memory consumption. + This should be used in cases where this is the last access to the resource. + E.g. the final write of a resource after all processing is finished.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_adapters_Memory.html b/v3/api/@ui5_fs_adapters_Memory.html new file mode 100644 index 0000000000..b8d886b289 --- /dev/null +++ b/v3/api/@ui5_fs_adapters_Memory.html @@ -0,0 +1,1304 @@ + + + + + + @ui5/fs/adapters/Memory - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/adapters/Memory

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/adapters/Memory + +

+ +
Virtual resource Adapter
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/adapters/Memory(parameters)

+ + + + + + +
+ +
Description:
+
  • The constructor.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virBasePath + + +string + + + + + + + + + + + Virtual base path. Must be absolute, POSIX-style, and must end with a slash
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
List of glob patterns to exclude
project + + +@ui5/project/specifications/Project + + + + + + + <optional>
+ + + + + +
Project this adapter belongs to (if any)
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + +

write(resource, optionsopt) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Writes the content of a resource to a path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + Resource to write
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
readOnly + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be written read-only + Do not use in conjunction with the drain option. + The written file will be used as the new source of this resources content. + Therefore the written file should not be altered by any means. + Activating this option might improve overall memory consumption.
drain + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether the resource content shall be emptied during the write process. + Do not use in conjunction with the readOnly option. + Activating this option might improve overall memory consumption. + This should be used in cases where this is the last access to the resource. + E.g. the final write of a resource after all processing is finished.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_readers_Filter.html b/v3/api/@ui5_fs_readers_Filter.html new file mode 100644 index 0000000000..7658529e45 --- /dev/null +++ b/v3/api/@ui5_fs_readers_Filter.html @@ -0,0 +1,1087 @@ + + + + + + @ui5/fs/readers/Filter - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/readers/Filter

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/readers/Filter + +

+ +
A reader that allows dynamic filtering of resources passed through it
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/fs/readers/Filter(parameters)

+ + + + + + +
+ +
Description:
+
  • Constructor
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
reader + + +@ui5/fs/AbstractReader + + + + + The resource reader or collection to wrap
callback + + +@ui5/fs/readers/Filter~callback + + + + + Filter function. Will be called for every resource read through this reader.
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + + + + +

callback(resource) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Filter callback
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resource + + +@ui5/fs/Resource + + + + + Resource to test
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Whether to keep the resource +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_fs_readers_Link.html b/v3/api/@ui5_fs_readers_Link.html new file mode 100644 index 0000000000..a1565892e0 --- /dev/null +++ b/v3/api/@ui5_fs_readers_Link.html @@ -0,0 +1,941 @@ + + + + + + @ui5/fs/readers/Link - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/readers/Link

+ + + + + + + +
+ +
+ +

+ + @ui5/fs/readers/Link + +

+ +
A reader that allows for rewriting paths segments of all resources passed through it.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + + + + + + + + +
+ +
Description:
+
  • Constructor
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
import Link from "@ui5/fs/readers/Link";
+const linkedReader = new Link({
+    reader: sourceReader,
+    pathMapping: {
+         linkPath: `/app`,
+         targetPath: `/resources/my-app-name/`
+     }
+});
+
+// The following resolves with a @ui5/fs/ResourceFacade of the resource
+// located at "/resources/my-app-name/Component.js" in the sourceReader
+const resource = await linkedReader.byPath("/app/Component.js");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
reader + + +@ui5/fs/AbstractReader + + + + + The resource reader or collection to wrap
pathMapping + + +@ui5/fs/readers/Link/PathMapping + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

byGlob(virPattern, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching glob patterns.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
byGlob("**‏/*.{html,htm}");
+byGlob("**‏/.library");
+byGlob("/pony/*");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPattern + + +string +| + +Array.<string> + + + + + + + + + + + glob pattern as string or array of glob patterns for + virtual directory structure
options + + +object + + + + + + + <optional>
+ + + + + +
glob options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to list of resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

byPath(virPath, optionsopt) → {Promise.<@ui5/fs/Resource>}

+ + + + + + +
+ +
Description:
+
  • Locates resources by matching a given path.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virPath + + +string + + + + + + + + + + + Virtual path
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
nodir + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Do not match directories
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a single resource +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/fs/Resource> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_logger_Logger.html b/v3/api/@ui5_logger_Logger.html new file mode 100644 index 0000000000..7433218c82 --- /dev/null +++ b/v3/api/@ui5_logger_Logger.html @@ -0,0 +1,1911 @@ + + + + + + @ui5/logger/Logger - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/logger/Logger

+ + + + + + + +
+ +
+ +

+ + @ui5/logger/Logger + +

+ +
Standard logging module for UI5 Tooling and extensions. +

+Emits ui5.log events on the process object, +which can be handled by dedicated writers, +like @ui5/logger/writers/Console. +

+If no listener is attached to an event, messages are written directly to the process.stderr stream.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/logger/Logger(moduleName)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
moduleName + + +string + + + + + Identifier for messages created by this logger. +Example: module:submodule:Class
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + +

Members

+ + + +

LOG_EVENT_NAME :string

+ + + + + +
+ +
Description:
+
  • Event name used for emitting new log-message event on the +process object
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Event name used for emitting new log-message event on the +process object +
+ + + +
Type:
+
    +
  • + +string + + + +
  • +
+ + + + + + + + +

LOG_LEVELS :Array.<string>

+ + + + + +
+ +
Description:
+
  • Available log levels, ordered by priority: +
    +
      +
    1. silly
    2. +
    3. verbose
    4. +
    5. perf
    6. +
    7. info (default)
    8. +
    9. warn
    10. +
    11. error
    12. +
    13. silent
    14. +
    + +Log level silent is special in the sense that no messages can be submitted with that level. +It can be used to suppress all logging.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Available log levels, ordered by priority: +
+
    +
  1. silly
  2. +
  3. verbose
  4. +
  5. perf
  6. +
  7. info (default)
  8. +
  9. warn
  10. +
  11. error
  12. +
  13. silent
  14. +
+ +Log level silent is special in the sense that no messages can be submitted with that level. +It can be used to suppress all logging. +
+ + + +
Type:
+
    +
  • + +Array.<string> + + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

error(…message)

+ + + + + + +
+ +
Description:
+
  • Create a log entry with the error level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
message + + +any + + + + + + + + + + + <repeatable>
+ +
Messages to log. An automatic string conversion is applied if necessary
+ + + + + + + + + + + + + + + + + + + + + + + + +

info(…message)

+ + + + + + +
+ +
Description:
+
  • Create a log entry with the info level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
message + + +any + + + + + + + + + + + <repeatable>
+ +
Messages to log. An automatic string conversion is applied if necessary
+ + + + + + + + + + + + + + + + + + + + + + + + +

isLevelEnabled(levelName) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Tests whether the provided log level is enabled by the current log level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
levelName + + +string + + + + + Log level to test
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided level is enabled +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

perf(…message)

+ + + + + + +
+ +
Description:
+
  • Create a log entry with the perf level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
message + + +any + + + + + + + + + + + <repeatable>
+ +
Messages to log. An automatic string conversion is applied if necessary
+ + + + + + + + + + + + + + + + + + + + + + + + +

silly(…message)

+ + + + + + +
+ +
Description:
+
  • Create a log entry with the silly level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
message + + +any + + + + + + + + + + + <repeatable>
+ +
Messages to log. An automatic string conversion is applied if necessary
+ + + + + + + + + + + + + + + + + + + + + + + + +

verbose(…message)

+ + + + + + +
+ +
Description:
+
  • Create a log entry with the verbose level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
message + + +any + + + + + + + + + + + <repeatable>
+ +
Messages to log. An automatic string conversion is applied if necessary
+ + + + + + + + + + + + + + + + + + + + + + + + +

warn(…message)

+ + + + + + +
+ +
Description:
+
  • Create a log entry with the warn level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
message + + +any + + + + + + + + + + + <repeatable>
+ +
Messages to log. An automatic string conversion is applied if necessary
+ + + + + + + + + + + + + + + + + + + + + + + + +

(static) getLevel() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the current log level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ The current log level. Defaults to info +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

(static) isLevelEnabled(levelName) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Tests whether the provided log level is enabled by the current log level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
levelName + + +string + + + + + Log level to test
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided level is enabled +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) setLevel(levelName)

+ + + + + + +
+ +
Description:
+
  • Sets the standard log level. +
    +Example: Setting it to perf would suppress all silly and verbose +logging, and only show perf, info, warn and error logs.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
levelName + + +string + + + + + New log level
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_logger_writers_Console.html b/v3/api/@ui5_logger_writers_Console.html new file mode 100644 index 0000000000..afe835da5d --- /dev/null +++ b/v3/api/@ui5_logger_writers_Console.html @@ -0,0 +1,482 @@ + + + + + + @ui5/logger/writers/Console - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/logger/writers/Console

+ + + + + + + +
+ +
+ +

+ + @ui5/logger/writers/Console + +

+ +
Standard handler for events emitted by @ui5/logger modules. Writes messages to +process.stderr stream +and renders a progress bar for UI5 Tooling build processes. +

+The progress bar is only used in interactive terminals. If verbose logging is enabled, the progress +bar is disabled.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/logger/writers/Console()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

disable()

+ + + + + + +
+ +
Description:
+
  • Detaches all event listeners and stops writing to output stream
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

enable()

+ + + + + + +
+ +
Description:
+
  • Attaches all event listeners and starts writing to output stream
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

(static) init()

+ + + + + + +
+ +
Description:
+
  • Creates a new instance and subscribes it to all events
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_build_ProjectBuilder.html b/v3/api/@ui5_project_build_ProjectBuilder.html new file mode 100644 index 0000000000..2af896d35d --- /dev/null +++ b/v3/api/@ui5_project_build_ProjectBuilder.html @@ -0,0 +1,1531 @@ + + + + + + @ui5/project/build/ProjectBuilder - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/build/ProjectBuilder

+ + + + + + + +
+ +
+ +

+ + @ui5/project/build/ProjectBuilder + +

+ + +
+ +
+ +
+ + + + + +

new @ui5/project/build/ProjectBuilder(parameters)

+ + + + + + +
+ +
Description:
+
  • Executes a project build, including all necessary or requested dependencies
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
graph + + +@ui5/project/graph/ProjectGraph + + + + + + + + + + + Project graph
buildConfig + + +@ui5/project/build/ProjectBuilder~BuildConfiguration + + + + + + + <optional>
+ + + + + +
Build configuration
taskRepository + + +@ui5/builder/tasks/taskRepository + + + + + + + + + + + Task Repository module to use
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) build(parameters) → {Promise}

+ + + + + + +
+ +
Description:
+
  • Executes a project build, including all necessary or requested dependencies
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
destPath + + +string + + + + + + + + + + + + + Target path
cleanDest + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Decides whether project should clean the target path before build
includedDependencies + + +Array.<(string|RegExp)> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of names of projects to include in the build result + If the wildcard '*' is provided, all dependencies will be included in the build result.
excludedDependencies + + +Array.<(string|RegExp)> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of names of projects to exclude from the build result.
dependencyIncludes + + +@ui5/project/build/ProjectBuilder~DependencyIncludes + + + + + + + <optional>
+ + + + + +
+ + Alternative to the includedDependencies and excludedDependencies parameters. + Allows for a more sophisticated configuration for defining which dependencies should be + part of the build result. If this is provided, the other mentioned parameters are ignored.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once the build has finished +
+ + + +
+
+ Type +
+
+ +Promise + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

BuildConfiguration

+ + + + + +
+ +
Description:
+
  • Build Configuration
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
selfContained + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Flag to activate self contained build
cssVariables + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Flag to activate CSS variables generation
jsdoc + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Flag to activate JSDoc build
createBuildManifest + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Whether to create a build manifest file for the root project. + This is currently only supported for projects of type 'library' and 'theme-library' + No other dependencies can be included in the build result.
includedTasks + + +Array.<string> + + + + + + + <optional>
+ + + +
+ + [] + + List of tasks to be included
excludedTasks + + +Array.<string> + + + + + + + <optional>
+ + + +
+ + [] + + List of tasks to be excluded. + If the wildcard '*' is provided, only the included tasks will be executed.
+ + + + + + +
+ Build Configuration +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

DependencyIncludes

+ + + + + +
+ +
Description:
+
  • As an alternative to providing plain lists of names of dependencies to include and exclude, you can provide a +more complex "Dependency Includes" object to define which dependencies should be part of the build result. +
    +This information is then used to compile lists of includedDependencies and +excludedDependencies, which are applied during the build process. +

    +Regular expression-parameters are directly applied to a list of all project dependencies +so that they don't need to be evaluated in later processing steps. +

    +Generally, includes are handled with a higher priority than excludes. Additionally, operations for processing +transitive dependencies are handled with a lower priority than explicitly mentioned dependencies. The "default" +dependency-includes are appended at the end. +

    +The priority of the various dependency lists is applied in the following order. +Note that a later exclude can't overrule an earlier include. +
    +
      +
    1. includeDependency, includeDependencyRegExp
    2. +
    3. excludeDependency, excludeDependencyRegExp
    4. +
    5. includeDependencyTree
    6. +
    7. excludeDependencyTree
    8. +
    9. defaultIncludeDependency, defaultIncludeDependencyRegExp, + defaultIncludeDependencyTree
    10. +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
includeAllDependencies + + +boolean + + + + + Whether all dependencies should be part of the build result + This parameter has the lowest priority and basically includes all remaining (not excluded) projects as include
includeDependency + + +Array.<string> + + + + + The dependencies to be considered in includedDependencies; the + * character can be used as wildcard for all dependencies and + is an alias for the CLI option --all
includeDependencyRegExp + + +Array.<string> + + + + + Strings which are interpreted as regular expressions + to describe the selection of dependencies to be considered in includedDependencies
includeDependencyTree + + +Array.<string> + + + + + The dependencies to be considered in includedDependencies; + transitive dependencies are also appended
excludeDependency + + +Array.<string> + + + + + The dependencies to be considered in excludedDependencies
excludeDependencyRegExp + + +Array.<string> + + + + + Strings which are interpreted as regular expressions + to describe the selection of dependencies to be considered in excludedDependencies
excludeDependencyTree + + +Array.<string> + + + + + The dependencies to be considered in excludedDependencies; + transitive dependencies are also appended
defaultIncludeDependency + + +Array.<string> + + + + + Same as includeDependency parameter; + typically used in project build settings
defaultIncludeDependencyRegExp + + +Array.<string> + + + + + Same as includeDependencyRegExp parameter; + typically used in project build settings
defaultIncludeDependencyTree + + +Array.<string> + + + + + Same as includeDependencyTree parameter; + typically used in project build settings
+ + + + + + +
+ As an alternative to providing plain lists of names of dependencies to include and exclude, you can provide a +more complex "Dependency Includes" object to define which dependencies should be part of the build result. +
+This information is then used to compile lists of includedDependencies and +excludedDependencies, which are applied during the build process. +

+Regular expression-parameters are directly applied to a list of all project dependencies +so that they don't need to be evaluated in later processing steps. +

+Generally, includes are handled with a higher priority than excludes. Additionally, operations for processing +transitive dependencies are handled with a lower priority than explicitly mentioned dependencies. The "default" +dependency-includes are appended at the end. +

+The priority of the various dependency lists is applied in the following order. +Note that a later exclude can't overrule an earlier include. +
+
    +
  1. includeDependency, includeDependencyRegExp
  2. +
  3. excludeDependency, excludeDependencyRegExp
  4. +
  5. includeDependencyTree
  6. +
  7. excludeDependencyTree
  8. +
  9. defaultIncludeDependency, defaultIncludeDependencyRegExp, + defaultIncludeDependencyTree
  10. +
+
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_build_helpers_TaskUtil.html b/v3/api/@ui5_project_build_helpers_TaskUtil.html new file mode 100644 index 0000000000..5b662d026e --- /dev/null +++ b/v3/api/@ui5_project_build_helpers_TaskUtil.html @@ -0,0 +1,2434 @@ + + + + + + @ui5/project/build/helpers/TaskUtil - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/build/helpers/TaskUtil

+ + + + + + + +
+ +
+ +

+ + @ui5/project/build/helpers/TaskUtil + +

+ +
Convenience functions for UI5 tasks. +An instance of this class is passed to every standard UI5 task that requires it. + +Custom tasks that define a specification version >= 2.2 will receive an interface +to an instance of this class when called. +The set of available functions on that interface depends on the specification +version defined for the extension.
+ + +
+ +
+ + + + + + + + + + + + + + + +

Members

+ + + +

STANDARD_TAGS :@ui5/project/build/helpers/TaskUtil~StandardBuildTags

+ + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+ + + + + + + + + +

resourceFactory :@ui5/project/build/helpers/TaskUtil~resourceFactory

+ + + + + +
+ +
Description:
+
  • Provides limited access to @ui5/fs/resourceFactory functions + +

    +This attribute is only available to custom task extensions defining +Specification Version 3.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Provides limited access to @ui5/fs/resourceFactory functions + +

+This attribute is only available to custom task extensions defining +Specification Version 3.0 and above. +
+ + + +
Type:
+ + + + + + + + + + + +

Methods

+ + + + + + +

clearTag(resource, tag)

+ + + + + + +
+ +
Description:
+
  • Clears the value of a tag stored for the given resource's path. +It's like the tag was never set for that resource. + +

    +This method is only available to custom task extensions defining +Specification Version 2.2 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resource + + +@ui5/fs/Resource + + + + + Resource-instance the tag should be cleared for
tag + + +string + + + + + Tag
+ + + + + + + + + + + + + + + + + + + + + + + + +

getDependencies(projectNameopt) → {Array.<string>}

+ + + + + + +
+ +
Description:
+
  • Retrieve a list of direct dependencies of a given project from the dependency graph. +Note that this list does not include transitive dependencies. + +

    +This method is only available to custom task extensions defining +Specification Version 3.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectName + + +string + + + + + + + <optional>
+ + + + + +
Name of the project to retrieve. Defaults to the project currently being built
+ + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ If the requested project is unknown to the graph +
+
+
+
+
+
+ Type +
+
+ +Error + + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+ Names of all direct dependencies +
+ + + +
+
+ Type +
+
+ +Array.<string> + + + +
+
+ + + + + + + + + + +

getProject(projectNameOrResourceopt) → {@ui5/project/build/helpers/TaskUtil~ProjectInterface|undefined}

+ + + + + + +
+ +
Description:
+
  • Retrieve a single project from the dependency graph + +

    +This method is only available to custom task extensions defining +Specification Version 3.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectNameOrResource + + +string +| + +@ui5/fs/Resource + + + + + + + <optional>
+ + + + + +
Name of the project to retrieve or a Resource instance to retrieve the associated project for. +Defaults to the name of the project currently being built
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification Version-dependent interface to the Project instance or undefined +if the project name is unknown or the provided resource is not associated with any project. +
+ + + +
+
+ Type +
+
+ +@ui5/project/build/helpers/TaskUtil~ProjectInterface +| + +undefined + + + +
+
+ + + + + + + + + + +

getTag(resource, tag) → {string|boolean|integer|undefined}

+ + + + + + +
+ +
Description:
+
  • Retrieves the value for a stored tag. If no value is stored, undefined is returned. + +

    +This method is only available to custom task extensions defining +Specification Version 2.2 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resource + + +@ui5/fs/Resource + + + + + Resource-instance the tag should be retrieved for
tag + + +string + + + + + Name of the tag
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Tag value for the given resource. + undefined if no value is available +
+ + + +
+
+ Type +
+
+ +string +| + +boolean +| + +integer +| + +undefined + + + +
+
+ + + + + + + + + + +

isRootProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project currently being built is the root project. + +

    +This method is only available to custom task extensions defining +Specification Version 2.2 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ true if the currently built project is the root project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

registerCleanupTask(callback)

+ + + + + + +
+ +
Description:
+
  • Register a function that must be executed once the build is finished. This can be used to, for example, +clean up files temporarily created on the file system. If the callback returns a Promise, it will be waited for. +It will also be executed in cases where the build has failed or has been aborted. + +

    +This method is only available to custom task extensions defining +Specification Version 2.2 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + + Callback to register. If it returns a Promise, it will be waited for
+ + + + + + + + + + + + + + + + + + + + + + + + +

setTag(resource, tag, valueopt)

+ + + + + + +
+ +
Description:
+
  • Stores a tag with value for a given resource's path. Note that the tag is independent of the supplied +resource instance. For two resource instances with the same path, the same tag value is returned. +If the path of a resource is changed, any tag information previously stored for that resource is lost. + +

    +This method is only available to custom task extensions defining +Specification Version 2.2 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
resource + + +@ui5/fs/Resource + + + + + + + + + + + + + Resource-instance the tag should be stored for
tag + + +string + + + + + + + + + + + + + Name of the tag. Currently only the + STANDARD_TAGS are allowed
value + + +string +| + +boolean +| + +integer + + + + + + + <optional>
+ + + + + +
+ + true + + Tag value. Must be primitive
+ + + + + + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + +

ProjectInterface

+ + + + + +
+ +
Description:
+
  • Specification Version-dependent Project interface. +For details on individual functions, see Project
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
getType + + +function + + + + + Get the project type
getName + + +function + + + + + Get the project name
getVersion + + +function + + + + + Get the project version
getNamespace + + +function + + + + + Get the project namespace
getRootReader + + +function + + + + + Get the project rootReader
getReader + + +function + + + + + Get the project reader
getRootPath + + +function + + + + + Get the local File System path of the project's root directory
getSourcePath + + +function + + + + + Get the local File System path of the project's source directory
getCustomConfiguration + + +function + + + + + Get the project Custom Configuration
isFrameworkProject + + +function + + + + + Check whether the project is a UI5-Framework project
getFrameworkName + + +function + + + + + Get the project's framework name configuration
getFrameworkVersion + + +function + + + + + Get the project's framework version configuration
getFrameworkDependencies + + +function + + + + + Get the project's framework dependencies configuration
+ + + + + + +
+ Specification Version-dependent Project interface. +For details on individual functions, see Project +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

StandardBuildTags

+ + + + + +
+ +
Description:
+
  • Standard Build Tags. See UI5 Tooling +RFC 0008 +for details.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
OmitFromBuildResult + + +string + + + + + Setting this tag to true will prevent the resource from being written to the build target directory
IsBundle + + +string + + + + + This tag identifies resources that contain (i.e. bundle) multiple other resources
IsDebugVariant + + +string + + + + + This tag identifies resources that are a debug variant (typically named with a "-dbg" suffix) + of another resource. This tag is part of the build manifest.
HasDebugVariant + + +string + + + + + This tag identifies resources for which a debug variant has been created. + This tag is part of the build manifest.
+ + + + + + +
+ Standard Build Tags. See UI5 Tooling +RFC 0008 +for details. +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

resourceFactory

+ + + + + +
+ +
Description:
+
  • Specification Version-dependent set of @ui5/fs/resourceFactory +functions provided to tasks. +For details on individual functions, see @ui5/fs/resourceFactory
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
createResource + + +function + + + + + Creates a Resource. + Accepts the same parameters as the Resource constructor.
createReaderCollection + + +function + + + + + Creates a reader collection: + ReaderCollection
createReaderCollectionPrioritized + + +function + + + + + Creates a prioritized reader collection: + ReaderCollectionPrioritized
createFilterReader + + +function + + + + + Create a Filter-Reader with the given reader.
createLinkReader + + +function + + + + + Create a Link-Reader with the given reader.
createFlatReader + + +function + + + + + Create a Link-Reader +where all requests are prefixed with /resources/.
+ + + + + + +
+ Specification Version-dependent set of @ui5/fs/resourceFactory +functions provided to tasks. +For details on individual functions, see @ui5/fs/resourceFactory +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_config_Configuration.html b/v3/api/@ui5_project_config_Configuration.html new file mode 100644 index 0000000000..f8463e2b28 --- /dev/null +++ b/v3/api/@ui5_project_config_Configuration.html @@ -0,0 +1,933 @@ + + + + + + @ui5/project/config/Configuration - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/config/Configuration

+ + + + + + + +
+ +
+ +

+ + @ui5/project/config/Configuration + +

+ +
Provides basic configuration settings for @ui5/project/ui5Framework/* resolvers. +Reads/writes configuration from/to ~/.ui5rc
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/config/Configuration(configuration)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
configuration + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
mavenSnapshotEndpointUrl + + +string + + + + + + + <optional>
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getMavenSnapshotEndpointUrl() → {string}

+ + + + + + +
+ +
Description:
+
  • Maven Repository Snapshot URL. +Used to download artifacts and packages from Maven's build-snapshots URL.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

toJson() → {object}

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ The configuration in a JSON format +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

(async, static) fromFile(filePathopt) → {Promise.<@ui5/project/config/Configuration>}

+ + + + + + +
+ +
Description:
+
  • Creates Configuration from a JSON file
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
filePath + + +string + + + + + + + <optional>
+ + + + + +
+ + "~/.ui5rc" + + Path to configuration JSON file
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Configuration instance +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/project/config/Configuration> + + + +
+
+ + + + + + + + + + +

(async, static) toFile(config, filePathopt) → {Promise.<void>}

+ + + + + + +
+ +
Description:
+
  • Saves Configuration to a JSON file
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
config + + +@ui5/project/config/Configuration + + + + + + + + + + + + + Configuration to save
filePath + + +string + + + + + + + <optional>
+ + + + + +
+ + "~/.ui5rc" + + Path to configuration JSON file
+ + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Promise.<void> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_graph_ProjectGraph.html b/v3/api/@ui5_project_graph_ProjectGraph.html new file mode 100644 index 0000000000..40bd163329 --- /dev/null +++ b/v3/api/@ui5_project_graph_ProjectGraph.html @@ -0,0 +1,3833 @@ + + + + + + @ui5/project/graph/ProjectGraph - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/graph/ProjectGraph

+ + + + + + + +
+ +
+ +

+ + @ui5/project/graph/ProjectGraph + +

+ +
A rooted, directed graph representing a UI5 project, its dependencies and available extensions. +

+While it allows defining cyclic dependencies, both traversal functions will throw an error if they encounter cycles.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/graph/ProjectGraph(parameters)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
rootProjectName + + +string + + + + + Root project name
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

addExtension(extension)

+ + + + + + +
+ +
Description:
+
  • Add an extension to the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
extension + + +@ui5/project/specifications/Extension + + + + + Extension which should be available in the graph
+ + + + + + + + + + + + + + + + + + + + + + + + +

addProject(project)

+ + + + + + +
+ +
Description:
+
  • Add a project to the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
project + + +@ui5/project/specifications/Project + + + + + Project which should be added to the graph
+ + + + + + + + + + + + + + + + + + + + + + + + +

(async) build(parameters) → {Promise}

+ + + + + + +
+ +
Description:
+
  • Executes a build on the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Build parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
destPath + + +string + + + + + + + + + + + + + Target path
cleanDest + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Decides whether project should clean the target path before build
includedDependencies + + +Array.<(string|RegExp)> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of names of projects to include in the build result + If the wildcard '*' is provided, all dependencies will be included in the build result.
excludedDependencies + + +Array.<(string|RegExp)> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of names of projects to exclude from the build result.
dependencyIncludes + + +@ui5/project/build/ProjectBuilder~DependencyIncludes + + + + + + + <optional>
+ + + + + +
+ + Alternative to the includedDependencies and excludedDependencies parameters. + Allows for a more sophisticated configuration for defining which dependencies should be + part of the build result. If this is provided, the other mentioned parameters will be ignored.
selfContained + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Flag to activate self contained build
cssVariables + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Flag to activate CSS variables generation
jsdoc + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Flag to activate JSDoc build
createBuildManifest + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether to create a build manifest file for the root project. + This is currently only supported for projects of type 'library' and 'theme-library'
includedTasks + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of tasks to be included
excludedTasks + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of tasks to be excluded. + If the wildcard '*' is provided, only the included tasks will be executed.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to undefined once build has finished +
+ + + +
+
+ Type +
+
+ +Promise + + + +
+
+ + + + + + + + + + +

declareDependency(fromProjectName, toProjectName)

+ + + + + + +
+ +
Description:
+
  • Declare a dependency from one project in the graph to another
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
fromProjectName + + +string + + + + + Name of the depending project
toProjectName + + +string + + + + + Name of project on which the other depends
+ + + + + + + + + + + + + + + + + + + + + + + + +

declareOptionalDependency(fromProjectName, toProjectName)

+ + + + + + +
+ +
Description:
+
  • Declare a dependency from one project in the graph to another
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
fromProjectName + + +string + + + + + Name of the depending project
toProjectName + + +string + + + + + Name of project on which the other depends
+ + + + + + + + + + + + + + + + + + + + + + + + +

getDependencies(projectName) → {Array.<string>}

+ + + + + + +
+ +
Description:
+
  • Get all direct dependencies of a project as an array of project names
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Name of the project to retrieve the dependencies of
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Names of all direct dependencies +
+ + + +
+
+ Type +
+
+ +Array.<string> + + + +
+
+ + + + + + + + + + +

getExtension(extensionName) → {@ui5/project/specifications/Extension|undefined}

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
extensionName + + +string + + + + + Name of the extension to retrieve
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Extension instance or undefined if the extension is unknown to the graph +
+ + + +
+
+ Type +
+
+ +@ui5/project/specifications/Extension +| + +undefined + + + +
+
+ + + + + + + + + + +

getExtensionNames() → {Array.<string>}

+ + + + + + +
+ +
Description:
+
  • Get names of all extensions in the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Names of all extensions +
+ + + +
+
+ Type +
+
+ +Array.<string> + + + +
+
+ + + + + + + + + + +

getExtensions() → {Iterable.<@ui5/project/specifications/Extension>}

+ + + + + + +
+ +
Description:
+
  • Get all extensions in the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Iterable.<@ui5/project/specifications/Extension> + + + +
+
+ + + + + + + + + + +

getProject(projectName) → {@ui5/project/specifications/Project|undefined}

+ + + + + + +
+ +
Description:
+
  • Retrieve a single project from the dependency graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Name of the project to retrieve
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ project instance or undefined if the project is unknown to the graph +
+ + + +
+
+ Type +
+
+ +@ui5/project/specifications/Project +| + +undefined + + + +
+
+ + + + + + + + + + +

getProjectNames() → {Array.<string>}

+ + + + + + +
+ +
Description:
+
  • Get names of all projects in the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Names of all projects +
+ + + +
+
+ Type +
+
+ +Array.<string> + + + +
+
+ + + + + + + + + + +

getProjects() → {Iterable.<@ui5/project/specifications/Project>}

+ + + + + + +
+ +
Description:
+
  • Get all projects in the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Iterable.<@ui5/project/specifications/Project> + + + +
+
+ + + + + + + + + + +

getRoot() → {@ui5/project/specifications/Project}

+ + + + + + +
+ +
Description:
+
  • Get the root project of the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Root project +
+ + + +
+
+ Type +
+
+ +@ui5/project/specifications/Project + + + +
+
+ + + + + + + + + + +

getSize() → {integer}

+ + + + + + +
+ +
Description:
+
  • Get the number of projects in the graph
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Count of projects in the graph +
+ + + +
+
+ Type +
+
+ +integer + + + +
+
+ + + + + + + + + + +

getTransitiveDependencies(projectName) → {Array.<string>}

+ + + + + + +
+ +
Description:
+
  • Get all (direct and transitive) dependencies of a project as an array of project names
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Name of the project to retrieve the dependencies of
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Names of all direct and transitive dependencies +
+ + + +
+
+ Type +
+
+ +Array.<string> + + + +
+
+ + + + + + + + + + +

isSealed() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project graph has been sealed. +This means the graph is read-only. Neither projects, nor dependencies between projects +can be added or removed.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project graph has been sealed +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

join(projectGraph)

+ + + + + + +
+ +
Description:
+
  • Join another project graph into this one. +Projects and extensions which already exist in this graph will cause an error to be thrown
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectGraph + + +@ui5/project/graph/ProjectGraph + + + + + Project Graph to merge into this one
+ + + + + + + + + + + + + + + + + + + + + + + + +

(async) resolveOptionalDependencies()

+ + + + + + +
+ +
Description:
+
  • Transforms any optional dependencies declared in the graph to non-optional dependency, if the target +can already be reached from the root project.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

seal()

+ + + + + + +
+ +
Description:
+
  • Seal the project graph so that no further changes can be made to it
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

(async) traverseBreadthFirst(startNameopt, callback)

+ + + + + + +
+ +
Description:
+
  • Visit every project in the graph that can be reached by the given entry project exactly once. +The entry project defaults to the root project. +In case a cycle is detected, an error is thrown
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
startName + + +string + + + + + + + <optional>
+ + + + + +
Name of the project to start the traversal at. Defaults to the graph's root project
callback + + +@ui5/project/graph/ProjectGraph~traversalCallback + + + + + + + + + + + Will be called
+ + + + + + + + + + + + + + + + + + + + + + + + +

(async) traverseDepthFirst(startNameopt, callback)

+ + + + + + +
+ +
Description:
+
  • Visit every project in the graph that can be reached by the given entry project exactly once. +The entry project defaults to the root project. +In case a cycle is detected, an error is thrown
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
startName + + +string + + + + + + + <optional>
+ + + + + +
Name of the project to start the traversal at. Defaults to the graph's root project
callback + + +@ui5/project/graph/ProjectGraph~traversalCallback + + + + + + + + + + + Will be called
+ + + + + + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + + + + +

(async) traversalCallback(parameters) → {Promise|undefined}

+ + + + + + +
+ +
Description:
+
  • Callback for graph traversal operations
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters passed to the callback +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
project + + +@ui5/project/specifications/Project + + + + + Project that is currently visited
dependencies + + +Array.<string> + + + + + Array containing the names of all direct dependencies of the project
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ If a promise is returned, + graph traversal will wait and only continue once the promise has resolved. +
+ + + +
+
+ Type +
+
+ +Promise +| + +undefined + + + +
+
+ + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_graph_ProjectGraphBuilder-NodeProvider.html b/v3/api/@ui5_project_graph_ProjectGraphBuilder-NodeProvider.html new file mode 100644 index 0000000000..6c7195b048 --- /dev/null +++ b/v3/api/@ui5_project_graph_ProjectGraphBuilder-NodeProvider.html @@ -0,0 +1,501 @@ + + + + + + NodeProvider - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

NodeProvider

+ + + + + + + +
+ +
+ +

+ + NodeProvider + +

+ + +
+ +
+ +
+ + + +
+ +
Description:
+
  • Node Provider interface
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
Node Provider interface
+ + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getDependencies(node, workspaceopt) → {Array.<Node>}

+ + + + + + +
+ +
Description:
+
  • Retrieve information on given a nodes dependencies
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
node + + +Node + + + + + + + + + + + The root node of the dependency graph
workspace + + +@ui5/project/graph/Workspace + + + + + + + <optional>
+ + + + + +
workspace instance to use for overriding node resolution
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Array of nodes which are direct dependencies of the given node +
+ + + +
+
+ Type +
+
+ +Array.<Node> + + + +
+
+ + + + + + + + + + +

getRootNode() → {Node}

+ + + + + + +
+ +
Description:
+
  • Retrieve information on the root module
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ The root node of the dependency graph +
+ + + +
+
+ Type +
+
+ +Node + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_graph_Workspace.html b/v3/api/@ui5_project_graph_Workspace.html new file mode 100644 index 0000000000..53f90ab36d --- /dev/null +++ b/v3/api/@ui5_project_graph_Workspace.html @@ -0,0 +1,1299 @@ + + + + + + @ui5/project/graph/Workspace - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/graph/Workspace

+ + + + + + + +
+ +
+ +

+ + @ui5/project/graph/Workspace + +

+ +
UI5 Workspace
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/graph/Workspace(options)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
cwd + + +string + + + + + Path to use for resolving all paths of the workspace configuration from. + This should contain platform-specific path separators (i.e. must not be POSIX on non-POSIX systems)
configuration + + +@ui5/project/graph/Workspace~Configuration + + + + + Workspace configuration
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) getModuleByNodeId(nodeId) → {Promise.<(@ui5/project/graph/Module|undefined)>}

+ + + + + + +
+ +
Description:
+
  • For a given node id (e.g. the value of the name property in a package.json), +returns a [Module]{ @ui5/project/graph/Module} instance or undefined depending on whether the module +has been found in the configured dependency-management resolution paths of this workspace +and contains at least one project or extension
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
nodeId + + +string + + + + + Node ID of the module
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Module instance, or undefined if none is found +
+ + + +
+
+ Type +
+
+ +Promise.<(@ui5/project/graph/Module|undefined)> + + + +
+
+ + + + + + + + + + +

(async) getModuleByProjectName(projectName) → {Promise.<(@ui5/project/graph/Module|undefined)>}

+ + + + + + +
+ +
Description:
+
  • For a given project name (e.g. the value of the metadata.name property in a ui5.yaml), +returns a [Module]{ @ui5/project/graph/Module} instance or undefined depending on whether the project +has been found in the configured dependency-management resolution paths of this workspace
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Name of the project
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Module instance, or undefined if none is found +
+ + + +
+
+ Type +
+
+ +Promise.<(@ui5/project/graph/Module|undefined)> + + + +
+
+ + + + + + + + + + +

(async) getModules() → {Promise.<Array.<@ui5/project/graph/Module>>}

+ + + + + + +
+ +
Description:
+
  • Returns an array of [Module]{ @ui5/project/graph/Module} instances found in the configured +dependency-management resolution paths of this workspace, sorted by module ID.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Array of Module instances sorted by module ID +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/project/graph/Module>> + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the name of this workspace
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Name of this workspace configuration +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

Configuration

+ + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
node.specVersion + + +string + + + + + Workspace Specification Version
node.metadata + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + Name of the workspace configuration
+ +
node.dependencyManagement + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resolutions + + +Array.<@ui5/project/graph/Workspace~DependencyManagementResolutions> + + + + +
+ +
+ + + + + + +
+ Workspace configuration. For details, refer to the +UI5 Workspaces documentation +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

DependencyManagementResolution

+ + + + + +
+ +
Description:
+
  • A resolution entry for the dependency management section of the workspace configuration
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
path + + +string + + + + + Relative path to use for the workspace resolution process
+ + + + + + +
+ A resolution entry for the dependency management section of the workspace configuration +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_graph_providers_DependencyTree.html b/v3/api/@ui5_project_graph_providers_DependencyTree.html new file mode 100644 index 0000000000..2bc59b2366 --- /dev/null +++ b/v3/api/@ui5_project_graph_providers_DependencyTree.html @@ -0,0 +1,697 @@ + + + + + + @ui5/project/graph/providers/DependencyTree - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/graph/providers/DependencyTree

+ + + + + + + +
+ +
+ +

+ + @ui5/project/graph/providers/DependencyTree + +

+ +
Helper module to create a @ui5/project/graph/ProjectGraph +from a dependency tree as returned by translators.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/graph/providers/DependencyTree(options)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
dependencyTree + + +@ui5/project/graph/providers/DependencyTree~TreeNode + + + + + + + + + + + Dependency tree as returned by a translator
rootConfiguration + + +object + + + + + + + <optional>
+ + + + + +
Configuration object to use for the root module instead of reading from a configuration file
rootConfigPath + + +string + + + + + + + <optional>
+ + + + + +
Configuration file to use for the root module instead the default ui5.yaml
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + +

TreeNode

+ + + + + +
+ +
Description:
+
  • Tree node
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
node.id + + +string + + + + + + + + + Unique ID for the project
node.version + + +string + + + + + + + + + Version of the project
node.path + + +string + + + + + + + + + File System path to access the projects resources
node.configuration + + +object +| + +Array.<object> + + + + + + + <optional>
+ + + +
Configuration object or array of objects to use instead of reading from a configuration file
node.configPath + + +string + + + + + + + <optional>
+ + + +
Configuration file to use instead the default ui5.yaml
dependencies + + +Array.<@ui5/project/graph/providers/DependencyTree~TreeNode> + + + + + + + + +
+ + + + + + +
+ Tree node +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_graph_providers_NodePackageDependencies.html b/v3/api/@ui5_project_graph_providers_NodePackageDependencies.html new file mode 100644 index 0000000000..2d1de51087 --- /dev/null +++ b/v3/api/@ui5_project_graph_providers_NodePackageDependencies.html @@ -0,0 +1,395 @@ + + + + + + @ui5/project/graph/providers/NodePackageDependencies - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/graph/providers/NodePackageDependencies

+ + + + + + + +
+ +
+ +

+ + @ui5/project/graph/providers/NodePackageDependencies + +

+ + +
+ +
+ +
+ + + + + +

new @ui5/project/graph/providers/NodePackageDependencies(options)

+ + + + + + +
+ +
Description:
+
  • Generates a project graph from npm modules
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
cwd + + +string + + + + + + + + + + + Directory to start searching for the root module
rootConfiguration + + +object + + + + + + + <optional>
+ + + + + +
Configuration object to use for the root module instead of reading from a configuration file
rootConfigPath + + +string + + + + + + + <optional>
+ + + + + +
Configuration file to use for the root module instead the default ui5.yaml
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_ComponentProject.html b/v3/api/@ui5_project_specifications_ComponentProject.html new file mode 100644 index 0000000000..eb077205be --- /dev/null +++ b/v3/api/@ui5_project_specifications_ComponentProject.html @@ -0,0 +1,2390 @@ + + + + + + @ui5/project/specifications/ComponentProject - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/ComponentProject

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/ComponentProject + +

+ +
Subclass for projects potentially containing Components
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCustomConfiguration() → {object}

+ + + + + + +
+ +
Description:
+
  • Get the project's customConfiguration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Custom Configuration +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

getFrameworkDependencies() → {Array.<@ui5/project/specifications/Project~FrameworkDependency>}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework dependencies configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework dependencies configuration +
+ + + +
+
+ Type +
+
+ +Array.<@ui5/project/specifications/Project~FrameworkDependency> + + + +
+
+ + + + + + + + + + +

getFrameworkName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework name configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework name configuration, either OpenUI5 or SAPUI5 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getFrameworkVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework version configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework version configuration, e.g 1.110.0 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getNamespace() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project namespace
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project namespace in slash notation (e.g. my/project/name) +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getReader(optionsopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a ReaderCollection for accessing all resources of the +project in the specified "style": + +
      +
    • buildtime: Resource paths are always prefixed with /resources/ + or /test-resources/ followed by the project's namespace. + Any configured build-excludes are applied
    • +
    • dist: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + Any configured build-excludes are applied
    • +
    • runtime: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + This style is typically used for serving resources directly. Therefore, build-excludes are not applied +
    • flat: Resource paths are never prefixed and namespaces are omitted if possible. Note that + project types like "theme-library", which can have multiple namespaces, can't omit them. + Any configured build-excludes are applied
    • +
    + +If project resources have been changed through the means of a workspace, those changes +are reflected in the provided reader too. + +Resource readers always use POSIX-style paths.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
style + + +string + + + + + + + <optional>
+ + + + + +
+ + buildtime + + Path style to access resources. + Can be "buildtime", "dist", "runtime" or "flat"
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSourcePath() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the path of the project's source directory. This might not be POSIX-style on some platforms. +Projects with multiple source paths will throw an error. For example Modules.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ In case a project has multiple source directories +
+
+
+
+
+
+ Type +
+
+ +Error + + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+ Absolute path to the source directory of the project +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getWorkspace() → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a resource reader/writer for accessing and modifying a project's resources
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

isFrameworkProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project is a UI5-Framework project
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project is a framework project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_Extension.html b/v3/api/@ui5_project_specifications_Extension.html new file mode 100644 index 0000000000..2771f87b96 --- /dev/null +++ b/v3/api/@ui5_project_specifications_Extension.html @@ -0,0 +1,1186 @@ + + + + + + @ui5/project/specifications/Extension - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/Extension

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/Extension + +

+ +
Extension
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_Project.html b/v3/api/@ui5_project_specifications_Project.html new file mode 100644 index 0000000000..2cacbdd905 --- /dev/null +++ b/v3/api/@ui5_project_specifications_Project.html @@ -0,0 +1,2532 @@ + + + + + + @ui5/project/specifications/Project - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/Project

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/Project + +

+ +
Project
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCustomConfiguration() → {object}

+ + + + + + +
+ +
Description:
+
  • Get the project's customConfiguration
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Custom Configuration +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

getFrameworkDependencies() → {Array.<@ui5/project/specifications/Project~FrameworkDependency>}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework dependencies configuration
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework dependencies configuration +
+ + + +
+
+ Type +
+
+ +Array.<@ui5/project/specifications/Project~FrameworkDependency> + + + +
+
+ + + + + + + + + + +

getFrameworkName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework name configuration
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework name configuration, either OpenUI5 or SAPUI5 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getFrameworkVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework version configuration
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework version configuration, e.g 1.110.0 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getNamespace() → {string|null}

+ + + + + + +
+ +
Description:
+
  • Get the project namespace. Returns `null` for projects that have none or multiple namespaces, +for example Modules or Theme Libraries.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project namespace in slash notation (e.g. my/project/name) or null +
+ + + +
+
+ Type +
+
+ +string +| + +null + + + +
+
+ + + + + + + + + + +

getReader(optionsopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a ReaderCollection for accessing all resources of the +project in the specified "style": + +
      +
    • buildtime: Resource paths are always prefixed with /resources/ + or /test-resources/ followed by the project's namespace. + Any configured build-excludes are applied
    • +
    • dist: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + Any configured build-excludes are applied
    • +
    • runtime: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + This style is typically used for serving resources directly. Therefore, build-excludes are not applied +
    • flat: Resource paths are never prefixed and namespaces are omitted if possible. Note that + project types like "theme-library", which can have multiple namespaces, can't omit them. + Any configured build-excludes are applied
    • +
    + +Resource readers always use POSIX-style paths.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
style + + +string + + + + + + + <optional>
+ + + + + +
+ + buildtime + + Path style to access resources. + Can be "buildtime", "dist", "runtime" or "flat"
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection allowing access to all resources of the project +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSourcePath() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the path of the project's source directory. This might not be POSIX-style on some platforms. +Projects with multiple source paths will throw an error. For example Modules.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ In case a project has multiple source directories +
+
+
+
+
+
+ Type +
+
+ +Error + + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+ Absolute path to the source directory of the project +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getWorkspace() → {@ui5/fs/DuplexCollection}

+ + + + + + +
+ +
Description:
+
  • Get a DuplexCollection for accessing and modifying a +project's resources. This is always of style buildtime.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ DuplexCollection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/DuplexCollection + + + +
+
+ + + + + + + + + + +

isFrameworkProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project is a UI5-Framework project
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project is a framework project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

FrameworkDependency

+ + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + Name of the framework library. For example sap.ui.core
development + + +boolean + + + + + Whether the dependency is meant for development purposes only
optional + + +boolean + + + + + Whether the dependency should be treated as optional
+ + + + + + +
+ Framework dependency entry of the project configuration. +Also see Framework Configuration: Dependencies +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_Specification.html b/v3/api/@ui5_project_specifications_Specification.html new file mode 100644 index 0000000000..61c713cd35 --- /dev/null +++ b/v3/api/@ui5_project_specifications_Specification.html @@ -0,0 +1,1392 @@ + + + + + + @ui5/project/specifications/Specification - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/Specification

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/Specification + +

+ +
Abstract superclass for all projects and extensions
+ + +
+ +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

(async, static) create(parameters)

+ + + + + + +
+ +
Description:
+
  • Create a Specification instance for the given parameters
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +string + + + + + Unique ID
version + + +string + + + + + Version
modulePath + + +string + + + + + Absolute File System path to access resources
configuration + + +object + + + + + Type-dependent configuration object. Typically defined in a ui5.yaml
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_extensions_ProjectShim.html b/v3/api/@ui5_project_specifications_extensions_ProjectShim.html new file mode 100644 index 0000000000..637947d835 --- /dev/null +++ b/v3/api/@ui5_project_specifications_extensions_ProjectShim.html @@ -0,0 +1,1432 @@ + + + + + + @ui5/project/specifications/extensions/ProjectShim - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/extensions/ProjectShim

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/extensions/ProjectShim + +

+ +
ProjectShim
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCollectionShims()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

getConfigurationShims()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

getDependencyShims()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_extensions_ServerMiddleware.html b/v3/api/@ui5_project_specifications_extensions_ServerMiddleware.html new file mode 100644 index 0000000000..859a20d334 --- /dev/null +++ b/v3/api/@ui5_project_specifications_extensions_ServerMiddleware.html @@ -0,0 +1,1268 @@ + + + + + + @ui5/project/specifications/extensions/ServerMiddleware - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/extensions/ServerMiddleware

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/extensions/ServerMiddleware + +

+ +
ServerMiddleware
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

(async) getMiddleware()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_extensions_Task.html b/v3/api/@ui5_project_specifications_extensions_Task.html new file mode 100644 index 0000000000..c3761eb840 --- /dev/null +++ b/v3/api/@ui5_project_specifications_extensions_Task.html @@ -0,0 +1,1350 @@ + + + + + + @ui5/project/specifications/extensions/Task - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/extensions/Task

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/extensions/Task + +

+ +
Task
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

(async) getRequiredDependenciesCallback()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

(async) getTask()

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_types_Application.html b/v3/api/@ui5_project_specifications_types_Application.html new file mode 100644 index 0000000000..e732f2fe09 --- /dev/null +++ b/v3/api/@ui5_project_specifications_types_Application.html @@ -0,0 +1,2359 @@ + + + + + + @ui5/project/specifications/types/Application - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/types/Application

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/types/Application + +

+ +
Application
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCustomConfiguration() → {object}

+ + + + + + +
+ +
Description:
+
  • Get the project's customConfiguration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Custom Configuration +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

getFrameworkDependencies() → {Array.<@ui5/project/specifications/Project~FrameworkDependency>}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework dependencies configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework dependencies configuration +
+ + + +
+
+ Type +
+
+ +Array.<@ui5/project/specifications/Project~FrameworkDependency> + + + +
+
+ + + + + + + + + + +

getFrameworkName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework name configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework name configuration, either OpenUI5 or SAPUI5 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getFrameworkVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework version configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework version configuration, e.g 1.110.0 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getNamespace() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project namespace
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project namespace in slash notation (e.g. my/project/name) +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getReader(optionsopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a ReaderCollection for accessing all resources of the +project in the specified "style": + +
      +
    • buildtime: Resource paths are always prefixed with /resources/ + or /test-resources/ followed by the project's namespace. + Any configured build-excludes are applied
    • +
    • dist: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + Any configured build-excludes are applied
    • +
    • runtime: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + This style is typically used for serving resources directly. Therefore, build-excludes are not applied +
    • flat: Resource paths are never prefixed and namespaces are omitted if possible. Note that + project types like "theme-library", which can have multiple namespaces, can't omit them. + Any configured build-excludes are applied
    • +
    + +If project resources have been changed through the means of a workspace, those changes +are reflected in the provided reader too. + +Resource readers always use POSIX-style paths.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
style + + +string + + + + + + + <optional>
+ + + + + +
+ + buildtime + + Path style to access resources. + Can be "buildtime", "dist", "runtime" or "flat"
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSourcePath() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the path of the project's source directory. This might not be POSIX-style on some platforms.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Absolute path to the source directory of the project +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getWorkspace() → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a resource reader/writer for accessing and modifying a project's resources
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

isFrameworkProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project is a UI5-Framework project
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project is a framework project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_types_Library.html b/v3/api/@ui5_project_specifications_types_Library.html new file mode 100644 index 0000000000..dc47c41abb --- /dev/null +++ b/v3/api/@ui5_project_specifications_types_Library.html @@ -0,0 +1,2359 @@ + + + + + + @ui5/project/specifications/types/Library - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/types/Library

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/types/Library + +

+ +
Library
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCustomConfiguration() → {object}

+ + + + + + +
+ +
Description:
+
  • Get the project's customConfiguration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Custom Configuration +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

getFrameworkDependencies() → {Array.<@ui5/project/specifications/Project~FrameworkDependency>}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework dependencies configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework dependencies configuration +
+ + + +
+
+ Type +
+
+ +Array.<@ui5/project/specifications/Project~FrameworkDependency> + + + +
+
+ + + + + + + + + + +

getFrameworkName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework name configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework name configuration, either OpenUI5 or SAPUI5 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getFrameworkVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework version configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework version configuration, e.g 1.110.0 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getNamespace() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project namespace
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project namespace in slash notation (e.g. my/project/name) +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getReader(optionsopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a ReaderCollection for accessing all resources of the +project in the specified "style": + +
      +
    • buildtime: Resource paths are always prefixed with /resources/ + or /test-resources/ followed by the project's namespace. + Any configured build-excludes are applied
    • +
    • dist: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + Any configured build-excludes are applied
    • +
    • runtime: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + This style is typically used for serving resources directly. Therefore, build-excludes are not applied +
    • flat: Resource paths are never prefixed and namespaces are omitted if possible. Note that + project types like "theme-library", which can have multiple namespaces, can't omit them. + Any configured build-excludes are applied
    • +
    + +If project resources have been changed through the means of a workspace, those changes +are reflected in the provided reader too. + +Resource readers always use POSIX-style paths.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
style + + +string + + + + + + + <optional>
+ + + + + +
+ + buildtime + + Path style to access resources. + Can be "buildtime", "dist", "runtime" or "flat"
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSourcePath() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the path of the project's source directory. This might not be POSIX-style on some platforms.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Absolute path to the source directory of the project +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getWorkspace() → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a resource reader/writer for accessing and modifying a project's resources
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

isFrameworkProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project is a UI5-Framework project
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project is a framework project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_types_Module.html b/v3/api/@ui5_project_specifications_types_Module.html new file mode 100644 index 0000000000..f809a5b730 --- /dev/null +++ b/v3/api/@ui5_project_specifications_types_Module.html @@ -0,0 +1,2370 @@ + + + + + + @ui5/project/specifications/types/Module - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/types/Module

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/types/Module + +

+ +
Module
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCustomConfiguration() → {object}

+ + + + + + +
+ +
Description:
+
  • Get the project's customConfiguration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Custom Configuration +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

getFrameworkDependencies() → {Array.<@ui5/project/specifications/Project~FrameworkDependency>}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework dependencies configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework dependencies configuration +
+ + + +
+
+ Type +
+
+ +Array.<@ui5/project/specifications/Project~FrameworkDependency> + + + +
+
+ + + + + + + + + + +

getFrameworkName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework name configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework name configuration, either OpenUI5 or SAPUI5 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getFrameworkVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework version configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework version configuration, e.g 1.110.0 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getNamespace() → {string|null}

+ + + + + + +
+ +
Description:
+
  • Get the project namespace. Returns `null` for projects that have none or multiple namespaces, +for example Modules or Theme Libraries.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project namespace in slash notation (e.g. my/project/name) or null +
+ + + +
+
+ Type +
+
+ +string +| + +null + + + +
+
+ + + + + + + + + + +

getReader(optionsopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a ReaderCollection for accessing all resources of the +project in the specified "style": + +
      +
    • buildtime: Resource paths are always prefixed with /resources/ + or /test-resources/ followed by the project's namespace. + Any configured build-excludes are applied
    • +
    • dist: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + Any configured build-excludes are applied
    • +
    • runtime: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + This style is typically used for serving resources directly. Therefore, build-excludes are not applied +
    • flat: Resource paths are never prefixed and namespaces are omitted if possible. Note that + project types like "theme-library", which can have multiple namespaces, can't omit them. + Any configured build-excludes are applied
    • +
    + +If project resources have been changed through the means of a workspace, those changes +are reflected in the provided reader too. + +Resource readers always use POSIX-style paths.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
style + + +string + + + + + + + <optional>
+ + + + + +
+ + buildtime + + Path style to access resources. + Can be "buildtime", "dist", "runtime" or "flat"
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSourcePath()

+ + + + + + +
+ +
Description:
+
  • Since Modules have multiple source paths, this function always throws with an exception
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ Projects of type module have more than one source path +
+
+
+
+
+
+ Type +
+
+ +Error + + + +
+
+
+
+
+ + + + + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getWorkspace() → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a resource reader/writer for accessing and modifying a project's resources
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

isFrameworkProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project is a UI5-Framework project
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project is a framework project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_types_ThemeLibrary.html b/v3/api/@ui5_project_specifications_types_ThemeLibrary.html new file mode 100644 index 0000000000..b253ea3380 --- /dev/null +++ b/v3/api/@ui5_project_specifications_types_ThemeLibrary.html @@ -0,0 +1,2367 @@ + + + + + + @ui5/project/specifications/types/ThemeLibrary - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/types/ThemeLibrary

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/types/ThemeLibrary + +

+ +
ThemeLibrary
+ + +
+ +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

getCustomConfiguration() → {object}

+ + + + + + +
+ +
Description:
+
  • Get the project's customConfiguration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Custom Configuration +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + +

getFrameworkDependencies() → {Array.<@ui5/project/specifications/Project~FrameworkDependency>}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework dependencies configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework dependencies configuration +
+ + + +
+
+ Type +
+
+ +Array.<@ui5/project/specifications/Project~FrameworkDependency> + + + +
+
+ + + + + + + + + + +

getFrameworkName() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework name configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework name configuration, either OpenUI5 or SAPUI5 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getFrameworkVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the project's framework version configuration
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Framework version configuration, e.g 1.110.0 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getId() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the ID of this specification. + +

    Note: Only to be used for special occasions as it is specific to the provider that was used and does +not necessarily represent something defined by the project.

    + +For general purposes of a unique identifier use +getName instead.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification ID +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getKind() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the kind of this specification, for example project or extension
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification kind +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getName() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the name of this specification. Represents a unique identifier.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification name +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getNamespace() → {string|null}

+ + + + + + +
+ +
Description:
+
  • Get the project namespace. Returns `null` for projects that have none or multiple namespaces, +for example Modules or Theme Libraries.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project namespace in slash notation (e.g. my/project/name) or null +
+ + + +
+
+ Type +
+
+ +string +| + +null + + + +
+
+ + + + + + + + + + +

getReader(optionsopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Get a ReaderCollection for accessing all resources of the +project in the specified "style": + +
      +
    • buildtime: Resource paths are always prefixed with /resources/ + or /test-resources/ followed by the project's namespace. + Any configured build-excludes are applied
    • +
    • dist: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + Any configured build-excludes are applied
    • +
    • runtime: Resource paths always match with what the UI5 runtime expects. + This means that paths generally depend on the project type. Applications for example use a "flat"-like + structure, while libraries use a "buildtime"-like structure. + This style is typically used for serving resources directly. Therefore, build-excludes are not applied +
    • flat: Resource paths are never prefixed and namespaces are omitted if possible. Note that + project types like "theme-library", which can have multiple namespaces, can't omit them. + Any configured build-excludes are applied
    • +
    + +If project resources have been changed through the means of a workspace, those changes +are reflected in the provided reader too. + +Resource readers always use POSIX-style paths.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
style + + +string + + + + + + + <optional>
+ + + + + +
+ + buildtime + + Path style to access resources. + Can be "buildtime", "dist", "runtime" or "flat"
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A reader collection instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getRootPath() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's file system path. This might not be POSIX-style on some platforms
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project root path +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getRootReader(parametersopt) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Gets a ReaderCollection for the root directory of the specification. +Resource readers always use POSIX-style
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
parameters + + +object + + + + + + + <optional>
+ + + + + +
Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to apply any excludes defined in an optional .gitignore in the root directory
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

getSourcePath() → {string}

+ + + + + + +
+ +
Description:
+
  • Get the path of the project's source directory
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Absolute path to the source directory of the project +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getSpecVersion() → {@ui5/project/specifications/SpecificationVersion}

+ + + + + + +
+ +
Description:
+
  • Returns an instance of a helper class representing a Specification Version
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/project/specifications/SpecificationVersion + + + +
+
+ + + + + + + + + + +

getType() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the type of this specification, +for example application or library in case of projects, +and task or server-middleware in case of extensions
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification type +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getVersion() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the specification's generic version, as typically defined in a package.json
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Project version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getWorkspace() → {@ui5/fs/DuplexCollection}

+ + + + + + +
+ +
Description:
+
  • Get a DuplexCollection for accessing and modifying a +project's resources. + +This is always of style buildtime, wich for theme libraries is identical to style +runtime.
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ DuplexCollection +
+ + + +
+
+ Type +
+
+ +@ui5/fs/DuplexCollection + + + +
+
+ + + + + + + + + + +

isFrameworkProject() → {boolean}

+ + + + + + +
+ +
Description:
+
  • Check whether the project is a UI5-Framework project
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the project is a framework project +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_specifications_utils_SpecificationVersion.html b/v3/api/@ui5_project_specifications_utils_SpecificationVersion.html new file mode 100644 index 0000000000..b44c18f024 --- /dev/null +++ b/v3/api/@ui5_project_specifications_utils_SpecificationVersion.html @@ -0,0 +1,3483 @@ + + + + + + @ui5/project/specifications/utils/SpecificationVersion - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/specifications/utils/SpecificationVersion

+ + + + + + + +
+ +
+ +

+ + @ui5/project/specifications/utils/SpecificationVersion + +

+ +
Helper class representing a Specification Version. Featuring helper functions for easy comparison +of versions.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/specifications/utils/SpecificationVersion(specVersion)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version to use for all comparison operations
+ + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ Throws if provided Specification Version is not supported by this version of @ui5/project +
+
+
+
+
+
+ Type +
+
+ +Error + + + +
+
+
+
+
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

eq(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version is equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version is equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

gt(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version is greater than the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version is greater than the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

gte(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version is greater than or equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version is greater than or equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

lt(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version is smaller than the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version is smaller than the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

lte(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version is smaller than or equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version is smaller than or equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

major() → {integer}

+ + + + + + +
+ +
Description:
+
  • Returns the major-version of the instance's Specification Version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Major version +
+ + + +
+
+ Type +
+
+ +integer + + + +
+
+ + + + + + + + + + +

minor() → {integer}

+ + + + + + +
+ +
Description:
+
  • Returns the minor-version of the instance's Specification Version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Minor version +
+ + + +
+
+ Type +
+
+ +integer + + + +
+
+ + + + + + + + + + +

neq(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version is not equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version is not equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

satisfies(range) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the instance's Specification Version falls into the provided range
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
range + + +string + + + + + Semver-style version range, +for example 2.2 - 2.4
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the instance's Specification Version falls into the provided range +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

toString() → {string}

+ + + + + + +
+ +
Description:
+
  • Returns the Specification Version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification Version +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

(static) eq(specVersion, testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
testVersion + + +string + + + + + A Specification Version to compare the provided Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) gt(specVersion, testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is greater than the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
testVersion + + +string + + + + + A Specification Version to compare the provided Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is greater than the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) gte(specVersion, testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is greater than or equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
testVersion + + +string + + + + + A Specification Version to compare the provided Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is greater than or equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) isSupportedSpecVersion(testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is supported by this version of @ui5/project
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
testVersion + + +string + + + + + A Specification Version to compare the instance's Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is supported +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) lt(specVersion, testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is smaller than the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
testVersion + + +string + + + + + A Specification Version to compare the provided Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is smaller than the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) lte(specVersion, testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is smaller than or equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
testVersion + + +string + + + + + A Specification Version to compare the provided Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is smaller than or equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) major(specVersion) → {integer}

+ + + + + + +
+ +
Description:
+
  • Returns the major-version of the provided Specification Version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Major version +
+ + + +
+
+ Type +
+
+ +integer + + + +
+
+ + + + + + + + + + +

(static) minor(specVersion) → {integer}

+ + + + + + +
+ +
Description:
+
  • Returns the minor-version of the provided Specification Version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Minor version +
+ + + +
+
+ Type +
+
+ +integer + + + +
+
+ + + + + + + + + + +

(static) neq(specVersion, testVersion) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version is not equal to the provided test version
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
testVersion + + +string + + + + + A Specification Version to compare the provided Specification Version to
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version is not equal to the provided version +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) satisfies(specVersion, range) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Test whether the provided Specification Version falls into the provided range
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
specVersion + + +string + + + + + Specification Version
range + + +string + + + + + Semver-style version range, +for example 2.2 - 2.4
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided Specification Version falls into the provided range +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_ui5Framework_AbstractResolver.html b/v3/api/@ui5_project_ui5Framework_AbstractResolver.html new file mode 100644 index 0000000000..6884213a95 --- /dev/null +++ b/v3/api/@ui5_project_ui5Framework_AbstractResolver.html @@ -0,0 +1,692 @@ + + + + + + @ui5/project/ui5Framework/AbstractResolver - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/ui5Framework/AbstractResolver

+ + + + + + + +
+ +
+ +

+ + @ui5/project/ui5Framework/AbstractResolver + +

+ +
Abstract Resolver
+ + +
+ +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) install(libraryNames) → {@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult}

+ + + + + + +
+ +
Description:
+
  • Installs the provided libraries and their dependencies
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
const resolver = new Sapui5Resolver({version: "1.76.0"});
+// Or for OpenUI5:
+// const resolver = new Openui5Resolver({version: "1.76.0"});
+
+resolver.install(["sap.ui.core", "sap.m"]).then(({libraryMetadata}) => {
+	// Installation done
+}).catch((err) => {
+	// Handle installation errors
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
libraryNames + + +Array.<string> + + + + + List of library names to be installed
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Resolves with an object containing the libraryMetadata +
+ + + +
+
+ Type +
+
+ +@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

LibraryMetadataEntry

+ + + + + +
+ +
Description:
+
  • Library metadata entry
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +string + + + + + Identifier
version + + +string + + + + + Version
path + + +string + + + + + Path
dependencies + + +Array.<string> + + + + + List of dependency ids
optionalDependencies + + +Array.<string> + + + + + List of optional dependency ids
+ + + + + + +
+ Library metadata entry +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + +
Example
+ +
const libraryMetadataEntry = {
+		"id": "@openui5/sap.ui.core",
+		"version": "1.75.0",
+		"path": "~/.ui5/framework/packages/@openui5/sap.ui.core/1.75.0",
+		"dependencies": [],
+		"optionalDependencies": []
+};
+ + + + + +

ResolverInstallResult

+ + + + + +
+ +
Description:
+
  • Install result
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
libraryMetadata + + +object.<string, @ui5/project/ui5Framework/AbstractResolver~LibraryMetadataEntry> + + + + + Object containing all installed libraries with library name as key
+ + + + + + +
+ Install result +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + +
Example
+ +
const resolverInstallResult = {
+	"libraryMetadata": {
+		"sap.ui.core": {
+			// ...
+		},
+		"sap.m": {
+			// ...
+		}
+	}
+};
+ + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_ui5Framework_Openui5Resolver.html b/v3/api/@ui5_project_ui5Framework_Openui5Resolver.html new file mode 100644 index 0000000000..4d9c35087d --- /dev/null +++ b/v3/api/@ui5_project_ui5Framework_Openui5Resolver.html @@ -0,0 +1,720 @@ + + + + + + @ui5/project/ui5Framework/Openui5Resolver - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/ui5Framework/Openui5Resolver

+ + + + + + + +
+ +
+ +

+ + @ui5/project/ui5Framework/Openui5Resolver + +

+ +
Resolver for the OpenUI5 framework
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/ui5Framework/Openui5Resolver(options)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +* + + + + + options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
version + + +string + + + + + + + + + + + + + OpenUI5 version to use
cwd + + +string + + + + + + + <optional>
+ + + + + +
+ + process.cwd() + + Working directory to resolve configurations like .npmrc
ui5HomeDir + + +string + + + + + + + <optional>
+ + + + + +
+ + "~/.ui5" + + UI5 home directory location. This will be used to store packages, +metadata and configuration used by the resolvers. Relative to `process.cwd()`
cacheDir + + +string + + + + + + + <optional>
+ + + + + +
+ + Where to store temp/cached packages.
packagesDir + + +string + + + + + + + <optional>
+ + + + + +
+ + Where to install packages
stagingDir + + +string + + + + + + + <optional>
+ + + + + +
+ + The staging directory for the packages
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) install(libraryNames) → {@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult}

+ + + + + + +
+ +
Description:
+
  • Installs the provided libraries and their dependencies
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
const resolver = new Sapui5Resolver({version: "1.76.0"});
+// Or for OpenUI5:
+// const resolver = new Openui5Resolver({version: "1.76.0"});
+
+resolver.install(["sap.ui.core", "sap.m"]).then(({libraryMetadata}) => {
+	// Installation done
+}).catch((err) => {
+	// Handle installation errors
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
libraryNames + + +Array.<string> + + + + + List of library names to be installed
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Resolves with an object containing the libraryMetadata +
+ + + +
+
+ Type +
+
+ +@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_ui5Framework_Sapui5MavenSnapshotResolver.html b/v3/api/@ui5_project_ui5Framework_Sapui5MavenSnapshotResolver.html new file mode 100644 index 0000000000..410bc0eacb --- /dev/null +++ b/v3/api/@ui5_project_ui5Framework_Sapui5MavenSnapshotResolver.html @@ -0,0 +1,731 @@ + + + + + + @ui5/project/ui5Framework/Sapui5MavenSnapshotResolver - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/ui5Framework/Sapui5MavenSnapshotResolver

+ + + + + + + +
+ +
+ +

+ + @ui5/project/ui5Framework/Sapui5MavenSnapshotResolver + +

+ +
Resolver for the SAPUI5 framework + +This Resolver downloads and installs SNAPSHOTS of UI5 libraries from +a Maven repository. It's meant for internal usage only as no use cases +outside of SAP are known.
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/ui5Framework/Sapui5MavenSnapshotResolver(options)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +* + + + + + options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
snapshotEndpointUrl + + +string + + + + + + + <optional>
+ + + + + +
+ + Maven Repository Snapshot URL. Can by overruled + by setting the UI5_MAVEN_SNAPSHOT_ENDPOINT_URL environment variable. If neither is provided, + falling back to the standard Maven settings.xml file (if existing).
version + + +string + + + + + + + + + + + + + SAPUI5 version to use
sources + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether to install framework libraries as sources or +pre-built (with build manifest)
cwd + + +string + + + + + + + <optional>
+ + + + + +
+ + process.cwd() + + Current working directory
ui5HomeDir + + +string + + + + + + + <optional>
+ + + + + +
+ + "~/.ui5" + + UI5 home directory location. This will be used to store packages, +metadata and configuration used by the resolvers. Relative to `process.cwd()`
cacheMode + + +module:@ui5/project/ui5Framework/maven/CacheMode + + + + + + + <optional>
+ + + + + +
+ + Default + + Cache mode to use
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) install(libraryNames) → {@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult}

+ + + + + + +
+ +
Description:
+
  • Installs the provided libraries and their dependencies
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
const resolver = new Sapui5Resolver({version: "1.76.0"});
+// Or for OpenUI5:
+// const resolver = new Openui5Resolver({version: "1.76.0"});
+
+resolver.install(["sap.ui.core", "sap.m"]).then(({libraryMetadata}) => {
+	// Installation done
+}).catch((err) => {
+	// Handle installation errors
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
libraryNames + + +Array.<string> + + + + + List of library names to be installed
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Resolves with an object containing the libraryMetadata +
+ + + +
+
+ Type +
+
+ +@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_ui5Framework_Sapui5Resolver.html b/v3/api/@ui5_project_ui5Framework_Sapui5Resolver.html new file mode 100644 index 0000000000..6e723b5b5c --- /dev/null +++ b/v3/api/@ui5_project_ui5Framework_Sapui5Resolver.html @@ -0,0 +1,720 @@ + + + + + + @ui5/project/ui5Framework/Sapui5Resolver - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/ui5Framework/Sapui5Resolver

+ + + + + + + +
+ +
+ +

+ + @ui5/project/ui5Framework/Sapui5Resolver + +

+ +
Resolver for the SAPUI5 framework
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new @ui5/project/ui5Framework/Sapui5Resolver(options)

+ + + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +* + + + + + options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
version + + +string + + + + + + + + + + + + + SAPUI5 version to use
cwd + + +string + + + + + + + <optional>
+ + + + + +
+ + process.cwd() + + Working directory to resolve configurations like .npmrc
ui5HomeDir + + +string + + + + + + + <optional>
+ + + + + +
+ + "~/.ui5" + + UI5 home directory location. This will be used to store packages, +metadata and configuration used by the resolvers. Relative to `process.cwd()`
cacheDir + + +string + + + + + + + <optional>
+ + + + + +
+ + Where to store temp/cached packages.
packagesDir + + +string + + + + + + + <optional>
+ + + + + +
+ + Where to install packages
stagingDir + + +string + + + + + + + <optional>
+ + + + + +
+ + The staging directory for packages
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ + + +

Extends

+ + + + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(async) install(libraryNames) → {@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult}

+ + + + + + +
+ +
Description:
+
  • Installs the provided libraries and their dependencies
+ + + +
Source:
+
+ + + + + + + + + +
Overrides:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
const resolver = new Sapui5Resolver({version: "1.76.0"});
+// Or for OpenUI5:
+// const resolver = new Openui5Resolver({version: "1.76.0"});
+
+resolver.install(["sap.ui.core", "sap.m"]).then(({libraryMetadata}) => {
+	// Installation done
+}).catch((err) => {
+	// Handle installation errors
+});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
libraryNames + + +Array.<string> + + + + + List of library names to be installed
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Resolves with an object containing the libraryMetadata +
+ + + +
+
+ Type +
+
+ +@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_project_validation_ValidationError.html b/v3/api/@ui5_project_validation_ValidationError.html new file mode 100644 index 0000000000..1403b2f558 --- /dev/null +++ b/v3/api/@ui5_project_validation_ValidationError.html @@ -0,0 +1,306 @@ + + + + + + @ui5/project/validation/ValidationError - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/validation/ValidationError

+ + + + + + + +
+ +
+ +

+ + @ui5/project/validation/ValidationError + +

+ +
Error class for validation of project configuration.
+ + +
+ +
+ + + +

Extends

+ + + + +
    +
  • Error
  • +
+ + + + + + + + + + + + + + + +

Members

+ + + +

(readonly) message :string

+ + + + + +
+ +
Description:
+
  • Formatted error message
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Formatted error message +
+ + + +
Type:
+
    +
  • + +string + + + +
  • +
+ + + + + + + + +

(constant) name :string

+ + + + + +
+ +
Description:
+
  • ValidationError
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Default Value:
+
    +
  • ValidationError
  • +
+ + + + + + + +
+ + + + + +
+ ValidationError +
+ + + +
Type:
+
    +
  • + +string + + + +
  • +
+ + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/@ui5_server_middleware_MiddlewareUtil.html b/v3/api/@ui5_server_middleware_MiddlewareUtil.html new file mode 100644 index 0000000000..74560f817f --- /dev/null +++ b/v3/api/@ui5_server_middleware_MiddlewareUtil.html @@ -0,0 +1,1810 @@ + + + + + + @ui5/server/middleware/MiddlewareUtil - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/server/middleware/MiddlewareUtil

+ + + + + + + +
+ +
+ +

+ + @ui5/server/middleware/MiddlewareUtil + +

+ +
Convenience functions for UI5 Server middleware. +An instance of this class is passed to every standard UI5 Server middleware. +Custom middleware that define a specification version >= 2.0 will also receive an instance +of this class as part of the parameters of their create-middleware function. + +The set of functions that can be accessed by a custom middleware depends on the specification +version defined for the extension.
+ + +
+ +
+ + + + + + + + + + + + + + + +

Members

+ + + +

resourceFactory :@ui5/server/middleware/MiddlewareUtil~resourceFactory

+ + + + + +
+ +
Description:
+
  • Provides limited access to @ui5/fs/resourceFactory functions + +

    +This attribute is only available to custom server middleware extensions defining +Specification Version 3.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Provides limited access to @ui5/fs/resourceFactory functions + +

+This attribute is only available to custom server middleware extensions defining +Specification Version 3.0 and above. +
+ + + +
Type:
+ + + + + + + + + + + +

Methods

+ + + + + + +

getDependencies(projectNameopt) → {Array.<string>}

+ + + + + + +
+ +
Description:
+
  • Retrieve a list of direct dependencies of a given project from the dependency graph. +Note that this list does not include transitive dependencies. + +

    +This method is only available to custom server middleware extensions defining +Specification Version 3.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectName + + +string + + + + + + + <optional>
+ + + + + +
Name of the project to retrieve. +Defaults to the name of the current root project
+ + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ If the requested project is unknown to the graph +
+
+
+
+
+
+ Type +
+
+ +Error + + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+ Names of all direct dependencies +
+ + + +
+
+ Type +
+
+ +Array.<string> + + + +
+
+ + + + + + + + + + +

getMimeInfo(resourcePath) → {@ui5/server/middleware/MiddlewareUtil.MimeInfo}

+ + + + + + +
+ +
Description:
+
  • Returns MIME information derived from a given resource path. +

    +This method is only available to custom middleware extensions defining +Specification Version 2.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resourcePath + + +object + + + + +
+ + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/server/middleware/MiddlewareUtil.MimeInfo + + + +
+
+ + + + + + + + + + +

getPathname(req) → {string}

+ + + + + + +
+ +
Description:
+
  • Returns the pathname +of a given request. Any escape sequences will be decoded. +

    +This method is only available to custom middleware extensions defining +Specification Version 2.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
req + + +object + + + + + Request object
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Pathname +of the given request +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

getProject(projectNameOrResourceopt) → {@ui5/server/middleware/MiddlewareUtil~ProjectInterface|undefined}

+ + + + + + +
+ +
Description:
+
  • Retrieve a single project from the dependency graph + +

    +This method is only available to custom server middleware extensions defining +Specification Version 3.0 and above.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectNameOrResource + + +string +| + +@ui5/fs/Resource + + + + + + + <optional>
+ + + + + +
Name of the project to retrieve or a Resource instance to retrieve the associated project for. +Defaults to the name of the current root project
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Specification Version-dependent interface to the Project instance or undefined +if the project name is unknown or the provided resource is not associated with any project. +
+ + + +
+
+ Type +
+
+ +@ui5/server/middleware/MiddlewareUtil~ProjectInterface +| + +undefined + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

MimeInfo

+ + + + + +
+ +
Description:
+
  • MIME Info
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + +string + + + + + Detected content-type for the given resource path
charset + + +string + + + + + Default charset for the detected content-type
contentType + + +string + + + + + Calculated content-type header value
+ + + + + + +
+ MIME Info +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + +
Example
+ +
const mimeInfo = {
+	"type": "text/html",
+	"charset": "utf-8",
+	"contentType": "text/html; charset=utf-8"
+};
+ + + + + +

ProjectInterface

+ + + + + +
+ +
Description:
+
  • Specification Version-dependent Project interface. +For details on individual functions, see Project
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
getType + + +function + + + + + Get the project type
getName + + +function + + + + + Get the project name
getVersion + + +function + + + + + Get the project version
getNamespace + + +function + + + + + Get the project namespace
getRootReader + + +function + + + + + Get the project rootReader
getReader + + +function + + + + + Get the project reader, defaulting to "runtime" style instead of "buildtime"
getRootPath + + +function + + + + + Get the local File System path of the project's root directory
getSourcePath + + +function + + + + + Get the local File System path of the project's source directory
getCustomConfiguration + + +function + + + + + Get the project Custom Configuration
isFrameworkProject + + +function + + + + + Check whether the project is a UI5-Framework project
getFrameworkName + + +function + + + + + Get the project's framework name configuration
getFrameworkVersion + + +function + + + + + Get the project's framework version configuration
getFrameworkDependencies + + +function + + + + + Get the project's framework dependencies configuration
+ + + + + + +
+ Specification Version-dependent Project interface. +For details on individual functions, see Project +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

resourceFactory

+ + + + + +
+ +
Description:
+
  • Specification Version-dependent set of @ui5/fs/resourceFactory +functions provided to middleware. +For details on individual functions, see @ui5/fs/resourceFactory
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
createResource + + +function + + + + + Creates a Resource. + Accepts the same parameters as the Resource constructor.
createReaderCollection + + +function + + + + + Creates a reader collection: + ReaderCollection
createReaderCollectionPrioritized + + +function + + + + + Creates a prioritized reader collection: + ReaderCollectionPrioritized
createFilterReader + + +function + + + + + Create a Filter-Reader with the given reader.
createLinkReader + + +function + + + + + Create a Link-Reader with the given reader.
createFlatReader + + +function + + + + + Create a Link-Reader +where all requests are prefixed with /resources/.
+ + + + + + +
+ Specification Version-dependent set of @ui5/fs/resourceFactory +functions provided to middleware. +For details on individual functions, see @ui5/fs/resourceFactory +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/builder_lib_processors_bootstrapHtmlTransformer.js.html b/v3/api/builder_lib_processors_bootstrapHtmlTransformer.js.html new file mode 100644 index 0000000000..0f648a1154 --- /dev/null +++ b/v3/api/builder_lib_processors_bootstrapHtmlTransformer.js.html @@ -0,0 +1,137 @@ + + + + + + + builder/lib/processors/bootstrapHtmlTransformer.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/bootstrapHtmlTransformer.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:bootstrapHtmlTransformer");
+import cheerio from "cheerio";
+
+/**
+ * @module @ui5/builder/processors/bootstrapHtmlTransformer
+ */
+
+/**
+ * Transforms the UI5 bootstrap of a HTML resource files.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of resources to be processed
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.src Bootstrap "src" that should be used
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with the cloned resources
+ */
+export default function({resources, options: {src}}) {
+	async function processResource(resource) {
+		const content = await resource.getString();
+		const $ = cheerio.load(content);
+		const bootstrapScript = $("script#sap-ui-bootstrap");
+		if (bootstrapScript.length === 1) {
+			bootstrapScript.attr("src", src);
+			resource.setString($.html());
+		} else if (bootstrapScript.length > 1) {
+			log.warn("Skipping bootstrap transformation. " +
+				"Found multiple bootstrap script tags with id=sap-ui-bootstrap.");
+		} else {
+			log.warn("Skipping bootstrap transformation. " +
+				"Could not find bootstrap script tag with id=sap-ui-bootstrap.");
+		}
+		return resource;
+	}
+
+	return Promise.all(resources.map(processResource));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_bundlers_flexChangesBundler.js.html b/v3/api/builder_lib_processors_bundlers_flexChangesBundler.js.html new file mode 100644 index 0000000000..dd110cb30b --- /dev/null +++ b/v3/api/builder_lib_processors_bundlers_flexChangesBundler.js.html @@ -0,0 +1,215 @@ + + + + + + + builder/lib/processors/bundlers/flexChangesBundler.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/bundlers/flexChangesBundler.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:bundlers:flexChangesBundler");
+import {createResource} from "@ui5/fs/resourceFactory";
+
+/**
+ * @public
+ * @module @ui5/builder/processors/bundlers/flexChangesBundler
+ */
+
+/**
+ * Bundles all supplied changes.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of resources to be processed
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pathPrefix Prefix for bundle path
+ * @param {string} parameters.options.hasFlexBundleVersion true if minUI5Version >= 1.73 than
+ *															create flexibility-bundle.json
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with flex changes bundle resources
+ */
+export default function({resources, options: {pathPrefix, hasFlexBundleVersion}}) {
+	let bundleName = "changes-bundle.json";
+
+	function sortByTimeStamp(a, b) {
+		return a.creation > b.creation ? 1 : -1;
+	}
+
+	/**
+	 * bundle changes resource to json string
+	 *
+	 * @param {Array} changesContent Array of resources files
+	 * @returns {string} Json sting of changes and control variants
+	 */
+	function sortAndStringifyInFlexFormat(changesContent) {
+		changesContent = changesContent.sort(sortByTimeStamp);
+		const changes = [];
+		const variantDependentControlChanges = [];
+		const compVariants = [];
+		const variants = [];
+		const variantChanges = [];
+		const variantManagementChanges = [];
+
+		changesContent.forEach(function(content) {
+			if (content.layer === "VENDOR") {
+				content.support.user = "SAP";
+			}
+			switch (content.fileType) {
+			case "change":
+				if (content.appDescriptorChange && (content.appDescriptorChange === "true" ||
+						content.appDescriptorChange == true)) {
+					break;
+				}
+				if (content.variantReference && content.variantReference !== "") {
+					variantDependentControlChanges.push(content);
+				} else {
+					changes.push(content);
+				}
+				break;
+			case "variant":
+				compVariants.push(content);
+				break;
+			case "ctrl_variant":
+				variants.push(content);
+				break;
+			case "ctrl_variant_change":
+				variantChanges.push(content);
+				break;
+			case "ctrl_variant_management_change":
+				variantManagementChanges.push(content);
+				break;
+			}
+		});
+
+		if (!hasFlexBundleVersion && (compVariants.length != 0 || variants.length != 0 || variantChanges.length != 0 ||
+				variantDependentControlChanges.length != 0 || variantManagementChanges.length != 0)) {
+			throw new Error(
+				"There are some control variant changes in the changes folder. This only works with a " +
+				"minUI5Version 1.73.0. Please update the minUI5Version in the manifest.json to 1.73.0 or higher");
+		}
+		// create changes-bundle.json
+		if (!hasFlexBundleVersion) {
+			return JSON.stringify(changes);
+		} else {
+			bundleName = "flexibility-bundle.json";
+			const newChangeFormat = {
+				changes,
+				compVariants,
+				variants,
+				variantChanges,
+				variantDependentControlChanges,
+				variantManagementChanges
+			};
+
+			return JSON.stringify(newChangeFormat);
+		}
+	}
+
+	return Promise.all(resources.map((resource) => {
+		return resource.getBuffer().then((buffer) => {
+			return JSON.parse(buffer.toString());
+		});
+	})).then((changesContent) => {
+		const nNumberOfChanges = changesContent.length;
+		log.info("Changes collected. Number of changes: " + nNumberOfChanges);
+		const result = [];
+		if (nNumberOfChanges > 0) {
+			changesContent = sortAndStringifyInFlexFormat(changesContent);
+			result.push(createResource({
+				path: `${pathPrefix}/changes/${bundleName}`,
+				string: changesContent
+			}));
+		}
+		return result;
+	});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_bundlers_moduleBundler.js.html b/v3/api/builder_lib_processors_bundlers_moduleBundler.js.html new file mode 100644 index 0000000000..d55fbe6a3c --- /dev/null +++ b/v3/api/builder_lib_processors_bundlers_moduleBundler.js.html @@ -0,0 +1,287 @@ + + + + + + + builder/lib/processors/bundlers/moduleBundler.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/bundlers/moduleBundler.js

+ + + + + + + +
+
+
import BundleBuilder from "../../lbt/bundle/Builder.js";
+import LocatorResourcePool from "../../lbt/resources/LocatorResourcePool.js";
+import EvoResource from "@ui5/fs/Resource";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:bundlers:moduleBundler");
+
+/**
+ * @public
+ * @module @ui5/builder/processors/bundlers/moduleBundler
+ */
+
+/**
+ * A ModuleBundleDefinitionSection specifies the embedding mode (either 'provided', 'raw', 'preload', 'require'
+ * or 'bundleInfo') and lists the resources that should be in- or excluded from the section.
+ * <p>
+ * <b>Module bundle section modes</b><br>
+ * <ul>
+ * 	<li>
+ *		<code>provided</code>: A section of mode 'provided' defines a set of modules that should not be included in
+ * the bundle file itself, but which should be assumed to be already loaded (or 'provided') by the environment into
+ * which the bundle module is loaded.
+ * 	</li>
+ *	<li>
+ *		<code>raw</code>: A 'raw' section determines the set of modules that should be embedded, sorts them according
+ *		to their dependencies and writes them out 1:1 without any transformation or wrapping (raw). Only JavaScript
+ *		sources can be embedded in a raw section.
+ *	</li>
+ *	<li>
+ *		<code>preload</code>: A 'preload' section packages resources that should be stored in the preload cache in the
+ *		client. They can embed any textual resource type (JavaScript, XML, JSON and .properties files) that the
+ *		bundling supports. UI5 modules are wrapped into a 'sap.ui.predefine' call. Other JavaScript modules will be
+ *		embedded into a 'jQuery.sap.registerPreload' call, or in a "sap.ui.require.preload" call when
+ *      the ui5loader is available.
+ *	</li>
+ *	<li>
+ *		<code>require</code>: A 'require' section is transformed into a sequence of jQuery.sap.require calls. The
+ *		list will be resolved like an include pattern list in any of the other sections and for each of the resolved
+ *		modules, a jQuery.sap.require will be created. In case the ui5loader is available, 'sap.ui.requireSync' is
+ *		used instead.
+ *	</li>
+ *	<li>
+ *		<code>bundleInfo</code>: A 'bundleInfo' section describes the content of another named bundle. This information
+ *		is transformed into a ui5loader-"bundlesUI5" configuration.
+ *		At runtime, if a module is known to be contained in a bundle, the loader will require that bundle before
+ *		the module itself.
+ *		This requires the ui5loader to be available at build time and UI5 version 1.74.0 or higher at runtime.
+ *	</li>
+ * </ul>
+ * </p>
+ *
+ * @public
+ * @typedef {object} ModuleBundleDefinitionSection
+ * @property {string} mode The embedding mode. Either 'provided', 'raw', 'preload', 'require' or 'bundleInfo'
+ * @property {string[]} filters List of modules declared as glob patterns (resource name patterns) that should be
+ *		in- or excluded.
+ * 		A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk,
+ *		denote an arbitrary number of characters or folder names.
+ * 		Excludes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later
+ *		exclusion overrides an earlier inclusion, and vice versa.
+ * @example <caption>List of modules as glob patterns that should be in- or excluded</caption>
+ * // Includes everything from "some/path/to/module/",
+ * // but excludes the subfolder "some/path/to/module/to/be/excluded/"
+ * const section = {
+ * 	"filters": [
+ * 		"some/path/to/module/",
+ * 		"!some/path/to/module/to/be/excluded/"
+ * 	]
+ * };
+ *
+ * @property {boolean} [resolve=false] Whether (transitive) dependencies of modules that match the given filters
+ *		should be resolved and added to the module set
+ * @property {boolean} [resolveConditional=false] Whether conditional dependencies of modules should be resolved
+ * 		and added to the module set for this section
+ * @property {boolean} [renderer=false] Whether renderers for controls should be added to the module set
+ * @property {boolean} [declareRawModules=false] Whether raw modules should be declared after jQuery.sap.global
+ *		became available. With the usage of the ui5loader, this flag should be set to 'false'
+ * @property {boolean} [sort=true] Whether the modules should be sorted by their dependencies
+ */
+
+/* eslint-disable max-len */
+/**
+ * Module bundle definition
+ *
+ * @public
+ * @typedef {object} ModuleBundleDefinition
+ * @property {string} name The module bundle name
+ * @property {string[]} [defaultFileTypes=[".js", ".control.xml", ".fragment.html", ".fragment.json", ".fragment.xml", ".view.html", ".view.json", ".view.xml"]]
+ *   List of default file types to be included in the bundle
+ * @property {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinitionSection[]} sections List of module bundle definition sections.
+ */
+/* eslint-enable max-len */
+
+/**
+ * Module bundle options
+ *
+ * @public
+ * @typedef {object} ModuleBundleOptions
+ * @property {boolean} [optimize=true] Whether the module bundle gets minified
+ * @property {boolean} [sourceMap=true] Whether to generate a source map file for the bundle
+ * @property {boolean} [decorateBootstrapModule=false] If set to 'false', bootable bundles won't be decorated
+ *   with an optimization marker
+ * @property {boolean} [addTryCatchRestartWrapper=false] Whether to wrap bootable bundles with
+ *   a try/catch to filter out "Restart" errors
+ * @property {boolean} [usePredefineCalls=false] If set to 'true', sap.ui.predefine is used for UI5 modules
+ * @property {number} [numberOfParts=1] The number of parts the module bundle should be splitted
+ * @property {boolean} [ignoreMissingModules=false] When searching for modules which are optional for further
+ *   processing, do not throw in case they are missing
+ */
+
+/**
+ * Result set
+ *
+ * @public
+ * @typedef {object} ModuleBundlerResult
+ * @property {@ui5/fs/Resource} bundle Bundle resource
+ * @property {@ui5/fs/Resource} sourceMap Source Map
+ */
+
+/* eslint-disable max-len */
+/**
+ * Legacy module bundler.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources Resources
+ * @param {object} parameters.options Options
+ * @param {object} [parameters.options.moduleNameMapping]
+ 				Optional mapping of resource paths to module name in order to overwrite the default determination
+ * @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition} parameters.options.bundleDefinition Module
+				bundle definition
+ * @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleOptions} [parameters.options.bundleOptions] Module
+				bundle options
+ * @returns {Promise<module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundlerResult[]>}
+ * Promise resolving with module bundle resources
+ */
+/* eslint-enable max-len */
+export default function({resources, options: {bundleDefinition, bundleOptions, moduleNameMapping}}) {
+	// Apply defaults without modifying the passed object
+	bundleOptions = Object.assign({}, {
+		optimize: true,
+		sourceMap: true,
+		decorateBootstrapModule: false,
+		addTryCatchRestartWrapper: false,
+		usePredefineCalls: false,
+		numberOfParts: 1,
+		ignoreMissingModules: false
+	}, bundleOptions);
+
+	const pool = new LocatorResourcePool({
+		ignoreMissingModules: bundleOptions.ignoreMissingModules
+	});
+	const builder = new BundleBuilder(pool);
+
+	if (log.isLevelEnabled("verbose")) {
+		log.verbose(`Generating bundle:`);
+		log.verbose(`bundleDefinition: ${JSON.stringify(bundleDefinition, null, 2)}`);
+		log.verbose(`bundleOptions: ${JSON.stringify(bundleOptions, null, 2)}`);
+	}
+	return pool.prepare( resources, moduleNameMapping ).
+		then( () => builder.createBundle(bundleDefinition, bundleOptions) ).
+		then( (results) => {
+			let bundles;
+			if (results instanceof Array) {
+				bundles = results;
+			} else {
+				bundles = [results];
+			}
+
+			return Promise.all(bundles.map((bundleObj) => {
+				if ( bundleObj ) {
+					const {name, content, sourceMap} = bundleObj;
+					// console.log("creating bundle as '%s'", "/resources/" + name);
+					const res = {};
+					res.bundle = new EvoResource({
+						path: "/resources/" + name,
+						string: content
+					});
+					if (sourceMap) {
+						res.sourceMap = new EvoResource({
+							path: "/resources/" + name + ".map",
+							string: sourceMap
+						});
+					}
+					return res;
+				}
+			}));
+		});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_jsdoc_apiIndexGenerator.js.html b/v3/api/builder_lib_processors_jsdoc_apiIndexGenerator.js.html new file mode 100644 index 0000000000..122d49004f --- /dev/null +++ b/v3/api/builder_lib_processors_jsdoc_apiIndexGenerator.js.html @@ -0,0 +1,154 @@ + + + + + + + builder/lib/processors/jsdoc/apiIndexGenerator.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/jsdoc/apiIndexGenerator.js

+ + + + + + + +
+
+
import {createResource} from "@ui5/fs/resourceFactory";
+import createIndex from "./lib/createIndexFiles.cjs";
+
+/**
+ * @public
+ * @module @ui5/builder/processors/jsdoc/apiIndexGenerator
+ */
+
+/**
+ * Compiles API index resources from all <code>api.json</code> resources available in the given test resources directory
+ * as created by the [sdkTransformer]{@link @ui5/builder/processors/sdkTransformer} processor.
+ * The resulting index resources (e.g. <code>api-index.json</code>,  <code>api-index-deprecated.json</code>,
+ * <code>api-index-experimental.json</code> and <code>api-index-since.json</code>) are mainly to be used in the SDK.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {string} parameters.versionInfoPath Path to <code>sap-ui-version.json</code> resource
+ * @param {string} parameters.testResourcesRootPath Path to <code>/test-resources</code> root directory in the
+ *														given fs
+ * @param {string} parameters.targetApiIndexPath Path to create the generated API index JSON resource for
+ * @param {string} parameters.targetApiIndexDeprecatedPath Path to create the generated API index "deprecated" JSON
+ *															resource for
+ * @param {string} parameters.targetApiIndexExperimentalPath Path to create the generated API index "experimental" JSON
+ *																resource for
+ * @param {string} parameters.targetApiIndexSincePath Path to create the generated API index "since" JSON resource for
+ * @param {fs|module:@ui5/fs/fsInterface} parameters.fs Node fs or
+ * 				custom [fs interface]{@link module:@ui5/fs/fsInterface} to use
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with created resources <code>api-index.json</code>,
+ * <code>api-index-deprecated.json</code>, <code>api-index-experimental.json</code> and
+ * <code>api-index-since.json</code> (names depend on the supplied paths)
+ */
+const apiIndexGenerator = async function({
+	versionInfoPath, testResourcesRootPath, targetApiIndexPath, targetApiIndexDeprecatedPath,
+	targetApiIndexExperimentalPath, targetApiIndexSincePath, fs
+} = {}) {
+	if (!versionInfoPath || !testResourcesRootPath || !targetApiIndexPath || !targetApiIndexDeprecatedPath ||
+			!targetApiIndexExperimentalPath || !targetApiIndexSincePath || !fs) {
+		throw new Error("[apiIndexGenerator]: One or more mandatory parameters not provided");
+	}
+
+	const resourceMap = await createIndex(versionInfoPath, testResourcesRootPath, targetApiIndexPath,
+		targetApiIndexDeprecatedPath, targetApiIndexExperimentalPath, targetApiIndexSincePath, {
+			fs,
+			returnOutputFiles: true
+		});
+
+	return Object.keys(resourceMap).map((resPath) => {
+		return createResource({
+			path: resPath,
+			string: resourceMap[resPath]
+		});
+	});
+};
+
+export default apiIndexGenerator;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_jsdoc_jsdocGenerator.js.html b/v3/api/builder_lib_processors_jsdoc_jsdocGenerator.js.html new file mode 100644 index 0000000000..4a3c9ffdae --- /dev/null +++ b/v3/api/builder_lib_processors_jsdoc_jsdocGenerator.js.html @@ -0,0 +1,283 @@ + + + + + + + builder/lib/processors/jsdoc/jsdocGenerator.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/jsdoc/jsdocGenerator.js

+ + + + + + + +
+
+
import {spawn} from "node:child_process";
+import fs from "graceful-fs";
+import path from "node:path";
+import {promisify} from "node:util";
+const writeFile = promisify(fs.writeFile);
+import {createAdapter} from "@ui5/fs/resourceFactory";
+import {createRequire} from "node:module";
+import {fileURLToPath} from "node:url";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const require = createRequire(import.meta.url);
+
+/**
+ * @public
+ * @module @ui5/builder/processors/jsdoc/jsdocGenerator
+ */
+
+/**
+ * JSDoc generator
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {string} parameters.sourcePath Path of the source files to be processed
+ * @param {string} parameters.targetPath Path to write any output files
+ * @param {string} parameters.tmpPath Path to write temporary and debug files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {string} parameters.options.namespace Namespace to build (e.g. <code>some/project/name</code>)
+ * @param {string} parameters.options.version Project version
+ * @param {Array} [parameters.options.variants=["apijson"]] JSDoc variants to be built
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with newly created resources
+ */
+export default async function jsdocGenerator(
+	{sourcePath, targetPath, tmpPath, options: {projectName, namespace, version, variants}} = {}
+) {
+	if (!sourcePath || !targetPath || !tmpPath || !projectName || !namespace || !version) {
+		throw new Error("[jsdocGenerator]: One or more mandatory parameters not provided");
+	}
+
+	if (!variants || variants.length === 0) {
+		variants = ["apijson"];
+	}
+
+	const config = await jsdocGenerator._generateJsdocConfig({
+		targetPath,
+		tmpPath,
+		namespace,
+		projectName,
+		version,
+		variants
+	});
+
+	const configPath = await jsdocGenerator._writeJsdocConfig(tmpPath, config);
+
+	await jsdocGenerator._buildJsdoc({
+		sourcePath,
+		configPath
+	});
+
+	const fsTarget = createAdapter({
+		fsBasePath: targetPath,
+		virBasePath: "/"
+	});
+
+	// create resources from the output files
+	return Promise.all([
+		fsTarget.byPath(`/test-resources/${namespace}/designtime/api.json`)
+		// fsTarget.byPath(`/libraries/${options.projectName}.js`)
+	]).then((res) => res.filter(($)=>$));
+}
+
+
+/**
+ * Generate jsdoc-config.json content
+ *
+ * @private
+ * @param {object} parameters Parameters
+ * @param {string} parameters.targetPath Path to write any output files
+ * @param {string} parameters.tmpPath Path to write temporary and debug files
+ * @param {string} parameters.projectName Project name
+ * @param {string} parameters.version Project version
+ * @param {string} parameters.namespace Namespace to use (e.g. <code>some/project/name</code>)
+ * @param {Array} parameters.variants JSDoc variants to be built
+ * @returns {string} jsdoc-config.json content string
+ */
+async function generateJsdocConfig({targetPath, tmpPath, namespace, projectName, version, variants}) {
+	// Backlash needs to be escaped as double-backslash
+	// This is not only relevant for win32 paths but also for
+	//	Unix directory names that contain a backslash in their name
+	const backslashRegex = /\\/g;
+
+	// Resolve path to this script to get the path to the JSDoc extensions folder
+	const jsdocPath = path.normalize(__dirname);
+	const pluginPath = path.join(jsdocPath, "lib", "ui5", "plugin.cjs").replace(backslashRegex, "\\\\");
+	// Using export via package.json to allow loading the CJS template.
+	// jsdoc appends /publish to the provided path but doesn't allow to
+	// add the .cjs extension, so loading won't work otherwise.
+	const templatePath = "@ui5/builder/internal/jsdoc/template";
+	const destinationPath = path.normalize(tmpPath).replace(backslashRegex, "\\\\");
+	const jsapiFilePath = path.join(targetPath, "libraries", projectName + ".js").replace(backslashRegex, "\\\\");
+	const apiJsonFolderPath = path.join(tmpPath, "dependency-apis").replace(backslashRegex, "\\\\");
+	const apiJsonFilePath =
+		path.join(targetPath, "test-resources", path.normalize(namespace), "designtime", "api.json")
+			.replace(backslashRegex, "\\\\");
+
+	// Note: While the projectName could also be used here, it is not ensured that it fits to
+	// the library namespace.
+	// As the "uilib" information is used to check for certain constraints it must be aligned with
+	// the technical namespace that is used in the folder-structure, library.js and for the
+	// sap.ui.base.Object based classes.
+	const uilib = namespace.replace(/\//g, ".");
+
+	const config = `{
+		"plugins": ["${pluginPath}"],
+		"opts": {
+			"recurse": true,
+			"lenient": true,
+			"template": "${templatePath}",
+			"ui5": {
+				"saveSymbols": true
+			},
+			"destination": "${destinationPath}"
+		},
+		"templates": {
+			"ui5": {
+				"variants": ${JSON.stringify(variants)},
+				"version": "${version}",
+				"uilib": "${uilib}",
+				"jsapiFile": "${jsapiFilePath}",
+				"apiJsonFolder": "${apiJsonFolderPath}",
+				"apiJsonFile": "${apiJsonFilePath}"
+			}
+		}
+	}`;
+	return config;
+}
+
+/**
+ * Write jsdoc-config.json to file system
+ *
+ * @private
+ * @param {string} targetDirPath Directory Path to write the jsdoc-config.json file to
+ * @param {string} config jsdoc-config.json content
+ * @returns {string} Full path to the written jsdoc-config.json file
+ */
+async function writeJsdocConfig(targetDirPath, config) {
+	const configPath = path.join(targetDirPath, "jsdoc-config.json");
+	await writeFile(configPath, config);
+	return configPath;
+}
+
+
+/**
+ * Execute JSDoc build by spawning JSDoc as an external process
+ *
+ * @private
+ * @param {object} parameters Parameters
+ * @param {string} parameters.sourcePath Project resources (input for JSDoc generation)
+ * @param {string} parameters.configPath Full path to jsdoc-config.json file
+ * @returns {Promise<undefined>}
+ */
+async function buildJsdoc({sourcePath, configPath}) {
+	const args = [
+		require.resolve("jsdoc/jsdoc"),
+		"-c",
+		configPath,
+		"--verbose",
+		sourcePath
+	];
+	const exitCode = await new Promise((resolve /* , reject */) => {
+		const child = spawn("node", args, {
+			stdio: ["ignore", "ignore", "inherit"]
+		});
+		child.on("close", resolve);
+	});
+
+	if (exitCode !== 0) {
+		throw new Error(`JSDoc reported an error, check the log for issues (exit code: ${exitCode})`);
+	}
+}
+
+jsdocGenerator._generateJsdocConfig = generateJsdocConfig;
+jsdocGenerator._writeJsdocConfig = writeJsdocConfig;
+jsdocGenerator._buildJsdoc = buildJsdoc;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_jsdoc_sdkTransformer.js.html b/v3/api/builder_lib_processors_jsdoc_sdkTransformer.js.html new file mode 100644 index 0000000000..f29b485fa9 --- /dev/null +++ b/v3/api/builder_lib_processors_jsdoc_sdkTransformer.js.html @@ -0,0 +1,142 @@ + + + + + + + builder/lib/processors/jsdoc/sdkTransformer.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/jsdoc/sdkTransformer.js

+ + + + + + + +
+
+
import {createResource} from "@ui5/fs/resourceFactory";
+import transformer from "./lib/transformApiJson.cjs";
+
+/**
+ * @public
+ * @module @ui5/builder/processors/jsdoc/sdkTransformer
+ */
+
+/**
+ * Transform api.json as created by [jsdocGenerator]{@link @ui5/builder/processors/jsdoc/jsdocGenerator}
+ * for usage in a UI5 SDK
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {string} parameters.apiJsonPath Path to the projects api.json file as created by
+ *				[jsdocGenerator]{@link @ui5/builder/processors/jsdoc/jsdocGenerator}
+ * @param {string} parameters.dotLibraryPath Path to the projects .library file
+ * @param {string[]} parameters.dependencyApiJsonPaths List of paths to the api.json files of all dependencies of
+ *				the project as created by [jsdocGenerator]{@link @ui5/builder/processors/jsdoc/jsdocGenerator}
+ * @param {string} parameters.targetApiJsonPath Path to create the new, transformed api.json resource for
+ * @param {fs|module:@ui5/fs/fsInterface} parameters.fs Node fs or
+ * 				custom [fs interface]{@link module:@ui5/fs/fsInterface} to use
+ *
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with created resources
+ */
+const sdkTransformer = async function({
+	apiJsonPath, dotLibraryPath, dependencyApiJsonPaths, targetApiJsonPath, fs} = {}
+) {
+	if (!apiJsonPath || !dotLibraryPath || !targetApiJsonPath || !dependencyApiJsonPaths || !fs) {
+		throw new Error("[sdkTransformer]: One or more mandatory parameters not provided");
+	}
+	const fakeTargetPath = "/ignore/this/path/resource/will/be/returned";
+	const apiJsonContent = await transformer(apiJsonPath, fakeTargetPath, dotLibraryPath, dependencyApiJsonPaths, "", {
+		fs,
+		returnOutputFiles: true
+	});
+	return [createResource({
+		path: targetApiJsonPath,
+		string: apiJsonContent
+	})];
+};
+
+export default sdkTransformer;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_libraryLessGenerator.js.html b/v3/api/builder_lib_processors_libraryLessGenerator.js.html new file mode 100644 index 0000000000..4650a8822d --- /dev/null +++ b/v3/api/builder_lib_processors_libraryLessGenerator.js.html @@ -0,0 +1,280 @@ + + + + + + + builder/lib/processors/libraryLessGenerator.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/libraryLessGenerator.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:libraryLessGenerator");
+
+import {promisify} from "node:util";
+import posixPath from "node:path/posix";
+import Resource from "@ui5/fs/Resource";
+
+const IMPORT_PATTERN = /@import .*"(.*)";/g;
+const BASE_LESS_PATTERN = /^\/resources\/sap\/ui\/core\/themes\/([^/]+)\/base\.less$/;
+const GLOBAL_LESS_PATTERN = /^\/resources\/sap\/ui\/core\/themes\/([^/]+)\/global\.less$/;
+
+class LibraryLessGenerator {
+	constructor({fs}) {
+		const readFile = promisify(fs.readFile);
+		this.readFile = async (filePath) => readFile(filePath, {encoding: "utf8"});
+	}
+	async generate({filePath, fileContent}) {
+		return `/* NOTE: This file was generated as an optimized version of ` +
+			`"library.source.less" for the Theme Designer. */\n\n` +
+			(await this.resolveLessImports({
+				filePath,
+				fileContent
+			}));
+	}
+	static getPathToRoot(baseDir) {
+		return posixPath.relative(baseDir, "/") + "/";
+	}
+	async resolveLessImports({filePath, fileContent}) {
+		const imports = this.findLessImports(fileContent);
+		if (!imports.length) {
+			// Skip processing when no imports are found
+			return fileContent;
+		}
+		const replacements = await Promise.all(imports.map(async (importMatch) => {
+			const baseDir = posixPath.dirname(filePath);
+			const resolvedFilePath = posixPath.resolve(baseDir, importMatch.path);
+			importMatch.content = await this.resolveLessImport(importMatch.path, resolvedFilePath, baseDir);
+			return importMatch;
+		}));
+
+		// Apply replacements in reverse order to not modify the relevant indices
+		const array = Array.from(fileContent);
+		for (let i = replacements.length - 1; i >= 0; i--) {
+			const replacement = replacements[i];
+			if (!replacement.content) {
+				continue;
+			}
+			array.splice(
+				/* index   */ replacement.matchStart,
+				/* count   */ replacement.matchLength,
+				/* insert  */ replacement.content
+			);
+		}
+		return array.join("");
+	}
+	async resolveLessImport(originalFilePath, resolvedFilePath, baseDir) {
+		// Rewrite base.less imports
+		const baseLessMatch = BASE_LESS_PATTERN.exec(resolvedFilePath);
+		if (baseLessMatch) {
+			let baseLessThemeName = baseLessMatch[1];
+			if (baseLessThemeName === "base") {
+				baseLessThemeName = "baseTheme";
+			}
+
+			const baseLessPath = LibraryLessGenerator.getPathToRoot(baseDir) +
+				"Base/baseLib/" + baseLessThemeName + "/base.less";
+			return "@import \"" + baseLessPath + "\"; /* ORIGINAL IMPORT PATH: \"" + originalFilePath + "\" */\n";
+		}
+
+		// Rewrite library imports to correct file name
+		if (posixPath.basename(resolvedFilePath) === "library.source.less") {
+			return `@import "${originalFilePath.replace(/library\.source\.less$/, "library.less")}";`;
+		}
+
+		// Excluding global.less within sap.ui.core
+		// It must be imported by the Theme Designer (also see declaration in sap/ui/core/.theming)
+		if (GLOBAL_LESS_PATTERN.test(resolvedFilePath)) {
+			return null;
+		}
+
+		/*
+		 * Throw error in case of files which are not in the same directory as the current file because
+		 * inlining them would break relative URLs.
+		 * A possible solution would be to rewrite relative URLs when inlining the content.
+		 *
+		 * Keeping the import will cause errors since only "library.less" and "global.less" are
+		 * configured to be available to the Theme Designer (.theming generated in generateThemeDesignerResources).
+		 */
+		const relativeFilePath = posixPath.relative(baseDir, resolvedFilePath);
+		if (relativeFilePath.includes(posixPath.sep)) {
+			throw new Error(
+				`Could not inline import '${resolvedFilePath}' outside of theme directory '${baseDir}'. ` +
+				`Stylesheets must be located in the theme directory (no sub-directories).`
+			);
+		}
+
+		let importedFileContent;
+		try {
+			importedFileContent = await this.readFile(resolvedFilePath);
+		} catch (err) {
+			if (err.code === "ENOENT") {
+				throw new Error(
+					`libraryLessGenerator: Unable to resolve import '${originalFilePath}' from '${baseDir}'\n` +
+					err.message
+				);
+			} else {
+				throw err;
+			}
+		}
+		return `/* START "${originalFilePath}" */\n` +
+			(await this.resolveLessImports({
+				filePath: resolvedFilePath,
+				fileContent: importedFileContent
+			})) +
+			`\n/* END "${originalFilePath}" */\n`;
+	}
+	findLessImports(fileContent) {
+		const imports = [];
+		let match;
+		while ((match = IMPORT_PATTERN.exec(fileContent)) !== null) {
+			imports.push({
+				path: match[1],
+				matchStart: match.index,
+				matchLength: match[0].length
+			});
+		}
+		return imports;
+	}
+}
+
+/**
+ * @public
+ * @module @ui5/builder/processors/libraryLessGenerator
+ */
+
+/**
+ * Creates a "library.less" file for the SAP Theme Designer based on a "library.source.less" file.
+ *
+ * <ul>
+ * <li>Bundles all *.less file of the theme by replacing the import with the corresponding file content</li>
+ * <li>Imports to "base.less" are adopted so that they point to the "BaseLib" that is available within
+ * the Theme Designer infrastructure</li>
+ * <li>Imports to "global.less" are kept as they should not be bundled</li>
+ * <li>Imports to "library.source.less" are adopted to "library.less"</li>
+ * </ul>
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of <code>library.source.less</code>
+ * resources
+ * @param {fs|module:@ui5/fs/fsInterface} parameters.fs Node fs or custom
+ * [fs interface]{@link module:@ui5/fs/fsInterface}
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with library.less resources
+ */
+async function createLibraryLess({resources, fs}) {
+	const generator = new LibraryLessGenerator({fs});
+	return Promise.all(resources.map(async (librarySourceLessResource) => {
+		const filePath = librarySourceLessResource.getPath();
+		const fileContent = await librarySourceLessResource.getString();
+
+		log.verbose(`Generating library.less file based on ${filePath}`);
+
+		const libraryLessFileContent = await generator.generate({filePath, fileContent});
+		const libraryLessFilePath = posixPath.join(posixPath.dirname(filePath), "library.less");
+
+		return new Resource({
+			path: libraryLessFilePath,
+			string: libraryLessFileContent
+		});
+	}));
+}
+
+export default createLibraryLess;
+
+let myLibraryLessGenerator;
+// Export class for testing only
+/* istanbul ignore else */
+if (process.env.NODE_ENV === "test") {
+	myLibraryLessGenerator = LibraryLessGenerator;
+}
+export const _LibraryLessGenerator = myLibraryLessGenerator;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_minifier.js.html b/v3/api/builder_lib_processors_minifier.js.html new file mode 100644 index 0000000000..50790568ff --- /dev/null +++ b/v3/api/builder_lib_processors_minifier.js.html @@ -0,0 +1,213 @@ + + + + + + + builder/lib/processors/minifier.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/minifier.js

+ + + + + + + +
+
+
import {fileURLToPath} from "node:url";
+import posixPath from "node:path/posix";
+import os from "node:os";
+import workerpool from "workerpool";
+import Resource from "@ui5/fs/Resource";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:minifier");
+
+const debugFileRegex = /((?:\.view|\.fragment|\.controller|\.designtime|\.support)?\.js)$/;
+
+const MIN_WORKERS = 2;
+const MAX_WORKERS = 4;
+const osCpus = os.cpus().length || 1;
+const maxWorkers = Math.max(Math.min(osCpus - 1, MAX_WORKERS), MIN_WORKERS);
+
+// Shared workerpool across all executions until the taskUtil cleanup is triggered
+let pool;
+
+function getPool(taskUtil) {
+	if (!pool) {
+		log.verbose(`Creating workerpool with up to ${maxWorkers} workers (available CPU cores: ${osCpus})`);
+		const workerPath = fileURLToPath(new URL("./minifierWorker.js", import.meta.url));
+		pool = workerpool.pool(workerPath, {
+			workerType: "auto",
+			maxWorkers
+		});
+		taskUtil.registerCleanupTask(() => {
+			log.verbose(`Terminating workerpool`);
+			const poolToBeTerminated = pool;
+			pool = null;
+			poolToBeTerminated.terminate();
+		});
+	}
+	return pool;
+}
+
+async function minifyInWorker(options, taskUtil) {
+	return getPool(taskUtil).exec("execMinification", [options]);
+}
+
+/**
+ * @public
+ * @module @ui5/builder/processors/minifier
+ */
+
+/**
+ * Result set
+ *
+ * @public
+ * @typedef {object} MinifierResult
+ * @property {@ui5/fs/Resource} resource Minified resource
+ * @property {@ui5/fs/Resource} dbgResource Debug (non-minified) variant
+ * @property {@ui5/fs/Resource} sourceMap Source Map
+ */
+
+/**
+ * Minifies the supplied resources.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of resources to be processed
+ * @param {@ui5/builder/tasks/TaskUtil|object} [parameters.taskUtil] TaskUtil instance.
+ *    Required when using the <code>useWorkers</code> option
+ * @param {object} [parameters.options] Options
+ * @param {boolean} [parameters.options.addSourceMappingUrl=true]
+ *   Whether to add a sourceMappingURL reference to the end of the minified resource
+ * @param {boolean} [parameters.options.useWorkers=false]
+ *  Whether to offload the minification task onto separate CPU threads. This often speeds up the build process
+ * @returns {Promise<module:@ui5/builder/processors/minifier~MinifierResult[]>}
+ *   Promise resolving with object of resource, dbgResource and sourceMap
+ */
+export default async function({resources, taskUtil, options: {addSourceMappingUrl = true, useWorkers = false} = {}}) {
+	let minify;
+	if (useWorkers) {
+		if (!taskUtil) {
+			// TaskUtil is required for worker support
+			throw new Error(`Minifier: Option 'useWorkers' requires a taskUtil instance to be provided`);
+		}
+		minify = minifyInWorker;
+	} else {
+		// Do not use workerpool
+		minify = (await import("./minifierWorker.js")).default;
+	}
+
+	return Promise.all(resources.map(async (resource) => {
+		const dbgPath = resource.getPath().replace(debugFileRegex, "-dbg$1");
+		const dbgResource = await resource.clone();
+		dbgResource.setPath(dbgPath);
+
+		const filename = posixPath.basename(resource.getPath());
+		const code = await resource.getString();
+
+		const sourceMapOptions = {
+			filename
+		};
+		if (addSourceMappingUrl) {
+			sourceMapOptions.url = filename + ".map";
+		}
+		const dbgFilename = posixPath.basename(dbgPath);
+
+		const result = await minify({
+			filename,
+			dbgFilename,
+			code,
+			sourceMapOptions
+		}, taskUtil);
+		resource.setString(result.code);
+		const sourceMapResource = new Resource({
+			path: resource.getPath() + ".map",
+			string: result.map
+		});
+		return {resource, dbgResource, sourceMapResource};
+	}));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_nonAsciiEscaper.js.html b/v3/api/builder_lib_processors_nonAsciiEscaper.js.html new file mode 100644 index 0000000000..c4aec2117c --- /dev/null +++ b/v3/api/builder_lib_processors_nonAsciiEscaper.js.html @@ -0,0 +1,215 @@ + + + + + + + builder/lib/processors/nonAsciiEscaper.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/nonAsciiEscaper.js

+ + + + + + + +
+
+
import escapeUnicode from "escape-unicode";
+
+/**
+ * @public
+ * @module @ui5/builder/processors/nonAsciiEscaper
+ */
+
+/**
+ * @see https://en.wikipedia.org/wiki/ASCII
+ * ascii contains 128 characters.
+ * its char codes reach from 0 to 127.
+ * @type {number}
+ */
+const CHAR_CODE_OF_LAST_ASCII_CHARACTER = 127;
+
+// use memoization for escapeUnicode function for performance
+const memoizeEscapeUnicodeMap = Object.create(null);
+const memoizeEscapeUnicode = function(sChar) {
+	if (memoizeEscapeUnicodeMap[sChar]) {
+		return memoizeEscapeUnicodeMap[sChar];
+	}
+	memoizeEscapeUnicodeMap[sChar] = escapeUnicode(sChar);
+	return memoizeEscapeUnicodeMap[sChar];
+};
+
+/**
+ * Escapes non ASCII characters with unicode escape sequences.
+ *
+ * @see https://en.wikipedia.org/wiki/ASCII
+ * @see https://tools.ietf.org/html/rfc5137#section-6.1
+ *
+ *
+ * @param {string} string input string with non ascii characters, e.g. L♥VE
+ * @returns {{string: (string), modified: boolean}} output string with all non ascii
+ * characters being escaped by unicode sequence, e.g. L\u2665VE
+ */
+const escapeNonAscii = function(string) {
+	let result = "";
+	let modified = false;
+	for (let i = 0; i < string.length; i++) {
+		const char = string[i];
+		// check for non ascii characters (characters which have a char code
+		// greater than the ascii character code range)
+		if (string.charCodeAt(i) > CHAR_CODE_OF_LAST_ASCII_CHARACTER) {
+			result += memoizeEscapeUnicode(char);
+			modified = true;
+		} else {
+			result += char;
+		}
+	}
+	return {
+		modified,
+		string: result
+	};
+};
+
+/**
+ * Escapes non ASCII characters with unicode escape sequences.
+ *
+ * @example
+ * const encoding = nonAsciiEscaper.getEncodingFromAlias("ISO-8859-1");
+ * nonAsciiEscaper({resources, options: {encoding}});
+ *
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of resources to be processed
+ * @param {object} [parameters.options] Options
+ * @param {string} [parameters.options.encoding="utf8"] resource file encoding
+ *   ({@link https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings Node.js character encodings}).
+ *   Use #getEncodingFromAlias to get the encoding string
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with the processed resources
+ */
+async function nonAsciiEscaper({resources, options: {encoding}}) {
+	encoding = encoding || "utf8";
+
+	async function processResource(resource) {
+		const resourceString = (await resource.getBuffer()).toString(encoding);
+		const escaped = escapeNonAscii(resourceString);
+		// only modify the resource's string if it was changed
+		if (escaped.modified) {
+			resource.setString(escaped.string);
+		}
+		return resource;
+	}
+
+	return Promise.all(resources.map(processResource));
+}
+
+const encodingMap = {
+	"UTF-8": "utf8",
+	"ISO-8859-1": "latin1",
+};
+
+/**
+ * Provides a mapping from user-friendly encoding name (alias) such as "UTF-8" and "ISO-8859-1" to node
+ * specific encoding name such as "utf8" or "latin1". Simplifies usage of nonAsciiEscaper encoding option
+ * such that it can be used standalone without the respective task (e.g. in Splitter, Bundler and related projects).
+ *
+ * @public
+ * @function getEncodingFromAlias
+ * @alias @ui5/builder/processors/nonAsciiEscaper․getEncodingFromAlias
+ * @static
+ *
+ * @param {string} encoding encoding labels: "UTF-8" and "ISO-8859-1"
+ * @returns {string} node.js character encoding string, e.g. utf8 and latin1
+ */
+nonAsciiEscaper.getEncodingFromAlias = function(encoding) {
+	if (!encodingMap[encoding]) {
+		throw new Error(
+			`Encoding "${encoding}" is not supported. Only ${Object.keys(encodingMap).join(", ")} are allowed values` );
+	}
+	return encodingMap[encoding];
+};
+
+export default nonAsciiEscaper;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_stringReplacer.js.html b/v3/api/builder_lib_processors_stringReplacer.js.html new file mode 100644 index 0000000000..44d1e0e779 --- /dev/null +++ b/v3/api/builder_lib_processors_stringReplacer.js.html @@ -0,0 +1,125 @@ + + + + + + + builder/lib/processors/stringReplacer.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/stringReplacer.js

+ + + + + + + +
+
+
/**
+ * @public
+ * @module @ui5/builder/processors/stringReplacer
+ */
+
+/**
+ * Replaces placeholders with corresponding values.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of resources to be processed
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pattern Pattern of placeholders
+ * @param {string} parameters.options.replacement Replacement for placeholders
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with modified resources
+ */
+export default function({resources, options: {pattern, replacement}}) {
+	return Promise.all(resources.map(async (resource) => {
+		const content = await resource.getString();
+		const newContent = content.replaceAll(pattern, replacement);
+		if (content !== newContent) {
+			resource.setString(newContent);
+		}
+		return resource;
+	}));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_themeBuilder.js.html b/v3/api/builder_lib_processors_themeBuilder.js.html new file mode 100644 index 0000000000..851179c454 --- /dev/null +++ b/v3/api/builder_lib_processors_themeBuilder.js.html @@ -0,0 +1,265 @@ + + + + + + + builder/lib/processors/themeBuilder.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/themeBuilder.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:themeBuilder");
+import posixPath from "node:path/posix";
+import less from "less-openui5";
+import Resource from "@ui5/fs/Resource";
+
+const libraryMatchPattern = /^\/resources\/(.*)\/themes\/[^/]*\/library\.source\.less$/i;
+
+/**
+ * @public
+ * @module @ui5/builder/processors/ThemeBuilder
+ */
+
+/**
+ * Builds a library theme
+ *
+ * @public
+ * @class
+ */
+export class ThemeBuilder {
+	/**
+	 * Constructor
+	 *
+	 * @public
+	 * @param {fs|module:@ui5/fs/fsInterface} fs Node fs or custom
+	 * 		[fs interface]{@link module:@ui5/fs/fsInterface}
+	 */
+	constructor({fs}) {
+		this.builder = new less.Builder({fs});
+	}
+
+	/**
+	 * Starts the theme build
+	 *
+	 * @public
+	 * @param {@ui5/fs/Resource[]} resources Library files
+	 * @param {object} [options] Build options
+	 * @param {boolean} [options.compress=false] Compress build output (CSS / JSON)
+	 * @param {boolean} [options.cssVariables=false] Generates the CSS variables
+	 *   (css-variables.css, css-variables.source.less) and the skeleton for a theme
+	 *   (library-skeleton.css, [library-skeleton-RTL.css])
+	 * @returns {Promise<@ui5/fs/Resource[]>} Resolving with array of created files
+	 */
+	build(resources, {compress = false, cssVariables = false} = {}) {
+		const files = [];
+
+		const compile = (resource) => {
+			log.verbose(`Compiling ${resource.getPath()}`);
+
+			let libraryName;
+			const libraryMatch = libraryMatchPattern.exec(resource.getPath());
+			if (libraryMatch) {
+				libraryName = libraryMatch[1].replace(/\//g, ".");
+			}
+
+			return this.builder.build({
+				lessInputPath: resource.getPath(),
+				library: {
+					name: libraryName
+				},
+				compiler: {
+					compress
+				},
+				cssVariables
+			}).then((result) => {
+				const themeDir = posixPath.dirname(resource.getPath());
+
+				const libCss = new Resource({
+					path: themeDir + "/library.css",
+					string: result.css
+				});
+
+				const libCssRtl = new Resource({
+					path: themeDir + "/library-RTL.css",
+					string: result.cssRtl
+				});
+
+				const libParams = new Resource({
+					path: themeDir + "/library-parameters.json",
+					string: JSON.stringify(result.variables, null, compress ? null : "\t")
+				});
+
+				files.push(libCss, libCssRtl, libParams);
+
+				if (cssVariables) {
+					const libCssVarsSource = new Resource({
+						path: themeDir + "/css_variables.source.less",
+						string: result.cssVariablesSource
+					});
+					const libCssVars = new Resource({
+						path: themeDir + "/css_variables.css",
+						string: result.cssVariables
+					});
+					const libCssSkel = new Resource({
+						path: themeDir + "/library_skeleton.css",
+						string: result.cssSkeleton
+					});
+					const libCssSkelRtl = new Resource({
+						path: themeDir + "/library_skeleton-RTL.css",
+						string: result.cssSkeletonRtl
+					});
+
+					files.push(libCssVarsSource, libCssVars, libCssSkel, libCssSkelRtl);
+				}
+			}, (err) => {
+				log.error(`Error while compiling ${resource.getPath()}: ${err.message}`);
+				throw err;
+			});
+		};
+
+		return Promise.all(resources.map(compile)).then(() => {
+			return files;
+		});
+	}
+
+	/**
+	 * Clears all cached build results.
+	 *
+	 * Use this method to prevent high memory consumption when building many themes within the same process.
+ 	 *
+	 * @public
+	 */
+	clearCache() {
+		this.builder.clearCache();
+	}
+}
+
+/**
+ *
+ * @public
+ * @typedef {object} ThemeBuilderOptions
+ * @property {boolean} [compress=false] Compress build output (CSS / JSON)
+ * @property {boolean} [cssVariables=false] Generates the CSS variables
+ * (css-variables.css, css-variables.source.less) and the skeleton for a theme
+ * (library-skeleton.css, [library-skeleton-RTL.css])
+ */
+
+/**
+ * Builds a library theme.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @alias @ui5/builder/processors/themeBuilder
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/Resource[]} parameters.resources List of <code>library.source.less</code>
+ *   resources to be processed
+ * @param {fs|module:@ui5/fs/fsInterface} parameters.fs Node fs or custom
+ *   [fs interface]{@link module:@ui5/fs/fsInterface}
+ * @param {module:@ui5/builder/processors/ThemeBuilder~ThemeBuilderOptions} [parameters.options] Options
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with theme resources
+ */
+export default async function({
+	resources,
+	fs,
+	options = {}
+}) {
+	const {compress, cssVariables} =
+	/** @type {module:@ui5/builder/processors/ThemeBuilder~ThemeBuilderOptions} */ (options);
+	const themeBuilder = new ThemeBuilder({fs});
+	return themeBuilder.build(resources, {
+		compress,
+		cssVariables
+	}).then((files) => {
+		themeBuilder.clearCache();
+		return files;
+	});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_processors_versionInfoGenerator.js.html b/v3/api/builder_lib_processors_versionInfoGenerator.js.html new file mode 100644 index 0000000000..0c4f4876a8 --- /dev/null +++ b/v3/api/builder_lib_processors_versionInfoGenerator.js.html @@ -0,0 +1,565 @@ + + + + + + + builder/lib/processors/versionInfoGenerator.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/processors/versionInfoGenerator.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:processors:versionInfoGenerator");
+import {createResource} from "@ui5/fs/resourceFactory";
+import posixPath from "node:path/posix";
+
+/**
+ * @public
+ * @module @ui5/builder/processors/versionInfoGenerator
+ */
+
+function pad(v) {
+	return String(v).padStart(2, "0");
+}
+function getTimestamp() {
+	const date = new Date();
+	const year = date.getFullYear();
+	const month = pad(date.getMonth() + 1);
+	const day = pad(date.getDate());
+	const hours = pad(date.getHours());
+	const minutes = pad(date.getMinutes());
+	// yyyyMMddHHmm
+	return year + month + day + hours + minutes;
+}
+
+/**
+ * Manifest libraries as defined in the manifest.json file
+ *
+ * @typedef {Object<string, {lazy: boolean}>} ManifestLibraries
+ *
+ * sample:
+ * <pre>
+ * {
+ * 	"sap.chart": {
+ * 		"lazy": true
+ * 	},
+ * 	"sap.f": { }
+ * }
+ * </pre>
+ */
+
+/**
+ * Extracted information from a manifest's <code>sap.app</code> and <code>sap.ui5</code> sections.
+ *
+ * @typedef {object} ManifestInfo
+ *
+ * @property {string} id The library name, e.g. "lib.x"
+ * @property {string} embeddedBy the library this component is embedded in, e.g. "lib.x"
+ * @property {string[]} embeds the embedded component names, e.g. ["lib.x.sub"]
+ * @property {module:@ui5/builder/processors/versionInfoGenerator~ManifestLibraries} libs the dependencies, e.g.
+ * 				{"sap.chart":{"lazy": true}, "sap.f":{}}
+ */
+
+
+/**
+ * Processes manifest resource and extracts information.
+ *
+ * @param {@ui5/fs/Resource} manifestResource
+ * @returns {Promise<module:@ui5/builder/processors/versionInfoGenerator~ManifestInfo>}
+ */
+const processManifest = async (manifestResource) => {
+	const manifestContent = await manifestResource.getString();
+	const manifestObject = JSON.parse(manifestContent);
+	const manifestInfo = Object.create(null);
+
+	// sap.ui5/dependencies is used for the "manifestHints/libs"
+	if (manifestObject["sap.ui5"]) {
+		const manifestDependencies = manifestObject["sap.ui5"]["dependencies"];
+		if (manifestDependencies && manifestDependencies.libs) {
+			const libs = Object.create(null);
+			for (const [libKey, libValue] of Object.entries(manifestDependencies.libs)) {
+				libs[libKey] = Object.create(null);
+				if (libValue.lazy) {
+					libs[libKey].lazy = true;
+				}
+			}
+			manifestInfo.libs = libs;
+		}
+	}
+
+	// sap.app/embeds, sap.app/embeddedBy and sap.app/id is used for "components"
+	if (manifestObject["sap.app"]) {
+		const manifestEmbeds = manifestObject["sap.app"]["embeds"];
+		manifestInfo.embeds = manifestEmbeds;
+
+		const manifestEmbeddedBy = manifestObject["sap.app"]["embeddedBy"];
+		manifestInfo.embeddedBy = manifestEmbeddedBy;
+
+		const id = manifestObject["sap.app"]["id"];
+		manifestInfo.id = id;
+	}
+	return manifestInfo;
+};
+
+/**
+ * Checks if a component (componentPath) is bundled with the library (embeddedBy)
+ *
+ * @param {string} embeddedBy e.g. "../"
+ * @param {string} componentPath e.g. "lib/x/sub"
+ * @param {string} libraryPathPrefix e.g. "lib/x"
+ * @returns {boolean} whether or not this component is bundled with the library
+ */
+const isBundledWithLibrary = (embeddedBy, componentPath, libraryPathPrefix) => {
+	if (typeof embeddedBy === "undefined") {
+		log.verbose("  Component doesn't declare 'sap.app/embeddedBy', don't list it as 'embedded'");
+		return false;
+	}
+	if (typeof embeddedBy !== "string") {
+		log.error(
+			`  Component '${componentPath}': property 'sap.app/embeddedBy' is of type '${typeof embeddedBy}' ` +
+			`(expected 'string'), it won't be listed as 'embedded'`);
+		return false;
+	}
+	if ( !embeddedBy.length ) {
+		log.error(
+			`  Component '${componentPath}': property 'sap.app/embeddedBy' has an empty string value ` +
+			`(which is invalid), it won't be listed as 'embedded'`
+		);
+		return false;
+	}
+	let resolvedEmbeddedBy = posixPath.resolve(componentPath, embeddedBy);
+	if ( resolvedEmbeddedBy && !resolvedEmbeddedBy.endsWith("/") ) {
+		resolvedEmbeddedBy = resolvedEmbeddedBy + "/";
+	}
+	if ( libraryPathPrefix === resolvedEmbeddedBy ) {
+		log.verbose("  Component's 'sap.app/embeddedBy' property points to library, list it as 'embedded'");
+		return true;
+	} else {
+		log.verbose(
+			`  Component's 'sap.app/embeddedBy' points to '${resolvedEmbeddedBy}', don't list it as 'embedded'`);
+		return false;
+	}
+};
+
+/**
+ * Retrieves the manifest path of a subcomponent
+ *
+ * @param {string} filePath path to the manifest, e.g. "lib/x/manifest.json"
+ * @param {string} subPath relative sub path, e.g. "sub"
+ * @returns {string} manifest path, e.g. "lib/x/sub/manifest.json"
+ */
+const getManifestPath = (filePath, subPath) => {
+	return posixPath.resolve(posixPath.dirname(filePath), subPath, "manifest.json");
+};
+
+/**
+ * Represents dependency information for a library.
+ * Dependencies can be retrieved using <code>#getResolvedLibraries</code>
+ * and with that are resolved recursively
+ */
+class DependencyInfo {
+	/**
+	 *
+	 * @param {module:@ui5/builder/processors/versionInfoGenerator~ManifestLibraries} libs
+	 * @param {string} name library name, e.g. "lib.x"
+	 */
+	constructor(libs, name) {
+		this.libs = libs;
+		this.name = name;
+	}
+
+	/**
+	 * Add library to libsResolved and if already present
+	 * merge lazy property
+	 *
+	 * @param {string} libName library name, e.g. "lib.x"
+	 * @param {boolean} lazy
+	 * @returns {{lazy: boolean}} the added library
+	 */
+	addResolvedLibDependency(libName, lazy) {
+		let alreadyResolved = this._libsResolved[libName];
+		if (!alreadyResolved) {
+			alreadyResolved = Object.create(null);
+			if (lazy) {
+				alreadyResolved.lazy = true;
+			}
+			this._libsResolved[libName] = alreadyResolved;
+		} else {
+			// siblings if sibling is eager only if one other sibling eager
+			alreadyResolved.lazy = alreadyResolved.lazy && lazy;
+		}
+		return alreadyResolved;
+	}
+
+	/**
+	 * Resolves dependencies recursively and retrieves them with
+	 * - resolved siblings a lazy and a eager dependency becomes eager
+	 * - resolved children become lazy if their parent is lazy
+	 *
+	 * @param {Map<string,DependencyInfo>} dependencyInfoMap
+	 * @returns {module:@ui5/builder/processors/versionInfoGenerator~ManifestLibraries} resolved libraries
+	 */
+	getResolvedLibraries(dependencyInfoMap) {
+		if (!this._libsResolved) {
+			// early set if there is a potential cycle
+			this._libsResolved = Object.create(null);
+			if (!this.libs) {
+				return this._libsResolved;
+			}
+			for (const [libName, libValue] of Object.entries(this.libs)) {
+				const lazy = libValue.lazy;
+				const dependencyInfoObjectAdded = this.addResolvedLibDependency(libName, lazy);
+				const dependencyInfo = dependencyInfoMap.get(libName);
+				if (dependencyInfo) {
+					const childLibsResolved = dependencyInfo.getResolvedLibraries(dependencyInfoMap);
+
+					// children if parent is lazy children become lazy
+					for (const [resolvedLibName, resolvedLib] of Object.entries(childLibsResolved)) {
+						this.addResolvedLibDependency(resolvedLibName,
+							resolvedLib.lazy || dependencyInfoObjectAdded.lazy);
+					}
+				} else {
+					log.info(`Cannot find dependency '${libName}' `+
+						`defined in the manifest.json or .library file of project '${this.name}'. ` +
+						"This might prevent some UI5 runtime performance optimizations from taking effect. " +
+						"Please double check your project's dependency configuration.");
+				}
+			}
+		}
+		return this._libsResolved;
+	}
+}
+
+
+/**
+ * Sorts the keys of a given object
+ *
+ * @param {object} obj the object
+ * @returns {object} the object with sorted keys
+ */
+const sortObjectKeys = (obj) => {
+	const sortedObject = Object.create(null);
+	const keys = Object.keys(obj);
+	keys.sort();
+	keys.forEach((key) => {
+		sortedObject[key] = obj[key];
+	});
+	return sortedObject;
+};
+
+/**
+ * Builds the manifestHints object from the dependencyInfo
+ *
+ * @param {DependencyInfo} dependencyInfo
+ * @param {Map<string, DependencyInfo>} dependencyInfoMap
+ * @returns {{dependencies: {libs: ManifestLibraries}}} manifestHints
+ */
+const getManifestHints = (dependencyInfo, dependencyInfoMap) => {
+	if (dependencyInfo) {
+		const libsResolved = dependencyInfo.getResolvedLibraries(dependencyInfoMap);
+		if (libsResolved && Object.keys(libsResolved).length) {
+			return {
+				dependencies: {
+					libs: sortObjectKeys(libsResolved)
+				}
+			};
+		}
+	}
+};
+
+/**
+ * Common type for Library and Component
+ * embeds and bundled components make only sense for library
+ *
+ * @typedef {object} ArtifactInfo
+ * @property {string} componentName The library name, e.g. "lib.x"
+ * @property {Set<string>} bundledComponents The embedded components which have an embeddedBy reference to the library
+ * @property {DependencyInfo} dependencyInfo The dependency info object
+ * @property {module:@ui5/builder/processors/versionInfoGenerator~ArtifactInfo[]} embeds The embedded artifact infos
+ */
+
+
+/**
+ * Processes the manifest and creates a ManifestInfo and an ArtifactInfo.
+ *
+ * @param {@ui5/fs/Resource} libraryManifest
+ * @param {string} [name] library name, if not provided using the ManifestInfo's id
+ * @returns {Promise<{manifestInfo: ManifestInfo, libraryArtifactInfo: ArtifactInfo}>}
+ */
+async function processManifestAndGetArtifactInfo(libraryManifest, name) {
+	const manifestInfo = await processManifest(libraryManifest);
+	name = name || manifestInfo.id;
+	const libraryArtifactInfo = Object.create(null);
+	libraryArtifactInfo.componentName = name;
+	libraryArtifactInfo.dependencyInfo = new DependencyInfo(manifestInfo.libs, name);
+	return {manifestInfo, libraryArtifactInfo};
+}
+
+/**
+ * Processes the library info and fills the maps <code>dependencyInfoMap</code> and <code>embeddedInfoMap</code>.
+ *
+ * @param {module:@ui5/builder/processors/versionInfoGenerator~LibraryInfo} libraryInfo
+ * @returns {Promise<module:@ui5/builder/processors/versionInfoGenerator~ArtifactInfo|undefined>}
+ */
+const processLibraryInfo = async (libraryInfo) => {
+	if (!libraryInfo.libraryManifest) {
+		log.verbose(
+			`Cannot add meta information for library '${libraryInfo.name}'. The manifest.json file cannot be found`);
+		return;
+	}
+
+	const {manifestInfo, libraryArtifactInfo} =
+		await processManifestAndGetArtifactInfo(libraryInfo.libraryManifest, libraryInfo.name);
+
+	const bundledComponents = new Set();
+	libraryArtifactInfo.bundledComponents = bundledComponents;
+
+	const embeds = manifestInfo.embeds||[]; // e.g. ["sub"]
+	// filter only embedded manifests
+	const embeddedPaths = embeds.map((embed) => {
+		return getManifestPath(libraryInfo.libraryManifest.getPath(), embed);
+	});
+	// e.g. manifest resource with lib/x/sub/manifest.json
+	let embeddedManifests = libraryInfo.embeddedManifests || [];
+	embeddedManifests = embeddedManifests.filter((manifestResource) => {
+		return embeddedPaths.includes(manifestResource.getPath());
+	});
+
+	// get all embedded manifests
+	const embeddedManifestPromises = embeddedManifests.map(async (embeddedManifest) => {
+		const {manifestInfo: embeddedManifestInfo, libraryArtifactInfo: embeddedArtifactInfo} =
+			await processManifestAndGetArtifactInfo(embeddedManifest);
+
+		const componentName = embeddedManifestInfo.id;
+
+		const embeddedManifestDirName = posixPath.dirname(embeddedManifest.getPath());
+		const libraryManifestDirName = posixPath.dirname(libraryInfo.libraryManifest.getPath());
+
+		if (isBundledWithLibrary(embeddedManifestInfo.embeddedBy, embeddedManifestDirName,
+			libraryManifestDirName + "/")) {
+			bundledComponents.add(componentName);
+		}
+		return embeddedArtifactInfo;
+	});
+
+	const embeddedArtifactInfos = await Promise.all(embeddedManifestPromises);
+	libraryArtifactInfo.embeds = embeddedArtifactInfos;
+
+	return libraryArtifactInfo;
+};
+
+/**
+ * Library Info
+ *
+ * contains information about the name and the version of the library and its manifest, as well as the nested manifests.
+ *
+ * @public
+ * @typedef {object} LibraryInfo
+ * @property {string} name The library name, e.g. "lib.x"
+ * @property {string} version The library version, e.g. "1.0.0"
+ * @property {@ui5/fs/Resource} libraryManifest library manifest resource,
+ *  e.g. resource with path "lib/x/manifest.json"
+ * @property {@ui5/fs/Resource[]} embeddedManifests list of embedded manifest resources,
+ *  e.g. resource with path "lib/x/sub/manifest.json"
+ */
+
+/**
+ * Creates sap-ui-version.json.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.rootProjectName Name of the root project
+ * @param {string} parameters.options.rootProjectVersion Version of the root project
+ * @param {module:@ui5/builder/processors/versionInfoGenerator~LibraryInfo[]} parameters.options.libraryInfos Array of
+ *				objects representing libraries,
+ *  e.g. <pre>
+ *   {
+ *      name: "lib.x",
+ *      version: "1.0.0",
+ *      libraryManifest: @ui5/fs/Resource,
+ *      embeddedManifests: @ui5/fs/Resource[]
+ *   }
+ * </pre>
+ * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with an array containing the versionInfo resource
+ */
+
+export default async function({options}) {
+	if (!options.rootProjectName || options.rootProjectVersion === undefined || options.libraryInfos === undefined) {
+		throw new Error("[versionInfoGenerator]: Missing options parameters");
+	}
+
+	const buildTimestamp = getTimestamp();
+
+	/**
+	 * componentName to dependency info
+	 *
+	 * @type {Map<string, DependencyInfo>}
+	 */
+	const dependencyInfoMap = new Map();
+
+
+	// process library infos
+	const libraryInfosProcessPromises = options.libraryInfos.map((libraryInfo) => {
+		return processLibraryInfo(libraryInfo);
+	});
+
+	let artifactInfos = await Promise.all(libraryInfosProcessPromises);
+	artifactInfos = artifactInfos.filter(Boolean);
+
+	// fill dependencyInfoMap
+	artifactInfos.forEach((artifactInfo) => {
+		dependencyInfoMap.set(artifactInfo.componentName, artifactInfo.dependencyInfo);
+	});
+
+
+	const libraries = options.libraryInfos.map((libraryInfo) => {
+		const library = {
+			name: libraryInfo.name,
+			version: libraryInfo.version,
+			buildTimestamp: buildTimestamp,
+			scmRevision: ""// TODO: insert current library scm revision here
+		};
+
+		const dependencyInfo = dependencyInfoMap.get(libraryInfo.name);
+		const manifestHints = getManifestHints(dependencyInfo, dependencyInfoMap);
+		if (manifestHints) {
+			library.manifestHints = manifestHints;
+		}
+		return library;
+	});
+
+	// sort libraries alphabetically
+	libraries.sort((a, b) => {
+		return a.name.localeCompare(b.name);
+	});
+
+	// components
+	let components;
+	artifactInfos.forEach((artifactInfo) => {
+		artifactInfo.embeds.forEach((embeddedArtifactInfo) => {
+			const componentObject = Object.create(null);
+			const bundledComponents = artifactInfo.bundledComponents;
+			const componentName = embeddedArtifactInfo.componentName;
+			if (!bundledComponents.has(componentName)) {
+				componentObject.hasOwnPreload = true;
+			}
+			componentObject.library = artifactInfo.componentName;
+
+			const manifestHints = getManifestHints(embeddedArtifactInfo.dependencyInfo, dependencyInfoMap);
+			if (manifestHints) {
+				componentObject.manifestHints = manifestHints;
+			}
+
+			components = components || Object.create(null);
+			components[componentName] = componentObject;
+		});
+	});
+
+	// sort components alphabetically
+	components = components && sortObjectKeys(components);
+
+	const versionJson = {
+		name: options.rootProjectName,
+		version: options.rootProjectVersion, // TODO: insert current application version here
+		buildTimestamp: buildTimestamp,
+		scmRevision: "", // TODO: insert current application scm revision here
+		// gav: "", // TODO: insert current application id + version here
+		libraries,
+		components
+	};
+
+	return [createResource({
+		path: "/resources/sap-ui-version.json",
+		string: JSON.stringify(versionJson, null, "\t")
+	})];
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_buildThemes.js.html b/v3/api/builder_lib_tasks_buildThemes.js.html new file mode 100644 index 0000000000..7d84033682 --- /dev/null +++ b/v3/api/builder_lib_tasks_buildThemes.js.html @@ -0,0 +1,242 @@ + + + + + + + builder/lib/tasks/buildThemes.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/buildThemes.js

+ + + + + + + +
+
+
import path from "node:path";
+import themeBuilder from "../processors/themeBuilder.js";
+import fsInterface from "@ui5/fs/fsInterface";
+import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:buildThemes");
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/buildThemes
+ */
+/**
+ * Task to build a library theme.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {string} parameters.options.inputPattern Search pattern for *.less files to be built
+ * @param {string} [parameters.options.librariesPattern] Search pattern for .library files
+ * @param {string} [parameters.options.themesPattern] Search pattern for sap.ui.core theme folders
+ * @param {boolean} [parameters.options.compress=true]
+ * @param {boolean} [parameters.options.cssVariables=false]
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({
+	workspace, dependencies,
+	options: {
+		projectName, inputPattern, librariesPattern, themesPattern, compress, cssVariables
+	}
+}) {
+	const combo = new ReaderCollectionPrioritized({
+		name: `theme - prioritize workspace over dependencies: ${projectName}`,
+		readers: [workspace, dependencies]
+	});
+
+	compress = compress === undefined ? true : compress;
+
+	const pAllResources = workspace.byGlob(inputPattern);
+	let pAvailableLibraries;
+	let pAvailableThemes;
+	if (librariesPattern) {
+		// If a librariesPattern is given
+		//	we will use it to reduce the set of libraries a theme will be built for
+		pAvailableLibraries = combo.byGlob(librariesPattern);
+	}
+	if (themesPattern) {
+		// If a themesPattern is given
+		//	we will use it to reduce the set of themes that will be built
+		pAvailableThemes = combo.byGlob(themesPattern, {nodir: false});
+	}
+
+	/* Don't try to build themes for libraries that are not available
+	(maybe replace this with something more aware of which dependencies are optional and therefore
+		legitimately missing and which not (fault case))
+		*/
+	let availableLibraries;
+	if (pAvailableLibraries) {
+		availableLibraries = [];
+		(await pAvailableLibraries).forEach((resource) => {
+			const library = path.dirname(resource.getPath());
+			if (!availableLibraries.includes(library)) {
+				availableLibraries.push(library);
+			}
+		});
+	}
+	let availableThemes;
+	if (pAvailableThemes) {
+		availableThemes = (await pAvailableThemes)
+			.filter((resource) => resource.getStatInfo().isDirectory())
+			.map((resource) => {
+				return path.basename(resource.getPath());
+			});
+	}
+
+	let allResources = await pAllResources;
+
+	const isAvailable = function(resource) {
+		let libraryAvailable = false;
+		let themeAvailable = false;
+		const resourcePath = resource.getPath();
+		const themeName = path.basename(path.dirname(resourcePath));
+
+		if (!availableLibraries || availableLibraries.length === 0) {
+			libraryAvailable = true; // If no libraries are found, build themes for all libraries
+		} else {
+			for (let i = availableLibraries.length - 1; i >= 0; i--) {
+				if (resourcePath.startsWith(availableLibraries[i])) {
+					libraryAvailable = true;
+				}
+			}
+		}
+
+		if (!availableThemes || availableThemes.length === 0) {
+			themeAvailable = true; // If no themes are found, build all themes
+		} else {
+			themeAvailable = availableThemes.includes(themeName);
+		}
+
+		if (log.isLevelEnabled("verbose")) {
+			if (!libraryAvailable) {
+				log.silly(`Skipping ${resourcePath}: Library is not available`);
+			}
+			if (!themeAvailable) {
+				log.verbose(`Skipping ${resourcePath}: sap.ui.core theme '${themeName}' is not available. ` +
+				"If you experience missing themes, check whether you have added the corresponding theme " +
+				"library to your projects dependencies and make sure that your custom themes contain " +
+				"resources for the sap.ui.core namespace.");
+			}
+		}
+
+		// Only build if library and theme are available
+		return libraryAvailable && themeAvailable;
+	};
+
+	if (availableLibraries || availableThemes) {
+		if (log.isLevelEnabled("verbose")) {
+			log.verbose("Filtering themes to be built:");
+			if (availableLibraries) {
+				log.verbose(`Available libraries: ${availableLibraries.join(", ")}`);
+			}
+			if (availableThemes) {
+				log.verbose(`Available sap.ui.core themes: ${availableThemes.join(", ")}`);
+			}
+		}
+		allResources = allResources.filter(isAvailable);
+	}
+
+	const processedResources = await themeBuilder({
+		resources: allResources,
+		fs: fsInterface(combo),
+		options: {
+			compress,
+			cssVariables: !!cssVariables
+		}
+	});
+
+	await Promise.all(processedResources.map((resource) => {
+		return workspace.write(resource);
+	}));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_bundlers_generateBundle.js.html b/v3/api/builder_lib_tasks_bundlers_generateBundle.js.html new file mode 100644 index 0000000000..72639573e4 --- /dev/null +++ b/v3/api/builder_lib_tasks_bundlers_generateBundle.js.html @@ -0,0 +1,221 @@ + + + + + + + builder/lib/tasks/bundlers/generateBundle.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/bundlers/generateBundle.js

+ + + + + + + +
+
+
import moduleBundler from "../../processors/bundlers/moduleBundler.js";
+import createModuleNameMapping from "./utils/createModuleNameMapping.js";
+import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/bundlers/generateBundle
+ */
+
+/* eslint-disable max-len */
+/**
+ * Generates a bundle based on the given bundle definition
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/ReaderCollection} parameters.dependencies Collection to read dependency files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition} parameters.options.bundleDefinition Module
+ * 			bundle definition
+ * @param {module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleOptions} [parameters.options.bundleOptions] Module
+ * 			bundle options
+ * @returns {Promise} Promise resolving with <code>undefined</code> once data has been written
+ */
+/* eslint-enable max-len */
+export default async function({
+	workspace, dependencies, taskUtil, options: {projectName, bundleDefinition, bundleOptions}
+}) {
+	let combo = new ReaderCollectionPrioritized({
+		name: `generateBundle - prioritize workspace over dependencies: ${projectName}`,
+		readers: [workspace, dependencies]
+	});
+
+	const optimize = !bundleOptions || bundleOptions.optimize !== false;
+	if (taskUtil) {
+		/* Scenarios
+			1. Optimize bundle with minification already done
+				Workspace:
+					* /resources/my/lib/Control.js 				[ui5:HasDebugVariant]
+					* /resources/my/lib/Control.js.map 			[ui5:HasDebugVariant]
+					* /resources/my/lib/Control-dbg.js 			[ui5:IsDebugVariant]
+
+				Bundler input:
+					* /resources/my/lib/Control.js
+					* /resources/my/lib/Control.js.map
+
+				=> Filter out debug resources
+
+			2. Optimize bundle with no minification
+				* /resources/my/lib/Control.js
+
+				=> No action necessary
+
+			3. Debug-bundle with minification already done
+				Workspace:
+					* /resources/my/lib/Control.js 				[ui5:HasDebugVariant]
+					* /resources/my/lib/Control.js.map 			[ui5:HasDebugVariant]
+					* /resources/my/lib/Control-dbg.js 			[ui5:IsDebugVariant]
+
+				Bundler input:
+					* /resources/my/lib/Control-dbg.js
+					* moduleNameMapping: [{"/resources/my/lib/Control-dbg.js": "my/lib/Control.js"}]
+
+				=> Filter out minified-resources (tagged as "HasDebugVariant", incl. source maps) and rename debug-files
+
+			4. Debug-bundle with no minification
+				* /resources/my/lib/Control.js
+
+				=> No action necessary
+
+			5. Bundle with external input (optimize or not), e.g. TS-project
+				Workspace:
+					* /resources/my/lib/Control.ts
+					* /resources/my/lib/Control.js
+					* /resources/my/lib/Control.js.map
+
+				Bundler input:
+					* /resources/my/lib/Control.js
+					* /resources/my/lib/Control.js.map
+		*/
+
+		// Omit -dbg files for optimize bundles and vice versa
+		const filterTag = optimize ?
+			taskUtil.STANDARD_TAGS.IsDebugVariant : taskUtil.STANDARD_TAGS.HasDebugVariant;
+		combo = taskUtil.resourceFactory.createFilterReader({
+			reader: combo,
+			callback: function(resource) {
+				return !taskUtil.getTag(resource, filterTag);
+			}
+		});
+	}
+
+	return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
+		const options = {bundleDefinition, bundleOptions};
+		if (!optimize && taskUtil) {
+			options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
+		}
+		return moduleBundler({options, resources}).then((bundles) => {
+			return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
+				if (!bundle) {
+					// Skip empty bundles
+					return;
+				}
+				if (taskUtil) {
+					taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
+					if (sourceMap) {
+						// Clear tag that might have been set by the minify task, in cases where
+						// the bundle name is identical to a source file
+						taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+					}
+				}
+				const writes = [workspace.write(bundle)];
+				if (sourceMap) {
+					writes.push(workspace.write(sourceMap));
+				}
+				return Promise.all(writes);
+			}));
+		});
+	});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_bundlers_generateComponentPreload.js.html b/v3/api/builder_lib_tasks_bundlers_generateComponentPreload.js.html new file mode 100644 index 0000000000..44cbace4c4 --- /dev/null +++ b/v3/api/builder_lib_tasks_bundlers_generateComponentPreload.js.html @@ -0,0 +1,273 @@ + + + + + + + builder/lib/tasks/bundlers/generateComponentPreload.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/bundlers/generateComponentPreload.js

+ + + + + + + +
+
+
import path from "node:path";
+import moduleBundler from "../../processors/bundlers/moduleBundler.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:bundlers:generateComponentPreload");
+import {negateFilters} from "../../lbt/resources/ResourceFilterList.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/bundlers/generateComponentPreload
+ */
+
+/**
+ * Task to for application bundling.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {string[]} [parameters.options.excludes=[]] List of modules declared as glob patterns (resource name patterns)
+ * that should be excluded.
+ * A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk,
+ * denote an arbitrary number of characters or folder names.
+ * Re-includes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later
+ * inclusion overrides an earlier exclusion, and vice versa.
+ * @param {string[]} [parameters.options.paths] Array of paths (or glob patterns) for component files
+ * @param {string[]} [parameters.options.namespaces] Array of component namespaces
+ * @param {string[]} [parameters.options.skipBundles] Names of bundles that should not be created
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({
+	workspace, taskUtil, options: {projectName, paths, namespaces, skipBundles = [], excludes = []}
+}) {
+	let nonDbgWorkspace = workspace;
+	if (taskUtil) {
+		nonDbgWorkspace = taskUtil.resourceFactory.createFilterReader({
+			reader: workspace,
+			callback: function(resource) {
+				// Remove any debug variants
+				return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
+			}
+		});
+	}
+
+	return nonDbgWorkspace.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}")
+		.then(async (resources) => {
+			let allNamespaces = [];
+			if (paths) {
+				allNamespaces = await Promise.all(paths.map(async (componentPath) => {
+					const globPath = "/resources/" + componentPath;
+					log.verbose(`Globbing for Components directories with configured path ${globPath}...`);
+					const components = await nonDbgWorkspace.byGlob(globPath);
+					return components.map((component) => {
+						const compDir = path.dirname(component.getPath()).replace(/^\/resources\//i, "");
+						log.verbose(`Found component namespace ${compDir}`);
+						return compDir;
+					});
+				}));
+			}
+			if (namespaces) {
+				allNamespaces.push(...namespaces);
+			}
+
+			allNamespaces = Array.prototype.concat.apply([], allNamespaces);
+			// As this task is often called with a single namespace, also check
+			//	for bad calls like "namespaces: [undefined]"
+			if (!allNamespaces || !allNamespaces.length || !allNamespaces[0]) {
+				throw new Error("generateComponentPreload: No component namespace(s) " +
+					`found for project: ${projectName}`);
+			}
+
+			const allFilterExcludes = negateFilters(excludes);
+			const unusedFilterExcludes = new Set(allFilterExcludes);
+
+			const bundleDefinitions = allNamespaces.map((namespace) => {
+				const bundleName = `${namespace}/Component-preload.js`;
+				if (skipBundles.includes(bundleName)) {
+					log.verbose(`Skipping generation of bundle ${bundleName}`);
+					return null;
+				}
+
+				const filters = [
+					`${namespace}/`,
+					`${namespace}/**/manifest.json`,
+					`${namespace}/changes/changes-bundle.json`,
+					`${namespace}/changes/flexibility-bundle.json`,
+					`!${namespace}/test/`
+				];
+
+				// Add configured excludes for namespace
+				allFilterExcludes.forEach((filterExclude) => {
+					// Allow all excludes (!) and limit re-includes (+) to the component namespace
+					if (filterExclude.startsWith("!") || filterExclude.startsWith(`+${namespace}/`)) {
+						filters.push(filterExclude);
+						unusedFilterExcludes.delete(filterExclude);
+					}
+				});
+
+				// Exclude other namespaces at the end of filter list to override potential re-includes
+				// from "excludes" config
+				allNamespaces.forEach((ns) => {
+					if (ns !== namespace && ns.startsWith(`${namespace}/`)) {
+						filters.push(`!${ns}/`);
+						// Explicitly exclude manifest.json files of subcomponents since the general exclude above this
+						// comment only applies to the configured default file types, which do not include ".json"
+						filters.push(`!${ns}/**/manifest.json`);
+					}
+				});
+
+				return {
+					name: bundleName,
+					defaultFileTypes: [
+						".js",
+						".control.xml",
+						".fragment.html",
+						".fragment.json",
+						".fragment.xml",
+						".view.html",
+						".view.json",
+						".view.xml",
+						".properties"
+					],
+					sections: [
+						{
+							mode: "preload",
+							filters: filters,
+							resolve: false,
+							resolveConditional: false,
+							renderer: false
+						}
+					]
+				};
+			});
+
+			if (unusedFilterExcludes.size > 0) {
+				unusedFilterExcludes.forEach((filterExclude) => {
+					log.warn(
+						`Configured preload exclude contains invalid re-include: !${filterExclude.substr(1)}. ` +
+						`Re-includes must start with a component namespace (${allNamespaces.join(" or ")})`
+					);
+				});
+			}
+
+			return Promise.all(bundleDefinitions.filter(Boolean).map((bundleDefinition) => {
+				log.verbose(`Generating ${bundleDefinition.name}...`);
+				return moduleBundler({
+					resources,
+					options: {
+						bundleDefinition,
+						bundleOptions: {
+							ignoreMissingModules: true,
+							optimize: true
+						}
+					}
+				});
+			}));
+		})
+		.then((results) => {
+			const bundles = Array.prototype.concat.apply([], results);
+			return Promise.all(bundles.map(({bundle, sourceMap}) => {
+				if (taskUtil) {
+					taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
+					// Clear tag that might have been set by the minify task, in cases where
+					// the bundle name is identical to a source file
+					taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+				}
+				return Promise.all([
+					workspace.write(bundle),
+					workspace.write(sourceMap)
+				]);
+			}));
+		});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_bundlers_generateFlexChangesBundle.js.html b/v3/api/builder_lib_tasks_bundlers_generateFlexChangesBundle.js.html new file mode 100644 index 0000000000..362c94c119 --- /dev/null +++ b/v3/api/builder_lib_tasks_bundlers_generateFlexChangesBundle.js.html @@ -0,0 +1,208 @@ + + + + + + + builder/lib/tasks/bundlers/generateFlexChangesBundle.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/bundlers/generateFlexChangesBundle.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:bundlers:generateFlexChangesBundle");
+import flexChangesBundler from "../../processors/bundlers/flexChangesBundler.js";
+import semver from "semver";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/bundlers/generateFlexChangesBundle
+ */
+
+/* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
+/**
+ * Task to create changesBundle.json file containing all changes stored in the /changes folder for easier consumption
+ * at runtime.
+ * If a change bundle is created, "sap.ui.fl" is added as a dependency to the manifest.json if not already present -
+ * if the dependency is already listed but lazy-loaded, lazy loading is disabled.
+ * If minUI5Version >= 1.73 flexibility-bundle.json will be create.
+ * If there are control variants and minUI5Version < 1.73 build will break and throw an error.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} [parameters.options] Options
+ * @param {string} [parameters.options.projectNamespace] Project Namespace
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, taskUtil, options = {}}) {
+	// Backward compatibility: "namespace" option got renamed to "projectNamespace"
+	const namespace = options.projectNamespace || options.namespace;
+
+	// Use the given namespace if available, otherwise use no namespace
+	// (e.g. in case no manifest.json is present)
+	let pathPrefix = "";
+	if (namespace) {
+		pathPrefix = `/resources/${namespace}`;
+	}
+
+	function updateJson(data) {
+		// ensure the existence of the libs section in the dependencies
+		data["sap.ui5"] = data["sap.ui5"] || {};
+		data["sap.ui5"].dependencies = data["sap.ui5"].dependencies || {};
+		const mLibs = data["sap.ui5"].dependencies.libs = data["sap.ui5"].dependencies.libs || {};
+
+		if (mLibs["sap.ui.fl"]) {
+			log.verbose("sap.ui.fl found in manifest.json");
+			if (mLibs["sap.ui.fl"].lazy) {
+				log.verbose("sap.ui.fl 'lazy' attribute found in manifest.json, setting it to false...");
+				mLibs["sap.ui.fl"].lazy = false;
+			}
+		} else {
+			log.verbose("sap.ui.fl not found in manifest.json, inserting it...");
+			mLibs["sap.ui.fl"] = {};
+		}
+	}
+
+	async function updateFLdependency() {
+		const manifestResource = await workspace.byPath(`${pathPrefix}/manifest.json`);
+		const manifestContent = JSON.parse(await manifestResource.getString());
+
+		updateJson(manifestContent);
+		manifestResource.setString(JSON.stringify(manifestContent, null, "\t"));
+
+		await workspace.write(manifestResource);
+	}
+
+	async function readManifestMinUI5Version() {
+		const manifestResource = await workspace.byPath(`${pathPrefix}/manifest.json`);
+		const manifestContent = JSON.parse(await manifestResource.getString());
+
+		manifestContent["sap.ui5"] = manifestContent["sap.ui5"] || {};
+		manifestContent["sap.ui5"].dependencies = manifestContent["sap.ui5"].dependencies || {};
+		return manifestContent["sap.ui5"].dependencies.minUI5Version =
+			manifestContent["sap.ui5"].dependencies.minUI5Version || "";
+	}
+
+	log.verbose("Collecting flexibility changes");
+	const allResources = await workspace.byGlob(
+		`${pathPrefix}/changes/*.{change,variant,ctrl_variant,ctrl_variant_change,ctrl_variant_management_change}`);
+	if (allResources.length > 0) {
+		const version = semver.coerce(await readManifestMinUI5Version());
+		let hasFlexBundleVersion = false;
+		if (semver.compare(version, "1.73.0") >= 0) {
+			hasFlexBundleVersion = true;
+		}
+		const processedResources = await flexChangesBundler({
+			resources: allResources,
+			options: {
+				pathPrefix,
+				hasFlexBundleVersion
+			}
+		});
+		await Promise.all(processedResources.map((resource) => {
+			log.verbose("Writing flexibility changes bundle");
+			return workspace.write(resource);
+		}));
+		// Add the sap.ui.fl dependency if a bundle has been created
+		if (processedResources.length > 0) {
+			await updateFLdependency();
+		}
+
+		// Do not write bundled source files to build result
+		if (taskUtil) {
+			allResources.forEach((resource) => {
+				taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+			});
+		}
+	}
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_bundlers_generateLibraryPreload.js.html b/v3/api/builder_lib_tasks_bundlers_generateLibraryPreload.js.html new file mode 100644 index 0000000000..803b69583a --- /dev/null +++ b/v3/api/builder_lib_tasks_bundlers_generateLibraryPreload.js.html @@ -0,0 +1,549 @@ + + + + + + + builder/lib/tasks/bundlers/generateLibraryPreload.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/bundlers/generateLibraryPreload.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:bundlers:generateLibraryPreload");
+import moduleBundler from "../../processors/bundlers/moduleBundler.js";
+import {negateFilters} from "../../lbt/resources/ResourceFilterList.js";
+import createModuleNameMapping from "./utils/createModuleNameMapping.js";
+
+function getDefaultLibraryPreloadFilters(namespace, excludes) {
+	const filters = [
+		`${namespace}/`,
+		`${namespace}/**/manifest.json`,
+		`!${namespace}/**/*-preload.js`, // exclude all bundles
+		`!${namespace}/designtime/`,
+		`!${namespace}/**/*.designtime.js`,
+		`!${namespace}/**/*.support.js`
+	];
+
+	if (Array.isArray(excludes)) {
+		const allFilterExcludes = negateFilters(excludes);
+		// Add configured excludes at the end of filter list
+		allFilterExcludes.forEach((filterExclude) => {
+			// Allow all excludes (!) and limit re-includes (+) to the library namespace
+			if (filterExclude.startsWith("!") || filterExclude.startsWith(`+${namespace}/`)) {
+				filters.push(filterExclude);
+			} else {
+				log.warn(`Configured preload exclude contains invalid re-include: !${filterExclude.substr(1)}. ` +
+				`Re-includes must start with the library's namespace ${namespace}`);
+			}
+		});
+	}
+
+	return filters;
+}
+
+function getBundleDefinition(namespace, excludes) {
+	// TODO: move to config of actual core project
+	if (namespace === "sap/ui/core") {
+		return {
+			name: `${namespace}/library-preload.js`,
+			sections: [
+				{
+					// exclude the content of sap-ui-core by declaring it as 'provided'
+					mode: "provided",
+					filters: [
+						"ui5loader-autoconfig.js",
+						"sap/ui/core/Core.js"
+					],
+					resolve: true
+				},
+				{
+					mode: "preload",
+					filters: [
+						// Note: Don't pass configured preload excludes for sap.ui.core
+						// as they are already hardcoded below.
+						// In future the sap/ui/core/library-preload should be configured
+						// as a custom bundle in the ui5.yaml.
+						...getDefaultLibraryPreloadFilters(namespace),
+
+						`!${namespace}/cldr/`,
+						"*.js",
+						"sap/base/",
+						"sap/ui/base/",
+						"sap/ui/dom/",
+						"sap/ui/events/",
+						"sap/ui/model/",
+						"sap/ui/security/",
+						"sap/ui/util/",
+						"sap/ui/Global.js",
+
+						// include only thirdparty that is very likely to be used
+						"sap/ui/thirdparty/crossroads.js",
+						"sap/ui/thirdparty/caja-html-sanitizer.js",
+						"sap/ui/thirdparty/hasher.js",
+						"sap/ui/thirdparty/signals.js",
+						"sap/ui/thirdparty/jquery-mobile-custom.js",
+						"sap/ui/thirdparty/jqueryui/jquery-ui-core.js",
+						"sap/ui/thirdparty/jqueryui/jquery-ui-position.js",
+
+						// other excludes (not required for productive scenarios)
+						"!sap-ui-*.js",
+						"!sap/ui/core/support/",
+						"!sap/ui/core/plugin/DeclarativeSupport.js",
+						"!sap/ui/core/plugin/LessSupport.js"
+
+					],
+					resolve: false,
+					resolveConditional: false,
+					renderer: true
+				}
+			]
+		};
+	}
+	return {
+		name: `${namespace}/library-preload.js`,
+		sections: [
+			{
+				mode: "preload",
+				filters: getDefaultLibraryPreloadFilters(namespace, excludes),
+				resolve: false,
+				resolveConditional: false,
+				renderer: true
+			}
+		]
+	};
+}
+
+function getDesigntimeBundleDefinition(namespace) {
+	return {
+		name: `${namespace}/designtime/library-preload.designtime.js`,
+		sections: [
+			{
+				mode: "preload",
+				filters: [
+					`${namespace}/**/*.designtime.js`,
+					`${namespace}/designtime/`,
+					`!${namespace}/**/*-preload.designtime.js`,
+					`!${namespace}/designtime/**/*.properties`,
+					`!${namespace}/designtime/**/*.svg`,
+					`!${namespace}/designtime/**/*.xml`
+				],
+				resolve: false,
+				resolveConditional: false,
+				renderer: false
+			}
+		]
+	};
+}
+
+function getSupportFilesBundleDefinition(namespace) {
+	return {
+		name: `${namespace}/library-preload.support.js`,
+		sections: [
+			{
+				mode: "preload",
+				filters: [
+					`${namespace}/**/*.support.js`,
+					`!${namespace}/**/*-preload.support.js`
+				],
+				resolve: false,
+				resolveConditional: false,
+				renderer: false
+			}
+		]
+	};
+}
+
+function getModuleBundlerOptions(config) {
+	const moduleBundlerOptions = {};
+
+	// required in sap-ui-core-nojQuery.js and sap-ui-core-nojQuery-dbg.js
+	const providedSection = {
+		mode: "provided",
+		filters: [
+			"jquery-ui-core.js",
+			"jquery-ui-datepicker.js",
+			"jquery-ui-position.js",
+			"sap/ui/thirdparty/jquery.js",
+			"sap/ui/thirdparty/jquery/*",
+			"sap/ui/thirdparty/jqueryui/*"
+		]
+	};
+
+	moduleBundlerOptions.bundleOptions = {
+		optimize: config.preload,
+		decorateBootstrapModule: config.preload,
+		addTryCatchRestartWrapper: config.preload,
+		usePredefineCalls: config.preload
+	};
+
+	moduleBundlerOptions.bundleDefinition = getSapUiCoreBunDef(config.name, config.filters, config.preload);
+
+	if (config.provided) {
+		moduleBundlerOptions.bundleDefinition.sections.unshift(providedSection);
+	}
+
+	if (config.moduleNameMapping) {
+		moduleBundlerOptions.moduleNameMapping = config.moduleNameMapping;
+	}
+
+	return moduleBundlerOptions;
+}
+
+function getSapUiCoreBunDef(name, filters, preload) {
+	const bundleDefinition = {
+		name,
+		sections: []
+	};
+
+	// add raw section
+	bundleDefinition.sections.push({
+		// include all 'raw' modules that are needed for the UI5 loader
+		mode: "raw",
+		filters,
+		resolve: true, // dependencies for raw modules are taken from shims in .library files
+		sort: true, // topological sort on raw modules is mandatory
+		declareModules: false
+	});
+
+	if (preload) {
+		// add preload section
+		bundleDefinition.sections.push({
+			mode: "preload",
+			filters: [
+				"sap/ui/core/Core.js"
+			],
+			resolve: true
+		});
+	}
+
+	// add require section
+	bundleDefinition.sections.push({
+		mode: "require",
+		filters: [
+			"sap/ui/core/Core.js"
+		]
+	});
+
+	return bundleDefinition;
+}
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/bundlers/generateLibraryPreload
+ */
+
+/**
+ * Task for library bundling.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/project/build/helpers/TaskUtil} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {string[]} [parameters.options.skipBundles] Names of bundles that should not be created
+ * @param {string[]} [parameters.options.excludes=[]] List of modules declared as glob patterns (resource name patterns)
+ * that should be excluded from the library-preload.js bundle.
+ * A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk,
+ * denote an arbitrary number of characters or folder names.
+ * Re-includes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later
+ * inclusion overrides an earlier exclusion, and vice versa.
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, taskUtil, options: {skipBundles = [], excludes = [], projectName}}) {
+	let nonDbgWorkspace = workspace;
+	if (taskUtil) {
+		nonDbgWorkspace = taskUtil.resourceFactory.createFilterReader({
+			reader: workspace,
+			callback: function(resource) {
+				// Remove any debug variants
+				return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
+			}
+		});
+	}
+
+	const execModuleBundlerIfNeeded = ({options, resources}) => {
+		if (skipBundles.includes(options.bundleDefinition.name)) {
+			log.verbose(`Skipping generation of bundle ${options.bundleDefinition.name}`);
+			return null;
+		}
+		return moduleBundler({options, resources});
+	};
+
+	return nonDbgWorkspace.byGlob("/**/*.{js,json,xml,html,properties,library,js.map}").then(async (resources) => {
+		// Find all libraries and create a library-preload.js bundle
+
+		let p = Promise.resolve();
+
+		// Create core bundles for older versions (<1.97.0) which don't define bundle configuration in the ui5.yaml
+		// See: https://github.com/SAP/openui5/commit/ff127fd2d009162ea43ad312dec99d759ebc23a0
+		if (projectName === "sap.ui.core") {
+			// Instead of checking the sap.ui.core library version, the specVersion is checked against all versions
+			// that have been defined for sap.ui.core before the bundle configuration has been introduced.
+			// This is mainly to have an easier check without version parsing or using semver.
+			// If no project/specVersion is available, the bundles should also be created to not break potential
+			// existing use cases without a properly formed/formatted project tree.
+			if (!taskUtil || taskUtil.getProject().getSpecVersion().lte("2.0")) {
+				const isEvo = resources.find((resource) => {
+					return resource.getPath() === "/resources/ui5loader.js";
+				});
+
+				let unoptimizedModuleNameMapping;
+				let unoptimizedResources = resources;
+				if (taskUtil) {
+					const unoptimizedWorkspace = taskUtil.resourceFactory.createFilterReader({
+						reader: workspace,
+						callback: function(resource) {
+							// Remove any non-debug variants
+							return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
+						}
+					});
+					unoptimizedResources =
+						await unoptimizedWorkspace.byGlob("/**/*.{js,json,xml,html,properties,library,js.map}");
+
+					unoptimizedModuleNameMapping = createModuleNameMapping({
+						resources: unoptimizedResources,
+						taskUtil
+					});
+				}
+
+				let filters;
+				if (isEvo) {
+					filters = ["ui5loader-autoconfig.js"];
+				} else {
+					filters = ["jquery.sap.global.js"];
+				}
+				p = Promise.all([
+					execModuleBundlerIfNeeded({
+						options: getModuleBundlerOptions({name: "sap-ui-core.js", filters, preload: true}),
+						resources
+					}),
+					execModuleBundlerIfNeeded({
+						options: getModuleBundlerOptions({
+							name: "sap-ui-core-dbg.js", filters, preload: false,
+							moduleNameMapping: unoptimizedModuleNameMapping
+						}),
+						resources: unoptimizedResources
+					}),
+					execModuleBundlerIfNeeded({
+						options: getModuleBundlerOptions({
+							name: "sap-ui-core-nojQuery.js", filters, preload: true, provided: true
+						}),
+						resources
+					}),
+					execModuleBundlerIfNeeded({
+						options: getModuleBundlerOptions({
+							name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true,
+							moduleNameMapping: unoptimizedModuleNameMapping
+						}),
+						resources: unoptimizedResources
+					}),
+				]).then((results) => {
+					const bundles = Array.prototype.concat.apply([], results).filter(Boolean);
+					return Promise.all(bundles.map(({bundle, sourceMap}) => {
+						if (taskUtil) {
+							taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
+							if (sourceMap) {
+								// Clear tag that might have been set by the minify task, in cases where
+								// the bundle name is identical to a source file
+								taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+							}
+						}
+						const writes = [workspace.write(bundle)];
+						if (sourceMap) {
+							writes.push(workspace.write(sourceMap));
+						}
+						return Promise.all(writes);
+					}));
+				});
+			}
+		}
+
+		return p.then(() => {
+			return workspace.byGlob("/resources/**/.library").then((libraryIndicatorResources) => {
+				if (libraryIndicatorResources.length > 0) {
+					return libraryIndicatorResources;
+				} else {
+					// Fallback to "library.js" as library indicator
+					log.verbose(
+						`Could not find a ".library" file for project ${projectName}, ` +
+						`falling back to "library.js".`);
+					return workspace.byGlob("/resources/**/library.js");
+				}
+			}).then((libraryIndicatorResources) => {
+				if (libraryIndicatorResources.length < 1) {
+					// No library found - nothing to do
+					log.verbose(
+						`Could not find a ".library" or "library.js" file for project ${projectName}. ` +
+						`Skipping library preload bundling.`);
+					return;
+				}
+
+				return Promise.all(libraryIndicatorResources.map(async (libraryIndicatorResource) => {
+					// Determine library namespace from library indicator file path
+					// ending with either ".library" or "library.js" (see fallback logic above)
+					// e.g. /resources/sap/foo/.library => sap/foo
+					//      /resources/sap/bar/library.js => sap/bar
+					const libraryNamespacePattern = /^\/resources\/(.*)\/(?:\.library|library\.js)$/;
+					const libraryIndicatorPath = libraryIndicatorResource.getPath();
+					const libraryNamespaceMatch = libraryIndicatorPath.match(libraryNamespacePattern);
+					if (libraryNamespaceMatch && libraryNamespaceMatch[1]) {
+						const libraryNamespace = libraryNamespaceMatch[1];
+						const results = await Promise.all([
+							execModuleBundlerIfNeeded({
+								options: {
+									bundleDefinition: getBundleDefinition(libraryNamespace, excludes),
+									bundleOptions: {
+										optimize: true,
+										usePredefineCalls: true,
+										ignoreMissingModules: true
+									}
+								},
+								resources
+							}),
+							execModuleBundlerIfNeeded({
+								options: {
+									bundleDefinition: getDesigntimeBundleDefinition(libraryNamespace),
+									bundleOptions: {
+										optimize: true,
+										usePredefineCalls: true,
+										ignoreMissingModules: true,
+										skipIfEmpty: true
+									}
+								},
+								resources
+							}),
+							execModuleBundlerIfNeeded({
+								options: {
+									bundleDefinition: getSupportFilesBundleDefinition(libraryNamespace),
+									bundleOptions: {
+										optimize: false,
+										usePredefineCalls: true,
+										ignoreMissingModules: true,
+										skipIfEmpty: true
+									}
+									// Note: Although the bundle uses optimize=false, there is
+									// no moduleNameMapping needed, as support files are excluded from minification.
+								},
+								resources
+							})
+						]);
+						const bundles = Array.prototype.concat.apply([], results).filter(Boolean);
+						return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
+							if (bundle) {
+								if (taskUtil) {
+									taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
+									if (sourceMap) {
+										// Clear tag that might have been set by the minify task, in cases where
+										// the bundle name is identical to a source file
+										taskUtil.clearTag(sourceMap,
+											taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+									}
+								}
+								const writes = [workspace.write(bundle)];
+								if (sourceMap) {
+									writes.push(workspace.write(sourceMap));
+								}
+								return Promise.all(writes);
+							}
+						}));
+					} else {
+						log.verbose(
+							`Could not determine library namespace from file "${libraryIndicatorPath}" ` +
+							`for project ${projectName}. Skipping library preload bundling.`);
+						return Promise.resolve();
+					}
+				}));
+			});
+		});
+	});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_bundlers_generateStandaloneAppBundle.js.html b/v3/api/builder_lib_tasks_bundlers_generateStandaloneAppBundle.js.html new file mode 100644 index 0000000000..717cd95f2d --- /dev/null +++ b/v3/api/builder_lib_tasks_bundlers_generateStandaloneAppBundle.js.html @@ -0,0 +1,281 @@ + + + + + + + builder/lib/tasks/bundlers/generateStandaloneAppBundle.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/bundlers/generateStandaloneAppBundle.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:bundlers:generateStandaloneAppBundle");
+import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+import moduleBundler from "../../processors/bundlers/moduleBundler.js";
+import createModuleNameMapping from "./utils/createModuleNameMapping.js";
+
+function getBundleDefinition(config) {
+	const bundleDefinition = {
+		name: config.name,
+		defaultFileTypes: [
+			".js",
+			".control.xml",
+			".fragment.html",
+			".fragment.json",
+			".fragment.xml",
+			".view.html",
+			".view.json",
+			".view.xml",
+			".properties"
+		],
+		sections: []
+	};
+
+	// add raw section
+	bundleDefinition.sections.push({
+		// include all 'raw' modules that are needed for the UI5 loader
+		mode: "raw",
+		filters: config.filters,
+		resolve: true, // dependencies for raw modules are taken from shims in .library files
+		sort: true, // topological sort on raw modules is mandatory
+		declareModules: false
+	});
+
+	// preload section is only relevant for sap-ui-custom.js
+	if (config.preloadSection) {
+		bundleDefinition.sections.push({
+			mode: "preload",
+			filters: [
+				`${config.namespace || ""}/`,
+				`${config.namespace || ""}/**/manifest.json`,
+				`${config.namespace || ""}/changes/changes-bundle.json`,
+				`${config.namespace || ""}/changes/flexibility-bundle.json`,
+				`!${config.namespace || ""}/test/`,
+				"sap/ui/core/Core.js"
+			],
+			resolve: true,
+			resolveConditional: true,
+			renderer: true
+		});
+	}
+
+	bundleDefinition.sections.push({
+		mode: "require",
+		filters: [
+			"sap/ui/core/Core.js"
+		]
+	});
+
+	return bundleDefinition;
+}
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/bundlers/generateStandaloneAppBundle
+ */
+
+/* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
+/**
+ * Task for bundling standalone applications.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {string} [parameters.options.projectNamespace] Project namespace
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, dependencies, taskUtil, options}) {
+	const {projectName} = options;
+	// Backward compatibility: "namespace" option got renamed to "projectNamespace"
+	const namespace = options.projectNamespace || options.namespace;
+
+	if (!namespace) {
+		log.warn(`Namespace of project ${projectName} is not known. Self contained bundling is currently ` +
+			`unable to generate complete bundles for such projects.`);
+	}
+
+	const combo = new ReaderCollectionPrioritized({
+		name: `generateStandaloneAppBundle - prioritize workspace over dependencies: ${projectName}`,
+		readers: [workspace, dependencies]
+	});
+
+	let resourceReader = combo;
+	if (taskUtil) {
+		// Omit -dbg files
+		resourceReader = await taskUtil.resourceFactory.createFilterReader({
+			reader: combo,
+			callback: function(resource) {
+				return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
+			}
+		});
+	}
+	const resources = await resourceReader.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
+
+	const isEvo = resources.find((resource) => {
+		return resource.getPath() === "/resources/ui5loader.js";
+	});
+	let filters;
+	if (isEvo) {
+		filters = ["ui5loader-autoconfig.js"];
+	} else {
+		filters = ["jquery.sap.global.js"];
+	}
+
+	let unoptimizedModuleNameMapping;
+	let unoptimizedResources = resources;
+	if (taskUtil) {
+		const unoptimizedResourceReader = await taskUtil.resourceFactory.createFilterReader({
+			reader: combo,
+			callback: function(resource) {
+				// Remove any non-debug variants
+				return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
+			}
+		});
+
+		unoptimizedResources = await unoptimizedResourceReader
+			.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
+
+		unoptimizedModuleNameMapping = createModuleNameMapping({
+			resources: unoptimizedResources,
+			taskUtil
+		});
+	}
+
+	await Promise.all([
+		moduleBundler({
+			resources,
+			options: {
+				bundleDefinition: getBundleDefinition({
+					name: "sap-ui-custom.js",
+					filters,
+					namespace,
+					preloadSection: true
+				})
+			}
+		}),
+		moduleBundler({
+			resources: unoptimizedResources,
+			options: {
+				bundleDefinition: getBundleDefinition({
+					name: "sap-ui-custom-dbg.js",
+					filters,
+					namespace
+				}),
+				bundleOptions: {
+					optimize: false
+				},
+				moduleNameMapping: unoptimizedModuleNameMapping
+			}
+		})
+	]).then((results) => {
+		const bundles = Array.prototype.concat.apply([], results);
+		return Promise.all(bundles.map(({bundle, sourceMap}) => {
+			if (taskUtil) {
+				taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
+				if (sourceMap) {
+					// Clear tag that might have been set by the minify task, in cases where
+					// the bundle name is identical to a source file
+					taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+				}
+			}
+			const writes = [workspace.write(bundle)];
+			if (sourceMap) {
+				writes.push(workspace.write(sourceMap));
+			}
+			return Promise.all(writes);
+		}));
+	});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_escapeNonAsciiCharacters.js.html b/v3/api/builder_lib_tasks_escapeNonAsciiCharacters.js.html new file mode 100644 index 0000000000..f312f816cb --- /dev/null +++ b/v3/api/builder_lib_tasks_escapeNonAsciiCharacters.js.html @@ -0,0 +1,133 @@ + + + + + + + builder/lib/tasks/escapeNonAsciiCharacters.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/escapeNonAsciiCharacters.js

+ + + + + + + +
+
+
import nonAsciiEscaper from "../processors/nonAsciiEscaper.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/escapeNonAsciiCharacters
+ */
+
+/**
+ * Task to escape non ascii characters in properties files resources.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pattern Glob pattern to locate the files to be processed
+ * @param {string} parameters.options.encoding source file encoding either "UTF-8" or "ISO-8859-1"
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, options: {pattern, encoding}}) {
+	if (!encoding) {
+		throw new Error("[escapeNonAsciiCharacters] Mandatory option 'encoding' not provided");
+	}
+
+	const allResources = await workspace.byGlob(pattern);
+
+	const processedResources = await nonAsciiEscaper({
+		resources: allResources,
+		options: {
+			encoding: nonAsciiEscaper.getEncodingFromAlias(encoding)
+		}
+	});
+
+	await Promise.all(processedResources.map((resource) => workspace.write(resource)));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_generateCachebusterInfo.js.html b/v3/api/builder_lib_tasks_generateCachebusterInfo.js.html new file mode 100644 index 0000000000..330bc1c0e2 --- /dev/null +++ b/v3/api/builder_lib_tasks_generateCachebusterInfo.js.html @@ -0,0 +1,176 @@ + + + + + + + builder/lib/tasks/generateCachebusterInfo.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/generateCachebusterInfo.js

+ + + + + + + +
+
+
import crypto from "node:crypto";
+import {createResource} from "@ui5/fs/resourceFactory";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:generateCachebusterInfo");
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/generateCachebusterInfo
+ */
+
+async function signByTime(resource) {
+	return resource.getStatInfo().mtime.getTime();
+}
+
+async function signByHash(resource) {
+	const hasher = crypto.createHash("sha1");
+	const buffer = await resource.getBuffer();
+
+	hasher.update(buffer.toString("binary"));
+	return hasher.digest("hex");
+}
+
+function getSigner(type) {
+	type = type || "time";
+
+	switch (type) {
+	case "time":
+		return signByTime;
+	case "hash":
+		return signByHash;
+
+	default:
+		throw new Error(`Invalid signature type: '${type}'. Valid ones are: 'time' or 'hash'`);
+	}
+}
+
+/* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
+/**
+ * Task to generate the application cachebuster info file.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectNamespace Namespace of the application
+ * @param {string} [parameters.options.signatureType='time'] Type of signature to be used ('time' or 'hash')
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default function({workspace, options}) {
+	const {signatureType} = options;
+	// Backward compatibility: "namespace" option got renamed to "projectNamespace"
+	const namespace = options.projectNamespace || options.namespace;
+
+	const basePath = `/resources/${namespace}/`;
+	return workspace.byGlob(`/resources/${namespace}/**/*`)
+		.then(async (resources) => {
+			const cachebusterInfo = Object.create(null);
+			const signer = getSigner(signatureType);
+
+			await Promise.all(resources.map(async (resource) => {
+				let resourcePath = resource.getPath();
+				if (!resourcePath.startsWith(basePath)) {
+					log.verbose(
+						`Ignoring resource with path ${resourcePath} since it is not based on path ${basePath}`);
+					return;
+				}
+				// Remove base path. Absolute paths are not allowed in cachebuster info
+				resourcePath = resourcePath.replace(basePath, "");
+				cachebusterInfo[resourcePath] = await signer(resource);
+			}));
+			const cachebusterInfoResource = createResource({
+				path: `/resources/${namespace}/sap-ui-cachebuster-info.json`,
+				string: JSON.stringify(cachebusterInfo, null, 2)
+			});
+			return workspace.write(cachebusterInfoResource);
+		});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_generateLibraryManifest.js.html b/v3/api/builder_lib_tasks_generateLibraryManifest.js.html new file mode 100644 index 0000000000..dcb07496c9 --- /dev/null +++ b/v3/api/builder_lib_tasks_generateLibraryManifest.js.html @@ -0,0 +1,169 @@ + + + + + + + builder/lib/tasks/generateLibraryManifest.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/generateLibraryManifest.js

+ + + + + + + +
+
+

+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:generateLibraryManifest");
+import manifestCreator from "../processors/manifestCreator.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/generateLibraryManifest
+ */
+
+/**
+ * Task for creating a library manifest.json from its .library file.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default function({workspace, taskUtil, options: {projectName}}) {
+	// Note:
+	// *.library files are needed to identify libraries
+	// *.json files are needed to avoid overwriting them
+	// *.js files are needed to identify nested components
+	// *.less, *.css, *.theming and *.theme files are needed to identify supported themes
+	// *.properties to identify existence of i18n bundles (e.g. messagebundle.properties)
+	return workspace.byGlob("/resources/**/*.{js,json,library,less,css,theming,theme,properties}").then((resources) => {
+		// Find all libraries and create a manifest.json file
+		return workspace.byGlob("/resources/**/.library").then((libraryIndicatorResources) => {
+			if (libraryIndicatorResources.length < 1) {
+				// No library found - nothing to do
+				log.verbose(`Could not find a ".library" file for project ${projectName}. ` +
+					`Skipping library manifest generation.`);
+				return;
+			}
+
+			return Promise.all(libraryIndicatorResources.map((libraryIndicatorResource) => {
+				// Determine library namespace from library indicator file path
+				// ending with ".library"
+				// e.g. /resources/sap/foo/.library => sap/foo
+				const libraryNamespacePattern = /^\/resources\/(.*)\/\.library$/;
+				const libraryIndicatorPath = libraryIndicatorResource.getPath();
+				const libraryNamespaceMatch = libraryIndicatorPath.match(libraryNamespacePattern);
+				if (libraryNamespaceMatch && libraryNamespaceMatch[1]) {
+					const libraryNamespace = libraryNamespaceMatch[1];
+					return manifestCreator({
+						libraryResource: libraryIndicatorResource,
+						namespace: libraryNamespace,
+						resources,
+						getProjectVersion: (projectName) => {
+							return taskUtil?.getProject(projectName)?.getVersion();
+						},
+						options: {
+						}
+					}).then((manifest) => {
+						if (manifest) {
+							return workspace.write(manifest);
+						}
+					});
+				} else {
+					log.verbose(`Could not determine library namespace from file "${libraryIndicatorPath}" ` +
+						`for project ${projectName}. Skipping library manifest generation.`);
+					return Promise.resolve();
+				}
+			}));
+		});
+	});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_generateResourcesJson.js.html b/v3/api/builder_lib_tasks_generateResourcesJson.js.html new file mode 100644 index 0000000000..7ce5bff04c --- /dev/null +++ b/v3/api/builder_lib_tasks_generateResourcesJson.js.html @@ -0,0 +1,230 @@ + + + + + + + builder/lib/tasks/generateResourcesJson.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/generateResourcesJson.js

+ + + + + + + +
+
+

+import resourceListCreator from "../processors/resourceListCreator.js";
+
+const DEFAULT_EXCLUDES = [
+	/*
+	 * exclude mac metadata files
+	 */
+	"!**/.DS_Store",
+	/*
+	 * sap-ui-version.json is not part of the resources
+	 */
+	"!/resources/sap-ui-version.json"
+];
+
+function getCreatorOptions(projectName) {
+	const creatorOptions = {};
+	// TODO: Move configuration into ui5.yaml
+	if ( projectName === "sap.ui.core" ) {
+		Object.assign(creatorOptions, {
+			externalResources: {
+				"sap/ui/core": [
+					"*",
+					"sap/base/",
+					"sap/ui/"
+				]
+			}
+		});
+	} else if ( projectName === "sap.ui.integration" ) {
+		Object.assign(creatorOptions, {
+			externalResources: {
+				"sap/ui/integration": [
+					"sap-ui-integration*.js",
+				]
+			}
+		});
+	}
+	return creatorOptions;
+}
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/generateResourcesJson
+ */
+
+/**
+ * Task for creating a resources.json file, describing all productive build resources.
+ *
+ * <p>
+ * The detailed structure can be found in the documentation:
+ * {@link https://sdk.openui5.org/topic/adcbcf8b50924556ab3f321fcd9353ea}
+ * </p>
+ *
+ * <p>
+ * Not supported in combination with task {@link @ui5/builder/tasks/bundlers/generateStandaloneAppBundle}.
+ * Therefore it is also not supported in combination with self-contained build.
+ * </p>
+ *
+ * @example <caption>sample resources.json</caption>
+ * const resourcesJson = {
+ * 	"_version": "1.1.0",
+ * 	"resources": [
+ * 		{
+ * 			"name": "Component-preload.js",
+ * 			"module": "application/mine/Component-preload.js",
+ * 			"size": 3746,
+ * 			"merged": true,
+ * 			"included": [
+ * 				"application/mine/Component.js",
+ * 				"application/mine/changes/coding/MyExtension.js",
+ * 				"application/mine/changes/flexibility-bundle.json",
+ * 				"application/mine/changes/fragments/MyFragment.fragment.xml",
+ * 				"application/mine/manifest.json"
+ * 			]
+ * 		},
+ * 		{
+ * 			"name": "resources.json",
+ * 			"size": 1870
+ * 		},
+ * 		{
+ * 			"name": "rules/Button-dbg.support.js",
+ * 			"module": "application/mine/rules/Button.support.js",
+ * 			"size": 211,
+ * 			"format": "raw",
+ * 			"isDebug": true,
+ * 			"required": [
+ * 				"application/mine/library.js",
+ * 				"sap/ui/core/Control.js"
+ * 			],
+ * 			"condRequired": [
+ * 				"application/mine/changeHandler/SplitButton.js",
+ * 				"sap/ui/core/format/DateFormat.js"
+ * 			],
+ * 			"dynRequired": true,
+ * 			"support": true
+ * 		}
+ * 	]
+ * };
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, dependencies, taskUtil, options: {projectName}}) {
+	let resources = await workspace.byGlob(["/resources/**/*"].concat(DEFAULT_EXCLUDES));
+	let dependencyResources =
+			await dependencies.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
+
+	if (taskUtil) {
+		// Filter out resources that will be omitted from the build results
+		resources = resources.filter((resource) => {
+			return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+		});
+		dependencyResources = dependencyResources.filter((resource) => {
+			return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+		});
+	}
+
+	const resourceLists = await resourceListCreator({
+		resources,
+		dependencyResources,
+		options: getCreatorOptions(projectName),
+	});
+	await Promise.all(
+		resourceLists.map((resourceList) => workspace.write(resourceList))
+	);
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_generateThemeDesignerResources.js.html b/v3/api/builder_lib_tasks_generateThemeDesignerResources.js.html new file mode 100644 index 0000000000..dc8993e191 --- /dev/null +++ b/v3/api/builder_lib_tasks_generateThemeDesignerResources.js.html @@ -0,0 +1,388 @@ + + + + + + + builder/lib/tasks/generateThemeDesignerResources.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/generateThemeDesignerResources.js

+ + + + + + + +
+
+
import posixPath from "node:path/posix";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:generateThemeDesignerResources");
+import libraryLessGenerator from "../processors/libraryLessGenerator.js";
+import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+import Resource from "@ui5/fs/Resource";
+import fsInterface from "@ui5/fs/fsInterface";
+
+/**
+ * Returns a relative path from the given themeFolder to the root namespace.
+ *
+ * When combining the given themeFolder with the returned relative path it
+ * resolves to "/resources/". However the "/resources/" part is not important
+ * here as it doesn't exist within the theming engine environment where the
+ * UI5 resources are part of a "UI5" folder (e.g. "UI5/sap/ui/core/") that
+ * is next to a "Base" folder.
+ *
+ * @example
+ * getPathToRoot("/resources/sap/ui/foo/themes/base")
+ * > "../../../../../"
+ *
+ * @param {string} themeFolder Virtual path including /resources/
+ * @returns {string} Relative path to root namespace
+ */
+function getPathToRoot(themeFolder) {
+	// -2 for initial "/"" and "resources/"
+	return "../".repeat(themeFolder.split("/").length - 2);
+}
+
+/**
+ * Generates an less import statement for the given <code>filePath</code>
+ *
+ * @param {string} filePath The path to the desired file
+ * @returns {string} The less import statement
+ */
+function lessImport(filePath) {
+	return `@import "${filePath}";\n`;
+}
+
+function generateLibraryDotTheming({namespace, version, hasThemes}) {
+	const dotTheming = {
+		sEntity: "Library",
+		sId: namespace,
+		sVersion: version
+	};
+
+	if (namespace === "sap/ui/core") {
+		dotTheming.aFiles = [
+			"library",
+			"global", // Additional entry compared to UI5 root .theming
+			"css_variables",
+		];
+	}
+	if (!hasThemes) {
+		// Set ignore flag when there are no themes at all
+		// This is important in case a library used to contain themes that have been removed
+		// in a later version of the library.
+		dotTheming.bIgnore = true;
+	}
+
+	return new Resource({
+		path: `/resources/${namespace}/.theming`,
+		string: JSON.stringify(dotTheming, null, 2)
+	});
+}
+
+async function generateThemeDotTheming({workspace, combo, themeFolder}) {
+	const themeName = posixPath.basename(themeFolder);
+	const libraryMatchPattern = /^\/resources\/(.*)\/themes\/[^/]*$/i;
+	const libraryMatch = libraryMatchPattern.exec(themeFolder);
+	let libraryName;
+	if (libraryMatch) {
+		libraryName = libraryMatch[1].replace(/\//g, ".");
+	} else {
+		throw new Error(`Failed to extract library name from theme folder path: ${themeFolder}`);
+	}
+
+	const dotThemingTargetPath = posixPath.join(themeFolder, ".theming");
+	if (libraryName === "sap.ui.core") {
+		// sap.ui.core should always have a .theming file for all themes
+
+		if (await workspace.byPath(dotThemingTargetPath)) {
+			// .theming file present, skip further processing
+			return;
+		} else {
+			throw new Error(`.theming file for theme ${themeName} missing in sap.ui.core library source`);
+		}
+	}
+
+	let newDotThemingResource;
+	const coreDotThemingResource = await combo.byPath(`/resources/sap/ui/core/themes/${themeName}/.theming`);
+
+	if (coreDotThemingResource) {
+		// Copy .theming file from core
+		newDotThemingResource = await coreDotThemingResource.clone();
+		newDotThemingResource.setPath(dotThemingTargetPath);
+	} else {
+		// No core .theming file found for this theme => Generate a .theming file
+		const dotTheming = {
+			sEntity: "Theme",
+			sId: themeName,
+			sVendor: "SAP"
+		};
+
+		if (themeName !== "base") {
+			dotTheming.oExtends = "base";
+		}
+
+		newDotThemingResource = new Resource({
+			path: dotThemingTargetPath,
+			string: JSON.stringify(dotTheming, null, 2)
+		});
+	}
+	return newDotThemingResource;
+}
+
+async function createCssVariablesLessResource({workspace, combo, themeFolder}) {
+	const pathToRoot = getPathToRoot(themeFolder);
+	const cssVariablesSourceLessFile = "css_variables.source.less";
+	const cssVariablesLessFile = "css_variables.less";
+
+	// posix as it is a virtual path (separated with /)
+	const themeName = posixPath.basename(themeFolder);
+	// The "base" theme of the baseLib is called "baseTheme"
+	const baseLibThemeName = themeName === "base" ? "baseTheme" : themeName;
+
+	// Some themes do not have a base.less file (e.g. sap_hcb)
+	const hasBaseLess = !!(await combo.byPath(`/resources/sap/ui/core/themes/${themeName}/base.less`));
+
+	let cssVariablesLess =
+`/* NOTE: This file was generated as an optimized version of "${cssVariablesSourceLessFile}" \
+for the Theme Designer. */\n\n`;
+
+	if (themeName !== "base") {
+		const cssVariablesSourceLessResource = await workspace.byPath(
+			posixPath.join(themeFolder, cssVariablesSourceLessFile)
+		);
+
+		if (!cssVariablesSourceLessResource) {
+			throw new Error(`Could not find file "${cssVariablesSourceLessFile}" in theme "${themeFolder}"`);
+		}
+
+		const cssVariablesSourceLess = await cssVariablesSourceLessResource.getString();
+
+		cssVariablesLess += lessImport(`../base/${cssVariablesLessFile}`);
+		cssVariablesLess += `
+/* START "${cssVariablesSourceLessFile}" */
+${cssVariablesSourceLess}
+/* END "${cssVariablesSourceLessFile}" */
+
+`;
+	}
+
+	if (hasBaseLess) {
+		cssVariablesLess += lessImport(`${pathToRoot}../Base/baseLib/${baseLibThemeName}/base.less`);
+	}
+	cssVariablesLess += lessImport(`${pathToRoot}sap/ui/core/themes/${themeName}/global.less`);
+
+	return new Resource({
+		path: posixPath.join(themeFolder, cssVariablesLessFile),
+		string: cssVariablesLess
+	});
+}
+
+async function generateCssVariablesLess({workspace, combo, namespace}) {
+	let cssVariablesSourceLessResourcePattern;
+	if (namespace) {
+		// In case of a library only check for themes directly below the namespace
+		cssVariablesSourceLessResourcePattern = `/resources/${namespace}/themes/*/css_variables.source.less`;
+	} else {
+		// In case of a theme-library check for all "themes"
+		cssVariablesSourceLessResourcePattern = `/resources/**/themes/*/css_variables.source.less`;
+	}
+
+	const cssVariablesSourceLessResource = await workspace.byGlob(cssVariablesSourceLessResourcePattern);
+
+	const hasCssVariables = cssVariablesSourceLessResource.length > 0;
+
+	if (hasCssVariables) {
+		await Promise.all(
+			cssVariablesSourceLessResource.map(async (cssVariableSourceLess) => {
+				const themeFolder = posixPath.dirname(cssVariableSourceLess.getPath());
+				log.verbose(`Generating css_variables.less for theme ${themeFolder}`);
+				const r = await createCssVariablesLessResource({
+					workspace, combo, themeFolder
+				});
+				return await workspace.write(r);
+			})
+		);
+	}
+}
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/generateThemeDesignerResources
+ */
+
+/* eslint "jsdoc/check-param-names": ["error", {"disableExtraPropertyReporting":true}] */
+/**
+ * Generates resources required for integration with the SAP Theme Designer.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @param {string} parameters.options.version Project version
+ * @param {string} [parameters.options.projectNamespace] If the project is of type <code>library</code>,
+ * 														 provide its namespace.
+ * Omit for type <code>theme-library</code>
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, dependencies, options}) {
+	const {projectName, version} = options;
+	// Backward compatibility: "namespace" option got renamed to "projectNamespace"
+	const namespace = options.projectNamespace || options.namespace;
+
+	// Skip sap.ui.documentation since it is not intended to be available in SAP Theme Designer to create custom themes
+	if (namespace === "sap/ui/documentation") {
+		return;
+	}
+
+	let librarySourceLessPattern;
+	if (namespace) {
+		// In case of a library only check for themes directly below the namespace
+		librarySourceLessPattern = `/resources/${namespace}/themes/*/library.source.less`;
+	} else {
+		// In case of a theme-library check for all "themes"
+		librarySourceLessPattern = `/resources/**/themes/*/library.source.less`;
+	}
+
+	const librarySourceLessResources = await workspace.byGlob(librarySourceLessPattern);
+
+	const hasThemes = librarySourceLessResources.length > 0;
+
+	// library .theming file
+	// Only for type "library". Type "theme-library" does not provide a namespace
+	// Also needs to be created in case a library does not have any themes (see bIgnore flag)
+	if (namespace) {
+		log.verbose(`Generating .theming for namespace ${namespace}`);
+		const libraryDotThemingResource = generateLibraryDotTheming({
+			namespace,
+			version,
+			hasThemes
+		});
+		await workspace.write(libraryDotThemingResource);
+	}
+
+	if (!hasThemes) {
+		// Skip further processing as there are no themes
+		return;
+	}
+
+	const combo = new ReaderCollectionPrioritized({
+		name: `generateThemeDesignerResources - prioritize workspace over dependencies: ${projectName}`,
+		readers: [workspace, dependencies]
+	});
+
+	// theme .theming files
+	const themeDotThemingFiles = await Promise.all(
+		librarySourceLessResources.map((librarySourceLess) => {
+			const themeFolder = posixPath.dirname(librarySourceLess.getPath());
+			log.verbose(`Generating .theming for theme ${themeFolder}`);
+			return generateThemeDotTheming({
+				workspace, combo, themeFolder
+			});
+		})
+	);
+	await Promise.all(
+		themeDotThemingFiles.map(async (resource) => {
+			if (resource) {
+				await workspace.write(resource);
+			}
+		})
+	);
+
+	// library.less files
+	const libraryLessResources = await libraryLessGenerator({
+		resources: librarySourceLessResources,
+		fs: fsInterface(combo),
+	});
+	await Promise.all(
+		libraryLessResources.map((resource) => workspace.write(resource))
+	);
+
+	// css_variables.less
+	await generateCssVariablesLess({workspace, combo, namespace});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_generateVersionInfo.js.html b/v3/api/builder_lib_tasks_generateVersionInfo.js.html new file mode 100644 index 0000000000..1d3cc30569 --- /dev/null +++ b/v3/api/builder_lib_tasks_generateVersionInfo.js.html @@ -0,0 +1,152 @@ + + + + + + + builder/lib/tasks/generateVersionInfo.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/generateVersionInfo.js

+ + + + + + + +
+
+
import versionInfoGenerator from "../processors/versionInfoGenerator.js";
+
+const MANIFEST_JSON = "manifest.json";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/generateVersionInfo
+ */
+
+/**
+ * Task to create sap-ui-version.json
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pattern Glob pattern for .library resources
+ * @param {object} parameters.options.rootProject DuplexCollection to read and write files
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async ({workspace, dependencies, options: {rootProject, pattern}}) => {
+	const resources = await dependencies.byGlob(pattern);
+
+	const libraryInfosPromises = resources.map((dotLibResource) => {
+		const namespace = dotLibResource.getProject().getNamespace();
+		// pass all required resources to the processor
+		// the processor will then filter
+		return dependencies.byGlob(`/resources/${namespace}/**/${MANIFEST_JSON}`).then((manifestResources) => {
+			const libraryManifest = manifestResources.find((manifestResource) => {
+				return manifestResource.getPath() === `/resources/${namespace}/${MANIFEST_JSON}`;
+			});
+			const embeddedManifests =
+				manifestResources.filter((manifestResource) => manifestResource !== libraryManifest);
+			return {
+				libraryManifest,
+				embeddedManifests,
+				name: dotLibResource.getProject().getName(),
+				version: dotLibResource.getProject().getVersion()
+			};
+		});
+	});
+	const libraryInfos = await Promise.all(libraryInfosPromises);
+
+	const [versionInfoResource] = await versionInfoGenerator({
+		options: {
+			rootProjectName: rootProject.getName(),
+			rootProjectVersion: rootProject.getVersion(),
+			libraryInfos
+		}
+	});
+	return workspace.write(versionInfoResource);
+};
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_jsdoc_executeJsdocSdkTransformation.js.html b/v3/api/builder_lib_tasks_jsdoc_executeJsdocSdkTransformation.js.html new file mode 100644 index 0000000000..a966f4a6f5 --- /dev/null +++ b/v3/api/builder_lib_tasks_jsdoc_executeJsdocSdkTransformation.js.html @@ -0,0 +1,180 @@ + + + + + + + builder/lib/tasks/jsdoc/executeJsdocSdkTransformation.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/jsdoc/executeJsdocSdkTransformation.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:jsdoc:executeJsdocSdkTransformation");
+import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+import fsInterface from "@ui5/fs/fsInterface";
+import sdkTransformer from "../../processors/jsdoc/sdkTransformer.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/jsdoc/executeJsdocSdkTransformation
+ */
+
+/**
+ * Task to transform the api.json file as created by the
+ * [generateJsdoc]{@link @ui5/builder/tasks/jsdoc/generateJsdoc} task into a pre-processed api.json
+ * file suitable for the SDK.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {object} parameters.options Options
+ * @param {string|Array} parameters.options.dotLibraryPattern Pattern to locate the .library resource to be processed
+ * @param {string} parameters.options.projectName Project name
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+const executeJsdocSdkTransformation = async function(
+	{workspace, dependencies, options: {projectName, dotLibraryPattern}} = {}
+) {
+	if (!projectName || !dotLibraryPattern) {
+		throw new Error("[executeJsdocSdkTransformation]: One or more mandatory options not provided");
+	}
+
+	const [apiJsons, dotLibraries, depApiJsons] = await Promise.all([
+		workspace.byGlob("/test-resources/**/designtime/api.json"),
+		workspace.byGlob(dotLibraryPattern),
+		dependencies.byGlob("/test-resources/**/designtime/api.json")
+	]);
+	if (!apiJsons.length) {
+		log.info(`Failed to locate api.json resource for project ${projectName}. ` +
+			`Skipping SDK Transformation...`);
+		return;
+	} else if (apiJsons.length > 1) {
+		throw new Error(`[executeJsdocSdkTransformation]: Found more than one api.json resources for project ` +
+			`${projectName}.`);
+	}
+	if (!dotLibraries.length) {
+		throw new Error(`[executeJsdocSdkTransformation]: Failed to locate .library resource for project ` +
+			`${projectName}.`);
+	} else if (dotLibraries.length > 1) {
+		throw new Error(`[executeJsdocSdkTransformation]: Found more than one .library resources for project ` +
+			`${projectName}.`);
+	}
+
+	const combo = new ReaderCollectionPrioritized({
+		name: `executeJsdocSdkTransformation - custom workspace + dependencies FS: ${projectName}`,
+		readers: [workspace, dependencies]
+	});
+
+	const apiJsonPath = apiJsons[0].getPath();
+	const dotLibraryPath = dotLibraries[0].getPath();
+	const dependencyApiJsonPaths = depApiJsons.map((res) => {
+		return res.getPath();
+	});
+
+	// Target path is typically "/test-resources/${options.namespace}/designtime/apiref/api.json"
+	const targetApiJsonPath = apiJsonPath.replace(/\/api\.json$/i, "/apiref/api.json");
+
+	const createdResources = await sdkTransformer({
+		apiJsonPath,
+		dotLibraryPath,
+		dependencyApiJsonPaths,
+		targetApiJsonPath,
+		fs: fsInterface(combo)
+	});
+
+	await Promise.all(createdResources.map((resource) => {
+		return workspace.write(resource);
+	}));
+};
+
+export default executeJsdocSdkTransformation;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_jsdoc_generateApiIndex.js.html b/v3/api/builder_lib_tasks_jsdoc_generateApiIndex.js.html new file mode 100644 index 0000000000..20bf123089 --- /dev/null +++ b/v3/api/builder_lib_tasks_jsdoc_generateApiIndex.js.html @@ -0,0 +1,152 @@ + + + + + + + builder/lib/tasks/jsdoc/generateApiIndex.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/jsdoc/generateApiIndex.js

+ + + + + + + +
+
+
import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+import fsInterface from "@ui5/fs/fsInterface";
+import apiIndexGenerator from "../../processors/jsdoc/apiIndexGenerator.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/jsdoc/generateApiIndex
+ */
+
+/**
+ * Compiles an api-index.json resource from all available api.json resources as created by the
+ * [executeJsdocSdkTransformation]{@link @ui5/builder/tasks/jsdoc/executeJsdocSdkTransformation} task.
+ * The resulting api-index.json resource is mainly to be used in the SDK.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.projectName Project name
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({
+	workspace,
+	dependencies,
+	options: {projectName}
+}) {
+	const combo = new ReaderCollectionPrioritized({
+		name: `generateApiIndex - workspace + dependencies: ${projectName}`,
+		readers: [workspace, dependencies]
+	});
+
+	const versionInfoPath = "/resources/sap-ui-version.json";
+	const testResourcesRootPath = "/test-resources";
+	const targetApiIndexPath = "/docs/api/api-index.json";
+	const targetApiIndexDeprecatedPath = "/docs/api/api-index-deprecated.json";
+	const targetApiIndexExperimentalPath = "/docs/api/api-index-experimental.json";
+	const targetApiIndexSincePath = "/docs/api/api-index-since.json";
+
+	const createdResources = await apiIndexGenerator({
+		versionInfoPath,
+		testResourcesRootPath,
+		targetApiIndexPath,
+		targetApiIndexDeprecatedPath,
+		targetApiIndexExperimentalPath,
+		targetApiIndexSincePath,
+		fs: fsInterface(combo),
+	});
+
+	await Promise.all(createdResources.map((resource) => {
+		return workspace.write(resource);
+	}));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_jsdoc_generateJsdoc.js.html b/v3/api/builder_lib_tasks_jsdoc_generateJsdoc.js.html new file mode 100644 index 0000000000..dbc7db55cb --- /dev/null +++ b/v3/api/builder_lib_tasks_jsdoc_generateJsdoc.js.html @@ -0,0 +1,297 @@ + + + + + + + builder/lib/tasks/jsdoc/generateJsdoc.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/jsdoc/generateJsdoc.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("builder:tasks:jsdoc:generateJsdoc");
+import path from "node:path";
+import os from "node:os";
+import fs from "graceful-fs";
+import {rimraf} from "rimraf";
+import {promisify} from "node:util";
+const mkdtemp = promisify(fs.mkdtemp);
+const mkdir = promisify(fs.mkdir);
+import jsdocGenerator from "../../processors/jsdoc/jsdocGenerator.js";
+import {createAdapter} from "@ui5/fs/resourceFactory";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/jsdoc/generateJsdoc
+ */
+
+/**
+ *
+ * @public
+ * @typedef {object} GenerateJsdocOptions
+ * @property {string|string[]} pattern Pattern to locate the files to be processed
+ * @property {string} projectName Project name
+ * @property {string} namespace Namespace to build (e.g. <code>some/project/name</code>)
+ * @property {string} version Project version
+ */
+
+/**
+ * Task to execute a JSDoc build for UI5 projects
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+ * @param {module:@ui5/builder/tasks/jsdoc/generateJsdoc~GenerateJsdocOptions} parameters.options Options
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function generateJsdoc({
+	taskUtil,
+	workspace,
+	dependencies,
+	options = {}
+}) {
+	const {projectName, namespace, version, pattern} =
+	/** @type {module:@ui5/builder/tasks/jsdoc/generateJsdoc~GenerateJsdocOptions} */ (options);
+
+	if (!projectName || !namespace || !version || !pattern) {
+		throw new Error("[generateJsdoc]: One or more mandatory options not provided");
+	}
+
+	const {sourcePath: resourcePath, targetPath, tmpPath, cleanup} =
+		await utils.createTmpDirs(projectName);
+
+	taskUtil?.registerCleanupTask(cleanup);
+
+	const [writtenResourcesCount] = await Promise.all([
+		utils.writeResourcesToDir({
+			workspace,
+			pattern,
+			targetPath: resourcePath
+		}),
+		utils.writeDependencyApisToDir({
+			dependencies,
+			targetPath: path.join(tmpPath, "dependency-apis")
+		})
+	]);
+
+	if (writtenResourcesCount === 0) {
+		log.info(`Failed to find any input resources for project ${projectName} using pattern ` +
+			`${pattern}. Skipping JSDoc generation...`);
+		return;
+	}
+
+	const createdResources = await jsdocGenerator({
+		sourcePath: resourcePath,
+		targetPath,
+		tmpPath,
+		options: {
+			projectName,
+			namespace,
+			version,
+			variants: ["apijson"]
+		}
+	});
+
+	await Promise.all(createdResources.map((resource) => {
+		return workspace.write(resource);
+	}));
+}
+
+const utils = {
+	/**
+	 * Create temporary directories for JSDoc generation processor
+	 *
+	 * @private
+	 * @param {string} projectName Project name used for naming the temporary working directory
+	 * @returns {Promise<object>} Promise resolving with sourcePath, targetPath and tmpPath strings
+	 */
+	createTmpDirs: async function(projectName) {
+		const tmpDirPath = await utils.createTmpDir(projectName);
+
+		const sourcePath = path.join(tmpDirPath, "src"); // dir will be created by writing project resources below
+		await mkdir(sourcePath, {recursive: true});
+		const targetPath = path.join(tmpDirPath, "target"); // dir will be created by jsdoc itself
+		await mkdir(targetPath, {recursive: true});
+
+		const tmpPath = path.join(tmpDirPath, "tmp"); // dir needs to be created by us
+		await mkdir(tmpPath, {recursive: true});
+
+		return {
+			sourcePath,
+			targetPath,
+			tmpPath,
+			cleanup: async () => {
+				return rimraf(tmpDirPath);
+			}
+		};
+	},
+
+	/**
+	 * Create a temporary directory on the host system
+	 *
+	 * @private
+	 * @param {string} projectName Project name used for naming the temporary directory
+	 * @returns {Promise<string>} Promise resolving with path of the temporary directory
+	 */
+	createTmpDir: async function(projectName) {
+		const sanitizedProjectName = projectName.replace(/[^A-Za-z0-9]/g, "");
+
+		const tmpRootPath = path.join(os.tmpdir(), "ui5-tooling");
+		await mkdir(tmpRootPath, {recursive: true});
+
+		// Appending minus sign also because node docs advise to "avoid trailing X characters in prefix"
+		return mkdtemp(path.join(tmpRootPath, `jsdoc-${sanitizedProjectName}-`));
+	},
+
+	/**
+	 * Write resources from workspace matching the given pattern to the given fs destination
+	 *
+	 * @private
+	 * @param {object} parameters Parameters
+	 * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+	 * @param {string} parameters.pattern Pattern to match resources in workspace against
+	 * @param {string} parameters.targetPath Path to write the resources to
+	 * @returns {Promise<number>} Promise resolving with number of resources written to given directory
+	 */
+	writeResourcesToDir: async function({workspace, pattern, targetPath}) {
+		const fsTarget = createAdapter({
+			fsBasePath: targetPath,
+			virBasePath: "/resources/"
+		});
+
+		let allResources;
+		if (workspace.byGlobSource) { // API only available on duplex collections
+			allResources = await workspace.byGlobSource(pattern);
+		} else {
+			allResources = await workspace.byGlob(pattern);
+		}
+
+		// write all resources to the tmp folder
+		await Promise.all(allResources.map((resource) => fsTarget.write(resource)));
+		return allResources.length;
+	},
+
+	/**
+	 * Write api.json files of dependencies to given target path in a flat structure
+	 *
+	 * @private
+	 * @param {object} parameters Parameters
+	 * @param {@ui5/fs/AbstractReader} parameters.dependencies Reader or Collection to read dependency files
+	 * @param {string} parameters.targetPath Path to write the resources to
+	 * @returns {Promise<number>} Promise resolving with number of resources written to given directory
+	 */
+	writeDependencyApisToDir: async function({dependencies, targetPath}) {
+		const depApis = await dependencies.byGlob("/test-resources/**/designtime/api.json");
+
+		// Clone resources before changing their path
+		const apis = await Promise.all(depApis.map((resource) => resource.clone()));
+
+		for (let i = 0; i < apis.length; i++) {
+			apis[i].setPath(`/api-${i}.json`);
+		}
+
+		const fsTarget = createAdapter({
+			fsBasePath: targetPath,
+			virBasePath: "/"
+		});
+		await Promise.all(apis.map((resource) => fsTarget.write(resource)));
+		return apis.length;
+	}
+};
+
+// Export utils for testing only
+/* istanbul ignore else */
+if (process.env.NODE_ENV === "test") {
+	generateJsdoc._utils = utils;
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_minify.js.html b/v3/api/builder_lib_tasks_minify.js.html new file mode 100644 index 0000000000..0bc82f4fdd --- /dev/null +++ b/v3/api/builder_lib_tasks_minify.js.html @@ -0,0 +1,146 @@ + + + + + + + builder/lib/tasks/minify.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/minify.js

+ + + + + + + +
+
+
import minifier from "../processors/minifier.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/minify
+ */
+
+/**
+ * Task to minify resources.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {@ui5/project/build/helpers/TaskUtil|object} [parameters.taskUtil] TaskUtil
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pattern Pattern to locate the files to be processed
+ * @param {boolean} [parameters.options.omitSourceMapResources=false] Whether source map resources shall
+ * 		be tagged as "OmitFromBuildResult" and no sourceMappingURL shall be added to the minified resource
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default async function({workspace, taskUtil, options: {pattern, omitSourceMapResources = false}}) {
+	const resources = await workspace.byGlob(pattern);
+	const processedResources = await minifier({
+		resources,
+		taskUtil,
+		options: {
+			addSourceMappingUrl: !omitSourceMapResources,
+			useWorkers: !!taskUtil,
+		}
+	});
+
+	return Promise.all(processedResources.map(async ({resource, dbgResource, sourceMapResource}) => {
+		if (taskUtil) {
+			taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
+			taskUtil.setTag(dbgResource, taskUtil.STANDARD_TAGS.IsDebugVariant);
+			taskUtil.setTag(sourceMapResource, taskUtil.STANDARD_TAGS.HasDebugVariant);
+			if (omitSourceMapResources) {
+				taskUtil.setTag(sourceMapResource, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
+			}
+		}
+		return Promise.all([
+			workspace.write(resource),
+			workspace.write(dbgResource),
+			workspace.write(sourceMapResource)
+		]);
+	}));
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_replaceBuildtime.js.html b/v3/api/builder_lib_tasks_replaceBuildtime.js.html new file mode 100644 index 0000000000..9d6510d3de --- /dev/null +++ b/v3/api/builder_lib_tasks_replaceBuildtime.js.html @@ -0,0 +1,149 @@ + + + + + + + builder/lib/tasks/replaceBuildtime.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/replaceBuildtime.js

+ + + + + + + +
+
+
import stringReplacer from "../processors/stringReplacer.js";
+
+function pad(v) {
+	return String(v).padStart(2, "0");
+}
+function getTimestamp() {
+	const date = new Date();
+	const year = date.getFullYear();
+	const month = pad(date.getMonth() + 1);
+	const day = pad(date.getDate());
+	const hours = pad(date.getHours());
+	const minutes = pad(date.getMinutes());
+	// yyyyMMdd-HHmm
+	return year + month + day + "-" + hours + minutes;
+}
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/replaceBuildtime
+ */
+
+/**
+ * Task to replace the buildtime <code>${buildtime}</code>.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pattern Pattern to locate the files to be processed
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default function({workspace, options: {pattern}}) {
+	const timestamp = getTimestamp();
+
+	return workspace.byGlob(pattern)
+		.then((processedResources) => {
+			return stringReplacer({
+				resources: processedResources,
+				options: {
+					pattern: "${buildtime}",
+					replacement: timestamp
+				}
+			});
+		})
+		.then((processedResources) => {
+			return Promise.all(processedResources.map((resource) => {
+				return workspace.write(resource);
+			}));
+		});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_replaceCopyright.js.html b/v3/api/builder_lib_tasks_replaceCopyright.js.html new file mode 100644 index 0000000000..629cd293d2 --- /dev/null +++ b/v3/api/builder_lib_tasks_replaceCopyright.js.html @@ -0,0 +1,151 @@ + + + + + + + builder/lib/tasks/replaceCopyright.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/replaceCopyright.js

+ + + + + + + +
+
+
import stringReplacer from "../processors/stringReplacer.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/replaceCopyright
+ */
+
+/**
+ * Task to to replace the copyright.
+ *
+ * The following placeholders are replaced with corresponding values:
+ * <ul>
+ * 	<li>${copyright}</li>
+ * 	<li>@copyright@</li>
+ * </ul>
+ *
+ * If the copyright string contains the optional placeholder ${currentYear}
+ * it will be replaced with the current year.
+ * If no copyright string is given, no replacement is being done.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.copyright Replacement copyright
+ * @param {string} parameters.options.pattern Pattern to locate the files to be processed
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default function({workspace, options: {copyright, pattern}}) {
+	if (!copyright) {
+		return Promise.resolve();
+	}
+
+	// Replace optional placeholder ${currentYear} with the current year
+	copyright = copyright.replace(/(?:\$\{currentYear\})/, new Date().getFullYear());
+
+	return workspace.byGlob(pattern)
+		.then((processedResources) => {
+			return stringReplacer({
+				resources: processedResources,
+				options: {
+					pattern: /(?:\$\{copyright\}|@copyright@)/g,
+					replacement: copyright
+				}
+			});
+		})
+		.then((processedResources) => {
+			return Promise.all(processedResources.map((resource) => {
+				return workspace.write(resource);
+			}));
+		});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/builder_lib_tasks_replaceVersion.js.html b/v3/api/builder_lib_tasks_replaceVersion.js.html new file mode 100644 index 0000000000..95448dd719 --- /dev/null +++ b/v3/api/builder_lib_tasks_replaceVersion.js.html @@ -0,0 +1,134 @@ + + + + + + + builder/lib/tasks/replaceVersion.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

builder/lib/tasks/replaceVersion.js

+ + + + + + + +
+
+
import stringReplacer from "../processors/stringReplacer.js";
+
+/**
+ * @public
+ * @module @ui5/builder/tasks/replaceVersion
+ */
+
+/**
+ * Task to replace the version <code>${version}</code>.
+ *
+ * @public
+ * @function default
+ * @static
+ *
+ * @param {object} parameters Parameters
+ * @param {@ui5/fs/DuplexCollection} parameters.workspace DuplexCollection to read and write files
+ * @param {object} parameters.options Options
+ * @param {string} parameters.options.pattern Pattern to locate the files to be processed
+ * @param {string} parameters.options.version Replacement version
+ * @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
+ */
+export default function({workspace, options: {pattern, version}}) {
+	return workspace.byGlob(pattern)
+		.then((allResources) => {
+			return stringReplacer({
+				resources: allResources,
+				options: {
+					pattern: /\$\{(?:project\.)?version\}/g,
+					replacement: version
+				}
+			});
+		})
+		.then((processedResources) => {
+			return Promise.all(processedResources.map((resource) => {
+				return workspace.write(resource);
+			}));
+		});
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/custom.css b/v3/api/custom.css new file mode 100644 index 0000000000..c38efbd9f2 --- /dev/null +++ b/v3/api/custom.css @@ -0,0 +1,13 @@ +footer { + display: flex; +} +.ui5-footer-item { + flex-grow: 0; + margin: auto 0.6rem; + padding: 0.4rem 0; + white-space: nowrap; +} +.ui5-footer-item-growing { + flex-grow: 1; + white-space: normal; +} diff --git a/v3/api/fonts/Montserrat/Montserrat-Bold.eot b/v3/api/fonts/Montserrat/Montserrat-Bold.eot new file mode 100644 index 0000000000..f2970bbdc7 Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Bold.eot differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Bold.ttf b/v3/api/fonts/Montserrat/Montserrat-Bold.ttf new file mode 100644 index 0000000000..3bfd79b66f Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Bold.ttf differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Bold.woff b/v3/api/fonts/Montserrat/Montserrat-Bold.woff new file mode 100644 index 0000000000..92607654b7 Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Bold.woff differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Bold.woff2 b/v3/api/fonts/Montserrat/Montserrat-Bold.woff2 new file mode 100644 index 0000000000..d9940cd116 Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Bold.woff2 differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Regular.eot b/v3/api/fonts/Montserrat/Montserrat-Regular.eot new file mode 100644 index 0000000000..735d12b51e Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Regular.eot differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Regular.ttf b/v3/api/fonts/Montserrat/Montserrat-Regular.ttf new file mode 100644 index 0000000000..5da852a349 Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Regular.ttf differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Regular.woff b/v3/api/fonts/Montserrat/Montserrat-Regular.woff new file mode 100644 index 0000000000..bf9183271b Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Regular.woff differ diff --git a/v3/api/fonts/Montserrat/Montserrat-Regular.woff2 b/v3/api/fonts/Montserrat/Montserrat-Regular.woff2 new file mode 100644 index 0000000000..72d13c60bd Binary files /dev/null and b/v3/api/fonts/Montserrat/Montserrat-Regular.woff2 differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot new file mode 100644 index 0000000000..0f24510b88 Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg new file mode 100644 index 0000000000..5384f985d2 --- /dev/null +++ b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg @@ -0,0 +1,978 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf new file mode 100644 index 0000000000..e6c158c2fb Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff new file mode 100644 index 0000000000..d0a1c2929b Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 new file mode 100644 index 0000000000..d28697491e Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot new file mode 100644 index 0000000000..b4204488cc Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg new file mode 100644 index 0000000000..dee0949fd6 --- /dev/null +++ b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg @@ -0,0 +1,1049 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf new file mode 100644 index 0000000000..4d56c337a3 Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff new file mode 100644 index 0000000000..4681019d82 Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff differ diff --git a/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 new file mode 100644 index 0000000000..8ddcae37b2 Binary files /dev/null and b/v3/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 differ diff --git a/v3/api/fs_lib_AbstractReader.js.html b/v3/api/fs_lib_AbstractReader.js.html new file mode 100644 index 0000000000..d4851b5f90 --- /dev/null +++ b/v3/api/fs_lib_AbstractReader.js.html @@ -0,0 +1,225 @@ + + + + + + + fs/lib/AbstractReader.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/AbstractReader.js

+ + + + + + + +
+
+
import randomInt from "random-int";
+import Trace from "./tracing/Trace.js";
+
+/**
+ * Abstract resource locator implementing the general API for <b>reading</b> resources
+ *
+ * @abstract
+ * @public
+ * @class
+ * @alias @ui5/fs/AbstractReader
+ */
+class AbstractReader {
+	/**
+	 * The constructor.
+	 *
+	 * @public
+	 * @param {string} name Name of the reader. Typically used for tracing purposes
+	 */
+	constructor(name) {
+		if (new.target === AbstractReader) {
+			throw new TypeError("Class 'AbstractReader' is abstract");
+		}
+		this._name = name;
+	}
+
+	/*
+	 * Returns the name of the reader instance. This can be used for logging/tracing purposes.
+	 *
+	 * @returns {string} Name of the reader
+	 */
+	getName() {
+		return this._name || `<unnamed ${this.constructor.name} Reader>`;
+	}
+
+	/**
+	 * Locates resources by matching glob patterns.
+	 *
+	 * @example
+	 * byGlob("**‏/*.{html,htm}");
+	 * byGlob("**‏/.library");
+	 * byGlob("/pony/*");
+	 *
+	 * @public
+	 * @param {string|string[]} virPattern glob pattern as string or array of glob patterns for
+	 * 										virtual directory structure
+	 * @param {object} [options] glob options
+	 * @param {boolean} [options.nodir=true] Do not match directories
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	byGlob(virPattern, options = {nodir: true}) {
+		const trace = new Trace(virPattern);
+		return this._byGlob(virPattern, options, trace).then(function(result) {
+			trace.printReport();
+			return result;
+		}).then((resources) => {
+			if (resources.length > 1) {
+				// Pseudo randomize result order to prevent consumers from relying on it:
+				// Swap the first object with a randomly chosen one
+				const x = 0;
+				const y = randomInt(0, resources.length - 1);
+				// Swap object at index "x" with  "y"
+				resources[x] = [resources[y], resources[y]=resources[x]][0];
+			}
+			return resources;
+		});
+	}
+
+	/**
+	 * Locates resources by matching a given path.
+	 *
+	 * @public
+	 * @param {string} virPath Virtual path
+	 * @param {object} [options] Options
+	 * @param {boolean} [options.nodir=true] Do not match directories
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
+	 */
+	byPath(virPath, options = {nodir: true}) {
+		const trace = new Trace(virPath);
+		return this._byPath(virPath, options, trace).then(function(resource) {
+			trace.printReport();
+			return resource;
+		});
+	}
+
+	/**
+	 * Locates resources by one or more glob patterns.
+	 *
+	 * @abstract
+	 * @protected
+	 * @param {string|string[]} virPattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	_byGlob(virPattern, options, trace) {
+		throw new Error("Function '_byGlob' is not implemented");
+	}
+
+	/**
+	 * Locate resources by matching a single glob pattern.
+	 *
+	 * @abstract
+	 * @protected
+	 * @param {string} pattern glob pattern
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	_runGlob(pattern, options, trace) {
+		throw new Error("Function '_runGlob' is not implemented");
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @abstract
+	 * @protected
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
+	 */
+	_byPath(virPath, options, trace) {
+		throw new Error("Function '_byPath' is not implemented");
+	}
+}
+
+export default AbstractReader;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_AbstractReaderWriter.js.html b/v3/api/fs_lib_AbstractReaderWriter.js.html new file mode 100644 index 0000000000..c430f6c2d1 --- /dev/null +++ b/v3/api/fs_lib_AbstractReaderWriter.js.html @@ -0,0 +1,167 @@ + + + + + + + fs/lib/AbstractReaderWriter.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/AbstractReaderWriter.js

+ + + + + + + +
+
+
import AbstractReader from "./AbstractReader.js";
+
+/**
+ * Abstract resource locator implementing the general API for <b>reading and writing</b> resources
+ *
+ * @abstract
+ * @public
+ * @class
+ * @alias @ui5/fs/AbstractReaderWriter
+ * @extends @ui5/fs/AbstractReader
+ */
+class AbstractReaderWriter extends AbstractReader {
+	/**
+	 * The constructor.
+	 *
+	 * @public
+	 * @param {string} name Name of the reader/writer. Typically used for tracing purposes
+	 */
+	constructor(name) {
+		if (new.target === AbstractReaderWriter) {
+			throw new TypeError("Class 'AbstractReaderWriter' is abstract");
+		}
+		super(name);
+	}
+
+	/*
+	 * Returns the name of the reader/writer instance. This can be used for logging/tracing purposes.
+	 *
+	 * @returns {string} Name of the reader/writer
+	 */
+	getName() {
+		return this._name || `<unnamed ${this.constructor.name} Reader/Writer>`;
+	}
+
+	/**
+	 * Writes the content of a resource to a path.
+	 *
+	 * @public
+	 * @param {@ui5/fs/Resource} resource Resource to write
+	 * @param {object} [options]
+	 * @param {boolean} [options.readOnly=false] Whether the resource content shall be written read-only
+	 *						Do not use in conjunction with the <code>drain</code> option.
+	 *						The written file will be used as the new source of this resources content.
+	 *						Therefore the written file should not be altered by any means.
+	 *						Activating this option might improve overall memory consumption.
+	 * @param {boolean} [options.drain=false] Whether the resource content shall be emptied during the write process.
+	 *						Do not use in conjunction with the <code>readOnly</code> option.
+	 *						Activating this option might improve overall memory consumption.
+	 *						This should be used in cases where this is the last access to the resource.
+	 *						E.g. the final write of a resource after all processing is finished.
+	 * @returns {Promise<undefined>} Promise resolving once data has been written
+	 */
+	write(resource, options = {drain: false, readOnly: false}) {
+		return this._write(resource, options);
+	}
+
+	/**
+	 * Writes the content of a resource to a path.
+	 *
+	 * @abstract
+	 * @protected
+	 * @param {@ui5/fs/Resource} resource Resource to write
+	 * @param {object} [options] Write options, see above
+	 * @returns {Promise<undefined>} Promise resolving once data has been written
+	 */
+	_write(resource, options) {
+		throw new Error("Not implemented");
+	}
+}
+
+export default AbstractReaderWriter;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_DuplexCollection.js.html b/v3/api/fs_lib_DuplexCollection.js.html new file mode 100644 index 0000000000..9cba882420 --- /dev/null +++ b/v3/api/fs_lib_DuplexCollection.js.html @@ -0,0 +1,199 @@ + + + + + + + fs/lib/DuplexCollection.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/DuplexCollection.js

+ + + + + + + +
+
+
import AbstractReaderWriter from "./AbstractReaderWriter.js";
+import ReaderCollectionPrioritized from "./ReaderCollectionPrioritized.js";
+
+/**
+ * Wrapper to keep readers and writers together
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/DuplexCollection
+ * @extends @ui5/fs/AbstractReaderWriter
+ */
+class DuplexCollection extends AbstractReaderWriter {
+	/**
+	 * The Constructor.
+	 *
+	 * @param {object} parameters
+	 * @param {@ui5/fs/AbstractReader} parameters.reader Single reader or collection of readers
+	 * @param {@ui5/fs/AbstractReaderWriter} parameters.writer
+	 *			A ReaderWriter instance which is only used for writing files
+	 * @param {string} [parameters.name=""] The collection name
+	 */
+	constructor({reader, writer, name = ""}) {
+		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;
+		this._writer = writer;
+
+		this._combo = new ReaderCollectionPrioritized({
+			name: `${name} - ReaderCollectionPrioritized`,
+			readers: [
+				writer,
+				reader
+			]
+		});
+	}
+
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @private
+	 * @param {string|string[]} virPattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving with a list of resources
+	 */
+	_byGlob(virPattern, options, trace) {
+		return this._combo._byGlob(virPattern, options, trace);
+	}
+
+	/**
+	 * Locates resources by glob from source reader only.
+	 * For found resources that are also available in the writer, the writer resource will be returned.
+	 *
+	 * @param {string} virPattern glob pattern for virtual directory structure
+	 * @param {object} [options] glob options
+	 * @param {boolean} [options.nodir=true] Do not match directories
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	byGlobSource(virPattern, options = {nodir: true}) {
+		return this._reader.byGlob(virPattern, options).then((resources) => {
+			return Promise.all(resources.map((readerResource) => {
+				return this._writer.byPath(readerResource.getPath()).then((writerResource) => {
+					return writerResource || readerResource;
+				});
+			}));
+		});
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource|null>}
+	 *   Promise resolving to a single resource or <code>null</code> if no resource is found
+	 */
+	_byPath(virPath, options, trace) {
+		return this._combo._byPath(virPath, options, trace);
+	}
+
+	/**
+	 * Writes the content of a resource to a path.
+	 *
+	 * @private
+	 * @param {@ui5/fs/Resource} resource The Resource to write
+	 * @returns {Promise<undefined>} Promise resolving once data has been written
+	 */
+	_write(resource) {
+		return this._writer.write(resource);
+	}
+}
+
+export default DuplexCollection;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_ReaderCollection.js.html b/v3/api/fs_lib_ReaderCollection.js.html new file mode 100644 index 0000000000..d7010e03ec --- /dev/null +++ b/v3/api/fs_lib_ReaderCollection.js.html @@ -0,0 +1,182 @@ + + + + + + + fs/lib/ReaderCollection.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/ReaderCollection.js

+ + + + + + + +
+
+
import AbstractReader from "./AbstractReader.js";
+
+/**
+ * Resource Locator ReaderCollection
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/ReaderCollection
+ * @extends @ui5/fs/AbstractReader
+ */
+class ReaderCollection extends AbstractReader {
+	/**
+	 * The constructor.
+	 *
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.name The collection name
+	 * @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);
+
+		// Remove any undefined (empty) readers from array
+		this._readers = readers.filter(($) => $);
+	}
+
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @private
+	 * @param {string|string[]} pattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	_byGlob(pattern, options, trace) {
+		return Promise.all(this._readers.map(function(resourceLocator) {
+			return resourceLocator._byGlob(pattern, options, trace);
+		})).then((result) => {
+			trace.collection(this._name);
+			return Array.prototype.concat.apply([], result);
+		});
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource|null>}
+	 *   Promise resolving to a single resource or <code>null</code> if no resource is found
+	 */
+	_byPath(virPath, options, trace) {
+		const that = this;
+		const resourceLocatorCount = this._readers.length;
+		let resolveCount = 0;
+
+		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);
+		}
+
+		// Using Promise.race to deliver files that can be found as fast as possible
+		return Promise.race(this._readers.map(function(resourceLocator) {
+			return resourceLocator._byPath(virPath, options, trace).then(function(resource) {
+				return new Promise(function(resolve, reject) {
+					trace.collection(that._name);
+					resolveCount++;
+					if (resource) {
+						resource.pushCollection(that._name);
+						resolve(resource);
+					} else if (resolveCount === resourceLocatorCount) {
+						resolve(null);
+					}
+				});
+			});
+		}));
+	}
+}
+
+export default ReaderCollection;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_ReaderCollectionPrioritized.js.html b/v3/api/fs_lib_ReaderCollectionPrioritized.js.html new file mode 100644 index 0000000000..57a440c6f1 --- /dev/null +++ b/v3/api/fs_lib_ReaderCollectionPrioritized.js.html @@ -0,0 +1,186 @@ + + + + + + + fs/lib/ReaderCollectionPrioritized.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/ReaderCollectionPrioritized.js

+ + + + + + + +
+
+
import AbstractReader from "./AbstractReader.js";
+
+/**
+ * Prioritized Resource Locator Collection
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/ReaderCollectionPrioritized
+ * @extends @ui5/fs/AbstractReader
+ */
+class ReaderCollectionPrioritized extends AbstractReader {
+	/**
+	 * The constructor.
+	 *
+	 * @param {object} parameters
+	 * @param {string} parameters.name The collection name
+	 * @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);
+
+		// Remove any undefined (empty) readers from array
+		this._readers = readers.filter(($) => $);
+	}
+
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @private
+	 * @param {string|string[]} pattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	_byGlob(pattern, options, trace) {
+		return Promise.all(this._readers.map(function(resourceLocator) {
+			return resourceLocator._byGlob(pattern, options, trace);
+		})).then((result) => {
+			const files = Object.create(null);
+			const resources = [];
+			// Prefer files found in preceding resource locators
+			for (let i = 0; i < result.length; i++) {
+				for (let j = 0; j < result[i].length; j++) {
+					const resource = result[i][j];
+					const path = resource.getPath();
+					if (!files[path]) {
+						files[path] = true;
+						resources.push(resource);
+					}
+				}
+			}
+
+			trace.collection(this._name);
+			return resources;
+		});
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource|null>}
+	 *   Promise resolving to a single resource or <code>null</code> if no resource is found
+	 */
+	_byPath(virPath, options, trace) {
+		const that = this;
+		const byPath = (i) => {
+			if (i > this._readers.length - 1) {
+				return null;
+			}
+			return this._readers[i]._byPath(virPath, options, trace).then((resource) => {
+				if (resource) {
+					resource.pushCollection(that._name);
+					return resource;
+				} else {
+					return byPath(++i);
+				}
+			});
+		};
+		return byPath(0);
+	}
+}
+
+export default ReaderCollectionPrioritized;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_Resource.js.html b/v3/api/fs_lib_Resource.js.html new file mode 100644 index 0000000000..333aa1cdae --- /dev/null +++ b/v3/api/fs_lib_Resource.js.html @@ -0,0 +1,578 @@ + + + + + + + fs/lib/Resource.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/Resource.js

+ + + + + + + +
+
+
import stream from "node:stream";
+import clone from "clone";
+import posixPath from "node:path/posix";
+
+const fnTrue = () => true;
+const fnFalse = () => false;
+
+/**
+ * Resource. UI5 Tooling specific representation of a file's content and metadata
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/Resource
+ */
+class Resource {
+	#project;
+	#buffer;
+	#buffering;
+	#collections;
+	#contentDrained;
+	#createStream;
+	#name;
+	#path;
+	#sourceMetadata;
+	#statInfo;
+	#stream;
+	#streamDrained;
+	#isModified;
+
+	/**
+	* Function for dynamic creation of content streams
+	*
+	* @public
+	* @callback @ui5/fs/Resource~createStream
+	* @returns {stream.Readable} A readable stream of a resources content
+	*/
+
+	/**
+	 *
+	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.path Absolute virtual path of the resource
+	 * @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 {@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 {@ui5/project/specifications/Project} [parameters.project] Project this resource is associated with
+	 * @param {object} [parameters.sourceMetadata] Source metadata for UI5 Tooling internal use.
+	 * 	Typically set by an adapter to store information for later retrieval.
+	 */
+	constructor({path, statInfo, buffer, string, createStream, stream, project, sourceMetadata}) {
+		if (!path) {
+			throw new Error("Unable to create Resource: Missing parameter 'path'");
+		}
+		if (buffer && createStream || buffer && string || string && createStream || buffer && stream ||
+				string && stream || createStream && stream) {
+			throw new Error("Unable to create Resource: Please set only one content parameter. " +
+				"'buffer', 'string', 'stream' or 'createStream'");
+		}
+
+		this.setPath(path);
+
+		this.#sourceMetadata = sourceMetadata;
+		if (this.#sourceMetadata) {
+			// This flag indicates whether a resource has changed from its original source.
+			// resource.isModified() is not sufficient, since it only reflects the modification state of the
+			// current instance.
+			// Since the sourceMetadata object is inherited to clones, it is the only correct indicator
+			this.#sourceMetadata.contentModified = this.#sourceMetadata.contentModified || false;
+		}
+		this.#isModified = false;
+
+		this.#project = project;
+
+		this.#statInfo = statInfo || { // TODO
+			isFile: fnTrue,
+			isDirectory: fnFalse,
+			isBlockDevice: fnFalse,
+			isCharacterDevice: fnFalse,
+			isSymbolicLink: fnFalse,
+			isFIFO: fnFalse,
+			isSocket: fnFalse,
+			atimeMs: new Date().getTime(),
+			mtimeMs: new Date().getTime(),
+			ctimeMs: new Date().getTime(),
+			birthtimeMs: new Date().getTime(),
+			atime: new Date(),
+			mtime: new Date(),
+			ctime: new Date(),
+			birthtime: new Date()
+		};
+
+		if (createStream) {
+			this.#createStream = createStream;
+		} else if (stream) {
+			this.#stream = stream;
+		} else if (buffer) {
+			// Use private setter, not to accidentally set any modified flags
+			this.#setBuffer(buffer);
+		} else if (typeof string === "string" || string instanceof String) {
+			// Use private setter, not to accidentally set any modified flags
+			this.#setBuffer(Buffer.from(string, "utf8"));
+		}
+
+		// Tracing:
+		this.#collections = [];
+	}
+
+	/**
+	 * Gets a buffer with the resource content.
+	 *
+	 * @public
+	 * @returns {Promise<Buffer>} Promise resolving with a buffer of the resource content.
+	 */
+	async getBuffer() {
+		if (this.#contentDrained) {
+			throw new Error(`Content of Resource ${this.#path} has been drained. ` +
+				"This might be caused by requesting resource content after a content stream has been " +
+				"requested and no new content (e.g. a new stream) has been set.");
+		}
+		if (this.#buffer) {
+			return this.#buffer;
+		} else if (this.#createStream || this.#stream) {
+			return this.#getBufferFromStream();
+		} else {
+			throw new Error(`Resource ${this.#path} has no content`);
+		}
+	}
+
+	/**
+	 * Sets a Buffer as content.
+	 *
+	 * @public
+	 * @param {Buffer} buffer Buffer instance
+	 */
+	setBuffer(buffer) {
+		if (this.#sourceMetadata) {
+			this.#sourceMetadata.contentModified = true;
+		}
+		this.#isModified = true;
+		this.#setBuffer(buffer);
+	}
+
+	#setBuffer(buffer) {
+		this.#createStream = null;
+		// if (this.#stream) { // TODO this may cause strange issues
+		// 	this.#stream.destroy();
+		// }
+		this.#stream = null;
+		this.#buffer = buffer;
+		this.#contentDrained = false;
+		this.#streamDrained = false;
+	}
+
+	/**
+	 * Gets a string with the resource content.
+	 *
+	 * @public
+	 * @returns {Promise<string>} Promise resolving with the resource content.
+	 */
+	getString() {
+		if (this.#contentDrained) {
+			return Promise.reject(new Error(`Content of Resource ${this.#path} has been drained. ` +
+				"This might be caused by requesting resource content after a content stream has been " +
+				"requested and no new content (e.g. a new stream) has been set."));
+		}
+		return this.getBuffer().then((buffer) => buffer.toString());
+	}
+
+	/**
+	 * Sets a String as content
+	 *
+	 * @public
+	 * @param {string} string Resource content
+	 */
+	setString(string) {
+		this.setBuffer(Buffer.from(string, "utf8"));
+	}
+
+	/**
+	 * 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 @ui5/fs/Resource#setStream}, [setBuffer]{@link @ui5/fs/Resource#setBuffer}
+	 * or [setString]{@link @ui5/fs/Resource#setString}). This
+	 * is to prevent consumers from accessing drained streams.
+	 *
+	 * @public
+	 * @returns {stream.Readable} Readable stream for the resource content.
+	 */
+	getStream() {
+		if (this.#contentDrained) {
+			throw new Error(`Content of Resource ${this.#path} has been drained. ` +
+				"This might be caused by requesting resource content after a content stream has been " +
+				"requested and no new content (e.g. a new stream) has been set.");
+		}
+		let contentStream;
+		if (this.#buffer) {
+			const bufferStream = new stream.PassThrough();
+			bufferStream.end(this.#buffer);
+			contentStream = bufferStream;
+		} else if (this.#createStream || this.#stream) {
+			contentStream = this.#getStream();
+		}
+		if (!contentStream) {
+			throw new Error(`Resource ${this.#path} has no content`);
+		}
+		// If a stream instance is being returned, it will typically get drained be the consumer.
+		// In that case, further content access will result in a "Content stream has been drained" error.
+		// However, depending on the execution environment, a resources content stream might have been
+		//	transformed into a buffer. In that case further content access is possible as a buffer can't be
+		//	drained.
+		// To prevent unexpected "Content stream has been drained" errors caused by changing environments, we flag
+		//	the resource content as "drained" every time a stream is requested. Even if actually a buffer or
+		//	createStream callback is being used.
+		this.#contentDrained = true;
+		return contentStream;
+	}
+
+	/**
+	 * Sets a readable stream as content.
+	 *
+	 * @public
+	 * @param {stream.Readable|@ui5/fs/Resource~createStream} stream Readable stream of the resource content or
+	 														callback for dynamic creation of a readable stream
+	 */
+	setStream(stream) {
+		this.#isModified = true;
+		if (this.#sourceMetadata) {
+			this.#sourceMetadata.contentModified = true;
+		}
+
+		this.#buffer = null;
+		// if (this.#stream) { // TODO this may cause strange issues
+		// 	this.#stream.destroy();
+		// }
+		if (typeof stream === "function") {
+			this.#createStream = stream;
+			this.#stream = null;
+		} else {
+			this.#stream = stream;
+			this.#createStream = null;
+		}
+		this.#contentDrained = false;
+		this.#streamDrained = false;
+	}
+
+	/**
+	 * Gets the virtual resources path
+	 *
+	 * @public
+	 * @returns {string} Virtual path of the resource
+	 */
+	getPath() {
+		return this.#path;
+	}
+
+	/**
+	 * Sets the virtual resources path
+	 *
+	 * @public
+	 * @param {string} path Absolute virtual path of the resource
+	 */
+	setPath(path) {
+		path = posixPath.normalize(path);
+		if (!posixPath.isAbsolute(path)) {
+			throw new Error(`Unable to set resource path: Path must be absolute: ${path}`);
+		}
+		this.#path = path;
+		this.#name = posixPath.basename(path);
+	}
+
+	/**
+	 * Gets the resource name
+	 *
+	 * @public
+	 * @returns {string} Name of the resource
+	 */
+	getName() {
+		return this.#name;
+	}
+
+	/**
+	 * 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.#statInfo;
+	}
+
+	/**
+	 * 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() {
+		// if resource does not have any content it should have 0 bytes
+		if (!this.#buffer && !this.#createStream && !this.#stream) {
+			return 0;
+		}
+		const buffer = await this.getBuffer();
+		return buffer.byteLength;
+	}
+
+	/**
+	 * Adds a resource collection name that was involved in locating this resource.
+	 *
+	 * @param {string} name Resource collection name
+	 */
+	pushCollection(name) {
+		this.#collections.push(name);
+	}
+
+	/**
+	 * Returns a clone of the resource. The clones content is independent from that of the original resource
+	 *
+	 * @public
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving with the clone
+	 */
+	async clone() {
+		const options = await this.#getCloneOptions();
+		return new Resource(options);
+	}
+
+	async #getCloneOptions() {
+		const options = {
+			path: this.#path,
+			statInfo: clone(this.#statInfo),
+			sourceMetadata: clone(this.#sourceMetadata)
+		};
+
+		if (this.#stream) {
+			options.buffer = await this.#getBufferFromStream();
+		} else if (this.#createStream) {
+			options.createStream = this.#createStream;
+		} else if (this.#buffer) {
+			options.buffer = this.#buffer;
+		}
+
+		return options;
+	}
+
+	/**
+	 * 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.
+	 *
+	 * @public
+	 * @returns {@ui5/project/specifications/Project} Project this resource is associated with
+	 */
+	getProject() {
+		return this.#project;
+	}
+
+	/**
+	 * Assign a project to the resource
+	 *
+	 * @public
+	 * @param {@ui5/project/specifications/Project} project Project this resource is associated with
+	 */
+	setProject(project) {
+		if (this.#project) {
+			throw new Error(`Unable to assign project ${project.getName()} to resource ${this.#path}: ` +
+				`Resource is already associated to project ${this.#project}`);
+		}
+		this.#project = project;
+	}
+
+	/**
+	 * Check whether a project has been assigned to the resource
+	 *
+	 * @public
+	 * @returns {boolean} True if the resource is associated with a project
+	 */
+	hasProject() {
+		return !!this.#project;
+	}
+
+	/**
+	 * Check whether the content of this resource has been changed during its life cycle
+	 *
+	 * @public
+	 * @returns {boolean} True if the resource's content has been changed
+	 */
+	isModified() {
+		return this.#isModified;
+	}
+
+	/**
+	 * Tracing: Get tree for printing out trace
+	 *
+	 * @returns {object} Trace tree
+	 */
+	getPathTree() {
+		const tree = Object.create(null);
+
+		let pointer = tree[this.#path] = Object.create(null);
+
+		for (let i = this.#collections.length - 1; i >= 0; i--) {
+			pointer = pointer[this.#collections[i]] = Object.create(null);
+		}
+
+		return tree;
+	}
+
+	/**
+	 * Returns source metadata if any where provided during the creation of this resource.
+	 * Typically set by an adapter to store information for later retrieval.
+	 *
+	 * @returns {object|null}
+	 */
+	getSourceMetadata() {
+		return this.#sourceMetadata || null;
+	}
+
+	/**
+	 * Returns the content as stream.
+	 *
+	 * @private
+	 * @returns {stream.Readable} Readable stream
+	 */
+	#getStream() {
+		if (this.#streamDrained) {
+			throw new Error(`Content stream of Resource ${this.#path} is flagged as drained.`);
+		}
+		if (this.#createStream) {
+			return this.#createStream();
+		}
+		this.#streamDrained = true;
+		return this.#stream;
+	}
+
+	/**
+	 * Converts the buffer into a stream.
+	 *
+	 * @private
+	 * @returns {Promise<Buffer>} Promise resolving with buffer.
+	 */
+	#getBufferFromStream() {
+		if (this.#buffering) { // Prevent simultaneous buffering, causing unexpected access to drained stream
+			return this.#buffering;
+		}
+		return this.#buffering = new Promise((resolve, reject) => {
+			const contentStream = this.#getStream();
+			const buffers = [];
+			contentStream.on("data", (data) => {
+				buffers.push(data);
+			});
+			contentStream.on("error", (err) => {
+				reject(err);
+			});
+			contentStream.on("end", () => {
+				const buffer = Buffer.concat(buffers);
+				this.#setBuffer(buffer);
+				this.#buffering = null;
+				resolve(buffer);
+			});
+		});
+	}
+}
+
+export default Resource;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_ResourceFacade.js.html b/v3/api/fs_lib_ResourceFacade.js.html new file mode 100644 index 0000000000..c302c285ca --- /dev/null +++ b/v3/api/fs_lib_ResourceFacade.js.html @@ -0,0 +1,358 @@ + + + + + + + fs/lib/ResourceFacade.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/ResourceFacade.js

+ + + + + + + +
+
+
import posixPath from "node:path/posix";
+
+/**
+ * A {@link @ui5/fs/Resource Resource} with a different path than it's original
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/ResourceFacade
+ */
+class ResourceFacade {
+	#path;
+	#name;
+	#resource;
+
+	/**
+	 *
+	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.path Virtual path of the facade resource
+	 * @param {@ui5/fs/Resource} parameters.resource Resource to conceal
+	 */
+	constructor({path, resource}) {
+		if (!path) {
+			throw new Error("Unable to create ResourceFacade: Missing parameter 'path'");
+		}
+		if (!resource) {
+			throw new Error("Unable to create ResourceFacade: Missing parameter 'resource'");
+		}
+		path = posixPath.normalize(path);
+		if (!posixPath.isAbsolute(path)) {
+			throw new Error(`Unable to create ResourceFacade: Parameter 'path' must be absolute: ${path}`);
+		}
+		this.#path = path;
+		this.#name = posixPath.basename(path);
+		this.#resource = resource;
+	}
+
+	/**
+	 * Gets the resources path
+	 *
+	 * @public
+	 * @returns {string} (Virtual) path of the resource
+	 */
+	getPath() {
+		return this.#path;
+	}
+
+	/**
+	 * Gets the resource name
+	 *
+	 * @public
+	 * @returns {string} Name of the resource
+	 */
+	getName() {
+		return this.#name;
+	}
+
+	/**
+	 * 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`);
+	}
+
+	/**
+	 * 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<@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 @ui5/fs/Resource#setStream}, [setBuffer]{@link @ui5/fs/Resource#setBuffer}
+	 * or [setString]{@link @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|@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();
+	}
+
+	/**
+	 * 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.
+	 *
+	 * @public
+	 * @returns {@ui5/project/specifications/Project} Project this resource is associated with
+	 */
+	getProject() {
+		return this.#resource.getProject();
+	}
+
+	/**
+	 * Assign a project to the resource
+	 *
+	 * @public
+	 * @param {@ui5/project/specifications/Project} project Project this resource is associated with
+	 */
+	setProject(project) {
+		return this.#resource.setProject(project);
+	}
+
+	/**
+	 * Check whether a project has been assigned to the resource
+	 *
+	 * @public
+	 * @returns {boolean} True if the resource is associated with a project
+	 */
+	hasProject() {
+		return this.#resource.hasProject();
+	}
+	/**
+	 * Check whether the content of this resource has been changed during its life cycle
+	 *
+	 * @public
+	 * @returns {boolean} True if the resource's content has been changed
+	 */
+	isModified() {
+		return this.#resource.isModified();
+	}
+
+	/**
+	 * Returns source metadata if any where provided during the creation of this resource.
+	 * Typically set by an adapter to store information for later retrieval.
+	 *
+	 * @returns {object|null}
+	 */
+	getSourceMetadata() {
+		return this.#resource.getSourceMetadata();
+	}
+
+
+	/**
+	 * Returns the resource concealed by this facade
+	 *
+	 * @returns {@ui5/fs/Resource}
+	 */
+	getConcealedResource() {
+		return this.#resource;
+	}
+}
+
+export default ResourceFacade;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_WriterCollection.js.html b/v3/api/fs_lib_WriterCollection.js.html new file mode 100644 index 0000000000..333d98ae81 --- /dev/null +++ b/v3/api/fs_lib_WriterCollection.js.html @@ -0,0 +1,213 @@ + + + + + + + fs/lib/WriterCollection.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/WriterCollection.js

+ + + + + + + +
+
+
import AbstractReaderWriter from "./AbstractReaderWriter.js";
+import ReaderCollection from "./ReaderCollection.js";
+import escapeStringRegExp from "escape-string-regexp";
+
+/**
+ * Resource Locator WriterCollection
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/WriterCollection
+ * @extends @ui5/fs/AbstractReaderWriter
+ */
+class WriterCollection extends AbstractReaderWriter {
+	/**
+	 * The constructor.
+	 *
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.name The collection name
+	 * @param {object.<string, @ui5/fs/AbstractReaderWriter>} parameters.writerMapping
+	 * 	Mapping of virtual base paths to writers. Path are matched greedy
+	 *
+	 * @example
+	 * new WriterCollection({
+	 *     name: "Writer Collection",
+	 *     writerMapping: {
+	 *	       "/": writerA,
+	 *	       "/my/path/": writerB,
+	 *     }
+	 * });
+	 */
+	constructor({name, writerMapping}) {
+		super(name);
+
+		if (!writerMapping) {
+			throw new Error(`Cannot create WriterCollection ${this._name}: Missing parameter 'writerMapping'`);
+		}
+		const basePaths = Object.keys(writerMapping);
+		if (!basePaths.length) {
+			throw new Error(`Cannot create WriterCollection ${this._name}: Empty parameter 'writerMapping'`);
+		}
+
+		// Create a regular expression (which is greedy by nature) from all paths to easily
+		//	find the correct writer for any given resource path
+		this._basePathRegex = basePaths.sort().reduce((regex, basePath, idx) => {
+			// Validate base path
+			if (!basePath) {
+				throw new Error(`Empty path in path mapping of WriterCollection ${this._name}`);
+			}
+			if (!basePath.startsWith("/")) {
+				throw new Error(
+					`Missing leading slash in path mapping '${basePath}' of WriterCollection ${this._name}`);
+			}
+			if (!basePath.endsWith("/")) {
+				throw new Error(
+					`Missing trailing slash in path mapping '${basePath}' of WriterCollection ${this._name}`);
+			}
+
+			return `${regex}(?:${escapeStringRegExp(basePath)})??`;
+		}, "^(") + ")+.*?$";
+
+		this._writerMapping = writerMapping;
+		this._readerCollection = new ReaderCollection({
+			name: `Reader collection of writer collection '${this._name}'`,
+			readers: Object.values(writerMapping)
+		});
+	}
+
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @private
+	 * @param {string|string[]} pattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	_byGlob(pattern, options, trace) {
+		return this._readerCollection._byGlob(pattern, options, trace);
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
+	 */
+	_byPath(virPath, options, trace) {
+		return this._readerCollection._byPath(virPath, options, trace);
+	}
+
+	/**
+	 * Writes the content of a resource to a path.
+	 *
+	 * @private
+	 * @param {@ui5/fs/Resource} resource The Resource to write
+	 * @param {object} [options] Write options, see above
+	 * @returns {Promise<undefined>} Promise resolving once data has been written
+	 */
+	_write(resource, options) {
+		const resourcePath = resource.getPath();
+
+		const basePathMatch = resourcePath.match(this._basePathRegex);
+		if (!basePathMatch || basePathMatch.length < 2) {
+			throw new Error(
+				`Failed to find a writer for resource with path ${resourcePath} in WriterCollection ${this._name}. ` +
+				`Base paths handled by this collection are: ${Object.keys(this._writerMapping).join(", ")}`);
+		}
+		const writer = this._writerMapping[basePathMatch[1]];
+		return writer._write(resource, options);
+	}
+}
+
+export default WriterCollection;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_adapters_AbstractAdapter.js.html b/v3/api/fs_lib_adapters_AbstractAdapter.js.html new file mode 100644 index 0000000000..ac78233f54 --- /dev/null +++ b/v3/api/fs_lib_adapters_AbstractAdapter.js.html @@ -0,0 +1,390 @@ + + + + + + + fs/lib/adapters/AbstractAdapter.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/adapters/AbstractAdapter.js

+ + + + + + + +
+
+
import path from "node:path/posix";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("resources:adapters:AbstractAdapter");
+import {minimatch} from "minimatch";
+import micromatch from "micromatch";
+import AbstractReaderWriter from "../AbstractReaderWriter.js";
+import Resource from "../Resource.js";
+
+/**
+ * Abstract Resource Adapter
+ *
+ * @abstract
+ * @public
+ * @class
+ * @alias @ui5/fs/adapters/AbstractAdapter
+ * @extends @ui5/fs/AbstractReaderWriter
+ */
+class AbstractAdapter extends AbstractReaderWriter {
+	/**
+	 * The constructor
+	 *
+	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.virBasePath
+	 *   Virtual base path. Must be absolute, POSIX-style, and must end with a slash
+	 * @param {string[]} [parameters.excludes] List of glob patterns to exclude
+	 * @param {object} [parameters.project] Experimental, internal parameter. Do not use
+	 */
+	constructor({virBasePath, excludes = [], project}) {
+		if (new.target === AbstractAdapter) {
+			throw new TypeError("Class 'AbstractAdapter' is abstract");
+		}
+		super();
+
+		if (!virBasePath) {
+			throw new Error(`Unable to create adapter: Missing parameter 'virBasePath'`);
+		}
+		if (!path.isAbsolute(virBasePath)) {
+			throw new Error(`Unable to create adapter: Virtual base path must be absolute but is '${virBasePath}'`);
+		}
+		if (!virBasePath.endsWith("/")) {
+			throw new Error(
+				`Unable to create adapter: Virtual base path must end with a slash but is '${virBasePath}'`);
+		}
+		this._virBasePath = virBasePath;
+		this._virBaseDir = virBasePath.slice(0, -1);
+		this._excludes = excludes;
+		this._excludesNegated = excludes.map((pattern) => `!${pattern}`);
+		this._project = project;
+	}
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @abstract
+	 * @private
+	 * @param {string|string[]} virPattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} [options={}] glob options
+	 * @param {boolean} [options.nodir=true] Do not match directories
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	async _byGlob(virPattern, options = {nodir: true}, trace) {
+		const excludes = this._excludesNegated;
+
+		if (!(virPattern instanceof Array)) {
+			virPattern = [virPattern];
+		}
+
+		// Append static exclude patterns
+		virPattern = Array.prototype.concat.apply(virPattern, excludes);
+		let patterns = virPattern.map(this._normalizePattern, this);
+		patterns = Array.prototype.concat.apply([], patterns);
+		if (patterns.length === 0) {
+			return [];
+		}
+
+		if (!options.nodir) {
+			for (let i = patterns.length - 1; i >= 0; i--) {
+				const idx = this._virBaseDir.indexOf(patterns[i]);
+				if (patterns[i] && idx !== -1 && idx < this._virBaseDir.length) {
+					const subPath = patterns[i];
+					return [
+						this._createResource({
+							statInfo: { // TODO: make closer to fs stat info
+								isDirectory: function() {
+									return true;
+								}
+							},
+							source: {
+								adapter: "Abstract"
+							},
+							path: subPath
+						})
+					];
+				}
+			}
+		}
+		return await this._runGlob(patterns, options, trace);
+	}
+
+	/**
+	 * Validate if virtual path should be excluded
+	 *
+	 * @param {string} virPath Virtual Path
+	 * @returns {boolean} True if path is excluded, otherwise false
+	 */
+	_isPathExcluded(virPath) {
+		return micromatch(virPath, this._excludes).length > 0;
+	}
+
+	/**
+	 * Validate if virtual path should be handled by the adapter.
+	 * This means that it either starts with the virtual base path of the adapter
+	 * or equals the base directory (base path without a trailing slash)
+	 *
+	 * @param {string} virPath Virtual Path
+	 * @returns {boolean} True if path should be handled
+	 */
+	_isPathHandled(virPath) {
+		// Check whether path starts with base path, or equals base directory
+		return virPath.startsWith(this._virBasePath) || virPath === this._virBaseDir;
+	}
+
+	/**
+	 * Normalizes virtual glob patterns.
+	 *
+	 * @private
+	 * @param {string} virPattern glob pattern for virtual directory structure
+	 * @returns {string[]} A list of normalized glob patterns
+	 */
+	_normalizePattern(virPattern) {
+		const that = this;
+		const mm = new minimatch.Minimatch(virPattern);
+
+		const basePathParts = this._virBaseDir.split("/");
+
+		function matchSubset(subset) {
+			let i;
+			for (i = 0; i < basePathParts.length; i++) {
+				const globPart = subset[i];
+				if (globPart === undefined) {
+					log.verbose("Ran out of glob parts to match (this should not happen):");
+					if (that._project) { // project is optional
+						log.verbose(`Project: ${that._project.getName()}`);
+					}
+					log.verbose(`Virtual base path: ${that._virBaseDir}`);
+					log.verbose(`Pattern to match: ${virPattern}`);
+					log.verbose(`Current subset (tried index ${i}):`);
+					log.verbose(subset);
+					return {idx: i, virtualMatch: true};
+				}
+				const basePathPart = basePathParts[i];
+				if (typeof globPart === "string") {
+					if (globPart !== basePathPart) {
+						return null;
+					} else {
+						continue;
+					}
+				} else if (globPart === minimatch.GLOBSTAR) {
+					return {idx: i};
+				} else { // Regex
+					if (!globPart.test(basePathPart)) {
+						return null;
+					} else {
+						continue;
+					}
+				}
+			}
+			if (subset.length === basePathParts.length) {
+				return {rootMatch: true};
+			}
+			return {idx: i};
+		}
+
+		const resultGlobs = [];
+		for (let i = 0; i < mm.set.length; i++) {
+			const match = matchSubset(mm.set[i]);
+			if (match) {
+				let resultPattern;
+				if (match.virtualMatch) {
+					resultPattern = basePathParts.slice(0, match.idx).join("/");
+				} else if (match.rootMatch) { // matched one up
+					resultPattern = ""; // root "/"
+				} else { // matched at some part of the glob
+					resultPattern = mm.globParts[i].slice(match.idx).join("/");
+					if (resultPattern.startsWith("/")) {
+						resultPattern = resultPattern.substr(1);
+					}
+				}
+				if (mm.negate) {
+					resultPattern = "!" + resultPattern;
+				}
+				resultGlobs.push(resultPattern);
+			}
+		}
+		return resultGlobs;
+	}
+
+	_createResource(parameters) {
+		if (this._project) {
+			parameters.project = this._project;
+		}
+		return new Resource(parameters);
+	}
+
+	_migrateResource(resource) {
+		// This function only returns a promise if a migration is necessary.
+		// Since this is rarely the case, we therefore reduce the amount of
+		// created Promises by making this differentiation
+
+		// Check if its a fs/Resource v3, function 'hasProject' was
+		// introduced with v3 therefore take it as the indicator
+		if (resource.hasProject) {
+			return resource;
+		}
+		return this._createFromLegacyResource(resource);
+	}
+
+	async _createFromLegacyResource(resource) {
+		const options = {
+			path: resource._path,
+			statInfo: resource._statInfo,
+			source: resource._source
+		};
+
+		if (resource._stream) {
+			options.buffer = await resource._getBufferFromStream();
+		} else if (resource._createStream) {
+			options.createStream = resource._createStream;
+		} else if (resource._buffer) {
+			options.buffer = resource._buffer;
+		}
+		return new Resource(options);
+	}
+
+	_assignProjectToResource(resource) {
+		if (this._project) {
+			// Assign project to resource if necessary
+			if (resource.hasProject()) {
+				if (resource.getProject() !== this._project) {
+					throw new Error(
+						`Unable to write resource associated with project ` +
+						`${resource.getProject().getName()} into adapter of project ${this._project.getName()}: ` +
+						resource.getPath());
+				}
+				return;
+			}
+			log.silly(`Associating resource ${resource.getPath()} with project ${this._project.getName()}`);
+			resource.setProject(this._project);
+		}
+	}
+
+	_resolveVirtualPathToBase(inputVirPath, writeMode = false) {
+		if (!path.isAbsolute(inputVirPath)) {
+			throw new Error(`Failed to resolve virtual path '${inputVirPath}': Path must be absolute`);
+		}
+		// Resolve any ".." segments to make sure we compare the effective start of the path
+		// with the virBasePath
+		const virPath = path.normalize(inputVirPath);
+
+		if (!writeMode) {
+			// When reading resources, validate against path excludes and return null if the given path
+			// does not match this adapters base path
+			if (!this._isPathHandled(virPath)) {
+				if (log.isLevelEnabled("silly")) {
+					log.silly(`Failed to resolve virtual path '${inputVirPath}': ` +
+						`Resolved path does not start with adapter base path '${this._virBasePath}' or equals ` +
+						`base dir: ${this._virBaseDir}`);
+				}
+				return null;
+			}
+			if (this._isPathExcluded(virPath)) {
+				if (log.isLevelEnabled("silly")) {
+					log.silly(`Failed to resolve virtual path '${inputVirPath}': ` +
+						`Resolved path is excluded by configuration of adapter with base path '${this._virBasePath}'`);
+				}
+				return null;
+			}
+		} else if (!this._isPathHandled(virPath)) {
+			// Resolved path is not within the configured base path and does
+			// not equal the virtual base directory.
+			// Since we don't want to write resources to foreign locations, we throw an error
+			throw new Error(
+				`Failed to write resource with virtual path '${inputVirPath}': Path must start with ` +
+				`the configured virtual base path of the adapter. Base path: '${this._virBasePath}'`);
+		}
+
+		const relPath = virPath.substr(this._virBasePath.length);
+		return relPath;
+	}
+}
+
+export default AbstractAdapter;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_adapters_FileSystem.js.html b/v3/api/fs_lib_adapters_FileSystem.js.html new file mode 100644 index 0000000000..363d7c9193 --- /dev/null +++ b/v3/api/fs_lib_adapters_FileSystem.js.html @@ -0,0 +1,467 @@ + + + + + + + fs/lib/adapters/FileSystem.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/adapters/FileSystem.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("resources:adapters:FileSystem");
+import path from "node:path";
+import {promisify} from "node:util";
+import fs from "graceful-fs";
+const copyFile = promisify(fs.copyFile);
+const chmod = promisify(fs.chmod);
+const mkdir = promisify(fs.mkdir);
+const stat = promisify(fs.stat);
+import {globby, isGitIgnored} from "globby";
+import {PassThrough} from "node:stream";
+import AbstractAdapter from "./AbstractAdapter.js";
+
+const READ_ONLY_MODE = 0o444;
+const ADAPTER_NAME = "FileSystem";
+/**
+ * File system resource adapter
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/adapters/FileSystem
+ * @extends @ui5/fs/adapters/AbstractAdapter
+ */
+class FileSystem extends AbstractAdapter {
+	/**
+	 * The Constructor.
+	 *
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.virBasePath
+	 *   Virtual base path. Must be absolute, POSIX-style, and must end with a slash
+	 * @param {string} parameters.fsBasePath
+	 *   File System base path. Must be absolute and must use platform-specific path segment separators
+	 * @param {string[]} [parameters.excludes] List of glob patterns to exclude
+	 * @param {object} [parameters.useGitignore=false]
+	 *   Whether to apply any excludes defined in an optional .gitignore in the given <code>fsBasePath</code> directory
+	 * @param {@ui5/project/specifications/Project} [parameters.project] Project this adapter belongs to (if any)
+	 */
+	constructor({virBasePath, project, fsBasePath, excludes, useGitignore=false}) {
+		super({virBasePath, project, excludes});
+
+		if (!fsBasePath) {
+			throw new Error(`Unable to create adapter: Missing parameter 'fsBasePath'`);
+		}
+
+		// Ensure path is resolved to an absolute path, ending with a slash (or backslash on Windows)
+		// path.resolve will always remove any trailing segment separator
+		this._fsBasePath = path.join(path.resolve(fsBasePath), path.sep);
+		this._useGitignore = !!useGitignore;
+	}
+
+	/**
+	 * 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 {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	async _runGlob(patterns, options = {nodir: true}, trace) {
+		const opt = {
+			cwd: this._fsBasePath,
+			dot: true,
+			onlyFiles: options.nodir,
+			followSymbolicLinks: false,
+			gitignore: this._useGitignore,
+		};
+		trace.globCall();
+
+		const promises = [];
+		if (!opt.onlyFiles && patterns.includes("")) { // Match physical root directory
+			promises.push(new Promise((resolve, reject) => {
+				fs.stat(this._fsBasePath, (err, stat) => {
+					if (err) {
+						reject(err);
+					} else {
+						resolve(this._createResource({
+							project: this._project,
+							statInfo: stat,
+							path: this._virBaseDir,
+							sourceMetadata: {
+								adapter: ADAPTER_NAME,
+								fsPath: this._fsBasePath
+							},
+							createStream: () => {
+								return fs.createReadStream(this._fsBasePath);
+							}
+						}));
+					}
+				});
+			}));
+		}
+
+		// Remove empty string glob patterns
+		// Starting with globby v8 or v9 empty glob patterns "" act like "**"
+		// Micromatch throws on empty strings. We just ignore them since they are
+		// typically caused by our normalization in the AbstractAdapter
+		const globbyPatterns = patterns.filter((pattern) => {
+			return pattern !== "";
+		});
+		if (globbyPatterns.length > 0) {
+			const matches = await globby(globbyPatterns, opt);
+			for (let i = matches.length - 1; i >= 0; i--) {
+				promises.push(new Promise((resolve, reject) => {
+					const virPath = (this._virBasePath + matches[i]);
+					const relPath = this._resolveVirtualPathToBase(virPath);
+					if (relPath === null) {
+						// Match is likely outside adapter base path
+						log.verbose(
+							`Failed to resolve virtual path of glob match '${virPath}': Path must start with ` +
+							`the configured virtual base path of the adapter. Base path: '${this._virBasePath}'`);
+						resolve(null);
+					}
+					const fsPath = this._resolveToFileSystem(relPath);
+
+					// Workaround for not getting the stat from the glob
+					fs.stat(fsPath, (err, stat) => {
+						if (err) {
+							reject(err);
+						} else {
+							resolve(this._createResource({
+								project: this._project,
+								statInfo: stat,
+								path: virPath,
+								sourceMetadata: {
+									adapter: ADAPTER_NAME,
+									fsPath: fsPath
+								},
+								createStream: () => {
+									return fs.createReadStream(fsPath);
+								}
+							}));
+						}
+					});
+				}));
+			}
+		}
+		const results = await Promise.all(promises);
+
+		// Flatten results
+		return Array.prototype.concat.apply([], results).filter(($) => $);
+	}
+
+	/**
+	 * Locate a resource by path.
+	 *
+	 * @private
+	 * @param {string} virPath Absolute virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource or null if not found
+	 */
+	async _byPath(virPath, options, trace) {
+		const relPath = this._resolveVirtualPathToBase(virPath);
+
+		if (relPath === null) {
+			// Neither starts with basePath, nor equals baseDirectory
+			if (!options.nodir && this._virBasePath.startsWith(virPath)) {
+				// Create virtual directories for the virtual base path (which has to exist)
+				// TODO: Maybe improve this by actually matching the base paths segments to the virPath
+				return this._createResource({
+					project: this._project,
+					statInfo: { // TODO: make closer to fs stat info
+						isDirectory: function() {
+							return true;
+						}
+					},
+					path: virPath
+				});
+			} else {
+				return null;
+			}
+		}
+
+		const fsPath = this._resolveToFileSystem(relPath);
+
+		trace.pathCall();
+
+		if (this._useGitignore) {
+			if (!this._isGitIgnored) {
+				this._isGitIgnored = await isGitIgnored({
+					cwd: this._fsBasePath
+				});
+			}
+			// Check whether path should be ignored
+			if (this._isGitIgnored(fsPath)) {
+				// Path is ignored by .gitignore
+				return null;
+			}
+		}
+
+		try {
+			const statInfo = await stat(fsPath);
+			if (options.nodir && statInfo.isDirectory()) {
+				return null;
+			}
+			const resourceOptions = {
+				project: this._project,
+				statInfo,
+				path: virPath,
+				sourceMetadata: {
+					adapter: ADAPTER_NAME,
+					fsPath
+				}
+			};
+
+			if (!statInfo.isDirectory()) {
+				// Add content as lazy stream
+				resourceOptions.createStream = function() {
+					return fs.createReadStream(fsPath);
+				};
+			}
+
+			return this._createResource(resourceOptions);
+		} catch (err) {
+			if (err.code === "ENOENT") { // "File or directory does not exist"
+				return null;
+			} else {
+				throw err;
+			}
+		}
+	}
+
+	/**
+	 * Writes the content of a resource to a path.
+	 *
+	 * @private
+	 * @param {@ui5/fs/Resource} resource Resource to write
+	 * @param {object} [options]
+	 * @param {boolean} [options.readOnly] Whether the resource content shall be written read-only
+	 *						Do not use in conjunction with the <code>drain</code> option.
+	 *						The written file will be used as the new source of this resources content.
+	 *						Therefore the written file should not be altered by any means.
+	 *						Activating this option might improve overall memory consumption.
+	 * @param {boolean} [options.drain] Whether the resource content shall be emptied during the write process.
+	 *						Do not use in conjunction with the <code>readOnly</code> option.
+	 *						Activating this option might improve overall memory consumption.
+	 *						This should be used in cases where this is the last access to the resource.
+	 *						E.g. the final write of a resource after all processing is finished.
+	 * @returns {Promise<undefined>} Promise resolving once data has been written
+	 */
+	async _write(resource, {drain, readOnly}) {
+		resource = this._migrateResource(resource);
+		if (resource instanceof Promise) {
+			// Only await if the migrate function returned a promise
+			// Otherwise await would automatically create a Promise, causing unwanted overhead
+			resource = await resource;
+		}
+		this._assignProjectToResource(resource);
+		if (drain && readOnly) {
+			throw new Error(`Error while writing resource ${resource.getPath()}: ` +
+				"Do not use options 'drain' and 'readOnly' at the same time.");
+		}
+
+		const relPath = this._resolveVirtualPathToBase(resource.getPath(), true);
+		const fsPath = this._resolveToFileSystem(relPath);
+		const dirPath = path.dirname(fsPath);
+
+		await mkdir(dirPath, {recursive: true});
+
+		const sourceMetadata = resource.getSourceMetadata();
+		if (sourceMetadata && sourceMetadata.adapter === ADAPTER_NAME && sourceMetadata.fsPath) {
+			// Resource has been created by FileSystem adapter. This means it might require special handling
+
+			/* The following code covers these four conditions:
+				1. FS-paths not equal + Resource not modified => Shortcut: Use fs.copyFile
+				2. FS-paths equal + Resource not modified => Shortcut: Skip write altogether
+				3. FS-paths equal + Resource modified => Drain stream into buffer. Later write from buffer as usual
+				4. FS-paths not equal + Resource modified => No special handling. Write from stream or buffer
+			*/
+
+			if (sourceMetadata.fsPath !== fsPath && !sourceMetadata.contentModified) {
+				// Shortcut: fs.copyFile can be used when the resource hasn't been modified
+				log.silly(`Resource hasn't been modified. Copying resource from ${sourceMetadata.fsPath} to ${fsPath}`);
+				await copyFile(sourceMetadata.fsPath, fsPath);
+				if (readOnly) {
+					await chmod(fsPath, READ_ONLY_MODE);
+				}
+				return;
+			} else if (sourceMetadata.fsPath === fsPath && !sourceMetadata.contentModified) {
+				log.silly(
+					`Resource hasn't been modified, target path equals source path. Skipping write to ${fsPath}`);
+				if (readOnly) {
+					await chmod(fsPath, READ_ONLY_MODE);
+				}
+				return;
+			} else if (sourceMetadata.fsPath === fsPath && sourceMetadata.contentModified) {
+				// Resource has been modified. Make sure all streams are drained to prevent
+				// issues caused by piping the original read-stream into a write-stream for the same path
+				await resource.getBuffer();
+			} else {/* Different paths + modifications require no special handling */}
+		}
+
+		log.silly(`Writing to ${fsPath}`);
+
+		await new Promise((resolve, reject) => {
+			let contentStream;
+
+			if (drain || readOnly) {
+				// Stream will be drained
+				contentStream = resource.getStream();
+
+				contentStream.on("error", (err) => {
+					reject(err);
+				});
+			} else {
+				// Transform stream into buffer before writing
+				contentStream = new PassThrough();
+				const buffers = [];
+				contentStream.on("error", (err) => {
+					reject(err);
+				});
+				contentStream.on("data", (data) => {
+					buffers.push(data);
+				});
+				contentStream.on("end", () => {
+					const buffer = Buffer.concat(buffers);
+					resource.setBuffer(buffer);
+				});
+				resource.getStream().pipe(contentStream);
+			}
+
+			const writeOptions = {};
+			if (readOnly) {
+				writeOptions.mode = READ_ONLY_MODE;
+			}
+
+			const write = fs.createWriteStream(fsPath, writeOptions);
+			write.on("error", (err) => {
+				reject(err);
+			});
+			write.on("close", (ex) => {
+				resolve();
+			});
+			contentStream.pipe(write);
+		});
+
+		if (readOnly) {
+			if (sourceMetadata?.fsPath === fsPath) {
+				// When streaming into the same file, permissions need to be changed explicitly
+				await chmod(fsPath, READ_ONLY_MODE);
+			}
+
+			// In case of readOnly, we drained the stream and can now set a new callback
+			// for creating a stream from written file
+			// This should be identical to buffering the resource content in memory, since the written file
+			// can not be modified.
+			// We chose this approach to be more memory efficient in scenarios where readOnly is used
+			resource.setStream(function() {
+				return fs.createReadStream(fsPath);
+			});
+		}
+	}
+
+	_resolveToFileSystem(relPath) {
+		const fsPath = path.join(this._fsBasePath, relPath);
+
+		if (!fsPath.startsWith(this._fsBasePath)) {
+			log.verbose(`Failed to resolve virtual path internally: ${relPath}`);
+			log.verbose(`  Adapter base path: ${this._fsBasePath}`);
+			log.verbose(`  Resulting path: ${fsPath}`);
+			throw new Error(
+				`Error while resolving internal virtual path: '${relPath}' resolves ` +
+				`to a directory not accessible by this File System adapter instance`);
+		}
+		return fsPath;
+	}
+}
+
+export default FileSystem;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_adapters_Memory.js.html b/v3/api/fs_lib_adapters_Memory.js.html new file mode 100644 index 0000000000..c92fdd9f20 --- /dev/null +++ b/v3/api/fs_lib_adapters_Memory.js.html @@ -0,0 +1,273 @@ + + + + + + + fs/lib/adapters/Memory.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/adapters/Memory.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("resources:adapters:Memory");
+import micromatch from "micromatch";
+import AbstractAdapter from "./AbstractAdapter.js";
+
+const ADAPTER_NAME = "Memory";
+
+/**
+ * Virtual resource Adapter
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/adapters/Memory
+ * @extends @ui5/fs/adapters/AbstractAdapter
+ */
+class Memory extends AbstractAdapter {
+	/**
+	 * The constructor.
+	 *
+	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.virBasePath
+	 *   Virtual base path. Must be absolute, POSIX-style, and must end with a slash
+	 * @param {string[]} [parameters.excludes] List of glob patterns to exclude
+	 * @param {@ui5/project/specifications/Project} [parameters.project] Project this adapter belongs to (if any)
+	 */
+	constructor({virBasePath, project, excludes}) {
+		super({virBasePath, project, excludes});
+		this._virFiles = Object.create(null); // map full of files
+		this._virDirs = Object.create(null); // map full of directories
+	}
+
+	/**
+	 * 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.
+	 *
+	 * @private
+	 * @param {Array} patterns array of glob patterns
+	 * @param {object} [options={}] glob options
+	 * @param {boolean} [options.nodir=true] Do not match directories
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	async _runGlob(patterns, options = {nodir: true}, trace) {
+		if (patterns[0] === "" && !options.nodir) { // Match virtual root directory
+			return [
+				this._createResource({
+					project: this._project,
+					statInfo: { // TODO: make closer to fs stat info
+						isDirectory: function() {
+							return true;
+						}
+					},
+					sourceMetadata: {
+						adapter: ADAPTER_NAME
+					},
+					path: this._virBasePath.slice(0, -1)
+				})
+			];
+		}
+
+		let matchedResources = await this._matchPatterns(patterns, this._virFiles);
+
+		if (!options.nodir) {
+			const matchedDirs = await this._matchPatterns(patterns, this._virDirs);
+			matchedResources = matchedResources.concat(matchedDirs);
+		}
+
+		return matchedResources;
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing.Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
+	 */
+	async _byPath(virPath, options, trace) {
+		const relPath = this._resolveVirtualPathToBase(virPath);
+		if (relPath === null) {
+			return null;
+		}
+
+		trace.pathCall();
+
+		const resource = this._virFiles[relPath];
+
+		if (!resource || (options.nodir && resource.getStatInfo().isDirectory())) {
+			return null;
+		} else {
+			return await this._cloneResource(resource);
+		}
+	}
+
+	/**
+	 * Writes the content of a resource to a path.
+	 *
+	 * @private
+	 * @param {@ui5/fs/Resource} resource The Resource to write
+	 * @returns {Promise<undefined>} Promise resolving once data has been written
+	 */
+	async _write(resource) {
+		resource = this._migrateResource(resource);
+		if (resource instanceof Promise) {
+			// Only await if the migrate function returned a promise
+			// Otherwise await would automatically create a Promise, causing unwanted overhead
+			resource = await resource;
+		}
+		this._assignProjectToResource(resource);
+		const relPath = this._resolveVirtualPathToBase(resource.getPath(), true);
+		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
+
+		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,
+					sourceMetadata: {
+						adapter: ADAPTER_NAME
+					},
+					statInfo: { // TODO: make closer to fs stat info
+						isDirectory: function() {
+							return true;
+						}
+					},
+					path: this._virBasePath + segment
+				});
+			}
+		}
+	}
+}
+
+export default Memory;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_fsInterface.js.html b/v3/api/fs_lib_fsInterface.js.html new file mode 100644 index 0000000000..de847de2d3 --- /dev/null +++ b/v3/api/fs_lib_fsInterface.js.html @@ -0,0 +1,188 @@ + + + + + + + fs/lib/fsInterface.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/fsInterface.js

+ + + + + + + +
+
+
function toPosix(inputPath) {
+	return inputPath.replace(/\\/g, "/");
+}
+
+/**
+ * @public
+ * @module @ui5/fs/fsInterface
+ */
+
+/**
+ * Wraps readers to access them through a [Node.js fs]{@link https://nodejs.org/api/fs.html} styled interface.
+ *
+ * @public
+ * @function default
+ * @static
+ * @param {@ui5/fs/AbstractReader} reader Resource Reader or Collection
+ *
+ * @returns {object} Object with [Node.js fs]{@link https://nodejs.org/api/fs.html} styled functions
+ * [<code>readFile</code>]{@link https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback},
+ * [<code>stat</code>]{@link https://nodejs.org/api/fs.html#fs_fs_stat_path_options_callback},
+ * [<code>readdir</code>]{@link https://nodejs.org/api/fs.html#fs_fs_readdir_path_options_callback} and
+ * [<code>mkdir</code>]{@link https://nodejs.org/api/fs.html#fs_fs_mkdir_path_options_callback}
+ */
+function fsInterface(reader) {
+	return {
+		readFile(fsPath, options, callback) {
+			if (typeof options === "function") {
+				callback = options;
+				options = undefined;
+			}
+			if (typeof options === "string") {
+				options = {encoding: options};
+			}
+			const posixPath = toPosix(fsPath);
+			reader.byPath(posixPath, {
+				nodir: false
+			}).then(function(resource) {
+				if (!resource) {
+					const error = new Error(`ENOENT: no such file or directory, open '${fsPath}'`);
+					error.code = "ENOENT"; // "File or directory does not exist"
+					callback(error);
+					return;
+				}
+
+				return resource.getBuffer().then(function(buffer) {
+					let res;
+
+					if (options && options.encoding) {
+						res = buffer.toString(options.encoding);
+					} else {
+						res = buffer;
+					}
+
+					callback(null, res);
+				});
+			}).catch(callback);
+		},
+		stat(fsPath, callback) {
+			const posixPath = toPosix(fsPath);
+			reader.byPath(posixPath, {
+				nodir: false
+			}).then(function(resource) {
+				if (!resource) {
+					const error = new Error(`ENOENT: no such file or directory, stat '${fsPath}'`);
+					error.code = "ENOENT"; // "File or directory does not exist"
+					callback(error);
+				} else {
+					callback(null, resource.getStatInfo());
+				}
+			}).catch(callback);
+		},
+		readdir(fsPath, callback) {
+			let posixPath = toPosix(fsPath);
+			if (!posixPath.match(/\/$/)) {
+				// Add trailing slash if not present
+				posixPath += "/";
+			}
+			reader.byGlob(posixPath + "*", {
+				nodir: false
+			}).then((resources) => {
+				const files = resources.map((resource) => {
+					return resource.getName();
+				});
+				callback(null, files);
+			}).catch(callback);
+		},
+		mkdir(fsPath, callback) {
+			setTimeout(callback, 0);
+		}
+	};
+}
+export default fsInterface;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_readers_Filter.js.html b/v3/api/fs_lib_readers_Filter.js.html new file mode 100644 index 0000000000..8c11a61fcf --- /dev/null +++ b/v3/api/fs_lib_readers_Filter.js.html @@ -0,0 +1,171 @@ + + + + + + + fs/lib/readers/Filter.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/readers/Filter.js

+ + + + + + + +
+
+
import AbstractReader from "../AbstractReader.js";
+
+/**
+ * A reader that allows dynamic filtering of resources passed through it
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/readers/Filter
+ * @extends @ui5/fs/AbstractReader
+ */
+class Filter extends AbstractReader {
+	/**
+	* Filter callback
+	*
+	* @public
+	* @callback @ui5/fs/readers/Filter~callback
+	* @param {@ui5/fs/Resource} resource Resource to test
+	* @returns {boolean} Whether to keep the resource
+	*/
+
+	/**
+	 * Constructor
+	 *
+ 	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {@ui5/fs/AbstractReader} parameters.reader The resource reader or collection to wrap
+	 * @param {@ui5/fs/readers/Filter~callback} parameters.callback
+	 * 				Filter function. Will be called for every resource read through this reader.
+	 */
+	constructor({reader, callback}) {
+		super();
+		if (!reader) {
+			throw new Error(`Missing parameter "reader"`);
+		}
+		if (!callback) {
+			throw new Error(`Missing parameter "callback"`);
+		}
+		this._reader = reader;
+		this._callback = callback;
+	}
+
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @private
+	 * @param {string|string[]} pattern glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing/Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	async _byGlob(pattern, options, trace) {
+		const result = await this._reader._byGlob(pattern, options, trace);
+		return result.filter(this._callback);
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing/Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
+	 */
+	async _byPath(virPath, options, trace) {
+		const result = await this._reader._byPath(virPath, options, trace);
+		if (result && !this._callback(result)) {
+			return null;
+		}
+		return result;
+	}
+}
+
+export default Filter;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_readers_Link.js.html b/v3/api/fs_lib_readers_Link.js.html new file mode 100644 index 0000000000..e0a98e7fa4 --- /dev/null +++ b/v3/api/fs_lib_readers_Link.js.html @@ -0,0 +1,235 @@ + + + + + + + fs/lib/readers/Link.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/readers/Link.js

+ + + + + + + +
+
+
import AbstractReader from "../AbstractReader.js";
+import ResourceFacade from "../ResourceFacade.js";
+import {prefixGlobPattern} from "../resourceFactory.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("resources:readers:Link");
+
+/**
+ * A reader that allows for rewriting paths segments of all resources passed through it.
+ *
+ * @example
+ * import Link from "@ui5/fs/readers/Link";
+ * const linkedReader = new Link({
+ *     reader: sourceReader,
+ *     pathMapping: {
+ *          linkPath: `/app`,
+ *          targetPath: `/resources/my-app-name/`
+ *      }
+ * });
+ *
+ * // The following resolves with a @ui5/fs/ResourceFacade of the resource
+ * // located at "/resources/my-app-name/Component.js" in the sourceReader
+ * const resource = await linkedReader.byPath("/app/Component.js");
+ *
+ * @public
+ * @class
+ * @alias @ui5/fs/readers/Link
+ * @extends @ui5/fs/AbstractReader
+ */
+class Link extends AbstractReader {
+	/**
+	 * Path mapping for a [Link]{@link @ui5/fs/readers/Link}
+	 *
+	 * @public
+	 * @typedef {object} @ui5/fs/readers/Link/PathMapping
+	 * @property {string} linkPath Path to match and replace in the requested path or pattern
+	 * @property {string} targetPath Path to use as a replacement in the request for the source reader
+	 */
+
+	/**
+	 * Constructor
+	 *
+ 	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {@ui5/fs/AbstractReader} parameters.reader The resource reader or collection to wrap
+	 * @param {@ui5/fs/readers/Link/PathMapping} parameters.pathMapping
+	 */
+	constructor({reader, pathMapping}) {
+		super();
+		if (!reader) {
+			throw new Error(`Missing parameter "reader"`);
+		}
+		if (!pathMapping) {
+			throw new Error(`Missing parameter "pathMapping"`);
+		}
+		this._reader = reader;
+		this._pathMapping = pathMapping;
+		Link._validatePathMapping(pathMapping);
+	}
+
+	/**
+	 * Locates resources by glob.
+	 *
+	 * @private
+	 * @param {string|string[]} patterns glob pattern as string or an array of
+	 *         glob patterns for virtual directory structure
+	 * @param {object} options glob options
+	 * @param {@ui5/fs/tracing/Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource[]>} Promise resolving to list of resources
+	 */
+	async _byGlob(patterns, options, trace) {
+		if (!(patterns instanceof Array)) {
+			patterns = [patterns];
+		}
+		patterns = patterns.map((pattern) => {
+			if (pattern.startsWith(this._pathMapping.linkPath)) {
+				pattern = pattern.substr(this._pathMapping.linkPath.length);
+			}
+			return prefixGlobPattern(pattern, this._pathMapping.targetPath);
+		});
+
+		// Flatten prefixed patterns
+		patterns = Array.prototype.concat.apply([], patterns);
+
+		// Keep resource's internal path unchanged for now
+		const resources = await this._reader._byGlob(patterns, options, trace);
+		return resources.map((resource) => {
+			const resourcePath = resource.getPath();
+			if (resourcePath.startsWith(this._pathMapping.targetPath)) {
+				return new ResourceFacade({
+					resource,
+					path: this._pathMapping.linkPath + resourcePath.substr(this._pathMapping.targetPath.length)
+				});
+			}
+		});
+	}
+
+	/**
+	 * Locates resources by path.
+	 *
+	 * @private
+	 * @param {string} virPath Virtual path
+	 * @param {object} options Options
+	 * @param {@ui5/fs/tracing/Trace} trace Trace instance
+	 * @returns {Promise<@ui5/fs/Resource>} Promise resolving to a single resource
+	 */
+	async _byPath(virPath, options, trace) {
+		if (!virPath.startsWith(this._pathMapping.linkPath)) {
+			return null;
+		}
+		const targetPath = this._pathMapping.targetPath + virPath.substr(this._pathMapping.linkPath.length);
+		log.silly(`byPath: Rewriting virtual path ${virPath} to ${targetPath}`);
+
+		const resource = await this._reader._byPath(targetPath, options, trace);
+		if (resource) {
+			return new ResourceFacade({
+				resource,
+				path: this._pathMapping.linkPath + resource.getPath().substr(this._pathMapping.targetPath.length)
+			});
+		}
+		return null;
+	}
+
+	static _validatePathMapping({linkPath, targetPath}) {
+		if (!linkPath) {
+			throw new Error(`Path mapping is missing attribute "linkPath"`);
+		}
+		if (!targetPath) {
+			throw new Error(`Path mapping is missing attribute "targetPath"`);
+		}
+		if (!linkPath.endsWith("/")) {
+			throw new Error(`Link path must end with a slash: ${linkPath}`);
+		}
+		if (!targetPath.endsWith("/")) {
+			throw new Error(`Target path must end with a slash: ${targetPath}`);
+		}
+	}
+}
+
+export default Link;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/fs_lib_resourceFactory.js.html b/v3/api/fs_lib_resourceFactory.js.html new file mode 100644 index 0000000000..5cf55ee4c4 --- /dev/null +++ b/v3/api/fs_lib_resourceFactory.js.html @@ -0,0 +1,376 @@ + + + + + + + fs/lib/resourceFactory.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

fs/lib/resourceFactory.js

+ + + + + + + +
+
+
import path from "node:path";
+import {minimatch} from "minimatch";
+import DuplexCollection from "./DuplexCollection.js";
+import FsAdapter from "./adapters/FileSystem.js";
+import MemAdapter from "./adapters/Memory.js";
+import ReaderCollection from "./ReaderCollection.js";
+import ReaderCollectionPrioritized from "./ReaderCollectionPrioritized.js";
+import Resource from "./Resource.js";
+import WriterCollection from "./WriterCollection.js";
+import Filter from "./readers/Filter.js";
+import Link from "./readers/Link.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("resources:resourceFactory");
+
+/**
+ * @module @ui5/fs/resourceFactory
+ * @description A collection of resource related APIs
+ * @public
+ */
+
+/**
+ * Creates a resource <code>ReaderWriter</code>.
+ *
+ * If a file system base path is given, file system resource <code>ReaderWriter</code> is returned.
+ * In any other case a virtual one.
+ *
+ * @public
+ * @param {object} parameters Parameters
+ * @param {string} parameters.virBasePath Virtual base path. Must be absolute, POSIX-style, and must end with a slash
+ * @param {string} [parameters.fsBasePath]
+ *   File System base path.
+ *   If this parameter is supplied, a File System adapter will be created instead of a Memory adapter.
+ *   The provided path must be absolute and must use platform-specific path segment separators.
+ * @param {string[]} [parameters.excludes] List of glob patterns to exclude
+ * @param {object} [parameters.useGitignore=false]
+ *   Whether to apply any excludes defined in an optional .gitignore in the base directory.
+ *   This parameter only takes effect in conjunction with the <code>fsBasePath</code> parameter.
+ * @param {@ui5/project/specifications/Project} [parameters.project] Project this adapter belongs to (if any)
+ * @returns {@ui5/fs/adapters/FileSystem|@ui5/fs/adapters/Memory} File System- or Virtual Adapter
+ */
+export function createAdapter({fsBasePath, virBasePath, project, excludes, useGitignore}) {
+	if (fsBasePath) {
+		return new FsAdapter({fsBasePath, virBasePath, project, excludes, useGitignore});
+	} else {
+		return new MemAdapter({virBasePath, project, excludes});
+	}
+}
+
+/**
+ * Creates a File System adapter and wraps it in a ReaderCollection
+ *
+ * @public
+ * @param {object} parameters Parameters
+ * @param {string} parameters.virBasePath Virtual base path. Must be absolute, POSIX-style, and must end with a slash
+ * @param {string} parameters.fsBasePath
+ *   File System base path. Must be absolute and must use platform-specific path segment separators
+ * @param {object} [parameters.project] Experimental, internal parameter. Do not use
+ * @param {string[]} [parameters.excludes] List of glob patterns to exclude
+ * @param {string} [parameters.name] Name for the reader collection
+ * @returns {@ui5/fs/ReaderCollection} Reader collection wrapping an adapter
+ */
+export function createReader({fsBasePath, virBasePath, project, excludes = [], name}) {
+	if (!fsBasePath) {
+		// Creating a reader with a memory adapter seems pointless right now
+		// since there would be no way to fill the adapter with resources
+		throw new Error(`Unable to create reader: Missing parameter "fsBasePath"`);
+	}
+	let normalizedExcludes = excludes;
+	// If a project is supplied, and that project is of type application,
+	// Prefix all exclude patterns with the virtual base path (unless it already starts with that)
+	// TODO 4.0: // TODO specVersion 4.0: Disallow excludes without namespaced prefix in configuration
+	// Specifying an exclude for "/test" is disambigous as it neither reflects the source path nor the
+	// ui5 runtime path of the excluded resources. Therefore, only allow paths like /resources/<namespace>/test
+	// starting with specVersion 4.0
+	if (excludes.length && project && project.getType() === "application") {
+		normalizedExcludes = excludes.map((pattern) => {
+			if (pattern.startsWith(virBasePath) || pattern.startsWith("!" + virBasePath)) {
+				return pattern;
+			}
+			log.verbose(
+				`Prefixing exclude pattern defined in application project ${project.getName()}: ${pattern}`);
+			return prefixGlobPattern(pattern, virBasePath);
+		});
+		// Flatten list of patterns
+		normalizedExcludes = Array.prototype.concat.apply([], normalizedExcludes);
+		log.verbose(`Effective exclude patterns for application project ${project.getName()}:\n` +
+			normalizedExcludes.join(", "));
+	}
+	return new ReaderCollection({
+		name,
+		readers: [createAdapter({
+			fsBasePath,
+			virBasePath,
+			project,
+			excludes: normalizedExcludes
+		})]
+	});
+}
+
+/**
+ * Creates a ReaderCollection
+ *
+ * @public
+ * @param {object} parameters Parameters
+ * @param {string} parameters.name The collection name
+ * @param {@ui5/fs/AbstractReader[]} parameters.readers List of resource readers (all tried in parallel)
+ * @returns {@ui5/fs/ReaderCollection} Reader collection wrapping provided readers
+ */
+export function createReaderCollection({name, readers}) {
+	return new ReaderCollection({
+		name,
+		readers
+	});
+}
+
+/**
+ * Creates a ReaderCollectionPrioritized
+ *
+ * @public
+ * @param {object} parameters
+ * @param {string} parameters.name The collection name
+ * @param {@ui5/fs/AbstractReader[]} parameters.readers Prioritized list of resource readers
+ * 																(first is tried first)
+ * @returns {@ui5/fs/ReaderCollectionPrioritized} Reader collection wrapping provided readers
+ */
+export function createReaderCollectionPrioritized({name, readers}) {
+	return new ReaderCollectionPrioritized({
+		name,
+		readers
+	});
+}
+
+/**
+ * Creates a WriterCollection
+ *
+ * @public
+ * @param {object} parameters
+ * @param {string} parameters.name The collection name
+ * @param {object.<string, @ui5/fs/AbstractReaderWriter>} parameters.writerMapping Mapping of virtual base
+ * 	paths to writers. Path are matched greedy
+ * @returns {@ui5/fs/WriterCollection} Writer collection wrapping provided writers
+ */
+export function createWriterCollection({name, writerMapping}) {
+	return new WriterCollection({
+		name,
+		writerMapping
+	});
+}
+
+/**
+ * Creates a [Resource]{@link @ui5/fs/Resource}.
+ * Accepts the same parameters as the [Resource]{@link @ui5/fs/Resource} constructor.
+ *
+ * @public
+ * @param {object} parameters Parameters to be passed to the resource constructor
+ * @returns {@ui5/fs/Resource} Resource
+ */
+export function createResource(parameters) {
+	return new Resource(parameters);
+}
+
+/**
+ * Creates a Workspace
+ *
+ * A workspace is a DuplexCollection which reads from the project sources. It is used during the build process
+ * to write modified files into a separate writer, this is usually a Memory adapter. If a file already exists it is
+ * fetched from the memory to work on it in further build steps.
+ *
+ * @public
+ * @param {object} parameters
+ * @param {@ui5/fs/AbstractReader} parameters.reader Single reader or collection of readers
+ * @param {@ui5/fs/AbstractReaderWriter} [parameters.writer] A ReaderWriter instance which is
+ *        only used for writing files. If not supplied, a Memory adapter will be created.
+ * @param {string} [parameters.name="workspace"] Name of the collection
+ * @param {string} [parameters.virBasePath="/"] Virtual base path
+ * @returns {@ui5/fs/DuplexCollection} DuplexCollection which wraps the provided resource locators
+ */
+export function createWorkspace({reader, writer, virBasePath = "/", name = "workspace"}) {
+	if (!writer) {
+		writer = new MemAdapter({
+			virBasePath
+		});
+	}
+
+	return new DuplexCollection({
+		reader,
+		writer,
+		name
+	});
+}
+
+/**
+ * Create a [Filter-Reader]{@link @ui5/fs/readers/Filter} with the given reader.
+ * The provided callback is called for every resource that is retrieved through the
+ * reader and decides whether the resource shall be passed on or dropped.
+ *
+ * @public
+ * @param {object} parameters
+ * @param {@ui5/fs/AbstractReader} parameters.reader Single reader or collection of readers
+ * @param {@ui5/fs/readers/Filter~callback} parameters.callback
+ * 				Filter function. Will be called for every resource passed through this reader.
+ * @returns {@ui5/fs/readers/Filter} Reader instance
+ */
+export function createFilterReader(parameters) {
+	return new Filter(parameters);
+}
+
+/**
+ * Create a [Link-Reader]{@link @ui5/fs/readers/Filter} with the given reader.
+ * The provided path mapping allows for rewriting paths segments of all resources passed through it.
+ *
+ * @example
+ * import {createLinkReader} from "@ui5/fs/resourceFactory";
+ * const linkedReader = createLinkReader({
+ *     reader: sourceReader,
+ *     pathMapping: {
+ *          linkPath: `/app`,
+ *          targetPath: `/resources/my-app-name/`
+ *      }
+ * });
+ *
+ * // The following resolves with a @ui5/fs/ResourceFacade of the resource
+ * // located at "/resources/my-app-name/Component.js" in the sourceReader
+ * const resource = await linkedReader.byPath("/app/Component.js");
+ *
+ * @public
+ * @param {object} parameters
+ * @param {@ui5/fs/AbstractReader} parameters.reader Single reader or collection of readers
+ * @param {@ui5/fs/readers/Link/PathMapping} parameters.pathMapping
+ * @returns {@ui5/fs/readers/Link} Reader instance
+ */
+export function createLinkReader(parameters) {
+	return new Link(parameters);
+}
+
+/**
+ * Create a [Link-Reader]{@link @ui5/fs/readers/Link} where all requests are prefixed with
+ * <code>/resources/<namespace></code>.
+ *
+ * This simulates "flat" resource access, which is for example common for projects of type
+ * "application".
+ *
+ * @public
+ * @param {object} parameters
+ * @param {@ui5/fs/AbstractReader} parameters.reader Single reader or collection of readers
+ * @param {string} parameters.namespace Project namespace
+ * @returns {@ui5/fs/readers/Link} Reader instance
+ */
+export function createFlatReader({reader, namespace}) {
+	return new Link({
+		reader: reader,
+		pathMapping: {
+			linkPath: `/`,
+			targetPath: `/resources/${namespace}/`
+		}
+	});
+}
+
+/**
+ * Normalizes virtual glob patterns by prefixing them with
+ * a given virtual base directory path
+ *
+ * @param {string} virPattern glob pattern for virtual directory structure
+ * @param {string} virBaseDir virtual base directory path to prefix the given patterns with
+ * @returns {string[]} A list of normalized glob patterns
+ */
+export function prefixGlobPattern(virPattern, virBaseDir) {
+	const mm = new minimatch.Minimatch(virPattern);
+
+	const resultGlobs = [];
+	for (let i = 0; i < mm.globSet.length; i++) {
+		let resultPattern = path.posix.join(virBaseDir, mm.globSet[i]);
+
+		if (mm.negate) {
+			resultPattern = "!" + resultPattern;
+		}
+		resultGlobs.push(resultPattern);
+	}
+	return resultGlobs;
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/global.html b/v3/api/global.html new file mode 100644 index 0000000000..88c8a74813 --- /dev/null +++ b/v3/api/global.html @@ -0,0 +1,336 @@ + + + + + + Global - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Global

+ + + + + + + +
+ +
+ +

+ + + +

+ + +
+ +
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +

Type Definitions

+ + + +

@ui5/fs/readers/Link/PathMapping

+ + + + + +
+ +
Description:
+
  • Path mapping for a Link
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
linkPath + + +string + + + + + Path to match and replace in the requested path or pattern
targetPath + + +string + + + + + Path to use as a replacement in the request for the source reader
+ + + + + + +
+ Path mapping for a Link +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/index.html b/v3/api/index.html new file mode 100644 index 0000000000..dcfc4647d0 --- /dev/null +++ b/v3/api/index.html @@ -0,0 +1,100 @@ + + + + + + Home - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + +
+ +
+ + + + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/logger_lib_index.js.html b/v3/api/logger_lib_index.js.html new file mode 100644 index 0000000000..7746cbf295 --- /dev/null +++ b/v3/api/logger_lib_index.js.html @@ -0,0 +1,147 @@ + + + + + + + logger/lib/index.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

logger/lib/index.js

+ + + + + + + +
+
+
import Logger from "./loggers/Logger.js";
+
+/**
+ * Interface for the UI5 Tooling logging module
+ *
+ * @public
+ * @module @ui5/logger
+ */
+
+/**
+ * Convenience function to create an instance of [@ui5/logger/Logger]{@link @ui5/logger/Logger}
+ *
+ * @public
+ * @param {string} moduleName Identifier for messages created by the logger.
+ * Example: <code>module:submodule:Class</code>
+ * @returns {@ui5/logger/Logger}
+ */
+export function getLogger(moduleName) {
+	return new Logger(moduleName);
+}
+
+/**
+ * Tests whether the provided log level is enabled by the current log level
+ *
+ * @public
+ * @function
+ * @param {string} levelName Log level to test
+ * @returns {boolean} True if the provided level is enabled
+ */
+export const isLogLevelEnabled = Logger.isLevelEnabled;
+
+/**
+ * Sets the standard log level.
+ * <br>
+ * <b>Example:</b> Setting it to <code>perf</code> would suppress all <code>silly</code> and <code>verbose</code>
+ * logging, and only show <code>perf</code>, <code>info</code>, <code>warn</code> and <code>error</code> logs.
+ *
+ * @public
+ * @function
+ * @param {string} levelName New log level
+ */
+export const setLogLevel = Logger.setLevel;
+
+/**
+ * Gets the current log level
+ *
+ * @public
+ * @function
+ * @returns {string} The current log level. Defaults to <code>info</code>
+ */
+export const getLogLevel = Logger.getLevel;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/logger_lib_loggers_Logger.js.html b/v3/api/logger_lib_loggers_Logger.js.html new file mode 100644 index 0000000000..e4db57da85 --- /dev/null +++ b/v3/api/logger_lib_loggers_Logger.js.html @@ -0,0 +1,336 @@ + + + + + + + logger/lib/loggers/Logger.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

logger/lib/loggers/Logger.js

+ + + + + + + +
+
+
import process from "node:process";
+import {inspect} from "node:util";
+
+// Module name must not contain any other characters than alphanumerical and some specials
+const rIllegalModuleNameChars = /[^0-9a-zA-Z-_:@./]/i;
+
+/**
+ * Standard logging module for UI5 Tooling and extensions.
+ * <br><br>
+ * Emits <code>ui5.log</code> events on the [<code>process</code>]{@link https://nodejs.org/api/process.html} object,
+ * which can be handled by dedicated writers,
+ * like [@ui5/logger/writers/Console]{@link @ui5/logger/writers/Console}.
+ * <br><br>
+ * If no listener is attached to an event, messages are written directly to the <code>process.stderr</code> stream.
+ *
+ * @public
+ * @class
+ * @alias @ui5/logger/Logger
+ */
+class Logger {
+	/**
+	 * Available log levels, ordered by priority:
+	 * <br>
+	 * <ol>
+	 *   <li>silly</li>
+	 *   <li>verbose</li>
+	 *   <li>perf</li>
+	 *   <li>info <i>(default)</i></li>
+	 *   <li>warn</li>
+	 *   <li>error</li>
+	 *   <li>silent</li>
+	 * </ol>
+	 *
+	 * Log level <code>silent</code> is special in the sense that no messages can be submitted with that level.
+	 * It can be used to suppress all logging.
+	 *
+	 * @member {string[]}
+	 * @public
+	*/
+	static LOG_LEVELS = ["silly", "verbose", "perf", "info", "warn", "error", "silent"];
+
+	/**
+	 * Event name used for emitting new log-message event on the
+	 * [<code>process</code>]{@link https://nodejs.org/api/process.html} object
+	 *
+	 * @member {string}
+	 * @public
+	*/
+	static LOG_EVENT_NAME = "ui5.log";
+
+	/**
+	 * Sets the standard log level.
+	 * <br>
+	 * <b>Example:</b> Setting it to <code>perf</code> would suppress all <code>silly</code> and <code>verbose</code>
+	 * logging, and only show <code>perf</code>, <code>info</code>, <code>warn</code> and <code>error</code> logs.
+	 *
+	 * @public
+	 * @param {string} levelName New log level
+	 */
+	static setLevel(levelName) {
+		process.env.UI5_LOG_LVL = levelName;
+	}
+
+	/**
+	 * Gets the current log level
+	 *
+	 * @public
+	 * @returns {string} The current log level. Defaults to <code>info</code>
+	 */
+	static getLevel() {
+		if (process.env.UI5_LOG_LVL) {
+			// Check whether set log level is valid
+			const levelName = process.env.UI5_LOG_LVL;
+			if (!Logger.LOG_LEVELS.includes(levelName)) {
+				throw new Error(
+					`UI5 Logger: Environment variable UI5_LOG_LVL is set to an unknown log level "${levelName}". ` +
+					`Valid levels are ${Logger.LOG_LEVELS.join(", ")}`);
+			}
+			return levelName;
+		} else {
+			return "info";
+		}
+	}
+
+	/**
+	 * Tests whether the provided log level is enabled by the current log level
+	 *
+	 * @public
+	 * @param {string} levelName Log level to test
+	 * @returns {boolean} True if the provided level is enabled
+	 */
+	static isLevelEnabled(levelName) {
+		const currIdx = Logger.LOG_LEVELS.indexOf(Logger.getLevel());
+		const reqIdx = Logger.LOG_LEVELS.indexOf(levelName);
+		if (reqIdx === -1) {
+			throw new Error(`Unknown log level "${levelName}"`);
+		}
+		return reqIdx >= currIdx;
+	}
+
+	/**
+	 * Formats a given parameter into a string
+	 *
+	 * @param {any} message Single log message parameter passed by a program
+	 * @returns {string} String representation for the given message
+	 */
+	static _formatMessage(message) {
+		if (typeof message === "string" || message instanceof String) {
+			return message;
+		}
+		return inspect(message, {
+			depth: 3,
+			compact: 2,
+		});
+	}
+
+	#moduleName;
+
+	/**
+	 *
+	 *
+	 * @public
+	 * @param {string} moduleName Identifier for messages created by this logger.
+	 * Example: <code>module:submodule:Class</code>
+	 */
+	constructor(moduleName) {
+		if (!moduleName) {
+			throw new Error("Logger: Missing moduleName parameter");
+		}
+		if (rIllegalModuleNameChars.test(moduleName)) {
+			throw new Error(`Logger: Invalid module name: ${moduleName}`);
+		}
+		this.#moduleName = moduleName;
+	}
+
+	/**
+	 * Tests whether the provided log level is enabled by the current log level
+	 *
+	 * @public
+	 * @param {string} levelName Log level to test
+	 * @returns {boolean} True if the provided level is enabled
+	 */
+	isLevelEnabled(levelName) {
+		return Logger.isLevelEnabled(levelName);
+	}
+
+	_emit(eventName, payload) {
+		return process.emit(eventName, payload);
+	}
+
+	_log(level, message) {
+		if (this.isLevelEnabled(level)) {
+			process.stderr.write(`[${level}] ${message}\n`);
+		}
+	}
+
+	_emitOrLog(level, message) {
+		const hasListeners = this._emit(Logger.LOG_EVENT_NAME, {
+			level,
+			message,
+			moduleName: this.#moduleName,
+		});
+		if (!hasListeners) {
+			this._log(level, `${this.#moduleName}: ${message}`);
+		}
+	}
+}
+
+/**
+ * Create a log entry with the <code>silly</code> level
+ *
+ * @public
+ * @name @ui5/logger/Logger#silly
+ * @function
+ * @memberof @ui5/logger/Logger
+ * @param {...any} message Messages to log. An automatic string conversion is applied if necessary
+ */
+
+/**
+ * Create a log entry with the <code>verbose</code> level
+ *
+ * @public
+ * @name @ui5/logger/Logger#verbose
+ * @function
+ * @memberof @ui5/logger/Logger
+ * @param {...any} message Messages to log. An automatic string conversion is applied if necessary
+ */
+
+/**
+ * Create a log entry with the <code>perf</code> level
+ *
+ * @public
+ * @name @ui5/logger/Logger#perf
+ * @function
+ * @memberof @ui5/logger/Logger
+ * @param {...any} message Messages to log. An automatic string conversion is applied if necessary
+ */
+
+/**
+ * Create a log entry with the <code>info</code> level
+ *
+ * @public
+ * @name @ui5/logger/Logger#info
+ * @function
+ * @memberof @ui5/logger/Logger
+ * @param {...any} message Messages to log. An automatic string conversion is applied if necessary
+ */
+
+/**
+ * Create a log entry with the <code>warn</code> level
+ *
+ * @public
+ * @name @ui5/logger/Logger#warn
+ * @function
+ * @memberof @ui5/logger/Logger
+ * @param {...any} message Messages to log. An automatic string conversion is applied if necessary
+ */
+
+/**
+ * Create a log entry with the <code>error</code> level
+ *
+ * @public
+ * @name @ui5/logger/Logger#error
+ * @function
+ * @memberof @ui5/logger/Logger
+ * @param {...any} message Messages to log. An automatic string conversion is applied if necessary
+ */
+
+Logger.LOG_LEVELS.forEach((logLevel) => {
+	if (logLevel === "silent") {
+		// This level is to suppress any logging. Hence we do not provide a dedicated log-function
+		return;
+	}
+	Logger.prototype[logLevel] = function(...args) {
+		const message = args.map(Logger._formatMessage).join(" ");
+		this._emitOrLog(logLevel, message);
+	};
+});
+
+export default Logger;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/logger_lib_writers_Console.js.html b/v3/api/logger_lib_writers_Console.js.html new file mode 100644 index 0000000000..6378a94423 --- /dev/null +++ b/v3/api/logger_lib_writers_Console.js.html @@ -0,0 +1,474 @@ + + + + + + + logger/lib/writers/Console.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

logger/lib/writers/Console.js

+ + + + + + + +
+
+
import process from "node:process";
+import {chalkStderr as chalk} from "chalk";
+import figures from "figures";
+import {MultiBar} from "cli-progress";
+import Logger from "../loggers/Logger.js";
+
+/**
+ * Standard handler for events emitted by @ui5/logger modules. Writes messages to
+ * [<code>process.stderr</code>]{@link https://nodejs.org/api/process.html#processstderr} stream
+ * and renders a progress bar for UI5 Tooling build processes.
+ * <br><br>
+ * The progress bar is only used in interactive terminals. If verbose logging is enabled, the progress
+ * bar is disabled.
+ *
+ * @public
+ * @class
+ * @alias @ui5/logger/writers/Console
+ */
+class Console {
+	#projectMetadata = new Map();
+	#progressBarContainer;
+	#progressBar;
+	#progressProjectWeight;
+
+	constructor() {
+		this._handleLogEvent = this.#handleLogEvent.bind(this);
+		this._handleBuildStatusEvent = this.#handleBuildStatusEvent.bind(this);
+		this._handleProjectBuildStatusEvent = this.#handleProjectBuildStatusEvent.bind(this);
+		this._handleBuildMetadataEvent = this.#handleBuildMetadataEvent.bind(this);
+		this._handleProjectBuildMetadataEvent = this.#handleProjectBuildMetadataEvent.bind(this);
+		this._handleStop = this.disable.bind(this);
+	}
+
+	/**
+	 * Attaches all event listeners and starts writing to output stream
+	 *
+	 * @public
+	 */
+	enable() {
+		process.on("ui5.log", this._handleLogEvent);
+		process.on("ui5.build-metadata", this._handleBuildMetadataEvent);
+		process.on("ui5.project-build-metadata", this._handleProjectBuildMetadataEvent);
+		process.on("ui5.build-status", this._handleBuildStatusEvent);
+		process.on("ui5.project-build-status", this._handleProjectBuildStatusEvent);
+		process.on("ui5.log.stop-console", this._handleStop);
+	}
+
+	/**
+	 * Detaches all event listeners and stops writing to output stream
+	 *
+	 * @public
+	 */
+	disable() {
+		process.off("ui5.log", this._handleLogEvent);
+		process.off("ui5.build-metadata", this._handleBuildMetadataEvent);
+		process.off("ui5.project-build-metadata", this._handleProjectBuildMetadataEvent);
+		process.off("ui5.build-status", this._handleBuildStatusEvent);
+		process.off("ui5.project-build-status", this._handleProjectBuildStatusEvent);
+		process.off("ui5.log.stop-console", this._handleStop);
+		if (this.#progressBarContainer) {
+			this.#progressBar.stop();
+			this.#progressBarContainer.stop(); // Will fire internal stop event
+		}
+	}
+
+	/*
+	 * Progress bar is only required when building projects. So we create it lazily
+	 */
+	_getProgressBar() {
+		// Do not use a progress bar if there is no text terminal attached or verbose logging is enabled
+		// * If log output is piped to a static output (= no TTY), no progress bar should be rendered
+		// * Since logging through the progress bar is asynchronous (controlled by the FPS setting),
+		//   exceptions might lead to log messages being dropped. Therefore do not use a progress bar
+		//   for verbose logging
+		// * If log-level is set to "silent", we should never render a progress bar
+		if (process.stderr.isTTY !== true || Logger.isLevelEnabled("verbose") || Logger.getLevel() === "silent") {
+			return null;
+		}
+		if (!this.#progressBarContainer) {
+			// We use a "MultiBar" instance even though we intend to only render a single progress bar
+			// This is because only MultiBar provides a "log" method as of today
+			this.#progressBarContainer = new MultiBar({
+				format: `{bar} {message}`,
+				barsize: 20,
+				linewrap: true,
+				emptyOnZero: 0,
+				hideCursor: true,
+
+				// FPS also controls how fast a log message will be rendered above the progress bar
+				fps: 120,
+
+				// Disable progress bar explicitly for non-TTY, even though this is already checked above
+				noTTYOutput: false,
+
+				// Graceful exit is required to ensure all terminal settings (e.g. hideCursor)
+				// are restored on SIGINT
+				gracefulExit: true,
+
+				// Required to prevent flickering when logging
+				forceRedraw: true,
+
+				clearOnComplete: true,
+				stopOnComplete: true,
+
+				barCompleteChar: figures.square,
+				barIncompleteChar: figures.squareLightShade,
+			});
+
+			// Initialize empty progress bar to enable logging through the multibar instance
+			this.#progressBar = this.#progressBarContainer.create(0, 0, {message: ""});
+
+			this.#progressBarContainer.on("stop", () => {
+				// Progress bar has finished and will remove itself from the output.
+				// Therefore, further logging needs to be done directly to process.stderr. Otherwise it would disappear.
+				// Therefore, we de-reference all instances now
+				this.#progressBarContainer = null;
+				this.#progressBar = null;
+			});
+		}
+		return this.#progressBar;
+	}
+
+	#writeMessage(level, message) {
+		if (!Logger.isLevelEnabled(level)) {
+			return;
+		}
+		const levelPrefix = this.#getLevelPrefix(level);
+		const msg = `${levelPrefix} ${message}\n`;
+
+		if (this.#progressBarContainer) {
+			// If a progress bar is in use, we have to log through it's API
+			// cli-progress requires full control of the stderr output to ensure correct rendering
+			this.#progressBarContainer.log(msg);
+		} else {
+			process.stderr.write(msg);
+		}
+	}
+
+	#handleLogEvent({level, message, moduleName}) {
+		this.#writeMessage(level, `${chalk.blue(moduleName)} ${message}`);
+	}
+
+	#handleBuildMetadataEvent({projectsToBuild}) {
+		projectsToBuild.forEach((projectName) => {
+			this.#projectMetadata.set(projectName, {
+				buildStarted: false,
+				buildSkipped: false,
+				buildEnded: false,
+				buildStartIndex: null,
+				projectTasks: new Map(),
+			});
+		});
+		this.#updateProgressBarTotal();
+	}
+
+	#handleProjectBuildMetadataEvent({tasksToRun, projectName, projectType}) {
+		const projectMetadata = this.#getProjectMetadata(projectName);
+		tasksToRun.forEach((taskName) => {
+			projectMetadata.projectTasks.set(taskName, {
+				executionStarted: false,
+				executionEnded: false,
+				executionStartIndex: null,
+			});
+		});
+		this.#updateProgressBarTotal();
+	}
+
+	#getProjectMetadata(projectName) {
+		const projectMetadata = this.#projectMetadata.get(projectName);
+		if (!projectMetadata) {
+			throw new Error(`writers/Console: Unknown project ${projectName}`);
+		}
+		return projectMetadata;
+	}
+
+	#updateProgressBarTotal() {
+		let numberOfTasks = 0;
+		this.#projectMetadata.forEach(({projectTasks}) => {
+			numberOfTasks += projectTasks.size;
+		});
+
+		// Project progress should weigh more than single task progress
+		// This is proportional to the number of projects (since that also multiplies the number of tasks)
+		this.#progressProjectWeight = this.#projectMetadata.size;
+		this._getProgressBar()?.setTotal(
+			(this.#progressProjectWeight * this.#projectMetadata.size) + numberOfTasks);
+	}
+
+	#handleBuildStatusEvent({level, projectName, projectType, status}) {
+		const projectMetadata = this.#getProjectMetadata(projectName);
+		if (projectMetadata.buildStartIndex === null) {
+			let nextIdx = 1;
+			this.#projectMetadata.forEach((metadata) => {
+				if (metadata.buildStartIndex !== null && metadata.buildStartIndex >= nextIdx) {
+					nextIdx = metadata.buildStartIndex + 1;
+				}
+			});
+			projectMetadata.buildStartIndex = nextIdx;
+		}
+		const buildIndex = `Project ${projectMetadata.buildStartIndex} of ${this.#projectMetadata.size}`;
+
+		let message;
+		switch (status) {
+		case "project-build-start":
+			if (projectMetadata.buildEnded) {
+				throw new Error(
+					`writers/Console: Unexpected project-build-start event for project ${projectName}. ` +
+					`Project build already ended`);
+			}
+			if (projectMetadata.buildStarted) {
+				throw new Error(
+					`writers/Console: Unexpected duplicate project-build-start event for project ${projectName}`);
+			}
+			if (projectMetadata.buildSkipped) {
+				throw new Error(
+					`writers/Console: Unexpected project-build-start event for project ${projectName}. ` +
+					`Project build already skipped`);
+			}
+			projectMetadata.buildStarted = true;
+			message = `${chalk.blue(figures.pointer)} ` +
+				`Building ${projectType} project ${chalk.bold(projectName)}...`;
+
+			// Update progress bar message with current project
+			this._getProgressBar()?.update({
+				message: `${figures.pointer} Building ${projectType} project ${projectName}...`
+			});
+			break;
+		case "project-build-end":
+			if (projectMetadata.buildEnded) {
+				throw new Error(
+					`writers/Console: Unexpected duplicate project-build-end event for project ${projectName}`);
+			}
+			if (projectMetadata.buildSkipped) {
+				throw new Error(
+					`writers/Console: Unexpected project-build-end event for project ${projectName}. ` +
+					`Project build already skipped`);
+			}
+			if (!projectMetadata.buildStarted) {
+				throw new Error(
+					`writers/Console: Unexpected project-build-end event for project ${projectName}. ` +
+					`No corresponding project-build-start event handled`);
+			}
+			projectMetadata.buildEnded = true;
+			message = `${chalk.green(figures.tick)} ` +
+				`Finished building ${projectType} project ${chalk.bold(projectName)}`;
+
+			// Update progress bar (if used)
+			this._getProgressBar()?.increment(this.#progressProjectWeight);
+			break;
+		case "project-build-skip":
+			if (projectMetadata.buildSkipped) {
+				throw new Error(
+					`writers/Console: Unexpected duplicate project-build-skip event for project ${projectName}`);
+			}
+			if (projectMetadata.buildEnded) {
+				throw new Error(
+					`writers/Console: Unexpected project-build-skip event for project ${projectName}. ` +
+					`Project build already ended`);
+			}
+			if (projectMetadata.buildStarted) {
+				throw new Error(
+					`writers/Console: Unexpected project-build-skip event for project ${projectName}. ` +
+					`Project build already started`);
+			}
+			projectMetadata.buildSkipped = true;
+			message = `${chalk.yellow(figures.tick)} ` +
+				`Skipping build of ${projectType} project ${chalk.bold(projectName)}`;
+
+			// Update progress bar (if used)
+			// All tasks of this projects are completed
+			this._getProgressBar()?.increment(this.#progressProjectWeight + projectMetadata.projectTasks.size);
+			break;
+		default:
+			this.#writeMessage("verbose",
+				`writers/Console: Received unknown build-status ${status} for project ${projectName}`);
+			return;
+		}
+
+		this.#writeMessage(level, `${chalk.grey(buildIndex)}: ${message}`);
+	}
+
+	#handleProjectBuildStatusEvent({level, projectName, projectType, taskName, status}) {
+		const {projectTasks} = this.#getProjectMetadata(projectName);
+		const taskMetadata = projectTasks.get(taskName);
+		if (!taskMetadata) {
+			throw new Error(`writers/Console: Unknown task ${taskName} for project ${projectName}`);
+		}
+		if (taskMetadata.executionStartIndex === null) {
+			let nextIdx = 1;
+			projectTasks.forEach((metadata) => {
+				if (metadata.executionStartIndex !== null && metadata.executionStartIndex >= nextIdx) {
+					nextIdx = metadata.executionStartIndex + 1;
+				}
+			});
+			taskMetadata.executionStartIndex = nextIdx;
+		}
+		let taskIndex = "";
+		if (Logger.isLevelEnabled("verbose")) {
+			taskIndex = chalk.grey(`Task ${taskMetadata.executionStartIndex} of ${projectTasks.size} `);
+		}
+
+		let message;
+		switch (status) {
+		case "task-start":
+			if (taskMetadata.executionEnded) {
+				throw new Error(
+					`writers/Console: Unexpected task-start event for project ${projectName}, task ${taskName}. ` +
+					`Task execution already ended`);
+			}
+			if (taskMetadata.executionStarted) {
+				throw new Error(`writers/Console: Unexpected duplicate task-start event ` +
+					`for project ${projectName}, task ${taskName}`);
+			}
+			taskMetadata.executionStarted = true;
+			message = `${chalk.blue(figures.pointerSmall)} Running task ${chalk.bold(taskName)}...`;
+			break;
+		case "task-end":
+			if (taskMetadata.executionEnded) {
+				throw new Error(`writers/Console: ` +
+					`Unexpected duplicate task-end event for project ${projectName}, task ${taskName}`);
+			}
+			if (!taskMetadata.executionStarted) {
+				throw new Error(
+					`writers/Console: Unexpected task-end event for project ${projectName}, task ${taskName}. ` +
+					`No corresponding task-start event handled`);
+			}
+			taskMetadata.executionEnded = true;
+			message = `${chalk.green(figures.tick)} Finished task ${chalk.bold(taskName)}`;
+
+			// Update progress bar (if used)
+			this._getProgressBar()?.increment(1);
+			break;
+		default:
+			this.#writeMessage("verbose",
+				`writers/Console: Received unknown project-build-status ${status} for project ${projectName}`);
+			return;
+		}
+
+		this.#writeMessage(level, `${chalk.blue(`${(projectName)}`)} ${taskIndex}${message}`);
+	}
+
+	#getLevelPrefix(level) {
+		switch (level) {
+		case "silly":
+			return chalk.inverse(level);
+		case "verbose":
+			return chalk.cyan("verb");
+		case "perf":
+			return chalk.bgYellow.red(level);
+		case "info":
+			return chalk.green(level);
+		case "warn":
+			return chalk.yellow(level);
+		case "error":
+			return chalk.bgRed.white(level);
+		// Log level silent does not produce messages
+		default:
+			return level;
+		}
+	}
+
+	/**
+	 * Creates a new instance and subscribes it to all events
+	 *
+	 * @public
+	 */
+	static init() {
+		const cH = new Console();
+		cH.enable();
+		return cH;
+	}
+
+	static stop() {
+		process.emit("ui5.log.stop-console");
+	}
+}
+
+export default Console;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/module-@ui5_builder_processors_ThemeBuilder.ThemeBuilder.html b/v3/api/module-@ui5_builder_processors_ThemeBuilder.ThemeBuilder.html new file mode 100644 index 0000000000..7f2eaee5f7 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_ThemeBuilder.ThemeBuilder.html @@ -0,0 +1,682 @@ + + + + + + ThemeBuilder - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

ThemeBuilder

+ + + + + + + +
+ +
+ +

+ @ui5/builder/processors/ThemeBuilder. + + + ThemeBuilder + +

+ +
Builds a library theme
+ + +
+ +
+ +
+ + + + +

Constructor

+ + +

new ThemeBuilder(fs)

+ + + + + + +
+ +
Description:
+
  • Constructor
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
fs + + +fs +| + +module:@ui5/fs/fsInterface + + + + + Node fs or custom + fs interface
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

build(resources, optionsopt) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Starts the theme build
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + + + + + + + Library files
options + + +object + + + + + + + <optional>
+ + + + + +
Build options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
compress + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Compress build output (CSS / JSON)
cssVariables + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Generates the CSS variables + (css-variables.css, css-variables.source.less) and the skeleton for a theme + (library-skeleton.css, [library-skeleton-RTL.css])
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Resolving with array of created files +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

clearCache()

+ + + + + + +
+ +
Description:
+
  • Clears all cached build results. + +Use this method to prevent high memory consumption when building many themes within the same process.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_ThemeBuilder.html b/v3/api/module-@ui5_builder_processors_ThemeBuilder.html new file mode 100644 index 0000000000..4877669022 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_ThemeBuilder.html @@ -0,0 +1,661 @@ + + + + + + @ui5/builder/processors/ThemeBuilder - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/ThemeBuilder

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + +

Classes

+ +
+
ThemeBuilder
+
+
+ + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Builds a library theme.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + + + + + + + List of library.source.less + resources to be processed
fs + + +fs +| + +module:@ui5/fs/fsInterface + + + + + + + + + + + Node fs or custom + fs interface
options + + +module:@ui5/builder/processors/ThemeBuilder~ThemeBuilderOptions + + + + + + + <optional>
+ + + + + +
Options
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with theme resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

ThemeBuilderOptions

+ + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
compress + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Compress build output (CSS / JSON)
cssVariables + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Generates the CSS variables +(css-variables.css, css-variables.source.less) and the skeleton for a theme +(library-skeleton.css, [library-skeleton-RTL.css])
+ + + + + + + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_bundlers_flexChangesBundler.html b/v3/api/module-@ui5_builder_processors_bundlers_flexChangesBundler.html new file mode 100644 index 0000000000..76d5321e5d --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_bundlers_flexChangesBundler.html @@ -0,0 +1,486 @@ + + + + + + @ui5/builder/processors/bundlers/flexChangesBundler - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/bundlers/flexChangesBundler

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Bundles all supplied changes.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + List of resources to be processed
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pathPrefix + + +string + + + + + Prefix for bundle path
hasFlexBundleVersion + + +string + + + + + true if minUI5Version >= 1.73 than + create flexibility-bundle.json
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with flex changes bundle resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_bundlers_moduleBundler.html b/v3/api/module-@ui5_builder_processors_bundlers_moduleBundler.html new file mode 100644 index 0000000000..df0cdb7e75 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_bundlers_moduleBundler.html @@ -0,0 +1,1760 @@ + + + + + + @ui5/builder/processors/bundlers/moduleBundler - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/bundlers/moduleBundler

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundlerResult>>}

+ + + + + + +
+ +
Description:
+
  • Legacy module bundler.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + Resources
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
moduleNameMapping + + +object + + + + + + + <optional>
+ + + + + +
Optional mapping of resource paths to module name in order to overwrite the default determination
bundleDefinition + + +module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition + + + + + + + + + + + Module + bundle definition
bundleOptions + + +module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleOptions + + + + + + + <optional>
+ + + + + +
Module + bundle options
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with module bundle resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundlerResult>> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

ModuleBundleDefinition

+ + + + + +
+ +
Description:
+
  • Module bundle definition
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
name + + +string + + + + + + + + + + + The module bundle name
defaultFileTypes + + +Array.<string> + + + + + + + <optional>
+ + + +
+ + [".js", ".control.xml", ".fragment.html", ".fragment.json", ".fragment.xml", ".view.html", ".view.json", ".view.xml"] + + List of default file types to be included in the bundle
sections + + +Array.<module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinitionSection> + + + + + + + + + + + List of module bundle definition sections.
+ + + + + + +
+ Module bundle definition +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

ModuleBundleDefinitionSection

+ + + + + +
+ +
Description:
+
  • A ModuleBundleDefinitionSection specifies the embedding mode (either 'provided', 'raw', 'preload', 'require' +or 'bundleInfo') and lists the resources that should be in- or excluded from the section. +

    +Module bundle section modes
    +

      +
    • + provided: A section of mode 'provided' defines a set of modules that should not be included in +the bundle file itself, but which should be assumed to be already loaded (or 'provided') by the environment into +which the bundle module is loaded. +
    • +
    • + raw: A 'raw' section determines the set of modules that should be embedded, sorts them according + to their dependencies and writes them out 1:1 without any transformation or wrapping (raw). Only JavaScript + sources can be embedded in a raw section. +
    • +
    • + preload: A 'preload' section packages resources that should be stored in the preload cache in the + client. They can embed any textual resource type (JavaScript, XML, JSON and .properties files) that the + bundling supports. UI5 modules are wrapped into a 'sap.ui.predefine' call. Other JavaScript modules will be + embedded into a 'jQuery.sap.registerPreload' call, or in a "sap.ui.require.preload" call when + the ui5loader is available. +
    • +
    • + require: A 'require' section is transformed into a sequence of jQuery.sap.require calls. The + list will be resolved like an include pattern list in any of the other sections and for each of the resolved + modules, a jQuery.sap.require will be created. In case the ui5loader is available, 'sap.ui.requireSync' is + used instead. +
    • +
    • + bundleInfo: A 'bundleInfo' section describes the content of another named bundle. This information + is transformed into a ui5loader-"bundlesUI5" configuration. + At runtime, if a module is known to be contained in a bundle, the loader will require that bundle before + the module itself. + This requires the ui5loader to be available at build time and UI5 version 1.74.0 or higher at runtime. +
    • +
    +

+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
mode + + +string + + + + + + + + + + + The embedding mode. Either 'provided', 'raw', 'preload', 'require' or 'bundleInfo'
filters + + +Array.<string> + + + + + + + + + + + List of modules declared as glob patterns (resource name patterns) that should be + in- or excluded. + A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk, + denote an arbitrary number of characters or folder names. + Excludes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later + exclusion overrides an earlier inclusion, and vice versa.
resolve + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Whether (transitive) dependencies of modules that match the given filters + should be resolved and added to the module set
resolveConditional + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Whether conditional dependencies of modules should be resolved + and added to the module set for this section
renderer + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Whether renderers for controls should be added to the module set
declareRawModules + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Whether raw modules should be declared after jQuery.sap.global + became available. With the usage of the ui5loader, this flag should be set to 'false'
sort + + +boolean + + + + + + + <optional>
+ + + +
+ + true + + Whether the modules should be sorted by their dependencies
+ + + + + + +
+ A ModuleBundleDefinitionSection specifies the embedding mode (either 'provided', 'raw', 'preload', 'require' +or 'bundleInfo') and lists the resources that should be in- or excluded from the section. +

+Module bundle section modes
+

    +
  • + provided: A section of mode 'provided' defines a set of modules that should not be included in +the bundle file itself, but which should be assumed to be already loaded (or 'provided') by the environment into +which the bundle module is loaded. +
  • +
  • + raw: A 'raw' section determines the set of modules that should be embedded, sorts them according + to their dependencies and writes them out 1:1 without any transformation or wrapping (raw). Only JavaScript + sources can be embedded in a raw section. +
  • +
  • + preload: A 'preload' section packages resources that should be stored in the preload cache in the + client. They can embed any textual resource type (JavaScript, XML, JSON and .properties files) that the + bundling supports. UI5 modules are wrapped into a 'sap.ui.predefine' call. Other JavaScript modules will be + embedded into a 'jQuery.sap.registerPreload' call, or in a "sap.ui.require.preload" call when + the ui5loader is available. +
  • +
  • + require: A 'require' section is transformed into a sequence of jQuery.sap.require calls. The + list will be resolved like an include pattern list in any of the other sections and for each of the resolved + modules, a jQuery.sap.require will be created. In case the ui5loader is available, 'sap.ui.requireSync' is + used instead. +
  • +
  • + bundleInfo: A 'bundleInfo' section describes the content of another named bundle. This information + is transformed into a ui5loader-"bundlesUI5" configuration. + At runtime, if a module is known to be contained in a bundle, the loader will require that bundle before + the module itself. + This requires the ui5loader to be available at build time and UI5 version 1.74.0 or higher at runtime. +
  • +
+

+
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + +
Example
+ +

List of modules as glob patterns that should be in- or excluded

+ +
// Includes everything from "some/path/to/module/",
+// but excludes the subfolder "some/path/to/module/to/be/excluded/"
+const section = {
+	"filters": [
+		"some/path/to/module/",
+		"!some/path/to/module/to/be/excluded/"
+	]
+};
+ + + + + +

ModuleBundleOptions

+ + + + + +
+ +
Description:
+
  • Module bundle options
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
optimize + + +boolean + + + + + + + <optional>
+ + + +
+ + true + + Whether the module bundle gets minified
sourceMap + + +boolean + + + + + + + <optional>
+ + + +
+ + true + + Whether to generate a source map file for the bundle
decorateBootstrapModule + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + If set to 'false', bootable bundles won't be decorated + with an optimization marker
addTryCatchRestartWrapper + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + Whether to wrap bootable bundles with + a try/catch to filter out "Restart" errors
usePredefineCalls + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + If set to 'true', sap.ui.predefine is used for UI5 modules
numberOfParts + + +number + + + + + + + <optional>
+ + + +
+ + 1 + + The number of parts the module bundle should be splitted
ignoreMissingModules + + +boolean + + + + + + + <optional>
+ + + +
+ + false + + When searching for modules which are optional for further + processing, do not throw in case they are missing
+ + + + + + +
+ Module bundle options +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + +

ModuleBundlerResult

+ + + + + +
+ +
Description:
+
  • Result set
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
bundle + + +@ui5/fs/Resource + + + + + Bundle resource
sourceMap + + +@ui5/fs/Resource + + + + + Source Map
+ + + + + + +
+ Result set +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_jsdoc_apiIndexGenerator.html b/v3/api/module-@ui5_builder_processors_jsdoc_apiIndexGenerator.html new file mode 100644 index 0000000000..f8bcd7ed76 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_jsdoc_apiIndexGenerator.html @@ -0,0 +1,543 @@ + + + + + + @ui5/builder/processors/jsdoc/apiIndexGenerator - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/jsdoc/apiIndexGenerator

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Compiles API index resources from all api.json resources available in the given test resources directory +as created by the sdkTransformer processor. +The resulting index resources (e.g. api-index.json, api-index-deprecated.json, +api-index-experimental.json and api-index-since.json) are mainly to be used in the SDK.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
versionInfoPath + + +string + + + + + Path to sap-ui-version.json resource
testResourcesRootPath + + +string + + + + + Path to /test-resources root directory in the + given fs
targetApiIndexPath + + +string + + + + + Path to create the generated API index JSON resource for
targetApiIndexDeprecatedPath + + +string + + + + + Path to create the generated API index "deprecated" JSON + resource for
targetApiIndexExperimentalPath + + +string + + + + + Path to create the generated API index "experimental" JSON + resource for
targetApiIndexSincePath + + +string + + + + + Path to create the generated API index "since" JSON resource for
fs + + +fs +| + +module:@ui5/fs/fsInterface + + + + + Node fs or + custom fs interface to use
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with created resources api-index.json, +api-index-deprecated.json, api-index-experimental.json and +api-index-since.json (names depend on the supplied paths) +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_jsdoc_jsdocGenerator.html b/v3/api/module-@ui5_builder_processors_jsdoc_jsdocGenerator.html new file mode 100644 index 0000000000..ce1996b289 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_jsdoc_jsdocGenerator.html @@ -0,0 +1,637 @@ + + + + + + @ui5/builder/processors/jsdoc/jsdocGenerator - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/jsdoc/jsdocGenerator

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • JSDoc generator
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
sourcePath + + +string + + + + + Path of the source files to be processed
targetPath + + +string + + + + + Path to write any output files
tmpPath + + +string + + + + + Path to write temporary and debug files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
projectName + + +string + + + + + + + + + + + + + Project name
namespace + + +string + + + + + + + + + + + + + Namespace to build (e.g. some/project/name)
version + + +string + + + + + + + + + + + + + Project version
variants + + +Array + + + + + + + <optional>
+ + + + + +
+ + ["apijson"] + + JSDoc variants to be built
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with newly created resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_jsdoc_sdkTransformer.html b/v3/api/module-@ui5_builder_processors_jsdoc_sdkTransformer.html new file mode 100644 index 0000000000..905fa29be0 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_jsdoc_sdkTransformer.html @@ -0,0 +1,490 @@ + + + + + + @ui5/builder/processors/jsdoc/sdkTransformer - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/jsdoc/sdkTransformer

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Transform api.json as created by jsdocGenerator +for usage in a UI5 SDK
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
apiJsonPath + + +string + + + + + Path to the projects api.json file as created by + jsdocGenerator
dotLibraryPath + + +string + + + + + Path to the projects .library file
dependencyApiJsonPaths + + +Array.<string> + + + + + List of paths to the api.json files of all dependencies of + the project as created by jsdocGenerator
targetApiJsonPath + + +string + + + + + Path to create the new, transformed api.json resource for
fs + + +fs +| + +module:@ui5/fs/fsInterface + + + + + Node fs or + custom fs interface to use
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with created resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_libraryLessGenerator.html b/v3/api/module-@ui5_builder_processors_libraryLessGenerator.html new file mode 100644 index 0000000000..597e5d64ea --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_libraryLessGenerator.html @@ -0,0 +1,424 @@ + + + + + + @ui5/builder/processors/libraryLessGenerator - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/libraryLessGenerator

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Creates a "library.less" file for the SAP Theme Designer based on a "library.source.less" file. + +
      +
    • Bundles all *.less file of the theme by replacing the import with the corresponding file content
    • +
    • Imports to "base.less" are adopted so that they point to the "BaseLib" that is available within +the Theme Designer infrastructure
    • +
    • Imports to "global.less" are kept as they should not be bundled
    • +
    • Imports to "library.source.less" are adopted to "library.less"
    • +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + List of library.source.less +resources
fs + + +fs +| + +module:@ui5/fs/fsInterface + + + + + Node fs or custom +fs interface
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with library.less resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_minifier.html b/v3/api/module-@ui5_builder_processors_minifier.html new file mode 100644 index 0000000000..24f55881a8 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_minifier.html @@ -0,0 +1,762 @@ + + + + + + @ui5/builder/processors/minifier - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/minifier

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<module:@ui5/builder/processors/minifier~MinifierResult>>}

+ + + + + + +
+ +
Description:
+
  • Minifies the supplied resources.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + + + + + + + List of resources to be processed
taskUtil + + +@ui5/builder/tasks/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil instance. + Required when using the useWorkers option
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
addSourceMappingUrl + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + + Whether to add a sourceMappingURL reference to the end of the minified resource
useWorkers + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether to offload the minification task onto separate CPU threads. This often speeds up the build process
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with object of resource, dbgResource and sourceMap +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<module:@ui5/builder/processors/minifier~MinifierResult>> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

MinifierResult

+ + + + + +
+ +
Description:
+
  • Result set
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resource + + +@ui5/fs/Resource + + + + + Minified resource
dbgResource + + +@ui5/fs/Resource + + + + + Debug (non-minified) variant
sourceMap + + +@ui5/fs/Resource + + + + + Source Map
+ + + + + + +
+ Result set +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_nonAsciiEscaper.html b/v3/api/module-@ui5_builder_processors_nonAsciiEscaper.html new file mode 100644 index 0000000000..8031a41d19 --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_nonAsciiEscaper.html @@ -0,0 +1,669 @@ + + + + + + @ui5/builder/processors/nonAsciiEscaper - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/nonAsciiEscaper

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Escapes non ASCII characters with unicode escape sequences.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
const encoding = nonAsciiEscaper.getEncodingFromAlias("ISO-8859-1");
+nonAsciiEscaper({resources, options: {encoding}});
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + + + + + + + List of resources to be processed
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
encoding + + +string + + + + + + + <optional>
+ + + + + +
+ + "utf8" + + resource file encoding + (Node.js character encodings). + Use #getEncodingFromAlias to get the encoding string
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with the processed resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + +

(static) getEncodingFromAlias(encoding) → {string}

+ + + + + + +
+ +
Description:
+
  • Provides a mapping from user-friendly encoding name (alias) such as "UTF-8" and "ISO-8859-1" to node +specific encoding name such as "utf8" or "latin1". Simplifies usage of nonAsciiEscaper encoding option +such that it can be used standalone without the respective task (e.g. in Splitter, Bundler and related projects).
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
encoding + + +string + + + + + encoding labels: "UTF-8" and "ISO-8859-1"
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ node.js character encoding string, e.g. utf8 and latin1 +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_stringReplacer.html b/v3/api/module-@ui5_builder_processors_stringReplacer.html new file mode 100644 index 0000000000..09ddefadbb --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_stringReplacer.html @@ -0,0 +1,485 @@ + + + + + + @ui5/builder/processors/stringReplacer - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/stringReplacer

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Replaces placeholders with corresponding values.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
resources + + +Array.<@ui5/fs/Resource> + + + + + List of resources to be processed
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pattern + + +string + + + + + Pattern of placeholders
replacement + + +string + + + + + Replacement for placeholders
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with modified resources +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_processors_versionInfoGenerator.html b/v3/api/module-@ui5_builder_processors_versionInfoGenerator.html new file mode 100644 index 0000000000..e351352d2e --- /dev/null +++ b/v3/api/module-@ui5_builder_processors_versionInfoGenerator.html @@ -0,0 +1,707 @@ + + + + + + @ui5/builder/processors/versionInfoGenerator - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/processors/versionInfoGenerator

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<Array.<@ui5/fs/Resource>>}

+ + + + + + +
+ +
Description:
+
  • Creates sap-ui-version.json.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
rootProjectName + + +string + + + + + Name of the root project
rootProjectVersion + + +string + + + + + Version of the root project
libraryInfos + + +Array.<module:@ui5/builder/processors/versionInfoGenerator~LibraryInfo> + + + + + Array of + objects representing libraries, + e.g.
+  {
+     name: "lib.x",
+     version: "1.0.0",
+     libraryManifest: @ui5/fs/Resource,
+     embeddedManifests: @ui5/fs/Resource[]
+  }
+
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with an array containing the versionInfo resource +
+ + + +
+
+ Type +
+
+ +Promise.<Array.<@ui5/fs/Resource>> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

LibraryInfo

+ + + + + +
+ +
Description:
+
  • Library Info + +contains information about the name and the version of the library and its manifest, as well as the nested manifests.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + The library name, e.g. "lib.x"
version + + +string + + + + + The library version, e.g. "1.0.0"
libraryManifest + + +@ui5/fs/Resource + + + + + library manifest resource, + e.g. resource with path "lib/x/manifest.json"
embeddedManifests + + +Array.<@ui5/fs/Resource> + + + + + list of embedded manifest resources, + e.g. resource with path "lib/x/sub/manifest.json"
+ + + + + + +
+ Library Info + +contains information about the name and the version of the library and its manifest, as well as the nested manifests. +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_buildThemes.html b/v3/api/module-@ui5_builder_tasks_buildThemes.html new file mode 100644 index 0000000000..5ec333804f --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_buildThemes.html @@ -0,0 +1,693 @@ + + + + + + @ui5/builder/tasks/buildThemes - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/buildThemes

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to build a library theme.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + Reader or Collection to read dependency files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
projectName + + +string + + + + + + + + + + + + + Project name
inputPattern + + +string + + + + + + + + + + + + + Search pattern for *.less files to be built
librariesPattern + + +string + + + + + + + <optional>
+ + + + + +
+ + Search pattern for .library files
themesPattern + + +string + + + + + + + <optional>
+ + + + + +
+ + Search pattern for sap.ui.core theme folders
compress + + +boolean + + + + + + + <optional>
+ + + + + +
+ + true + +
cssVariables + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + +
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_bundlers_generateBundle.html b/v3/api/module-@ui5_builder_tasks_bundlers_generateBundle.html new file mode 100644 index 0000000000..b1f430e14e --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_bundlers_generateBundle.html @@ -0,0 +1,626 @@ + + + + + + @ui5/builder/tasks/bundlers/generateBundle - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/bundlers/generateBundle

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise}

+ + + + + + +
+ +
Description:
+
  • Generates a bundle based on the given bundle definition
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/ReaderCollection + + + + + + + + + + + Collection to read dependency files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectName + + +string + + + + + + + + + + + Project name
bundleDefinition + + +module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleDefinition + + + + + + + + + + + Module + bundle definition
bundleOptions + + +module:@ui5/builder/processors/bundlers/moduleBundler~ModuleBundleOptions + + + + + + + <optional>
+ + + + + +
Module + bundle options
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_bundlers_generateComponentPreload.html b/v3/api/module-@ui5_builder_tasks_bundlers_generateComponentPreload.html new file mode 100644 index 0000000000..191eaf6067 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_bundlers_generateComponentPreload.html @@ -0,0 +1,691 @@ + + + + + + @ui5/builder/tasks/bundlers/generateComponentPreload - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/bundlers/generateComponentPreload

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to for application bundling.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
projectName + + +string + + + + + + + + + + + + + Project name
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of modules declared as glob patterns (resource name patterns) +that should be excluded. +A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk, +denote an arbitrary number of characters or folder names. +Re-includes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later +inclusion overrides an earlier exclusion, and vice versa.
paths + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + Array of paths (or glob patterns) for component files
namespaces + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + Array of component namespaces
skipBundles + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + Names of bundles that should not be created
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_bundlers_generateFlexChangesBundle.html b/v3/api/module-@ui5_builder_tasks_bundlers_generateFlexChangesBundle.html new file mode 100644 index 0000000000..d2862aa615 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_bundlers_generateFlexChangesBundle.html @@ -0,0 +1,535 @@ + + + + + + @ui5/builder/tasks/bundlers/generateFlexChangesBundle - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/bundlers/generateFlexChangesBundle

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to create changesBundle.json file containing all changes stored in the /changes folder for easier consumption +at runtime. +If a change bundle is created, "sap.ui.fl" is added as a dependency to the manifest.json if not already present - +if the dependency is already listed but lazy-loaded, lazy loading is disabled. +If minUI5Version >= 1.73 flexibility-bundle.json will be create. +If there are control variants and minUI5Version < 1.73 build will break and throw an error.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + <optional>
+ + + + + +
Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectNamespace + + +string + + + + + + + <optional>
+ + + + + +
Project Namespace
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_bundlers_generateLibraryPreload.html b/v3/api/module-@ui5_builder_tasks_bundlers_generateLibraryPreload.html new file mode 100644 index 0000000000..f0760f1a4c --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_bundlers_generateLibraryPreload.html @@ -0,0 +1,612 @@ + + + + + + @ui5/builder/tasks/bundlers/generateLibraryPreload - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/bundlers/generateLibraryPreload

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task for library bundling.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
taskUtil + + +@ui5/project/build/helpers/TaskUtil + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
projectName + + +string + + + + + + + + + + + + + Project name
skipBundles + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + Names of bundles that should not be created
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + [] + + List of modules declared as glob patterns (resource name patterns) +that should be excluded from the library-preload.js bundle. +A pattern ending with a slash '/' will, similarly to the use of a single '*' or double '**' asterisk, +denote an arbitrary number of characters or folder names. +Re-includes should be marked with a leading exclamation mark '!'. The order of filters is relevant; a later +inclusion overrides an earlier exclusion, and vice versa.
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_bundlers_generateStandaloneAppBundle.html b/v3/api/module-@ui5_builder_tasks_bundlers_generateStandaloneAppBundle.html new file mode 100644 index 0000000000..ebc87e0454 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_bundlers_generateStandaloneAppBundle.html @@ -0,0 +1,592 @@ + + + + + + @ui5/builder/tasks/bundlers/generateStandaloneAppBundle - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/bundlers/generateStandaloneAppBundle

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task for bundling standalone applications.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + + + + + + + Reader or Collection to read dependency files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectName + + +string + + + + + + + + + + + Project name
projectNamespace + + +string + + + + + + + <optional>
+ + + + + +
Project namespace
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_escapeNonAsciiCharacters.html b/v3/api/module-@ui5_builder_tasks_escapeNonAsciiCharacters.html new file mode 100644 index 0000000000..36c0d0ac48 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_escapeNonAsciiCharacters.html @@ -0,0 +1,485 @@ + + + + + + @ui5/builder/tasks/escapeNonAsciiCharacters - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/escapeNonAsciiCharacters

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to escape non ascii characters in properties files resources.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pattern + + +string + + + + + Glob pattern to locate the files to be processed
encoding + + +string + + + + + source file encoding either "UTF-8" or "ISO-8859-1"
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_generateCachebusterInfo.html b/v3/api/module-@ui5_builder_tasks_generateCachebusterInfo.html new file mode 100644 index 0000000000..884b30fab7 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_generateCachebusterInfo.html @@ -0,0 +1,517 @@ + + + + + + @ui5/builder/tasks/generateCachebusterInfo - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/generateCachebusterInfo

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to generate the application cachebuster info file.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
projectNamespace + + +string + + + + + + + + + + + + + Namespace of the application
signatureType + + +string + + + + + + + <optional>
+ + + + + +
+ + 'time' + + Type of signature to be used ('time' or 'hash')
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_generateLibraryManifest.html b/v3/api/module-@ui5_builder_tasks_generateLibraryManifest.html new file mode 100644 index 0000000000..ff6d6e8701 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_generateLibraryManifest.html @@ -0,0 +1,516 @@ + + + + + + @ui5/builder/tasks/generateLibraryManifest - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/generateLibraryManifest

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task for creating a library manifest.json from its .library file.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Project name
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_generateResourcesJson.html b/v3/api/module-@ui5_builder_tasks_generateResourcesJson.html new file mode 100644 index 0000000000..540ae7c693 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_generateResourcesJson.html @@ -0,0 +1,603 @@ + + + + + + @ui5/builder/tasks/generateResourcesJson - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/generateResourcesJson

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task for creating a resources.json file, describing all productive build resources. + +

    +The detailed structure can be found in the documentation: +https://sdk.openui5.org/topic/adcbcf8b50924556ab3f321fcd9353ea +

    + +

    +Not supported in combination with task @ui5/builder/tasks/bundlers/generateStandaloneAppBundle. +Therefore it is also not supported in combination with self-contained build. +

+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +

sample resources.json

+ +
const resourcesJson = {
+	"_version": "1.1.0",
+	"resources": [
+		{
+			"name": "Component-preload.js",
+			"module": "application/mine/Component-preload.js",
+			"size": 3746,
+			"merged": true,
+			"included": [
+				"application/mine/Component.js",
+				"application/mine/changes/coding/MyExtension.js",
+				"application/mine/changes/flexibility-bundle.json",
+				"application/mine/changes/fragments/MyFragment.fragment.xml",
+				"application/mine/manifest.json"
+			]
+		},
+		{
+			"name": "resources.json",
+			"size": 1870
+		},
+		{
+			"name": "rules/Button-dbg.support.js",
+			"module": "application/mine/rules/Button.support.js",
+			"size": 211,
+			"format": "raw",
+			"isDebug": true,
+			"required": [
+				"application/mine/library.js",
+				"sap/ui/core/Control.js"
+			],
+			"condRequired": [
+				"application/mine/changeHandler/SplitButton.js",
+				"sap/ui/core/format/DateFormat.js"
+			],
+			"dynRequired": true,
+			"support": true
+		}
+	]
+};
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + + + + + + + Reader or Collection to read dependency files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Project name
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_generateThemeDesignerResources.html b/v3/api/module-@ui5_builder_tasks_generateThemeDesignerResources.html new file mode 100644 index 0000000000..10145f2b24 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_generateThemeDesignerResources.html @@ -0,0 +1,563 @@ + + + + + + @ui5/builder/tasks/generateThemeDesignerResources - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/generateThemeDesignerResources

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Generates resources required for integration with the SAP Theme Designer.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + Reader or Collection to read dependency files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
projectName + + +string + + + + + + + + + + + Project name
version + + +string + + + + + + + + + + + Project version
projectNamespace + + +string + + + + + + + <optional>
+ + + + + +
If the project is of type library, + provide its namespace. +Omit for type theme-library
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_generateVersionInfo.html b/v3/api/module-@ui5_builder_tasks_generateVersionInfo.html new file mode 100644 index 0000000000..d5063fd48d --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_generateVersionInfo.html @@ -0,0 +1,509 @@ + + + + + + @ui5/builder/tasks/generateVersionInfo - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/generateVersionInfo

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to create sap-ui-version.json
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + Reader or Collection to read dependency files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pattern + + +string + + + + + Glob pattern for .library resources
rootProject + + +object + + + + + DuplexCollection to read and write files
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_jsdoc_executeJsdocSdkTransformation.html b/v3/api/module-@ui5_builder_tasks_jsdoc_executeJsdocSdkTransformation.html new file mode 100644 index 0000000000..79eb7aabb3 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_jsdoc_executeJsdocSdkTransformation.html @@ -0,0 +1,514 @@ + + + + + + @ui5/builder/tasks/jsdoc/executeJsdocSdkTransformation - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/jsdoc/executeJsdocSdkTransformation

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to transform the api.json file as created by the +generateJsdoc task into a pre-processed api.json +file suitable for the SDK.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + Reader or Collection to read dependency files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
dotLibraryPattern + + +string +| + +Array + + + + + Pattern to locate the .library resource to be processed
projectName + + +string + + + + + Project name
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_jsdoc_generateApiIndex.html b/v3/api/module-@ui5_builder_tasks_jsdoc_generateApiIndex.html new file mode 100644 index 0000000000..840db67105 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_jsdoc_generateApiIndex.html @@ -0,0 +1,487 @@ + + + + + + @ui5/builder/tasks/jsdoc/generateApiIndex - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/jsdoc/generateApiIndex

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Compiles an api-index.json resource from all available api.json resources as created by the +executeJsdocSdkTransformation task. +The resulting api-index.json resource is mainly to be used in the SDK.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + Reader or Collection to read dependency files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
projectName + + +string + + + + + Project name
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_jsdoc_generateJsdoc.html b/v3/api/module-@ui5_builder_tasks_jsdoc_generateJsdoc.html new file mode 100644 index 0000000000..22d809e4fa --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_jsdoc_generateJsdoc.html @@ -0,0 +1,701 @@ + + + + + + @ui5/builder/tasks/jsdoc/generateJsdoc - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/jsdoc/generateJsdoc

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to execute a JSDoc build for UI5 projects
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
dependencies + + +@ui5/fs/AbstractReader + + + + + + + + + + + Reader or Collection to read dependency files
options + + +module:@ui5/builder/tasks/jsdoc/generateJsdoc~GenerateJsdocOptions + + + + + + + + + + + Options
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

GenerateJsdocOptions

+ + + + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pattern + + +string +| + +Array.<string> + + + + + Pattern to locate the files to be processed
projectName + + +string + + + + + Project name
namespace + + +string + + + + + Namespace to build (e.g. some/project/name)
version + + +string + + + + + Project version
+ + + + + + + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_minify.html b/v3/api/module-@ui5_builder_tasks_minify.html new file mode 100644 index 0000000000..e467d1f84e --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_minify.html @@ -0,0 +1,573 @@ + + + + + + @ui5/builder/tasks/minify - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/minify

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to minify resources.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + + + + + + + DuplexCollection to read and write files
taskUtil + + +@ui5/project/build/helpers/TaskUtil +| + +object + + + + + + + <optional>
+ + + + + +
TaskUtil
options + + +object + + + + + + + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
pattern + + +string + + + + + + + + + + + + + Pattern to locate the files to be processed
omitSourceMapResources + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether source map resources shall + be tagged as "OmitFromBuildResult" and no sourceMappingURL shall be added to the minified resource
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_replaceBuildtime.html b/v3/api/module-@ui5_builder_tasks_replaceBuildtime.html new file mode 100644 index 0000000000..176baf0397 --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_replaceBuildtime.html @@ -0,0 +1,461 @@ + + + + + + @ui5/builder/tasks/replaceBuildtime - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/replaceBuildtime

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to replace the buildtime ${buildtime}.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pattern + + +string + + + + + Pattern to locate the files to be processed
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_replaceCopyright.html b/v3/api/module-@ui5_builder_tasks_replaceCopyright.html new file mode 100644 index 0000000000..ac18a55a8b --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_replaceCopyright.html @@ -0,0 +1,495 @@ + + + + + + @ui5/builder/tasks/replaceCopyright - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/replaceCopyright

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to to replace the copyright. + +The following placeholders are replaced with corresponding values: +
      +
    • ${copyright}
    • +
    • @copyright@
    • +
    + +If the copyright string contains the optional placeholder ${currentYear} +it will be replaced with the current year. +If no copyright string is given, no replacement is being done.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
copyright + + +string + + + + + Replacement copyright
pattern + + +string + + + + + Pattern to locate the files to be processed
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_builder_tasks_replaceVersion.html b/v3/api/module-@ui5_builder_tasks_replaceVersion.html new file mode 100644 index 0000000000..9b6591769c --- /dev/null +++ b/v3/api/module-@ui5_builder_tasks_replaceVersion.html @@ -0,0 +1,485 @@ + + + + + + @ui5/builder/tasks/replaceVersion - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/builder/tasks/replaceVersion

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(parameters) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Task to replace the version ${version}.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
workspace + + +@ui5/fs/DuplexCollection + + + + + DuplexCollection to read and write files
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pattern + + +string + + + + + Pattern to locate the files to be processed
version + + +string + + + + + Replacement version
+ +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving with undefined once data has been written +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_fs_fsInterface.html b/v3/api/module-@ui5_fs_fsInterface.html new file mode 100644 index 0000000000..4d8a2ab909 --- /dev/null +++ b/v3/api/module-@ui5_fs_fsInterface.html @@ -0,0 +1,341 @@ + + + + + + @ui5/fs/fsInterface - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/fsInterface

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(reader) → {object}

+ + + + + + +
+ +
Description:
+
  • Wraps readers to access them through a Node.js fs styled interface.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
reader + + +@ui5/fs/AbstractReader + + + + + Resource Reader or Collection
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Object with Node.js fs styled functions +readFile, +stat, +readdir and +mkdir +
+ + + +
+
+ Type +
+
+ +object + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_fs_resourceFactory.html b/v3/api/module-@ui5_fs_resourceFactory.html new file mode 100644 index 0000000000..dcb55a3610 --- /dev/null +++ b/v3/api/module-@ui5_fs_resourceFactory.html @@ -0,0 +1,2846 @@ + + + + + + @ui5/fs/resourceFactory - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/fs/resourceFactory

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ +
Description:
+
  • A collection of resource related APIs
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
A collection of resource related APIs
+ + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) createAdapter(parameters) → {@ui5/fs/adapters/FileSystem|@ui5/fs/adapters/Memory}

+ + + + + + +
+ +
Description:
+
  • Creates a resource ReaderWriter. + +If a file system base path is given, file system resource ReaderWriter is returned. +In any other case a virtual one.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
virBasePath + + +string + + + + + + + + + + + + + Virtual base path. Must be absolute, POSIX-style, and must end with a slash
fsBasePath + + +string + + + + + + + <optional>
+ + + + + +
+ + File System base path. + If this parameter is supplied, a File System adapter will be created instead of a Memory adapter. + The provided path must be absolute and must use platform-specific path segment separators.
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
+ + List of glob patterns to exclude
useGitignore + + +object + + + + + + + <optional>
+ + + + + +
+ + false + + Whether to apply any excludes defined in an optional .gitignore in the base directory. + This parameter only takes effect in conjunction with the fsBasePath parameter.
project + + +@ui5/project/specifications/Project + + + + + + + <optional>
+ + + + + +
+ + Project this adapter belongs to (if any)
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ File System- or Virtual Adapter +
+ + + +
+
+ Type +
+
+ +@ui5/fs/adapters/FileSystem +| + +@ui5/fs/adapters/Memory + + + +
+
+ + + + + + + + + + +

(static) createFilterReader(parameters) → {@ui5/fs/readers/Filter}

+ + + + + + +
+ +
Description:
+
  • Create a Filter-Reader with the given reader. +The provided callback is called for every resource that is retrieved through the +reader and decides whether the resource shall be passed on or dropped.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
reader + + +@ui5/fs/AbstractReader + + + + + Single reader or collection of readers
callback + + +@ui5/fs/readers/Filter~callback + + + + + Filter function. Will be called for every resource passed through this reader.
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/readers/Filter + + + +
+
+ + + + + + + + + + +

(static) createFlatReader(parameters) → {@ui5/fs/readers/Link}

+ + + + + + +
+ +
Description:
+
  • Create a Link-Reader where all requests are prefixed with +/resources/. + +This simulates "flat" resource access, which is for example common for projects of type +"application".
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
reader + + +@ui5/fs/AbstractReader + + + + + Single reader or collection of readers
namespace + + +string + + + + + Project namespace
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/readers/Link + + + +
+
+ + + + + + + + + + +

(static) createLinkReader(parameters) → {@ui5/fs/readers/Link}

+ + + + + + +
+ +
Description:
+
  • Create a Link-Reader with the given reader. +The provided path mapping allows for rewriting paths segments of all resources passed through it.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Example
+ +
import {createLinkReader} from "@ui5/fs/resourceFactory";
+const linkedReader = createLinkReader({
+    reader: sourceReader,
+    pathMapping: {
+         linkPath: `/app`,
+         targetPath: `/resources/my-app-name/`
+     }
+});
+
+// The following resolves with a @ui5/fs/ResourceFacade of the resource
+// located at "/resources/my-app-name/Component.js" in the sourceReader
+const resource = await linkedReader.byPath("/app/Component.js");
+ + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
reader + + +@ui5/fs/AbstractReader + + + + + Single reader or collection of readers
pathMapping + + +@ui5/fs/readers/Link/PathMapping + + + + +
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader instance +
+ + + +
+
+ Type +
+
+ +@ui5/fs/readers/Link + + + +
+
+ + + + + + + + + + +

(static) createReader(parameters) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Creates a File System adapter and wraps it in a ReaderCollection
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
virBasePath + + +string + + + + + + + + + + + Virtual base path. Must be absolute, POSIX-style, and must end with a slash
fsBasePath + + +string + + + + + + + + + + + File System base path. Must be absolute and must use platform-specific path segment separators
project + + +object + + + + + + + <optional>
+ + + + + +
Experimental, internal parameter. Do not use
excludes + + +Array.<string> + + + + + + + <optional>
+ + + + + +
List of glob patterns to exclude
name + + +string + + + + + + + <optional>
+ + + + + +
Name for the reader collection
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection wrapping an adapter +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

(static) createReaderCollection(parameters) → {@ui5/fs/ReaderCollection}

+ + + + + + +
+ +
Description:
+
  • Creates a ReaderCollection
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + The collection name
readers + + +Array.<@ui5/fs/AbstractReader> + + + + + List of resource readers (all tried in parallel)
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection wrapping provided readers +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollection + + + +
+
+ + + + + + + + + + +

(static) createReaderCollectionPrioritized(parameters) → {@ui5/fs/ReaderCollectionPrioritized}

+ + + + + + +
+ +
Description:
+
  • Creates a ReaderCollectionPrioritized
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + The collection name
readers + + +Array.<@ui5/fs/AbstractReader> + + + + + Prioritized list of resource readers + (first is tried first)
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Reader collection wrapping provided readers +
+ + + +
+
+ Type +
+
+ +@ui5/fs/ReaderCollectionPrioritized + + + +
+
+ + + + + + + + + + +

(static) createResource(parameters) → {@ui5/fs/Resource}

+ + + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + Parameters to be passed to the resource constructor
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Resource +
+ + + +
+
+ Type +
+
+ +@ui5/fs/Resource + + + +
+
+ + + + + + + + + + +

(static) createWorkspace(parameters) → {@ui5/fs/DuplexCollection}

+ + + + + + +
+ +
Description:
+
  • Creates a Workspace + +A workspace is a DuplexCollection which reads from the project sources. It is used during the build process +to write modified files into a separate writer, this is usually a Memory adapter. If a file already exists it is +fetched from the memory to work on it in further build steps.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
reader + + +@ui5/fs/AbstractReader + + + + + + + + + + + + + Single reader or collection of readers
writer + + +@ui5/fs/AbstractReaderWriter + + + + + + + <optional>
+ + + + + +
+ + A ReaderWriter instance which is + only used for writing files. If not supplied, a Memory adapter will be created.
name + + +string + + + + + + + <optional>
+ + + + + +
+ + "workspace" + + Name of the collection
virBasePath + + +string + + + + + + + <optional>
+ + + + + +
+ + "/" + + Virtual base path
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ DuplexCollection which wraps the provided resource locators +
+ + + +
+
+ Type +
+
+ +@ui5/fs/DuplexCollection + + + +
+
+ + + + + + + + + + +

(static) createWriterCollection(parameters) → {@ui5/fs/WriterCollection}

+ + + + + + +
+ +
Description:
+
  • Creates a WriterCollection
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parameters + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +string + + + + + The collection name
writerMapping + + +object.<string, @ui5/fs/AbstractReaderWriter> + + + + + Mapping of virtual base + paths to writers. Path are matched greedy
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Writer collection wrapping provided writers +
+ + + +
+
+ Type +
+
+ +@ui5/fs/WriterCollection + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_logger.html b/v3/api/module-@ui5_logger.html new file mode 100644 index 0000000000..e8ea326fbf --- /dev/null +++ b/v3/api/module-@ui5_logger.html @@ -0,0 +1,743 @@ + + + + + + @ui5/logger - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/logger

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ +
Description:
+
  • Interface for the UI5 Tooling logging module
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
Interface for the UI5 Tooling logging module
+ + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) getLogLevel() → {string}

+ + + + + + +
+ +
Description:
+
  • Gets the current log level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ The current log level. Defaults to info +
+ + + +
+
+ Type +
+
+ +string + + + +
+
+ + + + + + + + + + +

(static) getLogger(moduleName) → {@ui5/logger/Logger}

+ + + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
moduleName + + +string + + + + + Identifier for messages created by the logger. +Example: module:submodule:Class
+ + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +@ui5/logger/Logger + + + +
+
+ + + + + + + + + + +

(static) isLogLevelEnabled(levelName) → {boolean}

+ + + + + + +
+ +
Description:
+
  • Tests whether the provided log level is enabled by the current log level
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
levelName + + +string + + + + + Log level to test
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ True if the provided level is enabled +
+ + + +
+
+ Type +
+
+ +boolean + + + +
+
+ + + + + + + + + + +

(static) setLogLevel(levelName)

+ + + + + + +
+ +
Description:
+
  • Sets the standard log level. +
    +Example: Setting it to perf would suppress all silly and verbose +logging, and only show perf, info, warn and error logs.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
levelName + + +string + + + + + New log level
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_project_graph.html b/v3/api/module-@ui5_project_graph.html new file mode 100644 index 0000000000..edc61e68b2 --- /dev/null +++ b/v3/api/module-@ui5_project_graph.html @@ -0,0 +1,1662 @@ + + + + + + @ui5/project/graph - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/graph

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
Helper module to create a @ui5/project/graph/ProjectGraph +from a directory
+ + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) graphFromObject(options) → {Promise.<@ui5/project/graph/ProjectGraph>}

+ + + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
dependencyTree + + +@ui5/project/graph/providers/DependencyTree~TreeNode + + + + + + + + + + + + +
cwd + + +string + + + + + + + <optional>
+ + + + + +
+ + process.cwd() + + Directory to resolve relative paths to
rootConfiguration + + +object + + + + + + + <optional>
+ + + + + +
+ + Configuration object to use for the root module instead of reading from a configuration file
rootConfigPath + + +string + + + + + + + <optional>
+ + + + + +
+ + Configuration file to use for the root module instead the default ui5.yaml. Either a path relative to + cwd or an absolute path. In both case, platform-specific path segment separators must be used.
versionOverride + + +string + + + + + + + <optional>
+ + + + + +
+ + Framework version to use instead of the one defined in the root project
cacheMode + + +module:@ui5/project/ui5Framework/maven/CacheMode + + + + + + + <optional>
+ + + + + +
+ + Cache mode to use when consuming SNAPSHOT versions of a framework
resolveFrameworkDependencies + + +string + + + + + + + <optional>
+ + + + + +
+ + true + + Whether framework dependencies should be added to the graph
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a Project Graph instance +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/project/graph/ProjectGraph> + + + +
+
+ + + + + + + + + + +

(static) graphFromPackageDependencies(optionsopt) → {Promise.<@ui5/project/graph/ProjectGraph>}

+ + + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
options + + +object + + + + + + + <optional>
+ + + + + +
+
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
cwd + + +string + + + + + + + <optional>
+ + + + + +
+ + process.cwd() + + Directory to start searching for the root module
rootConfiguration + + +object + + + + + + + <optional>
+ + + + + +
+ + Configuration object to use for the root module instead of reading from a configuration file
rootConfigPath + + +string + + + + + + + <optional>
+ + + + + +
+ + Configuration file to use for the root module instead the default ui5.yaml. Either a path relative to + cwd or an absolute path. In both case, platform-specific path segment separators must be used.
versionOverride + + +string + + + + + + + <optional>
+ + + + + +
+ + Framework version to use instead of the one defined in the root project
resolveFrameworkDependencies + + +string + + + + + + + <optional>
+ + + + + +
+ + true + + Whether framework dependencies should be added to the graph
workspaceName + + +string + + + + + + + <optional>
+ + + + + +
+ + Name of the workspace configuration that should be used if any is provided
cacheMode + + +module:@ui5/project/ui5Framework/maven/CacheMode + + + + + + + <optional>
+ + + + + +
+ + Cache mode to use when consuming SNAPSHOT versions of a framework
workspaceConfigPath + + +string + + + + + + + <optional>
+ + + + + +
+ + ui5-workspace.yaml + + Workspace configuration file to use if no object has been provided
workspaceConfiguration + + +@ui5/project/graph/Workspace~Configuration + + + + + + + <optional>
+ + + + + +
+ + Workspace configuration object to use instead of reading from a configuration file. + Parameter workspaceName can either be omitted or has to match with the given configuration name
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a Project Graph instance +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/project/graph/ProjectGraph> + + + +
+
+ + + + + + + + + + +

(static) graphFromStaticFile(options) → {Promise.<@ui5/project/graph/ProjectGraph>}

+ + + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
filePath + + +object + + + + + + + <optional>
+ + + + + +
+ + projectDependencies.yaml + + Path to the dependency configuration file
cwd + + +string + + + + + + + <optional>
+ + + + + +
+ + process.cwd() + + Directory to resolve relative paths to
rootConfiguration + + +object + + + + + + + <optional>
+ + + + + +
+ + Configuration object to use for the root module instead of reading from a configuration file
rootConfigPath + + +string + + + + + + + <optional>
+ + + + + +
+ + Configuration file to use for the root module instead the default ui5.yaml. Either a path relative to + cwd or an absolute path. In both case, platform-specific path segment separators must be used.
versionOverride + + +string + + + + + + + <optional>
+ + + + + +
+ + Framework version to use instead of the one defined in the root project
cacheMode + + +module:@ui5/project/ui5Framework/maven/CacheMode + + + + + + + <optional>
+ + + + + +
+ + Cache mode to use when consuming SNAPSHOT versions of a framework
resolveFrameworkDependencies + + +string + + + + + + + <optional>
+ + + + + +
+ + true + + Whether framework dependencies should be added to the graph
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving to a Project Graph instance +
+ + + +
+
+ Type +
+
+ +Promise.<@ui5/project/graph/ProjectGraph> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_project_graph_ProjectGraphBuilder.html b/v3/api/module-@ui5_project_graph_ProjectGraphBuilder.html new file mode 100644 index 0000000000..8eb14ed5d9 --- /dev/null +++ b/v3/api/module-@ui5_project_graph_ProjectGraphBuilder.html @@ -0,0 +1,382 @@ + + + + + + @ui5/project/graph/ProjectGraphBuilder - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/graph/ProjectGraphBuilder

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) default(nodeProvider, workspaceopt) → {@ui5/project/graph/ProjectGraph}

+ + + + + + +
+ +
Description:
+
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
nodeProvider + + +@ui5/project/graph/ProjectGraphBuilder~NodeProvider + + + + + + + + + + + Node provider instance to use for building the graph
workspace + + +@ui5/project/graph/Workspace + + + + + + + <optional>
+ + + + + +
Optional workspace instance to use for overriding project resolutions
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ A new project graph instance +
+ + + +
+
+ Type +
+
+ +@ui5/project/graph/ProjectGraph + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_project_ui5Framework_maven_CacheMode.html b/v3/api/module-@ui5_project_ui5Framework_maven_CacheMode.html new file mode 100644 index 0000000000..d56a91dce2 --- /dev/null +++ b/v3/api/module-@ui5_project_ui5Framework_maven_CacheMode.html @@ -0,0 +1,281 @@ + + + + + + @ui5/project/ui5Framework/maven/CacheMode - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/ui5Framework/maven/CacheMode

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ +
Description:
+
  • Cache modes for maven consumption
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
Default + + +string + + + + + Cache everything, invalidate after 9 hours
Force + + +string + + + + + Use cache only. Do not send any requests to the repository
Off + + +string + + + + + Invalidate the cache and update from the repository
+ + + + + + +
Cache modes for maven consumption
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_project_validation_validator.html b/v3/api/module-@ui5_project_validation_validator.html new file mode 100644 index 0000000000..dd9ebc517d --- /dev/null +++ b/v3/api/module-@ui5_project_validation_validator.html @@ -0,0 +1,1116 @@ + + + + + + @ui5/project/validation/validator - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/project/validation/validator

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ +
Description:
+
  • A collection of validation related APIs
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
A collection of validation related APIs
+ + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) validate(options) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Validates the given ui5 configuration.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
config + + +object + + + + + + + + + + + UI5 Configuration to validate
project + + +object + + + + + + + + + + + Project information +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +string + + + + + ID of the project
+ +
yaml + + +object + + + + + + + <optional>
+ + + + + +
YAML information +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
path + + +string + + + + + + + + + + + + + Path of the YAML file
source + + +string + + + + + + + + + + + + + Content of the YAML file
documentIndex + + +number + + + + + + + <optional>
+ + + + + +
+ + 0 + + Document index in case the YAML file contains multiple documents
+ +
+ +
+ + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ Rejects with a ValidationError + when the validation fails. +
+
+
+
+
+
+ Type +
+
+ +@ui5/project/validation/ValidationError + + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+ Returns a Promise that resolves when the validation succeeds +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + +

(static) validateWorkspace(options) → {Promise.<undefined>}

+ + + + + + +
+ +
Description:
+
  • Validates the given ui5-workspace configuration.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + +object + + + + + +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
config + + +object + + + + + + + + + + + ui5-workspace Configuration to validate
yaml + + +object + + + + + + + <optional>
+ + + + + +
YAML information +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
path + + +string + + + + + + + + + + + + + Path of the YAML file
source + + +string + + + + + + + + + + + + + Content of the YAML file
documentIndex + + +number + + + + + + + <optional>
+ + + + + +
+ + 0 + + Document index in case the YAML file contains multiple documents
+ +
+ +
+ + + + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ Rejects with a ValidationError + when the validation fails. +
+
+
+
+
+
+ Type +
+
+ +@ui5/project/validation/ValidationError + + + +
+
+
+
+
+ + + + + +
Returns:
+ + +
+ Returns a Promise that resolves when the validation succeeds +
+ + + +
+
+ Type +
+
+ +Promise.<undefined> + + + +
+
+ + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/module-@ui5_server.html b/v3/api/module-@ui5_server.html new file mode 100644 index 0000000000..119d4823e5 --- /dev/null +++ b/v3/api/module-@ui5_server.html @@ -0,0 +1,1058 @@ + + + + + + @ui5/server - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

@ui5/server

+ + + + + + + +
+ +
+ +
+ +
+ +
+ + + +
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + +

Methods

+ + + + + + +

(static) serve(graph, options) → {Promise.<object>}

+ + + + + + +
+ +
Description:
+
  • Start a server for the given project (sub-)tree.
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
graph + + +@ui5/project/graph/ProjectGraph + + + + + Project graph
options + + +object + + + + + Options +
Properties
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
port + + +number + + + + + + + + + + + + + Port to listen to
changePortIfInUse + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + If true, change the port if it is already in use
h2 + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Whether HTTP/2 should be used - defaults to http
key + + +string + + + + + + + <optional>
+ + + + + +
+ + Path to private key to be used for https
cert + + +string + + + + + + + <optional>
+ + + + + +
+ + Path to certificate to be used for for https
simpleIndex + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Use a simplified view for the server directory listing
acceptRemoteConnections + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + If true, listens to remote connections and + not only to localhost connections
sendSAPTargetCSP + + +boolean +| + +module:@ui5/server.SAPTargetCSPOptions + + + + + + + <optional>
+ + + + + +
+ + false + + If set to true or an object, then the default (or configured) + set of security policies that SAP and UI5 aim for (AKA 'target policies'), + are send for any requested *.html file
serveCSPReports + + +boolean + + + + + + + <optional>
+ + + + + +
+ + false + + Enable CSP reports serving for request url + '/.ui5/csp/csp-reports.json'
+ +
+ + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Promise resolving once the server is listening. + It resolves with an object containing the port, + h2-flag and a close function, + which can be used to stop the server. +
+ + + +
+
+ Type +
+
+ +Promise.<object> + + + +
+
+ + + + + + + + + +

Type Definitions

+ + + +

SAPTargetCSPOptions

+ + + + + +
+ +
Description:
+
  • SAP target CSP middleware options
+ + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDefaultDescription
defaultPolicy + + +string + + + + + + + <optional>
+ + + +
+ + "sap-target-level-1" + +
defaultPolicyIsReportOnly + + +string + + + + + + + <optional>
+ + + +
+ + true + +
defaultPolicy2 + + +string + + + + + + + <optional>
+ + + +
+ + "sap-target-level-3" + +
defaultPolicy2IsReportOnly + + +string + + + + + + + <optional>
+ + + +
+ + true + +
ignorePaths + + +Array.<string> + + + + + + + <optional>
+ + + +
+ + ["test-resources/sap/ui/qunit/testrunner.html"] + +
+ + + + + + +
+ SAP target CSP middleware options +
+ + + +
Type:
+
    +
  • + +object + + + +
  • +
+ + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/v3/api/project_lib_build_ProjectBuilder.js.html b/v3/api/project_lib_build_ProjectBuilder.js.html new file mode 100644 index 0000000000..13765de334 --- /dev/null +++ b/v3/api/project_lib_build_ProjectBuilder.js.html @@ -0,0 +1,551 @@ + + + + + + + project/lib/build/ProjectBuilder.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/build/ProjectBuilder.js

+ + + + + + + +
+
+
import {rimraf} from "rimraf";
+import * as resourceFactory from "@ui5/fs/resourceFactory";
+import BuildLogger from "@ui5/logger/internal/loggers/Build";
+const log = new BuildLogger("ProjectBuilder");
+import composeProjectList from "./helpers/composeProjectList.js";
+import BuildContext from "./helpers/BuildContext.js";
+import prettyHrtime from "pretty-hrtime";
+
+/**
+ * @public
+ * @class
+ * @alias @ui5/project/build/ProjectBuilder
+ */
+class ProjectBuilder {
+	/**
+	 * Build Configuration
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/build/ProjectBuilder~BuildConfiguration
+	 * @property {boolean} [selfContained=false] Flag to activate self contained build
+	 * @property {boolean} [cssVariables=false] Flag to activate CSS variables generation
+	 * @property {boolean} [jsdoc=false] Flag to activate JSDoc build
+	 * @property {boolean} [createBuildManifest=false]
+	 *   Whether to create a build manifest file for the root project.
+	 *   This is currently only supported for projects of type 'library' and 'theme-library'
+	 *   No other dependencies can be included in the build result.
+	 * @property {Array.<string>} [includedTasks=[]] List of tasks to be included
+	 * @property {Array.<string>} [excludedTasks=[]] List of tasks to be excluded.
+	 * 			If the wildcard '*' is provided, only the included tasks will be executed.
+	 */
+
+	/**
+	 * As an alternative to providing plain lists of names of dependencies to include and exclude, you can provide a
+	 * more complex "Dependency Includes" object to define which dependencies should be part of the build result.
+	 * <br>
+	 * This information is then used to compile lists of <code>includedDependencies</code> and
+	 * <code>excludedDependencies</code>, which are applied during the build process.
+	 * <br><br>
+	 * Regular expression-parameters are directly applied to a list of all project dependencies
+	 * so that they don't need to be evaluated in later processing steps.
+	 * <br><br>
+	 * Generally, includes are handled with a higher priority than excludes. Additionally, operations for processing
+	 * transitive dependencies are handled with a lower priority than explicitly mentioned dependencies. The "default"
+	 * dependency-includes are appended at the end.
+	 * <br><br>
+	 * The priority of the various dependency lists is applied in the following order.
+	 * Note that a later exclude can't overrule an earlier include.
+	 * <br>
+	 * <ol>
+	 *   <li><code>includeDependency</code>, <code>includeDependencyRegExp</code></li>
+	 *   <li><code>excludeDependency</code>, <code>excludeDependencyRegExp</code></li>
+	 *   <li><code>includeDependencyTree</code></li>
+	 *   <li><code>excludeDependencyTree</code></li>
+	 *   <li><code>defaultIncludeDependency</code>, <code>defaultIncludeDependencyRegExp</code>,
+	 *     <code>defaultIncludeDependencyTree</code></li>
+	 * </ol>
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/build/ProjectBuilder~DependencyIncludes
+	 * @property {boolean} includeAllDependencies
+	 *   Whether all dependencies should be part of the build result
+	 *	 This parameter has the lowest priority and basically includes all remaining (not excluded) projects as include
+	 * @property {string[]} includeDependency
+	 *   The dependencies to be considered in <code>includedDependencies</code>; the
+	 *   <code>*</code> character can be used as wildcard for all dependencies and
+	 *   is an alias for the CLI option <code>--all</code>
+	 * @property {string[]} includeDependencyRegExp
+	 *   Strings which are interpreted as regular expressions
+	 *   to describe the selection of dependencies to be considered in <code>includedDependencies</code>
+	 * @property {string[]} includeDependencyTree
+	 *   The dependencies to be considered in <code>includedDependencies</code>;
+	 *   transitive dependencies are also appended
+	 * @property {string[]} excludeDependency
+	 *   The dependencies to be considered in <code>excludedDependencies</code>
+	 * @property {string[]} excludeDependencyRegExp
+	 *   Strings which are interpreted as regular expressions
+	 *   to describe the selection of dependencies to be considered in <code>excludedDependencies</code>
+	 * @property {string[]} excludeDependencyTree
+	 *   The dependencies to be considered in <code>excludedDependencies</code>;
+	 *   transitive dependencies are also appended
+	 * @property {string[]} defaultIncludeDependency
+	 *   Same as <code>includeDependency</code> parameter;
+	 *   typically used in project build settings
+	 * @property {string[]} defaultIncludeDependencyRegExp
+	 *   Same as <code>includeDependencyRegExp</code> parameter;
+	 *   typically used in project build settings
+	 * @property {string[]} defaultIncludeDependencyTree
+	 *   Same as <code>includeDependencyTree</code> parameter;
+	 *   typically used in project build settings
+	 */
+
+	/**
+	 * Executes a project build, including all necessary or requested dependencies
+	 *
+	 * @public
+	 * @param {object} parameters
+	 * @param {@ui5/project/graph/ProjectGraph} parameters.graph Project graph
+	 * @param {@ui5/project/build/ProjectBuilder~BuildConfiguration} [parameters.buildConfig] Build configuration
+	 * @param {@ui5/builder/tasks/taskRepository} parameters.taskRepository Task Repository module to use
+	 */
+	constructor({graph, buildConfig, taskRepository}) {
+		if (!graph) {
+			throw new Error(`Missing parameter 'graph'`);
+		}
+		if (!taskRepository) {
+			throw new Error(`Missing parameter 'taskRepository'`);
+		}
+		if (!graph.isSealed()) {
+			throw new Error(
+				`Can not build project graph with root node ${graph.getRoot().getName()}: Graph is not sealed`);
+		}
+
+		this._graph = graph;
+		this._buildContext = new BuildContext(graph, taskRepository, buildConfig);
+	}
+
+	/**
+	 * Executes a project build, including all necessary or requested dependencies
+	 *
+	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.destPath Target path
+	 * @param {boolean} [parameters.cleanDest=false] Decides whether project should clean the target path before build
+	 * @param {Array.<string|RegExp>} [parameters.includedDependencies=[]]
+	 *   List of names of projects to include in the build result
+	 *   If the wildcard '*' is provided, all dependencies will be included in the build result.
+	 * @param {Array.<string|RegExp>} [parameters.excludedDependencies=[]]
+	 *   List of names of projects to exclude from the build result.
+	 * @param {@ui5/project/build/ProjectBuilder~DependencyIncludes} [parameters.dependencyIncludes]
+	 *   Alternative to the <code>includedDependencies</code> and <code>excludedDependencies</code> parameters.
+	 *   Allows for a more sophisticated configuration for defining which dependencies should be
+	 *   part of the build result. If this is provided, the other mentioned parameters are ignored.
+	 * @returns {Promise} Promise resolving once the build has finished
+	 */
+	async build({
+		destPath, cleanDest = false,
+		includedDependencies = [], excludedDependencies = [],
+		dependencyIncludes
+	}) {
+		if (!destPath) {
+			throw new Error(`Missing parameter 'destPath'`);
+		}
+		if (dependencyIncludes) {
+			if (includedDependencies.length || excludedDependencies.length) {
+				throw new Error(
+					"Parameter 'dependencyIncludes' can't be used in conjunction " +
+					"with parameters 'includedDependencies' or 'excludedDependencies");
+			}
+		}
+		const rootProjectName = this._graph.getRoot().getName();
+		log.info(`Preparing build for project ${rootProjectName}`);
+		log.info(`  Target directory: ${destPath}`);
+
+		// Get project filter function based on include/exclude params
+		// (also logs some info to console)
+		const filterProject = await this._getProjectFilter({
+			explicitIncludes: includedDependencies,
+			explicitExcludes: excludedDependencies,
+			dependencyIncludes
+		});
+
+		// Count total number of projects to build based on input
+		const requestedProjects = this._graph.getProjectNames().filter(function(projectName) {
+			return filterProject(projectName);
+		});
+
+		if (this._buildContext.getBuildConfig().createBuildManifest && requestedProjects.length > 1) {
+			throw new Error(
+				`It is currently not supported to request the creation of a build manifest ` +
+				`while including any dependencies into the build result`);
+		}
+
+		const projectBuildContexts = await this._createRequiredBuildContexts(requestedProjects);
+		const cleanupSigHooks = this._registerCleanupSigHooks();
+		const fsTarget = resourceFactory.createAdapter({
+			fsBasePath: destPath,
+			virBasePath: "/"
+		});
+
+		const queue = [];
+		const alreadyBuilt = [];
+
+		// Create build queue based on graph depth-first search to ensure correct build order
+		await this._graph.traverseDepthFirst(async ({project}) => {
+			const projectName = project.getName();
+			const projectBuildContext = projectBuildContexts.get(projectName);
+			if (projectBuildContext) {
+				// Build context exists
+				//	=> This project needs to be built or, in case it has already
+				//		been built, it's build result needs to be written out (if requested)
+				queue.push(projectBuildContext);
+				if (!projectBuildContext.requiresBuild()) {
+					alreadyBuilt.push(projectName);
+				}
+			}
+		});
+
+		log.setProjects(queue.map((projectBuildContext) => {
+			return projectBuildContext.getProject().getName();
+		}));
+		if (queue.length > 1) { // Do not log if only the root project is being built
+			log.info(`Processing ${queue.length} projects`);
+			if (alreadyBuilt.length) {
+				log.info(`  Reusing build results of ${alreadyBuilt.length} projects`);
+				log.info(`  Building ${queue.length - alreadyBuilt.length} projects`);
+			}
+
+			if (log.isLevelEnabled("verbose")) {
+				log.verbose(`  Required projects:`);
+				log.verbose(`    ${queue
+					.map((projectBuildContext) => {
+						const projectName = projectBuildContext.getProject().getName();
+						let msg;
+						if (alreadyBuilt.includes(projectName)) {
+							const buildMetadata = projectBuildContext.getBuildMetadata();
+							const ts = new Date(buildMetadata.timestamp).toUTCString();
+							msg = `*> ${projectName} /// already built at ${ts}`;
+						} else {
+							msg = `=> ${projectName}`;
+						}
+						return msg;
+					})
+					.join("\n    ")}`);
+			}
+		}
+
+		if (cleanDest) {
+			log.info(`Cleaning target directory...`);
+			await rimraf(destPath);
+		}
+		const startTime = process.hrtime();
+		try {
+			const pWrites = [];
+			for (const projectBuildContext of queue) {
+				const projectName = projectBuildContext.getProject().getName();
+				const projectType = projectBuildContext.getProject().getType();
+				log.verbose(`Processing project ${projectName}...`);
+
+				// Only build projects that are not already build (i.e. provide a matching build manifest)
+				if (alreadyBuilt.includes(projectName)) {
+					log.skipProjectBuild(projectName, projectType);
+				} else {
+					log.startProjectBuild(projectName, projectType);
+					await projectBuildContext.getTaskRunner().runTasks();
+					log.endProjectBuild(projectName, projectType);
+				}
+				if (!requestedProjects.includes(projectName)) {
+					// Project has not been requested
+					//	=> Its resources shall not be part of the build result
+					continue;
+				}
+
+				log.verbose(`Writing out files...`);
+				pWrites.push(this._writeResults(projectBuildContext, fsTarget));
+			}
+			await Promise.all(pWrites);
+			log.info(`Build succeeded in ${this._getElapsedTime(startTime)}`);
+		} catch (err) {
+			log.error(`Build failed in ${this._getElapsedTime(startTime)}`);
+			throw err;
+		} finally {
+			this._deregisterCleanupSigHooks(cleanupSigHooks);
+			await this._executeCleanupTasks();
+		}
+	}
+
+	async _createRequiredBuildContexts(requestedProjects) {
+		const requiredProjects = new Set(this._graph.getProjectNames().filter((projectName) => {
+			return requestedProjects.includes(projectName);
+		}));
+
+		const projectBuildContexts = new Map();
+
+		for (const projectName of requiredProjects) {
+			log.verbose(`Creating build context for project ${projectName}...`);
+			const projectBuildContext = this._buildContext.createProjectContext({
+				project: this._graph.getProject(projectName)
+			});
+
+			projectBuildContexts.set(projectName, projectBuildContext);
+
+			if (projectBuildContext.requiresBuild()) {
+				const taskRunner = projectBuildContext.getTaskRunner();
+				const requiredDependencies = await taskRunner.getRequiredDependencies();
+
+				if (requiredDependencies.size === 0) {
+					continue;
+				}
+				// This project needs to be built and required dependencies to be built as well
+				this._graph.getDependencies(projectName).forEach((depName) => {
+					if (projectBuildContexts.has(depName)) {
+						// Build context already exists
+						//	=> Dependency will be built
+						return;
+					}
+					if (!requiredDependencies.has(depName)) {
+						return;
+					}
+					// Add dependency to list of projects to build
+					requiredProjects.add(depName);
+				});
+			}
+		}
+
+		return projectBuildContexts;
+	}
+
+	async _getProjectFilter({
+		dependencyIncludes,
+		explicitIncludes,
+		explicitExcludes
+	}) {
+		const {includedDependencies, excludedDependencies} = await composeProjectList(
+			this._graph,
+			dependencyIncludes || {
+				includeDependencyTree: explicitIncludes,
+				excludeDependencyTree: explicitExcludes
+			}
+		);
+
+		if (includedDependencies.length) {
+			if (includedDependencies.length === this._graph.getSize() - 1) {
+				log.info(`  Including all dependencies`);
+			} else {
+				log.info(`  Requested dependencies:`);
+				log.info(`    + ${includedDependencies.join("\n    + ")}`);
+			}
+		}
+		if (excludedDependencies.length) {
+			log.info(`  Excluded dependencies:`);
+			log.info(`    - ${excludedDependencies.join("\n    + ")}`);
+		}
+
+		const rootProjectName = this._graph.getRoot().getName();
+		return function projectFilter(projectName) {
+			function projectMatchesAny(deps) {
+				return deps.some((dep) => dep instanceof RegExp ?
+					dep.test(projectName) : dep === projectName);
+			}
+
+			if (projectName === rootProjectName) {
+				// Always include the root project
+				return true;
+			}
+
+			if (projectMatchesAny(excludedDependencies)) {
+				return false;
+			}
+
+			if (includedDependencies.includes("*") || projectMatchesAny(includedDependencies)) {
+				return true;
+			}
+
+			return false;
+		};
+	}
+
+	async _writeResults(projectBuildContext, target) {
+		const project = projectBuildContext.getProject();
+		const taskUtil = projectBuildContext.getTaskUtil();
+		const buildConfig = this._buildContext.getBuildConfig();
+		const reader = project.getReader({
+			// Force buildtime (=namespaced) style when writing with a build manifest
+			style: taskUtil.isRootProject() && buildConfig.createBuildManifest ? "buildtime" : "dist"
+		});
+		const resources = await reader.byGlob("/**/*");
+
+		if (taskUtil.isRootProject() && buildConfig.createBuildManifest) {
+			// Create and write a build manifest metadata file
+			const {
+				default: createBuildManifest
+			} = await import("./helpers/createBuildManifest.js");
+			const metadata = await createBuildManifest(project, buildConfig, this._buildContext.getTaskRepository());
+			await target.write(resourceFactory.createResource({
+				path: `/.ui5/build-manifest.json`,
+				string: JSON.stringify(metadata, null, "\t")
+			}));
+		}
+
+		await Promise.all(resources.map((resource) => {
+			if (taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.OmitFromBuildResult)) {
+				log.silly(`Skipping write of resource tagged as "OmitFromBuildResult": ` +
+					resource.getPath());
+				return; // Skip target write for this resource
+			}
+			return target.write(resource);
+		}));
+	}
+
+	async _executeCleanupTasks() {
+		log.info("Executing cleanup tasks...");
+		await this._buildContext.executeCleanupTasks();
+	}
+
+	_registerCleanupSigHooks() {
+		const that = this;
+		function createListener(exitCode) {
+			return function() {
+				// Asynchronously cleanup resources, then exit
+				that._executeCleanupTasks().then(() => {
+					process.exit(exitCode);
+				});
+			};
+		}
+
+		const processSignals = {
+			"SIGHUP": createListener(128 + 1),
+			"SIGINT": createListener(128 + 2),
+			"SIGTERM": createListener(128 + 15),
+			"SIGBREAK": createListener(128 + 21)
+		};
+
+		for (const signal of Object.keys(processSignals)) {
+			process.on(signal, processSignals[signal]);
+		}
+
+		// TODO: Also cleanup for unhandled rejections and exceptions?
+		// Add additional events like signals since they are registered on the process
+		//	event emitter in a similar fashion
+		// processSignals["unhandledRejection"] = createListener(1);
+		// process.once("unhandledRejection", processSignals["unhandledRejection"]);
+		// processSignals["uncaughtException"] = function(err, origin) {
+		// 	const fs = require("fs");
+		// 	fs.writeSync(
+		// 		process.stderr.fd,
+		// 		`Caught exception: ${err}\n` +
+		// 		`Exception origin: ${origin}`
+		// 	);
+		// 	createListener(1)();
+		// };
+		// process.once("uncaughtException", processSignals["uncaughtException"]);
+
+		return processSignals;
+	}
+
+	_deregisterCleanupSigHooks(signals) {
+		for (const signal of Object.keys(signals)) {
+			process.removeListener(signal, signals[signal]);
+		}
+	}
+
+	/**
+	 * Calculates the elapsed build time and returns a prettified output
+	 *
+	 * @private
+	 * @param {Array} startTime Array provided by <code>process.hrtime()</code>
+	 * @returns {string} Difference between now and the provided time array as formatted string
+	 */
+	_getElapsedTime(startTime) {
+		const timeDiff = process.hrtime(startTime);
+		return prettyHrtime(timeDiff);
+	}
+}
+
+export default ProjectBuilder;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_build_helpers_TaskUtil.js.html b/v3/api/project_lib_build_helpers_TaskUtil.js.html new file mode 100644 index 0000000000..5e837da71f --- /dev/null +++ b/v3/api/project_lib_build_helpers_TaskUtil.js.html @@ -0,0 +1,444 @@ + + + + + + + project/lib/build/helpers/TaskUtil.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/build/helpers/TaskUtil.js

+ + + + + + + +
+
+
import {
+	createReaderCollection,
+	createReaderCollectionPrioritized,
+	createResource,
+	createFilterReader,
+	createLinkReader,
+	createFlatReader
+} from "@ui5/fs/resourceFactory";
+
+/**
+ * Convenience functions for UI5 tasks.
+ * An instance of this class is passed to every standard UI5 task that requires it.
+ *
+ * Custom tasks that define a specification version >= 2.2 will receive an interface
+ * to an instance of this class when called.
+ * The set of available functions on that interface depends on the specification
+ * version defined for the extension.
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/build/helpers/TaskUtil
+ * @hideconstructor
+ */
+class TaskUtil {
+	/**
+	 * Standard Build Tags. See UI5 Tooling
+	 * [RFC 0008]{@link https://github.com/SAP/ui5-tooling/blob/main/rfcs/0008-resource-tagging-during-build.md}
+	 * for details.
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/build/helpers/TaskUtil~StandardBuildTags
+	 * @property {string} OmitFromBuildResult
+	 * 		Setting this tag to true will prevent the resource from being written to the build target directory
+	 * @property {string} IsBundle
+	 * 		This tag identifies resources that contain (i.e. bundle) multiple other resources
+	 * @property {string} IsDebugVariant
+	 * 		This tag identifies resources that are a debug variant (typically named with a "-dbg" suffix)
+	 * 		of another resource. This tag is part of the build manifest.
+	 * @property {string} HasDebugVariant
+	 * 		This tag identifies resources for which a debug variant has been created.
+	 * 		This tag is part of the build manifest.
+	 */
+
+	/**
+	 * Since <code>@ui5/project/build/helpers/ProjectBuildContext</code> is a private class, TaskUtil must not be
+	 * instantiated by modules other than @ui5/project itself.
+	 *
+	 * @param {object} parameters
+	 * @param {@ui5/project/build/helpers/ProjectBuildContext} parameters.projectBuildContext ProjectBuildContext
+	 * @public
+	 */
+	constructor({projectBuildContext}) {
+		this._projectBuildContext = projectBuildContext;
+		/**
+		 * @member {@ui5/project/build/helpers/TaskUtil~StandardBuildTags}
+		 * @public
+		*/
+		this.STANDARD_TAGS = Object.freeze({
+			// "Project" tags:
+			// Will be stored on project instance and are hence part of the build manifest
+			IsDebugVariant: "ui5:IsDebugVariant",
+			HasDebugVariant: "ui5:HasDebugVariant",
+
+			// "Build" tags:
+			// Will be stored on the project build context
+			// They are only available to the build tasks of a single project
+			OmitFromBuildResult: "ui5:OmitFromBuildResult",
+			IsBundle: "ui5:IsBundle"
+		});
+	}
+
+	/**
+	 * Stores a tag with value for a given resource's path. Note that the tag is independent of the supplied
+	 * resource instance. For two resource instances with the same path, the same tag value is returned.
+	 * If the path of a resource is changed, any tag information previously stored for that resource is lost.
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 2.2 and above</b>.
+	 *
+	 * @param {@ui5/fs/Resource} resource Resource-instance the tag should be stored for
+	 * @param {string} tag Name of the tag. Currently only the
+	 * 	[STANDARD_TAGS]{@link @ui5/project/build/helpers/TaskUtil#STANDARD_TAGS} are allowed
+	 * @param {string|boolean|integer} [value=true] Tag value. Must be primitive
+	 * @public
+	 */
+	setTag(resource, tag, value) {
+		if (typeof resource === "string") {
+			throw new Error("Deprecated parameter: " +
+				"Since UI5 Tooling 3.0, #setTag requires a resource instance. Strings are no longer accepted");
+		}
+
+		const collection = this._projectBuildContext.getResourceTagCollection(resource, tag);
+		return collection.setTag(resource, tag, value);
+	}
+
+	/**
+	 * Retrieves the value for a stored tag. If no value is stored, <code>undefined</code> is returned.
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 2.2 and above</b>.
+	 *
+	 * @param {@ui5/fs/Resource} resource Resource-instance the tag should be retrieved for
+	 * @param {string} tag Name of the tag
+	 * @returns {string|boolean|integer|undefined} Tag value for the given resource.
+	 * 										<code>undefined</code> if no value is available
+	 * @public
+	 */
+	getTag(resource, tag) {
+		if (typeof resource === "string") {
+			throw new Error("Deprecated parameter: " +
+				"Since UI5 Tooling 3.0, #getTag requires a resource instance. Strings are no longer accepted");
+		}
+		const collection = this._projectBuildContext.getResourceTagCollection(resource, tag);
+		return collection.getTag(resource, tag);
+	}
+
+	/**
+	 * Clears the value of a tag stored for the given resource's path.
+	 * It's like the tag was never set for that resource.
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 2.2 and above</b>.
+	 *
+	 * @param {@ui5/fs/Resource} resource Resource-instance the tag should be cleared for
+	 * @param {string} tag Tag
+	 * @public
+	 */
+	clearTag(resource, tag) {
+		if (typeof resource === "string") {
+			throw new Error("Deprecated parameter: " +
+				"Since UI5 Tooling 3.0, #clearTag requires a resource instance. Strings are no longer accepted");
+		}
+		const collection = this._projectBuildContext.getResourceTagCollection(resource, tag);
+		return collection.clearTag(resource, tag);
+	}
+
+	/**
+	 * Check whether the project currently being built is the root project.
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 2.2 and above</b>.
+	 *
+	 * @returns {boolean} <code>true</code> if the currently built project is the root project
+	 * @public
+	 */
+	isRootProject() {
+		return this._projectBuildContext.isRootProject();
+	}
+
+	/**
+	 * Retrieves a build option defined by its <code>key</code.
+	 * If no option with the given <code>key</code> is stored, <code>undefined</code> is returned.
+	 *
+	 * @param {string} key The option key
+	 * @returns {any|undefined} The build option (or undefined)
+	 * @private
+	 */
+	getBuildOption(key) {
+		return this._projectBuildContext.getOption(key);
+	}
+
+	/**
+	 * Register a function that must be executed once the build is finished. This can be used to, for example,
+	 * clean up files temporarily created on the file system. If the callback returns a Promise, it will be waited for.
+	 * It will also be executed in cases where the build has failed or has been aborted.
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 2.2 and above</b>.
+	 *
+	 * @param {Function} callback Callback to register. If it returns a Promise, it will be waited for
+	 * @public
+	 */
+	registerCleanupTask(callback) {
+		return this._projectBuildContext.registerCleanupTask(callback);
+	}
+
+	/**
+	 * Specification Version-dependent [Project]{@link @ui5/project/specifications/Project} interface.
+	 * For details on individual functions, see [Project]{@link @ui5/project/specifications/Project}
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/build/helpers/TaskUtil~ProjectInterface
+	 * @property {Function} getType Get the project type
+	 * @property {Function} getName Get the project name
+	 * @property {Function} getVersion Get the project version
+	 * @property {Function} getNamespace Get the project namespace
+	 * @property {Function} getRootReader Get the project rootReader
+	 * @property {Function} getReader Get the project reader
+	 * @property {Function} getRootPath Get the local File System path of the project's root directory
+	 * @property {Function} getSourcePath Get the local File System path of the project's source directory
+	 * @property {Function} getCustomConfiguration Get the project Custom Configuration
+	 * @property {Function} isFrameworkProject Check whether the project is a UI5-Framework project
+	 * @property {Function} getFrameworkName Get the project's framework name configuration
+	 * @property {Function} getFrameworkVersion Get the project's framework version configuration
+	 * @property {Function} getFrameworkDependencies Get the project's framework dependencies configuration
+	 */
+
+	/**
+	 * Retrieve a single project from the dependency graph
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 3.0 and above</b>.
+	 *
+	 * @param {string|@ui5/fs/Resource} [projectNameOrResource]
+	 * Name of the project to retrieve or a Resource instance to retrieve the associated project for.
+	 * Defaults to the name of the project currently being built
+	 * @returns {@ui5/project/build/helpers/TaskUtil~ProjectInterface|undefined}
+	 * Specification Version-dependent interface to the Project instance or <code>undefined</code>
+	 * if the project name is unknown or the provided resource is not associated with any project.
+	 * @public
+	 */
+	getProject(projectNameOrResource) {
+		if (projectNameOrResource) {
+			if (typeof projectNameOrResource === "string" || projectNameOrResource instanceof String) {
+				// A project name has been provided
+				return this._projectBuildContext.getProject(projectNameOrResource);
+			} else {
+				// A Resource instance has been provided
+				return projectNameOrResource.getProject();
+			}
+		}
+		// No parameter has been provided, default to the project currently being built.
+		return this._projectBuildContext.getProject();
+	}
+
+	/**
+	 * Retrieve a list of direct dependencies of a given project from the dependency graph.
+	 * Note that this list does not include transitive dependencies.
+	 *
+	 * </br></br>
+	 * This method is only available to custom task extensions defining
+	 * <b>Specification Version 3.0 and above</b>.
+	 *
+	 * @param {string} [projectName] Name of the project to retrieve. Defaults to the project currently being built
+	 * @returns {string[]} Names of all direct dependencies
+	 * @throws {Error} If the requested project is unknown to the graph
+	 * @public
+	 */
+	getDependencies(projectName) {
+		return this._projectBuildContext.getDependencies(projectName);
+	}
+
+	/**
+	 * Specification Version-dependent set of [@ui5/fs/resourceFactory]{@link @ui5/fs/resourceFactory}
+	 * functions provided to tasks.
+	 * For details on individual functions, see [@ui5/fs/resourceFactory]{@link @ui5/fs/resourceFactory}
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/build/helpers/TaskUtil~resourceFactory
+	 * @property {Function} createResource Creates a [Resource]{@link @ui5/fs/Resource}.
+	 * 	Accepts the same parameters as the [Resource]{@link @ui5/fs/Resource} constructor.
+	 * @property {Function} createReaderCollection Creates a reader collection:
+	 *	[ReaderCollection]{@link @ui5/fs/ReaderCollection}
+	 * @property {Function} createReaderCollectionPrioritized Creates a prioritized reader collection:
+	 *	[ReaderCollectionPrioritized]{@link @ui5/fs/ReaderCollectionPrioritized}
+	 * @property {Function} createFilterReader
+	 * 	Create a [Filter-Reader]{@link @ui5/fs/readers/Filter} with the given reader.
+	 * @property {Function} createLinkReader
+	 * 	Create a [Link-Reader]{@link @ui5/fs/readers/Filter} with the given reader.
+	 * @property {Function} createFlatReader Create a [Link-Reader]{@link @ui5/fs/readers/Link}
+	 * where all requests are prefixed with <code>/resources/<namespace></code>.
+	 */
+
+	/**
+	 * Provides limited access to [@ui5/fs/resourceFactory]{@link @ui5/fs/resourceFactory} functions
+	 *
+	 * </br></br>
+	 * This attribute is only available to custom task extensions defining
+	 * <b>Specification Version 3.0 and above</b>.
+	 *
+	 * @type {@ui5/project/build/helpers/TaskUtil~resourceFactory}
+	 * @public
+	 */
+	resourceFactory = {
+		createResource,
+		createReaderCollection,
+		createReaderCollectionPrioritized,
+		createFilterReader,
+		createLinkReader,
+		createFlatReader,
+	};
+
+	/**
+	 * Get an interface to an instance of this class that only provides those functions
+	 * that are supported by the given custom task extension specification version.
+	 *
+	 * @param {@ui5/project/specifications/SpecificationVersion} specVersion
+	 * SpecVersionComparator instance of the custom task
+	 * @returns {object} An object with bound instance methods supported by the given specification version
+	 */
+	getInterface(specVersion) {
+		if (specVersion.lte("2.1")) {
+			// Tasks defining specVersion <= 2.1 do not have access to any TaskUtil APIs
+			return undefined;
+		}
+
+		const baseInterface = {
+			STANDARD_TAGS: this.STANDARD_TAGS,
+		};
+		bindFunctions(this, baseInterface, [
+			"setTag", "clearTag", "getTag", "isRootProject", "registerCleanupTask"
+		]);
+
+		if (specVersion.gte("3.0")) {
+			// getProject function, returning an interfaced project instance
+			baseInterface.getProject = (projectName) => {
+				const project = this.getProject(projectName);
+				const baseProjectInterface = {};
+				bindFunctions(project, baseProjectInterface, [
+					"getType", "getName", "getVersion", "getNamespace",
+					"getRootReader", "getReader", "getRootPath", "getSourcePath",
+					"getCustomConfiguration", "isFrameworkProject", "getFrameworkName",
+					"getFrameworkVersion", "getFrameworkDependencies"
+				]);
+				return baseProjectInterface;
+			};
+			// getDependencies function, returning an array of project names
+			baseInterface.getDependencies = (projectName) => {
+				return this.getDependencies(projectName);
+			};
+
+			baseInterface.resourceFactory = Object.create(null);
+			[
+				// Once new functions get added, extract this array into a variable
+				// and enhance based on spec version once new functions get added
+				"createResource", "createReaderCollection", "createReaderCollectionPrioritized",
+				"createFilterReader", "createLinkReader", "createFlatReader",
+			].forEach((factoryFunction) => {
+				baseInterface.resourceFactory[factoryFunction] = this.resourceFactory[factoryFunction];
+			});
+		}
+		return baseInterface;
+	}
+}
+
+function bindFunctions(sourceObject, targetObject, funcNames) {
+	funcNames.forEach((funcName) => {
+		targetObject[funcName] = sourceObject[funcName].bind(sourceObject);
+	});
+}
+
+export default TaskUtil;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_config_Configuration.js.html b/v3/api/project_lib_config_Configuration.js.html new file mode 100644 index 0000000000..2435805890 --- /dev/null +++ b/v3/api/project_lib_config_Configuration.js.html @@ -0,0 +1,203 @@ + + + + + + + project/lib/config/Configuration.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/config/Configuration.js

+ + + + + + + +
+
+
import path from "node:path";
+import os from "node:os";
+
+/**
+ * Provides basic configuration settings for @ui5/project/ui5Framework/* resolvers.
+ * Reads/writes configuration from/to ~/.ui5rc
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/config/Configuration
+ */
+class Configuration {
+	#mavenSnapshotEndpointUrl;
+
+	/**
+	 * @param {object} configuration
+	 * @param {string} [configuration.mavenSnapshotEndpointUrl]
+	 */
+	constructor({mavenSnapshotEndpointUrl}) {
+		this.#mavenSnapshotEndpointUrl = mavenSnapshotEndpointUrl;
+	}
+
+	/**
+	 * Maven Repository Snapshot URL.
+	 * Used to download artifacts and packages from Maven's build-snapshots URL.
+	 *
+	 * @public
+	 * @returns {string}
+	 */
+	getMavenSnapshotEndpointUrl() {
+		return this.#mavenSnapshotEndpointUrl;
+	}
+
+	/**
+	 * @public
+	 * @returns {object} The configuration in a JSON format
+	 */
+	toJson() {
+		return {
+			mavenSnapshotEndpointUrl: this.#mavenSnapshotEndpointUrl,
+		};
+	}
+
+	/**
+	 * Creates Configuration from a JSON file
+	 *
+	 * @public
+	 * @static
+	 * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file
+	 * @returns {Promise<@ui5/project/config/Configuration>} Configuration instance
+	 */
+	static async fromFile(filePath) {
+		filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc"));
+
+		const {default: fs} = await import("graceful-fs");
+		const {promisify} = await import("node:util");
+		const readFile = promisify(fs.readFile);
+		let config;
+		try {
+			const fileContent = await readFile(filePath);
+			if (!fileContent.length) {
+				config = {};
+			} else {
+				config = JSON.parse(fileContent);
+			}
+		} catch (err) {
+			if (err.code === "ENOENT") {
+				// "File or directory does not exist"
+				config = {};
+			} else {
+				throw new Error(
+					`Failed to read UI5 Tooling configuration from ${filePath}: ${err.message}`, {
+						cause: err
+					});
+			}
+		}
+		return new Configuration(config);
+	}
+
+	/**
+	 * Saves Configuration to a JSON file
+	 *
+	 * @public
+	 * @static
+	 * @param {@ui5/project/config/Configuration} config Configuration to save
+	 * @param {string} [filePath="~/.ui5rc"] Path to configuration JSON file
+	 * @returns {Promise<void>}
+	 */
+	static async toFile(config, filePath) {
+		filePath = filePath || path.resolve(path.join(os.homedir(), ".ui5rc"));
+
+		const {default: fs} = await import("graceful-fs");
+		const {promisify} = await import("node:util");
+		const writeFile = promisify(fs.writeFile);
+
+		try {
+			return writeFile(filePath, JSON.stringify(config.toJson()));
+		} catch (err) {
+			throw new Error(
+				`Failed to write UI5 Tooling configuration to ${filePath}: ${err.message}`, {
+					cause: err
+				});
+		}
+	}
+}
+
+export default Configuration;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_ProjectGraph.js.html b/v3/api/project_lib_graph_ProjectGraph.js.html new file mode 100644 index 0000000000..b5ea0b1b28 --- /dev/null +++ b/v3/api/project_lib_graph_ProjectGraph.js.html @@ -0,0 +1,733 @@ + + + + + + + project/lib/graph/ProjectGraph.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/ProjectGraph.js

+ + + + + + + +
+
+
import {getLogger} from "@ui5/logger";
+const log = getLogger("graph:ProjectGraph");
+
+/**
+ * A rooted, directed graph representing a UI5 project, its dependencies and available extensions.
+ * <br><br>
+ * While it allows defining cyclic dependencies, both traversal functions will throw an error if they encounter cycles.
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/graph/ProjectGraph
+ */
+class ProjectGraph {
+	/**
+	 * @public
+	 * @param {object} parameters Parameters
+	 * @param {string} parameters.rootProjectName Root project name
+	 */
+	constructor({rootProjectName}) {
+		if (!rootProjectName) {
+			throw new Error(`Could not create ProjectGraph: Missing or empty parameter 'rootProjectName'`);
+		}
+		this._rootProjectName = rootProjectName;
+
+		this._projects = new Map(); // maps project name to instance (= nodes)
+		this._adjList = new Map(); // maps project name to dependencies (= edges)
+		this._optAdjList = new Map(); // maps project name to optional dependencies (= edges)
+
+		this._extensions = new Map(); // maps extension name to instance
+
+		this._sealed = false;
+		this._hasUnresolvedOptionalDependencies = false; // Performance optimization flag
+		this._taskRepository = null;
+	}
+
+	/**
+	 * Get the root project of the graph
+	 *
+	 * @public
+	 * @returns {@ui5/project/specifications/Project} Root project
+	 */
+	getRoot() {
+		const rootProject = this._projects.get(this._rootProjectName);
+		if (!rootProject) {
+			throw new Error(`Unable to find root project with name ${this._rootProjectName} in project graph`);
+		}
+		return rootProject;
+	}
+
+	/**
+	 * Add a project to the graph
+	 *
+	 * @public
+	 * @param {@ui5/project/specifications/Project} project Project which should be added to the graph
+	 */
+	addProject(project) {
+		this._checkSealed();
+		const projectName = project.getName();
+		if (this._projects.has(projectName)) {
+			throw new Error(
+				`Failed to add project ${projectName} to graph: A project with that name has already been added`);
+		}
+		if (!isNaN(projectName)) {
+			// Reject integer-like project names. They would take precedence when traversing object keys which
+			// could lead to unexpected behavior. We don't really expect anyone to use such names anyways
+			throw new Error(
+				`Failed to add project ${projectName} to graph: Project name must not be integer-like`);
+		}
+		log.verbose(`Adding project: ${projectName}`);
+		this._projects.set(projectName, project);
+		this._adjList.set(projectName, new Set());
+		this._optAdjList.set(projectName, new Set());
+	}
+
+	/**
+	 * Retrieve a single project from the dependency graph
+	 *
+	 * @public
+	 * @param {string} projectName Name of the project to retrieve
+	 * @returns {@ui5/project/specifications/Project|undefined}
+	 *					project instance or undefined if the project is unknown to the graph
+	 */
+	getProject(projectName) {
+		return this._projects.get(projectName);
+	}
+
+	/**
+	 * Get all projects in the graph
+	 *
+	 * @public
+	 * @returns {Iterable.<@ui5/project/specifications/Project>}
+	 */
+	getProjects() {
+		return this._projects.values();
+	}
+
+	/**
+	 * Get names of all projects in the graph
+	 *
+	 * @public
+	 * @returns {string[]} Names of all projects
+	 */
+	getProjectNames() {
+		return Array.from(this._projects.keys());
+	}
+
+	/**
+	 * Get the number of projects in the graph
+	 *
+	 * @public
+	 * @returns {integer} Count of projects in the graph
+	 */
+	getSize() {
+		return this._projects.size;
+	}
+
+	/**
+	 * Add an extension to the graph
+	 *
+	 * @public
+	 * @param {@ui5/project/specifications/Extension} extension Extension which should be available in the graph
+	 */
+	addExtension(extension) {
+		this._checkSealed();
+		const extensionName = extension.getName();
+		if (this._extensions.has(extensionName)) {
+			throw new Error(
+				`Failed to add extension ${extensionName} to graph: ` +
+				`An extension with that name has already been added`);
+		}
+		if (!isNaN(extensionName)) {
+			// Reject integer-like extension names. They would take precedence when traversing object keys which
+			// might lead to unexpected behavior in the future. We don't really expect anyone to use such names anyways
+			throw new Error(
+				`Failed to add extension ${extensionName} to graph: Extension name must not be integer-like`);
+		}
+		this._extensions.set(extensionName, extension);
+	}
+
+	/**
+	 * @public
+	 * @param {string} extensionName Name of the extension to retrieve
+	 * @returns {@ui5/project/specifications/Extension|undefined}
+	 *					Extension instance or undefined if the extension is unknown to the graph
+	 */
+	getExtension(extensionName) {
+		return this._extensions.get(extensionName);
+	}
+
+	/**
+	 * Get all extensions in the graph
+	 *
+	 * @public
+	 * @returns {Iterable.<@ui5/project/specifications/Extension>}
+	 */
+	getExtensions() {
+		return this._extensions.values();
+	}
+
+	/**
+	 * Get names of all extensions in the graph
+	 *
+	 * @public
+	 * @returns {string[]} Names of all extensions
+	 */
+	getExtensionNames() {
+		return Array.from(this._extensions.keys());
+	}
+
+	/**
+	 * Declare a dependency from one project in the graph to another
+	 *
+	 * @public
+	 * @param {string} fromProjectName Name of the depending project
+	 * @param {string} toProjectName Name of project on which the other depends
+	 */
+	declareDependency(fromProjectName, toProjectName) {
+		this._checkSealed();
+		try	{
+			log.verbose(`Declaring dependency: ${fromProjectName} depends on ${toProjectName}`);
+			this._declareDependency(this._adjList, fromProjectName, toProjectName);
+		} catch (err) {
+			throw new Error(
+				`Failed to declare dependency from project ${fromProjectName} to ${toProjectName}: ` +
+				err.message);
+		}
+	}
+
+
+	/**
+	 * Declare a dependency from one project in the graph to another
+	 *
+	 * @public
+	 * @param {string} fromProjectName Name of the depending project
+	 * @param {string} toProjectName Name of project on which the other depends
+	 */
+	declareOptionalDependency(fromProjectName, toProjectName) {
+		this._checkSealed();
+		try	{
+			log.verbose(`Declaring optional dependency: ${fromProjectName} depends on ${toProjectName}`);
+			this._declareDependency(this._optAdjList, fromProjectName, toProjectName);
+			this._hasUnresolvedOptionalDependencies = true;
+		} catch (err) {
+			throw new Error(
+				`Failed to declare optional dependency from project ${fromProjectName} to ${toProjectName}: ` +
+				err.message);
+		}
+	}
+
+	/**
+	 * Declare a dependency from one project in the graph to another
+	 *
+	 * @param {object} map Adjacency map to use
+	 * @param {string} fromProjectName Name of the depending project
+	 * @param {string} toProjectName Name of project on which the other depends
+	 */
+	_declareDependency(map, fromProjectName, toProjectName) {
+		if (!this._projects.has(fromProjectName)) {
+			throw new Error(
+				`Unable to find depending project with name ${fromProjectName} in project graph`);
+		}
+		if (!this._projects.has(toProjectName)) {
+			throw new Error(
+				`Unable to find dependency project with name ${toProjectName} in project graph`);
+		}
+		if (fromProjectName === toProjectName) {
+			throw new Error(
+				`A project can't depend on itself`);
+		}
+		const adjacencies = map.get(fromProjectName);
+		if (adjacencies.has(toProjectName)) {
+			log.warn(`Dependency has already been declared: ${fromProjectName} depends on ${toProjectName}`);
+		} else {
+			adjacencies.add(toProjectName);
+		}
+	}
+
+	/**
+	 * Get all direct dependencies of a project as an array of project names
+	 *
+	 * @public
+	 * @param {string} projectName Name of the project to retrieve the dependencies of
+	 * @returns {string[]} Names of all direct dependencies
+	 */
+	getDependencies(projectName) {
+		const adjacencies = this._adjList.get(projectName);
+		if (!adjacencies) {
+			throw new Error(
+				`Failed to get dependencies for project ${projectName}: ` +
+				`Unable to find project in project graph`);
+		}
+		return Array.from(adjacencies);
+	}
+
+	/**
+	 * Get all (direct and transitive) dependencies of a project as an array of project names
+	 *
+	 * @public
+	 * @param {string} projectName Name of the project to retrieve the dependencies of
+	 * @returns {string[]} Names of all direct and transitive dependencies
+	 */
+	getTransitiveDependencies(projectName) {
+		const dependencies = new Set();
+		if (!this._projects.has(projectName)) {
+			throw new Error(
+				`Failed to get transitive dependencies for project ${projectName}: ` +
+				`Unable to find project in project graph`);
+		}
+
+		const processDependency = (depName) => {
+			const adjacencies = this._adjList.get(depName);
+			adjacencies.forEach((depName) => {
+				if (!dependencies.has(depName)) {
+					dependencies.add(depName);
+					processDependency(depName);
+				}
+			});
+		};
+
+		processDependency(projectName);
+		return Array.from(dependencies);
+	}
+	/**
+	 * Checks whether a dependency is optional or not.
+	 * Currently only used in tests.
+	 *
+	 * @private
+	 * @param {string} fromProjectName Name of the depending project
+	 * @param {string} toProjectName Name of project on which the other depends
+	 * @returns {boolean} True if the dependency is currently optional
+	 */
+	isOptionalDependency(fromProjectName, toProjectName) {
+		const adjacencies = this._adjList.get(fromProjectName);
+		if (!adjacencies) {
+			throw new Error(
+				`Failed to determine whether dependency from ${fromProjectName} to ${toProjectName} ` +
+				`is optional: ` +
+				`Unable to find project with name ${fromProjectName} in project graph`);
+		}
+		if (adjacencies.has(toProjectName)) {
+			return false;
+		}
+		const optAdjacencies = this._optAdjList.get(fromProjectName);
+		if (optAdjacencies.has(toProjectName)) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Transforms any optional dependencies declared in the graph to non-optional dependency, if the target
+	 * can already be reached from the root project.
+	 *
+	 * @public
+	 */
+	async resolveOptionalDependencies() {
+		this._checkSealed();
+		if (!this._hasUnresolvedOptionalDependencies) {
+			log.verbose(`Skipping resolution of optional dependencies since none have been declared`);
+			return;
+		}
+		log.verbose(`Resolving optional dependencies...`);
+
+		// First collect all projects that are currently reachable from the root project (=all non-optional projects)
+		const resolvedProjects = new Set();
+		await this.traverseBreadthFirst(({project}) => {
+			resolvedProjects.add(project.getName());
+		});
+
+		let unresolvedOptDeps = false;
+		for (const [fromProjectName, optDependencies] of this._optAdjList) {
+			for (const toProjectName of optDependencies) {
+				if (resolvedProjects.has(toProjectName)) {
+					// Target node is already reachable in the graph
+					// => Resolve optional dependency
+					log.verbose(`Resolving optional dependency from ${fromProjectName} to ${toProjectName}...`);
+
+					if (this._adjList.get(toProjectName).has(fromProjectName)) {
+						log.verbose(
+							`  Cyclic optional dependency detected: ${toProjectName} already has a non-optional ` +
+							`dependency to ${fromProjectName}`);
+						log.verbose(
+							`  Optional dependency from ${fromProjectName} to ${toProjectName} ` +
+							`will not be declared as it would introduce a cycle`);
+						unresolvedOptDeps = true;
+					} else {
+						this.declareDependency(fromProjectName, toProjectName);
+						// This optional dependency has now been resolved
+						// => Remove it from the list of optional dependencies
+						optDependencies.delete(toProjectName);
+					}
+				} else {
+					unresolvedOptDeps = true;
+				}
+			}
+		}
+		if (!unresolvedOptDeps) {
+			this._hasUnresolvedOptionalDependencies = false;
+		}
+	}
+
+	/**
+	 * Callback for graph traversal operations
+	 *
+	 * @public
+	 * @async
+	 * @callback @ui5/project/graph/ProjectGraph~traversalCallback
+	 * @param {object} parameters Parameters passed to the callback
+	 * @param {@ui5/project/specifications/Project} parameters.project
+	 *   Project that is currently visited
+	 * @param {string[]} parameters.dependencies
+	 *   Array containing the names of all direct dependencies of the project
+	 * @returns {Promise|undefined} If a promise is returned,
+	 *   graph traversal will wait and only continue once the promise has resolved.
+	 */
+
+	/**
+	 * Visit every project in the graph that can be reached by the given entry project exactly once.
+	 * The entry project defaults to the root project.
+	 * In case a cycle is detected, an error is thrown
+	 *
+	 * @public
+	 * @param {string} [startName] Name of the project to start the traversal at. Defaults to the graph's root project
+	 * @param {@ui5/project/graph/ProjectGraph~traversalCallback} callback Will be called
+	 */
+	async traverseBreadthFirst(startName, callback) {
+		if (!callback) {
+			// Default optional first parameter
+			callback = startName;
+			startName = this._rootProjectName;
+		}
+
+		if (!this.getProject(startName)) {
+			throw new Error(`Failed to start graph traversal: Could not find project ${startName} in project graph`);
+		}
+
+		const queue = [{
+			projectNames: [startName],
+			ancestors: []
+		}];
+
+		const visited = Object.create(null);
+
+		while (queue.length) {
+			const {projectNames, ancestors} = queue.shift(); // Get and remove first entry from queue
+
+			await Promise.all(projectNames.map(async (projectName) => {
+				this._checkCycle(ancestors, projectName);
+
+				if (visited[projectName]) {
+					return visited[projectName];
+				}
+
+				return visited[projectName] = (async () => {
+					const newAncestors = [...ancestors, projectName];
+					const dependencies = this.getDependencies(projectName);
+
+					queue.push({
+						projectNames: dependencies,
+						ancestors: newAncestors
+					});
+
+					await callback({
+						project: this.getProject(projectName),
+						dependencies
+					});
+				})();
+			}));
+		}
+	}
+
+	/**
+	 * Visit every project in the graph that can be reached by the given entry project exactly once.
+	 * The entry project defaults to the root project.
+	 * In case a cycle is detected, an error is thrown
+	 *
+	 * @public
+	 * @param {string} [startName] Name of the project to start the traversal at. Defaults to the graph's root project
+	 * @param {@ui5/project/graph/ProjectGraph~traversalCallback} callback Will be called
+	 */
+	async traverseDepthFirst(startName, callback) {
+		if (!callback) {
+			// Default optional first parameter
+			callback = startName;
+			startName = this._rootProjectName;
+		}
+
+		if (!this.getProject(startName)) {
+			throw new Error(`Failed to start graph traversal: Could not find project ${startName} in project graph`);
+		}
+		return this._traverseDepthFirst(startName, Object.create(null), [], callback);
+	}
+
+	async _traverseDepthFirst(projectName, visited, ancestors, callback) {
+		this._checkCycle(ancestors, projectName);
+
+		if (visited[projectName]) {
+			return visited[projectName];
+		}
+		return visited[projectName] = (async () => {
+			const newAncestors = [...ancestors, projectName];
+			const dependencies = this.getDependencies(projectName);
+			await Promise.all(dependencies.map((depName) => {
+				return this._traverseDepthFirst(depName, visited, newAncestors, callback);
+			}));
+
+			await callback({
+				project: this.getProject(projectName),
+				dependencies
+			});
+		})();
+	}
+
+	/**
+	 * Join another project graph into this one.
+	 * Projects and extensions which already exist in this graph will cause an error to be thrown
+	 *
+	 * @public
+	 * @param {@ui5/project/graph/ProjectGraph} projectGraph Project Graph to merge into this one
+	 */
+	join(projectGraph) {
+		try {
+			this._checkSealed();
+			if (!projectGraph.isSealed()) {
+				// Seal input graph to prevent further modification
+				log.verbose(
+					`Sealing project graph with root project ${projectGraph._rootProjectName} ` +
+					`before joining it into project graph with root project ${this._rootProjectName}...`);
+				projectGraph.seal();
+			}
+			mergeMap(this._projects, projectGraph._projects);
+			mergeMap(this._extensions, projectGraph._extensions);
+			mergeMap(this._adjList, projectGraph._adjList);
+			mergeMap(this._optAdjList, projectGraph._optAdjList);
+
+			this._hasUnresolvedOptionalDependencies =
+				this._hasUnresolvedOptionalDependencies || projectGraph._hasUnresolvedOptionalDependencies;
+		} catch (err) {
+			throw new Error(
+				`Failed to join project graph with root project ${projectGraph._rootProjectName} into ` +
+				`project graph with root project ${this._rootProjectName}: ${err.message}`);
+		}
+	}
+
+	// Only to be used by @ui5/builder tests to inject its version of the taskRepository
+	setTaskRepository(taskRepository) {
+		this._taskRepository = taskRepository;
+	}
+
+	async _getTaskRepository() {
+		if (!this._taskRepository) {
+			this._taskRepository = await import("@ui5/builder/internal/taskRepository");
+		}
+		return this._taskRepository;
+	}
+
+	/**
+	 * Executes a build on the graph
+	 *
+	 * @public
+	 * @param {object} parameters Build parameters
+	 * @param {string} parameters.destPath Target path
+	 * @param {boolean} [parameters.cleanDest=false] Decides whether project should clean the target path before build
+	 * @param {Array.<string|RegExp>} [parameters.includedDependencies=[]]
+	 *			List of names of projects to include in the build result
+	 *			If the wildcard '*' is provided, all dependencies will be included in the build result.
+	 * @param {Array.<string|RegExp>} [parameters.excludedDependencies=[]]
+	 *			List of names of projects to exclude from the build result.
+	 * @param {@ui5/project/build/ProjectBuilder~DependencyIncludes} [parameters.dependencyIncludes]
+	 *   Alternative to the <code>includedDependencies</code> and <code>excludedDependencies</code> parameters.
+	 *   Allows for a more sophisticated configuration for defining which dependencies should be
+	 *   part of the build result. If this is provided, the other mentioned parameters will be ignored.
+	 * @param {boolean} [parameters.selfContained=false] Flag to activate self contained build
+	 * @param {boolean} [parameters.cssVariables=false] Flag to activate CSS variables generation
+	 * @param {boolean} [parameters.jsdoc=false] Flag to activate JSDoc build
+	 * @param {boolean} [parameters.createBuildManifest=false]
+	 * 			Whether to create a build manifest file for the root project.
+	 *			This is currently only supported for projects of type 'library' and 'theme-library'
+	 * @param {Array.<string>} [parameters.includedTasks=[]] List of tasks to be included
+	 * @param {Array.<string>} [parameters.excludedTasks=[]] List of tasks to be excluded.
+	 * 			If the wildcard '*' is provided, only the included tasks will be executed.
+	 * @returns {Promise} Promise resolving to <code>undefined</code> once build has finished
+	 */
+	async build({
+		destPath, cleanDest = false,
+		includedDependencies = [], excludedDependencies = [],
+		dependencyIncludes,
+		selfContained = false, cssVariables = false, jsdoc = false, createBuildManifest = false,
+		includedTasks = [], excludedTasks = []
+	}) {
+		this.seal(); // Do not allow further changes to the graph
+		if (this._built) {
+			throw new Error(
+				`Project graph with root node ${this._rootProjectName} has already been built. ` +
+				`Each graph can only be built once`);
+		}
+		this._built = true;
+		const {
+			default: ProjectBuilder
+		} = await import("../build/ProjectBuilder.js");
+		const builder = new ProjectBuilder({
+			graph: this,
+			taskRepository: await this._getTaskRepository(),
+			buildConfig: {
+				selfContained, cssVariables, jsdoc,
+				createBuildManifest,
+				includedTasks, excludedTasks,
+			}
+		});
+		await builder.build({
+			destPath, cleanDest,
+			includedDependencies, excludedDependencies,
+			dependencyIncludes,
+		});
+	}
+
+	/**
+	 * Seal the project graph so that no further changes can be made to it
+	 *
+	 * @public
+	 */
+	seal() {
+		this._sealed = true;
+	}
+
+	/**
+	 * Check whether the project graph has been sealed.
+	 * This means the graph is read-only. Neither projects, nor dependencies between projects
+	 * can be added or removed.
+	 *
+	 * @public
+	 * @returns {boolean} True if the project graph has been sealed
+	 */
+	isSealed() {
+		return this._sealed;
+	}
+
+	/**
+	 * Helper function to check and throw in case the project graph has been sealed.
+	 * Intended for use in any function that attempts to make changes to the graph.
+	 *
+	 * @throws Throws in case the project graph has been sealed
+	 */
+	_checkSealed() {
+		if (this._sealed) {
+			throw new Error(`Project graph with root node ${this._rootProjectName} has been sealed and is read-only`);
+		}
+	}
+
+	_checkCycle(ancestors, projectName) {
+		if (ancestors.includes(projectName)) {
+			// "Back-edge" detected. Neither BFS nor DFS searches should continue
+			// Mark first and last occurrence in chain with an asterisk and throw an error detailing the
+			// problematic dependency chain
+			ancestors[ancestors.indexOf(projectName)] = `*${projectName}*`;
+			throw new Error(`Detected cyclic dependency chain: ${ancestors.join(" -> ")} -> *${projectName}*`);
+		}
+	}
+
+	// TODO: introduce function to check for dangling nodes/consistency in general?
+}
+
+function mergeMap(target, source) {
+	for (const [key, value] of source) {
+		if (target.has(key)) {
+			throw new Error(`Failed to merge map: Key '${key}' already present in target set`);
+		}
+		if (value instanceof Set) {
+			// Shallow-clone any Sets
+			target.set(key, new Set(value));
+		} else {
+			target.set(key, value);
+		}
+	}
+}
+
+export default ProjectGraph;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_Workspace.js.html b/v3/api/project_lib_graph_Workspace.js.html new file mode 100644 index 0000000000..dd6131759e --- /dev/null +++ b/v3/api/project_lib_graph_Workspace.js.html @@ -0,0 +1,374 @@ + + + + + + + project/lib/graph/Workspace.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/Workspace.js

+ + + + + + + +
+
+
import fs from "graceful-fs";
+import {globby, isDynamicPattern} from "globby";
+import path from "node:path";
+import {promisify} from "node:util";
+import {getLogger} from "@ui5/logger";
+import Module from "./Module.js";
+import {validateWorkspace} from "../validation/validator.js";
+
+const readFile = promisify(fs.readFile);
+const log = getLogger("graph:Workspace");
+
+
+/**
+ * Workspace configuration. For details, refer to the
+ * [UI5 Workspaces documentation]{@link https://sap.github.io/ui5-tooling/v3/pages/Workspace/#configuration}
+ *
+ * @public
+ * @typedef {object} @ui5/project/graph/Workspace~Configuration
+ * @property {string} node.specVersion Workspace Specification Version
+ * @property {object} node.metadata
+ * @property {string} node.metadata.name Name of the workspace configuration
+ * @property {object} node.dependencyManagement
+ * @property {@ui5/project/graph/Workspace~DependencyManagementResolutions[]} node.dependencyManagement.resolutions
+ */
+
+/**
+ * A resolution entry for the dependency management section of the workspace configuration
+ *
+ * @public
+ * @typedef {object} @ui5/project/graph/Workspace~DependencyManagementResolution
+ * @property {string} path Relative path to use for the workspace resolution process
+ */
+
+/**
+ * UI5 Workspace
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/graph/Workspace
+ */
+class Workspace {
+	#visitedNodePaths = new Set();
+	#configValidated = false;
+	#configuration;
+	#cwd;
+
+	/**
+	 * @public
+	 * @param {object} options
+	 * @param {string} options.cwd Path to use for resolving all paths of the workspace configuration from.
+	 *   This should contain platform-specific path separators (i.e. must not be POSIX on non-POSIX systems)
+	 * @param {@ui5/project/graph/Workspace~Configuration} options.configuration
+	 *   Workspace configuration
+	 */
+	constructor({cwd, configuration}) {
+		if (!cwd) {
+			throw new Error(`Could not create Workspace: Missing or empty parameter 'cwd'`);
+		}
+		if (!configuration) {
+			throw new Error(`Could not create Workspace: Missing or empty parameter 'configuration'`);
+		}
+
+		this.#cwd = cwd;
+		this.#configuration = configuration;
+	}
+
+	/**
+	 * Get the name of this workspace
+	 *
+	 * @public
+	 * @returns {string} Name of this workspace configuration
+	 */
+	getName() {
+		return this.#configuration.metadata.name;
+	}
+
+	/**
+	 * Returns an array of [Module]{@ui5/project/graph/Module} instances found in the configured
+	 * dependency-management resolution paths of this workspace, sorted by module ID.
+	 *
+	 * @public
+	 * @returns {Promise<@ui5/project/graph/Module[]>}
+	 *   Array of Module instances sorted by module ID
+	 */
+	async getModules() {
+		const {moduleIdMap} = await this._getResolvedModules();
+		const sortedMap = new Map([...moduleIdMap].sort((a, b) => String(a[0]).localeCompare(b[0])));
+		return Array.from(sortedMap.values());
+	}
+
+	/**
+	 * For a given project name (e.g. the value of the <code>metadata.name</code> property in a ui5.yaml),
+	 * returns a [Module]{@ui5/project/graph/Module} instance or <code>undefined</code> depending on whether the project
+	 * has been found in the configured dependency-management resolution paths of this workspace
+	 *
+	 * @public
+	 * @param {string} projectName Name of the project
+	 * @returns {Promise<@ui5/project/graph/Module|undefined>}
+	 *   Module instance, or <code>undefined</code> if none is found
+	 */
+	async getModuleByProjectName(projectName) {
+		const {projectNameMap} = await this._getResolvedModules();
+		return projectNameMap.get(projectName);
+	}
+
+	/**
+	 * For a given node id (e.g. the value of the name property in a package.json),
+	 * returns a [Module]{@ui5/project/graph/Module} instance or <code>undefined</code> depending on whether the module
+	 * has been found in the configured dependency-management resolution paths of this workspace
+	 * and contains at least one project or extension
+	 *
+	 * @public
+	 * @param {string} nodeId Node ID of the module
+	 * @returns {Promise<@ui5/project/graph/Module|undefined>}
+	 *   Module instance, or <code>undefined</code> if none is found
+	 */
+	async getModuleByNodeId(nodeId) {
+		const {moduleIdMap} = await this._getResolvedModules();
+		return moduleIdMap.get(nodeId);
+	}
+
+	_getResolvedModules() {
+		if (this._pResolvedModules) {
+			return this._pResolvedModules;
+		}
+
+		return this._pResolvedModules = this._resolveModules();
+	}
+
+	async _resolveModules() {
+		await this._validateConfig();
+		const resolutions = this.#configuration.dependencyManagement?.resolutions;
+		if (!resolutions?.length) {
+			return {
+				projectNameMap: new Map(),
+				moduleIdMap: new Map()
+			};
+		}
+
+		let resolvedModules = await Promise.all(resolutions.map(async (resolutionConfig) => {
+			if (!resolutionConfig.path) {
+				throw new Error(
+					`Missing property 'path' in dependency resolution configuration of workspace ${this.getName()}`);
+			}
+			return await this._getModulesFromPath(
+				this.#cwd, resolutionConfig.path);
+		}));
+
+		// Flatten array since package-workspaces might have resolved to multiple modules for a single resolution
+		resolvedModules = Array.prototype.concat.apply([], resolvedModules);
+
+		const projectNameMap = new Map();
+		const moduleIdMap = new Map();
+		await Promise.all(resolvedModules.map(async (module) => {
+			const {project, extensions} = await module.getSpecifications();
+			if (project || extensions.length) {
+				moduleIdMap.set(module.getId(), module);
+			} else {
+				log.warn(
+					`Failed to create a project or extensions from module ${module.getId()} at ${module.getPath()}`);
+			}
+			if (project) {
+				projectNameMap.set(project.getName(), module);
+				log.verbose(`Module ${module.getId()} contains project ${project.getName()}`);
+			}
+			if (extensions.length) {
+				const extensionNames = extensions.map((e) => e.getName()).join(", ");
+				log.verbose(`Module ${module.getId()} contains extensions: ${extensionNames}`);
+			}
+		}));
+		return {
+			projectNameMap,
+			moduleIdMap
+		};
+	}
+
+	async _getModulesFromPath(cwd, relPath, failOnMissingFiles = true) {
+		const nodePath = path.join(cwd, relPath);
+		if (this.#visitedNodePaths.has(nodePath)) {
+			log.verbose(`Module located at ${nodePath} has already been visited`);
+			return [];
+		}
+		this.#visitedNodePaths.add(nodePath);
+		let pkg;
+		try {
+			pkg = await this._readPackageJson(nodePath);
+			if (!pkg?.name || !pkg?.version) {
+				throw new Error(
+					`package.json must contain fields 'name' and 'version'`);
+			}
+		} catch (err) {
+			if (!failOnMissingFiles && err.code === "ENOENT") {
+				// When resolving a dynamic workspace pattern (not a static path), ignore modules that
+				// are missing a package.json (this might simply indicate an empty directory)
+				log.verbose(`Ignoring module at path ${nodePath}: Directory does not contain a package.json`);
+				return [];
+			}
+			throw new Error(
+				`Failed to resolve workspace dependency resolution path ${relPath} to ${nodePath}: ${err.message}`);
+		}
+
+		// If the package.json defines an npm "workspaces", or an equivalent "ui5.workspaces" configuration,
+		// resolve the workspace and only use the resulting modules. The root package is ignored.
+		const packageWorkspaceConfig = pkg.ui5?.workspaces || pkg.workspaces;
+		if (packageWorkspaceConfig?.length) {
+			log.verbose(`Module ${pkg.name} provides a package.json workspaces configuration. ` +
+				`Ignoring the module and resolving workspaces instead...`);
+			const staticPatterns = [];
+			// Split provided patterns into dynamic and static patterns
+			// This is necessary, since fast-glob currently behaves different from
+			// 	"glob" (used by @npmcli/map-workspaces) in that it does not match the
+			// 	base directory in case it is equal to the pattern (https://github.com/mrmlnc/fast-glob/issues/47)
+			// For example a pattern "package-a" would not match a directory called
+			// 	"package-a" in the root directory of the project.
+			// 	We therefore detect the static pattern and resolve it directly
+			const dynamicPatterns = packageWorkspaceConfig.filter((pattern) => {
+				if (isDynamicPattern(pattern)) {
+					return true;
+				} else {
+					staticPatterns.push(pattern);
+					return false;
+				}
+			});
+
+			let searchPaths = [];
+			if (dynamicPatterns.length) {
+				searchPaths = await globby(dynamicPatterns, {
+					cwd: nodePath,
+					followSymbolicLinks: false,
+					onlyDirectories: true,
+				});
+			}
+			searchPaths.push(...staticPatterns);
+
+			const resolvedModules = new Map();
+			await Promise.all(searchPaths.map(async (pkgPath) => {
+				const modules = await this._getModulesFromPath(nodePath, pkgPath, staticPatterns.includes(pkgPath));
+				modules.forEach((module) => {
+					const id = module.getId();
+					if (!resolvedModules.get(id)) {
+						resolvedModules.set(id, module);
+					}
+				});
+			}));
+			return Array.from(resolvedModules.values());
+		} else {
+			return [new Module({
+				id: pkg.name,
+				version: pkg.version,
+				modulePath: nodePath
+			})];
+		}
+	}
+
+	/**
+	 * Reads the package.json file and returns its content
+	 *
+	 * @private
+	 * @param {string} modulePath Path to the module containing the package.json
+	 * @returns {object} Package json content
+	 */
+	async _readPackageJson(modulePath) {
+		const content = await readFile(path.join(modulePath, "package.json"), "utf8");
+		return JSON.parse(content);
+	}
+
+	async _validateConfig() {
+		if (this.#configValidated) {
+			return;
+		}
+		await validateWorkspace({
+			config: this.#configuration
+		});
+		this.#configValidated = true;
+	}
+}
+
+export default Workspace;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_graph.js.html b/v3/api/project_lib_graph_graph.js.html new file mode 100644 index 0000000000..6a4d3ae8d9 --- /dev/null +++ b/v3/api/project_lib_graph_graph.js.html @@ -0,0 +1,338 @@ + + + + + + + project/lib/graph/graph.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/graph.js

+ + + + + + + +
+
+
import path from "node:path";
+import projectGraphBuilder from "./projectGraphBuilder.js";
+import ui5Framework from "./helpers/ui5Framework.js";
+import createWorkspace from "./helpers/createWorkspace.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("generateProjectGraph");
+
+/**
+ * Helper module to create a [@ui5/project/graph/ProjectGraph]{@link @ui5/project/graph/ProjectGraph}
+ * from a directory
+ *
+ * @public
+ * @module @ui5/project/graph
+ */
+
+/**
+ * Generates a [@ui5/project/graph/ProjectGraph]{@link @ui5/project/graph/ProjectGraph} by resolving
+ * dependencies from package.json files and configuring projects from ui5.yaml files
+ *
+ * @public
+ * @static
+ * @param {object} [options]
+ * @param {string} [options.cwd=process.cwd()] Directory to start searching for the root module
+ * @param {object} [options.rootConfiguration]
+ *		Configuration object to use for the root module instead of reading from a configuration file
+ * @param {string} [options.rootConfigPath]
+ *		Configuration file to use for the root module instead the default ui5.yaml. Either a path relative to
+ *		<code>cwd</code> or an absolute path. In both case, platform-specific path segment separators must be used.
+ * @param {string} [options.versionOverride] Framework version to use instead of the one defined in the root project
+ * @param {string} [options.resolveFrameworkDependencies=true]
+ * 		Whether framework dependencies should be added to the graph
+ * @param {string} [options.workspaceName]
+ * 		Name of the workspace configuration that should be used if any is provided
+ * @param {module:@ui5/project/ui5Framework/maven/CacheMode} [options.cacheMode]
+ *      Cache mode to use when consuming SNAPSHOT versions of a framework
+ * @param {string} [options.workspaceConfigPath=ui5-workspace.yaml]
+ * 		Workspace configuration file to use if no object has been provided
+ * @param {@ui5/project/graph/Workspace~Configuration} [options.workspaceConfiguration]
+ * 		Workspace configuration object to use instead of reading from a configuration file.
+ * 		Parameter <code>workspaceName</code> can either be omitted or has to match with the given configuration name
+ * @returns {Promise<@ui5/project/graph/ProjectGraph>} Promise resolving to a Project Graph instance
+ */
+export async function graphFromPackageDependencies({
+	cwd, rootConfiguration, rootConfigPath,
+	versionOverride, cacheMode, resolveFrameworkDependencies = true,
+	workspaceName /* TODO 4.0: default workspaceName to "default" ? */,
+	workspaceConfiguration, workspaceConfigPath = "ui5-workspace.yaml"
+}) {
+	log.verbose(`Creating project graph using npm provider...`);
+	const {
+		default: NpmProvider
+	} = await import("./providers/NodePackageDependencies.js");
+
+	cwd = cwd ? path.resolve(cwd) : process.cwd();
+	rootConfigPath = utils.resolveConfigPath(cwd, rootConfigPath);
+
+	let workspace;
+	if (workspaceName || workspaceConfiguration) {
+		workspace = await createWorkspace({
+			cwd,
+			name: workspaceName,
+			configObject: workspaceConfiguration,
+			configPath: workspaceConfigPath
+		});
+	}
+
+	const provider = new NpmProvider({
+		cwd,
+		rootConfiguration,
+		rootConfigPath
+	});
+
+	const projectGraph = await projectGraphBuilder(provider, workspace);
+
+	if (resolveFrameworkDependencies) {
+		await ui5Framework.enrichProjectGraph(projectGraph, {versionOverride, cacheMode, workspace});
+	}
+
+	return projectGraph;
+}
+
+/**
+ * Generates a [@ui5/project/graph/ProjectGraph]{@link @ui5/project/graph/ProjectGraph} from a
+ * YAML file following the structure of
+ * [@ui5/project/graph/providers/DependencyTree~TreeNode]{@link @ui5/project/graph/providers/DependencyTree~TreeNode}.
+ *
+ * Documentation:
+ * [Static Dependency Definition]{@link https://sap.github.io/ui5-tooling/stable/pages/Overview/#static-dependency-definition}
+ *
+ * @public
+ * @static
+ * @param {object} options
+ * @param {object} [options.filePath=projectDependencies.yaml] Path to the dependency configuration file
+ * @param {string} [options.cwd=process.cwd()] Directory to resolve relative paths to
+ * @param {object} [options.rootConfiguration]
+ *		Configuration object to use for the root module instead of reading from a configuration file
+ * @param {string} [options.rootConfigPath]
+ *		Configuration file to use for the root module instead the default ui5.yaml. Either a path relative to
+ *		<code>cwd</code> or an absolute path. In both case, platform-specific path segment separators must be used.
+ * @param {string} [options.versionOverride] Framework version to use instead of the one defined in the root project
+ * @param {module:@ui5/project/ui5Framework/maven/CacheMode} [options.cacheMode]
+ *      Cache mode to use when consuming SNAPSHOT versions of a framework
+ * @param {string} [options.resolveFrameworkDependencies=true]
+ *		Whether framework dependencies should be added to the graph
+ * @returns {Promise<@ui5/project/graph/ProjectGraph>} Promise resolving to a Project Graph instance
+ */
+export async function graphFromStaticFile({
+	filePath = "projectDependencies.yaml", cwd,
+	rootConfiguration, rootConfigPath,
+	versionOverride, cacheMode, resolveFrameworkDependencies = true
+}) {
+	log.verbose(`Creating project graph using static file...`);
+	const {
+		default: DependencyTreeProvider
+	} = await import("./providers/DependencyTree.js");
+
+	cwd = cwd ? path.resolve(cwd) : process.cwd();
+	rootConfigPath = utils.resolveConfigPath(cwd, rootConfigPath);
+
+	const dependencyTree = await utils.readDependencyConfigFile(cwd, filePath);
+
+	const provider = new DependencyTreeProvider({
+		dependencyTree,
+		rootConfiguration,
+		rootConfigPath
+	});
+
+	const projectGraph = await projectGraphBuilder(provider);
+
+	if (resolveFrameworkDependencies) {
+		await ui5Framework.enrichProjectGraph(projectGraph, {versionOverride, cacheMode});
+	}
+
+	return projectGraph;
+}
+
+/**
+ * Generates a [@ui5/project/graph/ProjectGraph]{@link @ui5/project/graph/ProjectGraph} from the
+ * given <code>dependencyTree</code> following the structure of
+ * [@ui5/project/graph/providers/DependencyTree~TreeNode]{@link @ui5/project/graph/providers/DependencyTree~TreeNode}
+ *
+ * @public
+ * @static
+ * @param {object} options
+ * @param {@ui5/project/graph/providers/DependencyTree~TreeNode} options.dependencyTree
+ * @param {string} [options.cwd=process.cwd()] Directory to resolve relative paths to
+ * @param {object} [options.rootConfiguration]
+ *		Configuration object to use for the root module instead of reading from a configuration file
+ * @param {string} [options.rootConfigPath]
+ *		Configuration file to use for the root module instead the default ui5.yaml. Either a path relative to
+ *		<code>cwd</code> or an absolute path. In both case, platform-specific path segment separators must be used.
+ * @param {string} [options.versionOverride] Framework version to use instead of the one defined in the root project
+ * @param {module:@ui5/project/ui5Framework/maven/CacheMode} [options.cacheMode]
+ *      Cache mode to use when consuming SNAPSHOT versions of a framework
+ * @param {string} [options.resolveFrameworkDependencies=true]
+ *		Whether framework dependencies should be added to the graph
+ * @returns {Promise<@ui5/project/graph/ProjectGraph>} Promise resolving to a Project Graph instance
+*/
+export async function graphFromObject({
+	dependencyTree, cwd,
+	rootConfiguration, rootConfigPath,
+	versionOverride, cacheMode, resolveFrameworkDependencies = true
+}) {
+	log.verbose(`Creating project graph using object...`);
+	const {
+		default: DependencyTreeProvider
+	} = await import("./providers/DependencyTree.js");
+
+	cwd = cwd ? path.resolve(cwd) : process.cwd();
+	rootConfigPath = utils.resolveConfigPath(cwd, rootConfigPath);
+
+	const dependencyTreeProvider = new DependencyTreeProvider({
+		dependencyTree,
+		rootConfiguration,
+		rootConfigPath
+	});
+
+	const projectGraph = await projectGraphBuilder(dependencyTreeProvider);
+
+	if (resolveFrameworkDependencies) {
+		await ui5Framework.enrichProjectGraph(projectGraph, {versionOverride, cacheMode});
+	}
+
+	return projectGraph;
+}
+
+const utils = {
+	resolveConfigPath: function(cwd, configPath) {
+		if (configPath && !path.isAbsolute(configPath)) {
+			configPath = path.join(cwd, configPath);
+		}
+		return configPath;
+	},
+	readDependencyConfigFile: async function(cwd, filePath) {
+		const {
+			default: fs
+		} = await import("graceful-fs");
+		const {promisify} = await import("util");
+		const readFile = promisify(fs.readFile);
+		const parseYaml =(await import("js-yaml")).load;
+
+		filePath = utils.resolveConfigPath(cwd, filePath);
+
+		let dependencyTree;
+		try {
+			const contents = await readFile(filePath, {encoding: "utf-8"});
+			dependencyTree = parseYaml(contents, {
+				filename: filePath
+			});
+			utils.resolveProjectPaths(cwd, dependencyTree);
+		} catch (err) {
+			throw new Error(
+				`Failed to load dependency tree configuration from path ${filePath}: ${err.message}`);
+		}
+		return dependencyTree;
+	},
+
+	resolveProjectPaths: function(cwd, project) {
+		if (!project.path) {
+			throw new Error(`Missing or empty attribute 'path' for project ${project.id}`);
+		}
+		project.path = path.resolve(cwd, project.path);
+
+		if (!project.id) {
+			throw new Error(`Missing or empty attribute 'id' for project with path ${project.path}`);
+		}
+		if (!project.version) {
+			throw new Error(`Missing or empty attribute 'version' for project ${project.id}`);
+		}
+
+		if (project.dependencies) {
+			project.dependencies.forEach((project) => utils.resolveProjectPaths(cwd, project));
+		}
+		return project;
+	}
+};
+
+// Export function for testing only
+/* istanbul ignore else */
+if (process.env.NODE_ENV === "test") {
+	graphFromStaticFile._utils = utils;
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_helpers_ui5Framework.js.html b/v3/api/project_lib_graph_helpers_ui5Framework.js.html new file mode 100644 index 0000000000..21cd8f1212 --- /dev/null +++ b/v3/api/project_lib_graph_helpers_ui5Framework.js.html @@ -0,0 +1,510 @@ + + + + + + + project/lib/graph/helpers/ui5Framework.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/helpers/ui5Framework.js

+ + + + + + + +
+
+
import Module from "../Module.js";
+import ProjectGraph from "../ProjectGraph.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("graph:helpers:ui5Framework");
+
+class ProjectProcessor {
+	constructor({libraryMetadata, graph, workspace}) {
+		this._libraryMetadata = libraryMetadata;
+		this._graph = graph;
+		this._workspace = workspace;
+		this._projectGraphPromises = Object.create(null);
+	}
+	async addProjectToGraph(libName, ancestors) {
+		if (ancestors) {
+			this._checkCycle(ancestors, libName);
+		}
+		if (this._projectGraphPromises[libName]) {
+			return this._projectGraphPromises[libName];
+		}
+		return this._projectGraphPromises[libName] = this._addProjectToGraph(libName, ancestors);
+	}
+	async _addProjectToGraph(libName, ancestors = []) {
+		log.verbose(`Creating project for library ${libName}...`);
+
+		if (!this._libraryMetadata[libName]) {
+			throw new Error(`Failed to find library ${libName} in dist packages metadata.json`);
+		}
+
+		const depMetadata = this._libraryMetadata[libName];
+		const graph = this._graph;
+
+		if (graph.getProject(libName)) {
+			// Already added
+			return;
+		}
+
+		const dependencies = await Promise.all(depMetadata.dependencies.map(async (depName) => {
+			await this.addProjectToGraph(depName, [...ancestors, libName]);
+			return depName;
+		}));
+
+		if (depMetadata.optionalDependencies) {
+			const resolvedOptionals = await Promise.all(depMetadata.optionalDependencies.map(async (depName) => {
+				if (this._libraryMetadata[depName]) {
+					log.verbose(`Resolving optional dependency ${depName} for project ${libName}...`);
+					await this.addProjectToGraph(depName, [...ancestors, libName]);
+					return depName;
+				}
+			}));
+
+			dependencies.push(...resolvedOptionals.filter(($)=>$));
+		}
+
+		let projectIsFromWorkspace = false;
+		let ui5Module;
+		if (this._workspace) {
+			ui5Module = await this._workspace.getModuleByProjectName(libName);
+			if (ui5Module) {
+				log.info(`Resolved project ${libName} via ${this._workspace.getName()} workspace ` +
+					`to version ${ui5Module.getVersion()}`);
+				log.verbose(`  Resolved module ${libName} to path ${ui5Module.getPath()}`);
+				log.verbose(`  Requested version was: ${depMetadata.version}`);
+				projectIsFromWorkspace = true;
+			}
+		}
+
+		if (!ui5Module) {
+			ui5Module = new Module({
+				id: depMetadata.id,
+				version: depMetadata.version,
+				modulePath: depMetadata.path
+			});
+		}
+		const {project} = await ui5Module.getSpecifications();
+		graph.addProject(project);
+		dependencies.forEach((dependency) => {
+			graph.declareDependency(libName, dependency);
+		});
+		if (projectIsFromWorkspace) {
+			// Add any dependencies that are only declared in the workspace resolved project
+			// Do not remove superfluous dependencies (might be added later though)
+			await Promise.all(project.getFrameworkDependencies().map(async ({name, optional, development}) => {
+				// Only proceed with dependencies which are not "optional" or "development",
+				// and not already listed in the dependencies of the original node
+				if (optional || development || dependencies.includes(name)) {
+					return;
+				}
+
+				if (!this._libraryMetadata[name]) {
+					throw new Error(
+						`Unable to find dependency ${name}, required by project ${project.getName()} ` +
+						`(resolved via ${this._workspace.getName()} workspace) in current set of libraries. ` +
+						`Try adding it temporarily to the root project's dependencies`);
+				}
+
+				await this.addProjectToGraph(name, [...ancestors, libName]);
+				graph.declareDependency(libName, name);
+			}));
+		}
+	}
+	_checkCycle(ancestors, projectName) {
+		if (ancestors.includes(projectName)) {
+			// "Back-edge" detected. This would cause a deadlock
+			// Mark first and last occurrence in chain with an asterisk and throw an error detailing the
+			// problematic dependency chain
+			ancestors[ancestors.indexOf(projectName)] = `*${projectName}*`;
+			throw new Error(
+				`ui5Framework:ProjectPreprocessor: Detected cyclic dependency chain: ` +
+				`${ancestors.join(" -> ")} -> *${projectName}*`);
+		}
+	}
+}
+
+const utils = {
+	shouldIncludeDependency({optional, development}, root) {
+		// Root project should include all dependencies
+		// Otherwise only non-optional and non-development dependencies should be included
+		return root || (optional !== true && development !== true);
+	},
+	async getFrameworkLibrariesFromGraph(projectGraph) {
+		const ui5Dependencies = [];
+		const rootProject = projectGraph.getRoot();
+		await projectGraph.traverseBreadthFirst(async ({project}) => {
+			if (project !== rootProject && project.isFrameworkProject()) {
+				// Ignoring UI5 Framework libraries in dependencies
+				return;
+			}
+			// No need to check for specVersion since Specification API is >= 2.0 anyways
+			const frameworkDependencies = project.getFrameworkDependencies();
+			if (!frameworkDependencies.length) {
+				log.verbose(`Project ${project.getName()} has no framework dependencies`);
+				// Possible future enhancement: Fallback to detect OpenUI5 framework dependencies in package.json
+				return;
+			}
+
+			frameworkDependencies.forEach((dependency) => {
+				if (!ui5Dependencies.includes(dependency.name) &&
+						utils.shouldIncludeDependency(dependency, project === rootProject)) {
+					ui5Dependencies.push(dependency.name);
+				}
+			});
+		});
+		return ui5Dependencies;
+	},
+	async declareFrameworkDependenciesInGraph(projectGraph) {
+		const rootProject = projectGraph.getRoot();
+		await projectGraph.traverseBreadthFirst(async ({project}) => {
+			if (project !== rootProject && project.isFrameworkProject()) {
+				// Ignoring UI5 Framework libraries in dependencies
+				return;
+			}
+			// No need to check for specVersion since Specification API is >= 2.0 anyways
+			const frameworkDependencies = project.getFrameworkDependencies();
+
+			if (!frameworkDependencies.length) {
+				log.verbose(`Project ${project.getName()} has no framework dependencies`);
+				// Possible future enhancement: Fallback to detect OpenUI5 framework dependencies in package.json
+				return;
+			}
+
+			const isRoot = project === rootProject;
+			frameworkDependencies.forEach((dependency) => {
+				if (isRoot || !dependency.development) {
+					// Root project should include all dependencies
+					// Otherwise all non-development dependencies should be considered
+
+					if (isRoot) {
+						// Check for deprecated/internal dependencies of the root project
+						const depProject = projectGraph.getProject(dependency.name);
+						if (depProject && depProject.isDeprecated() && rootProject.getName() !== "testsuite") {
+							// No warning for testsuite projects
+							log.warn(`Dependency ${depProject.getName()} is deprecated ` +
+								`and should not be used for new projects!`);
+						}
+						if (depProject && depProject.isSapInternal() && !rootProject.getAllowSapInternal()) {
+							// Do not warn if project defines "allowSapInternal"
+							log.warn(`Dependency ${depProject.getName()} is restricted for use by ` +
+								`SAP internal projects only! ` +
+								`If the project ${rootProject.getName()} is an SAP internal project, ` +
+								`add the attribute "allowSapInternal: true" to its metadata configuration`);
+						}
+					}
+					if (!isRoot && dependency.optional) {
+						if (projectGraph.getProject(dependency.name)) {
+							projectGraph.declareOptionalDependency(project.getName(), dependency.name);
+						}
+					} else {
+						projectGraph.declareDependency(project.getName(), dependency.name);
+					}
+				}
+			});
+		});
+		await projectGraph.resolveOptionalDependencies();
+	},
+	checkForDuplicateFrameworkProjects(projectGraph, frameworkGraph) {
+		// Check for duplicate framework libraries
+		const projectGraphProjectNames = projectGraph.getProjectNames();
+		const duplicateFrameworkProjectNames = frameworkGraph.getProjectNames()
+			.filter((name) => projectGraphProjectNames.includes(name));
+
+		if (duplicateFrameworkProjectNames.length) {
+			throw new Error(
+				`Duplicate framework dependency definition(s) found for project ${projectGraph.getRoot().getName()}: ` +
+				`${duplicateFrameworkProjectNames.join(", ")}.\n` +
+				`Framework libraries should only be referenced via ui5.yaml configuration. ` +
+				`Neither the root project, nor any of its dependencies should include them as direct ` +
+				`dependencies (e.g. via package.json).`
+			);
+		}
+	},
+	/**
+	 * This logic needs to stay in sync with the dependency definitions for the
+	 * sapui5/distribution-metadata package.
+	 *
+	 * @param {@ui5/project/specifications/Project} project
+	 */
+	async getFrameworkLibraryDependencies(project) {
+		let dependencies = [];
+		let optionalDependencies = [];
+
+		if (project.getId().startsWith("@sapui5/")) {
+			project.getFrameworkDependencies().forEach((dependency) => {
+				if (dependency.optional) {
+					// Add optional dependency to optionalDependencies
+					optionalDependencies.push(dependency.name);
+				} else if (!dependency.development) {
+					// Add non-development dependency to dependencies
+					dependencies.push(dependency.name);
+				}
+			});
+		} else if (project.getId().startsWith("@openui5/")) {
+			const packageResource = await project.getRootReader().byPath("/package.json");
+			const packageInfo = JSON.parse(await packageResource.getString());
+
+			dependencies = Object.keys(
+				packageInfo.dependencies || {}
+			).map(($) => $.replace("@openui5/", "")); // @sapui5 dependencies must not be defined in package.json
+			optionalDependencies = Object.keys(
+				packageInfo.devDependencies || {}
+			).map(($) => $.replace("@openui5/", "")); // @sapui5 dependencies must not be defined in package.json
+		}
+
+		return {dependencies, optionalDependencies};
+	},
+	async getWorkspaceFrameworkLibraryMetadata({workspace, projectGraph}) {
+		const libraryMetadata = Object.create(null);
+		const ui5Modules = await workspace.getModules();
+		for (const ui5Module of ui5Modules) {
+			const {project} = await ui5Module.getSpecifications();
+			// Only framework projects that are not already part of the projectGraph should be handled.
+			// Otherwise they would be available twice which is checked
+			// after installing via checkForDuplicateFrameworkProjects
+			if (project?.isFrameworkProject?.() && !projectGraph.getProject(project.getName())) {
+				const metadata = libraryMetadata[project.getName()] = Object.create(null);
+				metadata.id = project.getId();
+				metadata.path = project.getRootPath();
+				metadata.version = project.getVersion();
+				const {dependencies, optionalDependencies} = await utils.getFrameworkLibraryDependencies(project);
+				metadata.dependencies = dependencies;
+				metadata.optionalDependencies = optionalDependencies;
+			}
+		}
+		return libraryMetadata;
+	},
+	ProjectProcessor
+};
+
+/**
+ *
+ *
+ * @private
+ * @module @ui5/project/helpers/ui5Framework
+ */
+export default {
+	/**
+	 *
+	 *
+	 * @public
+	 * @param {@ui5/project/graph/ProjectGraph} projectGraph
+	 * @param {object} [options]
+	 * @param {string} [options.versionOverride] Framework version to use instead of the root projects framework
+	 *   version
+	 * @param {module:@ui5/project/ui5Framework/maven/CacheMode} [options.cacheMode]
+ 	 *   Cache mode to use when consuming SNAPSHOT versions of a framework
+	 * @param {@ui5/project/graph/Workspace} [options.workspace]
+	 *   Optional workspace instance to use for overriding node resolutions
+	 * @returns {Promise<@ui5/project/graph/ProjectGraph>}
+	 *   Promise resolving with the given graph instance to allow method chaining
+	 */
+	enrichProjectGraph: async function(projectGraph, options = {}) {
+		const {workspace, cacheMode} = options;
+		const rootProject = projectGraph.getRoot();
+		const frameworkName = rootProject.getFrameworkName();
+		const frameworkVersion = rootProject.getFrameworkVersion();
+
+		// It is allowed to omit the framework version in ui5.yaml and only provide one via the override
+		// This is a common use case for framework libraries, which generally should not define a
+		// framework version in their respective ui5.yaml
+		let version = options.versionOverride || frameworkVersion;
+
+		if (rootProject.isFrameworkProject() && !version) {
+			// If the root project is a framework project and no framework version is defined,
+			// all framework dependencies must either be already part of the graph or part of the workspace.
+			// A mixed setup of framework deps within the graph AND from the workspace is currently not supported.
+
+			const someDependencyMissing = rootProject.getFrameworkDependencies().some((dep) => {
+				return utils.shouldIncludeDependency(dep) && !projectGraph.getProject(dep.name);
+			});
+
+			// If all dependencies are available there is nothing else to do here.
+			// In case of a workspace setup, the resolver will be created below without a version and
+			// will succeed in case no library needs to be actually installed.
+			if (!someDependencyMissing) {
+				return projectGraph;
+			}
+		}
+
+
+		if (!frameworkName && !frameworkVersion) {
+			log.verbose(`Root project ${rootProject.getName()} has no framework configuration. Nothing to do here`);
+			return projectGraph;
+		}
+
+		if (frameworkName !== "SAPUI5" && frameworkName !== "OpenUI5") {
+			throw new Error(
+				`Unknown framework.name "${frameworkName}" for project ${rootProject.getName()}. ` +
+				`Must be "OpenUI5" or "SAPUI5"`
+			);
+		}
+
+		let Resolver;
+		if (version && version.toLowerCase().endsWith("-snapshot")) {
+			Resolver = (await import("../../ui5Framework/Sapui5MavenSnapshotResolver.js")).default;
+		} else if (frameworkName === "OpenUI5") {
+			Resolver = (await import("../../ui5Framework/Openui5Resolver.js")).default;
+		} else if (frameworkName === "SAPUI5") {
+			Resolver = (await import("../../ui5Framework/Sapui5Resolver.js")).default;
+		}
+
+		if (options.versionOverride) {
+			version = await Resolver.resolveVersion(options.versionOverride, {cwd: rootProject.getRootPath()});
+			log.info(
+				`Overriding configured ${frameworkName} version ` +
+				`${frameworkVersion} with version ${version}`
+			);
+		}
+		const referencedLibraries = await utils.getFrameworkLibrariesFromGraph(projectGraph);
+		if (!referencedLibraries.length) {
+			log.verbose(
+				`No ${frameworkName} libraries referenced in project ${rootProject.getName()} ` +
+				`or in any of its dependencies`);
+			return projectGraph;
+		}
+
+		if (version) {
+			log.info(`Using ${frameworkName} version: ${version}`);
+		}
+
+		let providedLibraryMetadata;
+		if (workspace) {
+			providedLibraryMetadata = await utils.getWorkspaceFrameworkLibraryMetadata({
+				workspace, projectGraph
+			});
+		}
+
+		// Note: version might be undefined here and the Resolver will throw an error when calling
+		// #install and it can't be resolved via the provided library metadata
+		const resolver = new Resolver({
+			cwd: rootProject.getRootPath(),
+			version,
+			providedLibraryMetadata,
+			cacheMode
+		});
+
+		let startTime;
+		if (log.isLevelEnabled("verbose")) {
+			startTime = process.hrtime();
+		}
+
+		const {libraryMetadata} = await resolver.install(referencedLibraries);
+
+		if (log.isLevelEnabled("verbose")) {
+			const timeDiff = process.hrtime(startTime);
+			const {default: prettyHrtime} = await import("pretty-hrtime");
+			log.verbose(
+				`${frameworkName} dependencies ${referencedLibraries.join(", ")} ` +
+				`resolved in ${prettyHrtime(timeDiff)}`);
+		}
+
+		const frameworkGraph = new ProjectGraph({
+			rootProjectName: `fake-root-of-${rootProject.getName()}-framework-dependency-graph`
+		});
+
+		const projectProcessor = new utils.ProjectProcessor({
+			libraryMetadata,
+			graph: frameworkGraph,
+			workspace
+		});
+
+		await Promise.all(referencedLibraries.map(async (libName) => {
+			await projectProcessor.addProjectToGraph(libName);
+		}));
+
+		utils.checkForDuplicateFrameworkProjects(projectGraph, frameworkGraph);
+
+		log.verbose("Joining framework graph into project graph...");
+		projectGraph.join(frameworkGraph);
+		await utils.declareFrameworkDependenciesInGraph(projectGraph);
+		return projectGraph;
+	},
+
+	// Export for testing only
+	_utils: process.env.NODE_ENV === "test" ? utils : /* istanbul ignore next */ undefined
+};
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_projectGraphBuilder.js.html b/v3/api/project_lib_graph_projectGraphBuilder.js.html new file mode 100644 index 0000000000..d35f9cbee4 --- /dev/null +++ b/v3/api/project_lib_graph_projectGraphBuilder.js.html @@ -0,0 +1,482 @@ + + + + + + + project/lib/graph/projectGraphBuilder.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/projectGraphBuilder.js

+ + + + + + + +
+
+
import path from "node:path";
+import Module from "./Module.js";
+import ProjectGraph from "./ProjectGraph.js";
+import ShimCollection from "./ShimCollection.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("graph:projectGraphBuilder");
+
+function _handleExtensions(graph, shimCollection, extensions) {
+	extensions.forEach((extension) => {
+		const type = extension.getType();
+		switch (type) {
+		case "project-shim":
+			shimCollection.addProjectShim(extension);
+			break;
+		case "task":
+		case "server-middleware":
+			graph.addExtension(extension);
+			break;
+		default:
+			throw new Error(
+				`Encountered unexpected extension of type ${type} ` +
+				`Supported types are 'project-shim', 'task' and 'middleware'`);
+		}
+	});
+}
+
+function validateNode(node) {
+	if (node.specVersion) {
+		throw new Error(
+			`Provided node with ID ${node.id} contains a top-level 'specVersion' property. ` +
+			`With UI5 Tooling 3.0, project configuration needs to be provided in a dedicated ` +
+			`'configuration' object`);
+	}
+	if (node.metadata) {
+		throw new Error(
+			`Provided node with ID ${node.id} contains a top-level 'metadata' property. ` +
+			`With UI5 Tooling 3.0, project configuration needs to be provided in a dedicated ` +
+			`'configuration' object`);
+	}
+}
+
+/**
+ * @public
+ * @module @ui5/project/graph/ProjectGraphBuilder
+ */
+
+/**
+ * Dependency graph node representing a module
+ *
+ * @public
+ * @typedef {object} @ui5/project/graph/ProjectGraphBuilder~Node
+ * @property {string} node.id Unique ID for the project
+ * @property {string} node.version Version of the project
+ * @property {string} node.path File System path to access the projects resources
+ * @property {object|object[]} [node.configuration]
+ *	Configuration object or array of objects to use instead of reading from a configuration file
+ * @property {string} [node.configPath] Configuration file to use instead the default ui5.yaml
+ * @property {boolean} [node.optional]
+ *					Whether the node is an optional dependency of the parent it has been requested for
+ * @property {*} * Additional attributes are allowed but ignored.
+ *					These can be used to pass information internally in the provider.
+ */
+
+/**
+ * Node Provider interface
+ *
+ * @public
+ * @interface @ui5/project/graph/ProjectGraphBuilder~NodeProvider
+ */
+
+/**
+ * Retrieve information on the root module
+ *
+ * @public
+ * @function
+ * @name @ui5/project/graph/ProjectGraphBuilder~NodeProvider#getRootNode
+ * @returns {Node} The root node of the dependency graph
+ */
+
+/**
+ * Retrieve information on given a nodes dependencies
+ *
+ * @public
+ * @function
+ * @name @ui5/project/graph/ProjectGraphBuilder~NodeProvider#getDependencies
+ * @param {Node} node The root node of the dependency graph
+ * @param {@ui5/project/graph/Workspace} [workspace] workspace instance to use for overriding node resolution
+ * @returns {Node[]} Array of nodes which are direct dependencies of the given node
+ */
+
+/**
+ * Generic helper module to create a [@ui5/project/graph/ProjectGraph]{@link @ui5/project/graph/ProjectGraph}.
+ * For example from a dependency tree as returned by the legacy "translators".
+ *
+ * @public
+ * @function default
+ * @static
+ * @param {@ui5/project/graph/ProjectGraphBuilder~NodeProvider} nodeProvider
+ * 	Node provider instance to use for building the graph
+ * @param {@ui5/project/graph/Workspace} [workspace]
+ * 	Optional workspace instance to use for overriding project resolutions
+ * @returns {@ui5/project/graph/ProjectGraph} A new project graph instance
+ */
+async function projectGraphBuilder(nodeProvider, workspace) {
+	const shimCollection = new ShimCollection();
+	const moduleCollection = Object.create(null);
+	const handledExtensions = new Set(); // Set containing the IDs of modules which' extensions have been handled
+
+	const rootNode = await nodeProvider.getRootNode();
+	validateNode(rootNode);
+	const rootModule = new Module({
+		id: rootNode.id,
+		version: rootNode.version,
+		modulePath: rootNode.path,
+		configPath: rootNode.configPath,
+		configuration: rootNode.configuration
+	});
+	const {project: rootProject, extensions: rootExtensions} = await rootModule.getSpecifications();
+	if (!rootProject) {
+		throw new Error(
+			`Failed to create a UI5 project from module ${rootNode.id} at ${rootNode.path}. ` +
+			`Make sure the path is correct and a project configuration is present or supplied.`);
+	}
+
+	moduleCollection[rootNode.id] = rootModule;
+
+	const rootProjectName = rootProject.getName();
+
+	let qualifiedApplicationProject = null;
+	if (rootProject.getType() === "application") {
+		log.verbose(`Root project ${rootProjectName} qualified as application project for project graph`);
+		qualifiedApplicationProject = rootProject;
+	}
+
+
+	const projectGraph = new ProjectGraph({
+		rootProjectName: rootProjectName
+	});
+	projectGraph.addProject(rootProject);
+
+	function handleExtensions(extensions) {
+		return _handleExtensions(projectGraph, shimCollection, extensions);
+	}
+
+	handleExtensions(rootExtensions);
+	handledExtensions.add(rootNode.id);
+
+	const queue = [];
+
+	const rootDependencies = await nodeProvider.getDependencies(rootNode, workspace);
+
+	if (rootDependencies && rootDependencies.length) {
+		queue.push({
+			nodes: rootDependencies,
+			parentProject: rootProject
+		});
+	}
+
+	// Breadth-first search
+	while (queue.length) {
+		const {nodes, parentProject} = queue.shift(); // Get and remove first entry from queue
+		const res = await Promise.all(nodes.map(async (node) => {
+			let ui5Module = moduleCollection[node.id];
+
+			if (ui5Module) {
+				log.silly(
+					`Re-visiting module ${node.id} as a dependency of ${parentProject.getName()}`);
+
+				const {project, extensions} = await ui5Module.getSpecifications();
+				if (!project && !extensions.length) {
+					// Invalidate cache if the cached module is visited through another parent project and did not
+					// resolve to a project or extension(s) before.
+					// The module being visited now might be a different version containing for example
+					// UI5 Tooling configuration, or one of the parent projects could have defined a
+					// relevant configuration shim meanwhile
+					log.silly(
+						`Cached module ${node.id} did not resolve to any projects or extensions. ` +
+						`Recreating module as a dependency of ${parentProject.getName()}...`);
+					ui5Module = null;
+				}
+			}
+
+			if (!ui5Module) {
+				log.silly(`Visiting Module ${node.id} as a dependency of ${parentProject.getName()}`);
+				log.verbose(`Creating module ${node.id}...`);
+				validateNode(node);
+				ui5Module = moduleCollection[node.id] = new Module({
+					id: node.id,
+					version: node.version,
+					modulePath: node.path,
+					configPath: node.configPath,
+					configuration: node.configuration,
+					shimCollection
+				});
+			} else if (ui5Module.getPath() !== node.path) {
+				log.verbose(
+					`Warning - Dependency ${node.id} is available at multiple paths:` +
+					`\n  Location of the already processed module (this one will be used): ${ui5Module.getPath()}` +
+					`\n  Additional location (this one will be ignored): ${node.path}`);
+			}
+
+			const {project, extensions} = await ui5Module.getSpecifications();
+			return {
+				node,
+				project,
+				extensions
+			};
+		}));
+
+		// Keep this out of the async map function to ensure
+		// all projects and extensions are applied in a deterministic order
+		for (let i = 0; i < res.length; i++) {
+			const {
+				node, // Tree "raw" dependency tree node
+				project, // The project found for this node, if any
+				extensions // Any extensions found for this node
+			} = res[i];
+
+			if (extensions.length && (!node.optional || parentProject === rootProject)) {
+				// Only handle extensions in non-optional dependencies and any dependencies of the root project
+				if (handledExtensions.has(node.id)) {
+					// Do not handle extensions of the same module twice
+					log.verbose(`Extensions contained in module ${node.id} have already been handled`);
+				} else {
+					log.verbose(`Handling extensions for module ${node.id}...`);
+					// If a different module contains the same extension, we expect an error to be thrown by the graph
+					handleExtensions(extensions);
+					handledExtensions.add(node.id);
+				}
+			}
+
+			// Check for collection shims
+			const collectionShims = shimCollection.getCollectionShims(node.id);
+			if (collectionShims && collectionShims.length) {
+				log.verbose(
+					`One or more module collection shims have been defined for module ${node.id}. ` +
+					`Therefore the module itself will not be resolved.`);
+
+				const shimmedNodes = collectionShims.map(({name, shim}) => {
+					log.verbose(`Applying module collection shim ${name} for module ${node.id}:`);
+					return Object.entries(shim.modules).map(([shimModuleId, shimModuleRelPath]) => {
+						const shimModulePath = path.join(node.path, shimModuleRelPath);
+						log.verbose(`  Injecting module ${shimModuleId} with path ${shimModulePath}`);
+						return {
+							id: shimModuleId,
+							version: node.version,
+							path: shimModulePath
+						};
+					});
+				});
+
+				queue.push({
+					nodes: Array.prototype.concat.apply([], shimmedNodes),
+					parentProject,
+				});
+				// Skip collection node
+				continue;
+			}
+
+			let skipDependencies = false;
+			if (project) {
+				const projectName = project.getName();
+				if (project.getType() === "application") {
+					// Special handling of application projects of which there must be exactly *one*
+					// in the graph. Others shall be ignored.
+					if (!qualifiedApplicationProject) {
+						log.verbose(`Project ${projectName} qualified as application project for project graph`);
+						qualifiedApplicationProject = project;
+					} else if (qualifiedApplicationProject.getName() !== projectName) {
+						// Project is not a duplicate of an already qualified project (which should
+						// still be processed below), but a unique, additional application project
+
+						// TODO: Should this rather be a verbose logging?
+						//	projectPreprocessor handled this like any project that got ignored and did a
+						//	(in this case misleading) general verbose logging:
+						//	"Ignoring project with missing configuration"
+						log.info(
+							`Excluding additional application project ${projectName} from graph. `+
+							`The project graph can only feature a single project of type application. ` +
+							`Project ${qualifiedApplicationProject.getName()} has already qualified for that role.`);
+						continue;
+					}
+				}
+				if (projectGraph.getProject(projectName)) {
+					// Opposing to extensions, we are generally fine with the same project being contained in different
+					// modules. We simply ignore all but the first occurrence.
+					// This can happen for example if the same project is packaged in different ways/modules
+					// (e.g. one module containing the source and one containing the pre-built resources)
+					log.verbose(
+						`Project ${projectName} has already been added to the graph. ` +
+						`Skipping dependency resolution...`);
+					skipDependencies = true;
+				} else {
+					projectGraph.addProject(project);
+				}
+
+				if (parentProject) {
+					if (node.optional) {
+						projectGraph.declareOptionalDependency(parentProject.getName(), projectName);
+					} else {
+						projectGraph.declareDependency(parentProject.getName(), projectName);
+					}
+
+					if (project.isDeprecated() && parentProject === rootProject &&
+							parentProject.getName() !== "testsuite") {
+						// Only warn for direct dependencies of the root project
+						// No warning for testsuite projects
+						log.warn(
+							`Dependency ${project.getName()} is deprecated and should not be used for new projects!`);
+					}
+
+					if (project.isSapInternal() && parentProject === rootProject &&
+						!parentProject.getAllowSapInternal()) {
+						// Only warn for direct dependencies of the root project, except it defines "allowSapInternal"
+						log.warn(
+							`Dependency ${project.getName()} is restricted for use by SAP internal projects only! ` +
+							`If the project ${parentProject.getName()} is an SAP internal project, add the attribute ` +
+							`"allowSapInternal: true" to its metadata configuration`);
+					}
+				}
+			}
+
+			if (!project && !extensions.length) {
+				// Module provides neither a project nor an extension
+				// => Do not follow its dependencies
+				log.verbose(
+					`Module ${node.id} neither provides a project nor an extension. Skipping dependency resolution`);
+				skipDependencies = true;
+			}
+
+			if (skipDependencies) {
+				continue;
+			}
+
+			const nodeDependencies = await nodeProvider.getDependencies(node);
+			if (nodeDependencies && nodeDependencies.length) {
+				queue.push({
+					// copy array, so that the queue is stable while ignored project dependencies are removed
+					nodes: [...nodeDependencies],
+					parentProject: project ? project : parentProject,
+				});
+			}
+		}
+	}
+
+	// Apply dependency shims
+	for (const [shimmedModuleId, moduleDepShims] of Object.entries(shimCollection.getAllDependencyShims())) {
+		const sourceModule = moduleCollection[shimmedModuleId];
+
+		for (let j = 0; j < moduleDepShims.length; j++) {
+			const depShim = moduleDepShims[j];
+			if (!sourceModule) {
+				log.warn(`Could not apply dependency shim ${depShim.name} for ${shimmedModuleId}: ` +
+					`Module ${shimmedModuleId} is unknown`);
+				continue;
+			}
+			const {project: sourceProject} = await sourceModule.getSpecifications();
+			if (!sourceProject) {
+				log.warn(`Could not apply dependency shim ${depShim.name} for ${shimmedModuleId}: ` +
+					`Source module ${shimmedModuleId} does not contain a project`);
+				continue;
+			}
+			for (let k = 0; k < depShim.shim.length; k++) {
+				const targetModuleId = depShim.shim[k];
+				const targetModule = moduleCollection[targetModuleId];
+				if (!targetModule) {
+					log.warn(`Could not apply dependency shim ${depShim.name} for ${shimmedModuleId}: ` +
+						`Target module $${depShim} is unknown`);
+					continue;
+				}
+				const {project: targetProject} = await targetModule.getSpecifications();
+				if (!targetProject) {
+					log.warn(`Could not apply dependency shim ${depShim.name} for ${shimmedModuleId}: ` +
+						`Target module ${targetModuleId} does not contain a project`);
+					continue;
+				}
+				projectGraph.declareDependency(sourceProject.getName(), targetProject.getName());
+			}
+		}
+	}
+	await projectGraph.resolveOptionalDependencies();
+
+	return projectGraph;
+}
+
+export default projectGraphBuilder;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_providers_DependencyTree.js.html b/v3/api/project_lib_graph_providers_DependencyTree.js.html new file mode 100644 index 0000000000..271f131d0d --- /dev/null +++ b/v3/api/project_lib_graph_providers_DependencyTree.js.html @@ -0,0 +1,155 @@ + + + + + + + project/lib/graph/providers/DependencyTree.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/providers/DependencyTree.js

+ + + + + + + +
+
+
/**
+ * Tree node
+ *
+ * @public
+ * @class
+ * @typedef {object} @ui5/project/graph/providers/DependencyTree~TreeNode
+ * @property {string} node.id Unique ID for the project
+ * @property {string} node.version Version of the project
+ * @property {string} node.path File System path to access the projects resources
+ * @property {object|object[]} [node.configuration]
+ *	Configuration object or array of objects to use instead of reading from a configuration file
+ * @property {string} [node.configPath] Configuration file to use instead the default ui5.yaml
+ * @property {@ui5/project/graph/providers/DependencyTree~TreeNode[]} dependencies
+ */
+
+/**
+ * Helper module to create a [@ui5/project/graph/ProjectGraph]{@link @ui5/project/graph/ProjectGraph}
+ * from a dependency tree as returned by translators.
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/graph/providers/DependencyTree
+ */
+class DependencyTree {
+	/**
+	 * @param {object} options
+	 * @param {@ui5/project/graph/providers/DependencyTree~TreeNode} options.dependencyTree
+ 	 * 		Dependency tree as returned by a translator
+	 * @param {object} [options.rootConfiguration]
+	 *		Configuration object to use for the root module instead of reading from a configuration file
+	 * @param {string} [options.rootConfigPath]
+	 *		Configuration file to use for the root module instead the default ui5.yaml
+	 */
+	constructor({dependencyTree, rootConfiguration, rootConfigPath}) {
+		if (!dependencyTree) {
+			throw new Error(`Failed to instantiate DependencyTree provider: Missing parameter 'dependencyTree'`);
+		}
+		this._tree = dependencyTree;
+		if (rootConfiguration) {
+			this._tree.configuration = rootConfiguration;
+		}
+		if (rootConfigPath) {
+			this._tree.configPath = rootConfigPath;
+		}
+	}
+
+	async getRootNode() {
+		return this._tree;
+	}
+
+	async getDependencies(node) {
+		if (node.deduped || !node.dependencies) {
+			return [];
+		}
+		return node.dependencies;
+	}
+}
+
+export default DependencyTree;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_graph_providers_NodePackageDependencies.js.html b/v3/api/project_lib_graph_providers_NodePackageDependencies.js.html new file mode 100644 index 0000000000..836f1dbce8 --- /dev/null +++ b/v3/api/project_lib_graph_providers_NodePackageDependencies.js.html @@ -0,0 +1,272 @@ + + + + + + + project/lib/graph/providers/NodePackageDependencies.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/graph/providers/NodePackageDependencies.js

+ + + + + + + +
+
+
import path from "node:path";
+import {readPackageUp} from "read-pkg-up";
+import {readPackage} from "read-pkg";
+import {promisify} from "node:util";
+import fs from "graceful-fs";
+const realpath = promisify(fs.realpath);
+import resolve from "resolve";
+const resolveModulePath = promisify(resolve);
+import {getLogger} from "@ui5/logger";
+const log = getLogger("graph:providers:NodePackageDependencies");
+
+// Packages to consider:
+// * https://github.com/npm/read-package-json-fast
+// * https://github.com/npm/name-from-folder ?
+
+/**
+ * @public
+ * @class
+ * @alias @ui5/project/graph/providers/NodePackageDependencies
+ */
+class NodePackageDependencies {
+	/**
+	 * Generates a project graph from npm modules
+	 *
+	 * @public
+	 * @param {object} options
+	 * @param {string} options.cwd Directory to start searching for the root module
+	 * @param {object} [options.rootConfiguration]
+	 *		Configuration object to use for the root module instead of reading from a configuration file
+	 * @param {string} [options.rootConfigPath]
+	 *		Configuration file to use for the root module instead the default ui5.yaml
+	 */
+	constructor({cwd, rootConfiguration, rootConfigPath}) {
+		this._cwd = cwd;
+		this._rootConfiguration = rootConfiguration;
+		this._rootConfigPath = rootConfigPath;
+	}
+
+	async getRootNode() {
+		const rootPkg = await readPackageUp({
+			cwd: this._cwd,
+			normalize: false
+		});
+
+		if (!rootPkg || !rootPkg.packageJson) {
+			throw new Error(
+				`Failed to locate package.json for directory ${path.resolve(this._cwd)}`);
+		}
+		const modulePath = path.dirname(rootPkg.path);
+		return {
+			id: rootPkg.packageJson.name,
+			version: rootPkg.packageJson.version,
+			path: modulePath,
+			configuration: this._rootConfiguration,
+			configPath: this._rootConfigPath,
+			_dependencies: await this._getDependencies(modulePath, rootPkg.packageJson, true)
+		};
+	}
+
+	async getDependencies(node, workspace) {
+		log.verbose(`Resolving dependencies of ${node.id}...`);
+		if (!node._dependencies) {
+			return [];
+		}
+		return Promise.all(node._dependencies.map(async ({name, optional}) => {
+			const modulePath = await this._resolveModulePath(node.path, name, workspace);
+			return this._getNode(modulePath, optional, name);
+		}));
+	}
+
+	async _resolveModulePath(baseDir, moduleName, workspace) {
+		log.verbose(`Resolving module path for '${moduleName}'...`);
+
+		if (workspace) {
+			// Check whether node can be resolved via the provided Workspace instance
+			// If yes, replace the node from NodeProvider with the one from Workspace
+			const workspaceNode = await workspace.getModuleByNodeId(moduleName);
+			if (workspaceNode) {
+				log.info(`Resolved module ${moduleName} via ${workspace.getName()} workspace ` +
+					`to version ${workspaceNode.getVersion()}`);
+				log.verbose(`  Resolved module ${moduleName} to path ${workspaceNode.getPath()}`);
+				return workspaceNode.getPath();
+			}
+		}
+
+		try {
+			let packageJsonPath = await resolveModulePath(moduleName + "/package.json", {
+				basedir: baseDir,
+				preserveSymlinks: false
+			});
+			packageJsonPath = await realpath(packageJsonPath);
+
+			const modulePath = path.dirname(packageJsonPath);
+			log.verbose(`Resolved module ${moduleName} to path ${modulePath}`);
+			return modulePath;
+		} catch (err) {
+			throw new Error(
+				`Unable to locate module ${moduleName} via resolve logic: ${err.message}`);
+		}
+	}
+
+	/**
+	 * Resolves a Node module by reading its package.json
+	 *
+	 * @param {string} modulePath Path to the module.
+	 * @param {boolean} optional Whether this dependency is optional.
+	 * @param {string} [nameAlias] The name of the module. It's usually the same as the name definfed
+	 * 	in package.json and could easily be skipped. Useful when defining dependency as an alias:
+	 * 	{@link https://github.com/npm/rfcs/blob/main/implemented/0001-package-aliases.md}
+	 * @returns {Promise<object>}
+	 */
+	async _getNode(modulePath, optional, nameAlias) {
+		log.verbose(`Reading package.json in directory ${modulePath}...`);
+		const packageJson = await readPackage({
+			cwd: modulePath,
+			normalize: false
+		});
+
+		return {
+			id: nameAlias || packageJson.name,
+			version: packageJson.version,
+			path: modulePath,
+			optional,
+			_dependencies: await this._getDependencies(modulePath, packageJson)
+		};
+	}
+
+	async _getDependencies(modulePath, packageJson, rootModule = false) {
+		const dependencies = [];
+		if (packageJson.dependencies) {
+			Object.keys(packageJson.dependencies).forEach((depName) => {
+				dependencies.push({
+					name: depName,
+					optional: false
+				});
+			});
+		}
+		if (rootModule && packageJson.devDependencies) {
+			Object.keys(packageJson.devDependencies).forEach((depName) => {
+				dependencies.push({
+					name: depName,
+					optional: false
+				});
+			});
+		}
+		if (!rootModule && packageJson.devDependencies) {
+			await Promise.all(Object.keys(packageJson.devDependencies).map(async (depName) => {
+				try {
+					await this._resolveModulePath(modulePath, depName);
+					dependencies.push({
+						name: depName,
+						optional: true
+					});
+				} catch (err) {
+					// Ignore error since it's a development dependency of a non-root module
+				}
+			}));
+		}
+		if (packageJson.optionalDependencies) {
+			await Promise.all(Object.keys(packageJson.optionalDependencies).map(async (depName) => {
+				try {
+					await this._resolveModulePath(modulePath, depName);
+					dependencies.push({
+						name: depName,
+						optional: false
+					});
+				} catch (err) {
+					// Ignore error since it's an optional dependency
+				}
+			}));
+		}
+		return dependencies;
+	}
+}
+
+export default NodePackageDependencies;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_ComponentProject.js.html b/v3/api/project_lib_specifications_ComponentProject.js.html new file mode 100644 index 0000000000..f3d42f7b7e --- /dev/null +++ b/v3/api/project_lib_specifications_ComponentProject.js.html @@ -0,0 +1,476 @@ + + + + + + + project/lib/specifications/ComponentProject.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/ComponentProject.js

+ + + + + + + +
+
+
import {promisify} from "node:util";
+import Project from "./Project.js";
+import * as resourceFactory from "@ui5/fs/resourceFactory";
+
+/**
+ * Subclass for projects potentially containing Components
+ *
+ * @public
+ * @abstract
+ * @class
+ * @alias @ui5/project/specifications/ComponentProject
+ * @extends @ui5/project/specifications/Project
+ * @hideconstructor
+ */
+class ComponentProject extends Project {
+	constructor(parameters) {
+		super(parameters);
+		if (new.target === ComponentProject) {
+			throw new TypeError("Class 'ComponentProject' is abstract. Please use one of the 'types' subclasses");
+		}
+
+		this._pPom = null;
+		this._namespace = null;
+		this._isRuntimeNamespaced = true;
+	}
+
+	/* === Attributes === */
+	/**
+	 * Get the project namespace
+	 *
+	 * @public
+	 * @returns {string} Project namespace in slash notation (e.g. <code>my/project/name</code>)
+	 */
+	getNamespace() {
+		return this._namespace;
+	}
+
+	/**
+	* @private
+	*/
+	getCopyright() {
+		return this._config.metadata.copyright;
+	}
+
+	/**
+	* @private
+	*/
+	getComponentPreloadPaths() {
+		return this._config.builder && this._config.builder.componentPreload &&
+			this._config.builder.componentPreload.paths || [];
+	}
+
+	/**
+	* @private
+	*/
+	getComponentPreloadNamespaces() {
+		return this._config.builder && this._config.builder.componentPreload &&
+			this._config.builder.componentPreload.namespaces || [];
+	}
+
+	/**
+	* @private
+	*/
+	getComponentPreloadExcludes() {
+		return this._config.builder && this._config.builder.componentPreload &&
+			this._config.builder.componentPreload.excludes || [];
+	}
+
+	/**
+	* @private
+	*/
+	getMinificationExcludes() {
+		return this._config.builder && this._config.builder.minification &&
+			this._config.builder.minification.excludes || [];
+	}
+
+	/**
+	* @private
+	*/
+	getBundles() {
+		return this._config.builder && this._config.builder.bundles || [];
+	}
+
+	/**
+	* @private
+	*/
+	getPropertiesFileSourceEncoding() {
+		return this._config.resources && this._config.resources.configuration &&
+			this._config.resources.configuration.propertiesFileSourceEncoding || "UTF-8";
+	}
+
+	/* === Resource Access === */
+
+	/**
+	 * Get a [ReaderCollection]{@link @ui5/fs/ReaderCollection} for accessing all resources of the
+	 * project in the specified "style":
+	 *
+	 * <ul>
+	 * <li><b>buildtime:</b> Resource paths are always prefixed with <code>/resources/</code>
+	 *  or <code>/test-resources/</code> followed by the project's namespace.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>dist:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>runtime:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  This style is typically used for serving resources directly. Therefore, build-excludes are not applied
+	 * <li><b>flat:</b> Resource paths are never prefixed and namespaces are omitted if possible. Note that
+	 *  project types like "theme-library", which can have multiple namespaces, can't omit them.
+	 *  Any configured build-excludes are applied</li>
+	 * </ul>
+	 *
+	 * If project resources have been changed through the means of a workspace, those changes
+	 * are reflected in the provided reader too.
+	 *
+	 * Resource readers always use POSIX-style paths.
+	 *
+	 * @public
+	 * @param {object} [options]
+	 * @param {string} [options.style=buildtime] Path style to access resources.
+	 *   Can be "buildtime", "dist", "runtime" or "flat"
+	 * @returns {@ui5/fs/ReaderCollection} A reader collection instance
+	 */
+	getReader({style = "buildtime"} = {}) {
+		// TODO: Additional style 'ABAP' using "sap.platform.abap".uri from manifest.json?
+
+		// Apply builder excludes to all styles but "runtime"
+		const excludes = style === "runtime" ? [] : this.getBuilderResourcesExcludes();
+
+		if ((style === "runtime" || style === "dist") && this._isRuntimeNamespaced) {
+			// If the project's type requires a namespace at runtime, the
+			// dist- and runtime-style paths are identical to buildtime-style paths
+			style = "buildtime";
+		}
+		let reader = this._getReader(excludes);
+		switch (style) {
+		case "buildtime":
+			break;
+		case "runtime":
+		case "dist":
+			// Use buildtime reader and link it to /
+			// No test-resources for runtime resource access,
+			// unless runtime is namespaced
+			reader = resourceFactory.createFlatReader({
+				reader,
+				namespace: this._namespace
+			});
+			break;
+		case "flat":
+			// Use buildtime reader and link it to /
+			// No test-resources for runtime resource access,
+			// unless runtime is namespaced
+			reader = resourceFactory.createFlatReader({
+				reader,
+				namespace: this._namespace
+			});
+			break;
+		default:
+			throw new Error(`Unknown path mapping style ${style}`);
+		}
+
+		reader = this._addWriter(reader, style);
+		return reader;
+	}
+
+	/**
+	* Get a resource reader for the resources of the project
+	*
+	* @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	_getSourceReader() {
+		throw new Error(`_getSourceReader must be implemented by subclass ${this.constructor.name}`);
+	}
+
+	/**
+	* Get a resource reader for the test resources of the project
+	*
+	* @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	_getTestReader() {
+		throw new Error(`_getTestReader must be implemented by subclass ${this.constructor.name}`);
+	}
+
+	/**
+	 * Get a resource reader/writer for accessing and modifying a project's resources
+	 *
+	 * @public
+	 * @returns {@ui5/fs/ReaderCollection} A reader collection instance
+	 */
+	getWorkspace() {
+		// Workspace is always of style "buildtime"
+		// Therefore builder resource-excludes are always to be applied
+		const excludes = this.getBuilderResourcesExcludes();
+		return resourceFactory.createWorkspace({
+			name: `Workspace for project ${this.getName()}`,
+			reader: this._getReader(excludes),
+			writer: this._getWriter().collection
+		});
+	}
+
+	_getWriter() {
+		if (!this._writers) {
+			// writer is always of style "buildtime"
+			const namespaceWriter = resourceFactory.createAdapter({
+				virBasePath: "/",
+				project: this
+			});
+
+			const generalWriter = resourceFactory.createAdapter({
+				virBasePath: "/",
+				project: this
+			});
+
+			const collection = resourceFactory.createWriterCollection({
+				name: `Writers for project ${this.getName()}`,
+				writerMapping: {
+					[`/resources/${this._namespace}/`]: namespaceWriter,
+					[`/test-resources/${this._namespace}/`]: namespaceWriter,
+					[`/`]: generalWriter
+				}
+			});
+
+			this._writers = {
+				namespaceWriter,
+				generalWriter,
+				collection
+			};
+		}
+		return this._writers;
+	}
+
+	_getReader(excludes) {
+		let reader = this._getSourceReader(excludes);
+		const testReader = this._getTestReader(excludes);
+		if (testReader) {
+			reader = resourceFactory.createReaderCollection({
+				name: `Reader collection for project ${this.getName()}`,
+				readers: [reader, testReader]
+			});
+		}
+		return reader;
+	}
+
+	_addWriter(reader, style) {
+		const {namespaceWriter, generalWriter} = this._getWriter();
+
+		if ((style === "runtime" || style === "dist") && this._isRuntimeNamespaced) {
+			// If the project's type requires a namespace at runtime, the
+			// dist- and runtime-style paths are identical to buildtime-style paths
+			style = "buildtime";
+		}
+		const readers = [];
+		switch (style) {
+		case "buildtime":
+			// Writer already uses buildtime style
+			readers.push(namespaceWriter);
+			readers.push(generalWriter);
+			break;
+		case "runtime":
+		case "dist":
+			// Runtime is not namespaced: link namespace to /
+			readers.push(resourceFactory.createFlatReader({
+				reader: namespaceWriter,
+				namespace: this._namespace
+			}));
+			// Add general writer as is
+			readers.push(generalWriter);
+			break;
+		case "flat":
+			// Rewrite paths from "flat" to "buildtime"
+			readers.push(resourceFactory.createFlatReader({
+				reader: namespaceWriter,
+				namespace: this._namespace
+			}));
+			// General writer resources can't be flattened, so they are not available
+			break;
+		default:
+			throw new Error(`Unknown path mapping style ${style}`);
+		}
+		readers.push(reader);
+
+		return resourceFactory.createReaderCollectionPrioritized({
+			name: `Reader/Writer collection for project ${this.getName()}`,
+			readers
+		});
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _parseConfiguration(config) {
+		await super._parseConfiguration(config);
+	}
+
+	async _getNamespace() {
+		throw new Error(`_getNamespace must be implemented by subclass ${this.constructor.name}`);
+	}
+
+	/* === Helper === */
+	/**
+	 * Checks whether a given string contains a maven placeholder.
+	 * E.g. <code>${appId}</code>.
+	 *
+	 * @param {string} value String to check
+	 * @returns {boolean} True if given string contains a maven placeholder
+	 */
+	_hasMavenPlaceholder(value) {
+		return !!value.match(/^\$\{(.*)\}$/);
+	}
+
+	/**
+	 * Resolves a maven placeholder in a given string using the projects pom.xml
+	 *
+	 * @param {string} value String containing a maven placeholder
+	 * @returns {Promise<string>} Resolved string
+	 */
+	async _resolveMavenPlaceholder(value) {
+		const parts = value && value.match(/^\$\{(.*)\}$/);
+		if (parts) {
+			this._log.verbose(
+				`"${value}" contains a maven placeholder "${parts[1]}". Resolving from projects pom.xml...`);
+			const pom = await this._getPom();
+			let mvnValue;
+			if (pom.project && pom.project.properties && pom.project.properties[parts[1]]) {
+				mvnValue = pom.project.properties[parts[1]];
+			} else {
+				let obj = pom;
+				parts[1].split(".").forEach((part) => {
+					obj = obj && obj[part];
+				});
+				mvnValue = obj;
+			}
+			if (!mvnValue) {
+				throw new Error(`"${value}" couldn't be resolved from maven property ` +
+					`"${parts[1]}" of pom.xml of project ${this.getName()}`);
+			}
+			return mvnValue;
+		} else {
+			throw new Error(`"${value}" is not a maven placeholder`);
+		}
+	}
+
+	/**
+	 * Reads the projects pom.xml file
+	 *
+	 * @returns {Promise<object>} Resolves with a JSON representation of the content
+	 */
+	async _getPom() {
+		if (this._pPom) {
+			return this._pPom;
+		}
+
+		return this._pPom = this.getRootReader().byPath("/pom.xml")
+			.then(async (resource) => {
+				if (!resource) {
+					throw new Error(
+						`Could not find pom.xml in project ${this.getName()}`);
+				}
+				const content = await resource.getString();
+				const {
+					default: xml2js
+				} = await import("xml2js");
+				const parser = new xml2js.Parser({
+					explicitArray: false,
+					ignoreAttrs: true
+				});
+				const readXML = promisify(parser.parseString);
+				return readXML(content);
+			}).catch((err) => {
+				throw new Error(
+					`Failed to read pom.xml for project ${this.getName()}: ${err.message}`);
+			});
+	}
+}
+
+export default ComponentProject;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_Extension.js.html b/v3/api/project_lib_specifications_Extension.js.html new file mode 100644 index 0000000000..f9feeeb30d --- /dev/null +++ b/v3/api/project_lib_specifications_Extension.js.html @@ -0,0 +1,141 @@ + + + + + + + project/lib/specifications/Extension.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/Extension.js

+ + + + + + + +
+
+
import Specification from "./Specification.js";
+
+/**
+ * Extension
+ *
+ * @public
+ * @abstract
+ * @class
+ * @alias @ui5/project/specifications/Extension
+ * @extends @ui5/project/specifications/Specification
+ * @hideconstructor
+ */
+class Extension extends Specification {
+	constructor(parameters) {
+		super(parameters);
+		if (new.target === Extension) {
+			throw new TypeError("Class 'Extension' is abstract. Please use one of the 'types' subclasses");
+		}
+	}
+
+	/**
+	 * @param {object} parameters Specification parameters
+	 * @param {string} parameters.id Unique ID
+	 * @param {string} parameters.version Version
+	 * @param {string} parameters.modulePath File System path to access resources
+	 * @param {object} parameters.configuration Configuration object
+	 */
+	async init(parameters) {
+		await super.init(parameters);
+
+		try {
+			await this._validateConfig();
+		} catch (err) {
+			throw new Error(
+				`Failed to validate configuration of ${this.getType()} extension ${this.getName()}: ` +
+				err.message);
+		}
+
+		return this;
+	}
+
+	async _validateConfig() {}
+}
+
+export default Extension;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_Project.js.html b/v3/api/project_lib_specifications_Project.js.html new file mode 100644 index 0000000000..8b711aa01f --- /dev/null +++ b/v3/api/project_lib_specifications_Project.js.html @@ -0,0 +1,388 @@ + + + + + + + project/lib/specifications/Project.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/Project.js

+ + + + + + + +
+
+
import Specification from "./Specification.js";
+import ResourceTagCollection from "@ui5/fs/internal/ResourceTagCollection";
+
+/**
+ * Project
+ *
+ * @public
+ * @abstract
+ * @class
+ * @alias @ui5/project/specifications/Project
+ * @extends @ui5/project/specifications/Specification
+ * @hideconstructor
+ */
+class Project extends Specification {
+	constructor(parameters) {
+		super(parameters);
+		if (new.target === Project) {
+			throw new TypeError("Class 'Project' is abstract. Please use one of the 'types' subclasses");
+		}
+
+		this._resourceTagCollection = null;
+	}
+
+	/**
+	 * @param {object} parameters Specification parameters
+	 * @param {string} parameters.id Unique ID
+	 * @param {string} parameters.version Version
+	 * @param {string} parameters.modulePath File System path to access resources
+	 * @param {object} parameters.configuration Configuration object
+	 * @param {object} [parameters.buildManifest] Build metadata object
+	 */
+	async init(parameters) {
+		await super.init(parameters);
+
+		this._buildManifest = parameters.buildManifest;
+
+		await this._configureAndValidatePaths(this._config);
+		await this._parseConfiguration(this._config, this._buildManifest);
+
+		return this;
+	}
+
+	/* === Attributes === */
+	/**
+	 * Get the project namespace. Returns `null` for projects that have none or multiple namespaces,
+	 * for example Modules or Theme Libraries.
+	 *
+	 * @public
+	 * @returns {string|null} Project namespace in slash notation (e.g. <code>my/project/name</code>) or null
+	 */
+	getNamespace() {
+		// Default namespace for general Projects:
+		// Their resources should be structured with globally unique paths, hence their namespace is undefined
+		return null;
+	}
+
+	/**
+	 * Check whether the project is a UI5-Framework project
+	 *
+	 * @public
+	 * @returns {boolean} True if the project is a framework project
+	 */
+	isFrameworkProject() {
+		const id = this.getId();
+		return id.startsWith("@openui5/") || id.startsWith("@sapui5/");
+	}
+
+	/**
+	 * Get the project's customConfiguration
+	 *
+	 * @public
+	 * @returns {object} Custom Configuration
+	 */
+	getCustomConfiguration() {
+		return this._config.customConfiguration;
+	}
+
+	/**
+	 * Get the path of the project's source directory. This might not be POSIX-style on some platforms.
+	 * Projects with multiple source paths will throw an error. For example Modules.
+	 *
+	 * @public
+	 * @returns {string} Absolute path to the source directory of the project
+	 * @throws {Error} In case a project has multiple source directories
+	 */
+	getSourcePath() {
+		throw new Error(`getSourcePath must be implemented by subclass ${this.constructor.name}`);
+	}
+
+	/**
+	 * Get the project's framework name configuration
+	 *
+	 * @public
+	 * @returns {string} Framework name configuration, either <code>OpenUI5</code> or <code>SAPUI5</code>
+	 */
+	getFrameworkName() {
+		return this._config.framework?.name;
+	}
+
+	/**
+	 * Get the project's framework version configuration
+	 *
+	 * @public
+	 * @returns {string} Framework version configuration, e.g <code>1.110.0</code>
+	 */
+	getFrameworkVersion() {
+		return this._config.framework?.version;
+	}
+
+
+	/**
+	 * Framework dependency entry of the project configuration.
+	 * Also see [Framework Configuration: Dependencies]{@link https://sap.github.io/ui5-tooling/stable/pages/Configuration/#dependencies}
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/specifications/Project~FrameworkDependency
+	 * @property {string} name Name of the framework library. For example <code>sap.ui.core</code>
+	 * @property {boolean} development Whether the dependency is meant for development purposes only
+	 * @property {boolean} optional Whether the dependency should be treated as optional
+	 */
+
+	/**
+	 * Get the project's framework dependencies configuration
+	 *
+	 * @public
+	 * @returns {@ui5/project/specifications/Project~FrameworkDependency[]} Framework dependencies configuration
+	 */
+	getFrameworkDependencies() {
+		return this._config.framework?.libraries || [];
+	}
+
+	/**
+	 * Get the project's deprecated configuration
+	 *
+	 * @private
+	 * @returns {boolean} True if the project is flagged as deprecated
+	 */
+	isDeprecated() {
+		return !!this._config.metadata.deprecated;
+	}
+
+	/**
+	 * Get the project's sapInternal configuration
+	 *
+	 * @private
+	 * @returns {boolean} True if the project is flagged as SAP-internal
+	 */
+	isSapInternal() {
+		return !!this._config.metadata.sapInternal;
+	}
+
+	/**
+	 * Get the project's allowSapInternal configuration
+	 *
+	 * @private
+	 * @returns {boolean} True if the project allows for using SAP-internal projects
+	 */
+	getAllowSapInternal() {
+		return !!this._config.metadata.allowSapInternal;
+	}
+
+	/**
+	 * Get the project's builderResourcesExcludes configuration
+	 *
+	 * @private
+	 * @returns {string[]} BuilderResourcesExcludes configuration
+	 */
+	getBuilderResourcesExcludes() {
+		return this._config.builder?.resources?.excludes || [];
+	}
+
+	/**
+	 * Get the project's customTasks configuration
+	 *
+	 * @private
+	 * @returns {object[]} CustomTasks configuration
+	 */
+	getCustomTasks() {
+		return this._config.builder?.customTasks || [];
+	}
+
+	/**
+	 * Get the project's customMiddleware configuration
+	 *
+	 * @private
+	 * @returns {object[]} CustomMiddleware configuration
+	 */
+	getCustomMiddleware() {
+		return this._config.server?.customMiddleware || [];
+	}
+
+	/**
+	 * Get the project's serverSettings configuration
+	 *
+	 * @private
+	 * @returns {object} ServerSettings configuration
+	 */
+	getServerSettings() {
+		return this._config.server?.settings;
+	}
+
+	/**
+	 * Get the project's builderSettings configuration
+	 *
+	 * @private
+	 * @returns {object} BuilderSettings configuration
+	 */
+	getBuilderSettings() {
+		return this._config.builder?.settings;
+	}
+
+	/**
+	 * Get the project's buildManifest configuration
+	 *
+	 * @private
+	 * @returns {object|null} BuildManifest configuration or null if none is available
+	 */
+	getBuildManifest() {
+		return this._buildManifest || null;
+	}
+
+	/* === Resource Access === */
+	/**
+	 * Get a [ReaderCollection]{@link @ui5/fs/ReaderCollection} for accessing all resources of the
+	 * project in the specified "style":
+	 *
+	 * <ul>
+	 * <li><b>buildtime:</b> Resource paths are always prefixed with <code>/resources/</code>
+	 *  or <code>/test-resources/</code> followed by the project's namespace.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>dist:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>runtime:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  This style is typically used for serving resources directly. Therefore, build-excludes are not applied
+	 * <li><b>flat:</b> Resource paths are never prefixed and namespaces are omitted if possible. Note that
+	 *  project types like "theme-library", which can have multiple namespaces, can't omit them.
+	 *  Any configured build-excludes are applied</li>
+	 * </ul>
+	 *
+	 * Resource readers always use POSIX-style paths.
+	 *
+	 * @public
+	 * @param {object} [options]
+	 * @param {string} [options.style=buildtime] Path style to access resources.
+	 *   Can be "buildtime", "dist", "runtime" or "flat"
+	 * @returns {@ui5/fs/ReaderCollection} Reader collection allowing access to all resources of the project
+	 */
+	getReader(options) {
+		throw new Error(`getReader must be implemented by subclass ${this.constructor.name}`);
+	}
+
+	getResourceTagCollection() {
+		if (!this._resourceTagCollection) {
+			this._resourceTagCollection = new ResourceTagCollection({
+				allowedTags: ["ui5:IsDebugVariant", "ui5:HasDebugVariant"],
+				allowedNamespaces: ["project"],
+				tags: this.getBuildManifest()?.tags
+			});
+		}
+		return this._resourceTagCollection;
+	}
+
+	/**
+	* Get a [DuplexCollection]{@link @ui5/fs/DuplexCollection} for accessing and modifying a
+	* project's resources. This is always of style <code>buildtime</code>.
+	*
+	* @public
+	* @returns {@ui5/fs/DuplexCollection} DuplexCollection
+	*/
+	getWorkspace() {
+		throw new Error(`getWorkspace must be implemented by subclass ${this.constructor.name}`);
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _configureAndValidatePaths(config) {}
+
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _parseConfiguration(config) {}
+}
+
+export default Project;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_Specification.js.html b/v3/api/project_lib_specifications_Specification.js.html new file mode 100644 index 0000000000..5b8518a299 --- /dev/null +++ b/v3/api/project_lib_specifications_Specification.js.html @@ -0,0 +1,392 @@ + + + + + + + project/lib/specifications/Specification.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/Specification.js

+ + + + + + + +
+
+
import path from "node:path";
+import {getLogger} from "@ui5/logger";
+import {createReader} from "@ui5/fs/resourceFactory";
+import SpecificationVersion from "./SpecificationVersion.js";
+
+/**
+ * Abstract superclass for all projects and extensions
+ *
+ * @public
+ * @abstract
+ * @class
+ * @alias @ui5/project/specifications/Specification
+ * @hideconstructor
+ */
+class Specification {
+	/**
+	 * Create a Specification instance for the given parameters
+	 *
+	 * @param {object} parameters
+	 * @param {string} parameters.id Unique ID
+	 * @param {string} parameters.version Version
+	 * @param {string} parameters.modulePath Absolute File System path to access resources
+	 * @param {object} parameters.configuration
+	 *   Type-dependent configuration object. Typically defined in a ui5.yaml
+	 * @static
+	 * @public
+	 */
+	static async create(parameters) {
+		if (!parameters.configuration) {
+			throw new Error(
+				`Unable to create Specification instance: Missing configuration parameter`);
+		}
+		const {kind, type} = parameters.configuration;
+		if (!["project", "extension"].includes(kind)) {
+			throw new Error(`Unable to create Specification instance: Unknown kind '${kind}'`);
+		}
+
+		switch (type) {
+		case "application": {
+			return createAndInitializeSpec("types/Application.js", parameters);
+		}
+		case "library": {
+			return createAndInitializeSpec("types/Library.js", parameters);
+		}
+		case "theme-library": {
+			return createAndInitializeSpec("types/ThemeLibrary.js", parameters);
+		}
+		case "module": {
+			return createAndInitializeSpec("types/Module.js", parameters);
+		}
+		case "task": {
+			return createAndInitializeSpec("extensions/Task.js", parameters);
+		}
+		case "server-middleware": {
+			return createAndInitializeSpec("extensions/ServerMiddleware.js", parameters);
+		}
+		case "project-shim": {
+			return createAndInitializeSpec("extensions/ProjectShim.js", parameters);
+		}
+		default:
+			throw new Error(
+				`Unable to create Specification instance: Unknown specification type '${type}'`);
+		}
+	}
+
+	constructor() {
+		if (new.target === Specification) {
+			throw new TypeError("Class 'Specification' is abstract. Please use one of the 'types' subclasses");
+		}
+		this._log = getLogger(`specifications:types:${this.constructor.name}`);
+	}
+
+	/**
+	 * @param {object} parameters Specification parameters
+	 * @param {string} parameters.id Unique ID
+	 * @param {string} parameters.version Version
+	 * @param {string} parameters.modulePath Absolute File System path to access resources
+	 * @param {object} parameters.configuration Configuration object
+	 */
+	async init({id, version, modulePath, configuration}) {
+		if (!id) {
+			throw new Error(`Could not create Specification: Missing or empty parameter 'id'`);
+		}
+		if (!version) {
+			throw new Error(`Could not create Specification: Missing or empty parameter 'version'`);
+		}
+		if (!modulePath) {
+			throw new Error(`Could not create Specification: Missing or empty parameter 'modulePath'`);
+		}
+		if (!path.isAbsolute(modulePath)) {
+			throw new Error(`Could not create Specification: Parameter 'modulePath' must contain an absolute path`);
+		}
+		if (!configuration) {
+			throw new Error(`Could not create Specification: Missing or empty parameter 'configuration'`);
+		}
+
+		this._version = version;
+		this._modulePath = modulePath;
+
+		// The ID property is filled from the provider (e.g. package.json "name") and might differ between providers.
+		// It is mainly used to detect framework libraries marked by @openui5 / @sapui5 scopes of npm package.
+		// (see Project#isFrameworkProject)
+		// In general, the configured name (metadata.name) should be used instead as the unique identifier of a project.
+		this.__id = id;
+
+		// Deep clone config to prevent changes by reference
+		const config = JSON.parse(JSON.stringify(configuration));
+		const {validate} = await import("../validation/validator.js");
+
+		if (SpecificationVersion.major(config.specVersion) <= 1) {
+			const originalSpecVersion = config.specVersion;
+			this._log.verbose(`Detected legacy Specification Version ${config.specVersion}, defined for ` +
+				`${config.kind} ${config.metadata.name}. ` +
+				`Attempting to migrate the project to a supported specification version...`);
+			this._migrateLegacyProject(config);
+			try {
+				await validate({
+					config,
+					project: {
+						id
+					}
+				});
+			} catch (err) {
+				this._log.verbose(
+					`Validation error after migration of ${config.kind} ${config.metadata.name}:`);
+				this._log.verbose(err.message);
+				throw new Error(
+					`${config.kind} ${config.metadata.name} defines unsupported Specification Version ` +
+					`${originalSpecVersion}. Please manually upgrade to 3.0 or higher. ` +
+					`For details see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions - ` +
+					`An attempted migration to a supported specification version failed, ` +
+					`likely due to unrecognized configuration. Check verbose log for details.`);
+			}
+		} else {
+			await validate({
+				config,
+				project: {
+					id
+				}
+			});
+		}
+
+		// Check whether the given configuration matches the class by guessing the type name from the class name
+		if (config.type.replace("-", "") !== this.constructor.name.toLowerCase()) {
+			throw new Error(
+				`Configuration mismatch: Supplied configuration of type '${config.type}' does not match with ` +
+				`specification class ${this.constructor.name}`);
+		}
+
+		this._name = config.metadata.name;
+		this._kind = config.kind;
+		this._type = config.type;
+		this._specVersionString = config.specVersion;
+		this._specVersion = new SpecificationVersion(this._specVersionString);
+		this._config = config;
+
+		return this;
+	}
+
+	/* === Attributes === */
+	/**
+	 * Gets the ID of this specification.
+	 *
+	 * <p><b>Note: </b>Only to be used for special occasions as it is specific to the provider that was used and does
+	 * not necessarily represent something defined by the project.</p>
+	 *
+	 * For general purposes of a unique identifier use
+	 * {@link @ui5/project/specifications/Specification#getName getName} instead.
+	 *
+	 * @public
+	 * @returns {string} Specification ID
+	 */
+	getId() {
+		return this.__id;
+	}
+
+	/**
+	 * Gets the name of this specification. Represents a unique identifier.
+	 *
+	 * @public
+	 * @returns {string} Specification name
+	 */
+	getName() {
+		return this._name;
+	}
+
+	/**
+	 * Gets the kind of this specification, for example <code>project</code> or <code>extension</code>
+	 *
+	 * @public
+	 * @returns {string} Specification kind
+	 */
+	getKind() {
+		return this._kind;
+	}
+
+	/**
+	 * Gets the type of this specification,
+	 * for example <code>application</code> or <code>library</code> in case of projects,
+	 * and <code>task</code> or <code>server-middleware</code> in case of extensions
+	 *
+	 * @public
+	 * @returns {string} Specification type
+	 */
+	getType() {
+		return this._type;
+	}
+
+	/**
+	 * Returns an instance of a helper class representing a Specification Version
+	 *
+	 * @public
+	 * @returns {@ui5/project/specifications/SpecificationVersion}
+	 */
+	getSpecVersion() {
+		return this._specVersion;
+	}
+
+	/**
+	 * Gets the specification's generic version, as typically defined in a <code>package.json</code>
+	 *
+	 * @public
+	 * @returns {string} Project version
+	 */
+	getVersion() {
+		return this._version;
+	}
+
+	/**
+	 * Gets the specification's file system path. This might not be POSIX-style on some platforms
+	 *
+	 * @public
+	 * @returns {string} Project root path
+	 */
+	getRootPath() {
+		return this._modulePath;
+	}
+
+	/* === Resource Access === */
+	/**
+	 * Gets a [ReaderCollection]{@link @ui5/fs/ReaderCollection} for the root directory of the specification.
+	 * Resource readers always use POSIX-style
+	 *
+	 * @public
+	 * @param {object} [parameters] Parameters
+	 * @param {object} [parameters.useGitignore=true]
+	 *   Whether to apply any excludes defined in an optional .gitignore in the root directory
+	 * @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	getRootReader({useGitignore=true} = {}) {
+		return createReader({
+			fsBasePath: this.getRootPath(),
+			virBasePath: "/",
+			name: `Root reader for ${this.getType()} ${this.getKind()} ${this.getName()}`,
+			useGitignore
+		});
+	}
+
+	/* === Internals === */
+	/* === Helper === */
+	/**
+	 * @private
+	 * @param {string} dirPath Directory path, relative to the specification root
+	*/
+	async _dirExists(dirPath) {
+		const resource = await this.getRootReader().byPath(dirPath, {nodir: false});
+		if (resource && resource.getStatInfo().isDirectory()) {
+			return true;
+		}
+		return false;
+	}
+
+	_migrateLegacyProject(config) {
+		// Stick to 2.6 since 3.0 adds further restrictions (i.e. for the name) and enables
+		// functionality for extensions that shouldn't be enabled if the specVersion is not
+		// explicitly set to 3.x
+		config.specVersion = "2.6";
+
+		// propertiesFileSourceEncoding (relevant for applications and libraries) default
+		// has been changed to UTF-8 with specVersion 2.0
+		// Adding back the old default if no configuration is provided.
+		if (config.kind === "project" && ["application", "library"].includes(config.type) &&
+				!config.resources?.configuration?.propertiesFileSourceEncoding) {
+			config.resources = config.resources || {};
+			config.resources.configuration = config.resources.configuration || {};
+			config.resources.configuration.propertiesFileSourceEncoding = "ISO-8859-1";
+		}
+	}
+}
+
+async function createAndInitializeSpec(moduleName, params) {
+	const {default: Spec} = await import(`./${moduleName}`);
+	return new Spec().init(params);
+}
+
+export default Specification;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_SpecificationVersion.js.html b/v3/api/project_lib_specifications_SpecificationVersion.js.html new file mode 100644 index 0000000000..92dbd0c22c --- /dev/null +++ b/v3/api/project_lib_specifications_SpecificationVersion.js.html @@ -0,0 +1,389 @@ + + + + + + + project/lib/specifications/SpecificationVersion.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/SpecificationVersion.js

+ + + + + + + +
+
+
import semver from "semver";
+
+const SPEC_VERSION_PATTERN = /^\d+\.\d+$/;
+const SUPPORTED_VERSIONS = [
+	"0.1", "1.0", "1.1",
+	"2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6",
+	"3.0"
+];
+
+/**
+ * Helper class representing a Specification Version. Featuring helper functions for easy comparison
+ * of versions.
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/utils/SpecificationVersion
+ */
+class SpecificationVersion {
+	#specVersion;
+	#semverVersion;
+
+	/**
+	 * @public
+	 * @param {string} specVersion Specification Version to use for all comparison operations
+	 * @throws {Error} Throws if provided Specification Version is not supported by this version of @ui5/project
+	 */
+	constructor(specVersion) {
+		this.#specVersion = specVersion;
+		this.#semverVersion = getSemverCompatibleVersion(specVersion); // Throws for unsupported versions
+	}
+
+	/**
+	 * Returns the Specification Version
+	 *
+	 * @public
+	 * @returns {string} Specification Version
+	 */
+	toString() {
+		return this.#specVersion;
+	}
+
+	/**
+	 * Returns the major-version of the instance's Specification Version
+	 *
+	 * @public
+	 * @returns {integer} Major version
+	 */
+	major() {
+		return semver.major(this.#semverVersion);
+	}
+
+	/**
+	 * Returns the minor-version of the instance's Specification Version
+	 *
+	 * @public
+	 * @returns {integer} Minor version
+	 */
+	minor() {
+		return semver.minor(this.#semverVersion);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version falls into the provided range
+	 *
+	 * @public
+@param {string} range [Semver]{@link https://www.npmjs.com/package/semver}-style version range,
+for example <code>2.2 - 2.4</code>
+	 * @returns {boolean} True if the instance's Specification Version falls into the provided range
+	 */
+	satisfies(range) {
+		return semver.satisfies(this.#semverVersion, range);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version is greater than the provided test version
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the instance's Specification Version is greater than the provided version
+	 */
+	gt(testVersion) {
+		return handleSemverComparator(semver.gt, this.#semverVersion, testVersion);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version is greater than or equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the instance's Specification Version is greater than or equal to the provided version
+	 */
+	gte(testVersion) {
+		return handleSemverComparator(semver.gte, this.#semverVersion, testVersion);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version is smaller than the provided test version
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the instance's Specification Version is smaller than the provided version
+	 */
+	lt(testVersion) {
+		return handleSemverComparator(semver.lt, this.#semverVersion, testVersion);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version is smaller than or equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the instance's Specification Version is smaller than or equal to the provided version
+	 */
+	lte(testVersion) {
+		return handleSemverComparator(semver.lte, this.#semverVersion, testVersion);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version is equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the instance's Specification Version is equal to the provided version
+	 */
+	eq(testVersion) {
+		return handleSemverComparator(semver.eq, this.#semverVersion, testVersion);
+	}
+
+	/**
+	 * Test whether the instance's Specification Version is not equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the instance's Specification Version is not equal to the provided version
+	 */
+	neq(testVersion) {
+		return handleSemverComparator(semver.neq, this.#semverVersion, testVersion);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is supported by this version of @ui5/project
+	 *
+	 * @public
+	 * @param {string} testVersion A Specification Version to compare the instance's Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is supported
+	 */
+	static isSupportedSpecVersion(testVersion) {
+		return SUPPORTED_VERSIONS.includes(testVersion);
+	}
+
+	/**
+	 * Returns the major-version of the provided Specification Version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @returns {integer} Major version
+	 */
+	static major(specVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.major();
+	}
+
+	/**
+	 * Returns the minor-version of the provided Specification Version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @returns {integer} Minor version
+	 */
+	static minor(specVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.minor();
+	}
+
+	/**
+	 * Test whether the provided Specification Version falls into the provided range
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} range [Semver]{@link https://www.npmjs.com/package/semver}-style version range,
+	 * for example <code>2.2 - 2.4</code>
+	 * @returns {boolean} True if the provided Specification Version falls into the provided range
+	 */
+	static satisfies(specVersion, range) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.satisfies(range);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is greater than the provided test version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} testVersion A Specification Version to compare the provided Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is greater than the provided version
+	 */
+	static gt(specVersion, testVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.gt(testVersion);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is greater than or equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} testVersion A Specification Version to compare the provided Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is greater than or equal to the provided version
+	 */
+	static gte(specVersion, testVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.gte(testVersion);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is smaller than the provided test version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} testVersion A Specification Version to compare the provided Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is smaller than the provided version
+	 */
+	static lt(specVersion, testVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.lt(testVersion);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is smaller than or equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} testVersion A Specification Version to compare the provided Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is smaller than or equal to the provided version
+	 */
+	static lte(specVersion, testVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.lte(testVersion);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} testVersion A Specification Version to compare the provided Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is equal to the provided version
+	 */
+	static eq(specVersion, testVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.eq(testVersion);
+	}
+
+	/**
+	 * Test whether the provided Specification Version is not equal to the provided test version
+	 *
+	 * @public
+	 * @param {string} specVersion Specification Version
+	 * @param {string} testVersion A Specification Version to compare the provided Specification Version to
+	 * @returns {boolean} True if the provided Specification Version is not equal to the provided version
+	 */
+	static neq(specVersion, testVersion) {
+		const comparator = new SpecificationVersion(specVersion);
+		return comparator.neq(testVersion);
+	}
+}
+
+function getUnsupportedSpecVersionMessage(specVersion) {
+	return `Unsupported Specification Version ${specVersion} defined. Your UI5 CLI installation might be outdated. ` +
+		`For details, see https://sap.github.io/ui5-tooling/pages/Configuration/#specification-versions`;
+}
+
+function getSemverCompatibleVersion(specVersion) {
+	if (SpecificationVersion.isSupportedSpecVersion(specVersion)) {
+		return specVersion + ".0";
+	}
+	throw new Error(getUnsupportedSpecVersionMessage(specVersion));
+}
+
+function handleSemverComparator(comparator, baseVersion, testVersion) {
+	if (SPEC_VERSION_PATTERN.test(testVersion)) {
+		const a = baseVersion;
+		const b = testVersion + ".0";
+		return comparator(a, b);
+	}
+	throw new Error("Invalid spec version expectation given in comparator: " + testVersion);
+}
+
+export default SpecificationVersion;
+
+// Export local function for testing only
+export const __localFunctions__ = (process.env.NODE_ENV === "test") ?
+	{getSemverCompatibleVersion, handleSemverComparator} : /* istanbul ignore next */ undefined;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_extensions_ProjectShim.js.html b/v3/api/project_lib_specifications_extensions_ProjectShim.js.html new file mode 100644 index 0000000000..f1bdf82f40 --- /dev/null +++ b/v3/api/project_lib_specifications_extensions_ProjectShim.js.html @@ -0,0 +1,156 @@ + + + + + + + project/lib/specifications/extensions/ProjectShim.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/extensions/ProjectShim.js

+ + + + + + + +
+
+
import Extension from "../Extension.js";
+
+/**
+ * ProjectShim
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/extensions/ProjectShim
+ * @extends @ui5/project/specifications/Extension
+ * @hideconstructor
+ */
+class ProjectShim extends Extension {
+	constructor(parameters) {
+		super(parameters);
+	}
+
+
+	/* === Attributes === */
+	/**
+	* @public
+	*/
+	getDependencyShims() {
+		return this._config.shims.dependencies || {};
+	}
+
+	/**
+	* @public
+	*/
+	getConfigurationShims() {
+		return this._config.shims.configurations || {};
+	}
+
+	/**
+	* @public
+	*/
+	getCollectionShims() {
+		return this._config.shims.collections || {};
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	*/
+	async _validateConfig() {
+		if (this._config.shims.collections) {
+			const {
+				default: path
+			} = await import("path");
+			for (const dependencyDefinition of Object.values(this._config.shims.collections)) {
+				Object.values(dependencyDefinition.modules).forEach((depPath) => {
+					if (path.isAbsolute(depPath)) {
+						throw new Error("All module paths of collections defined in a project-shim must be relative");
+					}
+				});
+			}
+		}
+	}
+}
+
+export default ProjectShim;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_extensions_ServerMiddleware.js.html b/v3/api/project_lib_specifications_extensions_ServerMiddleware.js.html new file mode 100644 index 0000000000..84bfe1af07 --- /dev/null +++ b/v3/api/project_lib_specifications_extensions_ServerMiddleware.js.html @@ -0,0 +1,137 @@ + + + + + + + project/lib/specifications/extensions/ServerMiddleware.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/extensions/ServerMiddleware.js

+ + + + + + + +
+
+
import path from "node:path";
+import Extension from "../Extension.js";
+import {pathToFileURL} from "node:url";
+
+/**
+ * ServerMiddleware
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/extensions/ServerMiddleware
+ * @extends @ui5/project/specifications/Extension
+ * @hideconstructor
+ */
+class ServerMiddleware extends Extension {
+	constructor(parameters) {
+		super(parameters);
+	}
+
+	/* === Attributes === */
+	/**
+	* @public
+	*/
+	async getMiddleware() {
+		const middlewarePath = path.join(this.getRootPath(), this._config.middleware.path);
+		const {default: middleware} = await import(pathToFileURL(middlewarePath));
+		return middleware;
+	}
+	/* === Internals === */
+	/**
+	 * @private
+	*/
+	async _validateConfig() {
+		// TODO: Move to validator
+		if (/--\d+$/.test(this.getName())) {
+			throw new Error(`Server middleware name must not end with '--<number>'`);
+		}
+		// TODO: Check that paths exist
+	}
+}
+
+export default ServerMiddleware;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_extensions_Task.js.html b/v3/api/project_lib_specifications_extensions_Task.js.html new file mode 100644 index 0000000000..7ce9239428 --- /dev/null +++ b/v3/api/project_lib_specifications_extensions_Task.js.html @@ -0,0 +1,154 @@ + + + + + + + project/lib/specifications/extensions/Task.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/extensions/Task.js

+ + + + + + + +
+
+
import path from "node:path";
+import Extension from "../Extension.js";
+import {pathToFileURL} from "node:url";
+
+/**
+ * Task
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/extensions/Task
+ * @extends @ui5/project/specifications/Extension
+ * @hideconstructor
+ */
+class Task extends Extension {
+	constructor(parameters) {
+		super(parameters);
+	}
+
+	/* === Attributes === */
+	/**
+	* @public
+	*/
+	async getTask() {
+		return (await this._getImplementation()).task;
+	}
+
+	/**
+	* @public
+	*/
+	async getRequiredDependenciesCallback() {
+		return (await this._getImplementation()).determineRequiredDependencies;
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	*/
+	async _getImplementation() {
+		const taskPath = path.join(this.getRootPath(), this._config.task.path);
+		const {default: task, determineRequiredDependencies} = await import(pathToFileURL(taskPath));
+		return {
+			task, determineRequiredDependencies
+		};
+	}
+
+	/**
+	 * @private
+	*/
+	async _validateConfig() {
+		// TODO: Move to validator
+		if (/--\d+$/.test(this.getName())) {
+			throw new Error(`Task name must not end with '--<number>'`);
+		}
+		// TODO: Check that paths exist
+	}
+}
+
+export default Task;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_types_Application.js.html b/v3/api/project_lib_specifications_types_Application.js.html new file mode 100644 index 0000000000..9e77785db4 --- /dev/null +++ b/v3/api/project_lib_specifications_types_Application.js.html @@ -0,0 +1,330 @@ + + + + + + + project/lib/specifications/types/Application.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/types/Application.js

+ + + + + + + +
+
+
import fsPath from "node:path";
+import ComponentProject from "../ComponentProject.js";
+import {createReader} from "@ui5/fs/resourceFactory";
+
+/**
+ * Application
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/types/Application
+ * @extends @ui5/project/specifications/ComponentProject
+ * @hideconstructor
+ */
+class Application extends ComponentProject {
+	constructor(parameters) {
+		super(parameters);
+
+		this._pManifests = Object.create(null);
+
+		this._webappPath = "webapp";
+
+		this._isRuntimeNamespaced = false;
+	}
+
+
+	/* === Attributes === */
+
+	/**
+	* Get the cachebuster signature type configuration of the project
+	*
+	* @returns {string} <code>time</code> or <code>hash</code>
+	*/
+	getCachebusterSignatureType() {
+		return this._config.builder && this._config.builder.cachebuster &&
+			this._config.builder.cachebuster.signatureType || "time";
+	}
+
+	/**
+	 * Get the path of the project's source directory. This might not be POSIX-style on some platforms.
+	 *
+	 * @public
+	 * @returns {string} Absolute path to the source directory of the project
+	 */
+	getSourcePath() {
+		return fsPath.join(this.getRootPath(), this._webappPath);
+	}
+
+	/* === Resource Access === */
+	/**
+	* Get a resource reader for the sources of the project (excluding any test resources)
+	*
+	* @param {string[]} excludes List of glob patterns to exclude
+	* @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	_getSourceReader(excludes) {
+		return createReader({
+			fsBasePath: this.getSourcePath(),
+			virBasePath: `/resources/${this._namespace}/`,
+			name: `Source reader for application project ${this.getName()}`,
+			project: this,
+			excludes
+		});
+	}
+
+	_getTestReader() {
+		return null; // Applications do not have a dedicated test directory
+	}
+
+	_getRawSourceReader() {
+		return createReader({
+			fsBasePath: this.getSourcePath(),
+			virBasePath: "/",
+			name: `Source reader for application project ${this.getName()}`,
+			project: this
+		});
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _configureAndValidatePaths(config) {
+		await super._configureAndValidatePaths(config);
+
+		if (config.resources && config.resources.configuration &&
+			config.resources.configuration.paths && config.resources.configuration.paths.webapp) {
+			this._webappPath = config.resources.configuration.paths.webapp;
+		}
+
+		this._log.verbose(`Path mapping for application project ${this.getName()}:`);
+		this._log.verbose(`  Physical root path: ${this.getRootPath()}`);
+		this._log.verbose(`  Mapped to: ${this._webappPath}`);
+
+		if (!(await this._dirExists("/" + this._webappPath))) {
+			throw new Error(
+				`Unable to find source directory '${this._webappPath}' in application project ${this.getName()}`);
+		}
+	}
+
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	 * @param {object} buildDescription Cache metadata object
+	*/
+	async _parseConfiguration(config, buildDescription) {
+		await super._parseConfiguration(config, buildDescription);
+
+		if (buildDescription) {
+			this._namespace = buildDescription.namespace;
+			return;
+		}
+		this._namespace = await this._getNamespace();
+	}
+
+	/**
+	 * Determine application namespace either based on a project`s
+	 * manifest.json or manifest.appdescr_variant (fallback if present)
+	 *
+	 * @returns {string} Namespace of the project
+	 * @throws {Error} if namespace can not be determined
+	 */
+	async _getNamespace() {
+		try {
+			return await this._getNamespaceFromManifestJson();
+		} catch (manifestJsonError) {
+			if (manifestJsonError.code !== "ENOENT") {
+				throw manifestJsonError;
+			}
+			// No manifest.json present
+			// => attempt fallback to manifest.appdescr_variant (typical for App Variants)
+			try {
+				return await this._getNamespaceFromManifestAppDescVariant();
+			} catch (appDescVarError) {
+				if (appDescVarError.code === "ENOENT") {
+					// Fallback not possible: No manifest.appdescr_variant present
+					// => Throw error indicating missing manifest.json
+					// 	(do not mention manifest.appdescr_variant since it is only
+					// 	relevant for the rather "uncommon" App Variants)
+					throw new Error(
+						`Could not find required manifest.json for project ` +
+						`${this.getName()}: ${manifestJsonError.message}`);
+				}
+				throw appDescVarError;
+			}
+		}
+	}
+
+	/**
+	 * Determine application namespace by checking manifest.json.
+	 * Any maven placeholders are resolved from the projects pom.xml
+	 *
+	 * @returns {string} Namespace of the project
+	 * @throws {Error} if namespace can not be determined
+	 */
+	async _getNamespaceFromManifestJson() {
+		const manifest = await this._getManifest("/manifest.json");
+		let appId;
+		// check for a proper sap.app/id in manifest.json to determine namespace
+		if (manifest["sap.app"] && manifest["sap.app"].id) {
+			appId = manifest["sap.app"].id;
+		} else {
+			throw new Error(
+				`No sap.app/id configuration found in manifest.json of project ${this.getName()}`);
+		}
+
+		if (this._hasMavenPlaceholder(appId)) {
+			try {
+				appId = await this._resolveMavenPlaceholder(appId);
+			} catch (err) {
+				throw new Error(
+					`Failed to resolve namespace of project ${this.getName()}: ${err.message}`);
+			}
+		}
+		const namespace = appId.replace(/\./g, "/");
+		this._log.verbose(
+			`Namespace of project ${this.getName()} is ${namespace} (from manifest.json)`);
+		return namespace;
+	}
+
+	/**
+	 * Determine application namespace by checking manifest.appdescr_variant.
+	 *
+	 * @returns {string} Namespace of the project
+	 * @throws {Error} if namespace can not be determined
+	 */
+	async _getNamespaceFromManifestAppDescVariant() {
+		const manifest = await this._getManifest("/manifest.appdescr_variant");
+		let appId;
+		// check for the id property in manifest.appdescr_variant to determine namespace
+		if (manifest && manifest.id) {
+			appId = manifest.id;
+		} else {
+			throw new Error(
+				`No "id" property found in manifest.appdescr_variant of project ${this.getName()}`);
+		}
+
+		const namespace = appId.replace(/\./g, "/");
+		this._log.verbose(
+			`Namespace of project ${this.getName()} is ${namespace} (from manifest.appdescr_variant)`);
+		return namespace;
+	}
+
+	/**
+	 * Reads and parses a JSON file with the provided name from the projects source directory
+	 *
+	 * @param {string} filePath Name of the JSON file to read. Typically "manifest.json" or "manifest.appdescr_variant"
+	 * @returns {Promise<object>} resolves with an object containing the content requested manifest file
+	 */
+	async _getManifest(filePath) {
+		if (this._pManifests[filePath]) {
+			return this._pManifests[filePath];
+		}
+		return this._pManifests[filePath] = this._getRawSourceReader().byPath(filePath)
+			.then(async (resource) => {
+				if (!resource) {
+					const error = new Error(
+						`Could not find resource ${filePath} in project ${this.getName()}`);
+					error.code = "ENOENT"; // "File or directory does not exist"
+					throw error;
+				}
+				return JSON.parse(await resource.getString());
+			}).catch((err) => {
+				if (err.code === "ENOENT") {
+					throw err;
+				}
+				throw new Error(
+					`Failed to read ${filePath} for project ` +
+					`${this.getName()}: ${err.message}`);
+			});
+	}
+}
+
+export default Application;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_types_Library.js.html b/v3/api/project_lib_specifications_types_Library.js.html new file mode 100644 index 0000000000..b2ce9973da --- /dev/null +++ b/v3/api/project_lib_specifications_types_Library.js.html @@ -0,0 +1,636 @@ + + + + + + + project/lib/specifications/types/Library.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/types/Library.js

+ + + + + + + +
+
+
import fsPath from "node:path";
+import posixPath from "node:path/posix";
+import {promisify} from "node:util";
+import ComponentProject from "../ComponentProject.js";
+import * as resourceFactory from "@ui5/fs/resourceFactory";
+
+/**
+ * Library
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/types/Library
+ * @extends @ui5/project/specifications/ComponentProject
+ * @hideconstructor
+ */
+class Library extends ComponentProject {
+	constructor(parameters) {
+		super(parameters);
+
+		this._pManifest = null;
+		this._pDotLibrary = null;
+		this._pLibraryJs = null;
+
+		this._srcPath = "src";
+		this._testPath = "test";
+		this._testPathExists = false;
+		this._isSourceNamespaced = true;
+
+		this._propertiesFilesSourceEncoding = "UTF-8";
+	}
+
+	/* === Attributes === */
+	/**
+	*
+	* @private
+	*/
+	getLibraryPreloadExcludes() {
+		return this._config.builder && this._config.builder.libraryPreload &&
+			this._config.builder.libraryPreload.excludes || [];
+	}
+
+	/**
+	* @private
+	*/
+	getJsdocExcludes() {
+		return this._config.builder && this._config.builder.jsdoc && this._config.builder.jsdoc.excludes || [];
+	}
+
+	/**
+	 * Get the path of the project's source directory. This might not be POSIX-style on some platforms.
+	 *
+	 * @public
+	 * @returns {string} Absolute path to the source directory of the project
+	 */
+	getSourcePath() {
+		return fsPath.join(this.getRootPath(), this._srcPath);
+	}
+
+	/* === Resource Access === */
+	/**
+	* Get a resource reader for the sources of the project (excluding any test resources)
+	*
+	* @param {string[]} excludes List of glob patterns to exclude
+	* @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	_getSourceReader(excludes) {
+		// TODO: Throw for libraries with additional namespaces like sap.ui.core?
+		let virBasePath = "/resources/";
+		if (!this._isSourceNamespaced) {
+			// In case the namespace is not represented in the source directory
+			// structure, add it to the virtual base path
+			virBasePath += `${this._namespace}/`;
+		}
+		return resourceFactory.createReader({
+			fsBasePath: this.getSourcePath(),
+			virBasePath,
+			name: `Source reader for library project ${this.getName()}`,
+			project: this,
+			excludes
+		});
+	}
+
+	/**
+	* Get a resource reader for the test-resources of the project
+	*
+	* @param {string[]} excludes List of glob patterns to exclude
+	* @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	_getTestReader(excludes) {
+		if (!this._testPathExists) {
+			return null;
+		}
+		let virBasePath = "/test-resources/";
+		if (!this._isSourceNamespaced) {
+			// In case the namespace is not represented in the source directory
+			// structure, add it to the virtual base path
+			virBasePath += `${this._namespace}/`;
+		}
+		const testReader = resourceFactory.createReader({
+			fsBasePath: fsPath.join(this.getRootPath(), this._testPath),
+			virBasePath,
+			name: `Runtime test-resources reader for library project ${this.getName()}`,
+			project: this,
+			excludes
+		});
+		return testReader;
+	}
+
+	/**
+	 *
+	 * Get a resource reader for the sources of the project (excluding any test resources)
+	 * In the future the path structure can be flat or namespaced depending on the project
+	 *
+	 * @returns {@ui5/fs/ReaderCollection} Reader collection
+	*/
+	_getRawSourceReader() {
+		return resourceFactory.createReader({
+			fsBasePath: this.getSourcePath(),
+			virBasePath: "/",
+			name: `Source reader for library project ${this.getName()}`,
+			project: this
+		});
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _configureAndValidatePaths(config) {
+		await super._configureAndValidatePaths(config);
+
+		if (config.resources && config.resources.configuration && config.resources.configuration.paths) {
+			if (config.resources.configuration.paths.src) {
+				this._srcPath = config.resources.configuration.paths.src;
+			}
+			if (config.resources.configuration.paths.test) {
+				this._testPath = config.resources.configuration.paths.test;
+			}
+		}
+		if (!(await this._dirExists("/" + this._srcPath))) {
+			throw new Error(
+				`Unable to find source directory '${this._srcPath}' in library project ${this.getName()}`);
+		}
+		this._testPathExists = await this._dirExists("/" + this._testPath);
+
+		this._log.verbose(`Path mapping for library project ${this.getName()}:`);
+		this._log.verbose(`  Physical root path: ${this.getRootPath()}`);
+		this._log.verbose(`  Mapped to:`);
+		this._log.verbose(`    /resources/ => ${this._srcPath}`);
+		this._log.verbose(
+			`    /test-resources/ => ${this._testPath}${this._testPathExists ? "" : " [does not exist]"}`);
+	}
+
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	 * @param {object} buildDescription Cache metadata object
+	*/
+	async _parseConfiguration(config, buildDescription) {
+		await super._parseConfiguration(config, buildDescription);
+
+		if (buildDescription) {
+			this._namespace = buildDescription.namespace;
+			return;
+		}
+
+		this._namespace = await this._getNamespace();
+
+		if (!config.metadata.copyright) {
+			const copyright = await this._getCopyrightFromDotLibrary();
+			if (copyright) {
+				config.metadata.copyright = copyright;
+			}
+		}
+
+		if (this.isFrameworkProject()) {
+			// Only framework projects are allowed to provide preload-excludes in their .library file,
+			// and only if it is not already defined in the ui5.yaml
+			if (config.builder?.libraryPreload?.excludes) {
+				this._log.verbose(
+					`Using preload excludes for framework library ${this.getName()} from project configuration`);
+			} else {
+				this._log.verbose(
+					`No preload excludes defined in project configuration of framework library ` +
+					`${this.getName()}. Falling back to .library...`);
+				const excludes = await this._getPreloadExcludesFromDotLibrary();
+				if (excludes) {
+					if (!config.builder) {
+						config.builder = {};
+					}
+					if (!config.builder.libraryPreload) {
+						config.builder.libraryPreload = {};
+					}
+					config.builder.libraryPreload.excludes = excludes;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Determine library namespace by checking manifest.json with fallback to .library.
+	 * Any maven placeholders are resolved from the projects pom.xml
+	 *
+	 * @returns {string} Namespace of the project
+	 * @throws {Error} if namespace can not be determined
+	 */
+	async _getNamespace() {
+		// Trigger both reads asynchronously
+		const [{
+			namespace: manifestNs,
+			filePath: manifestPath
+		}, {
+			namespace: dotLibraryNs,
+			filePath: dotLibraryPath
+		}] = await Promise.all([
+			this._getNamespaceFromManifest(),
+			this._getNamespaceFromDotLibrary()
+		]);
+
+		let libraryNs;
+		let namespacePath;
+		if (manifestNs && dotLibraryNs) {
+			// Both files present
+			// => check whether they are on the same level
+			const manifestDepth = manifestPath.split("/").length;
+			const dotLibraryDepth = dotLibraryPath.split("/").length;
+
+			if (manifestDepth < dotLibraryDepth) {
+				// We see the .library file as the "leading" file of a library
+				// Therefore, a manifest.json on a higher level is something we do not except
+				throw new Error(`Failed to detect namespace for project ${this.getName()}: ` +
+					`Found a manifest.json on a higher directory level than the .library file. ` +
+					`It should be on the same or a lower level. ` +
+					`Note that a manifest.json on a lower level will be ignored.\n` +
+					`  manifest.json path: ${manifestPath}\n` +
+					`  is higher than\n` +
+					`  .library path: ${dotLibraryPath}`);
+			}
+			if (manifestDepth === dotLibraryDepth) {
+				if (posixPath.dirname(manifestPath) !== posixPath.dirname(dotLibraryPath)) {
+					// This just should not happen in your project
+					throw new Error(`Failed to detect namespace for project ${this.getName()}: ` +
+					`Found a manifest.json on the same directory level but in a different directory ` +
+					`than the .library file. They should be in the same directory.\n` +
+					`  manifest.json path: ${manifestPath}\n` +
+					`  is different to\n` +
+					`  .library path: ${dotLibraryPath}`);
+				}
+				// Typical scenario if both files are present
+				this._log.verbose(
+					`Found a manifest.json and a .library file on the same level for ` +
+					`project ${this.getName()}.`);
+				this._log.verbose(
+					`Resolving namespace of project ${this.getName()} from manifest.json...`);
+				libraryNs = manifestNs;
+				namespacePath = posixPath.dirname(manifestPath);
+			} else {
+				// Typical scenario: Some nested component has a manifest.json but the library itself only
+				// features a .library.  => Ignore the manifest.json
+				this._log.verbose(
+					`Ignoring manifest.json found on a lower level than the .library file of ` +
+					`project ${this.getName()}.`);
+				this._log.verbose(
+					`Resolving namespace of project ${this.getName()} from .library...`);
+				libraryNs = dotLibraryNs;
+				namespacePath = posixPath.dirname(dotLibraryPath);
+			}
+		} else if (manifestNs) {
+			// Only manifest available
+			this._log.verbose(
+				`Resolving namespace of project ${this.getName()} from manifest.json...`);
+			libraryNs = manifestNs;
+			namespacePath = posixPath.dirname(manifestPath);
+		} else if (dotLibraryNs) {
+			// Only .library available
+			this._log.verbose(
+				`Resolving namespace of project ${this.getName()} from .library...`);
+			libraryNs = dotLibraryNs;
+			namespacePath = posixPath.dirname(dotLibraryPath);
+		} else {
+			this._log.verbose(
+				`Failed to resolve namespace of project ${this.getName()} from manifest.json ` +
+				`or .library file. Falling back to library.js file path...`);
+		}
+
+		let namespace;
+		if (libraryNs) {
+			// Maven placeholders can only exist in manifest.json or .library configuration
+			if (this._hasMavenPlaceholder(libraryNs)) {
+				try {
+					libraryNs = await this._resolveMavenPlaceholder(libraryNs);
+				} catch (err) {
+					throw new Error(
+						`Failed to resolve namespace maven placeholder of project ` +
+						`${this.getName()}: ${err.message}`);
+				}
+			}
+
+			namespace = libraryNs.replace(/\./g, "/");
+			if (namespacePath === "/") {
+				this._log.verbose(`Detected flat library source structure for project ${this.getName()}`);
+				this._isSourceNamespaced = false;
+			} else {
+				namespacePath = namespacePath.replace("/", ""); // remove leading slash
+				if (namespacePath !== namespace) {
+					throw new Error(
+						`Detected namespace "${namespace}" does not match detected directory ` +
+						`structure "${namespacePath}" for project ${this.getName()}`);
+				}
+			}
+		} else {
+			try {
+				const libraryJsPath = await this._getLibraryJsPath();
+				namespacePath = posixPath.dirname(libraryJsPath);
+				namespace = namespacePath.replace("/", ""); // remove leading slash
+				if (namespace === "") {
+					throw new Error(`Found library.js file in root directory. ` +
+						`Expected it to be in namespace directory.`);
+				}
+				this._log.verbose(
+					`Deriving namespace for project ${this.getName()} from ` +
+					`path of library.js file`);
+			} catch (err) {
+				this._log.verbose(
+					`Namespace resolution from library.js file path failed for project ` +
+					`${this.getName()}: ${err.message}`);
+			}
+		}
+
+		if (!namespace) {
+			throw new Error(`Failed to detect namespace or namespace is empty for ` +
+				`project ${this.getName()}. Check verbose log for details.`);
+		}
+
+		this._log.verbose(
+			`Namespace of project ${this.getName()} is ${namespace}`);
+		return namespace;
+	}
+
+	async _getNamespaceFromManifest() {
+		try {
+			const {content: manifest, filePath} = await this._getManifest();
+			// check for a proper sap.app/id in manifest.json to determine namespace
+			if (manifest["sap.app"] && manifest["sap.app"].id) {
+				const namespace = manifest["sap.app"].id;
+				this._log.verbose(
+					`Found namespace ${namespace} in manifest.json of project ${this.getName()} ` +
+					`at ${filePath}`);
+				return {
+					namespace,
+					filePath
+				};
+			} else {
+				throw new Error(
+					`No sap.app/id configuration found in manifest.json of project ${this.getName()} ` +
+					`at ${filePath}`);
+			}
+		} catch (err) {
+			this._log.verbose(
+				`Namespace resolution from manifest.json failed for project ` +
+				`${this.getName()}: ${err.message}`);
+		}
+		return {};
+	}
+
+	async _getNamespaceFromDotLibrary() {
+		try {
+			const {content: dotLibrary, filePath} = await this._getDotLibrary();
+			const namespace = dotLibrary?.library?.name?._;
+			if (namespace) {
+				this._log.verbose(
+					`Found namespace ${namespace} in .library file of project ${this.getName()} ` +
+					`at ${filePath}`);
+				return {
+					namespace,
+					filePath
+				};
+			} else {
+				throw new Error(
+					`No library name found in .library of project ${this.getName()} ` +
+					`at ${filePath}`);
+			}
+		} catch (err) {
+			this._log.verbose(
+				`Namespace resolution from .library failed for project ` +
+				`${this.getName()}: ${err.message}`);
+		}
+		return {};
+	}
+
+	/**
+	 * Determines library copyright from given project configuration with fallback to .library.
+	 *
+	 * @returns {string|null} Copyright of the project
+	 */
+	async _getCopyrightFromDotLibrary() {
+		try {
+			// If no copyright replacement was provided by ui5.yaml,
+			// check if the .library file has a valid copyright replacement
+			const {content: dotLibrary, filePath} = await this._getDotLibrary();
+			if (dotLibrary?.library?.copyright?._) {
+				this._log.verbose(
+					`Using copyright from ${filePath} for project ${this.getName()}...`);
+				return dotLibrary.library.copyright._;
+			} else {
+				this._log.verbose(
+					`No copyright configuration found in ${filePath} ` +
+					`of project ${this.getName()}`);
+				return null;
+			}
+		} catch (err) {
+			this._log.verbose(
+				`Copyright determination from .library failed for project ` +
+				`${this.getName()}: ${err.message}`);
+			return null;
+		}
+	}
+
+	async _getPreloadExcludesFromDotLibrary() {
+		const {content: dotLibrary, filePath} = await this._getDotLibrary();
+		let excludes = dotLibrary?.library?.appData?.packaging?.["all-in-one"]?.exclude;
+		if (excludes) {
+			if (!Array.isArray(excludes)) {
+				excludes = [excludes];
+			}
+			this._log.verbose(
+				`Found ${excludes.length} preload excludes in .library file of ` +
+				`project ${this.getName()} at ${filePath}`);
+			return excludes.map((exclude) => {
+				return exclude.$.name;
+			});
+		} else {
+			this._log.verbose(
+				`No preload excludes found in .library of project ${this.getName()} ` +
+				`at ${filePath}`);
+			return null;
+		}
+	}
+
+	/**
+	 * Reads the projects manifest.json
+	 *
+	 * @returns {Promise<object>} resolves with an object containing the <code>content</code> (as JSON) and
+	 * 							<code>filePath</code> (as string) of the manifest.json file
+	 */
+	async _getManifest() {
+		if (this._pManifest) {
+			return this._pManifest;
+		}
+		return this._pManifest = this._getRawSourceReader().byGlob("**/manifest.json")
+			.then(async (manifestResources) => {
+				if (!manifestResources.length) {
+					throw new Error(`Could not find manifest.json file for project ${this.getName()}`);
+				}
+				if (manifestResources.length > 1) {
+					throw new Error(`Found multiple (${manifestResources.length}) manifest.json files ` +
+						`for project ${this.getName()}`);
+				}
+				const resource = manifestResources[0];
+				try {
+					return {
+						content: JSON.parse(await resource.getString()),
+						filePath: resource.getPath()
+					};
+				} catch (err) {
+					throw new Error(
+						`Failed to read ${resource.getPath()} for project ${this.getName()}: ${err.message}`);
+				}
+			});
+	}
+
+	/**
+	 * Reads the .library file
+	 *
+	 * @returns {Promise<object>} resolves with an object containing the <code>content</code> (as JSON) and
+	 * 							<code>filePath</code> (as string) of the .library file
+	 */
+	async _getDotLibrary() {
+		if (this._pDotLibrary) {
+			return this._pDotLibrary;
+		}
+		return this._pDotLibrary = this._getRawSourceReader().byGlob("**/.library")
+			.then(async (dotLibraryResources) => {
+				if (!dotLibraryResources.length) {
+					throw new Error(`Could not find .library file for project ${this.getName()}`);
+				}
+				if (dotLibraryResources.length > 1) {
+					throw new Error(`Found multiple (${dotLibraryResources.length}) .library files ` +
+						`for project ${this.getName()}`);
+				}
+				const resource = dotLibraryResources[0];
+				const content = await resource.getString();
+
+				try {
+					const {
+						default: xml2js
+					} = await import("xml2js");
+					const parser = new xml2js.Parser({
+						explicitArray: false,
+						explicitCharkey: true
+					});
+					const readXML = promisify(parser.parseString);
+					return {
+						content: await readXML(content),
+						filePath: resource.getPath()
+					};
+				} catch (err) {
+					throw new Error(
+						`Failed to read ${resource.getPath()} for project ${this.getName()}: ${err.message}`);
+				}
+			});
+	}
+
+	/**
+	 * Determines the path of the library.js file
+	 *
+	 * @returns {Promise<string>} resolves with an a string containing the file system path
+	 *								of the library.js file
+	 */
+	async _getLibraryJsPath() {
+		if (this._pLibraryJs) {
+			return this._pLibraryJs;
+		}
+		return this._pLibraryJs = this._getRawSourceReader().byGlob("**/library.js")
+			.then(async (libraryJsResources) => {
+				if (!libraryJsResources.length) {
+					throw new Error(`Could not find library.js file for project ${this.getName()}`);
+				}
+				if (libraryJsResources.length > 1) {
+					throw new Error(`Found multiple (${libraryJsResources.length}) library.js files ` +
+						`for project ${this.getName()}`);
+				}
+				// Content is not yet relevant, so don't read it
+				return libraryJsResources[0].getPath();
+			});
+	}
+}
+
+export default Library;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_types_Module.js.html b/v3/api/project_lib_specifications_types_Module.js.html new file mode 100644 index 0000000000..08c05720b7 --- /dev/null +++ b/v3/api/project_lib_specifications_types_Module.js.html @@ -0,0 +1,262 @@ + + + + + + + project/lib/specifications/types/Module.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/types/Module.js

+ + + + + + + +
+
+
import fsPath from "node:path";
+import Project from "../Project.js";
+import * as resourceFactory from "@ui5/fs/resourceFactory";
+
+/**
+ * Module
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/types/Module
+ * @extends @ui5/project/specifications/Project
+ * @hideconstructor
+ */
+class Module extends Project {
+	constructor(parameters) {
+		super(parameters);
+
+		this._paths = null;
+		this._writer = null;
+	}
+
+	/* === Attributes === */
+
+	/**
+	 * Since Modules have multiple source paths, this function always throws with an exception
+	 *
+	 * @public
+	 * @throws {Error} Projects of type module have more than one source path
+	 */
+	getSourcePath() {
+		throw new Error(`Projects of type module have more than one source path`);
+	}
+
+	/* === Resource Access === */
+
+	/**
+	 * Get a [ReaderCollection]{@link @ui5/fs/ReaderCollection} for accessing all resources of the
+	 * project in the specified "style":
+	 *
+	 * <ul>
+	 * <li><b>buildtime:</b> Resource paths are always prefixed with <code>/resources/</code>
+	 *  or <code>/test-resources/</code> followed by the project's namespace.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>dist:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>runtime:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  This style is typically used for serving resources directly. Therefore, build-excludes are not applied
+	 * <li><b>flat:</b> Resource paths are never prefixed and namespaces are omitted if possible. Note that
+	 *  project types like "theme-library", which can have multiple namespaces, can't omit them.
+	 *  Any configured build-excludes are applied</li>
+	 * </ul>
+	 *
+	 * If project resources have been changed through the means of a workspace, those changes
+	 * are reflected in the provided reader too.
+	 *
+	 * Resource readers always use POSIX-style paths.
+	 *
+	 * @public
+	 * @param {object} [options]
+	 * @param {string} [options.style=buildtime] Path style to access resources.
+	 *   Can be "buildtime", "dist", "runtime" or "flat"
+	 * @returns {@ui5/fs/ReaderCollection} A reader collection instance
+	 */
+	getReader({style = "buildtime"} = {}) {
+		// Apply builder excludes to all styles but "runtime"
+		const excludes = style === "runtime" ? [] : this.getBuilderResourcesExcludes();
+
+		const readers = this._paths.map(({name, virBasePath, fsBasePath}) => {
+			return resourceFactory.createReader({
+				name,
+				virBasePath,
+				fsBasePath,
+				project: this,
+				excludes
+			});
+		});
+		if (readers.length === 1) {
+			return readers[0];
+		}
+		const readerCollection = resourceFactory.createReaderCollection({
+			name: `Reader collection for module project ${this.getName()}`,
+			readers
+		});
+		return resourceFactory.createReaderCollectionPrioritized({
+			name: `Reader/Writer collection for project ${this.getName()}`,
+			readers: [this._getWriter(), readerCollection]
+		});
+	}
+
+	/**
+	 * Get a resource reader/writer for accessing and modifying a project's resources
+	 *
+	 * @public
+	 * @returns {@ui5/fs/ReaderCollection} A reader collection instance
+	 */
+	getWorkspace() {
+		const reader = this.getReader();
+
+		const writer = this._getWriter();
+		return resourceFactory.createWorkspace({
+			reader,
+			writer
+		});
+	}
+
+	_getWriter() {
+		if (!this._writer) {
+			this._writer = resourceFactory.createAdapter({
+				virBasePath: "/"
+			});
+		}
+
+		return this._writer;
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _configureAndValidatePaths(config) {
+		await super._configureAndValidatePaths(config);
+
+		this._log.verbose(`Path mapping for module project ${this.getName()}:`);
+		this._log.verbose(`  Physical root path: ${this.getRootPath()}`);
+		this._log.verbose(`  Mapped to:`);
+
+		if (config.resources?.configuration?.paths) {
+			const pathMappings = Object.entries(config.resources.configuration.paths);
+			if (this._log.isLevelEnabled("verbose")) {
+				// Log synchronously before async dir-exists checks
+				pathMappings.forEach(([virBasePath, relFsPath]) => {
+					this._log.verbose(`    ${virBasePath} => ${relFsPath}`);
+				});
+			}
+			this._paths = await Promise.all(pathMappings.map(async ([virBasePath, relFsPath]) => {
+				if (!(await this._dirExists("/" + relFsPath))) {
+					throw new Error(
+						`Unable to find source directory '${relFsPath}' in module project ${this.getName()}`);
+				}
+				return {
+					name: `'${relFsPath}'' reader for module project ${this.getName()}`,
+					virBasePath,
+					fsBasePath: fsPath.join(this.getRootPath(), relFsPath)
+				};
+			}));
+		} else {
+			this._log.verbose(`    / => <project root>`);
+			if (!(await this._dirExists("/"))) {
+				throw new Error(
+					`Unable to find root directory of module project ${this.getName()}`);
+			}
+			this._paths = [{
+				name: `Root reader for module project ${this.getName()}`,
+				virBasePath: "/",
+				fsBasePath: this.getRootPath()
+			}];
+		}
+	}
+}
+
+export default Module;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_specifications_types_ThemeLibrary.js.html b/v3/api/project_lib_specifications_types_ThemeLibrary.js.html new file mode 100644 index 0000000000..aaf83903ff --- /dev/null +++ b/v3/api/project_lib_specifications_types_ThemeLibrary.js.html @@ -0,0 +1,266 @@ + + + + + + + project/lib/specifications/types/ThemeLibrary.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/specifications/types/ThemeLibrary.js

+ + + + + + + +
+
+
import Project from "../Project.js";
+import fsPath from "node:path";
+import * as resourceFactory from "@ui5/fs/resourceFactory";
+
+/**
+ * ThemeLibrary
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/specifications/types/ThemeLibrary
+ * @extends @ui5/project/specifications/Project
+ * @hideconstructor
+ */
+class ThemeLibrary extends Project {
+	constructor(parameters) {
+		super(parameters);
+
+		this._srcPath = "src";
+		this._testPath = "test";
+		this._testPathExists = false;
+		this._writer = null;
+	}
+
+	/* === Attributes === */
+	/**
+	* @private
+	*/
+	getCopyright() {
+		return this._config.metadata.copyright;
+	}
+
+	/**
+	 * Get the path of the project's source directory
+	 *
+	 * @public
+	 * @returns {string} Absolute path to the source directory of the project
+	 */
+	getSourcePath() {
+		return fsPath.join(this.getRootPath(), this._srcPath);
+	}
+
+	/* === Resource Access === */
+	/**
+	 * Get a [ReaderCollection]{@link @ui5/fs/ReaderCollection} for accessing all resources of the
+	 * project in the specified "style":
+	 *
+	 * <ul>
+	 * <li><b>buildtime:</b> Resource paths are always prefixed with <code>/resources/</code>
+	 *  or <code>/test-resources/</code> followed by the project's namespace.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>dist:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  Any configured build-excludes are applied</li>
+	 * <li><b>runtime:</b> Resource paths always match with what the UI5 runtime expects.
+	 *  This means that paths generally depend on the project type. Applications for example use a "flat"-like
+	 *  structure, while libraries use a "buildtime"-like structure.
+	 *  This style is typically used for serving resources directly. Therefore, build-excludes are not applied
+	 * <li><b>flat:</b> Resource paths are never prefixed and namespaces are omitted if possible. Note that
+	 *  project types like "theme-library", which can have multiple namespaces, can't omit them.
+	 *  Any configured build-excludes are applied</li>
+	 * </ul>
+	 *
+	 * If project resources have been changed through the means of a workspace, those changes
+	 * are reflected in the provided reader too.
+	 *
+	 * Resource readers always use POSIX-style paths.
+	 *
+	 * @public
+	 * @param {object} [options]
+	 * @param {string} [options.style=buildtime] Path style to access resources.
+	 *   Can be "buildtime", "dist", "runtime" or "flat"
+	 * @returns {@ui5/fs/ReaderCollection} A reader collection instance
+	 */
+	getReader({style = "buildtime"} = {}) {
+		// Apply builder excludes to all styles but "runtime"
+		const excludes = style === "runtime" ? [] : this.getBuilderResourcesExcludes();
+
+		let reader = resourceFactory.createReader({
+			fsBasePath: this.getSourcePath(),
+			virBasePath: "/resources/",
+			name: `Runtime resources reader for theme-library project ${this.getName()}`,
+			project: this,
+			excludes
+		});
+		if (this._testPathExists) {
+			const testReader = resourceFactory.createReader({
+				fsBasePath: fsPath.join(this.getRootPath(), this._testPath),
+				virBasePath: "/test-resources/",
+				name: `Runtime test-resources reader for theme-library project ${this.getName()}`,
+				project: this,
+				excludes
+			});
+			reader = resourceFactory.createReaderCollection({
+				name: `Reader collection for theme-library project ${this.getName()}`,
+				readers: [reader, testReader]
+			});
+		}
+		const writer = this._getWriter();
+
+		return resourceFactory.createReaderCollectionPrioritized({
+			name: `Reader/Writer collection for project ${this.getName()}`,
+			readers: [writer, reader]
+		});
+	}
+
+	/**
+	* Get a [DuplexCollection]{@link @ui5/fs/DuplexCollection} for accessing and modifying a
+	* project's resources.
+	*
+	* This is always of style <code>buildtime</code>, wich for theme libraries is identical to style
+	* <code>runtime</code>.
+	*
+	* @public
+	* @returns {@ui5/fs/DuplexCollection} DuplexCollection
+	*/
+	getWorkspace() {
+		const reader = this.getReader();
+
+		const writer = this._getWriter();
+		return resourceFactory.createWorkspace({
+			reader,
+			writer
+		});
+	}
+
+	_getWriter() {
+		if (!this._writer) {
+			this._writer = resourceFactory.createAdapter({
+				virBasePath: "/",
+				project: this
+			});
+		}
+
+		return this._writer;
+	}
+
+	/* === Internals === */
+	/**
+	 * @private
+	 * @param {object} config Configuration object
+	*/
+	async _configureAndValidatePaths(config) {
+		await super._configureAndValidatePaths(config);
+
+		if (config.resources && config.resources.configuration && config.resources.configuration.paths) {
+			if (config.resources.configuration.paths.src) {
+				this._srcPath = config.resources.configuration.paths.src;
+			}
+			if (config.resources.configuration.paths.test) {
+				this._testPath = config.resources.configuration.paths.test;
+			}
+		}
+
+		if (!(await this._dirExists("/" + this._srcPath))) {
+			throw new Error(
+				`Unable to find source directory '${this._srcPath}' in theme-library project ${this.getName()}`);
+		}
+		this._testPathExists = await this._dirExists("/" + this._testPath);
+
+		this._log.verbose(`Path mapping for theme-library project ${this.getName()}:`);
+		this._log.verbose(`  Physical root path: ${this.getRootPath()}`);
+		this._log.verbose(`  Mapped to:`);
+		this._log.verbose(`    /resources/ => ${this._srcPath}`);
+		this._log.verbose(
+			`    /test-resources/ => ${this._testPath}${this._testPathExists ? "" : " [does not exist]"}`);
+	}
+}
+
+export default ThemeLibrary;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_ui5Framework_AbstractResolver.js.html b/v3/api/project_lib_ui5Framework_AbstractResolver.js.html new file mode 100644 index 0000000000..cb3f76260d --- /dev/null +++ b/v3/api/project_lib_ui5Framework_AbstractResolver.js.html @@ -0,0 +1,374 @@ + + + + + + + project/lib/ui5Framework/AbstractResolver.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/ui5Framework/AbstractResolver.js

+ + + + + + + +
+
+
import path from "node:path";
+import os from "node:os";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("ui5Framework:AbstractResolver");
+import semver from "semver";
+
+// Matches Semantic Versioning 2.0.0 versions
+// https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
+//
+// This needs to be aligned with the ui5.yaml JSON schema:
+// lib/validation/schema/specVersion/kind/project.json#/definitions/framework/properties/version/pattern
+//
+// eslint-disable-next-line max-len
+const SEMVER_VERSION_REGEXP = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
+
+// Reduced Semantic Versioning pattern
+// Matches MAJOR.MINOR as a simple version range to be resolved to the latest patch
+const VERSION_RANGE_REGEXP = /^(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-SNAPSHOT)?$/;
+
+/**
+ * Abstract Resolver
+ *
+ * @abstract
+ * @public
+ * @class
+ * @alias @ui5/project/ui5Framework/AbstractResolver
+ * @hideconstructor
+ */
+class AbstractResolver {
+	/* eslint-disable max-len */
+	/**
+	 * @param {*} options options
+	 * @param {string} [options.version] Framework version to use. When omitted, all libraries need to be available
+	 * via <code>providedLibraryMetadata</code> parameter. Otherwise an error is thrown.
+	 * @param {boolean} [options.sources=false] Whether to install framework libraries as sources or
+	 * 					pre-built (with build manifest)
+	 * @param {string} [options.cwd=process.cwd()] Current working directory
+	 * @param {string} [options.ui5HomeDir="~/.ui5"] UI5 home directory location. This will be used to store packages,
+	 * metadata and configuration used by the resolvers. Relative to `process.cwd()`
+	 * @param {object.<string, @ui5/project/ui5Framework/AbstractResolver~LibraryMetadataEntry>} [options.providedLibraryMetadata]
+	 * Resolver skips installing listed libraries and uses the dependency information to resolve their dependencies.
+	 * <code>version</code> can be omitted in case all libraries can be resolved via the <code>providedLibraryMetadata</code>.
+	 * Otherwise an error is thrown.
+	 */
+	/* eslint-enable max-len */
+	constructor({cwd, version, sources, ui5HomeDir, providedLibraryMetadata}) {
+		if (new.target === AbstractResolver) {
+			throw new TypeError("Class 'AbstractResolver' is abstract");
+		}
+
+		// In some CI environments, the homedir might be set explicitly to a relative
+		// path (e.g. "./"), but tooling requires an absolute path
+		this._ui5HomeDir = path.resolve(
+			ui5HomeDir || path.join(os.homedir(), ".ui5")
+		);
+		this._cwd = cwd ? path.resolve(cwd) : process.cwd();
+		this._version = version;
+
+		// Environment variable should always enforce usage of sources
+		if (process.env.UI5_PROJECT_USE_FRAMEWORK_SOURCES) {
+			sources = true;
+		}
+		this._sources = !!sources;
+
+		this._providedLibraryMetadata = providedLibraryMetadata;
+	}
+
+	async _processLibrary(libraryName, libraryMetadata, errors) {
+		// Check if library is already processed
+		if (libraryMetadata[libraryName]) {
+			return;
+		}
+		// Mark library as handled
+		libraryMetadata[libraryName] = Object.create(null);
+
+		log.verbose("Processing " + libraryName);
+
+		let promises;
+		const providedLibraryMetadata = this._providedLibraryMetadata?.[libraryName];
+		if (providedLibraryMetadata) {
+			log.verbose(`Skipping install for ${libraryName} (provided)`);
+			promises = {
+				// Use existing metadata if library is provided from outside (e.g. workspace)
+				metadata: Promise.resolve(providedLibraryMetadata),
+				// Provided libraries are already "installed"
+				install: Promise.resolve({
+					pkgPath: providedLibraryMetadata.path
+				})
+			};
+		} else if (!this._version) {
+			throw new Error(`Unable to install library ${libraryName}. No framework version provided.`);
+		} else {
+			promises = await this.handleLibrary(libraryName);
+		}
+
+		const [metadata, {pkgPath}] = await Promise.all([
+			promises.metadata.then((metadata) =>
+				this._processDependencies(libraryName, metadata, libraryMetadata, errors)),
+			promises.install
+		]);
+
+		// Add path to installed package to metadata
+		metadata.path = pkgPath;
+
+		// Add metadata entry
+		libraryMetadata[libraryName] = metadata;
+	}
+
+	async _processDependencies(libraryName, metadata, libraryMetadata, errors) {
+		if (metadata.dependencies.length > 0) {
+			log.verbose("Processing dependencies of " + libraryName);
+			await this._processLibraries(metadata.dependencies, libraryMetadata, errors);
+			log.verbose("Done processing dependencies of " + libraryName);
+		}
+		return metadata;
+	}
+
+	async _processLibraries(libraryNames, libraryMetadata, errors) {
+		const sourceErrors = new Set();
+		const results = await Promise.all(libraryNames.map(async (libraryName) => {
+			try {
+				await this._processLibrary(libraryName, libraryMetadata, errors);
+			} catch (err) {
+				if (sourceErrors.has(err.message)) {
+					return `Failed to resolve library ${libraryName}: Error already logged`;
+				}
+				sourceErrors.add(err.message);
+				log.verbose(`Failed to process library ${libraryName}`);
+				log.verbose(`Error: ${err.message}`);
+				log.verbose(`Call stack: ${err.stack}`);
+				return `Failed to resolve library ${libraryName}: ${err.message}`;
+			}
+		}));
+		// Don't add empty results (success)
+		errors.push(...results.filter(($) => $));
+	}
+
+	/**
+	 * Library metadata entry
+	 *
+	 * @example
+	 * const libraryMetadataEntry = {
+	 *		"id": "@openui5/sap.ui.core",
+	 *		"version": "1.75.0",
+	 *		"path": "~/.ui5/framework/packages/@openui5/sap.ui.core/1.75.0",
+	 *		"dependencies": [],
+	 *		"optionalDependencies": []
+	 * };
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/ui5Framework/AbstractResolver~LibraryMetadataEntry
+	 * @property {string} id Identifier
+	 * @property {string} version Version
+	 * @property {string} path Path
+	 * @property {string[]} dependencies List of dependency ids
+	 * @property {string[]} optionalDependencies List of optional dependency ids
+	 */
+
+	/**
+	 * Install result
+	 *
+	 * @example
+	 * const resolverInstallResult = {
+	 * 	"libraryMetadata": {
+	 * 		"sap.ui.core": {
+	 * 			// ...
+	 * 		},
+	 * 		"sap.m": {
+	 * 			// ...
+	 * 		}
+	 * 	}
+	 * };
+	 *
+	 * @public
+	 * @typedef {object} @ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult
+	 * @property {object.<string, @ui5/project/ui5Framework/AbstractResolver~LibraryMetadataEntry>} libraryMetadata
+	 *   Object containing all installed libraries with library name as key
+	 */
+
+	/**
+	 * Installs the provided libraries and their dependencies
+	 *
+	 * @example
+	 * const resolver = new Sapui5Resolver({version: "1.76.0"});
+	 * // Or for OpenUI5:
+	 * // const resolver = new Openui5Resolver({version: "1.76.0"});
+	 *
+	 * resolver.install(["sap.ui.core", "sap.m"]).then(({libraryMetadata}) => {
+	 * 	// Installation done
+	 * }).catch((err) => {
+	 * 	// Handle installation errors
+	 * });
+	 *
+	 * @public
+	 * @param {string[]} libraryNames List of library names to be installed
+	 * @returns {@ui5/project/ui5Framework/AbstractResolver~ResolverInstallResult}
+	 *   Resolves with an object containing the <code>libraryMetadata</code>
+	 */
+	async install(libraryNames) {
+		const libraryMetadata = Object.create(null);
+		const errors = [];
+
+		await this._processLibraries(libraryNames, libraryMetadata, errors);
+
+		if (errors.length === 1) {
+			throw new Error(errors[0]);
+		} if (errors.length > 1) {
+			const msg = errors.map((err, idx) => `  ${idx + 1}. ${err}`).join("\n");
+			throw new Error(`Resolution of framework libraries failed with errors:\n${msg}`);
+		}
+
+		return {
+			libraryMetadata
+		};
+	}
+
+	static async resolveVersion(version, {ui5HomeDir, cwd} = {}) {
+		let spec;
+		const isSnapshotVersion = version.toLowerCase().endsWith("-snapshot");
+		if (version === "latest" || version === "latest-snapshot") {
+			// Use a wildcard to resolve to the latest available version
+			spec = "*";
+		} else if (SEMVER_VERSION_REGEXP.test(version)) {
+			// Fully qualified version, can be used directly
+			spec = version;
+		} else if (VERSION_RANGE_REGEXP.test(version)) {
+			if (isSnapshotVersion) {
+				// For snapshot version ranges we need to insert a stand-in "x" for the patch level
+				// in order to make the semver check work: "1.112-SNAPSHOT" becomes "1.112.x-SNAPSHOT"
+				spec = version.replace(/-SNAPSHOT$/, ".x-SNAPSHOT");
+			} else {
+				spec = version;
+			}
+		} else {
+			throw new Error(`Framework version specifier "${version}" is incorrect or not supported`);
+		}
+		const versions = await this.fetchAllVersions({ui5HomeDir, cwd});
+		const resolvedVersion = semver.maxSatisfying(versions, spec, {
+			includePrerelease: isSnapshotVersion
+		});
+		if (!resolvedVersion) {
+			if (semver.valid(spec)) {
+				if (this.name === "Sapui5Resolver" && semver.lt(spec, "1.76.0")) {
+					throw new Error(`Could not resolve framework version ${version}. ` +
+						`Note that SAPUI5 framework libraries can only be consumed by the UI5 Tooling ` +
+						`starting with SAPUI5 v1.76.0`);
+				} else if (this.name === "Openui5Resolver" && semver.lt(spec, "1.52.5")) {
+					throw new Error(`Could not resolve framework version ${version}. ` +
+						`Note that OpenUI5 framework libraries can only be consumed by the UI5 Tooling ` +
+						`starting with OpenUI5 v1.52.5`);
+				}
+			}
+			throw new Error(
+				`Could not resolve framework version ${version}. ` +
+				`Make sure the version is valid and available in the configured registry.`);
+		}
+		return resolvedVersion;
+	}
+
+	// To be implemented by resolver
+	async getLibraryMetadata(libraryName) {
+		throw new Error("AbstractResolver: getLibraryMetadata must be implemented!");
+	}
+	async handleLibrary(libraryName) {
+		throw new Error("AbstractResolver: handleLibrary must be implemented!");
+	}
+	static fetchAllVersions(options) {
+		throw new Error("AbstractResolver: static fetchAllVersions must be implemented!");
+	}
+}
+
+/* istanbul ignore else */
+if (process.env.NODE_ENV === "test") {
+	// Export pattern for testing to be checked against JSON schema pattern
+	AbstractResolver._SEMVER_VERSION_REGEXP = SEMVER_VERSION_REGEXP;
+}
+
+export default AbstractResolver;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_ui5Framework_Openui5Resolver.js.html b/v3/api/project_lib_ui5Framework_Openui5Resolver.js.html new file mode 100644 index 0000000000..6af1d3b4d5 --- /dev/null +++ b/v3/api/project_lib_ui5Framework_Openui5Resolver.js.html @@ -0,0 +1,194 @@ + + + + + + + project/lib/ui5Framework/Openui5Resolver.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/ui5Framework/Openui5Resolver.js

+ + + + + + + +
+
+
import path from "node:path";
+import os from "node:os";
+import AbstractResolver from "./AbstractResolver.js";
+import Installer from "./npm/Installer.js";
+
+const OPENUI5_CORE_PACKAGE = "@openui5/sap.ui.core";
+
+/**
+ * Resolver for the OpenUI5 framework
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/ui5Framework/Openui5Resolver
+ * @extends @ui5/project/ui5Framework/AbstractResolver
+ */
+class Openui5Resolver extends AbstractResolver {
+	/**
+	 * @param {*} options options
+	 * @param {string} options.version OpenUI5 version to use
+	 * @param {string} [options.cwd=process.cwd()] Working directory to resolve configurations like .npmrc
+	 * @param {string} [options.ui5HomeDir="~/.ui5"] UI5 home directory location. This will be used to store packages,
+	 * metadata and configuration used by the resolvers. Relative to `process.cwd()`
+	 * @param {string} [options.cacheDir] Where to store temp/cached packages.
+	 * @param {string} [options.packagesDir] Where to install packages
+	 * @param {string} [options.stagingDir] The staging directory for the packages
+	 */
+	constructor(options) {
+		super(options);
+
+		const {cacheDir, packagesDir, stagingDir} = options;
+
+		this._installer = new Installer({
+			cwd: this._cwd,
+			ui5HomeDir: this._ui5HomeDir,
+			cacheDir, packagesDir, stagingDir
+		});
+		this._loadLibraryMetadata = Object.create(null);
+	}
+	static _getNpmPackageName(libraryName) {
+		return "@openui5/" + libraryName;
+	}
+	static _getLibaryName(pkgName) {
+		return pkgName.replace(/^@openui5\//, "");
+	}
+	getLibraryMetadata(libraryName) {
+		if (!this._loadLibraryMetadata[libraryName]) {
+			this._loadLibraryMetadata[libraryName] = Promise.resolve().then(async () => {
+				// Trigger manifest request to gather transitive dependencies
+				const pkgName = Openui5Resolver._getNpmPackageName(libraryName);
+				const libraryManifest = await this._installer.fetchPackageManifest({pkgName, version: this._version});
+				let dependencies = [];
+				if (libraryManifest.dependencies) {
+					const depNames = Object.keys(libraryManifest.dependencies);
+					dependencies = depNames.map(Openui5Resolver._getLibaryName);
+				}
+
+				// npm devDependencies are handled as "optionalDependencies"
+				// in terms of the UI5 framework metadata structure
+				let optionalDependencies = [];
+				if (libraryManifest.devDependencies) {
+					const devDepNames = Object.keys(libraryManifest.devDependencies);
+					optionalDependencies = devDepNames.map(Openui5Resolver._getLibaryName);
+				}
+
+				return {
+					id: pkgName,
+					version: this._version,
+					dependencies,
+					optionalDependencies
+				};
+			});
+		}
+		return this._loadLibraryMetadata[libraryName];
+	}
+	async handleLibrary(libraryName) {
+		const pkgName = Openui5Resolver._getNpmPackageName(libraryName);
+		return {
+			// Trigger metadata request
+			metadata: this.getLibraryMetadata(libraryName),
+			// Also trigger installation of package
+			install: this._installer.installPackage({
+				pkgName,
+				version: this._version
+			})
+		};
+	}
+	static async fetchAllVersions({ui5HomeDir, cwd} = {}) {
+		const installer = new Installer({
+			cwd: cwd ? path.resolve(cwd) : process.cwd(),
+			ui5HomeDir:
+				ui5HomeDir ? path.resolve(ui5HomeDir) :
+					path.join(os.homedir(), ".ui5")
+		});
+		return await installer.fetchPackageVersions({pkgName: OPENUI5_CORE_PACKAGE});
+	}
+}
+
+export default Openui5Resolver;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_ui5Framework_Sapui5MavenSnapshotResolver.js.html b/v3/api/project_lib_ui5Framework_Sapui5MavenSnapshotResolver.js.html new file mode 100644 index 0000000000..a60ef4c5cc --- /dev/null +++ b/v3/api/project_lib_ui5Framework_Sapui5MavenSnapshotResolver.js.html @@ -0,0 +1,371 @@ + + + + + + + project/lib/ui5Framework/Sapui5MavenSnapshotResolver.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/ui5Framework/Sapui5MavenSnapshotResolver.js

+ + + + + + + +
+
+
import path from "node:path";
+import os from "node:os";
+import semver from "semver";
+import AbstractResolver from "./AbstractResolver.js";
+import Installer from "./maven/Installer.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("ui5Framework:Sapui5MavenSnapshotResolver");
+
+const DIST_PKG_NAME = "@sapui5/distribution-metadata";
+const DIST_GROUP_ID = "com.sap.ui5.dist";
+const DIST_ARTIFACT_ID = "sapui5-sdk-dist";
+
+/**
+ * Resolver for the SAPUI5 framework
+ *
+ * This Resolver downloads and installs SNAPSHOTS of UI5 libraries from
+ * a Maven repository. It's meant for internal usage only as no use cases
+ * outside of SAP are known.
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/ui5Framework/Sapui5MavenSnapshotResolver
+ * @extends @ui5/project/ui5Framework/AbstractResolver
+ */
+class Sapui5MavenSnapshotResolver extends AbstractResolver {
+	/**
+	 * @param {*} options options
+	 * @param {string} [options.snapshotEndpointUrl] Maven Repository Snapshot URL. Can by overruled
+	 *	by setting the <code>UI5_MAVEN_SNAPSHOT_ENDPOINT_URL</code> environment variable. If neither is provided,
+	 *	falling back to the standard Maven settings.xml file (if existing).
+	 * @param {string} options.version SAPUI5 version to use
+	 * @param {boolean} [options.sources=false] Whether to install framework libraries as sources or
+	 * pre-built (with build manifest)
+	 * @param {string} [options.cwd=process.cwd()] Current working directory
+	 * @param {string} [options.ui5HomeDir="~/.ui5"] UI5 home directory location. This will be used to store packages,
+	 * metadata and configuration used by the resolvers. Relative to `process.cwd()`
+	 * @param {module:@ui5/project/ui5Framework/maven/CacheMode} [options.cacheMode=Default]
+	 * Cache mode to use
+	 */
+	constructor(options) {
+		super(options);
+
+		const {
+			cacheMode,
+		} = options;
+
+		this._installer = new Installer({
+			ui5HomeDir: this._ui5HomeDir,
+			snapshotEndpointUrlCb:
+				Sapui5MavenSnapshotResolver._createSnapshotEndpointUrlCallback(options.snapshotEndpointUrl),
+			cacheMode,
+		});
+		this._loadDistMetadata = null;
+
+		// TODO 4.0: Remove support for legacy snapshot versions
+		this._isLegacySnapshotVersion = semver.lt(this._version, "1.116.0-SNAPSHOT", {
+			includePrerelease: true
+		});
+	}
+	loadDistMetadata() {
+		if (!this._loadDistMetadata) {
+			this._loadDistMetadata = Promise.resolve().then(async () => {
+				const version = this._version;
+				log.verbose(
+					`Installing ${DIST_ARTIFACT_ID} in version ${version}...`
+				);
+
+				const {pkgPath: distPkgPath} = await this._installer.installPackage({
+					pkgName: DIST_PKG_NAME,
+					groupId: DIST_GROUP_ID,
+					artifactId: DIST_ARTIFACT_ID,
+					version,
+					classifier: "npm-sources",
+					extension: "zip",
+				});
+
+				return await this._installer.readJson(
+					path.join(distPkgPath, "metadata.json")
+				);
+			});
+		}
+		return this._loadDistMetadata;
+	}
+	async getLibraryMetadata(libraryName) {
+		const distMetadata = await this.loadDistMetadata();
+		const metadata = distMetadata.libraries[libraryName];
+
+		if (!metadata) {
+			throw new Error(`Could not find library "${libraryName}"`);
+		}
+
+		return metadata;
+	}
+	async handleLibrary(libraryName) {
+		const metadata = await this.getLibraryMetadata(libraryName);
+		if (!metadata.gav) {
+			throw new Error(
+				"Metadata is missing GAV (group, artifact and version) " +
+					"information. This might indicate an unsupported SNAPSHOT version."
+			);
+		}
+		const gav = metadata.gav.split(":");
+		let pkgName = metadata.npmPackageName;
+
+		// Use "npm-dist" artifact by default
+		let classifier;
+		let extension;
+		if (this._sources) {
+			// Use npm-sources artifact if sources are requested
+			classifier = "npm-sources";
+			extension = "zip";
+		} else {
+			// Add "prebuilt" suffix to package name
+			pkgName += "-prebuilt";
+
+			if (this._isLegacySnapshotVersion) {
+				// For legacy versions < 1.116.0-SNAPSHOT where npm-dist artifact is not
+				// yet available, use "default" JAR
+				classifier = null;
+				extension = "jar";
+			} else {
+				// Use "npm-dist" artifact by default
+				classifier = "npm-dist";
+				extension = "zip";
+			}
+		}
+
+		return {
+			metadata: Promise.resolve({
+				id: pkgName,
+				version: metadata.version,
+				dependencies: metadata.dependencies,
+				optionalDependencies: metadata.optionalDependencies,
+			}),
+			// Trigger installation of package
+			install: this._installer.installPackage({
+				pkgName,
+				groupId: gav[0],
+				artifactId: gav[1],
+				version: metadata.version,
+				classifier,
+				extension,
+			}),
+		};
+	}
+
+	static async fetchAllVersions({ui5HomeDir, cwd, snapshotEndpointUrl} = {}) {
+		const installer = new Installer({
+			cwd: cwd ? path.resolve(cwd) : process.cwd(),
+			ui5HomeDir: path.resolve(
+				ui5HomeDir || path.join(os.homedir(), ".ui5")
+			),
+			snapshotEndpointUrlCb: Sapui5MavenSnapshotResolver._createSnapshotEndpointUrlCallback(snapshotEndpointUrl),
+		});
+		return await installer.fetchPackageVersions({
+			groupId: DIST_GROUP_ID,
+			artifactId: DIST_ARTIFACT_ID,
+		});
+	}
+
+	static _createSnapshotEndpointUrlCallback(snapshotEndpointUrl) {
+		snapshotEndpointUrl = process.env.UI5_MAVEN_SNAPSHOT_ENDPOINT_URL || snapshotEndpointUrl;
+
+		if (!snapshotEndpointUrl) {
+			// Here we return a function which returns a promise that resolves with the URL.
+			// If we would already start resolving the settings.xml at this point, we'd need to always ask the
+			// end user for confirmation whether the resolved URL should be used. In some cases where the resources
+			// are already cached, this is actually not necessary and could be skipped
+			return Sapui5MavenSnapshotResolver._resolveSnapshotEndpointUrl;
+		} else {
+			return () => Promise.resolve(snapshotEndpointUrl);
+		}
+	}
+
+	/**
+	 * Read the Maven repository snapshot endpoint URL from the central
+	 * UI5 Tooling configuration, with a fallback to central Maven configuration (is existing)
+	 *
+	 * @returns {Promise<string>} The resolved snapshotEndpointUrl
+	 */
+	static async _resolveSnapshotEndpointUrl() {
+		const {default: Configuration} = await import("../config/Configuration.js");
+		const config = await Configuration.fromFile();
+		let url = config.getMavenSnapshotEndpointUrl();
+		if (url) {
+			log.verbose(`Using UI5 Tooling configuration for mavenSnapshotEndpointUrl: ${url}`);
+		} else {
+			log.verbose(`No mavenSnapshotEndpointUrl configuration found`);
+			url = await Sapui5MavenSnapshotResolver._resolveSnapshotEndpointUrlFromMaven();
+			if (url) {
+				log.verbose(`Updating UI5 Tooling configuration with new mavenSnapshotEndpointUrl: ${url}`);
+				const configJson = config.toJson();
+				configJson.mavenSnapshotEndpointUrl = url;
+				await Configuration.toFile(new Configuration(configJson));
+			}
+		}
+		return url;
+	}
+
+	/**
+	 * Tries to detect whether ~/.m2/settings.xml exist, and if so, whether
+	 * the snapshot.build URL is extracted from there
+	 *
+	 * @param {string} [settingsXML=~/.m2/settings.xml] Path to the settings.xml.
+	 * 				If not provided, the default location is used
+	 * @returns {Promise<string>} The resolved snapshot.build URL from ~/.m2/settings.xml
+	 */
+	static async _resolveSnapshotEndpointUrlFromMaven(settingsXML) {
+		if (!process.stdout.isTTY) {
+			// We can't prompt the user if stdout is non-interactive (i.e. in CI environments)
+			// Therefore skip resolution from Maven settings.xml altogether
+			return null;
+		}
+
+		settingsXML =
+			settingsXML || path.resolve(path.join(os.homedir(), ".m2", "settings.xml"));
+
+		const {default: fs} = await import("graceful-fs");
+		const {promisify} = await import("node:util");
+		const readFile = promisify(fs.readFile);
+		const xml2js = await import("xml2js");
+		const parser = new xml2js.Parser({
+			preserveChildrenOrder: true,
+			xmlns: true,
+		});
+		let url;
+
+		log.verbose(`Attempting to resolve snapshot endpoint URL from Maven configuration file at ${settingsXML}...`);
+		try {
+			const fileContent = await readFile(settingsXML);
+			const xmlContents = await parser.parseStringPromise(fileContent);
+
+			const snapshotBuildChunk = xmlContents?.settings?.profiles[0]?.profile.filter(
+				(prof) => prof.id[0]._ === "snapshot.build"
+			)[0];
+
+			url =
+				snapshotBuildChunk?.repositories?.[0]?.repository?.[0]?.url?.[0]?._ ||
+				snapshotBuildChunk?.pluginRepositories?.[0]?.pluginRepository?.[0]?.url?.[0]?._;
+
+			if (!url) {
+				log.verbose(`"snapshot.build" attribute could not be found in ${settingsXML}`);
+				return null;
+			}
+		} catch (err) {
+			if (err.code === "ENOENT") {
+				// "File or directory does not exist"
+				log.verbose(`File does not exist: ${settingsXML}`);
+			} else {
+				log.warning(`Failed to read Maven configuration file from ${settingsXML}: ${err.message}`);
+			}
+			return null;
+		}
+
+		const {default: yesno} = await import("yesno");
+		const ok = await yesno({
+			question:
+				"\nA Maven repository endpoint URL is required for consuming snapshot versions of UI5 libraries.\n" +
+				"You can configure one using the command: 'ui5 config set mavenSnapshotEndpointUrl <url>'\n\n" +
+				`The following URL has been found in a Maven configuration file at ${settingsXML}:\n${url}\n\n` +
+				`Continue with this endpoint URL and remember it for the future? (yes)`,
+			defaultValue: true,
+		});
+
+		if (ok) {
+			log.verbose(`Using Maven snapshot endpoint URL resolved from Maven configuration file: ${url}`);
+			return url;
+		} else {
+			log.verbose(`User rejected usage of the resolved URL`);
+			return null;
+		}
+	}
+}
+
+export default Sapui5MavenSnapshotResolver;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_ui5Framework_Sapui5Resolver.js.html b/v3/api/project_lib_ui5Framework_Sapui5Resolver.js.html new file mode 100644 index 0000000000..3236f2b6dd --- /dev/null +++ b/v3/api/project_lib_ui5Framework_Sapui5Resolver.js.html @@ -0,0 +1,215 @@ + + + + + + + project/lib/ui5Framework/Sapui5Resolver.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/ui5Framework/Sapui5Resolver.js

+ + + + + + + +
+
+
import path from "node:path";
+import os from "node:os";
+import semver from "semver";
+import AbstractResolver from "./AbstractResolver.js";
+import Installer from "./npm/Installer.js";
+import {getLogger} from "@ui5/logger";
+const log = getLogger("ui5Framework:Sapui5Resolver");
+
+const DIST_PKG_NAME = "@sapui5/distribution-metadata";
+
+/**
+ * Resolver for the SAPUI5 framework
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/ui5Framework/Sapui5Resolver
+ * @extends @ui5/project/ui5Framework/AbstractResolver
+ */
+class Sapui5Resolver extends AbstractResolver {
+	/**
+	 * @param {*} options options
+	 * @param {string} options.version SAPUI5 version to use
+	 * @param {string} [options.cwd=process.cwd()] Working directory to resolve configurations like .npmrc
+	 * @param {string} [options.ui5HomeDir="~/.ui5"] UI5 home directory location. This will be used to store packages,
+	 * metadata and configuration used by the resolvers. Relative to `process.cwd()`
+	 * @param {string} [options.cacheDir] Where to store temp/cached packages.
+	 * @param {string} [options.packagesDir] Where to install packages
+	 * @param {string} [options.stagingDir] The staging directory for packages
+	 */
+	constructor(options) {
+		super(options);
+
+		const {cacheDir, packagesDir, stagingDir} = options;
+
+		this._installer = new Installer({
+			cwd: this._cwd,
+			ui5HomeDir: this._ui5HomeDir,
+			cacheDir, packagesDir, stagingDir
+		});
+		this._loadDistMetadata = null;
+	}
+	loadDistMetadata() {
+		if (!this._loadDistMetadata) {
+			this._loadDistMetadata = Promise.resolve().then(async () => {
+				const version = this._version;
+				log.verbose(`Installing ${DIST_PKG_NAME} in version ${version}...`);
+				const pkgName = DIST_PKG_NAME;
+				const {pkgPath} = await this._installer.installPackage({
+					pkgName,
+					version
+				});
+
+				const metadata = await this._installer.readJson(path.join(pkgPath, "metadata.json"));
+				return metadata;
+			});
+		}
+		return this._loadDistMetadata;
+	}
+	async getLibraryMetadata(libraryName) {
+		const distMetadata = await this.loadDistMetadata();
+		const metadata = distMetadata.libraries[libraryName];
+
+		if (!metadata) {
+			throw new Error(`Could not find library "${libraryName}"`);
+		}
+
+		if (metadata.npmPackageName.startsWith("@openui5/") &&
+				semver.satisfies(this._version, "1.77.x")) {
+			// TODO: Remove this workaround once SAPUI5 1.77.x isn't used anymore.
+			//       As of Dec 2022 there are still ~80 downloads per week (npmjs.com stats).
+			// 1.77.x (at least 1.77.0-1.77.2) distribution metadata.json is missing
+			//	dependency information for all OpenUI5 libraries.
+			// Therefore we need to request those from the registry like it is done
+			//	for OpenUI5 projects.
+			const {default: Openui5Resolver} = await import("./Openui5Resolver.js");
+			const openui5Resolver = new Openui5Resolver({
+				cwd: this._cwd,
+				version: metadata.version
+			});
+			const openui5Metadata = await openui5Resolver.getLibraryMetadata(libraryName);
+			return {
+				npmPackageName: openui5Metadata.id,
+				version: openui5Metadata.version,
+				dependencies: openui5Metadata.dependencies,
+				optionalDependencies: openui5Metadata.optionalDependencies
+			};
+		}
+
+		return metadata;
+	}
+	async handleLibrary(libraryName) {
+		const metadata = await this.getLibraryMetadata(libraryName);
+
+		return {
+			metadata: Promise.resolve({
+				id: metadata.npmPackageName,
+				version: metadata.version,
+				dependencies: metadata.dependencies,
+				optionalDependencies: metadata.optionalDependencies
+			}),
+			// Trigger installation of package
+			install: this._installer.installPackage({
+				pkgName: metadata.npmPackageName,
+				version: metadata.version
+			})
+		};
+	}
+	static async fetchAllVersions({ui5HomeDir, cwd} = {}) {
+		const installer = new Installer({
+			cwd: cwd ? path.resolve(cwd) : process.cwd(),
+			ui5HomeDir:
+				ui5HomeDir ? path.resolve(ui5HomeDir) :
+					path.join(os.homedir(), ".ui5")
+		});
+		return await installer.fetchPackageVersions({pkgName: DIST_PKG_NAME});
+	}
+}
+
+export default Sapui5Resolver;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_ui5Framework_maven_CacheMode.js.html b/v3/api/project_lib_ui5Framework_maven_CacheMode.js.html new file mode 100644 index 0000000000..06c48e2146 --- /dev/null +++ b/v3/api/project_lib_ui5Framework_maven_CacheMode.js.html @@ -0,0 +1,114 @@ + + + + + + + project/lib/ui5Framework/maven/CacheMode.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/ui5Framework/maven/CacheMode.js

+ + + + + + + +
+
+

+
+/**
+ * Cache modes for maven consumption
+ *
+ * @public
+ * @readonly
+ * @enum {string}
+ * @property {string} Default Cache everything, invalidate after 9 hours
+ * @property {string} Force Use cache only. Do not send any requests to the repository
+ * @property {string} Off Invalidate the cache and update from the repository
+ * @module @ui5/project/ui5Framework/maven/CacheMode
+ */
+export default {
+	Default: "Default",
+	Force: "Force",
+	Off: "Off"
+};
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_validation_ValidationError.js.html b/v3/api/project_lib_validation_ValidationError.js.html new file mode 100644 index 0000000000..82859e4391 --- /dev/null +++ b/v3/api/project_lib_validation_ValidationError.js.html @@ -0,0 +1,379 @@ + + + + + + + project/lib/validation/ValidationError.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/validation/ValidationError.js

+ + + + + + + +
+
+
import chalk from "chalk";
+import escapeStringRegExp from "escape-string-regexp";
+
+/**
+ * Error class for validation of project configuration.
+ *
+ * @public
+ * @class
+ * @alias @ui5/project/validation/ValidationError
+ * @extends Error
+ * @hideconstructor
+ */
+class ValidationError extends Error {
+	constructor({errors, project, yaml}) {
+		super();
+
+		/**
+		 * ValidationError
+		 *
+		 * @constant
+		 * @default
+		 * @type {string}
+		 * @readonly
+		 * @public
+		 */
+		this.name = "ValidationError";
+
+		this.project = project;
+		this.yaml = yaml;
+
+		this.errors = ValidationError.filterErrors(errors);
+
+		/**
+		 * Formatted error message
+		 *
+		 * @type {string}
+		 * @readonly
+		 * @public
+		 */
+		this.message = this.formatErrors();
+
+		Error.captureStackTrace(this, this.constructor);
+	}
+
+	formatErrors() {
+		let separator = "\n\n";
+		if (process.stdout.isTTY) {
+			// Add a horizontal separator line between errors in case a terminal is used
+			separator += chalk.grey.dim("\u2500".repeat(process.stdout.columns || 80));
+		}
+		separator += "\n\n";
+		let message;
+
+		if (this.project) { // ui5-workspace.yaml is project independent, so in that case, no project is available
+			message = chalk.red(`Invalid ui5.yaml configuration for project ${this.project.id}`) + "\n\n";
+		} else {
+			message = chalk.red(`Invalid workspace configuration.`) + "\n\n";
+		}
+
+		message += this.errors.map((error) => {
+			return this.formatError(error);
+		}).join(separator);
+		return message;
+	}
+
+	formatError(error) {
+		let errorMessage = ValidationError.formatMessage(error);
+		if (this.yaml && this.yaml.path && this.yaml.source) {
+			const yamlExtract = ValidationError.getYamlExtract({error, yaml: this.yaml});
+			const errorLines = errorMessage.split("\n");
+			errorLines.splice(1, 0, "\n" + yamlExtract);
+			errorMessage = errorLines.join("\n");
+		}
+		return errorMessage;
+	}
+
+	static formatMessage(error) {
+		if (error.keyword === "errorMessage") {
+			return error.message;
+		}
+
+		let message = "Configuration ";
+		if (error.dataPath) {
+			message += chalk.underline(chalk.red(error.dataPath.substr(1))) + " ";
+		}
+
+		switch (error.keyword) {
+		case "additionalProperties":
+			message += `property ${error.params.additionalProperty} must not be provided here`;
+			break;
+		case "type":
+			message += `must be of type '${error.params.type}'`;
+			break;
+		case "required":
+			message += `must have required property '${error.params.missingProperty}'`;
+			break;
+		case "enum":
+			message += "must be equal to one of the allowed values\n";
+			message += "Allowed values: " + error.params.allowedValues.join(", ");
+			break;
+		default:
+			message += error.message;
+		}
+
+		return message;
+	}
+
+	static _findDuplicateError(error, errorIndex, errors) {
+		const foundIndex = errors.findIndex(($) => {
+			if ($.dataPath !== error.dataPath) {
+				return false;
+			} else if ($.keyword !== error.keyword) {
+				return false;
+			} else if (JSON.stringify($.params) !== JSON.stringify(error.params)) {
+				return false;
+			} else {
+				return true;
+			}
+		});
+		return foundIndex !== errorIndex;
+	}
+
+	static filterErrors(allErrors) {
+		return allErrors.filter((error, i, errors) => {
+			if (error.keyword === "if" || error.keyword === "oneOf") {
+				return false;
+			}
+
+			return !ValidationError._findDuplicateError(error, i, errors);
+		});
+	}
+
+	static analyzeYamlError({error, yaml}) {
+		if (error.dataPath === "" && error.keyword === "required") {
+			// There is no line/column for a missing required property on root level
+			return {line: -1, column: -1};
+		}
+
+		// Skip leading /
+		const objectPath = error.dataPath.substr(1).split("/");
+
+		if (error.keyword === "additionalProperties") {
+			objectPath.push(error.params.additionalProperty);
+		}
+
+		let currentSubstring;
+		let currentIndex;
+		if (yaml.documentIndex) {
+			const matchDocumentSeparator = /^---/gm;
+			let currentDocumentIndex = 0;
+			let document;
+			while ((document = matchDocumentSeparator.exec(yaml.source)) !== null) {
+				// If the first separator is not at the beginning of the file
+				// we are already at document index 1
+				// Using String#trim() to remove any whitespace characters
+				if (currentDocumentIndex === 0 && yaml.source.substring(0, document.index).trim().length > 0) {
+					currentDocumentIndex = 1;
+				}
+
+				if (currentDocumentIndex === yaml.documentIndex) {
+					currentIndex = document.index;
+					currentSubstring = yaml.source.substring(currentIndex);
+					break;
+				}
+
+				currentDocumentIndex++;
+			}
+			// Document could not be found
+			if (!currentSubstring) {
+				return {line: -1, column: -1};
+			}
+		} else {
+			// In case of index 0 or no index, use whole source
+			currentIndex = 0;
+			currentSubstring = yaml.source;
+		}
+
+		const matchArrayElementIndentation = /([ ]*)-/;
+
+		for (let i = 0; i < objectPath.length; i++) {
+			const property = objectPath[i];
+			let newIndex;
+
+			if (isNaN(property)) {
+				// Try to find a property
+
+				// Creating a regular expression that matches the property name a line
+				// except for comments, indicated by a hash sign "#".
+				const propertyRegExp = new RegExp(`^[^#]*?${escapeStringRegExp(property)}`, "m");
+
+				const propertyMatch = propertyRegExp.exec(currentSubstring);
+				if (!propertyMatch) {
+					return {line: -1, column: -1};
+				}
+				newIndex = propertyMatch.index + propertyMatch[0].length;
+			} else {
+				// Try to find the right index within an array definition.
+				// This currently only works for arrays defined with "-" in multiple lines.
+				// Arrays using square brackets are not supported.
+
+				const matchArrayElement = /(^|\r?\n)([ ]*-[^\r\n]*)/g;
+				const arrayIndex = parseInt(property);
+				let a = 0;
+				let firstIndentation = -1;
+				let match;
+				while ((match = matchArrayElement.exec(currentSubstring)) !== null) {
+					const indentationMatch = match[2].match(matchArrayElementIndentation);
+					if (!indentationMatch) {
+						return {line: -1, column: -1};
+					}
+					const currentIndentation = indentationMatch[1].length;
+					if (firstIndentation === -1) {
+						firstIndentation = currentIndentation;
+					} else if (currentIndentation !== firstIndentation) {
+						continue;
+					}
+					if (a === arrayIndex) {
+						// match[1] might be a line-break
+						newIndex = match.index + match[1].length + currentIndentation;
+						break;
+					}
+					a++;
+				}
+				if (!newIndex) {
+					// Could not find array element
+					return {line: -1, column: -1};
+				}
+			}
+			currentIndex += newIndex;
+			currentSubstring = yaml.source.substring(currentIndex);
+		}
+
+		const linesUntilMatch = yaml.source.substring(0, currentIndex).split(/\r?\n/);
+		const line = linesUntilMatch.length;
+		let column = linesUntilMatch[line - 1].length + 1;
+		const lastPathSegment = objectPath[objectPath.length - 1];
+		if (isNaN(lastPathSegment)) {
+			column -= lastPathSegment.length;
+		}
+
+		return {
+			line,
+			column
+		};
+	}
+
+	static getSourceExtract(yamlSource, line, column) {
+		let source = "";
+		const lines = yamlSource.split(/\r?\n/);
+
+		// Using line numbers instead of array indices
+		const startLine = Math.max(line - 2, 1);
+		const endLine = Math.min(line, lines.length);
+		const padLength = String(endLine).length;
+
+		for (let currentLine = startLine; currentLine <= endLine; currentLine++) {
+			const currentLineContent = lines[currentLine - 1];
+			let string = chalk.gray(
+				String(currentLine).padStart(padLength, " ") + ":"
+			) + " " + currentLineContent + "\n";
+			if (currentLine === line) {
+				string = chalk.bgRed(string);
+			}
+			source += string;
+		}
+
+		source += " ".repeat(column + padLength + 1) + chalk.red("^");
+
+		return source;
+	}
+
+	static getYamlExtract({error, yaml}) {
+		const {line, column} = ValidationError.analyzeYamlError({error, yaml});
+		if (line !== -1 && column !== -1) {
+			return chalk.grey(yaml.path + ":" + line) +
+				"\n\n" + ValidationError.getSourceExtract(yaml.source, line, column);
+		} else {
+			return chalk.grey(yaml.path) + "\n";
+		}
+	}
+}
+
+export default ValidationError;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/project_lib_validation_validator.js.html b/v3/api/project_lib_validation_validator.js.html new file mode 100644 index 0000000000..da26ba4acc --- /dev/null +++ b/v3/api/project_lib_validation_validator.js.html @@ -0,0 +1,241 @@ + + + + + + + project/lib/validation/validator.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

project/lib/validation/validator.js

+ + + + + + + +
+
+
import {fileURLToPath} from "node:url";
+import {readFile} from "node:fs/promises";
+
+/**
+ * @module @ui5/project/validation/validator
+ * @description A collection of validation related APIs
+ * @public
+ */
+
+/**
+ * @enum {string}
+ * @private
+ * @readonly
+ */
+export const SCHEMA_VARIANTS = {
+	"ui5": "ui5.json",
+	"ui5-workspace": "ui5-workspace.json"
+};
+
+class Validator {
+	constructor({Ajv, ajvErrors, schemaName}) {
+		if (!schemaName || !SCHEMA_VARIANTS[schemaName]) {
+			throw new Error(
+				`"schemaName" is missing or incorrect. The available schemaName variants are ${Object.keys(
+					SCHEMA_VARIANTS
+				).join(", ")}`
+			);
+		}
+
+		this._schemaName = SCHEMA_VARIANTS[schemaName];
+
+		this.ajv = new Ajv({
+			allErrors: true,
+			jsonPointers: true,
+			loadSchema: Validator.loadSchema
+		});
+		ajvErrors(this.ajv);
+	}
+
+	_compileSchema() {
+		const schemaName = this._schemaName;
+
+		if (!this._compiling) {
+			this._compiling = Promise.resolve().then(async () => {
+				const schema = await Validator.loadSchema(schemaName);
+				const validate = await this.ajv.compileAsync(schema);
+				return validate;
+			});
+		}
+		return this._compiling;
+	}
+
+	async validate({config, project, yaml}) {
+		const fnValidate = await this._compileSchema();
+		const valid = fnValidate(config);
+		if (!valid) {
+			// Read errors/schema from fnValidate before lazy loading ValidationError module.
+			// Otherwise they might be cleared already.
+			const {errors, schema} = fnValidate;
+			const {default: ValidationError} = await import("./ValidationError.js");
+			throw new ValidationError({
+				errors,
+				schema,
+				project,
+				yaml
+			});
+		}
+	}
+
+	static async loadSchema(schemaPath) {
+		const filePath = schemaPath.replace("http://ui5.sap/schema/", "");
+		const schemaFile = await readFile(
+			fileURLToPath(new URL(`./schema/${filePath}`, import.meta.url)), {encoding: "utf8"}
+		);
+		return JSON.parse(schemaFile);
+	}
+}
+
+const validator = Object.create(null);
+
+async function _validate(schemaName, options) {
+	if (!validator[schemaName]) {
+		validator[schemaName] = (async () => {
+			const {default: Ajv} = await import("ajv");
+			const {default: ajvErrors} = await import("ajv-errors");
+			return new Validator({Ajv, ajvErrors, schemaName});
+		})();
+	}
+
+	const schemaValidator = await validator[schemaName];
+	await schemaValidator.validate(options);
+}
+
+/**
+ * Validates the given ui5 configuration.
+ *
+ * @public
+ * @function
+ * @static
+ * @param {object} options
+ * @param {object} options.config UI5 Configuration to validate
+ * @param {object} options.project Project information
+ * @param {string} options.project.id ID of the project
+ * @param {object} [options.yaml] YAML information
+ * @param {string} options.yaml.path Path of the YAML file
+ * @param {string} options.yaml.source Content of the YAML file
+ * @param {number} [options.yaml.documentIndex=0] Document index in case the YAML file contains multiple documents
+ * @throws {@ui5/project/validation/ValidationError}
+ *   Rejects with a {@link @ui5/project/validation/ValidationError ValidationError}
+ *   when the validation fails.
+ * @returns {Promise<undefined>} Returns a Promise that resolves when the validation succeeds
+ */
+export async function validate(options) {
+	await _validate("ui5", options);
+}
+
+/**
+ * Validates the given ui5-workspace configuration.
+ *
+ * @public
+ * @function
+ * @static
+ * @param {object} options
+ * @param {object} options.config ui5-workspace Configuration to validate
+ * @param {object} [options.yaml] YAML information
+ * @param {string} options.yaml.path Path of the YAML file
+ * @param {string} options.yaml.source Content of the YAML file
+ * @param {number} [options.yaml.documentIndex=0] Document index in case the YAML file contains multiple documents
+ * @throws {@ui5/project/validation/ValidationError}
+ *   Rejects with a {@link @ui5/project/validation/ValidationError ValidationError}
+ *   when the validation fails.
+ * @returns {Promise<undefined>} Returns a Promise that resolves when the validation succeeds
+ */
+export async function validateWorkspace(options) {
+	await _validate("ui5-workspace", options);
+}
+
+export {
+	/**
+	 * For testing only!
+	 *
+	 * @private
+	 */
+	Validator as _Validator
+};
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/scripts/collapse.js b/v3/api/scripts/collapse.js new file mode 100644 index 0000000000..4e63926d41 --- /dev/null +++ b/v3/api/scripts/collapse.js @@ -0,0 +1,39 @@ +function hideAllButCurrent(){ + //by default all submenut items are hidden + //but we need to rehide them for search + document.querySelectorAll("nav > ul").forEach(function(parent) { + if (parent.className.indexOf("collapse_top") !== -1) { + parent.style.display = "none"; + } + }); + document.querySelectorAll("nav > ul > li > ul li").forEach(function(parent) { + parent.style.display = "none"; + }); + document.querySelectorAll("nav > h3").forEach(function(section) { + if (section.className.indexOf("collapsed_header") !== -1) { + section.addEventListener("click", function(){ + if (section.nextSibling.style.display === "none") { + section.nextSibling.style.display = "block"; + } else { + section.nextSibling.style.display = "none"; + } + }); + } + }); + + //only current page (if it exists) should be opened + var file = window.location.pathname.split("/").pop().replace(/\.html/, ''); + document.querySelectorAll("nav > ul > li > a").forEach(function(parent) { + var href = parent.attributes.href.value.replace(/\.html/, ''); + if (file === href) { + if (parent.parentNode.parentNode.className.indexOf("collapse_top") !== -1) { + parent.parentNode.parentNode.style.display = "block"; + } + parent.parentNode.querySelectorAll("ul li").forEach(function(elem) { + elem.style.display = "block"; + }); + } + }); +} + +hideAllButCurrent(); \ No newline at end of file diff --git a/v3/api/scripts/commonNav.js b/v3/api/scripts/commonNav.js new file mode 100644 index 0000000000..03e8202821 --- /dev/null +++ b/v3/api/scripts/commonNav.js @@ -0,0 +1,28 @@ +if (typeof fetch === 'function') { + const init = () => { + if (typeof scrollToNavItem !== 'function') return false + scrollToNavItem() + // hideAllButCurrent not always loaded + if (typeof hideAllButCurrent === 'function') hideAllButCurrent() + return true + } + fetch('./nav.inc.html') + .then(response => response.ok ? response.text() : `${response.url} => ${response.status} ${response.statusText}`) + .then(body => { + document.querySelector('nav').innerHTML += body + // nav.js should be quicker to load than nav.inc.html, a fallback just in case + return init() + }) + .then(done => { + if (done) return + let i = 0 + ;(function waitUntilNavJs () { + if (init()) return + if (i++ < 100) return setTimeout(waitUntilNavJs, 300) + console.error(Error('nav.js not loaded after 30s waiting for it')) + })() + }) + .catch(error => console.error(error)) +} else { + console.error(Error('Browser too old to display commonNav (remove commonNav docdash option)')) +} diff --git a/v3/api/scripts/linenumber.js b/v3/api/scripts/linenumber.js new file mode 100644 index 0000000000..8d52f7eafd --- /dev/null +++ b/v3/api/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(function() { + var source = document.getElementsByClassName('prettyprint source linenums'); + var i = 0; + var lineNumber = 0; + var lineId; + var lines; + var totalLines; + var anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = 'line' + lineNumber; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/v3/api/scripts/nav.js b/v3/api/scripts/nav.js new file mode 100644 index 0000000000..6dd8313429 --- /dev/null +++ b/v3/api/scripts/nav.js @@ -0,0 +1,12 @@ +function scrollToNavItem() { + var path = window.location.href.split('/').pop().replace(/\.html/, ''); + document.querySelectorAll('nav a').forEach(function(link) { + var href = link.attributes.href.value.replace(/\.html/, ''); + if (path === href) { + link.scrollIntoView({block: 'center'}); + return; + } + }) + } + + scrollToNavItem(); diff --git a/v3/api/scripts/polyfill.js b/v3/api/scripts/polyfill.js new file mode 100644 index 0000000000..44b4c92dcd --- /dev/null +++ b/v3/api/scripts/polyfill.js @@ -0,0 +1,4 @@ +//IE Fix, src: https://www.reddit.com/r/programminghorror/comments/6abmcr/nodelist_lacks_foreach_in_internet_explorer/ +if (typeof(NodeList.prototype.forEach)!==typeof(alert)){ + NodeList.prototype.forEach=Array.prototype.forEach; +} \ No newline at end of file diff --git a/v3/api/scripts/prettify/Apache-License-2.0.txt b/v3/api/scripts/prettify/Apache-License-2.0.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/v3/api/scripts/prettify/Apache-License-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/v3/api/scripts/prettify/lang-css.js b/v3/api/scripts/prettify/lang-css.js new file mode 100644 index 0000000000..041e1f5906 --- /dev/null +++ b/v3/api/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/v3/api/scripts/prettify/prettify.js b/v3/api/scripts/prettify/prettify.js new file mode 100644 index 0000000000..eef5ad7e6a --- /dev/null +++ b/v3/api/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p ul > li:not(.level-hide)").forEach(function(elem) { + elem.style.display = "block"; + }); + + if (typeof hideAllButCurrent === "function"){ + //let's do what ever collapse wants to do + hideAllButCurrent(); + } else { + //menu by default should be opened + document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { + elem.style.display = "block"; + }); + } + } else { + //we are searching + document.documentElement.setAttribute(searchAttr, ''); + + //show all parents + document.querySelectorAll("nav > ul > li").forEach(function(elem) { + elem.style.display = "block"; + }); + document.querySelectorAll("nav > ul").forEach(function(elem) { + elem.style.display = "block"; + }); + //hide all results + document.querySelectorAll("nav > ul > li > ul li").forEach(function(elem) { + elem.style.display = "none"; + }); + //show results matching filter + document.querySelectorAll("nav > ul > li > ul a").forEach(function(elem) { + if (!contains(elem.parentNode, search)) { + return; + } + elem.parentNode.style.display = "block"; + }); + //hide parents without children + document.querySelectorAll("nav > ul > li").forEach(function(parent) { + var countSearchA = 0; + parent.querySelectorAll("a").forEach(function(elem) { + if (contains(elem, search)) { + countSearchA++; + } + }); + + var countUl = 0; + var countUlVisible = 0; + parent.querySelectorAll("ul").forEach(function(ulP) { + // count all elements that match the search + if (contains(ulP, search)) { + countUl++; + } + + // count all visible elements + var children = ulP.children + for (i=0; i ul.collapse_top").forEach(function(parent) { + var countVisible = 0; + parent.querySelectorAll("li").forEach(function(elem) { + if (elem.style.display !== "none") { + countVisible++; + } + }); + + if (countVisible == 0) { + //has no child at all and does not contain text + parent.style.display = "none"; + } + }); + } +}); \ No newline at end of file diff --git a/v3/api/server_lib_middleware_MiddlewareUtil.js.html b/v3/api/server_lib_middleware_MiddlewareUtil.js.html new file mode 100644 index 0000000000..83ff27f009 --- /dev/null +++ b/v3/api/server_lib_middleware_MiddlewareUtil.js.html @@ -0,0 +1,369 @@ + + + + + + + server/lib/middleware/MiddlewareUtil.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

server/lib/middleware/MiddlewareUtil.js

+ + + + + + + +
+
+
import parseurl from "parseurl";
+import mime from "mime-types";
+import {
+	createReaderCollection,
+	createReaderCollectionPrioritized,
+	createResource,
+	createFilterReader,
+	createLinkReader,
+	createFlatReader
+} from "@ui5/fs/resourceFactory";
+
+/**
+ * Convenience functions for UI5 Server middleware.
+ * An instance of this class is passed to every standard UI5 Server middleware.
+ * Custom middleware that define a specification version >= 2.0 will also receive an instance
+ * of this class as part of the parameters of their create-middleware function.
+ *
+ * The set of functions that can be accessed by a custom middleware depends on the specification
+ * version defined for the extension.
+ *
+ * @public
+ * @class
+ * @alias @ui5/server/middleware/MiddlewareUtil
+ * @hideconstructor
+ */
+class MiddlewareUtil {
+	/**
+	 *
+	 * @param {object} parameters
+	 * @param {@ui5/project/graph/ProjectGraph} parameters.graph Relevant ProjectGraph
+	 * @param {@ui5/project/specifications/Project} parameters.project Project that is being served
+	 * @public
+	 */
+	constructor({graph, project}) {
+		if (!graph) {
+			throw new Error(`Missing parameter "graph"`);
+		}
+		if (!project) {
+			throw new Error(`Missing parameter "project"`);
+		}
+		this._graph = graph;
+		this._project = project;
+	}
+
+	/**
+	 * Returns the [pathname]{@link https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname}
+	 * of a given request. Any escape sequences will be decoded.
+	 * </br></br>
+	 * This method is only available to custom middleware extensions defining
+	 * <b>Specification Version 2.0 and above</b>.
+	 *
+	 * @param {object} req Request object
+	 * @returns {string} [Pathname]{@link https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname}
+	 * of the given request
+	 * @public
+	 */
+	getPathname(req) {
+		let {pathname} = parseurl(req);
+		pathname = decodeURIComponent(pathname);
+		return pathname;
+	}
+
+	/**
+	 * MIME Info
+	 *
+	 * @example
+	 * const mimeInfo = {
+	 * 	"type": "text/html",
+	 * 	"charset": "utf-8",
+	 * 	"contentType": "text/html; charset=utf-8"
+	 * };
+	 *
+	 * @public
+	 * @typedef {object} MimeInfo
+	 * @property {string} type Detected content-type for the given resource path
+	 * @property {string} charset Default charset for the detected content-type
+	 * @property {string} contentType Calculated content-type header value
+	 * @memberof @ui5/server/middleware/MiddlewareUtil
+	 */
+	/**
+	 * Returns MIME information derived from a given resource path.
+	 * </br></br>
+	 * This method is only available to custom middleware extensions defining
+	 * <b>Specification Version 2.0 and above</b>.
+	 *
+	 * @param {object} resourcePath
+	 * @returns {@ui5/server/middleware/MiddlewareUtil.MimeInfo}
+	 * @public
+	 */
+	getMimeInfo(resourcePath) {
+		const type = mime.lookup(resourcePath) || "application/octet-stream";
+		const charset = mime.charset(type);
+		return {
+			type,
+			charset,
+			contentType: type + (charset ? "; charset=" + charset : "")
+		};
+	}
+	/**
+	 * Specification Version-dependent [Project]{@link @ui5/project/specifications/Project} interface.
+	 * For details on individual functions, see [Project]{@link @ui5/project/specifications/Project}
+	 *
+	 * @public
+	 * @typedef {object} @ui5/server/middleware/MiddlewareUtil~ProjectInterface
+	 * @property {Function} getType Get the project type
+	 * @property {Function} getName Get the project name
+	 * @property {Function} getVersion Get the project version
+	 * @property {Function} getNamespace Get the project namespace
+	 * @property {Function} getRootReader Get the project rootReader
+	 * @property {Function} getReader Get the project reader, defaulting to "runtime" style instead of "buildtime"
+	 * @property {Function} getRootPath Get the local File System path of the project's root directory
+	 * @property {Function} getSourcePath Get the local File System path of the project's source directory
+	 * @property {Function} getCustomConfiguration Get the project Custom Configuration
+	 * @property {Function} isFrameworkProject Check whether the project is a UI5-Framework project
+	 * @property {Function} getFrameworkName Get the project's framework name configuration
+	 * @property {Function} getFrameworkVersion Get the project's framework version configuration
+	 * @property {Function} getFrameworkDependencies Get the project's framework dependencies configuration
+	 */
+
+	/**
+	 * Retrieve a single project from the dependency graph
+	 *
+	 * </br></br>
+	 * This method is only available to custom server middleware extensions defining
+	 * <b>Specification Version 3.0 and above</b>.
+	 *
+	 * @param {string|@ui5/fs/Resource} [projectNameOrResource]
+	 * Name of the project to retrieve or a Resource instance to retrieve the associated project for.
+	 * Defaults to the name of the current root project
+	 * @returns {@ui5/server/middleware/MiddlewareUtil~ProjectInterface|undefined}
+	 * Specification Version-dependent interface to the Project instance or <code>undefined</code>
+	 * if the project name is unknown or the provided resource is not associated with any project.
+	 * @public
+	 */
+	getProject(projectNameOrResource) {
+		if (projectNameOrResource) {
+			if (typeof projectNameOrResource === "string" || projectNameOrResource instanceof String) {
+				// A project name has been provided
+				return this._graph.getProject(projectNameOrResource);
+			} else {
+				// A Resource instance has been provided
+				return projectNameOrResource.getProject();
+			}
+		}
+		// No parameter has been provided, default to the root project
+		return this._project;
+	}
+
+	/**
+	 * Retrieve a list of direct dependencies of a given project from the dependency graph.
+	 * Note that this list does not include transitive dependencies.
+	 *
+	 * </br></br>
+	 * This method is only available to custom server middleware extensions defining
+	 * <b>Specification Version 3.0 and above</b>.
+	 *
+	 * @param {string} [projectName] Name of the project to retrieve.
+	 * Defaults to the name of the current root project
+	 * @returns {string[]} Names of all direct dependencies
+	 * @throws {Error} If the requested project is unknown to the graph
+	 * @public
+	 */
+	getDependencies(projectName) {
+		return this._graph.getDependencies(projectName || this._project.getName());
+	}
+
+	/**
+	 * Specification Version-dependent set of [@ui5/fs/resourceFactory]{@link @ui5/fs/resourceFactory}
+	 * functions provided to middleware.
+	 * For details on individual functions, see [@ui5/fs/resourceFactory]{@link @ui5/fs/resourceFactory}
+	 *
+	 * @public
+	 * @typedef {object} @ui5/server/middleware/MiddlewareUtil~resourceFactory
+	 * @property {Function} createResource Creates a [Resource]{@link @ui5/fs/Resource}.
+	 * 	Accepts the same parameters as the [Resource]{@link @ui5/fs/Resource} constructor.
+	 * @property {Function} createReaderCollection Creates a reader collection:
+	 *	[ReaderCollection]{@link @ui5/fs/ReaderCollection}
+	 * @property {Function} createReaderCollectionPrioritized Creates a prioritized reader collection:
+	 *	[ReaderCollectionPrioritized]{@link @ui5/fs/ReaderCollectionPrioritized}
+	 * @property {Function} createFilterReader
+	 * 	Create a [Filter-Reader]{@link @ui5/fs/readers/Filter} with the given reader.
+	 * @property {Function} createLinkReader
+	 * 	Create a [Link-Reader]{@link @ui5/fs/readers/Filter} with the given reader.
+	 * @property {Function} createFlatReader Create a [Link-Reader]{@link @ui5/fs/readers/Link}
+	 * where all requests are prefixed with <code>/resources/<namespace></code>.
+	 */
+
+	/**
+	 * Provides limited access to [@ui5/fs/resourceFactory]{@link @ui5/fs/resourceFactory} functions
+	 *
+	 * </br></br>
+	 * This attribute is only available to custom server middleware extensions defining
+	 * <b>Specification Version 3.0 and above</b>.
+	 *
+	 * @type {@ui5/server/middleware/MiddlewareUtil~resourceFactory}
+	 * @public
+	 */
+	resourceFactory = {
+		createResource,
+		createReaderCollection,
+		createReaderCollectionPrioritized,
+		createFilterReader,
+		createLinkReader,
+		createFlatReader,
+	};
+
+	/**
+	 * Get an interface to an instance of this class that only provides those functions
+	 * that are supported by the given custom middleware extension specification version.
+	 *
+	 * @param {@ui5/project/specifications/SpecificationVersion} specVersion
+	 * SpecVersionComparator instance of the custom server middleware
+	 * @returns {object} An object with bound instance methods supported by the given specification version
+	 */
+	getInterface(specVersion) {
+		if (specVersion.lt("2.0")) {
+			// Custom middleware defining specVersion <2.0 does not have access to any MiddlewareUtil API
+			return undefined;
+		}
+
+		const baseInterface = {};
+		bindFunctions(this, baseInterface, [
+			"getPathname", "getMimeInfo"
+		]);
+
+		if (specVersion.gte("3.0")) {
+			// getProject function, returning an interfaced project instance
+			baseInterface.getProject = (projectName) => {
+				const project = this.getProject(projectName);
+				const baseProjectInterface = {};
+				bindFunctions(project, baseProjectInterface, [
+					"getType", "getName", "getVersion", "getNamespace",
+					"getRootReader", "getRootPath", "getSourcePath",
+					"getCustomConfiguration", "isFrameworkProject", "getFrameworkName",
+					"getFrameworkVersion", "getFrameworkDependencies"
+				]);
+				// Project#getReader defaults to style "buildtime". However ui5-server uses
+				// style "runtime". The main difference is that for some project types (like applications)
+				// the /resources/<namespace> path prefix is omitted for "runtime". Also, no builder resource-
+				// exclude configuration is applied.
+				// Therefore default to style "runtime" here so that custom middleware will commonly work with
+				// the same paths as ui5-server and no unexpected builder-excludes.
+				baseProjectInterface.getReader = function(options = {style: "runtime"}) {
+					return project.getReader(options);
+				};
+				return baseProjectInterface;
+			};
+			// getDependencies function, returning an array of project names
+			baseInterface.getDependencies = (projectName) => {
+				return this.getDependencies(projectName);
+			};
+
+			baseInterface.resourceFactory = Object.create(null);
+			[
+				// Once new functions get added, extract this array into a variable
+				// and enhance based on spec version once new functions get added
+				"createResource", "createReaderCollection", "createReaderCollectionPrioritized",
+				"createFilterReader", "createLinkReader", "createFlatReader",
+			].forEach((factoryFunction) => {
+				baseInterface.resourceFactory[factoryFunction] = this.resourceFactory[factoryFunction];
+			});
+		}
+		return baseInterface;
+	}
+}
+
+function bindFunctions(sourceObject, targetObject, funcNames) {
+	funcNames.forEach((funcName) => {
+		targetObject[funcName] = sourceObject[funcName].bind(sourceObject);
+	});
+}
+
+export default MiddlewareUtil;
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/server_lib_server.js.html b/v3/api/server_lib_server.js.html new file mode 100644 index 0000000000..55b64109ff --- /dev/null +++ b/v3/api/server_lib_server.js.html @@ -0,0 +1,289 @@ + + + + + + + server/lib/server.js - UI5 Tooling - API Reference + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

server/lib/server.js

+ + + + + + + +
+
+
import express from "express";
+import portscanner from "portscanner";
+import MiddlewareManager from "./middleware/MiddlewareManager.js";
+import {createReaderCollection} from "@ui5/fs/resourceFactory";
+import ReaderCollectionPrioritized from "@ui5/fs/ReaderCollectionPrioritized";
+
+/**
+ * @public
+ * @module @ui5/server
+ */
+
+/**
+ * Returns a promise resolving by starting the server.
+ *
+ * @param {object} app The express application object
+ * @param {number} port Desired port to listen to
+ * @param {boolean} changePortIfInUse If true and the port is already in use, an unused port is searched
+ * @param {boolean} acceptRemoteConnections If true, listens to remote connections and not only to localhost connections
+ * @returns {Promise<object>} Returns an object containing server related information like (selected port, protocol)
+ * @private
+ */
+function _listen(app, port, changePortIfInUse, acceptRemoteConnections) {
+	return new Promise(function(resolve, reject) {
+		const options = {};
+
+		if (!acceptRemoteConnections) {
+			options.host = "localhost";
+		}
+
+		const host = options.host || "127.0.0.1";
+		let portMax;
+		if (changePortIfInUse) {
+			portMax = port + 30;
+		} else {
+			portMax = port;
+		}
+
+		portscanner.findAPortNotInUse(port, portMax, host, function(error, foundPort) {
+			if (error) {
+				reject(error);
+				return;
+			}
+
+			if (!foundPort) {
+				if (changePortIfInUse) {
+					const error = new Error(
+						`EADDRINUSE: Could not find available ports between ${port} and ${portMax}.`);
+					error.code = "EADDRINUSE";
+					error.errno = "EADDRINUSE";
+					error.address = host;
+					error.port = portMax;
+					reject(error);
+					return;
+				} else {
+					const error = new Error(`EADDRINUSE: Port ${port} is already in use.`);
+					error.code = "EADDRINUSE";
+					error.errno = "EADDRINUSE";
+					error.address = host;
+					error.port = portMax;
+					reject(error);
+					return;
+				}
+			}
+
+			options.port = foundPort;
+			const server = app.listen(options, function() {
+				resolve({port: options.port, server});
+			});
+
+			server.on("error", function(err) {
+				reject(err);
+			});
+		});
+	});
+}
+
+/**
+ * Adds SSL support to an express application.
+ *
+ * @param {object} parameters
+ * @param {object} parameters.app The original express application
+ * @param {string} parameters.key Path to private key to be used for https
+ * @param {string} parameters.cert Path to certificate to be used for for https
+ * @returns {Promise<object>} The express application with SSL support
+ * @private
+ */
+async function _addSsl({app, key, cert}) {
+	// Using spdy as http2 server as the native http2 implementation
+	// from Node v8.4.0 doesn't seem to work with express
+	const {default: spdy} = await import("spdy");
+	return spdy.createServer({cert, key}, app);
+}
+
+
+/**
+ * SAP target CSP middleware options
+ *
+ * @public
+ * @typedef {object} module:@ui5/server.SAPTargetCSPOptions
+ * @property {string} [defaultPolicy="sap-target-level-1"]
+ * @property {string} [defaultPolicyIsReportOnly=true]
+ * @property {string} [defaultPolicy2="sap-target-level-3"]
+ * @property {string} [defaultPolicy2IsReportOnly=true]
+ * @property {string[]} [ignorePaths=["test-resources/sap/ui/qunit/testrunner.html"]]
+ */
+
+
+/**
+ * Start a server for the given project (sub-)tree.
+ *
+ * @public
+ * @param {@ui5/project/graph/ProjectGraph} graph Project graph
+ * @param {object} options Options
+ * @param {number} options.port Port to listen to
+ * @param {boolean} [options.changePortIfInUse=false] If true, change the port if it is already in use
+ * @param {boolean} [options.h2=false] Whether HTTP/2 should be used - defaults to <code>http</code>
+ * @param {string} [options.key] Path to private key to be used for https
+ * @param {string} [options.cert] Path to certificate to be used for for https
+ * @param {boolean} [options.simpleIndex=false] Use a simplified view for the server directory listing
+ * @param {boolean} [options.acceptRemoteConnections=false] If true, listens to remote connections and
+ * 															not only to localhost connections
+ * @param {boolean|module:@ui5/server.SAPTargetCSPOptions} [options.sendSAPTargetCSP=false]
+ * 										If set to <code>true</code> or an object, then the default (or configured)
+ * 										set of security policies that SAP and UI5 aim for (AKA 'target policies'),
+ * 										are send for any requested <code>*.html</code> file
+ * @param {boolean} [options.serveCSPReports=false] Enable CSP reports serving for request url
+ * 										'/.ui5/csp/csp-reports.json'
+ * @returns {Promise<object>} Promise resolving once the server is listening.
+ * 							It resolves with an object containing the <code>port</code>,
+ * 							<code>h2</code>-flag and a <code>close</code> function,
+ * 							which can be used to stop the server.
+ */
+export async function serve(graph, {
+	port: requestedPort, changePortIfInUse = false, h2 = false, key, cert,
+	acceptRemoteConnections = false, sendSAPTargetCSP = false, simpleIndex = false, serveCSPReports = false
+}) {
+	const rootProject = graph.getRoot();
+
+	const readers = [];
+	await graph.traverseBreadthFirst(async function({project: dep}) {
+		if (dep.getName() === rootProject.getName()) {
+			// Ignore root project
+			return;
+		}
+		readers.push(dep.getReader({style: "runtime"}));
+	});
+
+	const dependencies = createReaderCollection({
+		name: `Dependency reader collection for project ${rootProject.getName()}`,
+		readers
+	});
+
+	const rootReader = rootProject.getReader({style: "runtime"});
+
+	// TODO change to ReaderCollection once duplicates are sorted out
+	const combo = new ReaderCollectionPrioritized({
+		name: "server - prioritize workspace over dependencies",
+		readers: [rootReader, dependencies]
+	});
+	const resources = {
+		rootProject: rootReader,
+		dependencies: dependencies,
+		all: combo
+	};
+
+	const middlewareManager = new MiddlewareManager({
+		graph,
+		rootProject,
+		resources,
+		options: {
+			sendSAPTargetCSP,
+			serveCSPReports,
+			simpleIndex
+		}
+	});
+
+	let app = express();
+	await middlewareManager.applyMiddleware(app);
+
+	if (h2) {
+		app = await _addSsl({app, key, cert});
+	}
+
+	const {port, server} = await _listen(app, requestedPort, changePortIfInUse, acceptRemoteConnections);
+
+	return {
+		h2,
+		port,
+		close: function(callback) {
+			server.close(callback);
+		}
+	};
+}
+
+
+
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + diff --git a/v3/api/styles/jsdoc.css b/v3/api/styles/jsdoc.css new file mode 100644 index 0000000000..0fe6d3cdab --- /dev/null +++ b/v3/api/styles/jsdoc.css @@ -0,0 +1,776 @@ +* { + box-sizing: border-box +} + +html, body { + height: 100%; + width: 100%; +} + +body { + color: #4d4e53; + background-color: white; + margin: 0 auto; + padding: 0 20px; + font-family: 'Helvetica Neue', Helvetica, sans-serif; + font-size: 16px; +} + +img { + max-width: 100%; +} + +a, +a:active { + color: #606; + text-decoration: none; +} + +a:hover { + text-decoration: none; +} + +article a { + border-bottom: 1px solid #ddd; +} + +article a:hover, article a:active { + border-bottom-color: #222; +} + +article .description a { + word-break: break-word; +} + +p, ul, ol, blockquote { + margin-bottom: 1em; + line-height: 160%; +} + +h1, h2, h3, h4, h5, h6 { + font-family: 'Montserrat', sans-serif; +} + +h1, h2, h3, h4, h5, h6 { + color: #000; + font-weight: 400; + margin: 0; +} + +h1 { + font-weight: 300; + font-size: 48px; + margin: 1em 0 .5em; +} + +h1.page-title { + font-size: 48px; + margin: 1em 30px; + line-height: 100%; + word-wrap: break-word; +} + +h2 { + font-size: 24px; + margin: 1.5em 0 .3em; +} + +h3 { + font-size: 24px; + margin: 1.2em 0 .3em; +} + +h4 { + font-size: 18px; + margin: 1em 0 .2em; + color: #4d4e53; +} + +h4.name { + color: #fff; + background: #6d426d; + box-shadow: 0 .25em .5em #d3d3d3; + border-top: 1px solid #d3d3d3; + border-bottom: 1px solid #d3d3d3; + margin: 1.5em 0 0.5em; + padding: .75em 0 .75em 10px; +} + +h4.name a { + color: #fc83ff; +} + +h4.name a:hover { + border-bottom-color: #fc83ff; +} + +h5, .container-overview .subsection-title { + font-size: 120%; + letter-spacing: -0.01em; + margin: 8px 0 3px 0; +} + +h6 { + font-size: 100%; + letter-spacing: -0.01em; + margin: 6px 0 3px 0; + font-style: italic; +} + +.usertext h1 { + font-family: "Source Sans Pro"; + font-size: 24px; + margin: 2.5em 0 1em; + font-weight: 400; +} + +.usertext h2 { + font-family: "Source Sans Pro"; + font-size: 18px; + margin: 2em 0 0.5em; + font-weight: 400; + +} + +.usertext h3 { + font-family: "Source Sans Pro"; + font-size: 15px; + margin: 1.5em 0 0; + font-weight: 400; +} + +.usertext h4 { + font-family: "Source Sans Pro"; + font-size: 14px; + margin: 0 0 0; + font-weight: 400; +} + +.usertext h5 { + font-size: 12px; + margin: 1em 0 0; + font-weight: normal; + color: #666; +} + +.usertext h6 { + font-size: 11px; + margin: 1em 0 0; + font-weight: normal; + font-style: normal; + color: #666; +} + + +tt, code, kbd, samp, pre { + font-family: Consolas, Monaco, 'Andale Mono', monospace; + background: #f4f4f4; +} + +tt, code, kbd, samp{ + padding: 1px 5px; +} + +pre { + padding-bottom: 1em; +} + +.class-description { + font-size: 130%; + line-height: 140%; + margin-bottom: 1em; + margin-top: 1em; +} + +.class-description:empty { + margin: 0 +} + +#main { + float: right; + width: calc(100% - 240px); +} + +header { + display: block +} + +section { + display: block; + background-color: #fff; + padding: 0 0 0 30px; +} + +.variation { + display: none +} + +.signature-attributes { + font-size: 60%; + color: #eee; + font-style: italic; + font-weight: lighter; +} + +nav { + float: left; + display: block; + width: 250px; + background: #fff; + overflow: auto; + position: fixed; + height: 100%; +} + +nav #nav-search{ + width: 210px; + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; + margin-right: 20px; + margin-top: 20px; +} + +nav.wrap a{ + word-wrap: break-word; +} + +nav h3 { + margin-top: 12px; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 700; + line-height: 24px; + margin: 15px 0 10px; + padding: 0; + color: #000; +} + +nav h3.collapsed_header { + cursor: pointer; +} + +nav ul { + font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif; + font-size: 100%; + line-height: 17px; + padding: 0; + margin: 0; + list-style-type: none; +} + +nav ul a, +nav ul a:active { + font-family: 'Montserrat', sans-serif; + line-height: 18px; + padding: 0; + display: block; + font-size: 12px; +} + +nav a:hover, +nav a:active { + color: #606; +} + +nav > ul { + padding: 0 10px; +} + +nav > ul > li > a { + color: #606; + margin-top: 10px; +} + +nav ul ul a { + color: hsl(207, 1%, 60%); + border-left: 1px solid hsl(207, 10%, 86%); +} + +nav ul ul a, +nav ul ul a:active { + padding-left: 20px +} + +nav h2 { + font-size: 13px; + margin: 10px 0 0 0; + padding: 0; +} + +nav > h2 > a { + margin: 10px 0 -10px; + color: #606 !important; +} + +footer { + color: hsl(0, 0%, 28%); + margin-left: 250px; + display: block; + padding: 15px; + font-style: italic; + font-size: 90%; +} + +.ancestors { + color: #999 +} + +.ancestors a { + color: #999 !important; +} + +.clear { + clear: both +} + +.important { + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px +} + +.type-signature { + color: #CA79CA +} + +.type-signature:last-child { + color: #eee; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.signature { + color: #fc83ff; +} + +.details { + margin-top: 6px; + border-left: 2px solid #DDD; + line-height: 20px; + font-size: 14px; +} + +.details dt { + width: auto; + float: left; + padding-left: 10px; +} + +.details dd { + margin-left: 70px; + margin-top: 6px; + margin-bottom: 6px; +} + +.details ul { + margin: 0 +} + +.details ul { + list-style-type: none +} + +.details pre.prettyprint { + margin: 0 +} + +.details .object-value { + padding-top: 0 +} + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption { + font-style: italic; + font-size: 107%; + margin: 0; +} + +.prettyprint { + font-size: 14px; + overflow: auto; +} + +.prettyprint.source { + width: inherit; + line-height: 18px; + display: block; + background-color: #0d152a; + color: #aeaeae; +} + +.prettyprint code { + line-height: 18px; + display: block; + background-color: #0d152a; + color: #4D4E53; +} + +.prettyprint > code { + padding: 15px; +} + +.prettyprint .linenums code { + padding: 0 15px +} + +.prettyprint .linenums li:first-of-type code { + padding-top: 15px +} + +.prettyprint code span.line { + display: inline-block +} + +.prettyprint.linenums { + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol { + padding-left: 0 +} + +.prettyprint.linenums li { + border-left: 3px #34446B solid; +} + +.prettyprint.linenums li.selected, .prettyprint.linenums li.selected * { + background-color: #34446B; +} + +.prettyprint.linenums li * { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.prettyprint.linenums li code:empty:after { + content:""; + display:inline-block; + width:0px; +} + +table { + border-spacing: 0; + border: 1px solid #ddd; + border-collapse: collapse; + border-radius: 3px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + width: 100%; + font-size: 14px; + margin: 1em 0; +} + +td, th { + margin: 0px; + text-align: left; + vertical-align: top; + padding: 10px; + display: table-cell; +} + +thead tr, thead tr { + background-color: #fff; + font-weight: bold; + border-bottom: 1px solid #ddd; +} + +.params .type { + white-space: nowrap; +} + +.params code { + white-space: pre; +} + +.params td, .params .name, .props .name, .name code { + color: #4D4E53; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 100%; +} + +.params td { + border-top: 1px solid #eee +} + +.params td.description > p:first-child, .props td.description > p:first-child { + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, .props td.description > p:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +span.param-type, .params td .param-type, .param-type dd { + color: #606; + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.param-type dt, .param-type dd { + display: inline-block +} + +.param-type { + margin: 14px 0; +} + +.disabled { + color: #454545 +} + +/* navicon button */ +.navicon-button { + display: none; + position: relative; + padding: 2.0625rem 1.5rem; + transition: 0.25s; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + opacity: .8; +} +.navicon-button .navicon:before, .navicon-button .navicon:after { + transition: 0.25s; +} +.navicon-button:hover { + transition: 0.5s; + opacity: 1; +} +.navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after { + transition: 0.25s; +} +.navicon-button:hover .navicon:before { + top: .825rem; +} +.navicon-button:hover .navicon:after { + top: -.825rem; +} + +/* navicon */ +.navicon { + position: relative; + width: 2.5em; + height: .3125rem; + background: #000; + transition: 0.3s; + border-radius: 2.5rem; +} +.navicon:before, .navicon:after { + display: block; + content: ""; + height: .3125rem; + width: 2.5rem; + background: #000; + position: absolute; + z-index: -1; + transition: 0.3s 0.25s; + border-radius: 1rem; +} +.navicon:before { + top: .625rem; +} +.navicon:after { + top: -.625rem; +} + +/* open */ +.nav-trigger:checked + label:not(.steps) .navicon:before, +.nav-trigger:checked + label:not(.steps) .navicon:after { + top: 0 !important; +} + +.nav-trigger:checked + label .navicon:before, +.nav-trigger:checked + label .navicon:after { + transition: 0.5s; +} + +/* Minus */ +.nav-trigger:checked + label { + -webkit-transform: scale(0.75); + transform: scale(0.75); +} + +/* × and + */ +.nav-trigger:checked + label.plus .navicon, +.nav-trigger:checked + label.x .navicon { + background: transparent; +} + +.nav-trigger:checked + label.plus .navicon:before, +.nav-trigger:checked + label.x .navicon:before { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + background: #FFF; +} + +.nav-trigger:checked + label.plus .navicon:after, +.nav-trigger:checked + label.x .navicon:after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + background: #FFF; +} + +.nav-trigger:checked + label.plus { + -webkit-transform: scale(0.75) rotate(45deg); + transform: scale(0.75) rotate(45deg); +} + +.nav-trigger:checked ~ nav { + left: 0 !important; +} + +.nav-trigger:checked ~ .overlay { + display: block; +} + +.nav-trigger { + position: fixed; + top: 0; + clip: rect(0, 0, 0, 0); +} + +.overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + background: hsla(0, 0%, 0%, 0.5); + z-index: 1; +} + +/* nav level */ +.level-hide { + display: none; +} +html[data-search-mode] .level-hide { + display: block; +} + + +@media only screen and (max-width: 680px) { + body { + overflow-x: hidden; + } + + nav { + background: #FFF; + width: 250px; + height: 100%; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: -250px; + z-index: 3; + padding: 0 10px; + transition: left 0.2s; + } + + .navicon-button { + display: inline-block; + position: fixed; + top: 1.5em; + right: 0; + z-index: 2; + } + + #main { + width: 100%; + } + + #main h1.page-title { + margin: 1em 0; + } + + #main section { + padding: 0; + } + + footer { + margin-left: 0; + } +} + +/** Add a '#' to static members */ +[data-type="member"] a::before { + content: '#'; + display: inline-block; + margin-left: -14px; + margin-right: 5px; +} + +#disqus_thread{ + margin-left: 30px; +} + +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 400; + src: url('../fonts/Montserrat/Montserrat-Regular.eot'); /* IE9 Compat Modes */ + src: url('../fonts/Montserrat/Montserrat-Regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/Montserrat/Montserrat-Regular.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Regular.woff') format('woff'), /* Pretty Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Regular.ttf') format('truetype'); /* Safari, Android, iOS */ +} + +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 700; + src: url('../fonts/Montserrat/Montserrat-Bold.eot'); /* IE9 Compat Modes */ + src: url('../fonts/Montserrat/Montserrat-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('../fonts/Montserrat/Montserrat-Bold.woff2') format('woff2'), /* Super Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Bold.woff') format('woff'), /* Pretty Modern Browsers */ + url('../fonts/Montserrat/Montserrat-Bold.ttf') format('truetype'); /* Safari, Android, iOS */ +} + +@font-face { + font-family: 'Source Sans Pro'; + src: url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot'); + src: url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2') format('woff2'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff') format('woff'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf') format('truetype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg#source_sans_proregular') format('svg'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Source Sans Pro'; + src: url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot'); + src: url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot?#iefix') format('embedded-opentype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2') format('woff2'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff') format('woff'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf') format('truetype'), + url('../fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg#source_sans_prolight') format('svg'); + font-weight: 300; + font-style: normal; + +} diff --git a/v3/api/styles/prettify.css b/v3/api/styles/prettify.css new file mode 100644 index 0000000000..6f4d2eea99 --- /dev/null +++ b/v3/api/styles/prettify.css @@ -0,0 +1,80 @@ +.pln { + color: #ddd; +} + +/* string content */ +.str { + color: #61ce3c; +} + +/* a keyword */ +.kwd { + color: #fbde2d; +} + +/* a comment */ +.com { + color: #aeaeae; +} + +/* a type name */ +.typ { + color: #8da6ce; +} + +/* a literal value */ +.lit { + color: #fbde2d; +} + +/* punctuation */ +.pun { + color: #ddd; +} + +/* lisp open bracket */ +.opn { + color: #000000; +} + +/* lisp close bracket */ +.clo { + color: #000000; +} + +/* a markup tag name */ +.tag { + color: #8da6ce; +} + +/* a markup attribute name */ +.atn { + color: #fbde2d; +} + +/* a markup attribute value */ +.atv { + color: #ddd; +} + +/* a declaration */ +.dec { + color: #EF5050; +} + +/* a variable name */ +.var { + color: #c82829; +} + +/* a function name */ +.fun { + color: #4271ae; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; + padding-bottom: 2px; +}