Merge branch 'subdux-selectors'

This commit is contained in:
Yanick Champoux 2023-09-20 10:49:05 -04:00
commit 7280381ca8
6 changed files with 105 additions and 89 deletions

View File

@ -15,6 +15,7 @@
},
"license": "MIT",
"module": "dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js"

View File

@ -122,17 +122,17 @@ export default class Updux<D extends DuxConfig> {
matcher: A,
mutation: Mutation<DuxActions<D>[A] extends (...args: any) => infer P ? P : never, DuxState<D>>,
terminal?: boolean,
);
): Updux<D>;
addMutation<A extends Action<any>>(
matcher: (action: A) => boolean,
mutation: Mutation<A, DuxState<D>>,
terminal?: boolean,
);
): Updux<D>;
addMutation<A extends ActionCreator<any>>(
actionCreator: A,
mutation: Mutation<ReturnType<A>, DuxState<D>>,
terminal?: boolean,
);
): Updux<D>;
addMutation(matcher, mutation, terminal = false) {
if (typeof matcher === 'string') {
@ -157,6 +157,8 @@ export default class Updux<D extends DuxConfig> {
mutation,
},
];
return this;
}
#defaultMutation;
@ -189,6 +191,7 @@ export default class Updux<D extends DuxConfig> {
options: Partial<{
preloadedState: DuxState<D>;
validate: boolean;
buildMiddleware: (middleware: any[]) => any
}> = {},
): EnhancedStore<DuxState<D>> & AugmentedMiddlewareAPI<D> {
const preloadedState = options.preloadedState;
@ -199,7 +202,7 @@ export default class Updux<D extends DuxConfig> {
this.selectors,
);
const middleware = [effects];
let middleware = [effects];
if (options.validate) {
middleware.unshift(
@ -207,6 +210,9 @@ export default class Updux<D extends DuxConfig> {
)
}
if (options.buildMiddleware)
middleware = options.buildMiddleware(middleware);
const store = configureStore({
reducer: this.reducer,
preloadedState,
@ -253,16 +259,16 @@ export default class Updux<D extends DuxConfig> {
addEffect(
actionType: keyof DuxActions<D>,
effect: EffectMiddleware<D>,
): EffectMiddleware<D>;
): Updux<D>;
addEffect(
actionCreator: { match: (action: any) => boolean },
effect: EffectMiddleware<D>,
): EffectMiddleware<D>;
): Updux<D>;
addEffect(
guardFunc: (action: AnyAction) => boolean,
effect: EffectMiddleware<D>,
): EffectMiddleware<D>;
addEffect(effect: EffectMiddleware<D>): EffectMiddleware<D>;
): Updux<D>;
addEffect(effect: EffectMiddleware<D>): Updux<D>;
addEffect(...args) {
let effect;
if (args.length === 1) {
@ -294,10 +300,10 @@ export default class Updux<D extends DuxConfig> {
this.#effects = [...this.#effects, effect];
return effect;
return this;
}
get effects() {
get effects(): any {
return this.memoBuildEffects(this.#effects, this.duxConfig.subduxes);
}

View File

@ -126,10 +126,10 @@ test('addEffect with actionCreator', () => {
const next = vi.fn();
const spy = vi.fn();
const mw = dux.addEffect(
const [mw] = dux.addEffect(
dux.actions.foo,
(api) => (next) => (action) => next(spy(action)),
);
).effects;
mw({} as any)(next)(dux.actions.bar());
expect(next).toHaveBeenCalled();
@ -152,10 +152,10 @@ test('addEffect with function', () => {
const next = vi.fn();
const spy = vi.fn();
const mw = dux.addEffect(
const [mw] = dux.addEffect(
(action) => action.type[0] === 'f',
(api) => (next) => (action) => next(spy(action)),
);
).effects;
mw({} as any)(next)(dux.actions.bar());
expect(next).toHaveBeenCalled();
@ -170,13 +170,13 @@ test('addEffect with function', () => {
test('catchall addEffect', () => {
const dux = new Updux({
initialState: {
a: 1
}
a: 1,
},
});
const spy = vi.fn();
dux.addEffect((api) => next => action => {
dux.addEffect((api) => (next) => (action) => {
expectTypeOf(api.getState()).toMatchTypeOf<{
a: number;
}>();
@ -191,7 +191,6 @@ test('catchall addEffect', () => {
store.dispatch({ type: 'noop' });
expect(spy).toHaveBeenCalled();
});
// TODO subdux effects

View File

@ -5,7 +5,7 @@ import Updux, { createAction } from './index.js';
describe('basic selectors', () => {
type State = { x: number };
const foo = new Updux({
const config = {
initialState: {
x: 1,
},
@ -23,8 +23,16 @@ describe('basic selectors', () => {
(y + incr) as number,
},
}),
// cause the type to fail
baz: new Updux({
selectors: {
getFromBaz: () => 'potato',
},
});
}),
},
};
const foo = new Updux(config);
const sample = {
x: 4,

View File

@ -17,9 +17,11 @@ type Values<X> = X[keyof X];
export type DuxSelectors<D> = (D extends { selectors: infer S } ? S : {}) &
(D extends { subduxes: infer SUB }
? Values<{
? UnionToIntersection<
Values<{
[key in keyof SUB]: RebaseSelectors<key, SUB[key]>;
}>
>
: {});
export function buildSelectors(localSelectors = {}, subduxes = {}) {

View File

@ -48,7 +48,7 @@
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */