diff --git a/README.md b/README.md index fe17ff1..1c8049e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ const tower = createTower({ committerName: 'Foo Bar', // Username and email to sign annotaged git tags committerEmail: 'foo@bar.baz', // Defaults to Semrel Extra Bot format: v => v + '', // Opt value formatter. Defaults to JSON.stringify - parse: v => v // Opt parser. Defaults to JSON.parse + parse: v => v, // Opt parser. Defaults to JSON.parse + filter: v => v % 2 // Opt low level filter (applied before parse). Defaults to () => true }) const id: string = 'some@tag' diff --git a/src/main/ts/index.ts b/src/main/ts/index.ts index 1e6f61b..463dca2 100644 --- a/src/main/ts/index.ts +++ b/src/main/ts/index.ts @@ -1,5 +1,5 @@ import {readTags, deleteTag, pushTags} from './git' -import {TTagEntry, TTower, TTowerFactory, TTowerOpts} from './interface' +import {TFilter, TTagEntry, TTower, TTowerFactory, TTowerOpts} from './interface' export const createTower: TTowerFactory = (opts: TTowerOpts): TTower => ({ async create(tag, data){ @@ -8,14 +8,18 @@ export const createTower: TTowerFactory = (opts: TTowerOpts): TTower => ({ }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - async read(id?: string) { + async read(id?: string | TFilter) { const parser = opts.parse || parse - const entries: TTagEntry[] = (await readTags(opts)).map(({tag: id, body}) => ({id, data: parser(body)})) - if (id === undefined) { - return entries + const predicate = typeof id === 'function' ? id : (opts.filter || filter) + const entries: TTagEntry[] = (await readTags(opts)) + .filter(predicate) + .map(({tag: id, body}) => ({id, data: parser(body)})) + + if (typeof id === 'string') { + return entries.find(({id: _id}) => _id === id) || null } - return entries.find(({id: _id}) => _id === id) || null + return entries }, async delete(tag) { await deleteTag({...opts, tag}) @@ -26,6 +30,7 @@ export const createTower: TTowerFactory = (opts: TTowerOpts): TTower => ({ } }) +const filter = () => true const format = JSON.stringify const parse = (value: any): TTagEntry['data'] => { try { diff --git a/src/main/ts/interface.ts b/src/main/ts/interface.ts index 9567012..af1ddab 100644 --- a/src/main/ts/interface.ts +++ b/src/main/ts/interface.ts @@ -4,10 +4,12 @@ export type TTagEntry = { data: any } +export type TFilter = (v: {tag: string, body: string}) => boolean + export type TTower = { create(id: string, data: TTagEntry['data']): Promise read(id: string): Promise - read(): Promise + read(fn?: TFilter): Promise update(id: string, data: TTagEntry['data']): Promise delete(id: string): Promise } @@ -22,6 +24,7 @@ export type TTowerOpts = { committerEmail?: string parse?: (v: string) => any format?: (v: any) => string + filter?: TFilter } export type TAnnotatedTag = { diff --git a/src/test/ts/index.test.ts b/src/test/ts/index.test.ts index 82389ac..3dab378 100644 --- a/src/test/ts/index.test.ts +++ b/src/test/ts/index.test.ts @@ -41,7 +41,7 @@ describe('tagTower', () => { assert.equal(await tower.read(id), null) }) - it('supports custom parse/format', async () => { + it('supports custom parse, format & filter', async () => { const cwd = path.resolve(temp, 'custom-format') await fs.mkdir(cwd, { recursive: true }) await exec('git', ['init', '--bare'], {cwd}) @@ -55,6 +55,10 @@ describe('tagTower', () => { }) await tower.create('foo', 'bar') + await tower.create('baz', 'qux') assert.equal((await tower.read('foo'))?.data, '++bar++') + + const filtered = await tower.read(({tag}) => tag === 'foo') + assert.deepEqual(filtered, [{id: 'foo', data: '++bar++'}]) }) })