7921 Commits
Author SHA1 Message Date
Bassel Kanso e666ee26ae Merge branch 'main' into develop 2026-06-02 17:08:25 +03:00
e56900bd07 enhancement(core): eliminate @strapi/typescript-utils from boot path (#26270)
Even with the lazy-fn pattern in Strapi.ts and compile.ts (#26266),
deep tracing shows @strapi/typescript-utils still loads at boot via
three independent paths:

- `services/metrics/sender.ts` top-imports tsUtils for two
  `isUsingTypeScriptSync` calls inside the sender factory. Even when
  telemetry is disabled, importing the file loads tsUtils.
- `services/metrics/index.ts` calls `createSender(strapi)`
  unconditionally, then `wrapWithRateLimit`. Both run when telemetry
  is disabled, even though their result is never used.
- `admin/server/src/controllers/admin.ts` destructures
  `{ isUsingTypeScript } = tsUtils` at the module top, firing the
  require unconditionally. The function is only consumed by
  `GET /admin/project-type`.
- `core/src/Strapi.ts` calls `tsUtils.resolveOutDirSync(...)` in the
  db factory even when `useTypescriptMigrations` is the default false,
  so the result is computed and thrown away.

Surgical changes:

- `metrics/sender.ts`: tsUtils becomes a lazy fn so loading the file
  is free.
- `metrics/index.ts`: gate `createSender(strapi)` and
  `wrapWithRateLimit(...)` behind `!isDisabled`.
- `admin.ts`: tsUtils becomes a lazy fn; isUsingTypeScript is a thin
  wrapper that resolves the require on first call.
- `Strapi.ts`: `useTypescriptMigrations` check is hoisted; tsUtils
  resolves only when the flag is true.

Measured (interleaved A/B, 12 runs each, fresh quickstart):
- typescript-utils loads at boot: 17 -> 0
- median wall-clock: 1803 ms -> 1696 ms (-107 ms, above noise)

Co-authored-by: Ben Irvin <ben.irvin@strapi.io>
Co-authored-by: Ben Irvin <ben@innerdvations.com>
2026-05-29 17:19:37 +00:00
Vishal Kumar SinghandBassel Kanso 6e7e28306c fix(admin): use ISO 639-1 da for Danish admin locale (#26322)
* fix(admin): use ISO 639-1 da for Danish admin locale

Rename admin translation bundles from dk to da, normalize legacy dk in
app config, custom translation keys, localStorage, and stored user language.

Closes #25761

* fix(admin): add dk json fallback and admin user language migration

Register internal migration admin::migrate-prefered-language-dk-to-da to
rewrite admin_users.prefered_language from dk to da.

Export importLocaleJsonWithLegacyDkFallback from strapi-admin and use it in
core loadAdminTrads plus every bundled plugin registerTrads so third-party
plugins that still ship only dk.json keep loading when the UI locale is da.

Add @strapi/admin devDependency where the helper is imported from JS or
packages that did not already list it.

Refs #26322

* fix(types): add importLocaleJson to strapi-admin registerTrads typing

* fix(admin): expand plugin locale list and merge under canonical codes

Moves legacy dk handling into StrapiApp.loadTrads (flatMap + uniq + normalize merge) so registerTrads keeps a stable API without importLocaleJson. Core admin bundles use try/catch dynamic imports per locale code.

* fix(admin): route plugin translations through importLocaleJson

Pass StrapiApp.importLocaleJson into registerTrads so core and third-party plugins share legacy locale JSON fallback (da -> dk) and one-shot deprecation warnings. Relax admin test console.warn filter for those messages. Refs #26322.

* fix(admin): keep plugin locale fallback internal

---------

Co-authored-by: Bassel Kanso <basselkanso82@gmail.com>
2026-05-29 18:26:00 +03:00
dependabot[bot] d0aa491f9f chore(deps): bump qs from 6.15.0 to 6.15.2 (#26417)
Bumps [qs](https://github.com/ljharb/qs) from 6.15.0 to 6.15.2.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.15.0...v6.15.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.15.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-28 17:36:20 +00:00
dependabot[bot] a5d30be517 chore(deps): bump axios from 1.16.0 to 1.16.1 (#26456)
Bumps [axios](https://github.com/axios/axios) from 1.16.0 to 1.16.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.16.0...v1.16.1)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.16.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-28 19:00:32 +02:00
1138f7c6ad chore(admin): remove punycode dependency (#26189)
* chore(admin): remove punycode dependency

WHATWG URL handles IDN natively on Node >=20, so the punycode call
before `new URL()` is redundant.

Per Node docs (https://nodejs.org/api/url.html#new-urlinput-base):

  Unicode characters appearing within the host name of input will be
  automatically converted to ASCII using the Punycode algorithm.

  const myURL = new URL('https://測試');
  // https://xn--g6w251d/

Drops `punycode` and `@types/punycode` from packages/core/admin.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(typescript): guard pathExistsSync against undefined config path

`getConfigPath` may return `undefined` when no tsconfig matches; passing
that into `fse.pathExistsSync` triggers DEP0187 on Node >=22:

  [DEP0187] DeprecationWarning: Passing invalid argument types to
  fs.existsSync is deprecated

Short-circuit to `false` when the path is not resolved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Ben Irvin <ben.irvin@strapi.io>
2026-05-28 15:09:31 +00:00
jhoward1994 42509493bf release: 5.47.0 2026-05-28 11:22:14 +00:00
Nico André 9247b9b093 feat(*): introduce MCP server (#26371) 2026-05-27 15:33:05 +01:00
Nico André d6f693da85 feat(*): introduce MCP server (#26371) 2026-05-27 16:27:48 +02:00
Filip ÓnodiandBassel Kanso e7772d621e feat(i18n): update and create Slovak translations (#25831)
Co-authored-by: Bassel Kanso <basselkanso82@gmail.com>
2026-05-26 15:10:41 +03:00
Bassel Kanso 1606e26317 fix(admin): avoid serving extensionless admin paths as static files (#26368) 2026-05-26 11:49:34 +03:00
1dd851498a feat(admin): add documentation helper link in HeaderLayout (revival of #23328) (#26422)
* feat(admin): add documentation helper link in HeaderLayout

Revival of #23328 (by @Mcastres), rebased on develop with review feedback
addressed and additional improvements:

- Replace hand-rolled find with react-router matchRoutes for proper path
  matching and specificity ranking
- Update doc URLs to canonical docs.strapi.io paths (drop redirected
  /user-docs/* and /dev-docs/* entries)
- Restore section anchors that were lost during doc-site reorganization
  (#providers, #email-templates, #advanced-settings, profile, rbac)
- Align array path entries with actual registered admin routes (rename
  /plugins/content-type-builder, /plugins/content-releases, settings
  prefix for purchase-content-releases and list-plugins, drop dead
  /marketplace external link)
- Add opt-out flag admin.flags.docLinks for white-label deployments
  (requested by @derrickmehaffy)
- Memoize getMatchingDocLink result per pathname
- Place doc link button next to primary action via gap on parent Flex
  (per @remidej review)
- Drop async from getMatchingDocLink, derive docLink synchronously from
  pathname (per @remidej review)

Closes #23328

Co-authored-by: Maxime Castres <17828745+Mcastres@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(admin): move DocLink type to getMatchingDocLink module

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): add docLinks flag to EE Window strapi type

The EE admin custom.d.ts redeclares window.strapi.flags and was missing
the docLinks property, causing test:ts:front to fail with TS2339 in
HeaderLayout.tsx.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: add getMachingDocLink tests

---------

Co-authored-by: Maxime Castres <17828745+Mcastres@users.noreply.github.com>
Co-authored-by: Ben Irvin <ben@innerdvations.com>
2026-05-26 09:59:00 +02:00
Nico André ebba42a369 feat(admin-tokens): remove adminTokens future flag (#26391) 2026-05-21 15:31:38 +02:00
Bassel Kanso c579537cbf Merge branch 'main' into develop 2026-05-20 12:23:13 +03:00
Bassel17 04ac8c3e90 release: 5.46.1 2026-05-20 09:09:00 +00:00
DMehaffyandClaude Opus 4.7 56d7a64c49 fix(admin): redirect active tab to login on session expiry (#26165)
* fix(admin): redirect active tab to login on session expiry

Two complementary changes that close the gap between server-side session
invalidation and client-side UX, fixes #26163:

1. **Active-tab redirect on 401.** baseQuery's 401 handler now invokes a
   session-expired callback in addition to dispatching `logoutAction`.
   AuthProvider registers `clearStateAndLogout` as that callback so the
   tab that originated the failing request is navigated to /auth/login —
   not just other tabs (which already react via the `storage` event).

2. **JWT-exp idle timer.** AuthProvider schedules a one-shot timer at the
   access token's `exp` claim. While the user is active, every API call
   that hits a 401 transparently refreshes the token (existing behavior in
   getFetchClient.withTokenRefresh), which updates Redux and reschedules
   the timer to the new exp. If no API activity occurs during the access
   token lifespan, the timer fires and the user is logged out — matching
   the configured server-side idle behavior without a separate activity
   tracker.

The mechanism is wired through a new `setOnSessionExpired` /
`triggerSessionExpired` pair in getFetchClient.ts (mirroring the existing
`setOnTokenUpdate` registry), keeping the React layer as the only place
that owns navigation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(admin): extract idle-session logout into testable hook

Per review feedback, move the JWT exp decoding into utils/jwt.ts and
the one-shot logout effect into a useIdleSessionLogout hook so both
have unit coverage. Hardens the decoder with type checks, base64url
padding, and a Number.isFinite guard on exp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 12:46:22 +00:00
dependabot[bot] c97abbdf2e chore(deps): bump sanitize-html from 2.13.0 to 2.17.4 (#26342)
Bumps [sanitize-html](https://github.com/apostrophecms/apostrophe/tree/HEAD/packages/sanitize-html) from 2.13.0 to 2.17.4.
- [Changelog](https://github.com/apostrophecms/apostrophe/blob/main/packages/sanitize-html/CHANGELOG.md)
- [Commits](https://github.com/apostrophecms/apostrophe/commits/HEAD/packages/sanitize-html)

---
updated-dependencies:
- dependency-name: sanitize-html
  dependency-version: 2.17.4
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-19 11:51:07 +02:00
Vishal Kumar SinghandBen Irvin df91d08122 fix(admin): gate expiresIn deprecation on user auth options (#26298)
* fix(admin): gate expiresIn deprecation on user auth options

getTokenOptions merges defaultJwtOptions, so options.expiresIn is always
set even when the project never configured admin.auth.options.expiresIn.
That made the bootstrap deprecation warn on every startup.

Read raw admin.auth.options via a small helper next to the token service
and cover it with unit tests.

Refs https://github.com/strapi/strapi/issues/25989

* chore: prettier

---------

Co-authored-by: Ben Irvin <ben@innerdvations.com>
2026-05-18 15:12:14 +00:00
6ed22b5cfa security(deps): upgrade multiple dependencies (#26326)
* chore: upgrade simple-git

* chore: upgrade axios

* chore: upgrade docusaurus

* chore: upgrade docusaurus family

* chore: yarn.lock

* chore: upgrade styled-components

* chore: upgrade yaml

* chore: bump fast-uri in pinned deps

* chore: bump axios in cloud plugin

* chore: remove unnecessary ts error suppression

* chore: align docusaurus packages

* chore: yarn.lock

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Jamie Howard <jhoward1994@gmail.com>
2026-05-15 08:52:31 +01:00
dependabot[bot] 49b96fcfdc chore(deps): bump axios from 1.15.1 to 1.15.2 (#26177)
Bumps [axios](https://github.com/axios/axios) from 1.15.1 to 1.15.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.15.1...v1.15.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.15.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 11:52:04 +02:00
Mark Kaylor 83fec11da9 Merge remote-tracking branch 'origin/main' into develop 2026-05-13 19:12:11 +02:00
markkaylor 7f34c4b7d9 release: 5.46.0 2026-05-13 13:39:32 +00:00
Nico AndréandBen Irvin c3d9daef94 fix(core/admin): admin and content api tokens retro-compatibility (#26313)
* fix(core/admin): api-token service treats kind.null as content-api

* fix(core/admin): services expose backward compatible 'api-token' shim

* enhancement(core/admin): api-token service uses pick instead of omit

* fix(core/admin): strategies content-api-token uses api-token-content-api service

* test: ensure api-token alias works

* test: fix useDocumentLayout for msw upgrade

---------

Co-authored-by: Ben Irvin <ben@innerdvations.com>
2026-05-13 14:57:11 +02:00
Maksim ZhukauandAdrien L 88f57e612e fix(admin): remove year 2041 limit on date/datetime pickers (#26209)
* fix: remove year 2041 limit on date/datetime pickers (closes #26180)

The @strapi/design-system DatePicker defaults to currentYear + 15 as maxDate,
capping year selection at 2041. Explicitly pass maxDate={new Date(9999, 11, 31)}
before the props spread so users can still override it, but the default is now
effectively unlimited.

* fix: lower date/datetime picker max year to 2099

---------

Co-authored-by: Adrien L <3693028+Adzouz@users.noreply.github.com>
2026-05-12 15:10:04 +02:00
Adrien L cad5c693bf fix(review-workflows): add assignee and review stage to list view filters (#26171)
* fix(review-workflows): add assignee to list view filters

* fix: improve perf and add assignee filters options

* fix: preload with data when filter exists

* fix: centralize and export type from content manager

* fix: assignee filter limit to 10 items
2026-05-12 10:08:29 +02:00
Andrei L b5452ab89f chore(eslint): migrate .eslintrc + .eslintignore to .eslintrc.cjs (#26216)
* chore(eslint): migrate .eslintrc + .eslintignore to .eslintrc.cjs

Consolidates the per-package ESLint setup into a single typed
`.eslintrc.cjs` file across the monorepo (177 files touched).

Why
- `.eslintignore` is removed in ESLint v9/v10. Folding ignore patterns
  into `ignorePatterns` inside the rc file is the supported migration
  path and unblocks future ESLint upgrades (which will likely be needed
  alongside the in-flight TypeScript 6 migration).
- `.cjs` extension is explicit about module format, so the configs keep
  working if any package later adopts `"type": "module"` (no CJS/ESM
  surprises).
- Wrapping each config in `// @ts-check` + a `Linter.Config`-typed
  `const config` block gives editor autocomplete and catches typos.
  Surfaced two real duplicates in
  `eslint-config-custom/back/typescript.js`
  (`node/no-unsupported-features/es-syntax`,
  `node/no-missing-import`), now deduplicated.
- `extends` references switched from the `custom/*` shorthand to the
  explicit `eslint-config-custom/*` package name. ESLint resolves both,
  but the explicit form makes the source unambiguous.
- Added `coverage/` to `ignorePatterns` so coverage output produced
  inside a workspace is not linted.

Misc
- `examples/kitchensink` had ESLint configured but no `lint` script;
  added one so the config actually runs.
- `nx.json` hash inputs updated:
  - removed `.eslintignore` (no longer exists)
  - replaced `{projectRoot}/.eslintrc.js` with
    `{projectRoot}/**/.eslintrc.cjs` so nested package configs are also
    part of the cache key (the previous glob missed them).
- `packages/utils/upgrade/tsconfig.eslint.json` include path updated
  from `.eslintrc.js` to `.eslintrc.cjs`.

Verification
- `eslint --print-config` resolves cleanly on sampled back/front
  packages (admin, users-permissions, upload).
- Full `pnpm -r lint` is clean.

* chore(eslint): set tsconfigRootDir for vscode-eslint typed linting

CLI lint resolved tsconfig paths via cwd, but vscode-eslint runs from
the workspace root and could not locate per-package tsconfigs. Set
parserOptions.tsconfigRootDir to __dirname in each package's
.eslintrc.cjs so the editor resolves typed-lint configs correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(eslint): self-ignore configs, scope coverage to jest packages

- Replace `env: { es6: true }` workaround with `.eslintrc.cjs` in
  ignorePatterns so eslint never lints the config file itself
  (root cause of the "const is not a keyword" parse error in es5)
- Add `.eslintrc.cjs` to ignorePatterns across all configs that
  were missing it
- Restrict `coverage/` ignorePatterns to workspace roots that
  actually run jest; drop from non-test packages and admin/server
  subdir configs (tests run from the workspace root)
2026-05-12 07:32:12 +00:00
Jamie Howard a2c5ecb225 Merge remote-tracking branch 'origin/main' into develop 2026-05-11 16:16:35 +01:00
Simon Norris 0edbf57ba6 Merge branch 'develop' into feature/button-remove-trial-banner 2026-05-11 14:40:18 +02:00
jhoward1994 9300041094 release: 5.45.1 2026-05-11 10:41:36 +00:00
Jamie Howard 5dd2e7376f [admin]key for select component and add missing translations (#26226) 2026-05-11 10:28:24 +00:00
6d83054647 chore(deps): migrate msw 1.x → 2.13.4 across admin test suites (#26065)
* chore(deps): bump msw to 1.3.5 and typedoc to 0.25.13

Widens TypeScript peer ranges in msw (>= 4.4.x) and typedoc (adds 5.4.x),
unblocking a future bump to typescript 5.6 required by react-intl 7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(deps): bump msw to 2.13.4 across admin test suites

Migrates 8 workspaces (admin, content-manager, content-releases, upload,
review-workflows, plugin-i18n, plugin-documentation, plugin-users-permissions)
from msw 1.3.5 to 2.13.4; bumps email's unused dep for consistency.

Handler changes:
- rest.X((req, res, ctx) => res(ctx.json(X))) → http.X(() => HttpResponse.json(X))
- res(ctx.status(N)) → new HttpResponse(null, { status: N })
- res.once(...) → http.X(path, handler, { once: true })
- res.networkError(...) → HttpResponse.error()
- await req.json<T>() / casts → http.METHOD<Params, Body>(...) generics
- RequestHandler → HttpHandler
- Empty 200 responses use HttpResponse.json({}) to avoid cross-realm
  SyntaxError instanceof check in getFetchClient.ts

Jest setup (per msw frequent-issues guide):
- jest-preset.front.js: customExportConditions: [''] so msw/node resolves
  under jsdom; .mjs swc transform; ESM allow-list for msw deps
  (rettime, @open-draft, outvariant, until-async, etc.)
- packages/admin-test-utils/src/environment.ts: polyfill Node fetch +
  streams + BroadcastChannel + URL into jsdom global. Blob/File/FormData
  intentionally left as jsdom's — Strapi app code threads them through
  jsdom-only APIs (FileReader, Image, HTMLFormElement) where realm matters.
  Comment in env.ts documents the trade-off.

Verified vs develop+msw@1.3.5 baseline: 0 net regressions across all 7
workspaces with msw test files; TypeScript clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Revert "chore(deps): bump typedoc to 0.25.13"

The typedoc bump was bundled with the msw 1.3.5 bump in 39d169cfbb but
isn't required for the msw v2 migration. Reverting the docs/ and
core/types typedoc dep back to 0.25.10 to keep this branch focused on
the msw upgrade.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(tests): type msw handler params via generics

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(tests): address review feedback on msw v2 migration

- env.ts: snapshot jsdom globals in setup(), restore in teardown() so
  per-test mutations cannot leak across files in a Jest worker.
- env.ts: collapse polyfill list and value map into a single NODE_GLOBALS
  source of truth; document the fetch trade-off (Node undici vs jsdom).
- handlers: replace `<never, Body>` generics with `<Record<string, never>,
  Body>` (msw v2 convention; `{}` blocked by ban-types).
- email: drop unused msw devDep entirely (zero source usage in workspace).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(tests): use realm-agnostic SyntaxError check; drop URL polyfill

Two follow-ups to the msw v2 migration:

- `getFetchClient.responseInterceptor` now matches `error?.name === 'SyntaxError'`
  rather than `instanceof SyntaxError`. Constructor identity differs across JS realms
  (under jsdom + Node fetch, an empty 200 throws a Node-realm `SyntaxError` that
  fails the jsdom-realm `instanceof` check; the same is true in browsers when the
  Response originates from a service worker / iframe). Name comparison is realm-
  agnostic. With this in place, empty 200 handlers can return `new HttpResponse()`
  again (closer to v1's `res(ctx.status(200))`) instead of the `HttpResponse.json({})`
  workaround.

- Drop `URL` / `URLSearchParams` from the env.ts polyfill list. jsdom already
  provides browser-spec versions, and Node's `URL.createObjectURL` only accepts
  Node-realm `Blob` — replacing it broke the "from computer" upload path in
  `LogoInput.tsx`. MSW v2's interceptor doesn't require these to come from Node.

env.ts comments restructured: all polyfill rationale lives in one top-of-file block
so the body is short and the trade-offs are documented in one place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(tests): switch content-type-builder jest env to shared polyfilled env

`aiClient.test.ts` constructs `new Response(...)` which jsdom does not provide
spec-compliantly. Align CTB with the other admin test suites by using
`@strapi/admin-test-utils/environment`, which polyfills Node's
`fetch`/`Request`/`Response`/streams into the jsdom global.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(tests): make msw v2 + undici body + jsdom realms work together

Three regressions surfaced by running the full front test suite under
jsdom + Node's undici fetch polyfill:

1. `TypeError: Body is unusable: Body has already been read` in every
   handler doing `await request.json()`. MSW v2's `RequestHandler.run()`
   calls `request.clone()` before invoking the resolver (to keep a copy
   for post-hoc logging). Under Node's undici, `Request.clone()` tees the
   underlying `ReadableStream` and locks the original body, so the
   resolver's `.json()` throws. Fix in `environment.ts`: wrap the global
   `Request` constructor to stash the stringified body on every instance
   and patch `Request.prototype.json` / `.text` to return the stash when
   present. Handlers now get the body regardless of how many times msw
   clones internally.

2. `expect.any(Array)` and `toStrictEqual` failing with "serializes to
   the same string" against msw response bodies. `Response.prototype.json`
   runs Node's `JSON.parse`, so the resulting objects carry Node-realm
   `Object`/`Array` prototypes; jsdom's `instanceof`/strict-equality
   matchers reject them. Patch `Response.prototype.json` to parse with
   the jsdom-realm `JSON`.

3. `useWidgets > should handle network errors gracefully` expected the
   toast text "Network error", which msw v1's `res.networkError('Network
   error')` surfaced verbatim. v2's `HttpResponse.error()` drops the
   custom message and fetch throws `TypeError: Failed to fetch`; update
   the assertion accordingly.

Also: `UIDInput` uses `jest.useFakeTimers()`. Adding `doNotFake:
['queueMicrotask', 'setImmediate']` keeps per-test runtime at ~1s
instead of ~10s (plain fake timers stall undici's internal microtasks
between request emission and handler resolution), and an `afterEach`
restores real timers so a failing test cannot leak fake timers into
the next one.

Verified with `nx run-many --target=test:front --parallel=1` across all
12 projects — all suites green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(admin): assert toast container in Widgets error tests

Replace text-match (`findByText('Server error' | 'Failed to fetch')`) with
`[data-sonner-toast]` container assertion. Decouples the test from toast
copy and from msw v1/v2 network-error message differences.

Addresses @jhoward1994's review comment on PR #26065.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(admin): assert toast text, scope msw handlers, use jsdom env

- Widgets tests: match actual toast text (Server error / fetch failure
  regex) instead of data-sonner-toast container.
- ConfirmBulkActionDialog: mark msw runtime handlers { once: true } so
  they do not leak across cases.
- content-type-builder: jest testEnvironment back to jsdom.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(tests): split jest env patches into modules

Refactor packages/admin-test-utils/src/environment.ts by extracting
the msw v2 + undici body + jsdom realm shims into dedicated modules
under src/patches/ (node-globals, request-body-stash,
response-json-realm, types).

Co-Authored-By: Jamie Howard <jhoward1994@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 08:45:04 +00:00
Simen 7f4c68c6b9 fix(admin): handle 204 no-content response in fetch client (#25416) 2026-05-08 15:11:32 +00:00
Simon Norris 216344ecf8 Merge branch 'develop' into feature/button-remove-trial-banner 2026-05-07 17:52:42 +02:00
e907cd111b fix(database): morph typeField wins over same-name fields in populate (#26120)
* chore: remove early exit for morph relation types

* fix: issues with creating morphToOne relations

* chore: add tests

* test: add polymorphic relations tests

* fix(database): let morph typeField win over same-named target fields in populate

morphToOne and morphToMany: merge target row first, then set typeField (__type or custom)
so the polymorphic target UID is authoritative

* chore: fix ts

* docs: add contributor doc for polymorphic relations (#26121)

* test: apply morph to one

---------

Co-authored-by: Boaz Poolman <boaz_skater@hotmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-07 16:42:49 +02:00
Simon Norris 49951e0633 Merge branch 'develop' into feature/button-remove-trial-banner 2026-05-07 11:04:44 +02:00
Simon Norris e696d94627 chore: adding translations for the banner
Adding "close" translations for the Upsell Banner
2026-05-07 10:30:58 +02:00
Simon Norris f04fe97a75 feat: getting that button to stick while the banner doesn't
The space left by the banner when closed bothered Mathilde, so I've
removed it and got the button to stick in the top right still!
2026-05-06 20:39:22 +02:00
Bassel17 c5bc749fee release: 5.45.0 2026-05-06 10:06:46 +00:00
Dominik JurigaandZiyi 86fe764f4f feat: sort based on publish status (#25689)
* feat: sort based on publish status

* chore: remove redundant `any` type assertions

* fix: override sort if `status` filter is present

* fix(content-manager): status sort ignored hasPublishedVersion and publicationStatusFilter

* fix(utils): remove unused STATUS_ATTRIBUTE constant

* fix(content-manager): missing deps in useEffect for status sort cleanup

---------

Co-authored-by: Ziyi <daydreamnation@live.com>
2026-05-04 13:19:13 +02:00
Ben Irvin 63276b515b fix(admin): type addMenuLink with optional Component for menu-only links (#26198) 2026-05-04 11:54:21 +02:00
Andrei LandBassel Kanso 90623baa6f fix(admin): clean up lazy component registration warnings (#25015)
* fix(admin): don't warn when Component is missing in addMenuLink/addSettingsLink

* fix: add some missing StrapiApp types

* fix(admin): clean up lazy component registrations

---------

Co-authored-by: Bassel Kanso <basselkanso82@gmail.com>
2026-04-30 16:27:48 +03:00
Ziyi fa6299100d feat(content-manager): add Zod 4 foundation utilities (#25574) 2026-04-30 14:55:04 +02:00
Adrien L 8156393f8f Merge pull request #26170 from strapi/main 2026-04-30 14:28:15 +02:00
guoyangzhenandAdrien Lepoutre 36b6d68198 fix: prevent trailing ? in URL when params is empty object (#25724) (#25900)
Co-authored-by: Adrien Lepoutre <3693028+Adzouz@users.noreply.github.com>
2026-04-30 09:29:38 +02:00
Nico André 52b8fd9e3d feat(admin): api token supports admin permissions and admin user ownership (#25657) 2026-04-29 17:57:36 +02:00
Adzouz 11554fe43e release: 5.44.0 2026-04-29 13:06:31 +00:00
Simon Norris 59498861f7 fix: using isValid & adding translations
Using isValid from date-fns to check the validity of the date & adding
translations
2026-04-28 16:47:35 +02:00
Simon Norris c5396f1c18 fix: making button float better
Updating Collapsed button CS to work better
2026-04-28 15:10:36 +02:00
Simon Norris e004e4800f Merge remote-tracking branch 'origin' into feature/button-remove-trial-banner 2026-04-28 13:06:00 +02:00
akash-dabhi-qedandAdrien Lepoutre 4d3719a327 fix: contain absolute descendants in OverflowingItem (#26133)
Co-authored-by: Adrien Lepoutre <3693028+Adzouz@users.noreply.github.com>
2026-04-28 11:50:23 +02:00