diff --git a/package.json b/package.json index d44a9c9..c5ce48f 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "pino-pretty": "^4.7.1", "qs": "^6.10.3", "semaphore": "^1.1.0", + "semver": "^7.6.0", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.0", "yup": "^1.3.2" diff --git a/src/advertising/external-ads.ts b/src/advertising/external-ads.ts index 4ee8418..fa08539 100644 --- a/src/advertising/external-ads.ts +++ b/src/advertising/external-ads.ts @@ -1,3 +1,5 @@ +import { satisfies as versionSatisfiesRange } from 'semver'; + import { objectStorageMethodsFactory, redisClient } from '../redis'; import { isDefined } from '../utils/helpers'; @@ -84,8 +86,7 @@ interface AdStylesOverrides { } interface ExtVersionConstraints { - firstExtVersion?: string; - lastExtVersion?: string; + extVersion?: string; } export interface AdPlacesRule extends ExtVersionConstraints { @@ -176,31 +177,5 @@ export const addAdProvidersForAllSites = async (providers: string[]) => export const removeAdProvidersForAllSites = async (providers: string[]) => redisClient.srem(AD_PROVIDERS_ALL_SITES_KEY, ...providers); -const compareVersions = (a: string, b: string) => { - const [aMajor = 0, aMinor = 0, aPatch = 0] = a.split('.').map(Number); - const [bMajor = 0, bMinor = 0, bPatch = 0] = b.split('.').map(Number); - - if (aMajor !== bMajor) { - return aMajor - bMajor; - } - - if (aMinor !== bMinor) { - return aMinor - bMinor; - } - - return aPatch - bPatch; -}; - -export const filterByVersion = (rules: T[], version = '1.20.1') => { - return rules.filter(({ firstExtVersion, lastExtVersion }) => { - if (isDefined(firstExtVersion) && compareVersions(firstExtVersion, version) > 0) { - return false; - } - - if (isDefined(lastExtVersion) && compareVersions(lastExtVersion, version) < 0) { - return false; - } - - return true; - }); -}; +export const filterByVersion = (rules: T[], version = '1.20.1') => + rules.filter(({ extVersion }) => !isDefined(extVersion) || versionSatisfiesRange(version, extVersion)); diff --git a/src/routers/slise-ad-rules/ad-places.ts b/src/routers/slise-ad-rules/ad-places.ts index ad0a562..422e671 100644 --- a/src/routers/slise-ad-rules/ad-places.ts +++ b/src/routers/slise-ad-rules/ad-places.ts @@ -69,19 +69,11 @@ import { * ExtVersionConstraints: * type: object * properties: - * firstExtVersion: + * extVersion: * type: string - * format: version * description: > - * The first extension version where the rule is applicable. If not specified, the rule is applicable - * for all extension versions not greater than the `lastExtVersion` value. If neither of them is specified, - * the rule is applicable for all extension versions. - * lastExtVersion: - * type: string - * format: version - * description: > - * The last extension version where the rule is applicable. If not specified, the rule is applicable - * for all extension versions not less than the `firstExtVersion` value. + * A range of versions where the rule is applicable. If not specified, the rule is applicable + * for all versions. See the [ranges format](https://www.npmjs.com/package/semver#ranges) * AdPlacesRule: * allOf: * - $ref: '#/components/schemas/ExtVersionConstraints' diff --git a/src/utils/schemas.ts b/src/utils/schemas.ts index 03e1e0f..2ad6a6b 100644 --- a/src/utils/schemas.ts +++ b/src/utils/schemas.ts @@ -1,3 +1,4 @@ +import { validRange as getValidatedRange } from 'semver'; import { array as arraySchema, ArraySchema as IArraySchema, @@ -60,8 +61,8 @@ const regexStringSchema = stringSchema().test('is-regex', function (value: strin export const regexStringListSchema = arraySchema().of(regexStringSchema.clone().required()); -const versionSchema = stringSchema().test('is-version', function (value: string | undefined) { - return !isDefined(value) || /^\d+\.\d+\.\d+$/.test(value); +const versionRangeSchema = stringSchema().test('is-version-range', function (value: string | undefined) { + return !isDefined(value) || isDefined(getValidatedRange(value)); }); const cssSelectorSchema = stringSchema().test('is-css-selector', function (value: string | undefined) { @@ -122,8 +123,7 @@ const adPlacesRulesSchema = arraySchema() .required(), stylesOverrides: arraySchema().of(adStylesOverridesSchema.clone().required()), shouldHideOriginal: booleanSchema().default(false), - firstExtVersion: versionSchema, - lastExtVersion: versionSchema + extVersion: versionRangeSchema }) .required() ) @@ -163,8 +163,7 @@ const permanentAdPlacesRulesSchema = arraySchema() elementToMeasureSelector: cssSelectorSchema, stylesOverrides: arraySchema().of(adStylesOverridesSchema.clone().required()), shouldHideOriginal: booleanSchema().default(false), - firstExtVersion: versionSchema, - lastExtVersion: versionSchema + extVersion: versionRangeSchema }) .test('insertion-place-specified', (value: PermanentAdPlacesRule | undefined) => { if (!value) { @@ -195,8 +194,7 @@ const adProvidersByDomainRulesSchema = arraySchema() .shape({ urlRegexes: arraySchema().of(regexStringSchema.clone().required()).required(), providers: arraySchema().of(stringSchema().required()).required(), - firstExtVersion: versionSchema, - lastExtVersion: versionSchema + extVersion: versionRangeSchema }) .required() ) @@ -207,8 +205,7 @@ export const adProvidersByDomainsRulesDictionarySchema: IObjectSchema> = diff --git a/yarn.lock b/yarn.lock index 4649e53..44c2709 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4014,6 +4014,13 @@ semver@^7.2.1, semver@^7.3.7, semver@^7.3.8: dependencies: lru-cache "^6.0.0" +semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"