|
| 1 | +import type { Project } from '@repo/editor' |
| 2 | +import { createFactory } from '@withease/factories' |
| 3 | +import { createEvent, createStore, sample } from 'effector' |
| 4 | +import { persist as persistInQuery } from 'effector-storage/query' |
| 5 | +import { once, readonly } from 'patronum' |
| 6 | +import { base64Url } from '#shared/lib/base64-url' |
| 7 | +import { defaultProject } from './default-project' |
| 8 | +import type { EditorGate } from './gate' |
| 9 | + |
| 10 | +export type ProjectSerializerStore = ReturnType<typeof createProjectSerializer> |
| 11 | + |
| 12 | +type Params = { |
| 13 | + gate: EditorGate |
| 14 | +} |
| 15 | + |
| 16 | +export const createProjectSerializer = createFactory((params: Params) => { |
| 17 | + const { gate } = params |
| 18 | + |
| 19 | + const $loadedProject = createStore<Project>(defaultProject) |
| 20 | + |
| 21 | + const userChangedProject = createEvent<Project>() |
| 22 | + const storageUpdated = createEvent<Project | null>() |
| 23 | + |
| 24 | + persistInQuery({ |
| 25 | + key: 'project', |
| 26 | + source: userChangedProject, |
| 27 | + pickup: sample({ |
| 28 | + clock: gate.opened, |
| 29 | + // TODO: maybe find another way to fix this |
| 30 | + filter: () => !process.env.STORYBOOK, |
| 31 | + }), |
| 32 | + target: storageUpdated, |
| 33 | + serialize: obj => base64Url.encode(JSON.stringify(obj)), |
| 34 | + deserialize: query => JSON.parse(base64Url.decode(query)) as Project, |
| 35 | + }) |
| 36 | + |
| 37 | + sample({ |
| 38 | + clock: once(storageUpdated), |
| 39 | + filter: project => project !== null, |
| 40 | + target: $loadedProject, |
| 41 | + }) |
| 42 | + |
| 43 | + return { |
| 44 | + $loadedProject: readonly($loadedProject), |
| 45 | + userChangedProject, |
| 46 | + } |
| 47 | +}) |
0 commit comments