Skip to content

refactor: Consolidate UI5 data directory resolution into resolveUi5DataDir#1456

Draft
d3xter666 wants to merge 15 commits into
mainfrom
refactor/resolve-ui5-data-dir
Draft

refactor: Consolidate UI5 data directory resolution into resolveUi5DataDir#1456
d3xter666 wants to merge 15 commits into
mainfrom
refactor/resolve-ui5-data-dir

Conversation

@d3xter666

@d3xter666 d3xter666 commented Jul 17, 2026

Copy link
Copy Markdown
Member

Introduces packages/project/lib/utils/dataDir.js with a single resolveUi5DataDir() utility that encapsulates the full resolution chain:

  1. UI5_DATA_DIR environment variable
  2. ui5DataDir from configuration file
  3. Default: ~/.ui5

Removes the duplicate getUi5DataDir() function from packages/cli/lib/framework/utils.js and migrates its callers (createFrameworkResolverInstance, frameworkResolverResolveVersion) to use resolveUi5DataDir() directly.

Consolidates and enforces the new utility accross packages

…taDir

Introduces packages/project/lib/utils/dataDir.js with a single
resolveUi5DataDir() utility that encapsulates the full resolution chain:
  1. UI5_DATA_DIR environment variable
  2. ui5DataDir from configuration file (~/.ui5rc)
  3. Default: ~/.ui5

Removes the duplicate getUi5DataDir() function from
packages/cli/lib/framework/utils.js and migrates its callers
(createFrameworkResolverInstance, frameworkResolverResolveVersion) to
use resolveUi5DataDir() directly.

The defensive fallbacks in the public Resolver/Installer APIs
(AbstractResolver, Openui5Resolver, Sapui5Resolver,
Sapui5MavenSnapshotResolver) are intentionally kept — those are
synchronous constructors that cannot call the async utility, and they
are publicly exported so external callers may pass undefined.
…ve path resolution

Renames the cwd option to projectRootPath to make its purpose explicit:
this is the root of the specific project being processed (where package.json
lives), not necessarily the shell's current working directory. When omitted,
falls back to process.cwd().

Callers in createFrameworkResolverInstance and frameworkResolverResolveVersion
now thread the project root through so relative ui5DataDir values in config
are resolved against the correct base directory.
…i5DataDir

Two call sites that duplicated the env→config→default resolution logic
are migrated to resolveUi5DataDir({projectRootPath}):

- packages/project/lib/graph/helpers/ui5Framework.js:
  enrichProjectGraph resolves ui5DataDir via resolveUi5DataDir using
  rootProject.getRootPath() as projectRootPath, then passes it to
  the framework Resolver. Configuration and os imports removed.

- packages/project/lib/build/cache/CacheManager.create():
  The no-ui5DataDir path now delegates to resolveUi5DataDir instead of
  inlining env/config/default logic. The explicit ui5DataDir option
  still resolves against cwd for backward compatibility. os and
  Configuration imports removed.

Tests updated: resolveUi5DataDir stub added to ui5Framework.js esmocks
so the stub mirrors the real resolution logic (including env and config
stubs), and package-exports count updated.
…i5DataDir

Two call sites that duplicated the env→config→default resolution logic
are migrated to resolveUi5DataDir({projectRootPath}):

- packages/project/lib/graph/helpers/ui5Framework.js:
  enrichProjectGraph resolves ui5DataDir via resolveUi5DataDir using
  rootProject.getRootPath() as projectRootPath, then passes it to
  the framework Resolver. Configuration and os imports removed.

- packages/project/lib/build/cache/CacheManager.create():
  The no-ui5DataDir path now delegates to resolveUi5DataDir instead of
  inlining env/config/default logic. The explicit ui5DataDir option
  still resolves against cwd for backward compatibility. os and
  Configuration imports removed.

Tests updated: resolveUi5DataDir stub added to ui5Framework.js esmocks
so the stub mirrors the real resolution logic (including env and config
stubs), and package-exports count updated.
@d3xter666
d3xter666 force-pushed the refactor/resolve-ui5-data-dir branch from 95e6631 to b449a91 Compare July 17, 2026 11:26
Replace hardcoded POSIX absolute paths (/my/project, /custom/data/dir,
etc.) with path.resolve(os.tmpdir(), ...) so assertions hold on all
platforms. On Windows, /foo is not an absolute path — it is relative
to the current drive root — causing four tests to fail.
@d3xter666
d3xter666 force-pushed the refactor/resolve-ui5-data-dir branch from b449a91 to b091c77 Compare July 17, 2026 11:27
- Use path.resolve instead of path.join for the default ~/.ui5 fallback
  so the result is absolute even when os.homedir() returns a relative
  path (e.g. "./" in some CI/container environments).

- Add edge-case test that asserts absoluteness when HOME is relative.

- Fix CLI framework/utils tests: stubs resolving undefined reflected
  old behavior where no ui5DataDir meant undefined; add clarifying
  comments that these tests validate stub wiring, not real resolution.

- Add utils/dataDir to the explicit API parity list in package-exports
  test so a path/mapping regression would be caught by a specific test.
- cli/framework/utils.js: stub now resolves the real default path
  (path.join(os.homedir(), ".ui5")) instead of undefined, matching
  the production contract of resolveUi5DataDir.

