UNPKG

threed-garden

Version:

ThreeD Garden: WebGL 3D Environment Interface for Next.JS React TypeScript Three.JS React-Three Physics, 2D Paper.JS; APIs: Apollo GraphQL, WordPress; CSS: Tailwind, Radix-UI; Libraries: FarmBot 3D; AI: OpenAI, DeepSeek

172 lines (147 loc) 5.06 kB
// 🫙 Store is a Jar, with States inside // ** "apollo-reactive-store": "0.0.4" import { makeVar, ReactiveVar, useReactiveVar } from '@apollo/client' // ** HELPER Components import ccm from '#/lib/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: true } ): StoreApi<Value> { // ** CREATE STORE SINGLETON const createStore = () => { return Object.keys(initialState).reduce<Store<Value>>((sum, key) => { return { ...sum, [key]: makeVar<Value>(initialState[key]), } }, {}) } // ** CREATE AN INSTANCE OF STORE 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(`%c🫙===================================================`, ccm.blueAlert) // console.debug(`store update(key) "${key}" with value: ${JSON.stringify(value)}`) console.debug(`%c🫙 store update(key) "${key}"`, ccm.blueAlert, value) // console.debug(`%c🫙===================================================`, ccm.blueAlert) } } 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(`%c🫙===================================================`, ccm.blueAlert) console.debug(`%c🫙 store getState(): {fields}`, ccm.blueAlert, fields) // console.debug(`%c🫙===================================================`, ccm.blueAlert) 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() }, } }