Skip to content

Commit

Permalink
feat(general): add option to use mapEntry/mapEntries directly on entries
Browse files Browse the repository at this point in the history
  • Loading branch information
Isaac Weaver committed Dec 17, 2018
1 parent acab70b commit 4182a48
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 11 deletions.
25 changes: 20 additions & 5 deletions src/ropex/RopexIndex.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { EntryKey, RopexState, RopexStateIndex } from './types';
import {
EntryKey,
RopexState,
RopexStateIndex,
RopexOptions,
EntryMap,
} from './types';
import { RopexStore } from './RopexStore';

export class RopexIndex<Entry extends object, K extends EntryKey> {
Expand Down Expand Up @@ -144,13 +150,18 @@ export class RopexIndex<Entry extends object, K extends EntryKey> {
*
* @param key The key of the entry to apply the map function to
* @param map Function to map an entry to another entry
* @param options Optional config for how to apply the map
*/
public mapEntry(key: K, map: (entry: Entry) => Entry): RopexIndex<Entry, K> {
public mapEntry(
key: K,
map: EntryMap<Entry>,
options?: RopexOptions,
): RopexIndex<Entry, K> {
if (!this.checkEntryInIndex(key)) {
return this;
}

this.ropexStore.mapEntry(key, map);
this.ropexStore.mapEntry(key, map, options);

return this;
}
Expand All @@ -159,10 +170,14 @@ export class RopexIndex<Entry extends object, K extends EntryKey> {
* Apply a map function to every entry in the index
*
* @param map Function to map an entry to another entry
* @param options Optional config for how to apply the map
*/
public mapEntries(map: (entry: Entry) => Entry): RopexIndex<Entry, K> {
public mapEntries(
map: EntryMap<Entry>,
options?: RopexOptions,
): RopexIndex<Entry, K> {
for (const key of this.indexState.keys) {
this.ropexStore.mapEntry(key, map);
this.ropexStore.mapEntry(key, map, options);
}

return this;
Expand Down
28 changes: 22 additions & 6 deletions src/ropex/RopexStore.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EntryKey, RopexState } from './types';
import { EntryKey, RopexState, EntryMap, RopexOptions } from './types';
import { RopexIndex } from './RopexIndex';

export class RopexStore<Entry extends object, K extends EntryKey> {
Expand Down Expand Up @@ -73,11 +73,23 @@ export class RopexStore<Entry extends object, K extends EntryKey> {
*
* @param key The key of the entry to apply the map function to
* @param map Function to map an entry to another entry
* @param options Optional config for how to apply the map
*/
public mapEntry(key: K, map: (entry: Entry) => Entry): RopexStore<Entry, K> {
public mapEntry(
key: K,
map: EntryMap<Entry>,
options?: RopexOptions,
): RopexStore<Entry, K> {
const entry = this.getEntry(key);

this.newState.drafts[key] = map(entry as Entry);
const config = options || { draft: true };

if (config.draft) {
this.newState.drafts[key] = map(entry as Entry);
} else {
this.newState.entries[key] = map(entry as Entry);
delete this.newState.drafts[key];
}

return this;
}
Expand All @@ -86,10 +98,14 @@ export class RopexStore<Entry extends object, K extends EntryKey> {
* Apply a map function to every entry in the store and safe the results as drafts
*
* @param map Function to map an entry to another entry
* @param options Optional config for how to apply the map
*/
public mapEntries(map: (entry: Entry) => Entry): RopexStore<Entry, K> {
for (const [key, entry] of Object.entries(this.getEntries())) {
this.newState.drafts[key] = map(entry as Entry);
public mapEntries(
map: EntryMap<Entry>,
options?: RopexOptions,
): RopexStore<Entry, K> {
for (const key of Object.keys(this.getEntries()) as K[]) {
this.mapEntry(key, map, options);
}

return this;
Expand Down
49 changes: 49 additions & 0 deletions src/ropex/__tests__/RopexIndex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,27 @@ describe('RopexIndex', () => {
.done(),
).toEqual(state);
});

it('Should update entries if draft is false', () => {
expect(
ropex({ ...baseState, drafts: {} })
.index('index')
.mapEntry('b', entry => ({ ...entry, data: 'test' }), {
draft: false,
})
.done(),
).toEqual({
...baseState,
entries: {
...baseState.entries,
b: {
id: 'b',
data: 'test',
},
},
drafts: {},
});
});
});

describe('.mapEntries()', () => {
Expand Down Expand Up @@ -254,6 +275,34 @@ describe('RopexIndex', () => {
.done(),
).toEqual(expectedState);
});

it('Should wipe the drafts and save as entries if draft is false', () => {
const state = {
...baseState,
entries: { ...baseState.entries, c: { id: 'c', data: 'test' } },
indexes: {
index: baseState.indexes.index,
other: { meta: {}, keys: ['c'] },
},
};

const expectedState = {
...state,
drafts: {},
entries: {
...state.entries,
a: { id: 'a', data: 'test' },
b: { id: 'b', data: 'test' },
},
};

expect(
ropex<Entry, string>(state)
.index('index')
.mapEntries(entry => ({ ...entry, data: 'test' }), { draft: false })
.done(),
).toEqual(expectedState);
});
});

describe('.remove()', () => {
Expand Down
37 changes: 37 additions & 0 deletions src/ropex/__tests__/RopexStore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,28 @@ describe('RopexStore', () => {
},
});
});

it('Should update the entries and clear the drafts if the option is set', () => {
expect(
ropex(baseState)
.mapEntry(
'b',
entry => ({
...entry,
data: entry.data + '_updated',
}),
{ draft: false },
)
.done(),
).toEqual({
...baseState,
entries: {
...baseState.entries,
b: { id: 'b', data: 'entry_b_draft_updated' },
},
drafts: {},
});
});
});
describe('.mapEntries()', () => {
it('Should apply map function to every entry and add result as draft', () => {
Expand Down Expand Up @@ -143,6 +165,21 @@ describe('RopexStore', () => {
},
});
});

it('Should update entries and clear drafts if draft is false', () => {
expect(
ropex(baseState)
.mapEntries(entry => ({ ...entry, data: 'test' }), { draft: false })
.done(),
).toEqual({
...baseState,
entries: {
a: { id: 'a', data: 'test' },
b: { id: 'b', data: 'test' },
},
drafts: {},
});
});
});

describe('.remove()', () => {
Expand Down
13 changes: 13 additions & 0 deletions src/ropex/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,16 @@ export type RopexState<E extends object, K extends EntryKey = string> = {
/** All the indexes */
indexes: Record<string, RopexStateIndex<any, K>>;
};

/**
* Function to map an entry to another entry
*/
export type EntryMap<E> = (entry: E) => E;

/**
* Options that can be passed to many RopeX functions
*/
export type RopexOptions = {
/** If true, will set the entries as drafts. Otherwise update the entries */
draft: boolean;
};

0 comments on commit 4182a48

Please sign in to comment.