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": [ diff --git a/apps/activitypub/package.json b/apps/activitypub/package.json index 17beedf95be..cd41e1103f0 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.32", "license": "MIT", "repository": { "type": "git", @@ -38,14 +38,14 @@ }, "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/react": "14.3.1", + "@testing-library/react": "catalog:", "@types/jest": "catalog:", "@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:", @@ -80,15 +80,15 @@ }, "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:*", "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 7fe80999129..59c43e18378 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:", @@ -44,16 +44,16 @@ "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", "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:", @@ -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 54254653521..b0825227641 100644 --- a/apps/admin-x-framework/package.json +++ b/apps/admin-x-framework/package.json @@ -74,8 +74,8 @@ ], "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/jest-dom": "5.17.0", - "@testing-library/react": "14.3.1", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:", "@tryghost/koenig-lexical": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", @@ -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:", @@ -97,16 +97,16 @@ "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", "@tryghost/admin-x-design-system": "workspace:*", "@tryghost/shade": "workspace:*", "bson-objectid": "catalog:", - "react": "18.3.1", - "react-dom": "18.3.1", - "react-hot-toast": "2.6.0", + "react": "catalog:", + "react-dom": "catalog:", + "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 3fefc2287a4..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,18 +63,18 @@ "clsx": "catalog:", "jszip": "3.10.1", "lucide-react": "catalog:", - "mingo": "2.5.3", - "react": "18.3.1", - "react-dom": "18.3.1", - "react-hot-toast": "2.6.0", + "mingo": "catalog:", + "react": "catalog:", + "react-dom": "catalog:", + "react-hot-toast": "catalog:", "react-select": "5.10.2", "sonner": "catalog:", "validator": "catalog:" }, "devDependencies": { "@playwright/test": "catalog:", - "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "14.3.1", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:", "@tryghost/admin-x-design-system": "workspace:*", "@tryghost/admin-x-framework": "workspace:*", "@tryghost/custom-fonts": "catalog:", @@ -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..ccb82720717 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -21,26 +21,26 @@ "@tryghost/posts": "workspace:*", "@tryghost/shade": "workspace:*", "@tryghost/stats": "workspace:*", - "mingo": "2.5.3", - "react": "18.3.1", - "react-dom": "18.3.1", + "mingo": "catalog:", + "react": "catalog:", + "react-dom": "catalog:", "zod": "catalog:" }, "devDependencies": { "@eslint/js": "catalog:eslint9", "@tailwindcss/vite": "catalog:", "@tanstack/react-query": "catalog:", - "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "14.3.1", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:", "@types/node": "catalog:", "@types/react": "catalog:", "@types/react-dom": "catalog:", "@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/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 6a47ccb414d..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": "5.17.0", - "@testing-library/react": "12.1.5", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:react17", "@tryghost/i18n": "workspace:*", "@tryghost/nql": "catalog:", "@vitejs/plugin-react": "catalog:", @@ -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/portal/package.json b/apps/portal/package.json index 9ec247d8a71..ad2fc682cdf 100644 --- a/apps/portal/package.json +++ b/apps/portal/package.json @@ -111,8 +111,8 @@ "devDependencies": { "@doist/react-interpolate": "2.2.2", "@sentry/react": "catalog:", - "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "12.1.5", + "@testing-library/jest-dom": "catalog:", + "@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 e5331c1c9f7..ceeb4f84a2e 100644 --- a/apps/posts/package.json +++ b/apps/posts/package.json @@ -40,17 +40,17 @@ "@playwright/test": "catalog:", "@tanstack/react-query": "catalog:", "@tanstack/react-virtual": "3.13.25", - "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "14.3.1", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:", "@types/jest": "catalog:", "@types/papaparse": "5.5.2", "@types/react": "catalog:", "@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:", @@ -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:", @@ -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 fe3b604ce85..80922eb3a2d 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:", @@ -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:", @@ -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:", @@ -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 03330d789a7..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:", @@ -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/sodo-search/package.json b/apps/sodo-search/package.json index e6ad60ae069..0d18fee69a8 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", @@ -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\"", @@ -93,8 +93,8 @@ ] }, "devDependencies": { - "@testing-library/jest-dom": "5.17.0", - "@testing-library/react": "12.1.5", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:react17", "@vitejs/plugin-react": "catalog:", "@vitest/coverage-v8": "catalog:", "concurrently": "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 0b60d6d6f1c..ba12ef78b57 100644 --- a/apps/stats/package.json +++ b/apps/stats/package.json @@ -37,9 +37,9 @@ "preview": "vite preview" }, "devDependencies": { - "@faker-js/faker": "9.9.0", - "@testing-library/jest-dom": "6.9.1", - "@testing-library/react": "14.3.1", + "@faker-js/faker": "catalog:", + "@testing-library/jest-dom": "catalog:", + "@testing-library/react": "catalog:", "@types/jest": "catalog:", "@types/node": "catalog:", "@types/react": "catalog:", @@ -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:", @@ -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/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/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/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/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/package.json b/ghost/core/package.json index ac52c797263..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", @@ -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", @@ -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" @@ -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/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/) 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 218e6ace6e1..37b2bcb69f5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,12 +6,42 @@ 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 + '@faker-js/faker': + specifier: 9.9.0 + version: 9.9.0 '@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 @@ -33,6 +63,12 @@ catalogs: '@tanstack/react-query': specifier: 4.44.0 version: 4.44.0 + '@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 @@ -132,9 +168,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 @@ -153,6 +195,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 @@ -168,6 +213,15 @@ 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-hot-toast: + specifier: 2.6.0 + version: 2.6.0 react-router: specifier: 7.14.0 version: 7.14.0 @@ -183,6 +237,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 @@ -214,7 +271,20 @@ 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 + version: 3.18.2 tailwindcss: specifier: 3.4.18 version: 3.4.18 @@ -335,7 +405,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:' @@ -356,10 +426,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 @@ -381,7 +451,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:' @@ -396,13 +466,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 @@ -447,13 +517,13 @@ importers: specifier: workspace:* version: link:../stats mingo: - specifier: 2.5.3 + specifier: 'catalog:' 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:' @@ -469,10 +539,10 @@ 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 + 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:' @@ -493,13 +563,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 @@ -566,34 +636,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:' @@ -611,7 +681,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 @@ -639,7 +709,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 @@ -675,13 +745,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:' @@ -699,10 +769,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:' @@ -732,7 +802,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:' @@ -753,13 +823,13 @@ 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 + specifier: 'catalog:' version: 2.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-router: specifier: 'catalog:' @@ -769,10 +839,10 @@ 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 + 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:' @@ -796,13 +866,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:' @@ -862,7 +932,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:' @@ -904,16 +974,16 @@ importers: specifier: 'catalog:' version: 1.17.0(react@18.3.1) mingo: - specifier: 2.5.3 + specifier: 'catalog:' 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 + 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 @@ -929,10 +999,10 @@ 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 + 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:* @@ -965,13 +1035,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:' @@ -989,10 +1059,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': @@ -1065,10 +1135,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 @@ -1078,10 +1148,10 @@ 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 + 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:* @@ -1111,7 +1181,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:' @@ -1154,10 +1224,10 @@ 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 + 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 @@ -1196,10 +1266,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:' @@ -1217,7 +1287,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:* @@ -1253,10 +1323,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:' @@ -1287,10 +1357,10 @@ 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 + 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:' @@ -1311,13 +1381,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:' @@ -1350,10 +1420,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 @@ -1368,13 +1438,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 @@ -1383,10 +1453,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 @@ -1395,7 +1465,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:' @@ -1428,13 +1498,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 @@ -1474,7 +1544,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:' @@ -1498,8 +1568,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 +1577,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:' @@ -1531,7 +1601,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:' @@ -1555,10 +1625,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': @@ -1598,7 +1668,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:' @@ -1637,17 +1707,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: 5.17.0 - version: 5.17.0 + 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:' @@ -1704,23 +1774,23 @@ 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 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: 6.9.1 + 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:' @@ -1744,13 +1814,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:' @@ -1774,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 @@ -2171,10 +2241,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 @@ -2213,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 @@ -2588,7 +2658,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 @@ -2678,7 +2748,7 @@ importers: specifier: 1.0.1 version: 1.0.1 zod: - specifier: 4.1.12 + specifier: 'catalog:' version: 4.1.12 devDependencies: '@actions/core': @@ -2835,7 +2905,7 @@ importers: specifier: 0.2.6 version: 0.2.6 tsx: - specifier: 4.21.0 + specifier: 'catalog:' version: 4.21.0 typescript: specifier: 'catalog:' @@ -2904,7 +2974,7 @@ importers: specifier: 'catalog:' version: 11.7.6 tsx: - specifier: 4.21.0 + specifier: 'catalog:' version: 4.21.0 typescript: specifier: 'catalog:' @@ -4797,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'} @@ -5238,10 +5304,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} @@ -5266,10 +5328,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} @@ -5323,10 +5381,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: @@ -8322,10 +8376,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'} @@ -8979,9 +9029,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==} @@ -9172,9 +9219,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==} @@ -11076,10 +11120,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'} @@ -13540,12 +13580,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'} @@ -13804,10 +13838,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==} @@ -15648,10 +15678,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} @@ -15660,10 +15686,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} @@ -15672,10 +15694,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'} @@ -15693,10 +15711,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} @@ -15729,10 +15743,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} @@ -24345,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)': @@ -24837,10 +24845,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 @@ -24880,11 +24884,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 @@ -25013,16 +25012,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 @@ -28204,18 +28193,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 @@ -29372,11 +29349,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': @@ -29590,10 +29562,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': @@ -32616,11 +32584,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 @@ -35989,7 +35952,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 @@ -36410,15 +36373,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): @@ -38799,13 +38753,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 @@ -38830,19 +38777,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 @@ -38855,12 +38789,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 @@ -38869,8 +38797,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 @@ -39012,15 +38938,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 4623031b7ba..5c25ce92910 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -25,8 +25,18 @@ allowBuilds: ssh2: true 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 + '@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 @@ -34,6 +44,8 @@ catalog: '@tailwindcss/postcss': 4.2.2 '@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 @@ -68,23 +80,30 @@ 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 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 postcss: 8.5.10 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 @@ -98,8 +117,13 @@ 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 overrides: '@tryghost/errors': ^1.3.7 @@ -166,51 +190,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/*"