Skip to content

Commit 9b1a7a0

Browse files
Merge pull request #89 from oliver-oloughlin/patch/improved-handle-many
refactored handleMany to be more reusable and handle errors
2 parents 439fc2e + b2a9017 commit 9b1a7a0

File tree

3 files changed

+159
-175
lines changed

3 files changed

+159
-175
lines changed

src/collection.ts

+71-60
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,20 @@ import {
3939
import { Document } from "./document.ts"
4040
import { model } from "./model.ts"
4141

42+
/**
43+
* Create a collection builder function.
44+
*
45+
* @example
46+
* ```ts
47+
* collection(model<number>(), {
48+
* idGenerator: () => ulid()
49+
* })
50+
* ```
51+
*
52+
* @param model - Model.
53+
* @param options - Collection options.
54+
* @returns A collection builder function.
55+
*/
4256
export function collection<const T1 extends KvValue>(
4357
model: Model<T1>,
4458
options?: CollectionOptions<T1>,
@@ -347,30 +361,12 @@ export class Collection<
347361
value: UpdateData<T1>,
348362
options?: UpdateManyOptions<T1>,
349363
) {
350-
// Initiate result and error list
351-
const result: (CommitResult<T1> | Deno.KvCommitError)[] = []
352-
const errors: unknown[] = []
353-
354364
// Update each document, add commit result to result list
355-
const { cursor } = await this.handleMany(async (doc) => {
356-
try {
357-
const cr = await this.updateDocument(doc, value, options)
358-
result.push(cr)
359-
} catch (e) {
360-
errors.push(e)
361-
}
362-
}, options)
363-
364-
// Throw errors if caught
365-
if (errors.length > 0) {
366-
throw errors
367-
}
368-
369-
// Return result list and current iterator cursor
370-
return {
371-
result,
372-
cursor,
373-
}
365+
return await this.handleMany(
366+
this._keys.idKey,
367+
(doc) => this.updateDocument(doc, value, options),
368+
options,
369+
)
374370
}
375371

376372
/**
@@ -445,7 +441,13 @@ export class Collection<
445441
*/
446442
async deleteMany(options?: ListOptions<T1>) {
447443
// Execute delete operation for each document entry
448-
return await this.handleMany((doc) => this.delete(doc.id), options)
444+
const { cursor } = await this.handleMany(
445+
this._keys.idKey,
446+
(doc) => this.delete(doc.id),
447+
options,
448+
)
449+
450+
return { cursor }
449451
}
450452

451453
/**
@@ -468,20 +470,12 @@ export class Collection<
468470
* @returns A promise that resovles to an object containing a list of the retrieved documents and the iterator cursor
469471
*/
470472
async getMany(options?: ListOptions<T1>) {
471-
// Initiate result list
472-
const result: Document<T1>[] = []
473-
474-
// Add each document entry to result list
475-
const { cursor } = await this.handleMany(
476-
(doc) => result.push(doc),
473+
// Get each document, return result list and current iterator cursor
474+
return await this.handleMany(
475+
this._keys.idKey,
476+
(doc) => doc,
477477
options,
478478
)
479-
480-
// Return result list and current iterator cursor
481-
return {
482-
result,
483-
cursor,
484-
}
485479
}
486480

487481
/**
@@ -505,8 +499,14 @@ export class Collection<
505499
* @returns A promise that resovles to an object containing the iterator cursor
506500
*/
507501
async forEach(fn: (doc: Document<T1>) => void, options?: ListOptions<T1>) {
508-
// Execute callback function for each document entry
509-
return await this.handleMany((doc) => fn(doc), options)
502+
// Execute callback function for each document entry and return cursor
503+
const { cursor } = await this.handleMany(
504+
this._keys.idKey,
505+
(doc) => fn(doc),
506+
options,
507+
)
508+
509+
return { cursor }
510510
}
511511

512512
/**
@@ -531,24 +531,16 @@ export class Collection<
531531
* @param options - List options, optional.
532532
* @returns A promise that resovles to an object containing a list of the callback results and the iterator cursor
533533
*/
534-
async map<const TMapped>(
535-
fn: (doc: Document<T1>) => TMapped,
534+
async map<const T>(
535+
fn: (doc: Document<T1>) => T,
536536
options?: ListOptions<T1>,
537537
) {
538-
// Initiate result list
539-
const result: TMapped[] = []
540-
541-
// Execute callback function for each document entry, add to result list
542-
const { cursor } = await this.handleMany(
543-
(doc) => result.push(fn(doc)),
538+
// Execute callback function for each document entry, return result and cursor
539+
return await this.handleMany(
540+
this._keys.idKey,
541+
(doc) => fn(doc),
544542
options,
545543
)
546-
547-
// Return result list and current iterator cursor
548-
return {
549-
result,
550-
cursor,
551-
}
552544
}
553545

554546
/**
@@ -571,7 +563,7 @@ export class Collection<
571563
async count(options?: CountOptions<T1>) {
572564
// Initiate count variable, increment for each document entry, return result
573565
let result = 0
574-
await this.handleMany(() => result++, options)
566+
await this.handleMany(this._keys.idKey, () => result++, options)
575567
return result
576568
}
577569

@@ -709,18 +701,24 @@ export class Collection<
709701
/**
710702
* Perform operations on lists of documents in the collection.
711703
*
704+
* @param prefixKey - Prefix key for list selector.
712705
* @param fn - Callback function.
713706
* @param options - List options, optional.
714707
* @returns Promise that resolves to object with iterator cursor.
715708
*/
716-
protected async handleMany(
717-
fn: (doc: Document<T1>) => unknown,
718-
options?: ListOptions<T1>,
709+
protected async handleMany<const T>(
710+
prefixKey: KvKey,
711+
fn: (doc: Document<T1>) => T,
712+
options: ListOptions<T1> | undefined,
719713
) {
720-
// Create list iterator with given options, initiate documents list
721-
const selector = createListSelector(this._keys.idKey, options)
714+
// Create list iterator with given options
715+
const selector = createListSelector(prefixKey, options)
722716
const iter = this.kv.list<T1>(selector, options)
717+
718+
// Initiate lists
723719
const docs: Document<T1>[] = []
720+
const result: Awaited<T>[] = []
721+
const errors: unknown[] = []
724722

725723
// Loop over each document entry
726724
for await (const { key, value, versionstamp } of iter) {
@@ -744,10 +742,23 @@ export class Collection<
744742
}
745743

746744
// Execute callback function for each document
747-
await allFulfilled(docs.map((doc) => fn(doc)))
745+
await allFulfilled(docs.map(async (doc) => {
746+
try {
747+
const res = await fn(doc)
748+
result.push(res)
749+
} catch (e) {
750+
errors.push(e)
751+
}
752+
}))
748753

749-
// Return current iterator cursor
754+
// Throw any caught errors
755+
if (errors.length > 0) {
756+
throw errors
757+
}
758+
759+
// Return result and current iterator cursor
750760
return {
761+
result,
751762
cursor: iter.cursor || undefined,
752763
}
753764
}

0 commit comments

Comments
 (0)