project/lib/ui5Framework/Sapui5Resolver.js

  1. import path from "node:path";
  2. import os from "node:os";
  3. import semver from "semver";
  4. import AbstractResolver from "./AbstractResolver.js";
  5. import Installer from "./npm/Installer.js";
  6. import {getLogger} from "@ui5/logger";
  7. const log = getLogger("ui5Framework:Sapui5Resolver");
  8. const DIST_PKG_NAME = "@sapui5/distribution-metadata";
  9. /**
  10. * Resolver for the SAPUI5 framework
  11. *
  12. * @public
  13. * @class
  14. * @alias @ui5/project/ui5Framework/Sapui5Resolver
  15. * @extends @ui5/project/ui5Framework/AbstractResolver
  16. */
  17. class Sapui5Resolver extends AbstractResolver {
  18. /**
  19. * @param {*} options options
  20. * @param {string} options.version SAPUI5 version to use
  21. * @param {string} [options.cwd=process.cwd()] Working directory to resolve configurations like .npmrc
  22. * @param {string} [options.ui5HomeDir="~/.ui5"] UI5 home directory location. This will be used to store packages,
  23. * metadata and configuration used by the resolvers. Relative to `process.cwd()`
  24. * @param {string} [options.cacheDir] Where to store temp/cached packages.
  25. * @param {string} [options.packagesDir] Where to install packages
  26. * @param {string} [options.stagingDir] The staging directory for packages
  27. */
  28. constructor(options) {
  29. super(options);
  30. const {cacheDir, packagesDir, stagingDir} = options;
  31. this._installer = new Installer({
  32. cwd: this._cwd,
  33. ui5HomeDir: this._ui5HomeDir,
  34. cacheDir, packagesDir, stagingDir
  35. });
  36. this._loadDistMetadata = null;
  37. }
  38. loadDistMetadata() {
  39. if (!this._loadDistMetadata) {
  40. this._loadDistMetadata = Promise.resolve().then(async () => {
  41. const version = this._version;
  42. log.verbose(`Installing ${DIST_PKG_NAME} in version ${version}...`);
  43. const pkgName = DIST_PKG_NAME;
  44. const {pkgPath} = await this._installer.installPackage({
  45. pkgName,
  46. version
  47. });
  48. const metadata = await this._installer.readJson(path.join(pkgPath, "metadata.json"));
  49. return metadata;
  50. });
  51. }
  52. return this._loadDistMetadata;
  53. }
  54. async getLibraryMetadata(libraryName) {
  55. const distMetadata = await this.loadDistMetadata();
  56. const metadata = distMetadata.libraries[libraryName];
  57. if (!metadata) {
  58. throw new Error(`Could not find library "${libraryName}"`);
  59. }
  60. if (metadata.npmPackageName.startsWith("@openui5/") &&
  61. semver.satisfies(this._version, "1.77.x")) {
  62. // TODO: Remove this workaround once SAPUI5 1.77.x isn't used anymore.
  63. // As of Dec 2022 there are still ~80 downloads per week (npmjs.com stats).
  64. // 1.77.x (at least 1.77.0-1.77.2) distribution metadata.json is missing
  65. // dependency information for all OpenUI5 libraries.
  66. // Therefore we need to request those from the registry like it is done
  67. // for OpenUI5 projects.
  68. const {default: Openui5Resolver} = await import("./Openui5Resolver.js");
  69. const openui5Resolver = new Openui5Resolver({
  70. cwd: this._cwd,
  71. version: metadata.version
  72. });
  73. const openui5Metadata = await openui5Resolver.getLibraryMetadata(libraryName);
  74. return {
  75. npmPackageName: openui5Metadata.id,
  76. version: openui5Metadata.version,
  77. dependencies: openui5Metadata.dependencies,
  78. optionalDependencies: openui5Metadata.optionalDependencies
  79. };
  80. }
  81. return metadata;
  82. }
  83. async handleLibrary(libraryName) {
  84. const metadata = await this.getLibraryMetadata(libraryName);
  85. return {
  86. metadata: Promise.resolve({
  87. id: metadata.npmPackageName,
  88. version: metadata.version,
  89. dependencies: metadata.dependencies,
  90. optionalDependencies: metadata.optionalDependencies
  91. }),
  92. // Trigger installation of package
  93. install: this._installer.installPackage({
  94. pkgName: metadata.npmPackageName,
  95. version: metadata.version
  96. })
  97. };
  98. }
  99. static async fetchAllVersions(options) {
  100. const installer = this._getInstaller(options);
  101. return await installer.fetchPackageVersions({pkgName: DIST_PKG_NAME});
  102. }
  103. static async fetchAllTags(options) {
  104. const installer = this._getInstaller(options);
  105. return installer.fetchPackageDistTags({pkgName: DIST_PKG_NAME});
  106. }
  107. static _getInstaller({ui5HomeDir, cwd} = {}) {
  108. return new Installer({
  109. cwd: cwd ? path.resolve(cwd) : process.cwd(),
  110. ui5HomeDir:
  111. ui5HomeDir ? path.resolve(ui5HomeDir) :
  112. path.join(os.homedir(), ".ui5")
  113. });
  114. }
  115. }
  116. export default Sapui5Resolver;