openreplay/tracker/tracker-zustand/src/index.ts
2022-09-26 12:32:36 +02:00

68 lines
1.6 KiB
TypeScript

import { App, Messages } from '@openreplay/tracker'
import { Encoder, sha1 } from './syncod/index.js'
export interface Options {
filter: (mutation: any, state: any) => boolean
transformer: (state: any) => any
mutationTransformer: (mutation: any) => any
}
function processMutationAndState(
app: App,
options: Options,
encoder: Encoder,
mutation: string[],
state: Record<string, any>,
) {
if (options.filter(mutation, state)) {
try {
const _mutation = encoder.encode(options.mutationTransformer(mutation))
const _state = encoder.encode(options.transformer(state))
const _table = encoder.commit()
for (let key in _table) app.send(Messages.OTable(key, _table[key]))
app.send(Messages.Zustand(_mutation, _state))
} catch (e) {
encoder.clear()
app.debug.error(e)
}
}
}
export default function(opts: Partial<Options> = {}) {
const options: Options = Object.assign(
{
filter: () => true,
transformer: (state) => state,
mutationTransformer: (mutation) => mutation,
},
opts,
)
return (app: App | null) => {
if (app === null) {
return Function.prototype
}
const encoder = new Encoder(sha1, 50)
const state = {}
return (
storeName: string = Math.random()
.toString(36)
.substring(2, 9),
) => (config: Function) => (
set: (...args: any) => void,
get: () => Record<string, any>,
api: any,
) =>
config(
(...args) => {
set(...args)
const newState = get()
state[storeName] = newState
const triggeredActions = args.map((action) => action.toString?.())
processMutationAndState(app, options, encoder, triggeredActions, state)
},
get,
api,
)
}
}