UNPKG

react-garden

Version:

React + TypeScript + ThreeJS app using Material UI on NextJS, Apollo Client, GraphQL + WordPress REST APIs, for ThreeD web development.. a part of the threed.ai code family.

158 lines (136 loc) 4.48 kB
// ** "apollo-reactive-store": "0.0.4" import { makeVar, ReactiveVar, useReactiveVar } from '@apollo/client' // [MM] COLORFUL CONSOLE MESSAGES (ccm) import { ccm0, ccm1, ccm2, ccm3, ccm4, ccm5, ccm6 } from '~/@core/utils/console-colors' type State<T> = Record<string | symbol, T> type Store<T> = Record<string | symbol, ReactiveVar<T>> type TypePolicies = { Query: { fields: { [key: string]: { read(): any } } } } type Updater<Value> = (state: Value) => Value | Value export interface StoreApi<Value> { getState<T>(store: string | symbol): Object get<T>(key: string | symbol): Value update<StateSlice>(key: string | symbol, value: Updater<Value>): Value useStore<T>(key: string | symbol): Value getTypePolicies(): TypePolicies reset(): void } export default function create<Value>(initialState: State<Value>, options = { debug: false }): StoreApi<Value> { const createStore = () => { return Object.keys(initialState).reduce<Store<Value>>((sum, key) => { return { ...sum, [key]: makeVar<Value>(initialState[key]), } }, {}) } let store = createStore() // DEBUGGING if (options.debug) { // console.debug(`store`, store) // console.debug(`initialState`, initialState) // console.debug(`initialState._type`, initialState._type) if (initialState._type === 'scene') { // returns Object {fields} const fields: Object | any = {} // starts blank const keys: string[] = Object.keys(store) // console.debug('keys', keys) keys.forEach((key: string, index: number) => { fields[key] = store[key]() // console.debug(`${index}: ${key}: ${store[key]()} = ${fields[key]}`) }) // returns Array of Objects {fields}[] // const fields = Object.keys(store).map((key: string) => { // return { [key]: store[key]() } // }) // not working here, for reference only // returns Array of Objects {fields}[] // const fields = Object.keys(store).reduce((sum, key) => { // return { // ...sum, // [key]: { // read() { // return store[key]() // }, // }, // } // }) // console.debug(`${initialState._type}Store current state {fields}`, fields) // console.debug('%c====================================', ccm5) } } const debug = (key: string, value: Updater<Value>): void => { if (options.debug) { console.debug(`store update(key) "${key}" with value: ${JSON.stringify(value)}`) } } return { getState(): Object { // returns Object {fields} const fields: Object | any = {} // starts blank const keys: string[] = Object.keys(store) // console.debug('keys', keys) keys.forEach((key: string, index: number) => { fields[key] = store[key]() // console.debug(`${index}: ${key}: ${store[key]()} = ${fields[key]}`) }) if (!fields) { throw new Error(`store getState(): "${JSON.stringify(store)}" is invalid`, store) } console.debug(`store getState(): {fields}`, fields) return fields }, get(key: string) { const reactiveVar = store[key] if (!reactiveVar) { throw new Error(`store get(key) "${key}" is invalid`) } return reactiveVar() }, update(key: string, value) { const reactiveVar = store[key] if (!reactiveVar) { throw new Error(`store update(key) "${key}" is invalid`) } debug(key, value) if (value instanceof Function) { return reactiveVar(value(reactiveVar())) } else { return reactiveVar(value) } }, useStore(key: string) { const reactiveVar = store[key] if (!reactiveVar) { throw new Error(`useStore: key "${key}" is invalid`) } return useReactiveVar(reactiveVar) }, getTypePolicies() { return { Query: { fields: Object.keys(store).reduce((sum, key) => { return { ...sum, [key]: { read() { return store[key]() }, }, } }, {}), }, } }, reset: () => { store = createStore() }, } }