Skip to content

feat(project): Replace stepBased opt-in with a task descriptor factory API - #1670

Draft
RandomByte wants to merge 5 commits into
mainfrom
refactor/specVersion-5.0-task-api
Draft

RandomByte wants to merge 5 commits into
mainfrom
refactor/specVersion-5.0-task-api

Conversation

@RandomByte

Copy link
Copy Markdown
Member

No description provided.

matz3 and others added 5 commits October 14, 2026 09:21
…y API

From Specification Version 5.0, a task module's default export is a factory
(options) => descriptor. The descriptor carries the whole task contract in one
object: exactly one of `steps` (step-based) or `task` (legacy single stage),
plus the optional `determineRequiredDependencies`, `determineBuildSignature`,
and `specVersion` properties. This replaces the former static `stepBased` export
and the top-level named-export callbacks, and resembles established plugin APIs
such as that of Vite.

All built-in tasks adopt the same shape: `determineBuildSignature`,
`requiresDependencies`, and the step-vs-task decision move out of the build
definitions into the task modules. The definition files shrink to per-project
options and skip decisions (`skip: true` replaces `taskFunction: null`). The
`generateBundle` wrapper stays in the definitions, because its
`enhanceBundlesWithDefaults` helper lives in @ui5/project and cannot move into
@ui5/builder.

A custom task's `specVersion` property, if declared, must equal the task
extension's configured Specification Version. Below 5.0 the default export stays
the legacy task body, invoked directly during the build; any object it returns
is ignored. The cache-internal `stepBased` flag (whether a stage ran the step
runner) is unrelated and is retained.

The descriptor is resolved once per build and memoized on `TaskDefinitions`,
shared by the build-signature phase and task execution. `BUILD_SIG_VERSION` and
`CACHE_VERSION` are bumped to invalidate existing caches; no backward-compat
shim is added, as the v5 line is still in alpha.
The specVersion 5.0 task-descriptor refactor left the legacy `task`-based
standard tasks with the body inline in the returned descriptor and a JSDoc
block that still documented the task-body parameters on the factory (the
default export), guarded by `/* eslint "jsdoc/check-param-names": "off" */`.

For every `task`-based standard task, move the body to a module-scoped `task`
function (a local `const` in generateJsdoc, where it closes over
factory-precomputed values) and carry the parameter JSDoc with it. The factory
JSDoc now documents only its own contract (`@returns {object} The task
descriptor`), so the eslint-disable is removed. Options the body reads are
destructured in its signature so the documented names match.

Split descriptors that packed multiple properties onto one line
(`{requiresDependencies: true, steps: [...]}`) onto separate lines, lifting a
single step into a named const where that keeps the step body from gaining a
further indent level.

No behavior change: the descriptor shape each factory returns is unchanged, so
`generateX().task(...)` and the step arrays stay identical. Builder lint and
unit tests pass.
The default export of a task module is a factory `(options) => descriptor`.
`build` was misleading, since the factory builds nothing: it declares the task
and returns its descriptor. Rename it to `defineTask`, matching the plugin-API
convention (Vite's `defineConfig`) and the descriptor's own `task`/`steps`
fields.

Give the factories that were anonymous (`export default function()`) the same
name, so every task module reads the same way. The utility
`createModuleNameMapping` keeps its own default export; it is not a task.
…port

The specVersion 5.0 refactor moved each legacy `task`-based standard task's
body (and its parameter JSDoc) onto a module-scoped `task` function, leaving the
public default export (the factory) with no parameter documentation. The
generated API reference then showed `default() => {object}` with no Parameters
section, so a consumer could no longer tell which options a task accepts to run
it standalone. `generateBundle` had the opposite problem: the body's
`parameters.{workspace,dependencies,taskUtil,options}` block stayed on the
factory, documenting a signature the factory does not have.

Document the factory's `options` on every `task`-based standard task, matching
the convention the step-based tasks already use. Each factory now names its
`options` parameter so the documented names match the signature, and the
`generateBundle` factory block drops the reader parameters it never receives.
The module-scoped `task` functions keep their own parameter JSDoc for
maintainers.

Also finish the `build` -> `defineTask` rename: update the stale factory naming
in the `runSteps` helper JSDoc and in the custom-task documentation examples
(the examples now use an anonymous default export, matching the others).

No behavior change: the only runtime change is an unused `options` parameter on
the factories. Builder lint and unit tests pass.
Add a shared public typedef TaskDescriptor on the @ui5/builder/tasks/runSteps
module and point every built-in task's default export at it, so the generated
API reference shows the descriptor's shape (steps, task, requiresDependencies,
determineRequiredDependencies, determineBuildSignature, specVersion) instead of
a bare "object".

Split the runSteps module comment into a standalone module, the typedef, and the
default function doclet, so the typedef attaches to the module and renders under
"Type Definitions". Add the missing requiresDependencies to the custom tasks
guide.

This branch has not been deployed

No deployments
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.

2 participants