Skip to content

Commit

Permalink
feat: CommonKeyValueDao beforeCreate hook
Browse files Browse the repository at this point in the history
Allows getByIdOrEmpty, patch
  • Loading branch information
kirillgroshkov committed Jan 4, 2022
1 parent 5c2f50f commit 4ed92a3
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 24 deletions.
25 changes: 7 additions & 18 deletions src/commondao/common.dao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export class CommonDao<
}

// CREATE
create(input: Partial<BM>, opt: CommonDaoOptions = {}): Saved<BM> {
let bm = this.cfg.hooks!.beforeCreate!(input) as BM
create(part: Partial<BM>, opt: CommonDaoOptions = {}): Saved<BM> {
let bm = this.cfg.hooks!.beforeCreate!(part) as BM
bm = this.validateAndConvert(bm, this.cfg.bmSchema, DBModelType.BM, opt)

// If no SCHEMA - return as is
Expand Down Expand Up @@ -124,29 +124,18 @@ export class CommonDao<
return bm || null
}

async getByIdOrCreate(
id: string,
bmToCreate: Partial<BM>,
opt?: CommonDaoOptions,
): Promise<Saved<BM>> {
const bm = await this.getById(id, opt)
if (bm) return bm

return this.create({ ...bmToCreate, id }, opt)
}

async getByIdOrEmpty(id: string, opt?: CommonDaoOptions): Promise<Saved<BM>> {
async getByIdOrEmpty(id: string, part: Partial<BM>, opt?: CommonDaoOptions): Promise<Saved<BM>> {
const bm = await this.getById(id, opt)
if (bm) return bm

return this.create({ id } as Partial<BM>, opt)
return this.create({ ...part, id }, opt)
}

async getByIdAsDBMOrEmpty(id: string, opt?: CommonDaoOptions): Promise<DBM> {
async getByIdAsDBMOrEmpty(id: string, part: Partial<BM>, opt?: CommonDaoOptions): Promise<DBM> {
const dbm = await this.getByIdAsDBM(id, opt)
if (dbm) return dbm

const bm: BM = this.create({ id } as Partial<BM>, opt) as any
const bm: BM = this.create({ ...part, id }, opt) as any
return await this.bmToDBM(bm, opt)
}

Expand Down Expand Up @@ -614,7 +603,7 @@ export class CommonDao<
): Promise<Saved<BM>> {
return await this.save(
{
...(await this.getByIdOrCreate(id, patch, opt)),
...(await this.getByIdOrEmpty(id, patch, opt)),
...patch,
} as any,
opt,
Expand Down
40 changes: 34 additions & 6 deletions src/kv/commonKeyValueDao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ export interface CommonKeyValueDaoCfg<T> {
logStarted?: boolean

hooks?: {
mapValueToBuffer(v: T): Promise<Buffer>
mapBufferToValue(b: Buffer): Promise<T>
mapValueToBuffer?: (v: T) => Promise<Buffer>
mapBufferToValue?: (b: Buffer) => Promise<T>
beforeCreate?: (v: Partial<T>) => Partial<T>
}
}

Expand All @@ -45,19 +46,46 @@ export class CommonKeyValueDao<T> {
await this.cfg.db.createTable(this.cfg.table, opt)
}

create(input: Partial<T> = {}): T {
return {
...this.cfg.hooks?.beforeCreate?.(input),
} as T
}

async getById(id?: string): Promise<T | null> {
if (!id) return null
const [r] = await this.getByIds([id])
return r?.[1] || null
}

async getByIdOrEmpty(id: string, part: Partial<T> = {}): Promise<T> {
const [r] = await this.getByIds([id])
if (r) return r[1]

return {
...this.cfg.hooks?.beforeCreate?.({}),
...part,
} as T
}

async patch(id: string, patch: Partial<T>): Promise<T> {
const v: T = {
...(await this.getByIdOrEmpty(id)),
...patch,
}

await this.save(id, v)

return v
}

async getByIds(ids: string[]): Promise<KeyValueTuple<string, T>[]> {
const entries = await this.cfg.db.getByIds(this.cfg.table, ids)
if (!this.cfg.hooks?.mapBufferToValue) return entries as any

return await pMap(entries, async ([id, buf]) => [
id,
await this.cfg.hooks!.mapBufferToValue(buf),
await this.cfg.hooks!.mapBufferToValue!(buf),
])
}

Expand All @@ -73,7 +101,7 @@ export class CommonKeyValueDao<T> {
} else {
bufferEntries = await pMap(entries, async ([id, v]) => [
id,
await this.cfg.hooks!.mapValueToBuffer(v),
await this.cfg.hooks!.mapValueToBuffer!(v),
])
}

Expand All @@ -100,7 +128,7 @@ export class CommonKeyValueDao<T> {
// todo: consider it when readableMap supports `errorMode: SUPPRESS`
// readableMap(this.cfg.db.streamValues(this.cfg.table, limit), async buf => await this.cfg.hooks!.mapBufferToValue(buf))
return this.cfg.db.streamValues(this.cfg.table, limit).pipe(
transformMap(async buf => await this.cfg.hooks!.mapBufferToValue(buf), {
transformMap(async buf => await this.cfg.hooks!.mapBufferToValue!(buf), {
errorMode: ErrorMode.SUPPRESS, // cause .pipe cannot propagate errors
}),
)
Expand All @@ -112,7 +140,7 @@ export class CommonKeyValueDao<T> {
}

return this.cfg.db.streamEntries(this.cfg.table, limit).pipe(
transformMap(async ([id, buf]) => [id, await this.cfg.hooks!.mapBufferToValue(buf)], {
transformMap(async ([id, buf]) => [id, await this.cfg.hooks!.mapBufferToValue!(buf)], {
errorMode: ErrorMode.SUPPRESS, // cause .pipe cannot propagate errors
}),
)
Expand Down

0 comments on commit 4ed92a3

Please sign in to comment.