- graph/helpers/ui5Framework.js: stub and assertions use path.resolve
  instead of path.join for the default ~/.ui5 path, matching the
  stricter absolute-path guarantee of the implementation.
The stub for resolveUi5DataDir does not need to compute a real
filesystem path — it just needs an opaque value that flows through
correctly. Replace path.join(os.homedir(), '.ui5') with the string
literal 'my-default-ui5-data-dir' and remove the unused os and path
imports.
@d3xter666
d3xter666 marked this pull request as ready for review July 17, 2026 14:58
@d3xter666
d3xter666 requested a review from a team July 17, 2026 14:58
@RandomByte

Copy link
Copy Markdown
Member

I'm wondering whether we still need the fallbacks in https://github.com/UI5/cli/blob/refactor/resolve-ui5-data-dir/packages/project/lib/ui5Framework/AbstractResolver.js#L44 and https://github.com/UI5/cli/blob/refactor/resolve-ui5-data-dir/packages/project/lib/build/cache/CacheManager.js#L77 since we now always provide a ui5DataDir value

Comment thread packages/project/lib/utils/dataDir.js
@d3xter666

d3xter666 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

I'm wondering whether we still need the fallbacks in https://github.com/UI5/cli/blob/refactor/resolve-ui5-data-dir/packages/project/lib/ui5Framework/AbstractResolver.js#L44 and https://github.com/UI5/cli/blob/refactor/resolve-ui5-data-dir/packages/project/lib/build/cache/CacheManager.js#L77 since we now always provide a ui5DataDir value

I had the same concnerns!
However, I see a potential backwards incompatibility in this case.
The AbstractResolver.js itself is internal only, but Openui5Resolver, Sapui5Resolver, Sapui5MavenSnapshotResolver are exposed as public APIs and passing {ui5DataDir: undefined} to them will break the current behaviour i.e. new Sapui5MavenSnapshotResolver({ui5DataDir: undefined}).

Removing the ui5DataDir argument from the constructor can potentially solve this issue, but from backwards compatibility perspective, to me it seems more risky

@RandomByte

Copy link
Copy Markdown
Member

I'm arguing to make it a required argument for AbstractResolver.

The current state in this PR is confusing IMHO: Passing {ui5DataDir: undefined} to CacheManager will properly resolve the directory from env and configuration. Passing the same to AbstractResolver will ignore env and configuration and simply use path.join(os.homedir(), ".ui5"). This makes me think that the two entities could end up working on different directories.

@d3xter666

d3xter666 commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

I'm arguing to make it a required argument for AbstractResolver.

The current state in this PR is confusing IMHO: Passing {ui5DataDir: undefined} to CacheManager will properly resolve the directory from env and configuration. Passing the same to AbstractResolver will ignore env and configuration and simply use path.join(os.homedir(), ".ui5"). This makes me think that the two entities could end up working on different directories.

Thank you @RandomByte !

I have tried to analyze the situation and how ui5DataDir evolves in the chain.
We have couple of scenarios: @ui5/cli command & API usage (i.e. @ui5/project/ui5Framework/*Resolver)

CLI

From CLI perspective, we have encapsulation and all the resolutions come from the newly introduced resolveUi5DataDir which resolves the same for all scenarios. In any of the CLI commands we explicitly provide ui5DataDir as an argument over the execution chain, but rather we rely on internal resolution and with this refactoring, this means resolveUi5DataDir() call.

API

The API perspective is a bit more complex and I will try to simplify it by couple of API calls to illustrate it clearer.

Resolver.resolveVersion({verions: 1.xxxx}) // ui5DataDir === undefined -> ~/.ui5

// resolveUi5DataDir() -> eventually can fallback to ~/.ui5, but before that will
// consider UI5_DATA_DIR and ui5.yaml configuration.
CacheManager.create();  // ui5DataDir === undefined

It is obvious that for the same default values for ui5DataDir we have different fallbacks. We need to align them!

With that refactoring, CacheManager.create() now supports the same fallback mechanism as AbstractResolver and it no longer resolves the ui5DataDir internally. Now as it is aligned with AbstractResolver, the resolution comes from the higher order component. In case of any AbstractResolver instance this is ui5Framework.enrichProjectGraph and for the CacheManager.create(), it is BuildContext.getCacheManager()

Here's the resolution: 9ac64b5

@d3xter666
d3xter666 force-pushed the refactor/resolve-ui5-data-dir branch from 085bae7 to 9ac64b5 Compare July 20, 2026 12:14
@d3xter666
d3xter666 requested review from a team, RandomByte and matz3 July 20, 2026 12:22
@RandomByte

Copy link
Copy Markdown
Member

I'm sorry, but I think this doesn't address my concern. There are still two public APIs that resolve the data dir differently. It seems like you just moved the resolution from one internal class to another, which doesn't change the behavior for external consumers:

  1. The ProjectBuilder class still internally resolves the data dir using the env-var + config-file fallback chain.
  2. The AbstractResolver class still ignores env-var and config-file and simply falls back to ~/.ui5

Take note that CacheManager is not a public API.

As I said before, I think aligning this thoroughly might mean that we need to force consumers of all public APIs to always provide the data dir, which no internal fallback. This might be a bigger refactoring, which we might not want to tackle now.

@d3xter666
d3xter666 marked this pull request as draft July 22, 2026 06:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants