From 80b1fcf2af43ed61cbc1b2d098cadcc0eee50c5d Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 11:26:31 -0500 Subject: [PATCH 01/10] Updated pnpm package age excludes to allow tryghost (#28314) no ref We do not need to block our own releases for security reasons. --- pnpm-workspace.yaml | 50 ++------------------------------------------- 1 file changed, 2 insertions(+), 48 deletions(-) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4623031b7ba..d266783c1a7 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -166,51 +166,5 @@ packageExtensions: dependencies: lodash: ^4.18.0 minimumReleaseAgeExclude: - # Intentional same-day NQL release required for relative date parsing - - "@tryghost/mongo-knex@0.9.5" - - "@tryghost/mongo-utils@0.6.4" - - "@tryghost/nql-lang@0.6.5" - - "@tryghost/nql@0.12.11" - # Framework release for api-framework update - - "@tryghost/api-framework@3.2.3" - - "@tryghost/debug@2.2.2" - - "@tryghost/promise@2.2.2" - - "@tryghost/root-utils@2.2.2" - - "@tryghost/tpl@2.2.2" - - "@tryghost/validator@3.1.3" - # Renovate security update: @number-flow/react@0.6.0 - - "@number-flow/react@0.6.0" - # Renovate security update: @aws-sdk/client-s3@3.1053.0 - - "@aws-sdk/client-s3@3.1053.0" - # Renovate security update: @vitest/coverage-v8@4.1.7 - - "@vitest/coverage-v8@4.1.7" - # Renovate security update: vitest@4.1.7 - - vitest@4.1.7 - # Renovate security update: @hookform/resolvers@5.4.0 - - "@hookform/resolvers@5.4.0" - # Renovate security update: @types/node@22.19.19 - - "@types/node@22.19.19" - # Renovate security update: @types/react@18.3.29 - - "@types/react@18.3.29" - # Renovate security update: @playwright/test@1.60.0 - - "@playwright/test@1.60.0" - # Renovate security update: tmp@0.2.6 - - tmp@0.2.6 - # Koenig editor release for klipy GIF provider migration - - "@tryghost/html-to-mobiledoc@3.3.2" - - "@tryghost/kg-card-factory@5.2.2" - - "@tryghost/kg-clean-basic-html@4.3.2" - - "@tryghost/kg-converters@1.2.2" - - "@tryghost/kg-default-atoms@5.2.2" - - "@tryghost/kg-default-cards@10.3.2" - - "@tryghost/kg-default-nodes@2.1.2" - - "@tryghost/kg-default-transforms@1.3.2" - - "@tryghost/kg-html-to-lexical@1.3.2" - - "@tryghost/kg-lexical-html-renderer@1.4.2" - - "@tryghost/kg-markdown-html-renderer@7.2.2" - - "@tryghost/kg-mobiledoc-html-renderer@7.2.2" - - "@tryghost/kg-parser-plugins@4.3.2" - - "@tryghost/kg-simplemde@3.1.2" - - "@tryghost/kg-unsplash-selector@0.4.2" - - "@tryghost/kg-utils@1.1.2" - - "@tryghost/koenig-lexical@1.8.2" + # Our own packages are published by us, so the release-age delay doesn't apply + - "@tryghost/*" From ed5f11d64276c5e0556c970de47dd4367be38da7 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 14:01:17 -0500 Subject: [PATCH 02/10] Cleaned up ghost/core's zod dependency to use the catalog (#28320) no ref ghost/core pinned `zod` inline at 4.1.12, which is exactly the catalog value. With `catalogMode: strict`, every other zod consumer already references the catalog; pointing ghost/core at `catalog:` keeps the version single-sourced. --- ghost/core/package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ghost/core/package.json b/ghost/core/package.json index ac52c797263..16560e90154 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -239,7 +239,7 @@ "type-fest": "catalog:", "ua-parser-js": "1.0.41", "xml": "1.0.1", - "zod": "4.1.12" + "zod": "catalog:" }, "overrides": { "lodash.template": "4.5.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 218e6ace6e1..38b3f83526f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2678,7 +2678,7 @@ importers: specifier: 1.0.1 version: 1.0.1 zod: - specifier: 4.1.12 + specifier: 'catalog:' version: 4.1.12 devDependencies: '@actions/core': From 6081172a311436a0acada8885cdfce440eb275c1 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 14:14:03 -0500 Subject: [PATCH 03/10] Converged eslint-plugin-react-hooks and catalogued the tailwindcss plugin split (#28319) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no ref Two ESLint plugins were drifting: - `eslint-plugin-react-hooks` was 5.2.0 in admin but 4.6.2 in 7 other React apps by accident. Unified everyone on 5.2.0 via the catalog. No new lint errors surface; the few `exhaustive-deps` warnings already exist on `main` under 4.6.2. - `eslint-plugin-tailwindcss` tracks the Tailwind v4/v3 lane split, so it's moved into the catalog (4.0.0-beta.0) and the `tailwind3` named catalog (3.18.2) to mirror `tailwindcss` itself — making the split intentional rather than incidental. --- apps/activitypub/package.json | 6 +-- apps/admin-x-design-system/package.json | 4 +- apps/admin-x-framework/package.json | 4 +- apps/admin-x-settings/package.json | 4 +- apps/admin/package.json | 4 +- apps/comments-ui/package.json | 2 +- apps/posts/package.json | 4 +- apps/shade/package.json | 4 +- apps/signup-form/package.json | 2 +- apps/stats/package.json | 4 +- pnpm-lock.yaml | 67 +++++++++++++------------ pnpm-workspace.yaml | 3 ++ 12 files changed, 57 insertions(+), 51 deletions(-) diff --git a/apps/activitypub/package.json b/apps/activitypub/package.json index 17beedf95be..66b9d0087e6 100644 --- a/apps/activitypub/package.json +++ b/apps/activitypub/package.json @@ -1,6 +1,6 @@ { "name": "@tryghost/activitypub", - "version": "3.1.30", + "version": "3.1.31", "license": "MIT", "repository": { "type": "git", @@ -43,9 +43,9 @@ "@types/react": "catalog:", "@types/react-dom": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "jest": "29.7.0", "jsdom": "catalog:", "tailwindcss": "catalog:", diff --git a/apps/admin-x-design-system/package.json b/apps/admin-x-design-system/package.json index 7fe80999129..07fe7893e7d 100644 --- a/apps/admin-x-design-system/package.json +++ b/apps/admin-x-design-system/package.json @@ -44,9 +44,9 @@ "c8": "catalog:", "chai": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "glob": "catalog:", "jsdom": "catalog:", "lodash-es": "4.18.1", diff --git a/apps/admin-x-framework/package.json b/apps/admin-x-framework/package.json index 54254653521..69daf88262e 100644 --- a/apps/admin-x-framework/package.json +++ b/apps/admin-x-framework/package.json @@ -83,9 +83,9 @@ "@vitest/coverage-v8": "catalog:", "c8": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "glob": "catalog:", "jsdom": "catalog:", "msw": "catalog:", diff --git a/apps/admin-x-settings/package.json b/apps/admin-x-settings/package.json index 3fefc2287a4..e37f30e2a86 100644 --- a/apps/admin-x-settings/package.json +++ b/apps/admin-x-settings/package.json @@ -85,9 +85,9 @@ "@types/validator": "catalog:", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "jsdom": "catalog:", "tailwindcss": "catalog:", "vite": "catalog:", diff --git a/apps/admin/package.json b/apps/admin/package.json index ca75f79c280..5bff24bd335 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -38,9 +38,9 @@ "@vitejs/plugin-react-swc": "4.1.0", "eslint": "catalog:eslint9", "eslint-plugin-no-relative-import-paths": "1.6.1", - "eslint-plugin-react-hooks": "5.2.0", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "globals": "17.6.0", "jest-extended": "7.0.0", "jsdom": "catalog:", diff --git a/apps/comments-ui/package.json b/apps/comments-ui/package.json index 6a47ccb414d..f20d336ca46 100644 --- a/apps/comments-ui/package.json +++ b/apps/comments-ui/package.json @@ -73,7 +73,7 @@ "concurrently": "catalog:", "eslint": "catalog:", "eslint-plugin-i18next": "6.1.4", - "eslint-plugin-tailwindcss": "3.18.2", + "eslint-plugin-tailwindcss": "catalog:tailwind3", "jsdom": "catalog:", "moment": "2.30.1", "postcss": "catalog:", diff --git a/apps/posts/package.json b/apps/posts/package.json index e5331c1c9f7..f0e6d3bcbf4 100644 --- a/apps/posts/package.json +++ b/apps/posts/package.json @@ -48,9 +48,9 @@ "@types/validator": "catalog:", "@vitest/coverage-v8": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "jsdom": "catalog:", "msw": "catalog:", "tailwindcss": "catalog:", diff --git a/apps/shade/package.json b/apps/shade/package.json index fe3b604ce85..e7d671f96a0 100644 --- a/apps/shade/package.json +++ b/apps/shade/package.json @@ -94,10 +94,10 @@ "@vitest/coverage-v8": "catalog:", "c8": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", "eslint-plugin-storybook": "10.3.5", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "glob": "catalog:", "jsdom": "catalog:", "postcss": "catalog:", diff --git a/apps/signup-form/package.json b/apps/signup-form/package.json index 03330d789a7..5f3ed7682a2 100644 --- a/apps/signup-form/package.json +++ b/apps/signup-form/package.json @@ -47,7 +47,7 @@ "autoprefixer": "10.4.21", "concurrently": "catalog:", "eslint": "catalog:", - "eslint-plugin-tailwindcss": "3.18.2", + "eslint-plugin-tailwindcss": "catalog:tailwind3", "jsdom": "catalog:", "postcss": "catalog:", "postcss-import": "16.1.1", diff --git a/apps/stats/package.json b/apps/stats/package.json index 0b60d6d6f1c..6deca558134 100644 --- a/apps/stats/package.json +++ b/apps/stats/package.json @@ -47,9 +47,9 @@ "@vitest/coverage-v8": "catalog:", "dotenv": "catalog:", "eslint": "catalog:", - "eslint-plugin-react-hooks": "4.6.2", + "eslint-plugin-react-hooks": "catalog:", "eslint-plugin-react-refresh": "catalog:", - "eslint-plugin-tailwindcss": "4.0.0-beta.0", + "eslint-plugin-tailwindcss": "catalog:", "jsdom": "catalog:", "tailwindcss": "catalog:", "vite": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38b3f83526f..60a629d4dd8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,9 +132,15 @@ catalogs: eslint: specifier: 8.57.1 version: 8.57.1 + eslint-plugin-react-hooks: + specifier: 5.2.0 + version: 5.2.0 eslint-plugin-react-refresh: specifier: 0.5.2 version: 0.5.2 + eslint-plugin-tailwindcss: + specifier: 4.0.0-beta.0 + version: 4.0.0-beta.0 fs-extra: specifier: 11.3.5 version: 11.3.5 @@ -215,6 +221,9 @@ catalogs: specifier: 9.37.0 version: 9.37.0 tailwind3: + eslint-plugin-tailwindcss: + specifier: 3.18.2 + version: 3.18.2 tailwindcss: specifier: 3.4.18 version: 3.4.18 @@ -396,13 +405,13 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) jest: specifier: 29.7.0 @@ -493,13 +502,13 @@ importers: specifier: 1.6.1 version: 1.6.1 eslint-plugin-react-hooks: - specifier: 5.2.0 + specifier: 'catalog:' version: 5.2.0(eslint@9.37.0(jiti@2.7.0)) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@9.37.0(jiti@2.7.0)) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) globals: specifier: 17.6.0 @@ -675,13 +684,13 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) glob: specifier: 'catalog:' @@ -796,13 +805,13 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) glob: specifier: 'catalog:' @@ -965,13 +974,13 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) jsdom: specifier: 'catalog:' @@ -1111,7 +1120,7 @@ importers: specifier: 6.1.4 version: 6.1.4 eslint-plugin-tailwindcss: - specifier: 3.18.2 + specifier: catalog:tailwind3 version: 3.18.2(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.9.0)) jsdom: specifier: 'catalog:' @@ -1311,13 +1320,13 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) jsdom: specifier: 'catalog:' @@ -1498,8 +1507,8 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) @@ -1507,7 +1516,7 @@ importers: specifier: 10.3.5 version: 10.3.5(eslint@8.57.1)(storybook@10.3.5(@testing-library/dom@9.3.4)(prettier@3.8.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.9.3) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) glob: specifier: 'catalog:' @@ -1598,7 +1607,7 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-tailwindcss: - specifier: 3.18.2 + specifier: catalog:tailwind3 version: 3.18.2(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.9.0)) jsdom: specifier: 'catalog:' @@ -1744,13 +1753,13 @@ importers: specifier: 'catalog:' version: 8.57.1 eslint-plugin-react-hooks: - specifier: 4.6.2 - version: 4.6.2(eslint@8.57.1) + specifier: 'catalog:' + version: 5.2.0(eslint@8.57.1) eslint-plugin-react-refresh: specifier: 'catalog:' version: 0.5.2(eslint@8.57.1) eslint-plugin-tailwindcss: - specifier: 4.0.0-beta.0 + specifier: 'catalog:' version: 4.0.0-beta.0(tailwindcss@4.2.2) jsdom: specifier: 'catalog:' @@ -13540,12 +13549,6 @@ packages: peerDependencies: eslint: '>=8.40.0' - eslint-plugin-react-hooks@4.6.2: - resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - eslint-plugin-react-hooks@5.2.0: resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} engines: {node: '>=10'} @@ -35989,7 +35992,7 @@ snapshots: eslint: 8.57.1 globals: 17.6.0 - eslint-plugin-react-hooks@4.6.2(eslint@8.57.1): + eslint-plugin-react-hooks@5.2.0(eslint@8.57.1): dependencies: eslint: 8.57.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d266783c1a7..c838440ee1a 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -68,7 +68,9 @@ catalog: dompurify: 3.4.5 dotenv: 17.4.2 eslint: 8.57.1 + eslint-plugin-react-hooks: 5.2.0 eslint-plugin-react-refresh: 0.5.2 + eslint-plugin-tailwindcss: 4.0.0-beta.0 fs-extra: 11.3.5 glob: 13.0.6 jsdom: 29.1.1 @@ -100,6 +102,7 @@ catalogs: eslint: 9.37.0 tailwind3: tailwindcss: 3.4.18 + eslint-plugin-tailwindcss: 3.18.2 overrides: '@tryghost/errors': ^1.3.7 From cb07c8fa0eb3bbd89c0f56e6a1adfdebaffe9cc6 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 14:14:20 -0500 Subject: [PATCH 04/10] Converged @testing-library/jest-dom onto a single catalog version (#28318) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no ref `@testing-library/jest-dom` was split between 6.9.1 (5 apps) and 5.17.0 (admin-x-framework, comments-ui, sodo-search), with nothing holding them together. Adds it to the catalog at 6.9.1 and points every consumer at `catalog:`, bumping the three laggards and preventing future drift. sodo-search's test setup used the v5 `import matchers … expect.extend(matchers)` pattern that v6 removed, so it's switched to the `@testing-library/jest-dom/vitest` import already used by posts/admin-x-settings. --- apps/admin-x-framework/package.json | 2 +- apps/admin-x-settings/package.json | 2 +- apps/admin/package.json | 2 +- apps/comments-ui/package.json | 2 +- apps/portal/package.json | 2 +- apps/posts/package.json | 2 +- apps/sodo-search/package.json | 4 +- apps/sodo-search/test/setup-tests.js | 10 +- apps/stats/package.json | 2 +- pnpm-lock.yaml | 166 +++------------------------ pnpm-workspace.yaml | 1 + 11 files changed, 28 insertions(+), 167 deletions(-) diff --git a/apps/admin-x-framework/package.json b/apps/admin-x-framework/package.json index 69daf88262e..ea33f3ab4c2 100644 --- a/apps/admin-x-framework/package.json +++ b/apps/admin-x-framework/package.json @@ -74,7 +74,7 @@ ], "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/jest-dom": "5.17.0", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "14.3.1", "@tryghost/koenig-lexical": "catalog:", "@types/react": "catalog:", diff --git a/apps/admin-x-settings/package.json b/apps/admin-x-settings/package.json index e37f30e2a86..42494f9ce6d 100644 --- a/apps/admin-x-settings/package.json +++ b/apps/admin-x-settings/package.json @@ -73,7 +73,7 @@ }, "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/jest-dom": "6.9.1", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "14.3.1", "@tryghost/admin-x-design-system": "workspace:*", "@tryghost/admin-x-framework": "workspace:*", diff --git a/apps/admin/package.json b/apps/admin/package.json index 5bff24bd335..3b4db33af37 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -30,7 +30,7 @@ "@eslint/js": "catalog:eslint9", "@tailwindcss/vite": "catalog:", "@tanstack/react-query": "catalog:", - "@testing-library/jest-dom": "6.9.1", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "14.3.1", "@types/node": "catalog:", "@types/react": "catalog:", diff --git a/apps/comments-ui/package.json b/apps/comments-ui/package.json index f20d336ca46..b88d87dfd6a 100644 --- a/apps/comments-ui/package.json +++ b/apps/comments-ui/package.json @@ -62,7 +62,7 @@ }, "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/jest-dom": "5.17.0", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "12.1.5", "@tryghost/i18n": "workspace:*", "@tryghost/nql": "catalog:", diff --git a/apps/portal/package.json b/apps/portal/package.json index 9ec247d8a71..e259403d2bb 100644 --- a/apps/portal/package.json +++ b/apps/portal/package.json @@ -111,7 +111,7 @@ "devDependencies": { "@doist/react-interpolate": "2.2.2", "@sentry/react": "catalog:", - "@testing-library/jest-dom": "6.9.1", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "12.1.5", "@testing-library/user-event": "14.6.1", "@tryghost/i18n": "workspace:*", diff --git a/apps/posts/package.json b/apps/posts/package.json index f0e6d3bcbf4..3c0a695f5f8 100644 --- a/apps/posts/package.json +++ b/apps/posts/package.json @@ -40,7 +40,7 @@ "@playwright/test": "catalog:", "@tanstack/react-query": "catalog:", "@tanstack/react-virtual": "3.13.25", - "@testing-library/jest-dom": "6.9.1", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "14.3.1", "@types/jest": "catalog:", "@types/papaparse": "5.5.2", diff --git a/apps/sodo-search/package.json b/apps/sodo-search/package.json index e6ad60ae069..b21f6d2cc4b 100644 --- a/apps/sodo-search/package.json +++ b/apps/sodo-search/package.json @@ -1,6 +1,6 @@ { "name": "@tryghost/sodo-search", - "version": "1.8.21", + "version": "1.8.22", "license": "MIT", "repository": "https://github.com/TryGhost/Ghost", "author": "Ghost Foundation", @@ -93,7 +93,7 @@ ] }, "devDependencies": { - "@testing-library/jest-dom": "5.17.0", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "12.1.5", "@vitejs/plugin-react": "catalog:", "@vitest/coverage-v8": "catalog:", diff --git a/apps/sodo-search/test/setup-tests.js b/apps/sodo-search/test/setup-tests.js index d83569430b4..0e60c4021f6 100644 --- a/apps/sodo-search/test/setup-tests.js +++ b/apps/sodo-search/test/setup-tests.js @@ -1,5 +1,5 @@ -import matchers from '@testing-library/jest-dom/matchers'; -import {afterEach, expect} from 'vitest'; +import '@testing-library/jest-dom/vitest'; +import {afterEach} from 'vitest'; import {cleanup} from '@testing-library/react'; import {fetch} from 'cross-fetch'; @@ -13,8 +13,6 @@ globalThis.fetch = fetch; // Add the cleanup function for React testing library afterEach(cleanup); -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) +// jest-dom (imported above as /vitest) registers custom matchers for asserting +// on DOM nodes, e.g. expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom -expect.extend(matchers); diff --git a/apps/stats/package.json b/apps/stats/package.json index 6deca558134..a097b4aa8bd 100644 --- a/apps/stats/package.json +++ b/apps/stats/package.json @@ -38,7 +38,7 @@ }, "devDependencies": { "@faker-js/faker": "9.9.0", - "@testing-library/jest-dom": "6.9.1", + "@testing-library/jest-dom": "catalog:", "@testing-library/react": "14.3.1", "@types/jest": "catalog:", "@types/node": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60a629d4dd8..4aed288c3f1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,6 +33,9 @@ catalogs: '@tanstack/react-query': specifier: 4.44.0 version: 4.44.0 + '@testing-library/jest-dom': + specifier: 6.9.1 + version: 6.9.1 '@tryghost/api-framework': specifier: 3.2.3 version: 3.2.3 @@ -478,7 +481,7 @@ importers: specifier: 'catalog:' version: 4.44.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/jest-dom': - specifier: 6.9.1 + specifier: 'catalog:' version: 6.9.1 '@testing-library/react': specifier: 14.3.1 @@ -778,8 +781,8 @@ importers: specifier: 'catalog:' version: 1.60.0 '@testing-library/jest-dom': - specifier: 5.17.0 - version: 5.17.0 + specifier: 'catalog:' + version: 6.9.1 '@testing-library/react': specifier: 14.3.1 version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -938,7 +941,7 @@ importers: specifier: 'catalog:' version: 1.60.0 '@testing-library/jest-dom': - specifier: 6.9.1 + specifier: 'catalog:' version: 6.9.1 '@testing-library/react': specifier: 14.3.1 @@ -1087,8 +1090,8 @@ importers: specifier: 'catalog:' version: 1.60.0 '@testing-library/jest-dom': - specifier: 5.17.0 - version: 5.17.0 + specifier: 'catalog:' + version: 6.9.1 '@testing-library/react': specifier: 12.1.5 version: 12.1.5(@types/react@18.3.29)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -1163,7 +1166,7 @@ importers: specifier: 'catalog:' version: 7.120.4(react@17.0.2) '@testing-library/jest-dom': - specifier: 6.9.1 + specifier: 'catalog:' version: 6.9.1 '@testing-library/react': specifier: 12.1.5 @@ -1296,7 +1299,7 @@ importers: specifier: 3.13.25 version: 3.13.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/jest-dom': - specifier: 6.9.1 + specifier: 'catalog:' version: 6.9.1 '@testing-library/react': specifier: 14.3.1 @@ -1653,8 +1656,8 @@ importers: version: 17.0.2(react@17.0.2) devDependencies: '@testing-library/jest-dom': - specifier: 5.17.0 - version: 5.17.0 + specifier: 'catalog:' + version: 6.9.1 '@testing-library/react': specifier: 12.1.5 version: 12.1.5(@types/react@18.3.29)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -1726,7 +1729,7 @@ importers: specifier: 9.9.0 version: 9.9.0 '@testing-library/jest-dom': - specifier: 6.9.1 + specifier: 'catalog:' version: 6.9.1 '@testing-library/react': specifier: 14.3.1 @@ -5247,10 +5250,6 @@ packages: resolution: {integrity: sha512-j0+W5iQQ8hBh7tHZkTQv3q2Fh/M7Je72cIsYqC4OaktgtO7v1So9UTjp6uPBHIaB6beoF/RRsCgMJKvti0wADA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/expect-utils@30.4.1': - resolution: {integrity: sha512-ZBn5CglH8fBsQsvs4VWNzD4aWfUYks+IdOOQU3MEK71ol/BcVm+P+rtb1KpiFBpSWSCE27uOahyyf1vfqOVbcQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/expect@29.7.0': resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -5275,10 +5274,6 @@ packages: resolution: {integrity: sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/pattern@30.4.0': - resolution: {integrity: sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/reporters@29.7.0': resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -5332,10 +5327,6 @@ packages: resolution: {integrity: sha512-JHm87k7bA33hpBngtU8h6UBub/fqqA9uXfw+21j5Hmk7ooPHlboRNxHq0JcMtC+n8VJGP1mcfnD3Mk+XKe1oSw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jest/types@30.4.1': - resolution: {integrity: sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0': resolution: {integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==} peerDependencies: @@ -8331,10 +8322,6 @@ packages: resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} engines: {node: '>=14'} - '@testing-library/jest-dom@5.17.0': - resolution: {integrity: sha512-ynmNeT7asXyH3aSVv4vvX4Rb+0qjOhdNHnO/3vuZNqPmhDpV/+rCSGwQ7bLcmU2cJ4dvoheIO85LQj0IbJHEtg==} - engines: {node: '>=8', npm: '>=6', yarn: '>=1'} - '@testing-library/jest-dom@6.9.1': resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} @@ -8988,9 +8975,6 @@ packages: '@types/jest@29.5.14': resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - '@types/jest@30.0.0': - resolution: {integrity: sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==} - '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} @@ -9181,9 +9165,6 @@ packages: '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} - '@types/testing-library__jest-dom@5.14.9': - resolution: {integrity: sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw==} - '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} @@ -11085,10 +11066,6 @@ packages: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} - chalk@3.0.0: - resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} - engines: {node: '>=8'} - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -13807,10 +13784,6 @@ packages: resolution: {integrity: sha512-1zQrciTiQfRdo7qJM1uG4navm8DayFa2TgCSRlzUyNkhcJ6XUZF3hjnpkyr3VhAqPH7i/9GkG7Tv5abz6fqz0Q==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - expect@30.4.1: - resolution: {integrity: sha512-PMARsyh/JtqC20HoGqlFcIlQAyqUtW4PlI1rup1uhYJtKuwAjbvWi3GQMAn+STdHum/dk8xrKfUM1+5SAwpolA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - exponential-backoff@3.1.3: resolution: {integrity: sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==} @@ -15651,10 +15624,6 @@ packages: resolution: {integrity: sha512-HEtc9uFQgaUHkC7nLSlQL3Tph4Pjxt/yiPvkIrrDCt9jhoLIgxaubo1G+CFOnmHYMxHwwdaSN7mkIFs6ZK8OhA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-matcher-utils@30.4.1: - resolution: {integrity: sha512-zvYfX5CaeEkFrrLS9suWe9rvJrm9J1Iv3ua8kIBv9GEPzcnsfBf0bob37la7s67fs0nlBC3EuvkOLnXQKxtx4A==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-message-util@29.7.0: resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -15663,10 +15632,6 @@ packages: resolution: {integrity: sha512-Z/j4Bo+4ySJ+JPJN3b2Qbl9hDq3VrXmnjjGEWD/x0BCXeOXPTV1iZYYzl2X8c1MaCOL+ewMyNBcm88sboE6YWw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-message-util@30.4.1: - resolution: {integrity: sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-mock@29.7.0: resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -15675,10 +15640,6 @@ packages: resolution: {integrity: sha512-OTzICK8CpE+t4ndhKrwlIdbM6Pn8j00lvmSmq5ejiO+KxukbLjgOflKWMn3KE34EZdQm5RqTuKj+5RIEniYhog==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-mock@30.4.1: - resolution: {integrity: sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-pnp-resolver@1.2.3: resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} engines: {node: '>=6'} @@ -15696,10 +15657,6 @@ packages: resolution: {integrity: sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-regex-util@30.4.0: - resolution: {integrity: sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-resolve-dependencies@29.7.0: resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -15732,10 +15689,6 @@ packages: resolution: {integrity: sha512-/jZDa00a3Sz7rdyu55NLrQCIrbyIkbBxareejQI315f/i8HjYN+ZWsDLLpoQSiUIEIyZF/R8fDg3BmB8AtHttg==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-util@30.4.1: - resolution: {integrity: sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - jest-validate@29.7.0: resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -24840,10 +24793,6 @@ snapshots: dependencies: '@jest/get-type': 30.1.0 - '@jest/expect-utils@30.4.1': - dependencies: - '@jest/get-type': 30.1.0 - '@jest/expect@29.7.0': dependencies: expect: 29.7.0 @@ -24883,11 +24832,6 @@ snapshots: '@types/node': 25.9.1 jest-regex-util: 30.0.1 - '@jest/pattern@30.4.0': - dependencies: - '@types/node': 25.9.1 - jest-regex-util: 30.4.0 - '@jest/reporters@29.7.0(node-notifier@10.0.1)': dependencies: '@bcoe/v8-coverage': 0.2.3 @@ -25016,16 +24960,6 @@ snapshots: '@types/yargs': 17.0.35 chalk: 4.1.2 - '@jest/types@30.4.1': - dependencies: - '@jest/pattern': 30.4.0 - '@jest/schemas': 30.4.1 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 25.9.1 - '@types/yargs': 17.0.35 - chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@5.9.3)(vite@7.3.2(@types/node@22.19.19)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.9.0))': dependencies: glob: 13.0.6 @@ -28207,18 +28141,6 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@5.17.0': - dependencies: - '@adobe/css-tools': 4.5.0 - '@babel/runtime': 7.29.7 - '@types/testing-library__jest-dom': 5.14.9 - aria-query: 5.3.2 - chalk: 3.0.0 - css.escape: 1.5.1 - dom-accessibility-api: 0.5.16 - lodash: 4.18.1 - redent: 3.0.0 - '@testing-library/jest-dom@6.9.1': dependencies: '@adobe/css-tools': 4.5.0 @@ -29375,11 +29297,6 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 - '@types/jest@30.0.0': - dependencies: - expect: 30.4.1 - pretty-format: 30.4.1 - '@types/js-yaml@4.0.9': {} '@types/jsdom@28.0.3': @@ -29593,10 +29510,6 @@ snapshots: dependencies: '@types/node': 25.9.1 - '@types/testing-library__jest-dom@5.14.9': - dependencies: - '@types/jest': 30.0.0 - '@types/tough-cookie@4.0.5': {} '@types/trusted-types@2.0.7': @@ -32619,11 +32532,6 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 5.5.0 - chalk@3.0.0: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -36413,15 +36321,6 @@ snapshots: jest-mock: 30.3.0 jest-util: 30.3.0 - expect@30.4.1: - dependencies: - '@jest/expect-utils': 30.4.1 - '@jest/get-type': 30.1.0 - jest-matcher-utils: 30.4.1 - jest-message-util: 30.4.1 - jest-mock: 30.4.1 - jest-util: 30.4.1 - exponential-backoff@3.1.3: {} express-brute@1.0.1(express@4.22.2): @@ -38802,13 +38701,6 @@ snapshots: jest-diff: 30.3.0 pretty-format: 30.3.0 - jest-matcher-utils@30.4.1: - dependencies: - '@jest/get-type': 30.1.0 - chalk: 4.1.2 - jest-diff: 30.4.1 - pretty-format: 30.4.1 - jest-message-util@29.7.0: dependencies: '@babel/code-frame': 7.29.7 @@ -38833,19 +38725,6 @@ snapshots: slash: 3.0.0 stack-utils: 2.0.6 - jest-message-util@30.4.1: - dependencies: - '@babel/code-frame': 7.29.7 - '@jest/types': 30.4.1 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-util: 30.4.1 - picomatch: 4.0.4 - pretty-format: 30.4.1 - slash: 3.0.0 - stack-utils: 2.0.6 - jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 @@ -38858,12 +38737,6 @@ snapshots: '@types/node': 25.9.1 jest-util: 30.3.0 - jest-mock@30.4.1: - dependencies: - '@jest/types': 30.4.1 - '@types/node': 25.9.1 - jest-util: 30.4.1 - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): optionalDependencies: jest-resolve: 29.7.0 @@ -38872,8 +38745,6 @@ snapshots: jest-regex-util@30.0.1: {} - jest-regex-util@30.4.0: {} - jest-resolve-dependencies@29.7.0: dependencies: jest-regex-util: 29.6.3 @@ -39015,15 +38886,6 @@ snapshots: graceful-fs: 4.2.11 picomatch: 4.0.4 - jest-util@30.4.1: - dependencies: - '@jest/types': 30.4.1 - '@types/node': 25.9.1 - chalk: 4.1.2 - ci-info: 4.4.0 - graceful-fs: 4.2.11 - picomatch: 4.0.4 - jest-validate@29.7.0: dependencies: '@jest/types': 29.6.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c838440ee1a..ea49b858041 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -34,6 +34,7 @@ catalog: '@tailwindcss/postcss': 4.2.2 '@tailwindcss/vite': 4.2.2 '@tanstack/react-query': 4.44.0 + '@testing-library/jest-dom': 6.9.1 '@tryghost/api-framework': 3.2.3 '@tryghost/color-utils': 0.2.18 '@tryghost/custom-fonts': 1.0.10 From 96118fb8d6d352fea3c8c684cabedeb66f6a5543 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Tue, 2 Jun 2026 20:33:31 +0100 Subject: [PATCH 05/10] Fixed IndexNow pinging /404/ for posts with no web URL (#28311) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IndexNow (behind the `indexnow` labs flag) pings `api.indexnow.org` when a post is published or edited, resolving the post URL via `urlService.facade.getUrlForResource(...)`. That returns a `/404/` URL when a published post is not owned by any route — e.g. an imported or members post that falls outside the site's collections, or a routing config with no catch-all. In that case the ping submitted `https:///404/` instead of a post URL. --- ghost/core/core/server/services/indexnow.js | 12 ++++++++++ .../unit/server/services/indexnow.test.js | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/ghost/core/core/server/services/indexnow.js b/ghost/core/core/server/services/indexnow.js index db839d8e11d..0e76fc9240a 100644 --- a/ghost/core/core/server/services/indexnow.js +++ b/ghost/core/core/server/services/indexnow.js @@ -89,6 +89,18 @@ async function ping(post) { try { url = urlService.facade.getUrlForResource({...post, type: 'posts'}, {absolute: true}); + if (!url || url.endsWith('/404/')) { + logging.warn({ + system: { + event: 'indexnow.unresolved_url', + post_id: post.id, + post_slug: post.slug, + url + } + }, `${INDEXNOW_LOG_KEY} Skipped ping - post has no resolvable URL`); + return; + } + // Get the API key (auto-generated on boot by settings service) const key = getApiKey(); if (!key) { diff --git a/ghost/core/test/unit/server/services/indexnow.test.js b/ghost/core/test/unit/server/services/indexnow.test.js index c39e40ce4d0..6bcd550dbec 100644 --- a/ghost/core/test/unit/server/services/indexnow.test.js +++ b/ghost/core/test/unit/server/services/indexnow.test.js @@ -251,6 +251,11 @@ describe('IndexNow', function () { describe('ping()', function () { const ping = indexnow.__get__('ping'); + let urlStub; + + beforeEach(function () { + urlStub = sinon.stub(urlService.facade, 'getUrlForResource').returns('https://example.com/my-post/'); + }); it('with a post should execute ping', async function () { loggingStub = sinon.stub(logging, 'info'); @@ -266,6 +271,25 @@ describe('IndexNow', function () { assert.equal(loggingStub.args[0][0].system.status_code, 200); }); + it('does not ping when the post has no resolvable URL (/404/)', async function () { + urlStub.returns('https://example.com/404/'); + loggingStub = sinon.stub(logging, 'warn'); + const pingRequest = nock('https://api.indexnow.org') + .get(/\/indexnow/) + .reply(200); + const testPost = _.clone(testUtils.DataGenerator.Content.posts[2]); + + await ping(testPost); + + assert.equal(pingRequest.isDone(), false); + sinon.assert.calledOnce(loggingStub); + const logged = loggingStub.args[0][0].system; + assert.equal(logged.event, 'indexnow.unresolved_url'); + assert.equal(logged.url, 'https://example.com/404/'); + assert.equal(logged.post_id, testPost.id); + assert.equal(logged.post_slug, testPost.slug); + }); + it('with default post should not execute ping', async function () { const pingRequest = nock('https://api.indexnow.org') .get(/\/indexnow/) From a8e9c0714dddbdb48b240ac8df8d99ec286392b5 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 14:41:28 -0500 Subject: [PATCH 06/10] Moved React version pins into the pnpm catalog (#28317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no ref The React 18 (admin) vs React 17 (public bundles) split was inlined across ~14 `package.json` files with nothing enforcing which lane held which version. ESLint and Tailwind already express their version splits through named catalogs (`eslint9`, `tailwind3`); React was the one core split that didn't. This adds `react`, `react-dom`, and `@testing-library/react` to the catalog plus a `react17` named catalog, and points every consumer at the right entry. The eventual React bump then becomes a single catalog decision instead of another chance to drift. This is a no-op for resolved versions — the lockfile diff only reshapes specifiers into catalog refs; no package resolution changes. `^18.2.0` peer ranges are intentionally left loose. --- apps/activitypub/package.json | 6 +- apps/admin-x-design-system/package.json | 6 +- apps/admin-x-framework/package.json | 6 +- apps/admin-x-settings/package.json | 6 +- apps/admin/package.json | 6 +- apps/announcement-bar/package.json | 4 +- apps/comments-ui/package.json | 6 +- apps/portal/package.json | 6 +- apps/posts/package.json | 6 +- apps/shade/package.json | 6 +- apps/signup-form/package.json | 4 +- apps/sodo-search/package.json | 6 +- apps/stats/package.json | 6 +- ghost/admin/package.json | 4 +- pnpm-lock.yaml | 97 +++++++++++++++---------- pnpm-workspace.yaml | 7 ++ 16 files changed, 104 insertions(+), 78 deletions(-) diff --git a/apps/activitypub/package.json b/apps/activitypub/package.json index 66b9d0087e6..adcc73f4289 100644 --- a/apps/activitypub/package.json +++ b/apps/activitypub/package.json @@ -38,7 +38,7 @@ }, "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@types/jest": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", @@ -87,8 +87,8 @@ "clsx": "catalog:", "dompurify": "catalog:", "html2canvas-objectfit-fix": "1.2.0", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "react-hook-form": "7.72.1", "react-router": "catalog:", "sonner": "catalog:", diff --git a/apps/admin-x-design-system/package.json b/apps/admin-x-design-system/package.json index 07fe7893e7d..96626193d82 100644 --- a/apps/admin-x-design-system/package.json +++ b/apps/admin-x-design-system/package.json @@ -32,7 +32,7 @@ "@storybook/addon-links": "catalog:", "@storybook/react-vite": "catalog:", "@tailwindcss/postcss": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@testing-library/react-hooks": "8.0.1", "@types/lodash-es": "4.17.12", "@types/react": "catalog:", @@ -52,8 +52,8 @@ "lodash-es": "4.18.1", "postcss": "catalog:", "postcss-import": "16.1.1", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "sinon": "catalog:", "storybook": "catalog:", "tailwindcss": "catalog:", diff --git a/apps/admin-x-framework/package.json b/apps/admin-x-framework/package.json index ea33f3ab4c2..9d2f68fd158 100644 --- a/apps/admin-x-framework/package.json +++ b/apps/admin-x-framework/package.json @@ -75,7 +75,7 @@ "devDependencies": { "@playwright/test": "catalog:", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@tryghost/koenig-lexical": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", @@ -104,8 +104,8 @@ "@tryghost/admin-x-design-system": "workspace:*", "@tryghost/shade": "workspace:*", "bson-objectid": "catalog:", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "react-hot-toast": "2.6.0", "react-router": "catalog:" }, diff --git a/apps/admin-x-settings/package.json b/apps/admin-x-settings/package.json index 42494f9ce6d..1d8e3d4cd58 100644 --- a/apps/admin-x-settings/package.json +++ b/apps/admin-x-settings/package.json @@ -64,8 +64,8 @@ "jszip": "3.10.1", "lucide-react": "catalog:", "mingo": "2.5.3", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "react-hot-toast": "2.6.0", "react-select": "5.10.2", "sonner": "catalog:", @@ -74,7 +74,7 @@ "devDependencies": { "@playwright/test": "catalog:", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@tryghost/admin-x-design-system": "workspace:*", "@tryghost/admin-x-framework": "workspace:*", "@tryghost/custom-fonts": "catalog:", diff --git a/apps/admin/package.json b/apps/admin/package.json index 3b4db33af37..f3c71f4cb33 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -22,8 +22,8 @@ "@tryghost/shade": "workspace:*", "@tryghost/stats": "workspace:*", "mingo": "2.5.3", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "zod": "catalog:" }, "devDependencies": { @@ -31,7 +31,7 @@ "@tailwindcss/vite": "catalog:", "@tanstack/react-query": "catalog:", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@types/node": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", diff --git a/apps/announcement-bar/package.json b/apps/announcement-bar/package.json index 2c9904b11c8..f928eabed65 100644 --- a/apps/announcement-bar/package.json +++ b/apps/announcement-bar/package.json @@ -14,8 +14,8 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "catalog:react17", + "react-dom": "catalog:react17" }, "scripts": { "dev": "concurrently --kill-others --names preview,build \"vite preview -l silent\" \"pnpm build:watch\"", diff --git a/apps/comments-ui/package.json b/apps/comments-ui/package.json index b88d87dfd6a..6526a6b6d5a 100644 --- a/apps/comments-ui/package.json +++ b/apps/comments-ui/package.json @@ -56,14 +56,14 @@ "@tiptap/pm": "2.26.3", "@tiptap/react": "2.26.3", "@tryghost/debug": "catalog:", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "catalog:react17", + "react-dom": "catalog:react17", "react-string-replace": "2.0.1" }, "devDependencies": { "@playwright/test": "catalog:", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "12.1.5", + "@testing-library/react": "catalog:react17", "@tryghost/i18n": "workspace:*", "@tryghost/nql": "catalog:", "@vitejs/plugin-react": "catalog:", diff --git a/apps/portal/package.json b/apps/portal/package.json index e259403d2bb..ad2fc682cdf 100644 --- a/apps/portal/package.json +++ b/apps/portal/package.json @@ -112,7 +112,7 @@ "@doist/react-interpolate": "2.2.2", "@sentry/react": "catalog:", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "12.1.5", + "@testing-library/react": "catalog:react17", "@testing-library/user-event": "14.6.1", "@tryghost/i18n": "workspace:*", "@typescript-eslint/eslint-plugin": "8.49.0", @@ -125,8 +125,8 @@ "eslint": "catalog:", "eslint-plugin-i18next": "6.1.4", "jsdom": "catalog:", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "catalog:react17", + "react-dom": "catalog:react17", "vite": "catalog:", "vite-plugin-css-injected-by-js": "3.5.2", "vite-plugin-svgr": "catalog:", diff --git a/apps/posts/package.json b/apps/posts/package.json index 3c0a695f5f8..791fec7d74a 100644 --- a/apps/posts/package.json +++ b/apps/posts/package.json @@ -41,7 +41,7 @@ "@tanstack/react-query": "catalog:", "@tanstack/react-virtual": "3.13.25", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@types/jest": "catalog:", "@types/papaparse": "5.5.2", "@types/react": "catalog:", @@ -70,8 +70,8 @@ "lucide-react": "catalog:", "moment-timezone": "0.5.45", "papaparse": "5.5.3", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "react-router": "catalog:", "sonner": "catalog:", "temporal-polyfill": "0.3.2", diff --git a/apps/shade/package.json b/apps/shade/package.json index e7d671f96a0..4cfee5f6bd2 100644 --- a/apps/shade/package.json +++ b/apps/shade/package.json @@ -86,7 +86,7 @@ "@storybook/addon-links": "catalog:", "@storybook/react-vite": "catalog:", "@tailwindcss/postcss": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@types/node": "catalog:", "@types/react-world-flags": "1.6.0", "@typescript-eslint/parser": "catalog:", @@ -143,9 +143,9 @@ "date-fns": "4.1.0", "lucide-react": "catalog:", "moment-timezone": "^0.5.48", - "react": "18.3.1", + "react": "catalog:", "react-day-picker": "9.14.0", - "react-dom": "18.3.1", + "react-dom": "catalog:", "react-dropzone": "14.2.3", "react-hook-form": "7.72.1", "react-world-flags": "1.6.0", diff --git a/apps/signup-form/package.json b/apps/signup-form/package.json index 5f3ed7682a2..66e5a3af2f4 100644 --- a/apps/signup-form/package.json +++ b/apps/signup-form/package.json @@ -31,8 +31,8 @@ }, "dependencies": { "@tryghost/debug": "catalog:", - "react": "18.3.1", - "react-dom": "18.3.1" + "react": "catalog:", + "react-dom": "catalog:" }, "devDependencies": { "@playwright/test": "catalog:", diff --git a/apps/sodo-search/package.json b/apps/sodo-search/package.json index b21f6d2cc4b..0d18fee69a8 100644 --- a/apps/sodo-search/package.json +++ b/apps/sodo-search/package.json @@ -17,8 +17,8 @@ "@tryghost/debug": "catalog:", "@tryghost/i18n": "workspace:*", "flexsearch": "0.8.212", - "react": "17.0.2", - "react-dom": "17.0.2" + "react": "catalog:react17", + "react-dom": "catalog:react17" }, "scripts": { "dev": "concurrently --kill-others --names preview,build,tailwind \"vite preview -l silent\" \"pnpm build:watch\" \"pnpm tailwind\"", @@ -94,7 +94,7 @@ }, "devDependencies": { "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "12.1.5", + "@testing-library/react": "catalog:react17", "@vitejs/plugin-react": "catalog:", "@vitest/coverage-v8": "catalog:", "concurrently": "catalog:", diff --git a/apps/stats/package.json b/apps/stats/package.json index a097b4aa8bd..86b193a4489 100644 --- a/apps/stats/package.json +++ b/apps/stats/package.json @@ -39,7 +39,7 @@ "devDependencies": { "@faker-js/faker": "9.9.0", "@testing-library/jest-dom": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@types/jest": "catalog:", "@types/node": "catalog:", "@types/react": "catalog:", @@ -63,8 +63,8 @@ "i18n-iso-countries": "7.14.0", "moment": "2.24.0", "moment-timezone": "0.5.45", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "react-svg-map": "2.2.0" }, "nx": { diff --git a/ghost/admin/package.json b/ghost/admin/package.json index 5e8a0bff3d0..ef6adb93830 100644 --- a/ghost/admin/package.json +++ b/ghost/admin/package.json @@ -138,8 +138,8 @@ "postcss-import": "12.0.1", "pretender": "3.4.7", "process": "0.11.10", - "react": "18.3.1", - "react-dom": "18.3.1", + "react": "catalog:", + "react-dom": "catalog:", "reframe.js": "4.0.2", "semver": "7.7.4", "sentry-testkit": "5.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4aed288c3f1..4b9c3d6e884 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,6 +36,9 @@ catalogs: '@testing-library/jest-dom': specifier: 6.9.1 version: 6.9.1 + '@testing-library/react': + specifier: 14.3.1 + version: 14.3.1 '@tryghost/api-framework': specifier: 3.2.3 version: 3.2.3 @@ -177,6 +180,12 @@ catalogs: preact: specifier: ^10.29.2 version: 10.29.2 + react: + specifier: 18.3.1 + version: 18.3.1 + react-dom: + specifier: 18.3.1 + version: 18.3.1 react-router: specifier: 7.14.0 version: 7.14.0 @@ -223,6 +232,16 @@ catalogs: eslint: specifier: 9.37.0 version: 9.37.0 + react17: + '@testing-library/react': + specifier: 12.1.5 + version: 12.1.5 + react: + specifier: 17.0.2 + version: 17.0.2 + react-dom: + specifier: 17.0.2 + version: 17.0.2 tailwind3: eslint-plugin-tailwindcss: specifier: 3.18.2 @@ -368,10 +387,10 @@ importers: specifier: 1.2.0 version: 1.2.0 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-hook-form: specifier: 7.72.1 @@ -393,7 +412,7 @@ importers: specifier: 'catalog:' version: 1.60.0 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: 'catalog:' @@ -462,10 +481,10 @@ importers: specifier: 2.5.3 version: 2.5.3 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) zod: specifier: 'catalog:' @@ -484,7 +503,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/node': specifier: 'catalog:' @@ -651,7 +670,7 @@ importers: specifier: 'catalog:' version: 4.2.2 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@testing-library/react-hooks': specifier: 8.0.1 @@ -711,10 +730,10 @@ importers: specifier: 16.1.1 version: 16.1.1(postcss@8.5.10) react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) sinon: specifier: 'catalog:' @@ -765,10 +784,10 @@ importers: specifier: 'catalog:' version: 2.0.4 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-hot-toast: specifier: 2.6.0 @@ -784,7 +803,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tryghost/koenig-lexical': specifier: 'catalog:' @@ -919,10 +938,10 @@ importers: specifier: 2.5.3 version: 2.5.3 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-hot-toast: specifier: 2.6.0 @@ -944,7 +963,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tryghost/admin-x-design-system': specifier: workspace:* @@ -1001,10 +1020,10 @@ importers: apps/announcement-bar: dependencies: react: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2 react-dom: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2(react@17.0.2) devDependencies: '@vitejs/plugin-react': @@ -1077,10 +1096,10 @@ importers: specifier: 'catalog:' version: 2.2.1 react: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2 react-dom: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2(react@17.0.2) react-string-replace: specifier: 2.0.1 @@ -1093,7 +1112,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 12.1.5 + specifier: catalog:react17 version: 12.1.5(@types/react@18.3.29)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@tryghost/i18n': specifier: workspace:* @@ -1169,7 +1188,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 12.1.5 + specifier: catalog:react17 version: 12.1.5(@types/react@18.3.29)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@testing-library/user-event': specifier: 14.6.1 @@ -1208,10 +1227,10 @@ importers: specifier: 'catalog:' version: 29.1.1(@noble/hashes@1.8.0) react: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2 react-dom: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2(react@17.0.2) vite: specifier: 'catalog:' @@ -1265,10 +1284,10 @@ importers: specifier: 5.5.3 version: 5.5.3 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-router: specifier: 'catalog:' @@ -1302,7 +1321,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: 'catalog:' @@ -1440,13 +1459,13 @@ importers: specifier: 0.5.45 version: 0.5.45 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-day-picker: specifier: 9.14.0 version: 9.14.0(react@18.3.1) react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-dropzone: specifier: 14.2.3 @@ -1486,7 +1505,7 @@ importers: specifier: 'catalog:' version: 4.2.2 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/node': specifier: 'catalog:' @@ -1567,10 +1586,10 @@ importers: specifier: 'catalog:' version: 2.2.1 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) devDependencies: '@playwright/test': @@ -1649,17 +1668,17 @@ importers: specifier: 0.8.212 version: 0.8.212 react: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2 react-dom: - specifier: 17.0.2 + specifier: catalog:react17 version: 17.0.2(react@17.0.2) devDependencies: '@testing-library/jest-dom': specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 12.1.5 + specifier: catalog:react17 version: 12.1.5(@types/react@18.3.29)(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@vitejs/plugin-react': specifier: 'catalog:' @@ -1716,10 +1735,10 @@ importers: specifier: 0.5.45 version: 0.5.45 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-svg-map: specifier: 2.2.0 @@ -1732,7 +1751,7 @@ importers: specifier: 'catalog:' version: 6.9.1 '@testing-library/react': - specifier: 14.3.1 + specifier: 'catalog:' version: 14.3.1(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/jest': specifier: 'catalog:' @@ -2183,10 +2202,10 @@ importers: specifier: 0.11.10 version: 0.11.10 react: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1 react-dom: - specifier: 18.3.1 + specifier: 'catalog:' version: 18.3.1(react@18.3.1) reframe.js: specifier: 4.0.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ea49b858041..7c8103c9981 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -35,6 +35,7 @@ catalog: '@tailwindcss/vite': 4.2.2 '@tanstack/react-query': 4.44.0 '@testing-library/jest-dom': 6.9.1 + '@testing-library/react': 14.3.1 '@tryghost/api-framework': 3.2.3 '@tryghost/color-utils': 0.2.18 '@tryghost/custom-fonts': 1.0.10 @@ -83,6 +84,8 @@ catalog: node-html-markdown: 2.0.0 postcss: 8.5.10 preact: ^10.29.2 + react: 18.3.1 + react-dom: 18.3.1 react-router: 7.14.0 sinon: 22.0.0 sonner: 2.0.7 @@ -101,6 +104,10 @@ catalogs: eslint9: '@eslint/js': 9.37.0 eslint: 9.37.0 + react17: + react: 17.0.2 + react-dom: 17.0.2 + '@testing-library/react': 12.1.5 tailwind3: tailwindcss: 3.4.18 eslint-plugin-tailwindcss: 3.18.2 From 2ab3a51cdd1fd0b75f2d1fdb8e8e82dc0332c9b3 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 15:08:23 -0500 Subject: [PATCH 07/10] Catalogued shared single-version dependencies (#28323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no ref Moves cross-workspace dependencies that already agree on a single version into the pnpm catalog, so future bumps are one decision and Renovate can group them (see PLA-58). All consumers resolve to the same version today, so this is a no-op — the lockfile only gains catalog entries and reshapes specifiers; no package resolution changes. **Catalogued:** - Four multi-workspace singles: `@ebay/nice-modal-react`, `react-hot-toast`, `mingo`, `tsx` - The shared `@radix-ui/*` set (`avatar`, `checkbox`, `form`, `popover`, `separator`, `switch`, `tabs`, `tooltip`) — a lockstep cluster worth centralising even at two consumers, since the pieces move together. **Deliberately left inline:** single-consumer `@radix-ui/*` packages and other deps used in only one workspace — cataloguing a dep with one consumer adds indirection with no drift-prevention benefit. The bar applied here is "shared across workspaces, or a lockstep cluster," not raw consumer count. --- apps/activitypub/package.json | 4 +- apps/admin-x-design-system/package.json | 20 +++--- apps/admin-x-framework/package.json | 4 +- apps/admin-x-settings/package.json | 6 +- apps/admin/package.json | 2 +- apps/posts/package.json | 2 +- apps/shade/package.json | 16 ++--- ghost/core/package.json | 4 +- ghost/parse-email-address/package.json | 2 +- pnpm-lock.yaml | 94 +++++++++++++++++-------- pnpm-workspace.yaml | 12 ++++ 11 files changed, 107 insertions(+), 59 deletions(-) diff --git a/apps/activitypub/package.json b/apps/activitypub/package.json index adcc73f4289..cd41e1103f0 100644 --- a/apps/activitypub/package.json +++ b/apps/activitypub/package.json @@ -1,6 +1,6 @@ { "name": "@tryghost/activitypub", - "version": "3.1.31", + "version": "3.1.32", "license": "MIT", "repository": { "type": "git", @@ -80,7 +80,7 @@ }, "dependencies": { "@hookform/resolvers": "5.4.0", - "@radix-ui/react-form": "0.1.8", + "@radix-ui/react-form": "catalog:", "@tanstack/react-query": "catalog:", "@tryghost/admin-x-framework": "workspace:*", "@tryghost/shade": "workspace:*", diff --git a/apps/admin-x-design-system/package.json b/apps/admin-x-design-system/package.json index 96626193d82..59c43e18378 100644 --- a/apps/admin-x-design-system/package.json +++ b/apps/admin-x-design-system/package.json @@ -66,22 +66,22 @@ "dependencies": { "@dnd-kit/core": "6.3.1", "@dnd-kit/sortable": "7.0.2", - "@ebay/nice-modal-react": "1.2.13", - "@radix-ui/react-avatar": "1.1.11", - "@radix-ui/react-checkbox": "1.3.3", - "@radix-ui/react-form": "0.1.8", - "@radix-ui/react-popover": "1.1.15", + "@ebay/nice-modal-react": "catalog:", + "@radix-ui/react-avatar": "catalog:", + "@radix-ui/react-checkbox": "catalog:", + "@radix-ui/react-form": "catalog:", + "@radix-ui/react-popover": "catalog:", "@radix-ui/react-radio-group": "1.3.8", - "@radix-ui/react-separator": "1.1.8", - "@radix-ui/react-switch": "1.2.6", - "@radix-ui/react-tabs": "1.1.13", - "@radix-ui/react-tooltip": "1.2.8", + "@radix-ui/react-separator": "catalog:", + "@radix-ui/react-switch": "catalog:", + "@radix-ui/react-tabs": "catalog:", + "@radix-ui/react-tooltip": "catalog:", "@sentry/react": "catalog:", "@tryghost/shade": "workspace:*", "@uiw/react-codemirror": "4.25.10", "clsx": "catalog:", "react-colorful": "5.6.1", - "react-hot-toast": "2.6.0", + "react-hot-toast": "catalog:", "react-select": "5.10.2" }, "peerDependencies": { diff --git a/apps/admin-x-framework/package.json b/apps/admin-x-framework/package.json index 9d2f68fd158..b0825227641 100644 --- a/apps/admin-x-framework/package.json +++ b/apps/admin-x-framework/package.json @@ -97,7 +97,7 @@ "vitest": "catalog:" }, "dependencies": { - "@ebay/nice-modal-react": "1.2.13", + "@ebay/nice-modal-react": "catalog:", "@sentry/react": "catalog:", "@tanstack/react-query": "catalog:", "@tinybirdco/charts": "0.3.0", @@ -106,7 +106,7 @@ "bson-objectid": "catalog:", "react": "catalog:", "react-dom": "catalog:", - "react-hot-toast": "2.6.0", + "react-hot-toast": "catalog:", "react-router": "catalog:" }, "peerDependencies": { diff --git a/apps/admin-x-settings/package.json b/apps/admin-x-settings/package.json index 1d8e3d4cd58..cff4cfb2454 100644 --- a/apps/admin-x-settings/package.json +++ b/apps/admin-x-settings/package.json @@ -49,7 +49,7 @@ "@codemirror/search": "6.7.0", "@codemirror/lang-yaml": "6.1.3", "@dnd-kit/sortable": "7.0.2", - "@ebay/nice-modal-react": "1.2.13", + "@ebay/nice-modal-react": "catalog:", "@sentry/react": "catalog:", "@tanstack/react-query": "catalog:", "@tryghost/color-utils": "catalog:", @@ -63,10 +63,10 @@ "clsx": "catalog:", "jszip": "3.10.1", "lucide-react": "catalog:", - "mingo": "2.5.3", + "mingo": "catalog:", "react": "catalog:", "react-dom": "catalog:", - "react-hot-toast": "2.6.0", + "react-hot-toast": "catalog:", "react-select": "5.10.2", "sonner": "catalog:", "validator": "catalog:" diff --git a/apps/admin/package.json b/apps/admin/package.json index f3c71f4cb33..ccb82720717 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -21,7 +21,7 @@ "@tryghost/posts": "workspace:*", "@tryghost/shade": "workspace:*", "@tryghost/stats": "workspace:*", - "mingo": "2.5.3", + "mingo": "catalog:", "react": "catalog:", "react-dom": "catalog:", "zod": "catalog:" diff --git a/apps/posts/package.json b/apps/posts/package.json index 791fec7d74a..ceeb4f84a2e 100644 --- a/apps/posts/package.json +++ b/apps/posts/package.json @@ -58,7 +58,7 @@ "vitest": "catalog:" }, "dependencies": { - "@ebay/nice-modal-react": "1.2.13", + "@ebay/nice-modal-react": "catalog:", "@tryghost/color-utils": "catalog:", "@tryghost/admin-x-framework": "workspace:*", "@tryghost/koenig-lexical": "catalog:", diff --git a/apps/shade/package.json b/apps/shade/package.json index 4cfee5f6bd2..80922eb3a2d 100644 --- a/apps/shade/package.json +++ b/apps/shade/package.json @@ -105,7 +105,7 @@ "storybook": "catalog:", "tailwindcss": "catalog:", "tsc-alias": "1.8.17", - "tsx": "4.21.0", + "tsx": "catalog:", "tw-animate-css": "catalog:", "typescript": "catalog:", "vite": "catalog:", @@ -117,22 +117,22 @@ "@number-flow/react": "0.6.0", "@radix-ui/react-accordion": "1.2.12", "@radix-ui/react-alert-dialog": "1.1.15", - "@radix-ui/react-avatar": "1.1.11", - "@radix-ui/react-checkbox": "1.3.3", + "@radix-ui/react-avatar": "catalog:", + "@radix-ui/react-checkbox": "catalog:", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-dropdown-menu": "2.1.16", "@radix-ui/react-hover-card": "1.1.15", "@radix-ui/react-label": "2.1.8", - "@radix-ui/react-popover": "1.1.15", + "@radix-ui/react-popover": "catalog:", "@radix-ui/react-select": "2.2.6", - "@radix-ui/react-separator": "1.1.8", + "@radix-ui/react-separator": "catalog:", "@radix-ui/react-slider": "1.3.6", "@radix-ui/react-slot": "1.2.4", - "@radix-ui/react-switch": "1.2.6", - "@radix-ui/react-tabs": "1.1.13", + "@radix-ui/react-switch": "catalog:", + "@radix-ui/react-tabs": "catalog:", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-toggle-group": "1.1.11", - "@radix-ui/react-tooltip": "1.2.8", + "@radix-ui/react-tooltip": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", "@types/validator": "catalog:", diff --git a/ghost/core/package.json b/ghost/core/package.json index 16560e90154..610dcb193a2 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -209,7 +209,7 @@ "metascraper-title": "5.45.10", "metascraper-url": "5.45.10", "mime-types": "2.1.35", - "mingo": "2.5.3", + "mingo": "catalog:", "moment": "2.24.0", "moment-timezone": "0.5.45", "multer": "2.1.1", @@ -301,7 +301,7 @@ "sinon": "catalog:", "supertest": "6.3.4", "tmp": "0.2.6", - "tsx": "4.21.0", + "tsx": "catalog:", "typescript": "catalog:", "validator": "catalog:", "vitest": "catalog:" diff --git a/ghost/parse-email-address/package.json b/ghost/parse-email-address/package.json index d58fba4d3ce..41d9bf3b431 100644 --- a/ghost/parse-email-address/package.json +++ b/ghost/parse-email-address/package.json @@ -30,7 +30,7 @@ "c8": "catalog:", "eslint": "catalog:", "mocha": "catalog:", - "tsx": "4.21.0", + "tsx": "catalog:", "typescript": "catalog:" }, "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4b9c3d6e884..e5a7002c409 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,12 +6,39 @@ settings: catalogs: default: + '@ebay/nice-modal-react': + specifier: 1.2.13 + version: 1.2.13 '@eslint/js': specifier: 8.57.1 version: 8.57.1 '@playwright/test': specifier: 1.60.0 version: 1.60.0 + '@radix-ui/react-avatar': + specifier: 1.1.11 + version: 1.1.11 + '@radix-ui/react-checkbox': + specifier: 1.3.3 + version: 1.3.3 + '@radix-ui/react-form': + specifier: 0.1.8 + version: 0.1.8 + '@radix-ui/react-popover': + specifier: 1.1.15 + version: 1.1.15 + '@radix-ui/react-separator': + specifier: 1.1.8 + version: 1.1.8 + '@radix-ui/react-switch': + specifier: 1.2.6 + version: 1.2.6 + '@radix-ui/react-tabs': + specifier: 1.1.13 + version: 1.1.13 + '@radix-ui/react-tooltip': + specifier: 1.2.8 + version: 1.2.8 '@sentry/react': specifier: 7.120.4 version: 7.120.4 @@ -165,6 +192,9 @@ catalogs: lucide-react: specifier: 1.17.0 version: 1.17.0 + mingo: + specifier: 2.5.3 + version: 2.5.3 mocha: specifier: 11.7.6 version: 11.7.6 @@ -186,6 +216,9 @@ catalogs: react-dom: specifier: 18.3.1 version: 18.3.1 + react-hot-toast: + specifier: 2.6.0 + version: 2.6.0 react-router: specifier: 7.14.0 version: 7.14.0 @@ -201,6 +234,9 @@ catalogs: tailwindcss: specifier: 4.2.2 version: 4.2.2 + tsx: + specifier: 4.21.0 + version: 4.21.0 tw-animate-css: specifier: 1.4.0 version: 1.4.0 @@ -366,7 +402,7 @@ importers: specifier: 5.4.0 version: 5.4.0(react-hook-form@7.72.1(react@18.3.1)) '@radix-ui/react-form': - specifier: 0.1.8 + specifier: 'catalog:' version: 0.1.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tanstack/react-query': specifier: 'catalog:' @@ -478,7 +514,7 @@ importers: specifier: workspace:* version: link:../stats mingo: - specifier: 2.5.3 + specifier: 'catalog:' version: 2.5.3 react: specifier: 'catalog:' @@ -597,34 +633,34 @@ importers: specifier: 7.0.2 version: 7.0.2(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@ebay/nice-modal-react': - specifier: 1.2.13 + specifier: 'catalog:' version: 1.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-avatar': - specifier: 1.1.11 + specifier: 'catalog:' version: 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-checkbox': - specifier: 1.3.3 + specifier: 'catalog:' version: 1.3.3(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-form': - specifier: 0.1.8 + specifier: 'catalog:' version: 0.1.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': - specifier: 1.1.15 + specifier: 'catalog:' version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-radio-group': specifier: 1.3.8 version: 1.3.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-separator': - specifier: 1.1.8 + specifier: 'catalog:' version: 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-switch': - specifier: 1.2.6 + specifier: 'catalog:' version: 1.2.6(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': - specifier: 1.1.13 + specifier: 'catalog:' version: 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': - specifier: 1.2.8 + specifier: 'catalog:' version: 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/react': specifier: 'catalog:' @@ -642,7 +678,7 @@ importers: specifier: 5.6.1 version: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-hot-toast: - specifier: 2.6.0 + specifier: 'catalog:' version: 2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-select: specifier: 5.10.2 @@ -763,7 +799,7 @@ importers: apps/admin-x-framework: dependencies: '@ebay/nice-modal-react': - specifier: 1.2.13 + specifier: 'catalog:' version: 1.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/react': specifier: 'catalog:' @@ -790,7 +826,7 @@ importers: specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-hot-toast: - specifier: 2.6.0 + specifier: 'catalog:' version: 2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router: specifier: 'catalog:' @@ -893,7 +929,7 @@ importers: specifier: 7.0.2 version: 7.0.2(@dnd-kit/core@6.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) '@ebay/nice-modal-react': - specifier: 1.2.13 + specifier: 'catalog:' version: 1.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/react': specifier: 'catalog:' @@ -935,7 +971,7 @@ importers: specifier: 'catalog:' version: 1.17.0(react@18.3.1) mingo: - specifier: 2.5.3 + specifier: 'catalog:' version: 2.5.3 react: specifier: 'catalog:' @@ -944,7 +980,7 @@ importers: specifier: 'catalog:' version: 18.3.1(react@18.3.1) react-hot-toast: - specifier: 2.6.0 + specifier: 'catalog:' version: 2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-select: specifier: 5.10.2 @@ -1248,7 +1284,7 @@ importers: apps/posts: dependencies: '@ebay/nice-modal-react': - specifier: 1.2.13 + specifier: 'catalog:' version: 1.2.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@tryghost/admin-x-framework': specifier: workspace:* @@ -1381,10 +1417,10 @@ importers: specifier: 1.1.15 version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-avatar': - specifier: 1.1.11 + specifier: 'catalog:' version: 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-checkbox': - specifier: 1.3.3 + specifier: 'catalog:' version: 1.3.3(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-dialog': specifier: 1.1.15 @@ -1399,13 +1435,13 @@ importers: specifier: 2.1.8 version: 2.1.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': - specifier: 1.1.15 + specifier: 'catalog:' version: 1.1.15(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-select': specifier: 2.2.6 version: 2.2.6(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-separator': - specifier: 1.1.8 + specifier: 'catalog:' version: 1.1.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-slider': specifier: 1.3.6 @@ -1414,10 +1450,10 @@ importers: specifier: 1.2.4 version: 1.2.4(@types/react@18.3.29)(react@18.3.1) '@radix-ui/react-switch': - specifier: 1.2.6 + specifier: 'catalog:' version: 1.2.6(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tabs': - specifier: 1.1.13 + specifier: 'catalog:' version: 1.1.13(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-toggle': specifier: 1.1.10 @@ -1426,7 +1462,7 @@ importers: specifier: 1.1.11 version: 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-tooltip': - specifier: 1.2.8 + specifier: 'catalog:' version: 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.29))(@types/react@18.3.29)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/react': specifier: 'catalog:' @@ -1562,7 +1598,7 @@ importers: specifier: 1.8.17 version: 1.8.17 tsx: - specifier: 4.21.0 + specifier: 'catalog:' version: 4.21.0 tw-animate-css: specifier: 'catalog:' @@ -2619,7 +2655,7 @@ importers: specifier: 2.1.35 version: 2.1.35 mingo: - specifier: 2.5.3 + specifier: 'catalog:' version: 2.5.3 moment: specifier: 2.30.1 @@ -2866,7 +2902,7 @@ importers: specifier: 0.2.6 version: 0.2.6 tsx: - specifier: 4.21.0 + specifier: 'catalog:' version: 4.21.0 typescript: specifier: 'catalog:' @@ -2935,7 +2971,7 @@ importers: specifier: 'catalog:' version: 11.7.6 tsx: - specifier: 4.21.0 + specifier: 'catalog:' version: 4.21.0 typescript: specifier: 'catalog:' diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 7c8103c9981..407ce2cca79 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -25,8 +25,17 @@ allowBuilds: ssh2: true catalog: + '@ebay/nice-modal-react': 1.2.13 '@eslint/js': 8.57.1 '@playwright/test': 1.60.0 + '@radix-ui/react-avatar': 1.1.11 + '@radix-ui/react-checkbox': 1.3.3 + '@radix-ui/react-form': 0.1.8 + '@radix-ui/react-popover': 1.1.15 + '@radix-ui/react-separator': 1.1.8 + '@radix-ui/react-switch': 1.2.6 + '@radix-ui/react-tabs': 1.1.13 + '@radix-ui/react-tooltip': 1.2.8 '@sentry/react': 7.120.4 '@storybook/addon-docs': 10.3.5 '@storybook/addon-links': 10.3.5 @@ -79,6 +88,7 @@ catalog: jsonc-parser: 3.3.1 lodash: 4.18.1 lucide-react: 1.17.0 + mingo: 2.5.3 mocha: 11.7.6 msw: 2.14.6 node-html-markdown: 2.0.0 @@ -86,11 +96,13 @@ catalog: preact: ^10.29.2 react: 18.3.1 react-dom: 18.3.1 + react-hot-toast: 2.6.0 react-router: 7.14.0 sinon: 22.0.0 sonner: 2.0.7 storybook: 10.3.5 tailwindcss: 4.2.2 + tsx: 4.21.0 tw-animate-css: 1.4.0 type-fest: 5.6.0 typescript: 5.9.3 From 10fb9265396ed34eb6ceef905f194732dc62dcc4 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 16:20:13 -0500 Subject: [PATCH 08/10] Added Renovate grouping for pnpm catalog updates (#28324) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without grouping rules, each catalogued dependency still opens its own Renovate PR — so a single named-catalog bump can fan out into several PRs, which is the churn the catalog was meant to collapse. This adds the missing half of the catalog strategy: one reviewable PR per named catalog. Renovate tags every pnpm catalog dependency with a `pnpm.catalog.` depType, so the rules match on depType rather than restating each catalog's package list. They stay correct as entries are added to or removed from `pnpm-workspace.yaml`: - `react17 catalog` — `react`, `react-dom`, `@testing-library/react` - `eslint9 catalog` — `eslint`, `@eslint/js` - `tailwind3 catalog` — `tailwindcss`, `eslint-plugin-tailwindcss` These also override the shared preset's `group:monorepos` behaviour. That preset groups e.g. `eslint` + `@eslint/js` and `react` + `react-dom` *by name* across the whole repo, which would otherwise merge the default-catalog version lane (eslint 8, React 18) and the named-catalog lane (eslint 9, React 17) into a single PR. Matching by depType keeps each lane in its own PR — the separation the named catalogs exist to enforce. The main `catalog:` is intentionally left ungrouped. Its entries are independent of one another, so grouping them would only couple unrelated bumps and let one risky update block the rest of the group from merging. Per-catalog grouping is applied only where the catalog represents a genuine lockstep version lane. Composes with the existing rules: the named-catalog deps don't overlap the vulnerability-alert carve-out, the Ember/CSS freeze rules, or the `@tryghost/*` groups, so current behaviour is unchanged. The off-hours schedule is untouched. The `react17` group only takes effect once the React catalog split lands. ref https://linear.app/ghost/issue/PLA-58 --- .github/renovate.json5 | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index ecc0556ff3f..32bd31dc16f 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -225,6 +225,37 @@ ] }, + // Group each pinned-version pnpm catalog into a single PR per catalog. + // + // The named catalogs in pnpm-workspace.yaml (react17, eslint9, + // tailwind3) each hold a version lane we deliberately keep separate + // from the main `catalog:` — e.g. eslint 9 lives in `eslint9` while the + // default catalog stays on eslint 8. Renovate tags every catalog dep + // with a depType of `pnpm.catalog.`, so matching the depType + // groups the whole catalog without restating its package list and stays + // correct as entries are added or removed in pnpm-workspace.yaml. + // + // These also override the shared preset's `group:monorepos` rules, + // which would otherwise group e.g. eslint + @eslint/js *by name* and + // mix the default-catalog (v8) and eslint9-catalog (v9) bumps into one + // PR. Matching by depType keeps each lane in its own reviewable PR. + // + // The main `catalog:` is intentionally left ungrouped: its entries are + // independent, so grouping them would only couple unrelated bumps and + // let one risky update block the rest. + { + "groupName": "react17 catalog", + "matchDepTypes": ["pnpm.catalog.react17"] + }, + { + "groupName": "eslint9 catalog", + "matchDepTypes": ["pnpm.catalog.eslint9"] + }, + { + "groupName": "tailwind3 catalog", + "matchDepTypes": ["pnpm.catalog.tailwind3"] + }, + // Always automerge these packages: { "matchPackageNames": [ From bfa4c53d135d65d1c55ad2f44bd4276428493ab1 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 16:33:43 -0500 Subject: [PATCH 09/10] Converged faker onto v9 for e2e and stats (#28327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref https://linear.app/ghost/issue/PLA-59 `@faker-js/faker` was declared at two versions across the workspace — `8.4.1` in `e2e` and `9.9.0` in `apps/stats`. This catalogues a single `9.9.0` entry and points both consumers at it, collapsing the split so a future bump is one decision. --- apps/stats/package.json | 2 +- e2e/package.json | 2 +- pnpm-lock.yaml | 15 ++++++--------- pnpm-workspace.yaml | 1 + 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/apps/stats/package.json b/apps/stats/package.json index 86b193a4489..ba12ef78b57 100644 --- a/apps/stats/package.json +++ b/apps/stats/package.json @@ -37,7 +37,7 @@ "preview": "vite preview" }, "devDependencies": { - "@faker-js/faker": "9.9.0", + "@faker-js/faker": "catalog:", "@testing-library/jest-dom": "catalog:", "@testing-library/react": "catalog:", "@types/jest": "catalog:", diff --git a/e2e/package.json b/e2e/package.json index 23cbc9984e4..438e207be64 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -29,7 +29,7 @@ ], "devDependencies": { "@eslint/js": "catalog:", - "@faker-js/faker": "8.4.1", + "@faker-js/faker": "catalog:", "@playwright/test": "catalog:", "@tryghost/debug": "catalog:", "@tryghost/logging": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5a7002c409..e0679c3f2cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,9 @@ catalogs: '@eslint/js': specifier: 8.57.1 version: 8.57.1 + '@faker-js/faker': + specifier: 9.9.0 + version: 9.9.0 '@playwright/test': specifier: 1.60.0 version: 1.60.0 @@ -1781,7 +1784,7 @@ importers: version: 2.2.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) devDependencies: '@faker-js/faker': - specifier: 9.9.0 + specifier: 'catalog:' version: 9.9.0 '@testing-library/jest-dom': specifier: 'catalog:' @@ -1841,8 +1844,8 @@ importers: specifier: 'catalog:' version: 8.57.1 '@faker-js/faker': - specifier: 8.4.1 - version: 8.4.1 + specifier: 'catalog:' + version: 9.9.0 '@playwright/test': specifier: 'catalog:' version: 1.60.0 @@ -4864,10 +4867,6 @@ packages: resolution: {integrity: sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==} engines: {node: '>=14.0.0', npm: '>=6.0.0'} - '@faker-js/faker@8.4.1': - resolution: {integrity: sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} - '@faker-js/faker@9.9.0': resolution: {integrity: sha512-OEl393iCOoo/z8bMezRlJu+GlRGlsKbUAN7jKB6LhnKoqKve5DXRpalbItIIcwnCjs1k/FOPjFzcA6Qn+H+YbA==} engines: {node: '>=18.0.0', npm: '>=9.0.0'} @@ -24356,8 +24355,6 @@ snapshots: '@faker-js/faker@7.6.0': {} - '@faker-js/faker@8.4.1': {} - '@faker-js/faker@9.9.0': {} '@fastify/otel@0.18.0(@opentelemetry/api@1.9.1)': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 407ce2cca79..5c25ce92910 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -27,6 +27,7 @@ allowBuilds: catalog: '@ebay/nice-modal-react': 1.2.13 '@eslint/js': 8.57.1 + '@faker-js/faker': 9.9.0 '@playwright/test': 1.60.0 '@radix-ui/react-avatar': 1.1.11 '@radix-ui/react-checkbox': 1.3.3 From cb752778c02dbbedcf203fb78fdace8111556861 Mon Sep 17 00:00:00 2001 From: Steve Larson <9larsons@gmail.com> Date: Tue, 2 Jun 2026 17:11:24 -0500 Subject: [PATCH 10/10] Updated ghost/core seed-data generator to faker v9 (#28329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ref https://linear.app/ghost/issue/PLA-61 `ghost/core` was the last maintained workspace on `@faker-js/faker` 7.x. This points it at the catalogued `9.9.0` (e2e and stats converged in #28327) and migrates the seeder call sites off the APIs faker removed in v8/v9. faker is reachable only through the demo/dev data generator (`reset:data`) — there are no faker call sites in `test/`, and nothing asserts on generated output, so resolved values shifting between majors is cosmetic. --- .../server/data/seeders/data-generator.js | 2 +- .../seeders/importers/benefits-importer.js | 4 ++-- .../importers/comment-reports-importer.js | 2 +- .../seeders/importers/comments-importer.js | 8 ++++---- .../importers/email-batches-importer.js | 2 +- .../email-recipient-failures-importer.js | 2 +- .../data/seeders/importers/emails-importer.js | 14 ++++++------- .../data/seeders/importers/labels-importer.js | 2 +- .../members-click-events-importer.js | 6 +++--- .../seeders/importers/members-importer.js | 20 +++++++++---------- .../importers/members-labels-importer.js | 2 +- .../members-stripe-customers-importer.js | 5 +++-- ...stripe-customers-subscriptions-importer.js | 6 +++--- .../seeders/importers/newsletters-importer.js | 6 +++--- .../importers/offer-redemptions-importer.js | 6 +++--- .../importers/posts-authors-importer.js | 2 +- .../data/seeders/importers/posts-importer.js | 12 +++++------ .../seeders/importers/posts-tags-importer.js | 4 ++-- .../seeders/importers/products-importer.js | 4 ++-- .../recommendation-click-events-importer.js | 2 +- ...ecommendation-subscribe-events-importer.js | 2 +- .../seeders/importers/redirects-importer.js | 7 ++++--- .../seeders/importers/roles-users-importer.js | 2 +- .../importers/stripe-prices-importer.js | 4 ++-- .../importers/stripe-products-importer.js | 4 ++-- .../data/seeders/importers/tags-importer.js | 6 +++--- .../data/seeders/importers/users-importer.js | 10 ++++++---- .../importers/web-mentions-importer.js | 2 +- .../data/seeders/utils/database-date.js | 2 +- .../core/server/data/seeders/utils/random.js | 2 +- ghost/core/package.json | 2 +- pnpm-lock.yaml | 4 ++-- 32 files changed, 81 insertions(+), 77 deletions(-) diff --git a/ghost/core/core/server/data/seeders/data-generator.js b/ghost/core/core/server/data/seeders/data-generator.js index e0d13af59ac..9145e2d77fa 100644 --- a/ghost/core/core/server/data/seeders/data-generator.js +++ b/ghost/core/core/server/data/seeders/data-generator.js @@ -246,7 +246,7 @@ class DataGenerator { crypto.randomBytes = (size) => { const buffer = Buffer.alloc(size); for (let i = 0; i < size; i++) { - buffer[i] = Math.floor(faker.datatype.number({min: 0, max: 255})); + buffer[i] = Math.floor(faker.number.int({min: 0, max: 255})); } return buffer; }; diff --git a/ghost/core/core/server/data/seeders/importers/benefits-importer.js b/ghost/core/core/server/data/seeders/importers/benefits-importer.js index 951db60819a..e1ddd84d9ac 100644 --- a/ghost/core/core/server/data/seeders/importers/benefits-importer.js +++ b/ghost/core/core/server/data/seeders/importers/benefits-importer.js @@ -19,8 +19,8 @@ class BenefitsImporter extends TableImporter { return { id: this.fastFakeObjectId(), name: name, - slug: `${slugify(name)}-${faker.random.numeric(3)}`, - created_at: faker.date.between(blogStartDate, sixMonthsLater) + slug: `${slugify(name)}-${faker.string.numeric(3)}`, + created_at: faker.date.between({from: blogStartDate, to: sixMonthsLater}) }; } } diff --git a/ghost/core/core/server/data/seeders/importers/comment-reports-importer.js b/ghost/core/core/server/data/seeders/importers/comment-reports-importer.js index a4599cf262e..a0ebf823d27 100644 --- a/ghost/core/core/server/data/seeders/importers/comment-reports-importer.js +++ b/ghost/core/core/server/data/seeders/importers/comment-reports-importer.js @@ -51,7 +51,7 @@ class CommentReportsImporter extends TableImporter { const reportTime = dateToDatabaseString.randomBetween(this.model.created_at, new Date()); - const reporter = this.possibleReporters[faker.datatype.number(this.possibleReporters.length - 1)]; + const reporter = this.possibleReporters[faker.number.int(this.possibleReporters.length - 1)]; return { id: this.fastFakeObjectId(), diff --git a/ghost/core/core/server/data/seeders/importers/comments-importer.js b/ghost/core/core/server/data/seeders/importers/comments-importer.js index 1054e813bcd..58406b2b80c 100644 --- a/ghost/core/core/server/data/seeders/importers/comments-importer.js +++ b/ghost/core/core/server/data/seeders/importers/comments-importer.js @@ -32,7 +32,7 @@ class CommentsImporter extends TableImporter { shape: 'ease-out', trend: 'negative', // Use commentsPerPost as a baseline with some variance (+/- 20%) - total: Math.round(this.commentsPerPost * faker.datatype.float({min: 0.8, max: 1.2})), + total: Math.round(this.commentsPerPost * faker.number.float({min: 0.8, max: 1.2})), startTime: publishedAt, endTime: new Date() }).sort((a, b) => a.getTime() - b.getTime()); // Sort chronologically so replies always come after their targets @@ -68,11 +68,11 @@ class CommentsImporter extends TableImporter { let replyTarget; if (preferReplyToReply) { // Pick from existing replies to create a reply-to-reply - const replyToIndex = faker.datatype.number(existingReplies.length - 1); + const replyToIndex = faker.number.int(existingReplies.length - 1); replyTarget = existingReplies[replyToIndex]; } else { // Pick any random eligible comment - const replyToIndex = faker.datatype.number(eligibleComments.length - 1); + const replyToIndex = faker.number.int(eligibleComments.length - 1); replyTarget = eligibleComments[replyToIndex]; } const [replyToId, replyToParentId] = replyTarget; @@ -93,7 +93,7 @@ class CommentsImporter extends TableImporter { const event = { id: this.fastFakeObjectId(), post_id: this.model.id, - member_id: this.possibleMembers[faker.datatype.number(this.possibleMembers.length - 1)].id, + member_id: this.possibleMembers[faker.number.int(this.possibleMembers.length - 1)].id, parent_id: parentId, in_reply_to_id: inReplyToId, status: 'published', diff --git a/ghost/core/core/server/data/seeders/importers/email-batches-importer.js b/ghost/core/core/server/data/seeders/importers/email-batches-importer.js index cfc29dbfac3..a41496d6a39 100644 --- a/ghost/core/core/server/data/seeders/importers/email-batches-importer.js +++ b/ghost/core/core/server/data/seeders/importers/email-batches-importer.js @@ -27,7 +27,7 @@ class EmailBatchesImporter extends TableImporter { return { id: this.fastFakeObjectId(), email_id: this.model.id, - provider_id: `${new Date().toISOString().split('.')[0].replace(/[^0-9]/g, '')}.${faker.datatype.hexadecimal({length: 16, prefix: '', case: 'lower'})}@m.example.com`, + provider_id: `${new Date().toISOString().split('.')[0].replace(/[^0-9]/g, '')}.${faker.string.hexadecimal({length: 16, prefix: '', casing: 'lower'})}@m.example.com`, status: 'submitted', // TODO: introduce failures created_at: this.model.created_at, updated_at: dateToDatabaseString(dateToDatabaseString.randomBetween(emailSentDate, latestUpdatedDate)) diff --git a/ghost/core/core/server/data/seeders/importers/email-recipient-failures-importer.js b/ghost/core/core/server/data/seeders/importers/email-recipient-failures-importer.js index e4ae87cb87c..1d80b752dd5 100644 --- a/ghost/core/core/server/data/seeders/importers/email-recipient-failures-importer.js +++ b/ghost/core/core/server/data/seeders/importers/email-recipient-failures-importer.js @@ -57,7 +57,7 @@ class EmailRecipientFailuresImporter extends TableImporter { email_id: this.model.email_id, member_id: this.model.member_id, email_recipient_id: this.model.id, - event_id: faker.random.alphaNumeric(20), + event_id: faker.string.alphanumeric(20), ...error, failed_at: this.model.failed_at }; diff --git a/ghost/core/core/server/data/seeders/importers/emails-importer.js b/ghost/core/core/server/data/seeders/importers/emails-importer.js index b07055cbbe4..0465997c513 100644 --- a/ghost/core/core/server/data/seeders/importers/emails-importer.js +++ b/ghost/core/core/server/data/seeders/importers/emails-importer.js @@ -56,25 +56,25 @@ class EmailsImporter extends TableImporter { const recipientCount = this.membersSubscribeEvents .filter(entry => entry.newsletter_id === newsletter.id) .filter(entry => dateToDatabaseString.parse(entry.created_at) < timestamp).length; - const deliveredCount = Math.ceil(recipientCount * faker.datatype.float({ + const deliveredCount = Math.ceil(recipientCount * faker.number.float({ max: 1, min: 0.9, - precision: 0.001 + multipleOf: 0.001 })); - const openedCount = Math.ceil(deliveredCount * faker.datatype.float({ + const openedCount = Math.ceil(deliveredCount * faker.number.float({ max: 0.95, min: 0.6, - precision: 0.001 + multipleOf: 0.001 })); - const failedCount = Math.floor((recipientCount - deliveredCount) * faker.datatype.float({ + const failedCount = Math.floor((recipientCount - deliveredCount) * faker.number.float({ max: 0.05, min: 0, - precision: 0.001 + multipleOf: 0.001 })); return { id, - uuid: faker.datatype.uuid(), + uuid: faker.string.uuid(), post_id: this.model.id, status: 'submitted', recipient_filter: '', // TODO: Add recipient filter? diff --git a/ghost/core/core/server/data/seeders/importers/labels-importer.js b/ghost/core/core/server/data/seeders/importers/labels-importer.js index d7a61885b76..6c3cd93e620 100644 --- a/ghost/core/core/server/data/seeders/importers/labels-importer.js +++ b/ghost/core/core/server/data/seeders/importers/labels-importer.js @@ -17,7 +17,7 @@ class LabelsImporter extends TableImporter { generateName() { let name; do { - name = `${faker.color.human()} ${faker.name.jobType()}`; + name = `${faker.color.human()} ${faker.person.jobType()}`; name = `${name[0].toUpperCase()}${name.slice(1)}`; } while (this.generatedNames.has(name)); this.generatedNames.add(name); diff --git a/ghost/core/core/server/data/seeders/importers/members-click-events-importer.js b/ghost/core/core/server/data/seeders/importers/members-click-events-importer.js index e96ff922538..41e8c7e3bd2 100644 --- a/ghost/core/core/server/data/seeders/importers/members-click-events-importer.js +++ b/ghost/core/core/server/data/seeders/importers/members-click-events-importer.js @@ -36,7 +36,7 @@ class MembersClickEventsImporter extends TableImporter { setReferencedModel(model) { this.model = model; - this.amount = model.opened_at === null ? 0 : luck(40) ? faker.datatype.number({ + this.amount = model.opened_at === null ? 0 : luck(40) ? faker.number.int({ min: 0, max: this.quantity }) : 0; @@ -52,12 +52,12 @@ class MembersClickEventsImporter extends TableImporter { const openedAt = dateToDatabaseString.parse(this.model.opened_at); const laterOn = new Date(openedAt.getTime() + 1000 * 60 * 15); - const clickTime = faker.date.between(openedAt.getTime(), laterOn.getTime()); //added getTime here because it threw random errors + const clickTime = faker.date.between({from: openedAt.getTime(), to: laterOn.getTime()}); //added getTime here because it threw random errors return { id: this.fastFakeObjectId(), member_id: this.model.member_id, - redirect_id: this.redirectList[this.redirectList.length === 1 ? 0 : (faker.datatype.number({ + redirect_id: this.redirectList[this.redirectList.length === 1 ? 0 : (faker.number.int({ min: 0, max: this.redirectList.length - 1 }))].id, diff --git a/ghost/core/core/server/data/seeders/importers/members-importer.js b/ghost/core/core/server/data/seeders/importers/members-importer.js index e4cbe7a987e..325338b5cbf 100644 --- a/ghost/core/core/server/data/seeders/importers/members-importer.js +++ b/ghost/core/core/server/data/seeders/importers/members-importer.js @@ -10,7 +10,7 @@ const debug = require('@tryghost/debug')('MembersImporter'); class MembersImporter extends TableImporter { static table = 'members'; static dependencies = []; - defaultQuantity = faker.datatype.number({ + defaultQuantity = faker.number.int({ min: 7000, max: 8000 }); @@ -68,27 +68,27 @@ class MembersImporter extends TableImporter { generate() { const id = this.fastFakeObjectId(); // Use name from American locale to reflect an English-speaking audience - const name = `${americanFaker.name.firstName()} ${americanFaker.name.lastName()}`; + const name = `${americanFaker.person.firstName()} ${americanFaker.person.lastName()}`; const timestamp = this.timestamps.pop(); return { id, - uuid: faker.datatype.uuid(), - transient_id: faker.datatype.uuid(), - email: `${name.replace(' ', '.').replace(/[^a-zA-Z0-9]/g, '').toLowerCase()}${faker.datatype.number({min: 0, max: 999999})}@example.com`, + uuid: faker.string.uuid(), + transient_id: faker.string.uuid(), + email: `${name.replace(' ', '.').replace(/[^a-zA-Z0-9]/g, '').toLowerCase()}${faker.number.int({min: 0, max: 999999})}@example.com`, status: luck(5) ? 'comped' : luck(15) ? 'paid' : 'free', name: name, - expertise: luck(30) ? faker.name.jobTitle() : undefined, + expertise: luck(30) ? faker.person.jobTitle() : undefined, geolocation: JSON.stringify({ - country: faker.address.country(), - country_code: faker.address.countryCode('alpha-2'), - region: faker.address.state() + country: faker.location.country(), + country_code: faker.location.countryCode('alpha-2'), + region: faker.location.state() }), email_count: 0, // Depends on number of emails sent since created_at, the newsletter they're a part of and subscription status email_opened_count: 0, email_open_rate: null, // 40% of users logged in within a week, 60% sometime since registering - last_seen_at: luck(40) ? dateToDatabaseString(faker.date.recent(7)) : dateToDatabaseString(faker.date.between(timestamp, new Date())), + last_seen_at: luck(40) ? dateToDatabaseString(faker.date.recent({days: 7})) : dateToDatabaseString(faker.date.between({from: timestamp, to: new Date()})), created_at: dateToDatabaseString(timestamp), updated_at: dateToDatabaseString(timestamp) }; diff --git a/ghost/core/core/server/data/seeders/importers/members-labels-importer.js b/ghost/core/core/server/data/seeders/importers/members-labels-importer.js index 7424021e0ad..c97a61f11c3 100644 --- a/ghost/core/core/server/data/seeders/importers/members-labels-importer.js +++ b/ghost/core/core/server/data/seeders/importers/members-labels-importer.js @@ -27,7 +27,7 @@ class MembersLabelsImporter extends TableImporter { return { id: this.fastFakeObjectId(), member_id: this.model.id, - label_id: this.labels[faker.datatype.number({ + label_id: this.labels[faker.number.int({ min: 0, max: this.labels.length - 1 })].id, diff --git a/ghost/core/core/server/data/seeders/importers/members-stripe-customers-importer.js b/ghost/core/core/server/data/seeders/importers/members-stripe-customers-importer.js index 21e048c1376..22c85b00165 100644 --- a/ghost/core/core/server/data/seeders/importers/members-stripe-customers-importer.js +++ b/ghost/core/core/server/data/seeders/importers/members-stripe-customers-importer.js @@ -37,7 +37,7 @@ class MembersStripeCustomersImporter extends TableImporter { // The number should increase the older the member is const daysSinceMemberCreated = Math.floor((new Date() - dateToDatabaseString.parse(this.model.created_at)) / (1000 * 60 * 60 * 24)); - const shouldHaveStripeCustomer = faker.datatype.number({min: 0, max: 100}) < Math.max(Math.min(daysSinceMemberCreated / 60, 15), 2); + const shouldHaveStripeCustomer = faker.number.int({min: 0, max: 100}) < Math.max(Math.min(daysSinceMemberCreated / 60, 15), 2); if (!shouldHaveStripeCustomer) { return; @@ -47,7 +47,8 @@ class MembersStripeCustomersImporter extends TableImporter { return { id: this.fastFakeObjectId(), member_id: this.model.id, - customer_id: `cus_${faker.random.alphaNumeric(14, { + customer_id: `cus_${faker.string.alphanumeric({ + length: 14, casing: 'mixed' })}`, name: this.model.name, diff --git a/ghost/core/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js b/ghost/core/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js index eb4945adcce..36486edc33b 100644 --- a/ghost/core/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js +++ b/ghost/core/core/server/data/seeders/importers/members-stripe-customers-subscriptions-importer.js @@ -148,7 +148,7 @@ class MembersStripeCustomersSubscriptionsImporter extends TableImporter { return; } - const randomMonthDiff = faker.datatype.number({min: 1, max: monthDiff}); + const randomMonthDiff = faker.number.int({min: 1, max: monthDiff}); endDate.setMonth(startDate.getMonth() + randomMonthDiff); } else { // What is the year difference between startDate and now? Pick a random number in between @@ -158,7 +158,7 @@ class MembersStripeCustomersSubscriptionsImporter extends TableImporter { // Not possible to create an invalid subscription here return; } - const randomYearDiff = faker.datatype.number({min: 1, max: yearDiff}); + const randomYearDiff = faker.number.int({min: 1, max: yearDiff}); endDate.setFullYear(startDate.getFullYear() + randomYearDiff); } @@ -235,7 +235,7 @@ class MembersStripeCustomersSubscriptionsImporter extends TableImporter { return { id: this.fastFakeObjectId(), customer_id: customer.customer_id, - subscription_id: `sub_${faker.random.alphaNumeric(14)}`, + subscription_id: `sub_${faker.string.alphanumeric(14)}`, stripe_price_id: stripePrice.stripe_price_id, start_date: dateToDatabaseString(startDate), created_at: dateToDatabaseString(startDate), diff --git a/ghost/core/core/server/data/seeders/importers/newsletters-importer.js b/ghost/core/core/server/data/seeders/importers/newsletters-importer.js index b19e51250b1..792de9c0d5c 100644 --- a/ghost/core/core/server/data/seeders/importers/newsletters-importer.js +++ b/ghost/core/core/server/data/seeders/importers/newsletters-importer.js @@ -25,14 +25,14 @@ class NewslettersImporter extends TableImporter { return { id: this.fastFakeObjectId(), - uuid: faker.datatype.uuid(), + uuid: faker.string.uuid(), name: name, - slug: `${slugify(name)}-${faker.random.numeric(3)}`, + slug: `${slugify(name)}-${faker.string.numeric(3)}`, sender_reply_to: 'newsletter', status: 'active', subscribe_on_signup: faker.datatype.boolean(), sort_order: sortOrder, - created_at: faker.date.between(blogStartDate, weekAfter) + created_at: faker.date.between({from: blogStartDate, to: weekAfter}) }; } } diff --git a/ghost/core/core/server/data/seeders/importers/offer-redemptions-importer.js b/ghost/core/core/server/data/seeders/importers/offer-redemptions-importer.js index d7939e0b2f1..6ae8fcb843f 100644 --- a/ghost/core/core/server/data/seeders/importers/offer-redemptions-importer.js +++ b/ghost/core/core/server/data/seeders/importers/offer-redemptions-importer.js @@ -94,7 +94,7 @@ class OfferRedemptionsImporter extends TableImporter { subscriptionState.redemptionEndAt.valueOf() )); const latest = subscriptionState.redemptionEndAt > earliest ? subscriptionState.redemptionEndAt : earliest; - const createdAt = latest.valueOf() === earliest.valueOf() ? earliest : faker.date.between(earliest, latest); + const createdAt = latest.valueOf() === earliest.valueOf() ? earliest : faker.date.between({from: earliest, to: latest}); subscriptionState.lastRedeemedAt = createdAt; @@ -102,12 +102,12 @@ class OfferRedemptionsImporter extends TableImporter { } generate() { - const subscriptionIndex = faker.datatype.number({ + const subscriptionIndex = faker.number.int({ min: 0, max: this.subscriptionPool.length - 1 }); const subscriptionState = this.subscriptionPool[subscriptionIndex]; - const offerIndex = faker.datatype.number({ + const offerIndex = faker.number.int({ min: 0, max: subscriptionState.availableOffers.length - 1 }); diff --git a/ghost/core/core/server/data/seeders/importers/posts-authors-importer.js b/ghost/core/core/server/data/seeders/importers/posts-authors-importer.js index b994ceb5dda..001e93c05c7 100644 --- a/ghost/core/core/server/data/seeders/importers/posts-authors-importer.js +++ b/ghost/core/core/server/data/seeders/importers/posts-authors-importer.js @@ -23,7 +23,7 @@ class PostsAuthorsImporter extends TableImporter { return { id: this.fastFakeObjectId(), post_id: this.model.id, - author_id: this.users[faker.datatype.number(this.users.length - 1)].id, + author_id: this.users[faker.number.int(this.users.length - 1)].id, sort_order: sortOrder }; } diff --git a/ghost/core/core/server/data/seeders/importers/posts-importer.js b/ghost/core/core/server/data/seeders/importers/posts-importer.js index a131979f1c0..2de87922b07 100644 --- a/ghost/core/core/server/data/seeders/importers/posts-importer.js +++ b/ghost/core/core/server/data/seeders/importers/posts-importer.js @@ -7,7 +7,7 @@ const dateToDatabaseString = require('../utils/database-date'); class PostsImporter extends TableImporter { static table = 'posts'; static dependencies = ['newsletters']; - defaultQuantity = faker.datatype.number({ + defaultQuantity = faker.number.int({ min: 80, max: 120 }); @@ -26,7 +26,7 @@ class PostsImporter extends TableImporter { generate() { const title = faker.lorem.sentence(); - const content = faker.lorem.paragraphs(faker.datatype.number({ + const content = faker.lorem.paragraphs(faker.number.int({ min: 3, max: 10 })).split('\n'); @@ -34,7 +34,7 @@ class PostsImporter extends TableImporter { twoYearsAgo.setFullYear(twoYearsAgo.getFullYear() - 2); const twoWeeksFromNow = new Date(); twoWeeksFromNow.setDate(twoWeeksFromNow.getDate() + 14); - const timestamp = faker.date.between(twoYearsAgo, twoWeeksFromNow); + const timestamp = faker.date.between({from: twoYearsAgo, to: twoWeeksFromNow}); const currentTime = new Date(); let status = 'published'; @@ -55,12 +55,12 @@ class PostsImporter extends TableImporter { id, created_at: dateToDatabaseString(timestamp), updated_at: dateToDatabaseString(timestamp), - published_at: status === 'published' ? dateToDatabaseString(timestamp) : status === 'scheduled' ? dateToDatabaseString(faker.date.soon(5, timestamp)) : null, - uuid: faker.datatype.uuid(), + published_at: status === 'published' ? dateToDatabaseString(timestamp) : status === 'scheduled' ? dateToDatabaseString(faker.date.soon({days: 5, refDate: timestamp})) : null, + uuid: faker.string.uuid(), comment_id: this.type === 'post' ? id : null, title: title, type: this.type, - slug: `${slugify(title)}-${faker.random.numeric(3)}`, + slug: `${slugify(title)}-${faker.string.numeric(3)}`, status, visibility, lexical: JSON.stringify({ diff --git a/ghost/core/core/server/data/seeders/importers/posts-tags-importer.js b/ghost/core/core/server/data/seeders/importers/posts-tags-importer.js index 43248297901..1294c3b87d1 100644 --- a/ghost/core/core/server/data/seeders/importers/posts-tags-importer.js +++ b/ghost/core/core/server/data/seeders/importers/posts-tags-importer.js @@ -14,7 +14,7 @@ class PostsTagsImporter extends TableImporter { const posts = await this.transaction.select('id').from('posts').where('type', 'post'); this.tags = await this.transaction.select('id').from('tags'); - await this.importForEach(posts, quantity ? quantity / posts.length : () => faker.datatype.number({ + await this.importForEach(posts, quantity ? quantity / posts.length : () => faker.number.int({ min: 0, max: 3 })); @@ -30,7 +30,7 @@ class PostsTagsImporter extends TableImporter { this.sortOrder = this.sortOrder + 1; let tagIndex = 0; do { - tagIndex = faker.datatype.number(this.tags.length - 1); + tagIndex = faker.number.int(this.tags.length - 1); } while (this.notIndex.includes(tagIndex)); this.notIndex.push(tagIndex); diff --git a/ghost/core/core/server/data/seeders/importers/products-importer.js b/ghost/core/core/server/data/seeders/importers/products-importer.js index d2bc0cfef84..98111d737a0 100644 --- a/ghost/core/core/server/data/seeders/importers/products-importer.js +++ b/ghost/core/core/server/data/seeders/importers/products-importer.js @@ -80,9 +80,9 @@ class ProductsImporter extends TableImporter { return Object.assign({}, { id: this.fastFakeObjectId(), name: name, - slug: `${slugify(name)}-${faker.random.numeric(3)}`, + slug: `${slugify(name)}-${faker.string.numeric(3)}`, visibility: 'public', - created_at: faker.date.between(blogStartDate, sixMonthsLater) + created_at: faker.date.between({from: blogStartDate, to: sixMonthsLater}) }, tierInfo); } } diff --git a/ghost/core/core/server/data/seeders/importers/recommendation-click-events-importer.js b/ghost/core/core/server/data/seeders/importers/recommendation-click-events-importer.js index 1d83c5861c5..c8d9b6d2dae 100644 --- a/ghost/core/core/server/data/seeders/importers/recommendation-click-events-importer.js +++ b/ghost/core/core/server/data/seeders/importers/recommendation-click-events-importer.js @@ -14,7 +14,7 @@ class RecommendationClickEventsImporter extends TableImporter { const recommendations = await this.transaction.select('id', 'created_at').from('recommendations'); this.members = await this.transaction.select('id').from('members').limit(500); - await this.importForEach(recommendations, quantity ? quantity / recommendations.length : () => faker.datatype.number({min: 0, max: 30})); + await this.importForEach(recommendations, quantity ? quantity / recommendations.length : () => faker.number.int({min: 0, max: 30})); } generate() { diff --git a/ghost/core/core/server/data/seeders/importers/recommendation-subscribe-events-importer.js b/ghost/core/core/server/data/seeders/importers/recommendation-subscribe-events-importer.js index 43b4867d547..7984291f00e 100644 --- a/ghost/core/core/server/data/seeders/importers/recommendation-subscribe-events-importer.js +++ b/ghost/core/core/server/data/seeders/importers/recommendation-subscribe-events-importer.js @@ -14,7 +14,7 @@ class RecommendationSubscribeEventsImporter extends TableImporter { const recommendations = await this.transaction.select('id', 'created_at').from('recommendations').where('one_click_subscribe', true); this.members = await this.transaction.select('id').from('members').limit(500); - await this.importForEach(recommendations, quantity ? quantity / recommendations.length : () => faker.datatype.number({min: 0, max: 50})); + await this.importForEach(recommendations, quantity ? quantity / recommendations.length : () => faker.number.int({min: 0, max: 50})); } generate() { diff --git a/ghost/core/core/server/data/seeders/importers/redirects-importer.js b/ghost/core/core/server/data/seeders/importers/redirects-importer.js index 53555fae360..67b644a4de6 100644 --- a/ghost/core/core/server/data/seeders/importers/redirects-importer.js +++ b/ghost/core/core/server/data/seeders/importers/redirects-importer.js @@ -1,5 +1,6 @@ const TableImporter = require('./table-importer'); const {faker} = require('@faker-js/faker'); +const {slugify} = require('@tryghost/string'); class RedirectsImporter extends TableImporter { static table = 'redirects'; @@ -24,7 +25,7 @@ class RedirectsImporter extends TableImporter { this.model = model; // Reset the amount for each model - this.amount = faker.datatype.number({ + this.amount = faker.number.int({ min: 0, max: this.quantity }); @@ -37,8 +38,8 @@ class RedirectsImporter extends TableImporter { this.amount -= 1; return { id: this.fastFakeObjectId(), - from: `/r/${faker.datatype.hexadecimal({length: 8, prefix: '', case: 'lower'})}`, - to: `${faker.internet.url()}/${faker.helpers.slugify(`${faker.word.adjective()} ${faker.word.noun()}`).toLowerCase()}`, + from: `/r/${faker.string.hexadecimal({length: 8, prefix: '', casing: 'lower'})}`, + to: `${faker.internet.url()}/${slugify(`${faker.word.adjective()} ${faker.word.noun()}`).toLowerCase()}`, post_id: this.model.id, created_at: this.model.published_at, updated_at: this.model.published_at diff --git a/ghost/core/core/server/data/seeders/importers/roles-users-importer.js b/ghost/core/core/server/data/seeders/importers/roles-users-importer.js index 8677b592966..d0b50515020 100644 --- a/ghost/core/core/server/data/seeders/importers/roles-users-importer.js +++ b/ghost/core/core/server/data/seeders/importers/roles-users-importer.js @@ -27,7 +27,7 @@ class RolesUsersImporter extends TableImporter { generate() { const userRoles = ['Editor', 'Contributor', 'Author']; - const userRole = userRoles[faker.datatype.number({ + const userRole = userRoles[faker.number.int({ min: 0, max: userRoles.length - 1 })]; diff --git a/ghost/core/core/server/data/seeders/importers/stripe-prices-importer.js b/ghost/core/core/server/data/seeders/importers/stripe-prices-importer.js index 6d8b1a1b573..4670f961f1c 100644 --- a/ghost/core/core/server/data/seeders/importers/stripe-prices-importer.js +++ b/ghost/core/core/server/data/seeders/importers/stripe-prices-importer.js @@ -55,13 +55,13 @@ class StripePricesImporter extends TableImporter { return Object.assign({}, { id: this.fastFakeObjectId(), - stripe_price_id: faker.datatype.hexadecimal({ + stripe_price_id: faker.string.hexadecimal({ length: 64, prefix: '' }), stripe_product_id: this.model.stripe_product_id, active: true, - created_at: faker.date.between(blogStartDate, sixWeeksLater) + created_at: faker.date.between({from: blogStartDate, to: sixWeeksLater}) }, billingCycle); } } diff --git a/ghost/core/core/server/data/seeders/importers/stripe-products-importer.js b/ghost/core/core/server/data/seeders/importers/stripe-products-importer.js index cbae67f0781..b6c97cd1a35 100644 --- a/ghost/core/core/server/data/seeders/importers/stripe-products-importer.js +++ b/ghost/core/core/server/data/seeders/importers/stripe-products-importer.js @@ -22,11 +22,11 @@ class StripeProductsImporter extends TableImporter { return { id: this.fastFakeObjectId(), product_id: this.model.id, - stripe_product_id: faker.datatype.hexadecimal({ + stripe_product_id: faker.string.hexadecimal({ length: 64, prefix: '' }), - created_at: faker.date.between(blogStartDate, sixWeeksLater) + created_at: faker.date.between({from: blogStartDate, to: sixWeeksLater}) }; } } diff --git a/ghost/core/core/server/data/seeders/importers/tags-importer.js b/ghost/core/core/server/data/seeders/importers/tags-importer.js index fad371501c8..3b3f95f4f6b 100644 --- a/ghost/core/core/server/data/seeders/importers/tags-importer.js +++ b/ghost/core/core/server/data/seeders/importers/tags-importer.js @@ -6,7 +6,7 @@ const dateToDatabaseString = require('../utils/database-date'); class TagsImporter extends TableImporter { static table = 'tags'; static dependencies = ['users']; - defaultQuantity = faker.datatype.number({ + defaultQuantity = faker.number.int({ min: 16, max: 24 }); @@ -21,7 +21,7 @@ class TagsImporter extends TableImporter { } generate() { - let name = `${faker.color.human()} ${faker.name.jobType()} ${faker.random.numeric(10)}`; + let name = `${faker.color.human()} ${faker.person.jobType()} ${faker.string.numeric(10)}`; name = `${name[0].toUpperCase()}${name.slice(1)}`; const threeYearsAgo = new Date(); threeYearsAgo.setFullYear(threeYearsAgo.getFullYear() - 3); @@ -32,7 +32,7 @@ class TagsImporter extends TableImporter { name: name, slug: slugify(name), description: faker.lorem.sentence(), - created_at: dateToDatabaseString(faker.date.between(threeYearsAgo, twoYearsAgo)) + created_at: dateToDatabaseString(faker.date.between({from: threeYearsAgo, to: twoYearsAgo})) }; } } diff --git a/ghost/core/core/server/data/seeders/importers/users-importer.js b/ghost/core/core/server/data/seeders/importers/users-importer.js index 697d8d30a7d..f7924842fdd 100644 --- a/ghost/core/core/server/data/seeders/importers/users-importer.js +++ b/ghost/core/core/server/data/seeders/importers/users-importer.js @@ -14,15 +14,17 @@ class UsersImporter extends TableImporter { } async generate() { - const name = `${faker.name.firstName()} ${faker.name.lastName()}`; + const firstName = faker.person.firstName(); + const lastName = faker.person.lastName(); + const name = `${firstName} ${lastName}`; return { id: this.fastFakeObjectId(), name: name, slug: slugify(name), password: await security.password.hash(faker.color.human()), - email: faker.internet.email(name), - profile_image: faker.internet.avatar(), - created_at: dateToDatabaseString(faker.date.between(new Date(2016, 0), new Date())) + email: faker.internet.email({firstName, lastName}), + profile_image: faker.image.avatar(), + created_at: dateToDatabaseString(faker.date.between({from: new Date(2016, 0), to: new Date()})) }; } } diff --git a/ghost/core/core/server/data/seeders/importers/web-mentions-importer.js b/ghost/core/core/server/data/seeders/importers/web-mentions-importer.js index 397dfa1b3d5..87187655b18 100644 --- a/ghost/core/core/server/data/seeders/importers/web-mentions-importer.js +++ b/ghost/core/core/server/data/seeders/importers/web-mentions-importer.js @@ -16,7 +16,7 @@ class WebMentionsImporter extends TableImporter { generate() { const id = this.fastFakeObjectId(); - const author = `${faker.name.fullName()}`; + const author = `${faker.person.fullName()}`; // Generating only incoming recommendations for now, since we don't use webmentions for other things atm return { diff --git a/ghost/core/core/server/data/seeders/utils/database-date.js b/ghost/core/core/server/data/seeders/utils/database-date.js index 1a48d79aed5..1342e8a5ecc 100644 --- a/ghost/core/core/server/data/seeders/utils/database-date.js +++ b/ghost/core/core/server/data/seeders/utils/database-date.js @@ -26,7 +26,7 @@ dateToDatabaseString.randomBetween = function randomBetween(start, end) { const earliest = dateToDatabaseString.parse(start); const latest = dateToDatabaseString.parse(end); - return latest > earliest ? faker.date.between(earliest, latest) : earliest; + return latest > earliest ? faker.date.between({from: earliest, to: latest}) : earliest; }; module.exports = dateToDatabaseString; diff --git a/ghost/core/core/server/data/seeders/utils/random.js b/ghost/core/core/server/data/seeders/utils/random.js index 49a9b345975..06b6a1d1cf1 100644 --- a/ghost/core/core/server/data/seeders/utils/random.js +++ b/ghost/core/core/server/data/seeders/utils/random.js @@ -5,7 +5,7 @@ const {faker} = require('@faker-js/faker'); * @param {number} lowerThan Only this % of people will achieve this luck * @returns {boolean} Whether this person is lucky enough for the condition */ -const luck = lowerThan => faker.datatype.number({ +const luck = lowerThan => faker.number.int({ min: 1, max: 100 }) <= lowerThan; diff --git a/ghost/core/package.json b/ghost/core/package.json index 610dcb193a2..28dd12e548a 100644 --- a/ghost/core/package.json +++ b/ghost/core/package.json @@ -84,7 +84,7 @@ "dependencies": { "@aws-sdk/client-s3": "3.1053.0", "@extractus/oembed-extractor": "3.2.1", - "@faker-js/faker": "7.6.0", + "@faker-js/faker": "catalog:", "@isaacs/ttlcache": "1.4.1", "@sentry/node": "7.120.4", "@tryghost/adapter-base-cache": "0.1.25", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0679c3f2cc..37b2bcb69f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2283,8 +2283,8 @@ importers: specifier: 3.2.1 version: 3.2.1(encoding@0.1.13) '@faker-js/faker': - specifier: 7.6.0 - version: 7.6.0 + specifier: 'catalog:' + version: 9.9.0 '@isaacs/ttlcache': specifier: 1.4.1 version: 1.4.1