Skip to content

Support multiple packages #72

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: create package name filter
  • Loading branch information
OmarCastro committed Apr 1, 2022
commit f5facbe988e2d9085e87b4e888f96905030a1746
76 changes: 76 additions & 0 deletions __tests__/packages/package-name-filter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { getPackageNameFilter } from '../../src/packages'

describe('package name filter -- create filter', () => {

const packageNameList = [
'com.company.project.module1.package1',
'com.company.project.module1.package2',
'com.company.project.module2.package1',
'com.company.project.module2.package2',
'com.company.project.module3.package-name-lorem',
'com.company.project.module3.package-name-ipsum',
'com.company.project.module3.package-name-dolor',
]

it('getPackageNameFilter -- wildcard filter', done => {
const filter = getPackageNameFilter('com.company.project.module1.*')

const result = packageNameList.filter(filter.apply);

expect(filter.subfilters[0].type).toBe('wildcard')
expect(result).toEqual([
'com.company.project.module1.package1',
'com.company.project.module1.package2',
])
done()
})

it('getPackageNameFilter -- regex filter', done => {
const filter = getPackageNameFilter('/com\\.company\\.project\\.module.*\\.package1/')
const result = packageNameList.filter(filter.apply);

expect(filter.subfilters[0].type).toBe('regex')
expect(result).toEqual([
'com.company.project.module1.package1',
'com.company.project.module2.package1',
])
done()
})

it('getPackageNameFilter -- exact match filter', done => {
const filter = getPackageNameFilter('com.company.project.module1.package1')
const result = packageNameList.filter(filter.apply);

expect(filter.subfilters[0].type).toBe('string')
expect(result).toEqual(['com.company.project.module1.package1'])
done()
})


it('getPackageNameFilter -- multiple filters', done => {
const filter = getPackageNameFilter('com.company.project.module1.package1, com.company.project.module2.*, /.*module3.*-ipsum/')
const result = packageNameList.filter(filter.apply);

expect(filter.subfilters.length).toBe(3)
expect(filter.subfilters[0].type).toBe('string')
expect(filter.subfilters[1].type).toBe('wildcard')
expect(filter.subfilters[2].type).toBe('regex')
expect(result).toEqual([
'com.company.project.module1.package1',
'com.company.project.module2.package1',
'com.company.project.module2.package2',
'com.company.project.module3.package-name-ipsum'
])
done()
})


it('getPackageNameFilter -- memoization, same input shoud return same output', done => {
const filterText = 'com.company.project.module1.package1, com.company.project.module2.*, /.*module3.*-dolor/, *.-lorem'
const filter1 = getPackageNameFilter(filterText)
const filter2 = getPackageNameFilter(filterText)
expect(filter1).toBe(filter2)
expect(filter1.subfilters.length).toBe(4)
done()
})
})
114 changes: 114 additions & 0 deletions src/packages/package-name-filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Used to apply memoization on getPackageNameFilter
*/
const resultCache = {} as Record<string, PackageNamesFilter>

interface PackageNameSubFilter {
type: 'regex' | 'wildcard' | 'string'
apply: (packageName: string) => boolean
}

interface PackageNamesFilter {
readonly subfilters: readonly PackageNameSubFilter[]
readonly isEmpty: boolean
readonly apply: (packageName: string) => boolean
}


/**
* Get a filter based on package names to match
*
* @param packageNames - serialized package names filter as string
* @returns the respective package filter
*/
export function getPackageNameFilter(packageNames: string) : PackageNamesFilter {
if(resultCache[packageNames] ){
return resultCache[packageNames]
}
const result = calculatePackageNameFilter(packageNames)
resultCache[packageNames] = result
return result
}

const emptyFilter = Object.freeze({
subfilters: Object.freeze([]),
isEmpty: true,
apply:() => false as boolean
})

/**
* Generates a filter based package names to match
*
* @param packageNames - serialized package names filter as string
* @returns the respective package filter
*/
function calculatePackageNameFilter(packageNames: string): Readonly<PackageNamesFilter> {
if(packageNames === ""){
return emptyFilter;
}
const separatedPackageNames = packageNames
.split(",")
.map(packageName => packageName.trim())
.filter(packageNames => packageNames !== "")


if (separatedPackageNames.length <= 0){
return emptyFilter;
}

const subfilters = separatedPackageNames.map(createFilter)
return {
subfilters,
isEmpty: subfilters.length <= 0,
apply:(packageNames) => subfilters.some(filter => filter.apply(packageNames))
}

}


function createFilter(packageName: string): PackageNameSubFilter {
if(packageName.startsWith('*') || packageName.endsWith('*')){
return createWildcardFilter(packageName)
} else if(packageName.startsWith("/") && packageName.endsWith("/")){
return createRegexFilter(packageName)
} else {
return createExactMatchFilter(packageName)
}
}

function createWildcardFilter(wildcardPackageName: string): PackageNameSubFilter {
const startsWithWildCard = wildcardPackageName.startsWith('*')
const endsWithWildCard = wildcardPackageName.endsWith('*')
let fn: PackageNameSubFilter["apply"]
if(startsWithWildCard && endsWithWildCard){
const targetText = wildcardPackageName.substring(1, wildcardPackageName.length - 1)
fn = (packageName: string) => packageName.includes(targetText)
} else if(startsWithWildCard){
const targetText = wildcardPackageName.substring(1)
fn = (packageName: string) => packageName.endsWith(targetText)
} else {
const targetText = wildcardPackageName.substring(0, wildcardPackageName.length - 1)
fn = (packageName: string) => packageName.startsWith(targetText)
}
return {
type: 'wildcard',
apply: fn
}
}

function createRegexFilter(regexPackageName: string): PackageNameSubFilter {
const regexPattern = regexPackageName.substring(1, regexPackageName.length - 1)
const regex = new RegExp(regexPattern)
return {
type: 'regex',
apply: (packageName: string) => regex.test(packageName)
}
}

function createExactMatchFilter(matchingPackageName: string): PackageNameSubFilter {
return {
type: 'string',
apply: (packageName: string) => packageName === matchingPackageName
}

}