Merge branch 'validate-schema'

This commit is contained in:
Yanick Champoux 2023-09-07 09:57:37 -04:00
commit 8e16d9fef7
3 changed files with 39 additions and 1 deletions

View File

@ -2,6 +2,7 @@
"type": "module",
"dependencies": {
"@yanick/updeep-remeda": "^2.2.0",
"ajv": "^8.12.0",
"expect-type": "^0.16.0",
"immer": "^9.0.15",
"json-schema-shorthand": "^2.0.0",

View File

@ -22,6 +22,7 @@ import {
EffectMiddleware,
} from './effects.js';
import buildSchema from './schema.js';
import Ajv from 'ajv';
export type Mutation<A = AnyAction, S = any> = (
payload: A extends {
@ -32,6 +33,19 @@ export type Mutation<A = AnyAction, S = any> = (
action: A,
) => (state: S) => S | void;
function buildValidateMiddleware(schema) {
// @ts-ignore
const ajv = new Ajv();
const validate = ajv.compile(schema);
return (api) => next => action => {
next(action);
const valid = validate(api.getState());
if (!valid) throw new Error("validation failed after action " + JSON.stringify(action) + "\n" + JSON.stringify(validate.errors));
}
}
export default class Updux<D extends DuxConfig> {
#mutations = [];
@ -174,6 +188,7 @@ export default class Updux<D extends DuxConfig> {
createStore(
options: Partial<{
preloadedState: DuxState<D>;
validate: boolean;
}> = {},
): EnhancedStore<DuxState<D>> & AugmentedMiddlewareAPI<D> {
const preloadedState = options.preloadedState;
@ -184,10 +199,18 @@ export default class Updux<D extends DuxConfig> {
this.selectors,
);
const middleware = [effects];
if (options.validate) {
middleware.unshift(
buildValidateMiddleware(this.schema)
)
}
const store = configureStore({
reducer: this.reducer,
preloadedState,
middleware: [effects],
middleware,
});
const dispatch: any = store.dispatch;

View File

@ -29,3 +29,17 @@ test('schema default inherits from initial state', () => {
expect(dux.schema.default).toEqual(8);
});
test('validate', () => {
const dux = new Updux({
initialState: 12,
actions: {
doItWrong: null,
},
});
dux.addMutation('doItWrong', () => () => 'potato' as any);
const store = dux.createStore({ validate: true });
expect(() => store.dispatch.doItWrong()).toThrow();
});