diff --git a/README.md b/README.md index 3b2dec557a..f1c025446a 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ Strapi is a free and open-source headless CMS delivering your content anywhere you need. - **Keep control over your data**. With Strapi, you know where your data is stored, and you keep full control at all times. -- **Self-hosted**. You can host and scale Strapi projects the way you want. You can choose any hosting platform you want: AWS, Render, Netlify, Heroku, a VPS, or a dedicated server. You can scale as you grow, 100% independent. -- **Database agnostic**. Strapi works with SQL databases. You can choose the database you prefer: PostgreSQL, MySQL, MariaDB, and SQLite. +- **Self-hosted**. You can host and scale Strapi projects the way you want. You can choose any hosting platform you want: AWS, Render, Heroku, a VPS, or a dedicated server. You can scale as you grow, 100% independent. +- **Database agnostic**. You can choose the database you prefer. Strapi works with SQL & NoSQL databases: MongoDB, PostgreSQL, MySQL, MariaDB, and SQLite. - **Customizable**. You can quickly build your logic by fully customizing APIs, routes, or plugins to fit your needs perfectly. ## Getting Started diff --git a/packages/core/utils/lib/__tests__/string-formatting.test.js b/packages/core/utils/lib/__tests__/string-formatting.test.js index fc7c3c0159..652583396a 100644 --- a/packages/core/utils/lib/__tests__/string-formatting.test.js +++ b/packages/core/utils/lib/__tests__/string-formatting.test.js @@ -1,6 +1,12 @@ 'use strict'; -const { escapeQuery, stringIncludes, stringEquals } = require('../string-formatting'); +const { + escapeQuery, + stringIncludes, + stringEquals, + getCommonBeginning, + getCommonPath, +} = require('../string-formatting'); describe('string-formatting', () => { describe('Escape Query', () => { @@ -64,4 +70,31 @@ describe('string-formatting', () => { expect(result).toBe(expectedResult); }); }); + + describe('getCommonBeginning', () => { + const tests = [ + [['abcd', 'abc', 'ab'], 'ab'], + [['abcd', 'abc'], 'abc'], + [['ab/cd', 'ab/c'], 'ab/c'], + [['abc', 'abc'], 'abc'], + ]; + test.each(tests)('%p has common beginning: %p', (a, expectedResult) => { + const result = getCommonBeginning(...a); + expect(result).toBe(expectedResult); + }); + }); + + describe('getCommonPath', () => { + const tests = [ + [['abc', 'ab'], ''], + [['http://ab.com/cd', 'http://ab.com/c'], 'http://ab.com'], + [['http://ab.com/admin', 'http://ab.com/api'], 'http://ab.com'], + [['http://ab.com/admin', 'http://ab.com/admin/'], 'http://ab.com/admin'], + [['http://ab.com/admin', 'http://ab.com/admin'], 'http://ab.com/admin'], + ]; + test.each(tests)('%p has common path: %p', (a, expectedResult) => { + const result = getCommonPath(...a); + expect(result).toBe(expectedResult); + }); + }); }); diff --git a/packages/core/utils/lib/config.js b/packages/core/utils/lib/config.js index b36e746706..0e1f2ae1d5 100644 --- a/packages/core/utils/lib/config.js +++ b/packages/core/utils/lib/config.js @@ -1,7 +1,7 @@ 'use strict'; const _ = require('lodash'); -const { getCommonBeginning } = require('./string-formatting'); +const { getCommonPath } = require('./string-formatting'); const getConfigUrls = (serverConfig, forAdminBuild = false) => { // Defines serverUrl value @@ -46,7 +46,7 @@ const getConfigUrls = (serverConfig, forAdminBuild = false) => { new URL(adminUrl).origin === new URL(serverUrl).origin && !forAdminBuild ) { - adminPath = adminUrl.replace(getCommonBeginning(serverUrl, adminUrl), ''); + adminPath = adminUrl.replace(getCommonPath(serverUrl, adminUrl), ''); adminPath = `/${_.trim(adminPath, '/')}`; } else if (adminUrl.startsWith('http')) { adminPath = new URL(adminUrl).pathname; diff --git a/packages/core/utils/lib/string-formatting.js b/packages/core/utils/lib/string-formatting.js index 1ee95f2874..594cebbeb3 100644 --- a/packages/core/utils/lib/string-formatting.js +++ b/packages/core/utils/lib/string-formatting.js @@ -1,23 +1,22 @@ 'use strict'; - +const _ = require('lodash'); const slugify = require('@sindresorhus/slugify'); const nameToSlug = (name, options = { separator: '-' }) => slugify(name, options); const nameToCollectionName = name => slugify(name, { separator: '_' }); -const getCommonBeginning = (str1 = '', str2 = '') => { - let common = ''; - let index = 0; - while (index < str1.length && index < str2.length) { - if (str1[index] === str2[index]) { - common += str1[index]; - index += 1; - } else { - break; - } - } - return common; +const getCommonBeginning = (...strings) => + _.takeWhile(strings[0], (char, index) => strings.every(string => string[index] === char)).join( + '' + ); + +const getCommonPath = (...paths) => { + const [segments, ...otherSegments] = paths.map(it => _.split(it, '/')); + return _.join( + _.takeWhile(segments, (str, index) => otherSegments.every(it => it[index] === str)), + '/' + ); }; const escapeQuery = (query, charsToEscape, escapeChar = '\\') => { @@ -39,6 +38,7 @@ module.exports = { nameToSlug, nameToCollectionName, getCommonBeginning, + getCommonPath, escapeQuery, stringIncludes, stringEquals,