Skip to content

Commit f6b3b50

Browse files
committed
[metrics] Add forEachMetric method
1 parent 2b0f091 commit f6b3b50

File tree

7 files changed

+69
-3
lines changed

7 files changed

+69
-3
lines changed

src/common/definable.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export const getDefinableFunctions = <Thing, RowValue>(
2929
): [
3030
() => Store,
3131
() => Ids,
32+
(cb: (id: Id, value: Thing) => void) => void,
3233
(id: Id) => boolean,
3334
(id: Id) => Id,
3435
(id: Id) => Thing | undefined,
@@ -54,6 +55,9 @@ export const getDefinableFunctions = <Thing, RowValue>(
5455

5556
const getThingIds = (): Ids => mapKeys(tableIds);
5657

58+
const forEachThing = (cb: (id: Id, value: Thing) => void): void =>
59+
mapForEach(things, cb);
60+
5761
const hasThing = (id: Id): boolean => collHas(things, id);
5862

5963
const getTableId = (id: Id): Id => mapGet(tableIds, id) as Id;
@@ -169,6 +173,7 @@ export const getDefinableFunctions = <Thing, RowValue>(
169173
return [
170174
getStore,
171175
getThingIds,
176+
forEachThing,
172177
hasThing,
173178
getTableId,
174179
getThing,

src/indexes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export const createIndexes: typeof createIndexesDecl = getCreateFunction(
3737
const [
3838
getStore,
3939
getIndexIds,
40+
_forEachIndex,
4041
hasIndex,
4142
getTableId,
4243
getIndex,

src/metrics.d.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ import {Id, IdOrNull, Ids} from './common.d';
2222
*/
2323
export type Metric = number;
2424

25+
/**
26+
* The MetricCallback type describes a function that takes a Metric's Id and a
27+
* callback to loop over each Row within it.
28+
*
29+
* A MetricCallback is provided when using the forEachMetric method, so that you
30+
* can do something based on every Metric in the Metrics object. See that method
31+
* for specific examples.
32+
*
33+
* @param metricId The Id of the Metric that the callback can operate on.
34+
* @param metric The value of the Metric.
35+
* @category Callback
36+
*/
37+
export type MetricCallback = (metricId: Id, metric?: Metric) => void;
38+
2539
/**
2640
* The Aggregate type describes a custom function that takes an array or numbers
2741
* and returns an aggregate that is used as a Metric.
@@ -478,6 +492,38 @@ export interface Metrics {
478492
*/
479493
getMetricIds(): Ids;
480494

495+
/**
496+
* The forEachMetric method takes a function that it will then call for each
497+
* Metric in the Metrics object.
498+
*
499+
* This method is useful for iterating over all the Metrics in a functional
500+
* style. The `metricCallback` parameter is a MetricCallback function that
501+
* will called with the Id of each Metric and its value.
502+
*
503+
* @param metricCallback The function that should be called for every Metric.
504+
* @example
505+
* This example iterates over each Metric in a Metrics object.
506+
*
507+
* ```js
508+
* const store = createStore().setTable('species', {
509+
* dog: {price: 5},
510+
* cat: {price: 4},
511+
* worm: {price: 1},
512+
* });
513+
* const metrics = createMetrics(store)
514+
* .setMetricDefinition('highestPrice', 'species', 'max', 'price')
515+
* .setMetricDefinition('lowestPrice', 'species', 'min', 'price');
516+
*
517+
* metrics.forEachMetric((metricId, metric) => {
518+
* console.log([metricId, metric]);
519+
* });
520+
* // -> ['highestPrice', 5]
521+
* // -> ['lowestPrice', 1]
522+
* ```
523+
* @category Iterator
524+
*/
525+
forEachMetric(metricCallback: MetricCallback): void;
526+
481527
/**
482528
* The hasMetric method returns a boolean indicating whether a given Metric
483529
* exists in the Metrics object, and has a value.

src/metrics.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export const createMetrics: typeof createMetricsDecl = getCreateFunction(
9898
const [
9999
getStore,
100100
getMetricIds,
101+
forEachMetric,
101102
hasMetric,
102103
getTableId,
103104
getMetric,
@@ -222,6 +223,7 @@ export const createMetrics: typeof createMetricsDecl = getCreateFunction(
222223

223224
getStore,
224225
getMetricIds,
226+
forEachMetric,
225227
hasMetric,
226228
getTableId,
227229
getMetric,

src/relationships.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const createRelationships: typeof createRelationshipsDecl =
3939
const [
4040
getStore,
4141
getRelationshipIds,
42+
_forEachRelationship,
4243
hasRelationship,
4344
getLocalTableId,
4445
getRelationship,

test/unit/common.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,9 @@ export const getMetricsObject = (
285285
metrics: Metrics,
286286
): IdMap<number | undefined> => {
287287
const metricsObject: IdMap<number | undefined> = {};
288-
metrics.getMetricIds().forEach((metricId) => {
289-
metricsObject[metricId] = metrics.getMetric(metricId);
290-
});
288+
metrics.forEachMetric(
289+
(metricId) => (metricsObject[metricId] = metrics.getMetric(metricId)),
290+
);
291291
return metricsObject;
292292
};
293293

test/unit/metrics.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,17 @@ describe('Miscellaneous', () => {
612612
expectNoChanges(listener);
613613
});
614614

615+
test('forEachMetric', () => {
616+
metrics.setMetricDefinition('m1', 't1', 'max', 'c1');
617+
metrics.setMetricDefinition('m2', 't1', 'min', 'c1');
618+
setCells();
619+
const eachMetric: any = {};
620+
metrics.forEachMetric(
621+
(metricId, metric) => (eachMetric[metricId] = metric),
622+
);
623+
expect(eachMetric).toEqual({m1: 5, m2: 1});
624+
});
625+
615626
test('are things present', () => {
616627
expect(metrics.hasMetric('m1')).toEqual(false);
617628
metrics.setMetricDefinition('m1', 't1');

0 commit comments

Comments
 (0)