From 6e4ffcae2caa2a95f3ac61ea8f64c86dc20da5cb Mon Sep 17 00:00:00 2001 From: Derrick Mehaffy Date: Fri, 20 Sep 2024 21:06:51 -0700 Subject: [PATCH 01/18] chore: change all internal cron tasks to named tasks --- packages/core/admin/ee/server/src/services/metrics.ts | 5 ++++- packages/core/admin/server/src/services/metrics.ts | 5 ++++- packages/core/core/src/ee/index.ts | 8 +++++++- .../server/src/services/metrics/weekly-metrics.ts | 7 ++++++- .../core/upload/server/src/services/weekly-metrics.ts | 7 ++++++- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/core/admin/ee/server/src/services/metrics.ts b/packages/core/admin/ee/server/src/services/metrics.ts index 18fb9d6a42..0f46432c2e 100644 --- a/packages/core/admin/ee/server/src/services/metrics.ts +++ b/packages/core/admin/ee/server/src/services/metrics.ts @@ -49,7 +49,10 @@ const sendUpdateProjectInformation = async (strapi: Core.Strapi) => { const startCron = (strapi: Core.Strapi) => { strapi.cron.add({ - '0 0 0 * * *': () => sendUpdateProjectInformation(strapi), + sendProjectInformation: { + task: () => sendUpdateProjectInformation(strapi), + options: '0 0 0 * * *', + }, }); }; diff --git a/packages/core/admin/server/src/services/metrics.ts b/packages/core/admin/server/src/services/metrics.ts index 67626e7b97..b5818ed7a6 100644 --- a/packages/core/admin/server/src/services/metrics.ts +++ b/packages/core/admin/server/src/services/metrics.ts @@ -30,7 +30,10 @@ const sendUpdateProjectInformation = async (strapi: Core.Strapi) => { const startCron = (strapi: Core.Strapi) => { strapi.cron.add({ - '0 0 0 * * *': () => sendUpdateProjectInformation(strapi), + sendProjectInformation: { + task: () => sendUpdateProjectInformation(strapi), + options: '0 0 0 * * *', + }, }); }; diff --git a/packages/core/core/src/ee/index.ts b/packages/core/core/src/ee/index.ts index 770107d725..f22302bd53 100644 --- a/packages/core/core/src/ee/index.ts +++ b/packages/core/core/src/ee/index.ts @@ -205,7 +205,13 @@ const checkLicense = async ({ strapi }: { strapi: Core.Strapi }) => { if (!shouldStayOffline) { await onlineUpdate({ strapi }); - strapi.cron.add({ [shiftCronExpression('0 0 */12 * * *')]: onlineUpdate }); + + strapi.cron.add({ + onlineUpdate: { + task: () => onlineUpdate({ strapi }), + options: shiftCronExpression('0 0 */12 * * *'), + }, + }); } else { if (!ee.licenseInfo.expireAt) { return disable('Your license does not have offline support.'); diff --git a/packages/core/review-workflows/server/src/services/metrics/weekly-metrics.ts b/packages/core/review-workflows/server/src/services/metrics/weekly-metrics.ts index 8bd5913d87..b6efeae3c2 100644 --- a/packages/core/review-workflows/server/src/services/metrics/weekly-metrics.ts +++ b/packages/core/review-workflows/server/src/services/metrics/weekly-metrics.ts @@ -70,7 +70,12 @@ export default ({ strapi }: { strapi: Core.Strapi }) => { async registerCron() { const weeklySchedule = await this.ensureWeeklyStoredCronSchedule(); - strapi.cron.add({ [weeklySchedule]: this.sendMetrics.bind(this) }); + strapi.cron.add({ + reviewWorkflowsWeekly: { + task: this.sendMetrics.bind(this), + options: weeklySchedule, + }, + }); }, }; }; diff --git a/packages/core/upload/server/src/services/weekly-metrics.ts b/packages/core/upload/server/src/services/weekly-metrics.ts index b415e8aff2..b70d4cf2d1 100644 --- a/packages/core/upload/server/src/services/weekly-metrics.ts +++ b/packages/core/upload/server/src/services/weekly-metrics.ts @@ -129,6 +129,11 @@ export default ({ strapi }: { strapi: Core.Strapi }) => ({ async registerCron() { const weeklySchedule = await this.ensureWeeklyStoredCronSchedule(); - strapi.cron.add({ [weeklySchedule]: this.sendMetrics.bind(this) }); + strapi.cron.add({ + uploadWeekly: { + task: this.sendMetrics.bind(this), + options: weeklySchedule, + }, + }); }, }); From 8dc5aa273027084a90fa711e4068dfa8fbd09e1e Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Mon, 23 Sep 2024 13:37:06 +0200 Subject: [PATCH 02/18] chore: upgrade webpack-dev-middleware to 6.1.2 (#21327) --- packages/core/strapi/package.json | 4 +- yarn.lock | 81 +++++++++++++++++++++---------- 2 files changed, 58 insertions(+), 27 deletions(-) diff --git a/packages/core/strapi/package.json b/packages/core/strapi/package.json index 44de9ae465..4547f7ce7c 100644 --- a/packages/core/strapi/package.json +++ b/packages/core/strapi/package.json @@ -108,7 +108,7 @@ "watch": "pack-up watch" }, "dependencies": { - "@pmmmwh/react-refresh-webpack-plugin": "0.5.11", + "@pmmmwh/react-refresh-webpack-plugin": "0.5.15", "@strapi/admin": "workspace:*", "@strapi/cloud-cli": "workspace:*", "@strapi/content-manager": "workspace:*", @@ -169,7 +169,7 @@ "vite": "5.1.7", "webpack": "^5.90.3", "webpack-bundle-analyzer": "^4.10.1", - "webpack-dev-middleware": "6.1.1", + "webpack-dev-middleware": "6.1.2", "webpack-hot-middleware": "2.26.1", "yalc": "1.0.0-pre.53", "yup": "0.32.9" diff --git a/yarn.lock b/yarn.lock index 97bed84f3e..17f4d25eb6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5677,18 +5677,16 @@ __metadata: languageName: node linkType: hard -"@pmmmwh/react-refresh-webpack-plugin@npm:0.5.11": - version: 0.5.11 - resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.11" +"@pmmmwh/react-refresh-webpack-plugin@npm:0.5.15": + version: 0.5.15 + resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.15" dependencies: - ansi-html-community: "npm:^0.0.8" - common-path-prefix: "npm:^3.0.0" + ansi-html: "npm:^0.0.9" core-js-pure: "npm:^3.23.3" error-stack-parser: "npm:^2.0.6" - find-up: "npm:^5.0.0" html-entities: "npm:^2.1.0" loader-utils: "npm:^2.0.4" - schema-utils: "npm:^3.0.0" + schema-utils: "npm:^4.2.0" source-map: "npm:^0.7.3" peerDependencies: "@types/webpack": 4.x || 5.x @@ -5696,7 +5694,7 @@ __metadata: sockjs-client: ^1.4.0 type-fest: ">=0.17.0 <5.0.0" webpack: ">=4.43.0 <6.0.0" - webpack-dev-server: 3.x || 4.x + webpack-dev-server: 3.x || 4.x || 5.x webpack-hot-middleware: 2.x webpack-plugin-serve: 0.x || 1.x peerDependenciesMeta: @@ -5712,7 +5710,7 @@ __metadata: optional: true webpack-plugin-serve: optional: true - checksum: 10c0/a9c8468417a14a23339e313cff6ddb8029e0637748973070e61d83a2534620b3492b9a42ecf9eb9d63cb709f53c17fe814bc7dd68d64c300db338e9fd7287bc4 + checksum: 10c0/ba310aa4d53070f59c8a374d1d256c5965c044c0c3fb1ff6b55353fb5e86de08a490a7bd59a31f0d4951f8f29f81864c7df224fe1342543a95d048b7413ff171 languageName: node linkType: hard @@ -9474,7 +9472,7 @@ __metadata: version: 0.0.0-use.local resolution: "@strapi/strapi@workspace:packages/core/strapi" dependencies: - "@pmmmwh/react-refresh-webpack-plugin": "npm:0.5.11" + "@pmmmwh/react-refresh-webpack-plugin": "npm:0.5.15" "@strapi/admin": "workspace:*" "@strapi/cloud-cli": "workspace:*" "@strapi/content-manager": "workspace:*" @@ -9547,7 +9545,7 @@ __metadata: vite: "npm:5.1.7" webpack: "npm:^5.90.3" webpack-bundle-analyzer: "npm:^4.10.1" - webpack-dev-middleware: "npm:6.1.1" + webpack-dev-middleware: "npm:6.1.2" webpack-hot-middleware: "npm:2.26.1" yalc: "npm:1.0.0-pre.53" yup: "npm:0.32.9" @@ -12408,7 +12406,7 @@ __metadata: languageName: node linkType: hard -"ajv-keywords@npm:^5.0.0": +"ajv-keywords@npm:^5.0.0, ajv-keywords@npm:^5.1.0": version: 5.1.0 resolution: "ajv-keywords@npm:5.1.0" dependencies: @@ -12467,6 +12465,18 @@ __metadata: languageName: node linkType: hard +"ajv@npm:^8.9.0": + version: 8.17.1 + resolution: "ajv@npm:8.17.1" + dependencies: + fast-deep-equal: "npm:^3.1.3" + fast-uri: "npm:^3.0.1" + json-schema-traverse: "npm:^1.0.0" + require-from-string: "npm:^2.0.2" + checksum: 10c0/ec3ba10a573c6b60f94639ffc53526275917a2df6810e4ab5a6b959d87459f9ef3f00d5e7865b82677cb7d21590355b34da14d1d0b9c32d75f95a187e76fff35 + languageName: node + linkType: hard + "ansi-align@npm:^3.0.0": version: 3.0.1 resolution: "ansi-align@npm:3.0.1" @@ -12510,7 +12520,7 @@ __metadata: languageName: node linkType: hard -"ansi-html-community@npm:0.0.8, ansi-html-community@npm:^0.0.8": +"ansi-html-community@npm:0.0.8": version: 0.0.8 resolution: "ansi-html-community@npm:0.0.8" bin: @@ -12519,6 +12529,15 @@ __metadata: languageName: node linkType: hard +"ansi-html@npm:^0.0.9": + version: 0.0.9 + resolution: "ansi-html@npm:0.0.9" + bin: + ansi-html: bin/ansi-html + checksum: 10c0/4a5de9802fb50193e32b51a9ea48dc0d7e4436b860cb819d7110c62f2bfb1410288e1a2f9a848269f5eab8f903797a7f0309fe4c552f92a92b61a5b759ed52bd + languageName: node + linkType: hard + "ansi-regex@npm:^2.0.0": version: 2.1.1 resolution: "ansi-regex@npm:2.1.1" @@ -14613,13 +14632,6 @@ __metadata: languageName: node linkType: hard -"common-path-prefix@npm:^3.0.0": - version: 3.0.0 - resolution: "common-path-prefix@npm:3.0.0" - checksum: 10c0/c4a74294e1b1570f4a8ab435285d185a03976c323caa16359053e749db4fde44e3e6586c29cd051100335e11895767cbbd27ea389108e327d62f38daf4548fdb - languageName: node - linkType: hard - "common-tags@npm:^1.8.0": version: 1.8.2 resolution: "common-tags@npm:1.8.2" @@ -18077,6 +18089,13 @@ __metadata: languageName: node linkType: hard +"fast-uri@npm:^3.0.1": + version: 3.0.1 + resolution: "fast-uri@npm:3.0.1" + checksum: 10c0/3cd46d6006083b14ca61ffe9a05b8eef75ef87e9574b6f68f2e17ecf4daa7aaadeff44e3f0f7a0ef4e0f7e7c20fc07beec49ff14dc72d0b500f00386592f2d10 + languageName: node + linkType: hard + "fast-xml-parser@npm:4.2.5": version: 4.2.5 resolution: "fast-xml-parser@npm:4.2.5" @@ -28670,7 +28689,7 @@ __metadata: languageName: node linkType: hard -"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": +"schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0": version: 3.3.0 resolution: "schema-utils@npm:3.3.0" dependencies: @@ -28693,6 +28712,18 @@ __metadata: languageName: node linkType: hard +"schema-utils@npm:^4.2.0": + version: 4.2.0 + resolution: "schema-utils@npm:4.2.0" + dependencies: + "@types/json-schema": "npm:^7.0.9" + ajv: "npm:^8.9.0" + ajv-formats: "npm:^2.1.1" + ajv-keywords: "npm:^5.1.0" + checksum: 10c0/8dab7e7800316387fd8569870b4b668cfcecf95ac551e369ea799bbcbfb63fb0365366d4b59f64822c9f7904d8c5afcfaf5a6124a4b08783e558cd25f299a6b4 + languageName: node + linkType: hard + "scripts-front@workspace:scripts/front": version: 0.0.0-use.local resolution: "scripts-front@workspace:scripts/front" @@ -32204,9 +32235,9 @@ __metadata: languageName: node linkType: hard -"webpack-dev-middleware@npm:6.1.1": - version: 6.1.1 - resolution: "webpack-dev-middleware@npm:6.1.1" +"webpack-dev-middleware@npm:6.1.2": + version: 6.1.2 + resolution: "webpack-dev-middleware@npm:6.1.2" dependencies: colorette: "npm:^2.0.10" memfs: "npm:^3.4.12" @@ -32218,7 +32249,7 @@ __metadata: peerDependenciesMeta: webpack: optional: true - checksum: 10c0/f8f5b7f7591fa3e4d4008b28ab2b5c13367a24587257e3e37cff31e2d8a6c859de5294af83c79e8faf3137db194377f392fffacdf5010b5c1311eba6f9b71568 + checksum: 10c0/90c415a770c7db493f4a7d8f3308d761ff63249f628fa8a133eac5a61e849cdf658398e189fc2d95ce0ea884641363f964db6b269c6cea877765321dd7f14b9a languageName: node linkType: hard From b50ce8a77e6e81657c52dc64d09b126acdcf5543 Mon Sep 17 00:00:00 2001 From: Bassel Kanso Date: Mon, 23 Sep 2024 16:27:11 +0300 Subject: [PATCH 03/18] fix: cannot create component from dynamic zone --- .../admin/src/components/SelectCategory.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/content-type-builder/admin/src/components/SelectCategory.tsx b/packages/core/content-type-builder/admin/src/components/SelectCategory.tsx index 28a8782743..2ed4a80f7b 100644 --- a/packages/core/content-type-builder/admin/src/components/SelectCategory.tsx +++ b/packages/core/content-type-builder/admin/src/components/SelectCategory.tsx @@ -16,6 +16,7 @@ interface SelectCategoryProps { onChange: (value: { target: { name: string; value: any; type: string } }) => void; value?: string; isCreating?: boolean; + dynamicZoneTarget?: string | null; } export const SelectCategory = ({ @@ -25,6 +26,7 @@ export const SelectCategory = ({ onChange, value = undefined, isCreating, + dynamicZoneTarget, }: SelectCategoryProps) => { const { formatMessage } = useIntl(); const { allComponentsCategories } = useDataManager(); @@ -48,7 +50,7 @@ export const SelectCategory = ({ Date: Mon, 23 Sep 2024 08:46:56 -0700 Subject: [PATCH 04/18] chore: add workflow for automatically closing v4 issues with label --- .github/workflows/issues_handleLabel.yml | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/issues_handleLabel.yml b/.github/workflows/issues_handleLabel.yml index baabf10c5d..cec3c8b7ae 100644 --- a/.github/workflows/issues_handleLabel.yml +++ b/.github/workflows/issues_handleLabel.yml @@ -70,6 +70,43 @@ jobs: issue-number: ${{ github.event.issue.number }} close-reason: 'not_planned' + # v4 Legacy Issues + - name: 'Comment: unsupported v4 issues' + if: "${{ github.event.label.name == 'flag: v4-unsupported' }}" + uses: actions-cool/issues-helper@v3 + with: + actions: 'create-comment' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + > This is a templated message + + Hello @${{ github.event.issue.user.login }}, + + Thank you for reporting this potential bug report, please keep in mind that we are no longer accepting low/medium severity bug reports for Strapi v4. + We have confirmed that this issue is a low/medium severity bug and is not reproducable in Strapi 5. We advise upgrading to Strapi 5 to resolve this issue. + + The recommended action we suggest for v4 users is to utilize the various migration resources to upgrade your package from Strapi 4 to Strapi 5: + + - [Updating documentation](https://docs.strapi.io/dev-docs/migration/v4-to-v5/introduction-and-faq) + - [Step by Step Guide](https://docs.strapi.io/dev-docs/migration/v4-to-v5/step-by-step) + - [Upgrade Tool](https://docs.strapi.io/dev-docs/upgrade-tool) + - [Breaking Changes list](https://docs.strapi.io/dev-docs/migration/v4-to-v5/breaking-changes) + - [Specific Resources](https://docs.strapi.io/dev-docs/migration/v4-to-v5/additional-resources/introduction) + + Please see our [Security file](https://github.com/strapi/strapi/security) for more information about supported versions. + For now this issue is marked as closed. + + Thank You + - name: 'Close: unsupported v4 issues' + if: "${{ github.event.label.name == 'flag: v4-unsupported' }}" + uses: actions-cool/issues-helper@v3 + with: + actions: 'close-issue' + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + close-reason: 'not_planned' + # Feature request redirections - name: 'Comment: redirect feature request to canny' if: "${{ github.event.label.name == 'issue: feature request' }}" From cb1dcabb44cbb8d6c474d6d8866e3f4006b60f90 Mon Sep 17 00:00:00 2001 From: Derrick Mehaffy Date: Mon, 23 Sep 2024 08:55:42 -0700 Subject: [PATCH 05/18] chore: Update security document in relation to Strapi 5 stable release --- SECURITY.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 8753aaa67f..9d6cf6b81f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,18 +2,20 @@ ## Supported Versions -As of April 2024 (and until this document is updated), only the v4.x.x _GA_ or _STABLE_ releases of Strapi are supported for updates and bug fixes. Any previous versions are currently not supported and users are advised to use them "at their own risk". +As of September 2024 (and until this document is updated), only the v4.x.x and v5.x.x _GA_ or _STABLE_ releases of Strapi are supported for updates and bug fixes. Any previous versions are currently not supported and users are advised to use them "at their own risk". -| Version | Release Tag | Support Starts | Support Ends | Security Updates Until | Notes | -| ------- | ----------- | -------------- | -------------- | ---------------------- | -------------------- | -| 5.x.x | GA | October 2024 | Further Notice | Further Notice | LTS (Future) | -| 5.x.x | RC | N/A | October 2024 | N/A | Non-Production Usage | -| 5.x.x | Beta | N/A | N/A | N/A | Not Supported | -| 5.x.x | Alpha | N/A | N/A | N/A | Not Supported | -| 4.x.x | GA | November 2021 | October 2025 | April 2026 | LTS | -| 4.x.x | Beta | N/A | N/A | N/A | Not Supported | -| 4.x.x | Alpha | N/A | N/A | N/A | Not Supported | -| 3.x.x | N/A | N/A | N/A | N/A | End Of Life | +**Note**: The v4.x.x LTS version will only receive high/critical severity fixes until April 2026. Any Medium/Low severity issues will not be fixed unless specific exceptions are made. + +| Version | Release Tag | Support Starts | Support Ends | Security Updates Until | Notes | +|---------|-------------|----------------|----------------|------------------------|--------------------------------| +| 5.x.x | GA / Stable | September 2024 | Further Notice | Further Notice | LTS | +| 5.x.x | RC | N/A | September 2024 | N/A | Not Supported | +| 5.x.x | Beta | N/A | N/A | N/A | Not Supported | +| 5.x.x | Alpha | N/A | N/A | N/A | Not Supported | +| 4.x.x | GA / Stable | November 2021 | October 2025 | April 2026 | LTS (High/Critical fixes only) | +| 4.x.x | Beta | N/A | N/A | N/A | Not Supported | +| 4.x.x | Alpha | N/A | N/A | N/A | Not Supported | +| 3.x.x | N/A | N/A | N/A | N/A | End Of Life | ## Reporting a Vulnerability From fc507797fe8259a8e5cab3f37563de06c08b003d Mon Sep 17 00:00:00 2001 From: DMehaffy Date: Mon, 23 Sep 2024 08:57:46 -0700 Subject: [PATCH 06/18] Update .github/workflows/issues_handleLabel.yml Co-authored-by: Alexandre BODIN --- .github/workflows/issues_handleLabel.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issues_handleLabel.yml b/.github/workflows/issues_handleLabel.yml index cec3c8b7ae..4a63199d36 100644 --- a/.github/workflows/issues_handleLabel.yml +++ b/.github/workflows/issues_handleLabel.yml @@ -86,7 +86,7 @@ jobs: Thank you for reporting this potential bug report, please keep in mind that we are no longer accepting low/medium severity bug reports for Strapi v4. We have confirmed that this issue is a low/medium severity bug and is not reproducable in Strapi 5. We advise upgrading to Strapi 5 to resolve this issue. - The recommended action we suggest for v4 users is to utilize the various migration resources to upgrade your package from Strapi 4 to Strapi 5: + The recommended action we suggest for v4 users is to utilize the various migration resources to upgrade from Strapi 4 to Strapi 5: - [Updating documentation](https://docs.strapi.io/dev-docs/migration/v4-to-v5/introduction-and-faq) - [Step by Step Guide](https://docs.strapi.io/dev-docs/migration/v4-to-v5/step-by-step) From 9cb35c0a30d6a1f359b6524865d3f07fee9f0eb4 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Tue, 24 Sep 2024 10:00:14 +0200 Subject: [PATCH 07/18] fix: use existing transaction to batch insert (#21404) --- .../document-service/utils/unidirectional-relations.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core/core/src/services/document-service/utils/unidirectional-relations.ts b/packages/core/core/src/services/document-service/utils/unidirectional-relations.ts index 6210b4bfe1..cec816d624 100644 --- a/packages/core/core/src/services/document-service/utils/unidirectional-relations.ts +++ b/packages/core/core/src/services/document-service/utils/unidirectional-relations.ts @@ -86,8 +86,6 @@ const sync = async ( ); await strapi.db.transaction(async ({ trx }) => { - const con = strapi.db.getConnection(); - // Iterate old relations that are deleted and insert the new ones for (const { joinTable, relations } of oldRelations) { // Update old ids with the new ones @@ -98,7 +96,7 @@ const sync = async ( }); // Insert those relations into the join table - await con.batchInsert(joinTable.name, newRelations).transacting(trx); + await trx.batchInsert(joinTable.name, newRelations, 1000); } }); }; From 55534e946613324d46c5db9c47ebe61964ae3512 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Tue, 24 Sep 2024 10:59:50 +0200 Subject: [PATCH 08/18] chore: update tar to 6.2.1 (#21328) --- package.json | 2 +- packages/cli/cloud/package.json | 2 +- packages/core/data-transfer/package.json | 2 +- yarn.lock | 16 ++++++++-------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index a4a444b207..a64df5f316 100644 --- a/package.json +++ b/package.json @@ -148,7 +148,7 @@ "stream-chain": "2.2.5", "stream-json": "1.8.0", "supertest": "6.3.3", - "tar": "6.1.13", + "tar": "6.2.1", "ts-jest": "29.1.0", "typescript": "5.3.2", "yalc": "1.0.0-pre.53", diff --git a/packages/cli/cloud/package.json b/packages/cli/cloud/package.json index bc0c066bb9..e5e54f1688 100644 --- a/packages/cli/cloud/package.json +++ b/packages/cli/cloud/package.json @@ -61,7 +61,7 @@ "open": "8.4.0", "ora": "5.4.1", "pkg-up": "3.1.0", - "tar": "6.1.13", + "tar": "6.2.1", "xdg-app-paths": "8.3.0", "yup": "0.32.9" }, diff --git a/packages/core/data-transfer/package.json b/packages/core/data-transfer/package.json index 614593b659..b8b04ff0ec 100644 --- a/packages/core/data-transfer/package.json +++ b/packages/core/data-transfer/package.json @@ -54,7 +54,7 @@ "semver": "7.5.4", "stream-chain": "2.2.5", "stream-json": "1.8.0", - "tar": "6.1.13", + "tar": "6.2.1", "tar-stream": "2.2.0", "ws": "8.17.1" }, diff --git a/yarn.lock b/yarn.lock index 17f4d25eb6..2c48d45756 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8471,7 +8471,7 @@ __metadata: open: "npm:8.4.0" ora: "npm:5.4.1" pkg-up: "npm:3.1.0" - tar: "npm:6.1.13" + tar: "npm:6.2.1" tsconfig: "workspace:*" xdg-app-paths: "npm:8.3.0" yup: "npm:0.32.9" @@ -8745,7 +8745,7 @@ __metadata: semver: "npm:7.5.4" stream-chain: "npm:2.2.5" stream-json: "npm:1.8.0" - tar: "npm:6.1.13" + tar: "npm:6.2.1" tar-stream: "npm:2.2.0" typescript: "npm:5.3.2" ws: "npm:8.17.1" @@ -29830,7 +29830,7 @@ __metadata: stream-chain: "npm:2.2.5" stream-json: "npm:1.8.0" supertest: "npm:6.3.3" - tar: "npm:6.1.13" + tar: "npm:6.2.1" ts-jest: "npm:29.1.0" typescript: "npm:5.3.2" yalc: "npm:1.0.0-pre.53" @@ -30481,17 +30481,17 @@ __metadata: languageName: node linkType: hard -"tar@npm:6.1.13": - version: 6.1.13 - resolution: "tar@npm:6.1.13" +"tar@npm:6.2.1": + version: 6.2.1 + resolution: "tar@npm:6.2.1" dependencies: chownr: "npm:^2.0.0" fs-minipass: "npm:^2.0.0" - minipass: "npm:^4.0.0" + minipass: "npm:^5.0.0" minizlib: "npm:^2.1.1" mkdirp: "npm:^1.0.3" yallist: "npm:^4.0.0" - checksum: 10c0/eee5f264f3f3c27cd8d4934f80c568470f92811c416144ab671bb36b45a8ed55fbfbbd31f0146f3eddaca91fd564c9a7ec4d2086940968b836f4a2c54146c060 + checksum: 10c0/a5eca3eb50bc11552d453488344e6507156b9193efd7635e98e867fab275d527af53d8866e2370cd09dfe74378a18111622ace35af6a608e5223a7d27fe99537 languageName: node linkType: hard From c7b2b2abcc5dff9a90efa3e0a78cca3f293996e5 Mon Sep 17 00:00:00 2001 From: Simone Date: Tue, 24 Sep 2024 11:01:14 +0200 Subject: [PATCH 09/18] chore: migrate media-library initial setup (#21375) * chore: migrate and create config files for the migration * chore: migrate test utils to TS * chore: fix the typo * chore: fix eslint errors * chore: fix prettier error --- SECURITY.md | 2 +- packages/core/upload/admin/.eslintrc | 12 ++++++++++++ .../Breadcrumbs/CrumbSimpleMenuAsync.jsx | 3 +-- .../FolderCard/tests/FolderCard.test.jsx | 2 +- .../pages/App/ConfigureTheView/state/reducer.js | 7 ++++++- .../core/upload/admin/src/utils/urlYupSchema.js | 1 + .../admin/tests/{handlers.js => handlers.ts} | 15 +++++++++++---- .../upload/admin/tests/{setup.js => setup.ts} | 0 .../upload/admin/tests/{utils.jsx => utils.ts} | 0 packages/core/upload/admin/tsconfig.build.json | 10 ++++++++++ packages/core/upload/admin/tsconfig.json | 11 +++++++++++ packages/core/upload/jest.config.front.js | 2 +- packages/core/upload/jsconfig.json | 8 -------- packages/core/upload/package.json | 11 +++++++++++ packages/core/upload/packup.config.ts | 4 +++- packages/core/upload/server/src/bootstrap.ts | 1 + .../controllers/validation/admin/folder-file.ts | 4 ++-- .../services/__tests__/upload/uploadImage.test.ts | 3 ++- .../extensions/__tests__/sign-media.test.ts | 15 ++++++++++++++- 19 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 packages/core/upload/admin/.eslintrc rename packages/core/upload/admin/tests/{handlers.js => handlers.ts} (90%) rename packages/core/upload/admin/tests/{setup.js => setup.ts} (100%) rename packages/core/upload/admin/tests/{utils.jsx => utils.ts} (100%) create mode 100644 packages/core/upload/admin/tsconfig.build.json create mode 100644 packages/core/upload/admin/tsconfig.json delete mode 100644 packages/core/upload/jsconfig.json diff --git a/SECURITY.md b/SECURITY.md index 9d6cf6b81f..dc920c827a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,7 +7,7 @@ As of September 2024 (and until this document is updated), only the v4.x.x and v **Note**: The v4.x.x LTS version will only receive high/critical severity fixes until April 2026. Any Medium/Low severity issues will not be fixed unless specific exceptions are made. | Version | Release Tag | Support Starts | Support Ends | Security Updates Until | Notes | -|---------|-------------|----------------|----------------|------------------------|--------------------------------| +| ------- | ----------- | -------------- | -------------- | ---------------------- | ------------------------------ | | 5.x.x | GA / Stable | September 2024 | Further Notice | Further Notice | LTS | | 5.x.x | RC | N/A | September 2024 | N/A | Not Supported | | 5.x.x | Beta | N/A | N/A | N/A | Not Supported | diff --git a/packages/core/upload/admin/.eslintrc b/packages/core/upload/admin/.eslintrc new file mode 100644 index 0000000000..46fc0d13cb --- /dev/null +++ b/packages/core/upload/admin/.eslintrc @@ -0,0 +1,12 @@ +{ + "root": true, + "overrides": [ + { + "files": ["**/*.js", "**/*.jsx"], + "extends": ["custom/front"], + "rules": { + "import/extensions": "off" + } + } + ] +} \ No newline at end of file diff --git a/packages/core/upload/admin/src/components/Breadcrumbs/CrumbSimpleMenuAsync.jsx b/packages/core/upload/admin/src/components/Breadcrumbs/CrumbSimpleMenuAsync.jsx index f863ede6e1..ad687f57f7 100644 --- a/packages/core/upload/admin/src/components/Breadcrumbs/CrumbSimpleMenuAsync.jsx +++ b/packages/core/upload/admin/src/components/Breadcrumbs/CrumbSimpleMenuAsync.jsx @@ -1,8 +1,7 @@ import React, { useState } from 'react'; import { useQueryParams } from '@strapi/admin/strapi-admin'; -import { Loader } from '@strapi/design-system'; -import { CrumbSimpleMenu, MenuItem } from '@strapi/design-system'; +import { CrumbSimpleMenu, Loader, MenuItem } from '@strapi/design-system'; import PropTypes from 'prop-types'; import { useIntl } from 'react-intl'; import { NavLink, useLocation } from 'react-router-dom'; diff --git a/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.jsx b/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.jsx index 43aa8a8a79..da07039c87 100644 --- a/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.jsx +++ b/packages/core/upload/admin/src/components/FolderCard/tests/FolderCard.test.jsx @@ -19,7 +19,7 @@ const ComponentFixture = ({ to, ...props }) => { } + startAction={null} onClick={() => {}} to={to} {...props} diff --git a/packages/core/upload/admin/src/pages/App/ConfigureTheView/state/reducer.js b/packages/core/upload/admin/src/pages/App/ConfigureTheView/state/reducer.js index c24678d5fb..baf069bff6 100644 --- a/packages/core/upload/admin/src/pages/App/ConfigureTheView/state/reducer.js +++ b/packages/core/upload/admin/src/pages/App/ConfigureTheView/state/reducer.js @@ -5,7 +5,12 @@ import set from 'lodash/set'; import { ON_CHANGE, SET_LOADED } from './actionTypes'; import { init, initialState } from './init'; -const reducer = (state = initialState, action) => +const reducer = ( + state = initialState, + action = { + type: '', + } +) => // eslint-disable-next-line consistent-return produce(state, (draftState) => { switch (action.type) { diff --git a/packages/core/upload/admin/src/utils/urlYupSchema.js b/packages/core/upload/admin/src/utils/urlYupSchema.js index c33a043b6e..70330926a0 100644 --- a/packages/core/upload/admin/src/utils/urlYupSchema.js +++ b/packages/core/upload/admin/src/utils/urlYupSchema.js @@ -6,6 +6,7 @@ import getTrad from './getTrad'; export const urlSchema = yup.object().shape({ urls: yup.string().test({ name: 'isUrlValid', + // eslint-disable-next-line no-template-curly-in-string message: '${path}', test(values = '') { const urls = values.split(/\r?\n/); diff --git a/packages/core/upload/admin/tests/handlers.js b/packages/core/upload/admin/tests/handlers.ts similarity index 90% rename from packages/core/upload/admin/tests/handlers.js rename to packages/core/upload/admin/tests/handlers.ts index c8de7cc25f..b4051630d4 100644 --- a/packages/core/upload/admin/tests/handlers.js +++ b/packages/core/upload/admin/tests/handlers.ts @@ -1,6 +1,13 @@ import { rest } from 'msw'; import qs from 'qs'; +// Define the expected structure of your query parameters +interface CustomQuery extends qs.ParsedQs { + filters?: { + $and?: Array<{ parent: { id: string } }>; + }; +} + const handlers = [ rest.get('/upload/configuration', async (req, res, ctx) => { return res( @@ -48,7 +55,7 @@ const handlers = [ ); }), rest.get('/upload/folders', async (req, res, ctx) => { - const query = qs.parse(req.url.search.slice(1)); + const query: CustomQuery = qs.parse(req.url.search.slice(1)); if (query._q) { return res( @@ -183,13 +190,13 @@ const handlers = [ }), rest.get('*/an-image.png', (req, res, ctx) => - res(ctx.set('Content-Type', 'image/png'), ctx.body()) + res(ctx.set('Content-Type', 'image/png'), ctx.body('Successful response')) ), rest.get('*/a-pdf.pdf', (req, res, ctx) => - res(ctx.set('Content-Type', 'application/pdf'), ctx.body()) + res(ctx.set('Content-Type', 'application/pdf'), ctx.body('Successful response')) ), rest.get('*/a-video.mp4', (req, res, ctx) => - res(ctx.set('Content-Type', 'video/mp4'), ctx.body()) + res(ctx.set('Content-Type', 'video/mp4'), ctx.body('Successful response')) ), rest.get('*/not-working-like-cors.lutin', (req, res, ctx) => res(ctx.json({}))), rest.get('*/some-where-not-existing.jpg', (req, res) => res.networkError('Failed to fetch')), diff --git a/packages/core/upload/admin/tests/setup.js b/packages/core/upload/admin/tests/setup.ts similarity index 100% rename from packages/core/upload/admin/tests/setup.js rename to packages/core/upload/admin/tests/setup.ts diff --git a/packages/core/upload/admin/tests/utils.jsx b/packages/core/upload/admin/tests/utils.ts similarity index 100% rename from packages/core/upload/admin/tests/utils.jsx rename to packages/core/upload/admin/tests/utils.ts diff --git a/packages/core/upload/admin/tsconfig.build.json b/packages/core/upload/admin/tsconfig.build.json new file mode 100644 index 0000000000..6af52a63b9 --- /dev/null +++ b/packages/core/upload/admin/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "extends": "tsconfig/client.json", + "compilerOptions": { + "rootDir": "../", + "baseUrl": ".", + "outDir": "./dist" + }, + "include": ["./src", "../shared", "../package.json"], + "exclude": ["**/__mocks__", "./src/**/tests", "**/*.test.*"] +} diff --git a/packages/core/upload/admin/tsconfig.json b/packages/core/upload/admin/tsconfig.json new file mode 100644 index 0000000000..17d69ac5c6 --- /dev/null +++ b/packages/core/upload/admin/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "tsconfig/client.json", + "compilerOptions": { + "rootDir": "../", + "baseUrl": ".", + "paths": { + "@tests/*": ["./tests/*"] + } + }, + "include": ["../package.json", "./src", "../shared", "./tests"] +} diff --git a/packages/core/upload/jest.config.front.js b/packages/core/upload/jest.config.front.js index ccb2e58321..1d67f26ac9 100644 --- a/packages/core/upload/jest.config.front.js +++ b/packages/core/upload/jest.config.front.js @@ -6,5 +6,5 @@ module.exports = { moduleNameMapper: { '^@tests/(.*)$': '/admin/tests/$1', }, - setupFilesAfterEnv: ['./admin/tests/setup.js'], + setupFilesAfterEnv: ['./admin/tests/setup.ts'], }; diff --git a/packages/core/upload/jsconfig.json b/packages/core/upload/jsconfig.json deleted file mode 100644 index 986fd6eba5..0000000000 --- a/packages/core/upload/jsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "baseUrl": ".", - "paths": { - "@tests/*": ["./admin/tests/*"] - } - } -} diff --git a/packages/core/upload/package.json b/packages/core/upload/package.json index f2191b188d..ec8eeb80fd 100644 --- a/packages/core/upload/package.json +++ b/packages/core/upload/package.json @@ -17,11 +17,19 @@ ], "exports": { "./strapi-admin": { + "types": "./dist/admin/src/index.d.ts", "source": "./admin/src/index.js", "import": "./dist/admin/index.mjs", "require": "./dist/admin/index.js", "default": "./dist/admin/index.js" }, + "./_internal/shared": { + "types": "./dist/shared/index.d.ts", + "source": "./shared/index.ts", + "import": "./dist/shared/index.mjs", + "require": "./dist/shared/index.js", + "default": "./dist/shared/index.js" + }, "./strapi-server": { "types": "./dist/server/src/index.d.ts", "source": "./server/src/index.ts", @@ -41,6 +49,9 @@ "lint": "run -T eslint .", "test:front": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js", "test:unit": "run -T jest", + "test:ts:back": "run -T tsc --noEmit -p server/tsconfig.json", + "test:ts:front": "run -T tsc -p admin/tsconfig.json", + "test:front:watch": "run -T cross-env IS_EE=true jest --config ./jest.config.front.js --watch", "test:unit:watch": "run -T jest --watch", "watch": "pack-up watch" }, diff --git a/packages/core/upload/packup.config.ts b/packages/core/upload/packup.config.ts index b531c51a21..2c398928e5 100644 --- a/packages/core/upload/packup.config.ts +++ b/packages/core/upload/packup.config.ts @@ -3,9 +3,11 @@ import { Config, defineConfig } from '@strapi/pack-up'; const config: Config = defineConfig({ bundles: [ { - source: './admin/src/index.js', + types: './dist/admin/src/index.d.ts', + source: './admin/src/index.js', // TODO: change it with the .ts file import: './dist/admin/index.mjs', require: './dist/admin/index.js', + tsconfig: './admin/tsconfig.build.json', runtime: 'web', }, { diff --git a/packages/core/upload/server/src/bootstrap.ts b/packages/core/upload/server/src/bootstrap.ts index 5e41bb2e43..af3bb3712f 100644 --- a/packages/core/upload/server/src/bootstrap.ts +++ b/packages/core/upload/server/src/bootstrap.ts @@ -25,6 +25,7 @@ export async function bootstrap({ strapi }: { strapi: Core.Strapi }) { config && Object.keys(defaultValue).every((key) => Object.prototype.hasOwnProperty.call(config, key)) ) { + // eslint-disable-next-line no-continue continue; } diff --git a/packages/core/upload/server/src/controllers/validation/admin/folder-file.ts b/packages/core/upload/server/src/controllers/validation/admin/folder-file.ts index d0f0b3363a..ed4378ea43 100644 --- a/packages/core/upload/server/src/controllers/validation/admin/folder-file.ts +++ b/packages/core/upload/server/src/controllers/validation/admin/folder-file.ts @@ -29,7 +29,7 @@ const validateStructureMoveManyFoldersFilesSchema = yup const validateDuplicatesMoveManyFoldersFilesSchema = yup .object() - .test('are-folders-unique', 'some folders already exist', async function (value) { + .test('are-folders-unique', 'some folders already exist', async function areFoldersUnique(value) { const { folderIds, destinationFolderId } = value; if (isEmpty(folderIds)) return true; @@ -58,7 +58,7 @@ const validateMoveFoldersNotInsideThemselvesSchema = yup .test( 'dont-move-inside-self', 'folders cannot be moved inside themselves or one of its children', - async function (value) { + async function validateMoveFoldersNotInsideThemselves(value) { const { folderIds, destinationFolderId } = value; if (destinationFolderId === null || isEmpty(folderIds)) return true; diff --git a/packages/core/upload/server/src/services/__tests__/upload/uploadImage.test.ts b/packages/core/upload/server/src/services/__tests__/upload/uploadImage.test.ts index 8256cceb3a..4ef3439c87 100644 --- a/packages/core/upload/server/src/services/__tests__/upload/uploadImage.test.ts +++ b/packages/core/upload/server/src/services/__tests__/upload/uploadImage.test.ts @@ -47,7 +47,7 @@ const getFileData = (filePath: string) => ({ alternativeText: 'image.png', caption: 'image.png', ext: '.png', - folder: null, + folder: undefined, folderPath: '/', filepath: filePath, getStream: () => fs.createReadStream(filePath), @@ -56,6 +56,7 @@ const getFileData = (filePath: string) => ({ size: 4, width: 1500, tmpWorkingDirectory, + name: 'image.png', }); describe('Upload image', () => { diff --git a/packages/core/upload/server/src/services/extensions/__tests__/sign-media.test.ts b/packages/core/upload/server/src/services/extensions/__tests__/sign-media.test.ts index 3e78e176cc..ab1569d9f9 100644 --- a/packages/core/upload/server/src/services/extensions/__tests__/sign-media.test.ts +++ b/packages/core/upload/server/src/services/extensions/__tests__/sign-media.test.ts @@ -1,10 +1,11 @@ +import type { UID } from '@strapi/types'; import { signEntityMedia } from '../utils'; import { getService } from '../../../utils'; jest.mock('../../../utils'); describe('Upload | extensions | entity-manager', () => { - const modelUID = 'model'; + const modelUID = 'model' as UID.Schema; const componentUID = 'component'; const models = { @@ -71,6 +72,18 @@ describe('Upload | extensions | entity-manager', () => { spySignFileUrls = jest.fn(); jest.mocked(getService).mockImplementation(() => ({ signFileUrls: spySignFileUrls, + getFolderPath: jest.fn(), + deleteByIds: jest.fn(), + computeMetrics: jest.fn().mockResolvedValue({ + assetNumber: 0, + folderNumber: 0, + averageDepth: 0, + maxDepth: 0, + averageDeviationDepth: 0, + }), + sendMetrics: jest.fn().mockResolvedValue(undefined), + ensureWeeklyStoredCronSchedule: jest.fn().mockResolvedValue(undefined), + registerCron: jest.fn().mockResolvedValue(undefined), })); global.strapi = { From 89197526ed57a97d5310e816d1d3e4ea443acb94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-S=C3=A9bastien=20Herbaux?= Date: Tue, 24 Sep 2024 11:31:14 +0200 Subject: [PATCH 10/18] Add Placeholders for Empty Artifacts in Type Generation (#21441) --- .../typescript/lib/generators/components/index.js | 11 +++++++++++ .../typescript/lib/generators/content-types/index.js | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/packages/utils/typescript/lib/generators/components/index.js b/packages/utils/typescript/lib/generators/components/index.js index 0f3a2e24ef..3f42a70962 100644 --- a/packages/utils/typescript/lib/generators/components/index.js +++ b/packages/utils/typescript/lib/generators/components/index.js @@ -5,6 +5,11 @@ const { factory } = require('typescript'); const { models } = require('../common'); const { emitDefinitions, format, generateSharedExtensionDefinition } = require('../utils'); +const NO_COMPONENT_PLACEHOLDER_COMMENT = `/* + * The app doesn't have any components yet. + */ +`; + /** * Generate type definitions for Strapi Components * @@ -23,6 +28,12 @@ const generateComponentsDefinitions = async (options = {}) => { definition: models.schema.generateSchemaDefinition(contentType), })); + options.logger.debug(`Found ${componentsDefinitions.length} components.`); + + if (componentsDefinitions.length === 0) { + return { output: NO_COMPONENT_PLACEHOLDER_COMMENT, stats: {} }; + } + const formattedSchemasDefinitions = componentsDefinitions.reduce((acc, def) => { acc.push( // Definition diff --git a/packages/utils/typescript/lib/generators/content-types/index.js b/packages/utils/typescript/lib/generators/content-types/index.js index 74640a1cd2..f77181dd9c 100644 --- a/packages/utils/typescript/lib/generators/content-types/index.js +++ b/packages/utils/typescript/lib/generators/content-types/index.js @@ -5,6 +5,11 @@ const { factory } = require('typescript'); const { models } = require('../common'); const { emitDefinitions, format, generateSharedExtensionDefinition } = require('../utils'); +const NO_CONTENT_TYPE_PLACEHOLDER_COMMENT = `/* + * The app doesn't have any content-types yet. + */ +`; + /** * Generate type definitions for Strapi Content-Types * @@ -23,6 +28,12 @@ const generateContentTypesDefinitions = async (options = {}) => { definition: models.schema.generateSchemaDefinition(contentType), })); + options.logger.debug(`Found ${contentTypesDefinitions.length} content-types.`); + + if (contentTypesDefinitions.length === 0) { + return { output: NO_CONTENT_TYPE_PLACEHOLDER_COMMENT, stats: {} }; + } + const formattedSchemasDefinitions = contentTypesDefinitions.reduce((acc, def) => { acc.push( // Definition From e43238abaf91e70531f0653dc7d1776a6f21eccf Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Tue, 24 Sep 2024 12:52:57 +0200 Subject: [PATCH 11/18] fix: drop and create columns and indexes in the correct order (#21402) --- packages/core/database/src/schema/builder.ts | 35 ++++---- playwright.base.config.js | 2 +- .../edit-collection-type.spec.ts | 83 +++++++++++++++---- 3 files changed, 89 insertions(+), 31 deletions(-) diff --git a/packages/core/database/src/schema/builder.ts b/packages/core/database/src/schema/builder.ts index 2e07e11539..d9a2a78ab7 100644 --- a/packages/core/database/src/schema/builder.ts +++ b/packages/core/database/src/schema/builder.ts @@ -259,11 +259,6 @@ const createHelpers = (db: Database) => { dropForeignKey(tableBuilder, updatedForeignKey.object); } - for (const removedColumn of table.columns.removed) { - debug(`Dropping column ${removedColumn.name} on ${table.name}`); - dropColumn(tableBuilder, removedColumn); - } - // for mysql only, dropForeignKey also removes the index, so don't drop it twice const isMySQL = db.config.connection.client === 'mysql'; const ignoreForeignKeyNames = isMySQL @@ -287,7 +282,13 @@ const createHelpers = (db: Database) => { } } - // Update existing columns / foreign keys / indexes + // We drop columns after indexes to ensure that it doesn't cascade delete any indexes we expect to exist + for (const removedColumn of table.columns.removed) { + debug(`Dropping column ${removedColumn.name} on ${table.name}`); + dropColumn(tableBuilder, removedColumn); + } + + // Update existing columns for (const updatedColumn of table.columns.updated) { debug(`Updating column ${updatedColumn.name} on ${table.name}`); @@ -300,16 +301,7 @@ const createHelpers = (db: Database) => { } } - for (const updatedForeignKey of table.foreignKeys.updated) { - debug(`Recreating updated foreign key ${updatedForeignKey.name} on ${table.name}`); - createForeignKey(tableBuilder, updatedForeignKey.object); - } - - for (const updatedIndex of table.indexes.updated) { - debug(`Recreating updated index ${updatedIndex.name} on ${table.name}`); - createIndex(tableBuilder, updatedIndex.object); - } - + // Add any new columns for (const addedColumn of table.columns.added) { debug(`Creating column ${addedColumn.name} on ${table.name}`); @@ -321,6 +313,17 @@ const createHelpers = (db: Database) => { } } + // once the columns have all been updated, we can create indexes again + for (const updatedForeignKey of table.foreignKeys.updated) { + debug(`Recreating updated foreign key ${updatedForeignKey.name} on ${table.name}`); + createForeignKey(tableBuilder, updatedForeignKey.object); + } + + for (const updatedIndex of table.indexes.updated) { + debug(`Recreating updated index ${updatedIndex.name} on ${table.name}`); + createIndex(tableBuilder, updatedIndex.object); + } + for (const addedForeignKey of table.foreignKeys.added) { debug(`Creating foreign keys ${addedForeignKey.name} on ${table.name}`); createForeignKey(tableBuilder, addedForeignKey); diff --git a/playwright.base.config.js b/playwright.base.config.js index d68b582525..358bfadcf8 100644 --- a/playwright.base.config.js +++ b/playwright.base.config.js @@ -52,7 +52,7 @@ const createConfig = ({ port, testDir, appDir }) => ({ /* Fail the build on CI if you accidentally left test.only in the source code. */ forbidOnly: !!process.env.CI, /* Retry on CI only */ - retries: process.env.CI ? 3 : 0, + retries: process.env.CI ? 3 : 1, /* Opt out of parallel tests on CI. */ workers: 1, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ diff --git a/tests/e2e/tests/content-type-builder/collection-type/edit-collection-type.spec.ts b/tests/e2e/tests/content-type-builder/collection-type/edit-collection-type.spec.ts index d7a654d665..93537bb188 100644 --- a/tests/e2e/tests/content-type-builder/collection-type/edit-collection-type.spec.ts +++ b/tests/e2e/tests/content-type-builder/collection-type/edit-collection-type.spec.ts @@ -10,28 +10,56 @@ import { skipCtbTour, } from '../../../utils/shared'; -// TODO: fix the test so that it doesn't fail on CI -describeOnCondition(!process.env.CI)('Edit collection type', () => { +test.describe('Edit collection type', () => { + // very long timeout for these tests because they restart the server multiple times + test.describe.configure({ timeout: 300000 }); + // use a name with a capital and a space to ensure we also test the kebab-casing conversion for api ids const ctName = 'Secret Document'; - test.beforeEach(async ({ page }) => { - await resetFiles(); - await resetDatabaseAndImportDataFromPath('with-admin.tar'); - await page.goto('/admin'); + let dependentTestsInitialized = false; - await login({ page }); + test.beforeEach(async ({ page }) => { + // TODO: optimize and duplicate this logic in a standardized way other tests + // reduce each test run by having a fake `beforeAll` to create the content types only once + let loggedIn = false; + if (!dependentTestsInitialized) { + await resetFiles(); + await resetDatabaseAndImportDataFromPath('with-admin.tar'); + + await page.goto('/admin'); + + await login({ page }); + loggedIn = true; + await page.getByRole('link', { name: 'Content-Type Builder' }).click(); + + await skipCtbTour(page); + + // create a collection type to be used + await createCollectionType(page, { + name: ctName, + }); + + await createCollectionType(page, { + name: 'dog', + }); + await createCollectionType(page, { + name: 'owner', + }); + + dependentTestsInitialized = true; + } + + if (!loggedIn) { + await page.goto('/admin'); + + await login({ page }); + loggedIn = true; + } await page.getByRole('link', { name: 'Content-Type Builder' }).click(); - await skipCtbTour(page); - // TODO: create a "saveFileState" mechanism to be used so we don't have to do a full server restart before each test - // create a collection type to be used - await createCollectionType(page, { - name: ctName, - }); - await navToHeader(page, ['Content-Type Builder', ctName], ctName); }); @@ -41,6 +69,33 @@ describeOnCondition(!process.env.CI)('Edit collection type', () => { await resetFiles(); }); + // Tests for GH#21398 + test('Can update relation of type manyToOne to oneToOne', async ({ page }) => { + // Create dog owner relation in Content-Type Builder + await navToHeader(page, ['Content-Type Builder', 'Dog'], 'Dog'); + await page.getByRole('button', { name: /add another field to this/i }).click(); + await page.getByRole('button', { name: /relation/i }).click(); + await page.getByLabel('Basic settings').getByRole('button').nth(3).click(); + await page.getByRole('button', { name: /article/i }).click(); + await page.getByRole('menuitem', { name: /owner/i }).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Save' }).click(); + + await waitForRestart(page); + + await expect(page.getByRole('cell', { name: 'owner', exact: true })).toBeVisible(); + + // update dog owner relation in Content-Type Builder to oneToOne + await page.getByRole('button', { name: /edit owner/i }).click(); + await page.getByLabel('Basic settings').getByRole('button').nth(0).click(); + await page.getByRole('button', { name: 'Finish' }).click(); + await page.getByRole('button', { name: 'Save' }).click(); + + await waitForRestart(page); + + await expect(page.getByRole('cell', { name: 'owner', exact: true })).toBeVisible(); + }); + test('Can toggle internationalization', async ({ page }) => { await page.getByRole('button', { name: 'Edit' }).first().click(); await page.getByRole('tab', { name: 'Advanced settings' }).click(); From 8853cdb9515273fba90f27e772025f64eaff1c53 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Tue, 24 Sep 2024 13:41:13 +0200 Subject: [PATCH 12/18] chore: fix strip-hash (#21440) --- .github/workflows/adminBundleSize.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/adminBundleSize.yml b/.github/workflows/adminBundleSize.yml index ba41ca3b56..c71bf0e4ba 100644 --- a/.github/workflows/adminBundleSize.yml +++ b/.github/workflows/adminBundleSize.yml @@ -37,7 +37,7 @@ jobs: with: build-script: 'build:size' pattern: '**/build/**/*.{js,css,html,svg}' - strip-hash: "\\.(?:(\\w{8})\\.chunk)|(?:\\.(\\w{8}))" + strip-hash: "-(\\w{8})(\\.\\w+)$" minimum-change-threshold: 10 # FIXME: exclude unnamed webpack chunks - remove once webpack From 8893730a2fb9985151a6494e8997ccee2fbfb218 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Tue, 24 Sep 2024 14:37:34 +0200 Subject: [PATCH 13/18] fix(create-strapi-app): yarn 4 support (#21329) --- .../create-strapi-app/src/create-strapi.ts | 25 ++- .../src/utils/get-package-manager-args.ts | 144 ++++++++++++++++++ 2 files changed, 156 insertions(+), 13 deletions(-) create mode 100644 packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts diff --git a/packages/cli/create-strapi-app/src/create-strapi.ts b/packages/cli/create-strapi-app/src/create-strapi.ts index 94bd8e54b0..263a63a461 100644 --- a/packages/cli/create-strapi-app/src/create-strapi.ts +++ b/packages/cli/create-strapi-app/src/create-strapi.ts @@ -14,6 +14,7 @@ import { isStderrError } from './types'; import type { Scope } from './types'; import { logger } from './utils/logger'; import { gitIgnore } from './utils/gitignore'; +import { getInstallArgs } from './utils/get-package-manager-args'; async function createStrapi(scope: Scope) { const { rootPath } = scope; @@ -239,29 +240,27 @@ async function createApp(scope: Scope) { } } -const installArguments = ['install']; +async function runInstall({ rootPath, packageManager }: Scope) { + // include same cwd and env to ensure version check returns same version we use below + const { envArgs, cmdArgs } = await getInstallArgs(packageManager, { + cwd: rootPath, + env: { + ...process.env, + NODE_ENV: 'development', + }, + }); -const installArgumentsMap = { - npm: ['--legacy-peer-deps'], - yarn: ['--network-timeout 1000000'], - pnpm: [], -}; - -function runInstall({ rootPath, packageManager }: Scope) { const options: execa.Options = { cwd: rootPath, stdio: 'inherit', env: { ...process.env, + ...envArgs, NODE_ENV: 'development', }, }; - if (packageManager in installArgumentsMap) { - installArguments.push(...(installArgumentsMap[packageManager] ?? [])); - } - - const proc = execa(packageManager, installArguments, options); + const proc = execa(packageManager, cmdArgs, options); return proc; } diff --git a/packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts b/packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts new file mode 100644 index 0000000000..f1e21eef99 --- /dev/null +++ b/packages/cli/create-strapi-app/src/utils/get-package-manager-args.ts @@ -0,0 +1,144 @@ +import execa from 'execa'; +import semver from 'semver'; + +const installArguments = ['install']; + +type VersionedArgumentsMap = { + [key: string]: string[]; // Maps semver ranges to argument arrays +}; + +type VersionedEnvMap = { + [key: string]: Record; // Maps semver ranges to environment variables +}; + +// Set command line options for specific package managers, with full semver ranges +const installArgumentsMap: { + [key: string]: VersionedArgumentsMap; +} = { + npm: { + '*': ['--legacy-peer-deps'], + }, + yarn: { + '<4': ['--network-timeout', '1000000'], + '*': [], + }, + pnpm: { + '*': [], + }, +}; + +// Set environment variables for specific package managers, with full semver ranges +const installEnvMap: { + [key: string]: VersionedEnvMap; +} = { + yarn: { + '>=4': { YARN_HTTP_TIMEOUT: '1000000' }, + '*': {}, + }, + npm: { + '*': {}, + }, + pnpm: { + '*': {}, + }, +}; + +/** + * Retrieves the version of the specified package manager. + * + * Executes the package manager's `--version` command to determine its version. + * + * @param packageManager - The name of the package manager (e.g., 'npm', 'yarn', 'pnpm'). + * @param options - Optional execution options to pass to `execa`. + * @returns A promise that resolves to the trimmed version string of the package manager. + * + * @throws Will throw an error if the package manager's version cannot be determined. + */ +export const getPackageManagerVersion = async ( + packageManager: string, + options?: execa.Options +): Promise => { + try { + const { stdout } = await execa(packageManager, ['--version'], options); + return stdout.trim(); + } catch (err) { + throw new Error(`Error detecting ${packageManager} version: ${err}`); + } +}; + +/** + * Merges all matching semver ranges using a custom merge function. + * + * Iterates over the `versionMap`, checking if the provided `version` satisfies each semver range. + * If it does, the corresponding value is merged using the provided `mergeFn`. + * The merging starts with the value associated with the wildcard '*' key. + * + * @param version - The package manager version to check against the ranges. + * @param versionMap - A map of semver ranges to corresponding values (arguments or environment variables). + * @param mergeFn - A function that defines how to merge two values (accumulated and current). + * @returns The merged result of all matching ranges. + */ +function mergeMatchingVersionRanges( + version: string, + versionMap: { [key: string]: T }, + mergeFn: (acc: T, curr: T) => T +): T { + return Object.keys(versionMap).reduce((acc, range) => { + if (semver.satisfies(version, range) || range === '*') { + return mergeFn(acc, versionMap[range]); + } + return acc; + }, versionMap['*']); // Start with the wildcard entry +} + +function mergeArguments(acc: string[], curr: string[]): string[] { + return [...acc, ...curr]; +} + +function mergeEnvVars( + acc: Record, + curr: Record +): Record { + return { ...acc, ...curr }; +} + +/** + * Retrieves the install arguments and environment variables for a given package manager. + * + * This function determines the correct command line arguments and environment variables + * based on the package manager's version. It uses predefined semver ranges to match + * the package manager's version and merges all applicable settings. + * + * The arguments and environment variables are sourced from: + * - `installArgumentsMap` for command line arguments. + * - `installEnvMap` for environment variables. + * + * The function ensures that all matching semver ranges are considered and merged appropriately. + * It always includes the base `installArguments` (e.g., `['install']`) and applies any additional + * arguments or environment variables as defined by the matched version ranges. + * + * @param packageManager - The name of the package manager (e.g., 'npm', 'yarn', 'pnpm'). + * @param options - Optional execution options to pass to `execa`. + * @returns An object containing: + * - `cmdArgs`: The full array of install arguments for the given package manager and version. + * - `envArgs`: The merged environment variables applicable to the package manager and version. + * + * @throws Will throw an error if the package manager version cannot be determined. + */ +export const getInstallArgs = async (packageManager: string, options?: execa.Options) => { + const packageManagerVersion = await getPackageManagerVersion(packageManager, options); + + // Get environment variables + const envMap = installEnvMap[packageManager]; + const envArgs = packageManagerVersion + ? mergeMatchingVersionRanges(packageManagerVersion, envMap, mergeEnvVars) + : envMap['*']; + + // Get install arguments + const argsMap = installArgumentsMap[packageManager]; + const cmdArgs = packageManagerVersion + ? mergeMatchingVersionRanges(packageManagerVersion, argsMap, mergeArguments) + : argsMap['*']; + + return { envArgs, cmdArgs: [...installArguments, ...cmdArgs], version: packageManagerVersion }; +}; From 06e045b64431dab8bf466258b0a7b34cedd67337 Mon Sep 17 00:00:00 2001 From: Ben Irvin Date: Tue, 24 Sep 2024 16:35:48 +0200 Subject: [PATCH 14/18] fix(tooling): strip dashes and change min threshhold (#21445) --- .github/workflows/adminBundleSize.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/adminBundleSize.yml b/.github/workflows/adminBundleSize.yml index c71bf0e4ba..a3326e727f 100644 --- a/.github/workflows/adminBundleSize.yml +++ b/.github/workflows/adminBundleSize.yml @@ -37,8 +37,8 @@ jobs: with: build-script: 'build:size' pattern: '**/build/**/*.{js,css,html,svg}' - strip-hash: "-(\\w{8})(\\.\\w+)$" - minimum-change-threshold: 10 + strip-hash: "-([-\\w]{8})(\\.\\w+)$" + minimum-change-threshold: '5%' # FIXME: exclude unnamed webpack chunks - remove once webpack # does not create them anymore From 927824c76d693e161b80de7484e93d4010b7eb2e Mon Sep 17 00:00:00 2001 From: Lucas Boilly <45385696+lucasboilly@users.noreply.github.com> Date: Wed, 25 Sep 2024 03:18:18 -0500 Subject: [PATCH 15/18] chore: harmonized all button sizes in settings (#21457) --- .../admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx | 4 ++-- .../admin/admin/src/pages/Settings/pages/Roles/EditPage.tsx | 3 ++- .../admin/admin/src/pages/Settings/pages/Users/EditPage.tsx | 1 - .../pages/Settings/pages/Webhooks/components/WebhookForm.tsx | 2 -- .../admin/src/pages/SettingsPage/pages/SingleSignOnPage.tsx | 1 - .../core/review-workflows/admin/src/routes/settings/:id.tsx | 1 - 6 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx b/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx index b462951464..838561ed2f 100644 --- a/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx +++ b/packages/core/admin/admin/src/pages/Settings/pages/Roles/CreatePage.tsx @@ -11,6 +11,7 @@ import { TextInput, Typography, } from '@strapi/design-system'; +import { Check } from '@strapi/icons'; import { format } from 'date-fns'; import { Formik, Form, FormikHelpers } from 'formik'; import { useIntl } from 'react-intl'; @@ -197,14 +198,13 @@ const CreatePage = () => { handleReset(); permissionsRef.current?.resetForm(); }} - size="L" > {formatMessage({ id: 'app.components.Button.reset', defaultMessage: 'Reset', })} - diff --git a/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx b/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx index a117518ae8..3996ea7574 100644 --- a/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx +++ b/packages/core/admin/admin/src/pages/Settings/pages/Webhooks/components/WebhookForm.tsx @@ -98,7 +98,6 @@ const WebhookForm = ({ variant="tertiary" startIcon={} disabled={isCreating || isTriggering} - size="L" > {formatMessage({ id: 'Settings.webhooks.trigger', @@ -108,7 +107,6 @@ const WebhookForm = ({