adding the findSelectors

This commit is contained in:
Yanick Champoux 2022-08-30 10:09:24 -04:00
parent 63d8235346
commit 51421c1052
4 changed files with 66 additions and 11 deletions

View File

@ -40,7 +40,7 @@ export class Updux {
this.#selectors = buildSelectors(
config.selectors,
config.splatSelectors,
config.findSelectors,
this.#subduxes,
);

View File

@ -1,6 +1,8 @@
import { test, expect } from 'vitest';
import R from 'remeda';
import { dux } from './Updux.js';
import { dux, Updux } from './Updux.js';
import { matches } from './utils.js';
test('basic selectors', () => {
const foo = dux({
@ -22,3 +24,46 @@ test('basic selectors', () => {
expect(foo.selectors.getY({ bar: { y: 3 } })).toBe(3);
});
test('splat selector', async () => {
const bar = new Updux({
initial: { id: 0, label: '' },
selectors: {
getLabel: R.prop('label'),
getLabelAppended: (state) => (suffix) => state.label + ' ' + suffix,
},
});
const foo = new Updux({
initial: [],
findSelectors: {
getBar: (state) => (id) => {
return state.find(matches({ id }));
},
},
selectors: {
getNbrBars: (state) => state.length,
},
subduxes: {
'*': bar,
},
});
const state = [
{ id: 1, label: 'one' },
{ id: 2, label: 'two' },
];
const store = foo.createStore(state);
expect(foo.selectors.getBar(state)(2).state).toMatchObject(state[1]);
expect(store.getState.getBar(2).state).toMatchObject(state[1]);
expect(store.getState.getNbrBars()).toBe(2);
expect(store.getState.getBar(1).getLabel()).toEqual('one');
expect(store.getState.getBar(1).getLabelAppended('plus one')).toEqual(
'one plus one',
);
});

View File

@ -2,7 +2,7 @@ import R from 'remeda';
export function buildSelectors(
localSelectors,
splatSelector = {},
findSelectors = {},
subduxes = {},
) {
const subSelectors = Object.entries(subduxes).map(
@ -19,18 +19,22 @@ export function buildSelectors(
let splat = {};
for (const name in splatSelector) {
for (const name in findSelectors) {
splat[name] =
(state) =>
(mainState) =>
(...args) => {
const value = splatSelector[name](state)(...args);
const state = findSelectors[name](mainState)(...args);
const res = () => value;
return merge(
res,
mapValues(
return R.merge(
{ state },
R.mapValues(
subduxes['*'].selectors,
(selector) => () => selector(value),
(selector) =>
(...args) => {
let value = selector(state);
if (typeof value !== 'function') return value;
return value(...args);
},
),
);
};

6
src/utils.js Normal file
View File

@ -0,0 +1,6 @@
export const matches = (conditions) => (target) =>
Object.entries(conditions).every(([key, value]) =>
typeof value === 'function'
? value(target[key])
: target[key] === value,
);