Use a word-boundary regex (:name\b) instead of a plain string replace
so that a shorter param like :a doesn't corrupt a longer param :ab
when both are present in the route.
Signed-off-by: Patrik Oldsberg <rugvip@backstage.io>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The app/routes redirect config now performs the same :param and *
substitution that the legacy Redirect component did before navigating.
Named params captured by the `from` pattern are replaced in the `to`
string, enabling redirects like /users/:userId → /profile/:userId and
/old-docs → /docs/* (with splat forwarding).
Adds tests for both named-param and splat substitution.
Signed-off-by: Patrik Oldsberg <rugvip@backstage.io>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduces a Combobox component to Backstage UI for times when you want to allow users to choose from a list of values but also specify their own in some cases.
---------
Signed-off-by: James Brooks <jamesbrooks@spotify.com>
Style the bui-Link itself when keyboard-focused using the ring token,
matching the established pattern from ButtonLink. Also tweak the
changeset wording to reflect the new behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Emma Indal <emma.indahl@gmail.com>
Card's focus-ring CSS keys off data-focus-visible on the
bui-CardTrigger, but Link (the trigger when href is set) wasn't
emitting it because useLink does not track focus-visible state.
Compose useFocusRing in Link so keyboard focus is now properly
indicated on Card href=... and any other Link styled via
[data-focus-visible].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Emma Indal <emma.indahl@gmail.com>
Validate the parsed Retry-After value is a finite positive number before
using it as a delay, falling back to exponential backoff otherwise. This
prevents a near-zero delay tight retry loop when the header contains an
HTTP-date or unexpected value.
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Capturing globalThis.fetch as a value at construction time meant the
GitLabUrlReader tests bypassed the MSW fetch interceptor and hit the
real gitlab.com (returning 401). Wrapping the call resolves fetch at
invocation time so the patched fetch is used.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Each catch path now decides for itself whether to rethrow or sleep and
continue, so the loop body has a definite Response after the try/catch
and there is no shared `error: unknown` slot that could in principle be
thrown unset. Pulls the exponential delay into a tiny local helper to
share between the two retry paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Flip the order of the response/error check so TypeScript narrows the
types itself rather than relying on `response!` to assert what the code
already guarantees by construction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
- Cancel discarded response bodies before retrying so the underlying
connection can be returned to the pool instead of being held open
until the response is garbage collected.
- Stop asserting on the rejected error message in the network-error
retry test; track rejection via a flag so the test isn't tied to
fetch/MSW error strings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Removes a misplaced `mode: 'same-origin'` option that would have rejected
cross-origin requests when the integration is used from a browser, and
extends the retry wrapper so transient network errors are retried using
the configured `maxRetries`. Caller-initiated aborts still propagate
immediately.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Fredrik Adelöw <freben@spotify.com>
Adds a Scaffolder category entry for @kissmiklosjr/plugin-scaffolder-studio
with an iconUrl pointing at a new SVG illustrating the plugin's template
graph editor.
Signed-off-by: Kiss Miklos <kissmiklosjr@gmail.com>