@cervello/react 5.1.0-beta.9 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cervello.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cervello.cjs","sources":["../src/types/shared.ts","../src/lib/utils/object.ts","../src/lib/helpers/new-proxify-store.ts","../src/lib/store/new-index.ts","../src/lib/utils/subject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nexport type WithoutType<T, V, WithNever = {\n [K in keyof T]: Exclude<T[K], undefined> extends V\n ? never\n : (T[K] extends Record<string, unknown>\n ? WithoutType<T[K], V>\n : T[K])\n}> = Pick<WithNever, {\n [K in keyof WithNever]: WithNever[K] extends never ? never : K\n}[keyof WithNever]>\n\n\n\nexport type ObjectFromAttributes<T, Attributes extends Array< keyof WithoutType<T, Function> > > = {\n [k in Attributes[number]]: T[k]\n}\n\nexport type Maybe<T> = T | undefined\n\n\n\nexport type UseSelector<T> = <Attributes extends Array< Exclude<keyof WithoutType<T, Function>, '$value'> >>(\n selectors: Attributes,\n isEqualFunction?: (previousState: ObjectFromAttributes<T, Attributes>, currentState: ObjectFromAttributes<T, Attributes>) => boolean,\n) => T\n\nexport type FieldPath<T extends Record<string, any>> = {\n [K in keyof Required<T>]: T[K] extends Record<string, any>\n ? K extends string\n\n ? T[K] extends Function\n ? never\n : T[K] extends Array<any>\n ? K\n : `${K}.*` | `${K}.${FieldPath<T[K]>}`\n : never\n : K extends string\n ? K\n : never\n}[keyof T]\n\nexport const nonReactiveObjectSymbol = Symbol('nonReactiveObject')\nexport type StoreChange<T extends Record<string, any>> = {\n change: {\n fieldPath: FieldPath<T>\n newValue: any\n previousValue: any\n }\n storeValue: T\n}\n","/* eslint-disable no-cond-assign */\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { INTERNAL_VALUE_PROP } from '../helpers/constants'\n\n\n/**\n * Clones all the provided object and nested properties and it also\n * iterates nested arrays to deepClone them\n *\n * @param obj - base object to be cloned\n * @returns new cloned object with new reference\n */\nexport function deepClone <T> (obj: T): T {\n if (!obj || typeof obj !== 'object')\n return obj\n\n let newObj = {} as any\n\n if (Array.isArray(obj)) {\n newObj = obj.map(item => deepClone(item))\n // eslint-disable-next-line no-prototype-builtins\n } else if (!obj.hasOwnProperty('$$typeof')) {\n Object.entries(obj).forEach(([key, value]) => {\n newObj[key] = deepClone(value)\n })\n Object.getOwnPropertySymbols(obj).forEach((symbol) => {\n newObj[symbol] = (obj as any)[symbol]\n })\n } else {\n newObj = obj\n }\n\n return newObj as T\n}\n\n// function copyBuffer (cur: ArrayBufferView) {\n// if (cur instanceof Buffer)\n// return Buffer.from(cur)\n//\n//\n// return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n// }\n\n\n// INFO: From `rfdc` (really-fast-deep-clone) package for faster cloning taking care of circular references\nexport function deepClone2 <T> (obj: T): T {\n const refs: Array<any> = []\n const refsNew: Array<any> = []\n\n const constructorHandlers = new Map()\n\n constructorHandlers.set(Date, (o: string | number | Date) => new Date(o))\n constructorHandlers.set(Map, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Set(cloneArray(Array.from(o), fn)))\n\n let handler = null\n\n return clone(obj)\n\n function cloneArray (a: any, fn: any): any {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as any\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n // } else if (ArrayBuffer.isView(cur)) {\n // a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n\n if (index !== -1)\n a2[k] = refsNew[index]\n else\n a2[k] = fn(cur)\n }\n }\n\n return a2\n }\n\n function clone (o: any): any {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor)))\n return handler(o, clone)\n\n const o2 = {} as any\n\n refs.push(o)\n refsNew.push(o2)\n\n\n Object.getOwnPropertySymbols(o).forEach((symbol) => {\n o2[symbol] = (o)[symbol]\n })\n\n for (const k in o) {\n if (!Object.hasOwnProperty.call(o, k)) continue\n const cur = o[k]\n\n\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n // } else if (ArrayBuffer.isView(cur)) {\n // o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n\n if (i !== -1)\n o2[k] = refsNew[i]\n else\n o2[k] = clone(cur)\n }\n }\n refs.pop()\n refsNew.pop()\n\n\n return o2\n }\n}\n\n/**\n * Guard to check is variable is an object\n * @param obj - variable to be checked\n * @returns boolean\n */\nexport const isObject = (obj: unknown): obj is Record<string | symbol, unknown> => (\n obj !== null\n && typeof obj === 'object'\n && !Array.isArray(obj)\n)\n\n\nexport const isReactElement = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n\n return !!(obj.$$typeof)\n}\n\n\n\nexport function isValidReactiveObject <T extends Record<string, any>> (value: T): boolean {\n return isObject(value) && !isReactElement(value) && !(value as any)[nonReactiveObjectSymbol]\n}\n\n\n\n/**\n * Returns the actual target value instead of root\n * object with internals props like $$value$$\n *\n * @param target - object from subscription or proxy\n * @returns actual value\n */\nexport const okTarget = (target: any): any => target[INTERNAL_VALUE_PROP] ?? target\n\n\n\n\n/**\n * Gets an object with just the properties requested\n * instead of the full object\n *\n * @param properties - object properties\n * @param obj - target to get the properties\n * @returns New object with just the requested properties\n */\nexport function getPartialObjectFromProperties<T> (properties: Array<keyof T>, obj: T): any {\n return properties.reduce<any>((acc, curr) => {\n acc[curr] = obj[curr]\n\n return acc\n }, {})\n}\n\n\n\nconst stringify = (obj: any): string => JSON.stringify(obj)\n\n/**\n * Compare 2 provided objects by stringing them\n * @param a - first object\n * @param b - second object\n * @returns boolean\n */\nexport const contentComparer = (a: any, b: any): boolean => stringify(a) === stringify(b)\n","\nimport { isReactElement, isValidReactiveObject } from '../utils/object'\n\nimport type { StoreChange } from '../../types/shared'\nimport type { CacheableSubject } from '../utils/subject'\n\n\n\n// @ts-expect-error - Object.hasOwn is not defined in older Safari's browsers\n('hasOwn' in Object) || (Object.hasOwn = Object.call.bind(Object.hasOwnProperty))\n\nconst ROOT_VALUE = Symbol('value')\n\n\nexport function proxifyStore <T extends Record<string | symbol, any>> (\n store$$: CacheableSubject<StoreChange<T>>,\n objectToProxify: T,\n opts: {\n nestedFieldPath?: string\n parentObjectToProxify?: any\n // beforeChange?: (storeChange: StoreChange<T>) => any\n afterChange?: (storeChange: Array<StoreChange<T>>) => void\n } = {},\n): T {\n const fieldPath = opts.nestedFieldPath ?? 'root'\n\n const objectWithRootValue = {\n [ROOT_VALUE]: objectToProxify,\n } as unknown as T\n\n const rootFunctions = fieldPath === 'root'\n ? Object.fromEntries(Object.entries(objectToProxify).filter(([,v]) => typeof v === 'function'))\n : {}\n\n return new Proxy(objectWithRootValue, {\n get (targetObject, propName, receiver) {\n // INFO: !Internal only.\n // Used to get the fieldPath of the object (it means it's a proxified object)\n if (propName === '_$fieldPath') return fieldPath\n\n const isRootTarget = Object.hasOwn(targetObject, ROOT_VALUE)\n const target = isRootTarget ? targetObject[ROOT_VALUE] : targetObject\n\n\n // Called when the object is converted to JSON or string (i.e. JSON.stringify)\n if (propName === 'toJSON') {\n return () => {\n // Remove react-elements with circular which have circular references\n // before stringifying to prevent JSON.stringify(storeProxy) from failing\n return safeToJson(target)\n // return removeCircularReferences(target)\n }\n }\n\n // Get the whole store value without the proxy\n if (propName === '$value') {\n // return getUnproxiedObject(target)\n return target\n }\n\n\n const propertyValue = Reflect.get(target, propName, receiver)\n\n if (typeof propName === 'symbol') return propertyValue\n\n if (typeof propertyValue === 'function')\n return (propertyValue as () => any).bind(receiver)\n\n\n // Check if it's correct to be a reactive object\n // & is not a circular reference or the same object\n if (isValidReactiveObject(propertyValue) && propertyValue !== target) {\n // const newNestedFieldPath = `${fieldPath}.${propName}`\n\n // If it's already a proxified object, return it\n // if (propertyValue._$fieldPath === newNestedFieldPath) return propertyValue\n if (propertyValue._$fieldPath) return propertyValue\n\n // Create a new proxified object\n const proxiedNestedObject = proxifyStore(\n store$$ as any,\n propertyValue,\n {\n nestedFieldPath: `${fieldPath}.${propName}`,\n parentObjectToProxify: opts.parentObjectToProxify ?? target,\n // beforeChange: opts.beforeChange,\n afterChange: opts.afterChange,\n },\n )\n\n return target[propName] = proxiedNestedObject\n }\n\n return propertyValue\n },\n\n\n set (parentObject, key, newValue, receiver) {\n if (typeof key === 'symbol') return true\n\n const value = newValue\n const isRootTarget = Object.hasOwn(parentObject, ROOT_VALUE)\n\n // INFO: !Internal only.\n // Used to set the value of the store without notifying the store\n if (isRootTarget && key === '$$value') {\n (parentObject as any)[ROOT_VALUE] = value\n\n return true\n }\n\n if (isRootTarget && key === '$value') {\n const previousValue = parentObject[ROOT_VALUE]\n\n if (value === previousValue) return true\n\n if (safeStringify(value) === safeStringify(previousValue)) return true\n // if (JSON.stringify(value) === JSON.stringify(previousValue)) return true\n\n if (fieldPath !== 'root') {\n (parentObject as any)[ROOT_VALUE] = value\n } else {\n (parentObject as any)[ROOT_VALUE] = {\n ...rootFunctions,\n ...value,\n }\n store$$.next({\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(targetObject[ROOT_VALUE])),\n storeValue: parentObject[ROOT_VALUE],\n change: {\n fieldPath: 'root' as any,\n newValue: value,\n previousValue,\n },\n })\n }\n\n return true\n }\n\n const realInnerObject = isRootTarget ? parentObject[ROOT_VALUE] : parentObject\n const previousValue = Reflect.get(realInnerObject, key, receiver)\n\n\n if (previousValue === value) return true\n\n\n // New object values, check if the field has already a proxy created to use it instead of reacreating a new instance\n if (isValidReactiveObject(value) && previousValue?._$fieldPath)\n previousValue.$value = value\n else\n Reflect.set(realInnerObject, key, value, realInnerObject)\n\n\n const nextStoreChange = {\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(opts?.parentObjectToProxify ?? target)),\n storeValue: opts?.parentObjectToProxify ?? realInnerObject,\n change: {\n fieldPath: `${fieldPath}.${key}`.replace('root.', '') as any,\n newValue: value,\n previousValue,\n },\n }\n\n store$$.next(nextStoreChange)\n opts.afterChange?.([nextStoreChange])\n\n return true\n },\n\n has (t, p) {\n return Reflect.has(t[ROOT_VALUE], p)\n },\n\n ownKeys (t) {\n return Reflect.ownKeys(t[ROOT_VALUE])\n },\n\n getOwnPropertyDescriptor (t, p) {\n return Reflect.getOwnPropertyDescriptor(t[ROOT_VALUE], p)\n },\n\n })\n}\n\n//\n// function getUnproxiedObject (obj: any): any {\n// if (obj && typeof obj === 'object') {\n// if (obj[ROOT_VALUE]?.[ROOT_VALUE]) return '[Circular reference]'\n//\n// // Check if the object is a proxy\n// if (obj[ROOT_VALUE])\n// return getUnproxiedObject(obj[ROOT_VALUE])\n//\n//\n// // If it's not a proxy, return the object itself\n// return obj\n// }\n//\n// // If it's not an object, return it as is\n// return obj\n// }\n\n\nfunction safeStringify (obj: any): string {\n // use removeCircularReferences to avoid circular references\n // const cleanedObj = removeCircularReferences(obj)\n\n return JSON.stringify(\n obj,\n (_key, value) => {\n if (Array.isArray(value)) return value.map(i => safeStringify(i))\n\n if (isReactElement(value)) {\n // console.log('React element detected', value)\n\n return { props: safeStringify(value.props), type: typeof value.type === 'string' ? value.type : '' }\n }\n\n if (globalThis?.HTMLElement && value instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: value.innerHTML }\n\n // console.log('Value', value)\n\n return value\n })\n}\n\n\nfunction safeToJson (obj: any): Record<string, any> {\n const o: Record<string, any> = {}\n\n if (typeof obj !== 'object' || obj == null)\n return obj\n\n if (Array.isArray(obj))\n return obj.map(item => safeToJson(item))\n\n if (isReactElement(obj))\n return { props: safeToJson(obj.props), type: typeof obj.type === 'string' ? obj.type : '' }\n\n if (globalThis?.HTMLElement && obj instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: obj.innerHTML }\n\n Object.entries(obj).forEach(([key, v]) => {\n o[key] = safeToJson(v)\n })\n\n return o\n}\n\n\n// function removeCircularReferences (obj: any): any {\n// const seen = new WeakSet()\n//\n// function traverse (value: any): any {\n// if (value && typeof value === 'object') {\n// // If the object has already been seen, it's a circular reference\n// if (seen.has(value))\n// return null\n//\n// seen.add(value)\n//\n// if (Array.isArray(value))\n// return value.map(traverse)\n//\n//\n// const result: any = {}\n//\n// for (const key in value) {\n// if (Object.prototype.hasOwnProperty.call(value, key)) {\n// if (key === '_owner' && value.$$typeof) continue\n//\n// result[key] = traverse(value[key])\n// }\n// }\n//\n// return result\n// }\n//\n// // Return primitive values as-is\n// return value\n// }\n//\n// return traverse(obj)\n// }\n","\nimport { useLayoutEffect, useRef, useSyncExternalStore } from 'react'\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { proxifyStore } from '../helpers/new-proxify-store'\nimport { deepClone } from '../utils/object'\nimport { createCacheableSubject } from '../utils/subject'\n\nimport type { FieldPath, StoreChange } from '../../types/shared'\n\n\n\n\n// export type CervelloOptions<StoreValue extends Record<string, any>> = {\n// beforeChange?: (storeChange: StoreChange<StoreValue>) => unknown | undefined\n// afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n// }\n\nexport type CervelloOptions<StoreValue extends Record<string, any>> = {\n afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\nexport type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {\n initialValue?: (currentStore: StoreValue) => StoreValue | undefined | null,\n setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>,\n select?:\n | Array<FieldPath<StoreValue>>\n | (() => Array<FieldPath<StoreValue>>)\n onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\ntype MutableStoreValue<T extends Record<string, any>> = {\n $value: T\n} & T\n\n\n\n\n\n\n\n\nexport function nonReactive <T extends Record<string, any>> (initialValue: T): T {\n Object.defineProperty(initialValue, nonReactiveObjectSymbol, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return initialValue\n}\n\n\nexport function cervello <StoreValue extends Record<PropertyKey, any>> (\n initialValue: StoreValue,\n options?: CervelloOptions<StoreValue>,\n): {\n store: MutableStoreValue<StoreValue>,\n reset: () => void,\n useStore: (options?: CervelloUseStoreOptions<StoreValue>) => MutableStoreValue<StoreValue>\n } {\n const {\n // beforeChange,\n afterChange,\n } = options ?? {}\n\n const clonedInitialValue = (initialValue)\n const store$$ = createCacheableSubject<StoreChange<StoreValue>>(clonedInitialValue as any)\n\n const proxiedStore = proxifyStore(\n store$$ as any,\n clonedInitialValue,\n // { beforeChange, afterChange },\n { afterChange },\n ) as MutableStoreValue<StoreValue>\n\n\n return {\n store: proxiedStore,\n reset: () => {\n proxiedStore.$value = deepClone(initialValue)\n },\n useStore: (options) => {\n // const i = useId()\n const initialValue = options?.initialValue?.(proxiedStore.$value)\n const isInitialValueSet = useRef(false)\n\n if (!isInitialValueSet.current && initialValue && initialValue !== proxiedStore) {\n isInitialValueSet.current = true;\n (proxiedStore as any).$value = initialValue\n }\n\n const selectFieldPaths = useRef(\n (typeof options?.select === 'function'\n ? options?.select?.()\n : options?.select)\n ?? [],\n )\n\n const selectedFieldPathsForNestedObjects = useRef(\n selectFieldPaths.current\n .filter(fp => fp.includes('.*'))\n .map(fp => fp.replace('.*', '')),\n )\n\n\n useLayoutEffect(() => {\n if (options?.setValueOnMount) {\n void options.setValueOnMount(proxiedStore.$value).then((value) => {\n proxiedStore.$value = value\n }).catch((err) => {\n console.error('Error setting initial value on mount', err)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n\n useSyncExternalStore(\n (onStoreChange) => {\n const subscription = store$$.subscribe({\n next: (sc) => {\n // console.log('Store change', sc, i)\n const storeChanges = Array.isArray(sc)\n ? sc as Array<StoreChange<StoreValue>>\n : [sc]\n\n if (!options?.select) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n\n return\n }\n\n if (storeChanges.some(nextChange => (\n nextChange.change.fieldPath === 'root'\n || selectFieldPaths.current.includes(nextChange.change.fieldPath))\n || selectedFieldPathsForNestedObjects.current.find(fp => nextChange.change.fieldPath.startsWith(fp)),\n )) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n }\n },\n })\n\n return () => {\n subscription.unsubscribe()\n }\n },\n () => store$$.getValue(),\n () => store$$.getValue(),\n )\n\n return proxiedStore\n },\n }\n}\n","\nexport type Noop = () => void\n\n\nexport type Observer<T> = {\n next: (value: T) => void\n}\n\nexport type Subscription = {\n unsubscribe: Noop\n}\n\nexport type CacheableSubject<T> = {\n getValue: () => T\n subscribe: (value: Observer<T>) => Subscription\n unSubscribeAll: Noop\n} & Observer<T>\n\n\n// const WITH_FLUSHING = true\n\nexport function createCacheableSubject<T> (defaultValue: T, getValueOnSubscribe = false): CacheableSubject<T> {\n let isFlushing = false\n let itemsToFlush: Array<T> = []\n\n let observerList: Array<Observer<T>> = []\n let value = defaultValue\n\n const getValue = (): T => value\n\n const next = (newValue: T): void => {\n value = newValue\n\n // if (!WITH_FLUSHING) {\n // observerList.forEach((o) => { o.next(newValue) })\n //\n // return\n // }\n\n itemsToFlush.push(newValue)\n // observerList.forEach((o) => { o.next(newValue) })\n\n if (!isFlushing) {\n isFlushing = true\n void Promise.resolve().then(() => {\n observerList.forEach((o) => { o.next(itemsToFlush as T) })\n itemsToFlush = []\n isFlushing = false\n })\n }\n }\n\n const subscribe = (observer: Observer<T>): Subscription => {\n // Push cached value on subscribe\n if (getValueOnSubscribe) observer.next(value)\n // Store the observer to be notified\n observerList.push(observer)\n\n return {\n unsubscribe: () => {\n observerList = observerList.filter(o => o !== observer)\n },\n }\n }\n\n const unSubscribeAll = (): void => {\n observerList = []\n }\n\n return {\n getValue,\n next,\n subscribe,\n unSubscribeAll,\n }\n}\n"],"names":["nonReactiveObjectSymbol","Symbol","deepClone","obj","Array","isArray","newObj","map","item","hasOwnProperty","Object","entries","forEach","_ref","getOwnPropertySymbols","symbol","isObject","isReactElement","$$typeof","isValidReactiveObject","value","hasOwn","call","bind","proxifyStore","store$$","objectToProxify","opts","fieldPath","nestedFieldPath","_opts$nestedFieldPath","objectWithRootValue","_objectWithRootValue","ROOT_VALUE","rootFunctions","fromEntries","filter","v","Proxy","get","targetObject","propName","receiver","target","safeToJson","propertyValue","Reflect","_opts$parentObjectToP","_$fieldPath","parentObjectToProxify","afterChange","proxiedNestedObject","set","parentObject","key","newValue","_opts$parentObjectToP2","_opts","isRootTarget","previousValue","safeStringify","next","storeValue","change","realInnerObject","$value","nextStoreChange","replace","has","t","p","ownKeys","getOwnPropertyDescriptor","JSON","stringify","_key","i","props","type","globalThis","HTMLElement","content","innerHTML","o","initialValue","options","clonedInitialValue","defaultValue","getValueOnSubscribe","isFlushing","itemsToFlush","getValue","push","Promise","resolve","then","observerList","subscribe","observer","unsubscribe","unSubscribeAll","createCacheableSubject","proxiedStore","store","reset","useStore","_ref2","isInitialValueSet","useRef","current","selectFieldPaths","select","selectedFieldPathsForNestedObjects","fp","includes","useLayoutEffect","setValueOnMount","err","console","error","useSyncExternalStore","onStoreChange","subscription","sc","storeChanges","onChange","some","nextChange","find","startsWith","nonReactive","defineProperty","enumerable","writable","configurable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cervello.cjs","sources":["../src/types/shared.ts","../src/lib/utils/object.ts","../src/lib/helpers/new-proxify-store.ts","../src/lib/store/new-index.ts","../src/lib/utils/subject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nexport type WithoutType<T, V, WithNever = {\n [K in keyof T]: Exclude<T[K], undefined> extends V\n ? never\n : (T[K] extends Record<string, unknown>\n ? WithoutType<T[K], V>\n : T[K])\n}> = Pick<WithNever, {\n [K in keyof WithNever]: WithNever[K] extends never ? never : K\n}[keyof WithNever]>\n\n\n\nexport type ObjectFromAttributes<T, Attributes extends Array< keyof WithoutType<T, Function> > > = {\n [k in Attributes[number]]: T[k]\n}\n\nexport type Maybe<T> = T | undefined\n\n\n\nexport type UseSelector<T> = <Attributes extends Array< Exclude<keyof WithoutType<T, Function>, '$value'> >>(\n selectors: Attributes,\n isEqualFunction?: (previousState: ObjectFromAttributes<T, Attributes>, currentState: ObjectFromAttributes<T, Attributes>) => boolean,\n) => T\n\nexport type FieldPath<T extends Record<string, any>> = {\n [K in keyof Required<T>]: T[K] extends Record<string, any>\n ? K extends string\n\n ? T[K] extends Function\n ? never\n : T[K] extends Array<any>\n ? K\n : `${K}.*` | `${K}.${FieldPath<T[K]>}`\n : never\n : K extends string\n ? K\n : never\n}[keyof T]\n\nexport const nonReactiveObjectSymbol = Symbol('nonReactiveObject')\nexport type StoreChange<T extends Record<string, any>> = {\n change: {\n fieldPath: FieldPath<T>\n newValue: any\n previousValue: any\n }\n storeValue: T\n}\n","/* eslint-disable no-cond-assign */\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { INTERNAL_VALUE_PROP } from '../helpers/constants'\n\n\n/**\n * Clones all the provided object and nested properties and it also\n * iterates nested arrays to deepClone them\n *\n * @param obj - base object to be cloned\n * @returns new cloned object with new reference\n */\nexport function deepClone <T> (obj: T): T {\n if (!obj || typeof obj !== 'object')\n return obj\n\n let newObj = {} as any\n\n if (Array.isArray(obj)) {\n newObj = obj.map(item => deepClone(item))\n // eslint-disable-next-line no-prototype-builtins\n } else if (!obj.hasOwnProperty('$$typeof')) {\n Object.entries(obj).forEach(([key, value]) => {\n newObj[key] = deepClone(value)\n })\n Object.getOwnPropertySymbols(obj).forEach((symbol) => {\n newObj[symbol] = (obj as any)[symbol]\n })\n } else {\n newObj = obj\n }\n\n return newObj as T\n}\n\n// function copyBuffer (cur: ArrayBufferView) {\n// if (cur instanceof Buffer)\n// return Buffer.from(cur)\n//\n//\n// return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n// }\n\n\n// INFO: From `rfdc` (really-fast-deep-clone) package for faster cloning taking care of circular references\nexport function deepClone2 <T> (obj: T): T {\n const refs: Array<any> = []\n const refsNew: Array<any> = []\n\n const constructorHandlers = new Map()\n\n constructorHandlers.set(Date, (o: string | number | Date) => new Date(o))\n constructorHandlers.set(Map, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Set(cloneArray(Array.from(o), fn)))\n\n let handler = null\n\n return clone(obj)\n\n function cloneArray (a: any, fn: any): any {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as any\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n // } else if (ArrayBuffer.isView(cur)) {\n // a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n\n if (index !== -1)\n a2[k] = refsNew[index]\n else\n a2[k] = fn(cur)\n }\n }\n\n return a2\n }\n\n function clone (o: any): any {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor)))\n return handler(o, clone)\n\n const o2 = {} as any\n\n refs.push(o)\n refsNew.push(o2)\n\n\n Object.getOwnPropertySymbols(o).forEach((symbol) => {\n o2[symbol] = (o)[symbol]\n })\n\n for (const k in o) {\n if (!Object.hasOwnProperty.call(o, k)) continue\n const cur = o[k]\n\n\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n // } else if (ArrayBuffer.isView(cur)) {\n // o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n\n if (i !== -1)\n o2[k] = refsNew[i]\n else\n o2[k] = clone(cur)\n }\n }\n refs.pop()\n refsNew.pop()\n\n\n return o2\n }\n}\n\n/**\n * Guard to check is variable is an object\n * @param obj - variable to be checked\n * @returns boolean\n */\nexport const isObject = (obj: unknown): obj is Record<string | symbol, unknown> => (\n obj !== null\n && typeof obj === 'object'\n && !Array.isArray(obj)\n)\n\n\nexport const isReactElement = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n\n return !!(obj.$$typeof)\n}\n\n\n\nexport function isValidReactiveObject <T extends Record<string, any>> (value: T): boolean {\n return isObject(value) && !isReactElement(value) && !(value as any)[nonReactiveObjectSymbol]\n}\n\n\n\n/**\n * Returns the actual target value instead of root\n * object with internals props like $$value$$\n *\n * @param target - object from subscription or proxy\n * @returns actual value\n */\nexport const okTarget = (target: any): any => target[INTERNAL_VALUE_PROP] ?? target\n\n\n\n\n/**\n * Gets an object with just the properties requested\n * instead of the full object\n *\n * @param properties - object properties\n * @param obj - target to get the properties\n * @returns New object with just the requested properties\n */\nexport function getPartialObjectFromProperties<T> (properties: Array<keyof T>, obj: T): any {\n return properties.reduce<any>((acc, curr) => {\n acc[curr] = obj[curr]\n\n return acc\n }, {})\n}\n\n\n\nconst stringify = (obj: any): string => JSON.stringify(obj)\n\n/**\n * Compare 2 provided objects by stringing them\n * @param a - first object\n * @param b - second object\n * @returns boolean\n */\nexport const contentComparer = (a: any, b: any): boolean => stringify(a) === stringify(b)\n","\nimport { isReactElement, isValidReactiveObject } from '../utils/object'\n\nimport type { StoreChange } from '../../types/shared'\nimport type { CacheableSubject } from '../utils/subject'\n\n\n\n// @ts-expect-error - Object.hasOwn is not defined in older Safari's browsers\n('hasOwn' in Object) || (Object.hasOwn = Object.call.bind(Object.hasOwnProperty))\n\nconst ROOT_VALUE = Symbol('value')\n\n\nexport function proxifyStore <T extends Record<string | symbol, any>> (\n store$$: CacheableSubject<StoreChange<T>>,\n objectToProxify: T,\n opts: {\n nestedFieldPath?: string\n parentObjectToProxify?: any\n // beforeChange?: (storeChange: StoreChange<T>) => any\n afterChange?: (storeChange: Array<StoreChange<T>>) => void\n } = {},\n): T {\n const fieldPath = opts.nestedFieldPath ?? 'root'\n\n const objectWithRootValue = {\n [ROOT_VALUE]: objectToProxify,\n } as unknown as T\n\n const rootFunctions = fieldPath === 'root'\n ? Object.fromEntries(Object.entries(objectToProxify).filter(([,v]) => typeof v === 'function'))\n : {}\n\n return new Proxy(objectWithRootValue, {\n get (targetObject, propName, receiver) {\n // INFO: !Internal only.\n // Used to get the fieldPath of the object (it means it's a proxified object)\n if (propName === '_$fieldPath') return fieldPath\n\n const isRootTarget = Object.hasOwn(targetObject, ROOT_VALUE)\n const target = isRootTarget ? targetObject[ROOT_VALUE] : targetObject\n\n\n // Called when the object is converted to JSON or string (i.e. JSON.stringify)\n if (propName === 'toJSON') {\n return () => {\n // Remove react-elements with circular which have circular references\n // before stringifying to prevent JSON.stringify(storeProxy) from failing\n return safeToJson(target)\n // return removeCircularReferences(target)\n }\n }\n\n // Get the whole store value without the proxy\n if (propName === '$value') {\n // return getUnproxiedObject(target)\n return target\n }\n\n\n const propertyValue = Reflect.get(target, propName, receiver)\n\n if (typeof propName === 'symbol') return propertyValue\n\n if (typeof propertyValue === 'function')\n return (propertyValue as () => any).bind(receiver)\n\n\n // Check if it's correct to be a reactive object\n // & is not a circular reference or the same object\n if (isValidReactiveObject(propertyValue) && propertyValue !== target) {\n // const newNestedFieldPath = `${fieldPath}.${propName}`\n\n // If it's already a proxified object, return it\n // if (propertyValue._$fieldPath === newNestedFieldPath) return propertyValue\n if (propertyValue._$fieldPath) return propertyValue\n\n // Create a new proxified object\n const proxiedNestedObject = proxifyStore(\n store$$ as any,\n propertyValue,\n {\n nestedFieldPath: `${fieldPath}.${propName}`,\n parentObjectToProxify: opts.parentObjectToProxify ?? target,\n // beforeChange: opts.beforeChange,\n afterChange: opts.afterChange,\n },\n )\n\n return target[propName] = proxiedNestedObject\n }\n\n return propertyValue\n },\n\n\n set (parentObject, key, newValue, receiver) {\n if (typeof key === 'symbol') return true\n\n const value = newValue\n const isRootTarget = Object.hasOwn(parentObject, ROOT_VALUE)\n\n // INFO: !Internal only.\n // Used to set the value of the store without notifying the store\n if (isRootTarget && key === '$$value') {\n (parentObject as any)[ROOT_VALUE] = value\n\n return true\n }\n\n if (isRootTarget && key === '$value') {\n const previousValue = parentObject[ROOT_VALUE]\n\n if (value === previousValue) return true\n\n if (safeStringify(value) === safeStringify(previousValue)) return true\n // if (JSON.stringify(value) === JSON.stringify(previousValue)) return true\n\n if (fieldPath !== 'root') {\n (parentObject as any)[ROOT_VALUE] = value\n } else {\n (parentObject as any)[ROOT_VALUE] = {\n ...rootFunctions,\n ...value,\n }\n store$$.next({\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(targetObject[ROOT_VALUE])),\n storeValue: parentObject[ROOT_VALUE],\n change: {\n fieldPath: 'root' as any,\n newValue: value,\n previousValue,\n },\n })\n }\n\n return true\n }\n\n const realInnerObject = isRootTarget ? parentObject[ROOT_VALUE] : parentObject\n const previousValue = Reflect.get(realInnerObject, key, receiver)\n\n\n if (previousValue === value) return true\n\n\n // New object values, check if the field has already a proxy created to use it instead of reacreating a new instance\n if (isValidReactiveObject(value) && previousValue?._$fieldPath)\n previousValue.$value = value\n else\n Reflect.set(realInnerObject, key, value, realInnerObject)\n\n\n const nextStoreChange = {\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(opts?.parentObjectToProxify ?? target)),\n storeValue: opts?.parentObjectToProxify ?? realInnerObject,\n change: {\n fieldPath: `${fieldPath}.${key}`.replace('root.', '') as any,\n newValue: value,\n previousValue,\n },\n }\n\n store$$.next(nextStoreChange)\n opts.afterChange?.([nextStoreChange])\n\n return true\n },\n\n has (t, p) {\n return Reflect.has(t[ROOT_VALUE], p)\n },\n\n ownKeys (t) {\n return Reflect.ownKeys(t[ROOT_VALUE])\n },\n\n getOwnPropertyDescriptor (t, p) {\n return Reflect.getOwnPropertyDescriptor(t[ROOT_VALUE], p)\n },\n\n })\n}\n\n//\n// function getUnproxiedObject (obj: any): any {\n// if (obj && typeof obj === 'object') {\n// if (obj[ROOT_VALUE]?.[ROOT_VALUE]) return '[Circular reference]'\n//\n// // Check if the object is a proxy\n// if (obj[ROOT_VALUE])\n// return getUnproxiedObject(obj[ROOT_VALUE])\n//\n//\n// // If it's not a proxy, return the object itself\n// return obj\n// }\n//\n// // If it's not an object, return it as is\n// return obj\n// }\n\n\nfunction safeStringify (obj: any): string {\n // use removeCircularReferences to avoid circular references\n // const cleanedObj = removeCircularReferences(obj)\n\n return JSON.stringify(\n obj,\n (_key, value) => {\n if (Array.isArray(value)) return value.map(i => safeStringify(i))\n\n if (isReactElement(value)) {\n // console.log('React element detected', value)\n\n return { props: safeStringify(value.props), type: typeof value.type === 'string' ? value.type : '' }\n }\n\n if (globalThis?.HTMLElement && value instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: value.innerHTML }\n\n // console.log('Value', value)\n\n return value\n })\n}\n\n\nfunction safeToJson (obj: any): Record<string, any> {\n const o: Record<string, any> = {}\n\n if (typeof obj !== 'object' || obj == null)\n return obj\n\n if (Array.isArray(obj))\n return obj.map(item => safeToJson(item))\n\n if (isReactElement(obj))\n return { props: safeToJson(obj.props), type: typeof obj.type === 'string' ? obj.type : '' }\n\n if (globalThis?.HTMLElement && obj instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: obj.innerHTML }\n\n Object.entries(obj).forEach(([key, v]) => {\n o[key] = safeToJson(v)\n })\n\n return o\n}\n\n\n// function removeCircularReferences (obj: any): any {\n// const seen = new WeakSet()\n//\n// function traverse (value: any): any {\n// if (value && typeof value === 'object') {\n// // If the object has already been seen, it's a circular reference\n// if (seen.has(value))\n// return null\n//\n// seen.add(value)\n//\n// if (Array.isArray(value))\n// return value.map(traverse)\n//\n//\n// const result: any = {}\n//\n// for (const key in value) {\n// if (Object.prototype.hasOwnProperty.call(value, key)) {\n// if (key === '_owner' && value.$$typeof) continue\n//\n// result[key] = traverse(value[key])\n// }\n// }\n//\n// return result\n// }\n//\n// // Return primitive values as-is\n// return value\n// }\n//\n// return traverse(obj)\n// }\n","\nimport { useLayoutEffect, useRef, useSyncExternalStore } from 'react'\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { proxifyStore } from '../helpers/new-proxify-store'\nimport { deepClone } from '../utils/object'\nimport { createCacheableSubject } from '../utils/subject'\n\nimport type { FieldPath, StoreChange } from '../../types/shared'\n\n\n\n\n// export type CervelloOptions<StoreValue extends Record<string, any>> = {\n// beforeChange?: (storeChange: StoreChange<StoreValue>) => unknown | undefined\n// afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n// }\n\nexport type CervelloOptions<StoreValue extends Record<string, any>> = {\n afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\nexport type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {\n initialValue?: (currentStore: StoreValue) => StoreValue | null,\n setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>,\n select?:\n | Array<FieldPath<StoreValue>>\n | (() => Array<FieldPath<StoreValue>>)\n onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\ntype MutableStoreValue<T extends Record<string, any>> = {\n $value: T\n} & T\n\n\n\n\n\n\n\n\nexport function nonReactive <T extends Record<string, any>> (initialValue: T): T {\n Object.defineProperty(initialValue, nonReactiveObjectSymbol, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return initialValue\n}\n\n\nexport function cervello <StoreValue extends Record<PropertyKey, any>> (\n initialValue: StoreValue,\n options?: CervelloOptions<StoreValue>,\n): {\n store: MutableStoreValue<StoreValue>,\n reset: () => void,\n useStore: (options?: CervelloUseStoreOptions<StoreValue>) => MutableStoreValue<StoreValue>\n } {\n const {\n // beforeChange,\n afterChange,\n } = options ?? {}\n\n const clonedInitialValue = (initialValue)\n const store$$ = createCacheableSubject<StoreChange<StoreValue>>(clonedInitialValue as any)\n\n const proxiedStore = proxifyStore(\n store$$ as any,\n clonedInitialValue,\n // { beforeChange, afterChange },\n { afterChange },\n ) as MutableStoreValue<StoreValue>\n\n\n return {\n store: proxiedStore,\n reset: () => {\n proxiedStore.$value = deepClone(initialValue)\n },\n useStore: (options) => {\n // const i = useId()\n const initialValue = options?.initialValue?.(proxiedStore.$value)\n const isInitialValueSet = useRef(false)\n\n if (!isInitialValueSet.current && initialValue && initialValue !== proxiedStore) {\n isInitialValueSet.current = true;\n (proxiedStore as any).$value = initialValue\n }\n\n const selectFieldPaths = useRef(\n (typeof options?.select === 'function'\n ? options?.select?.()\n : options?.select)\n ?? [],\n )\n\n const selectedFieldPathsForNestedObjects = useRef(\n selectFieldPaths.current\n .filter(fp => fp.includes('.*'))\n .map(fp => fp.replace('.*', '')),\n )\n\n\n useLayoutEffect(() => {\n if (options?.setValueOnMount) {\n void options.setValueOnMount(proxiedStore.$value).then((value) => {\n proxiedStore.$value = value\n }).catch((err) => {\n console.error('Error setting initial value on mount', err)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n\n useSyncExternalStore(\n (onStoreChange) => {\n const subscription = store$$.subscribe({\n next: (sc) => {\n // console.log('Store change', sc, i)\n const storeChanges = Array.isArray(sc)\n ? sc as Array<StoreChange<StoreValue>>\n : [sc]\n\n if (!options?.select) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n\n return\n }\n\n if (storeChanges.some(nextChange => (\n nextChange.change.fieldPath === 'root'\n || selectFieldPaths.current.includes(nextChange.change.fieldPath))\n || selectedFieldPathsForNestedObjects.current.find(fp => nextChange.change.fieldPath.startsWith(fp)),\n )) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n }\n },\n })\n\n return () => {\n subscription.unsubscribe()\n }\n },\n () => store$$.getValue(),\n () => store$$.getValue(),\n )\n\n return proxiedStore\n },\n }\n}\n","\nexport type Noop = () => void\n\n\nexport type Observer<T> = {\n next: (value: T) => void\n}\n\nexport type Subscription = {\n unsubscribe: Noop\n}\n\nexport type CacheableSubject<T> = {\n getValue: () => T\n subscribe: (value: Observer<T>) => Subscription\n unSubscribeAll: Noop\n} & Observer<T>\n\n\n// const WITH_FLUSHING = true\n\nexport function createCacheableSubject<T> (defaultValue: T, getValueOnSubscribe = false): CacheableSubject<T> {\n let isFlushing = false\n let itemsToFlush: Array<T> = []\n\n let observerList: Array<Observer<T>> = []\n let value = defaultValue\n\n const getValue = (): T => value\n\n const next = (newValue: T): void => {\n value = newValue\n\n // if (!WITH_FLUSHING) {\n // observerList.forEach((o) => { o.next(newValue) })\n //\n // return\n // }\n\n itemsToFlush.push(newValue)\n // observerList.forEach((o) => { o.next(newValue) })\n\n if (!isFlushing) {\n isFlushing = true\n void Promise.resolve().then(() => {\n observerList.forEach((o) => { o.next(itemsToFlush as T) })\n itemsToFlush = []\n isFlushing = false\n })\n }\n }\n\n const subscribe = (observer: Observer<T>): Subscription => {\n // Push cached value on subscribe\n if (getValueOnSubscribe) observer.next(value)\n // Store the observer to be notified\n observerList.push(observer)\n\n return {\n unsubscribe: () => {\n observerList = observerList.filter(o => o !== observer)\n },\n }\n }\n\n const unSubscribeAll = (): void => {\n observerList = []\n }\n\n return {\n getValue,\n next,\n subscribe,\n unSubscribeAll,\n }\n}\n"],"names":["nonReactiveObjectSymbol","Symbol","deepClone","obj","Array","isArray","newObj","map","item","hasOwnProperty","Object","entries","forEach","_ref","getOwnPropertySymbols","symbol","isObject","isReactElement","$$typeof","isValidReactiveObject","value","hasOwn","call","bind","proxifyStore","store$$","objectToProxify","opts","fieldPath","nestedFieldPath","_opts$nestedFieldPath","objectWithRootValue","_objectWithRootValue","ROOT_VALUE","rootFunctions","fromEntries","filter","v","Proxy","get","targetObject","propName","receiver","target","safeToJson","propertyValue","Reflect","_opts$parentObjectToP","_$fieldPath","parentObjectToProxify","afterChange","proxiedNestedObject","set","parentObject","key","newValue","_opts$parentObjectToP2","_opts","isRootTarget","previousValue","safeStringify","next","storeValue","change","realInnerObject","$value","nextStoreChange","replace","has","t","p","ownKeys","getOwnPropertyDescriptor","JSON","stringify","_key","i","props","type","globalThis","HTMLElement","content","innerHTML","o","initialValue","options","clonedInitialValue","defaultValue","getValueOnSubscribe","isFlushing","itemsToFlush","getValue","push","Promise","resolve","then","observerList","subscribe","observer","unsubscribe","unSubscribeAll","createCacheableSubject","proxiedStore","store","reset","useStore","_ref2","isInitialValueSet","useRef","current","selectFieldPaths","select","selectedFieldPathsForNestedObjects","fp","includes","useLayoutEffect","setValueOnMount","err","console","error","useSyncExternalStore","onStoreChange","subscription","sc","storeChanges","onChange","some","nextChange","find","startsWith","nonReactive","defineProperty","enumerable","writable","configurable"],"mappings":"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"}
|
package/dist/cervello.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cervello.esm.js","sources":["../src/types/shared.ts","../src/lib/utils/object.ts","../src/lib/helpers/new-proxify-store.ts","../src/lib/store/new-index.ts","../src/lib/utils/subject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nexport type WithoutType<T, V, WithNever = {\n [K in keyof T]: Exclude<T[K], undefined> extends V\n ? never\n : (T[K] extends Record<string, unknown>\n ? WithoutType<T[K], V>\n : T[K])\n}> = Pick<WithNever, {\n [K in keyof WithNever]: WithNever[K] extends never ? never : K\n}[keyof WithNever]>\n\n\n\nexport type ObjectFromAttributes<T, Attributes extends Array< keyof WithoutType<T, Function> > > = {\n [k in Attributes[number]]: T[k]\n}\n\nexport type Maybe<T> = T | undefined\n\n\n\nexport type UseSelector<T> = <Attributes extends Array< Exclude<keyof WithoutType<T, Function>, '$value'> >>(\n selectors: Attributes,\n isEqualFunction?: (previousState: ObjectFromAttributes<T, Attributes>, currentState: ObjectFromAttributes<T, Attributes>) => boolean,\n) => T\n\nexport type FieldPath<T extends Record<string, any>> = {\n [K in keyof Required<T>]: T[K] extends Record<string, any>\n ? K extends string\n\n ? T[K] extends Function\n ? never\n : T[K] extends Array<any>\n ? K\n : `${K}.*` | `${K}.${FieldPath<T[K]>}`\n : never\n : K extends string\n ? K\n : never\n}[keyof T]\n\nexport const nonReactiveObjectSymbol = Symbol('nonReactiveObject')\nexport type StoreChange<T extends Record<string, any>> = {\n change: {\n fieldPath: FieldPath<T>\n newValue: any\n previousValue: any\n }\n storeValue: T\n}\n","/* eslint-disable no-cond-assign */\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { INTERNAL_VALUE_PROP } from '../helpers/constants'\n\n\n/**\n * Clones all the provided object and nested properties and it also\n * iterates nested arrays to deepClone them\n *\n * @param obj - base object to be cloned\n * @returns new cloned object with new reference\n */\nexport function deepClone <T> (obj: T): T {\n if (!obj || typeof obj !== 'object')\n return obj\n\n let newObj = {} as any\n\n if (Array.isArray(obj)) {\n newObj = obj.map(item => deepClone(item))\n // eslint-disable-next-line no-prototype-builtins\n } else if (!obj.hasOwnProperty('$$typeof')) {\n Object.entries(obj).forEach(([key, value]) => {\n newObj[key] = deepClone(value)\n })\n Object.getOwnPropertySymbols(obj).forEach((symbol) => {\n newObj[symbol] = (obj as any)[symbol]\n })\n } else {\n newObj = obj\n }\n\n return newObj as T\n}\n\n// function copyBuffer (cur: ArrayBufferView) {\n// if (cur instanceof Buffer)\n// return Buffer.from(cur)\n//\n//\n// return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n// }\n\n\n// INFO: From `rfdc` (really-fast-deep-clone) package for faster cloning taking care of circular references\nexport function deepClone2 <T> (obj: T): T {\n const refs: Array<any> = []\n const refsNew: Array<any> = []\n\n const constructorHandlers = new Map()\n\n constructorHandlers.set(Date, (o: string | number | Date) => new Date(o))\n constructorHandlers.set(Map, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Set(cloneArray(Array.from(o), fn)))\n\n let handler = null\n\n return clone(obj)\n\n function cloneArray (a: any, fn: any): any {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as any\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n // } else if (ArrayBuffer.isView(cur)) {\n // a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n\n if (index !== -1)\n a2[k] = refsNew[index]\n else\n a2[k] = fn(cur)\n }\n }\n\n return a2\n }\n\n function clone (o: any): any {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor)))\n return handler(o, clone)\n\n const o2 = {} as any\n\n refs.push(o)\n refsNew.push(o2)\n\n\n Object.getOwnPropertySymbols(o).forEach((symbol) => {\n o2[symbol] = (o)[symbol]\n })\n\n for (const k in o) {\n if (!Object.hasOwnProperty.call(o, k)) continue\n const cur = o[k]\n\n\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n // } else if (ArrayBuffer.isView(cur)) {\n // o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n\n if (i !== -1)\n o2[k] = refsNew[i]\n else\n o2[k] = clone(cur)\n }\n }\n refs.pop()\n refsNew.pop()\n\n\n return o2\n }\n}\n\n/**\n * Guard to check is variable is an object\n * @param obj - variable to be checked\n * @returns boolean\n */\nexport const isObject = (obj: unknown): obj is Record<string | symbol, unknown> => (\n obj !== null\n && typeof obj === 'object'\n && !Array.isArray(obj)\n)\n\n\nexport const isReactElement = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n\n return !!(obj.$$typeof)\n}\n\n\n\nexport function isValidReactiveObject <T extends Record<string, any>> (value: T): boolean {\n return isObject(value) && !isReactElement(value) && !(value as any)[nonReactiveObjectSymbol]\n}\n\n\n\n/**\n * Returns the actual target value instead of root\n * object with internals props like $$value$$\n *\n * @param target - object from subscription or proxy\n * @returns actual value\n */\nexport const okTarget = (target: any): any => target[INTERNAL_VALUE_PROP] ?? target\n\n\n\n\n/**\n * Gets an object with just the properties requested\n * instead of the full object\n *\n * @param properties - object properties\n * @param obj - target to get the properties\n * @returns New object with just the requested properties\n */\nexport function getPartialObjectFromProperties<T> (properties: Array<keyof T>, obj: T): any {\n return properties.reduce<any>((acc, curr) => {\n acc[curr] = obj[curr]\n\n return acc\n }, {})\n}\n\n\n\nconst stringify = (obj: any): string => JSON.stringify(obj)\n\n/**\n * Compare 2 provided objects by stringing them\n * @param a - first object\n * @param b - second object\n * @returns boolean\n */\nexport const contentComparer = (a: any, b: any): boolean => stringify(a) === stringify(b)\n","\nimport { isReactElement, isValidReactiveObject } from '../utils/object'\n\nimport type { StoreChange } from '../../types/shared'\nimport type { CacheableSubject } from '../utils/subject'\n\n\n\n// @ts-expect-error - Object.hasOwn is not defined in older Safari's browsers\n('hasOwn' in Object) || (Object.hasOwn = Object.call.bind(Object.hasOwnProperty))\n\nconst ROOT_VALUE = Symbol('value')\n\n\nexport function proxifyStore <T extends Record<string | symbol, any>> (\n store$$: CacheableSubject<StoreChange<T>>,\n objectToProxify: T,\n opts: {\n nestedFieldPath?: string\n parentObjectToProxify?: any\n // beforeChange?: (storeChange: StoreChange<T>) => any\n afterChange?: (storeChange: Array<StoreChange<T>>) => void\n } = {},\n): T {\n const fieldPath = opts.nestedFieldPath ?? 'root'\n\n const objectWithRootValue = {\n [ROOT_VALUE]: objectToProxify,\n } as unknown as T\n\n const rootFunctions = fieldPath === 'root'\n ? Object.fromEntries(Object.entries(objectToProxify).filter(([,v]) => typeof v === 'function'))\n : {}\n\n return new Proxy(objectWithRootValue, {\n get (targetObject, propName, receiver) {\n // INFO: !Internal only.\n // Used to get the fieldPath of the object (it means it's a proxified object)\n if (propName === '_$fieldPath') return fieldPath\n\n const isRootTarget = Object.hasOwn(targetObject, ROOT_VALUE)\n const target = isRootTarget ? targetObject[ROOT_VALUE] : targetObject\n\n\n // Called when the object is converted to JSON or string (i.e. JSON.stringify)\n if (propName === 'toJSON') {\n return () => {\n // Remove react-elements with circular which have circular references\n // before stringifying to prevent JSON.stringify(storeProxy) from failing\n return safeToJson(target)\n // return removeCircularReferences(target)\n }\n }\n\n // Get the whole store value without the proxy\n if (propName === '$value') {\n // return getUnproxiedObject(target)\n return target\n }\n\n\n const propertyValue = Reflect.get(target, propName, receiver)\n\n if (typeof propName === 'symbol') return propertyValue\n\n if (typeof propertyValue === 'function')\n return (propertyValue as () => any).bind(receiver)\n\n\n // Check if it's correct to be a reactive object\n // & is not a circular reference or the same object\n if (isValidReactiveObject(propertyValue) && propertyValue !== target) {\n // const newNestedFieldPath = `${fieldPath}.${propName}`\n\n // If it's already a proxified object, return it\n // if (propertyValue._$fieldPath === newNestedFieldPath) return propertyValue\n if (propertyValue._$fieldPath) return propertyValue\n\n // Create a new proxified object\n const proxiedNestedObject = proxifyStore(\n store$$ as any,\n propertyValue,\n {\n nestedFieldPath: `${fieldPath}.${propName}`,\n parentObjectToProxify: opts.parentObjectToProxify ?? target,\n // beforeChange: opts.beforeChange,\n afterChange: opts.afterChange,\n },\n )\n\n return target[propName] = proxiedNestedObject\n }\n\n return propertyValue\n },\n\n\n set (parentObject, key, newValue, receiver) {\n if (typeof key === 'symbol') return true\n\n const value = newValue\n const isRootTarget = Object.hasOwn(parentObject, ROOT_VALUE)\n\n // INFO: !Internal only.\n // Used to set the value of the store without notifying the store\n if (isRootTarget && key === '$$value') {\n (parentObject as any)[ROOT_VALUE] = value\n\n return true\n }\n\n if (isRootTarget && key === '$value') {\n const previousValue = parentObject[ROOT_VALUE]\n\n if (value === previousValue) return true\n\n if (safeStringify(value) === safeStringify(previousValue)) return true\n // if (JSON.stringify(value) === JSON.stringify(previousValue)) return true\n\n if (fieldPath !== 'root') {\n (parentObject as any)[ROOT_VALUE] = value\n } else {\n (parentObject as any)[ROOT_VALUE] = {\n ...rootFunctions,\n ...value,\n }\n store$$.next({\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(targetObject[ROOT_VALUE])),\n storeValue: parentObject[ROOT_VALUE],\n change: {\n fieldPath: 'root' as any,\n newValue: value,\n previousValue,\n },\n })\n }\n\n return true\n }\n\n const realInnerObject = isRootTarget ? parentObject[ROOT_VALUE] : parentObject\n const previousValue = Reflect.get(realInnerObject, key, receiver)\n\n\n if (previousValue === value) return true\n\n\n // New object values, check if the field has already a proxy created to use it instead of reacreating a new instance\n if (isValidReactiveObject(value) && previousValue?._$fieldPath)\n previousValue.$value = value\n else\n Reflect.set(realInnerObject, key, value, realInnerObject)\n\n\n const nextStoreChange = {\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(opts?.parentObjectToProxify ?? target)),\n storeValue: opts?.parentObjectToProxify ?? realInnerObject,\n change: {\n fieldPath: `${fieldPath}.${key}`.replace('root.', '') as any,\n newValue: value,\n previousValue,\n },\n }\n\n store$$.next(nextStoreChange)\n opts.afterChange?.([nextStoreChange])\n\n return true\n },\n\n has (t, p) {\n return Reflect.has(t[ROOT_VALUE], p)\n },\n\n ownKeys (t) {\n return Reflect.ownKeys(t[ROOT_VALUE])\n },\n\n getOwnPropertyDescriptor (t, p) {\n return Reflect.getOwnPropertyDescriptor(t[ROOT_VALUE], p)\n },\n\n })\n}\n\n//\n// function getUnproxiedObject (obj: any): any {\n// if (obj && typeof obj === 'object') {\n// if (obj[ROOT_VALUE]?.[ROOT_VALUE]) return '[Circular reference]'\n//\n// // Check if the object is a proxy\n// if (obj[ROOT_VALUE])\n// return getUnproxiedObject(obj[ROOT_VALUE])\n//\n//\n// // If it's not a proxy, return the object itself\n// return obj\n// }\n//\n// // If it's not an object, return it as is\n// return obj\n// }\n\n\nfunction safeStringify (obj: any): string {\n // use removeCircularReferences to avoid circular references\n // const cleanedObj = removeCircularReferences(obj)\n\n return JSON.stringify(\n obj,\n (_key, value) => {\n if (Array.isArray(value)) return value.map(i => safeStringify(i))\n\n if (isReactElement(value)) {\n // console.log('React element detected', value)\n\n return { props: safeStringify(value.props), type: typeof value.type === 'string' ? value.type : '' }\n }\n\n if (globalThis?.HTMLElement && value instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: value.innerHTML }\n\n // console.log('Value', value)\n\n return value\n })\n}\n\n\nfunction safeToJson (obj: any): Record<string, any> {\n const o: Record<string, any> = {}\n\n if (typeof obj !== 'object' || obj == null)\n return obj\n\n if (Array.isArray(obj))\n return obj.map(item => safeToJson(item))\n\n if (isReactElement(obj))\n return { props: safeToJson(obj.props), type: typeof obj.type === 'string' ? obj.type : '' }\n\n if (globalThis?.HTMLElement && obj instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: obj.innerHTML }\n\n Object.entries(obj).forEach(([key, v]) => {\n o[key] = safeToJson(v)\n })\n\n return o\n}\n\n\n// function removeCircularReferences (obj: any): any {\n// const seen = new WeakSet()\n//\n// function traverse (value: any): any {\n// if (value && typeof value === 'object') {\n// // If the object has already been seen, it's a circular reference\n// if (seen.has(value))\n// return null\n//\n// seen.add(value)\n//\n// if (Array.isArray(value))\n// return value.map(traverse)\n//\n//\n// const result: any = {}\n//\n// for (const key in value) {\n// if (Object.prototype.hasOwnProperty.call(value, key)) {\n// if (key === '_owner' && value.$$typeof) continue\n//\n// result[key] = traverse(value[key])\n// }\n// }\n//\n// return result\n// }\n//\n// // Return primitive values as-is\n// return value\n// }\n//\n// return traverse(obj)\n// }\n","\nimport { useLayoutEffect, useRef, useSyncExternalStore } from 'react'\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { proxifyStore } from '../helpers/new-proxify-store'\nimport { deepClone } from '../utils/object'\nimport { createCacheableSubject } from '../utils/subject'\n\nimport type { FieldPath, StoreChange } from '../../types/shared'\n\n\n\n\n// export type CervelloOptions<StoreValue extends Record<string, any>> = {\n// beforeChange?: (storeChange: StoreChange<StoreValue>) => unknown | undefined\n// afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n// }\n\nexport type CervelloOptions<StoreValue extends Record<string, any>> = {\n afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\nexport type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {\n initialValue?: (currentStore: StoreValue) => StoreValue | undefined | null,\n setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>,\n select?:\n | Array<FieldPath<StoreValue>>\n | (() => Array<FieldPath<StoreValue>>)\n onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\ntype MutableStoreValue<T extends Record<string, any>> = {\n $value: T\n} & T\n\n\n\n\n\n\n\n\nexport function nonReactive <T extends Record<string, any>> (initialValue: T): T {\n Object.defineProperty(initialValue, nonReactiveObjectSymbol, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return initialValue\n}\n\n\nexport function cervello <StoreValue extends Record<PropertyKey, any>> (\n initialValue: StoreValue,\n options?: CervelloOptions<StoreValue>,\n): {\n store: MutableStoreValue<StoreValue>,\n reset: () => void,\n useStore: (options?: CervelloUseStoreOptions<StoreValue>) => MutableStoreValue<StoreValue>\n } {\n const {\n // beforeChange,\n afterChange,\n } = options ?? {}\n\n const clonedInitialValue = (initialValue)\n const store$$ = createCacheableSubject<StoreChange<StoreValue>>(clonedInitialValue as any)\n\n const proxiedStore = proxifyStore(\n store$$ as any,\n clonedInitialValue,\n // { beforeChange, afterChange },\n { afterChange },\n ) as MutableStoreValue<StoreValue>\n\n\n return {\n store: proxiedStore,\n reset: () => {\n proxiedStore.$value = deepClone(initialValue)\n },\n useStore: (options) => {\n // const i = useId()\n const initialValue = options?.initialValue?.(proxiedStore.$value)\n const isInitialValueSet = useRef(false)\n\n if (!isInitialValueSet.current && initialValue && initialValue !== proxiedStore) {\n isInitialValueSet.current = true;\n (proxiedStore as any).$value = initialValue\n }\n\n const selectFieldPaths = useRef(\n (typeof options?.select === 'function'\n ? options?.select?.()\n : options?.select)\n ?? [],\n )\n\n const selectedFieldPathsForNestedObjects = useRef(\n selectFieldPaths.current\n .filter(fp => fp.includes('.*'))\n .map(fp => fp.replace('.*', '')),\n )\n\n\n useLayoutEffect(() => {\n if (options?.setValueOnMount) {\n void options.setValueOnMount(proxiedStore.$value).then((value) => {\n proxiedStore.$value = value\n }).catch((err) => {\n console.error('Error setting initial value on mount', err)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n\n useSyncExternalStore(\n (onStoreChange) => {\n const subscription = store$$.subscribe({\n next: (sc) => {\n // console.log('Store change', sc, i)\n const storeChanges = Array.isArray(sc)\n ? sc as Array<StoreChange<StoreValue>>\n : [sc]\n\n if (!options?.select) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n\n return\n }\n\n if (storeChanges.some(nextChange => (\n nextChange.change.fieldPath === 'root'\n || selectFieldPaths.current.includes(nextChange.change.fieldPath))\n || selectedFieldPathsForNestedObjects.current.find(fp => nextChange.change.fieldPath.startsWith(fp)),\n )) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n }\n },\n })\n\n return () => {\n subscription.unsubscribe()\n }\n },\n () => store$$.getValue(),\n () => store$$.getValue(),\n )\n\n return proxiedStore\n },\n }\n}\n","\nexport type Noop = () => void\n\n\nexport type Observer<T> = {\n next: (value: T) => void\n}\n\nexport type Subscription = {\n unsubscribe: Noop\n}\n\nexport type CacheableSubject<T> = {\n getValue: () => T\n subscribe: (value: Observer<T>) => Subscription\n unSubscribeAll: Noop\n} & Observer<T>\n\n\n// const WITH_FLUSHING = true\n\nexport function createCacheableSubject<T> (defaultValue: T, getValueOnSubscribe = false): CacheableSubject<T> {\n let isFlushing = false\n let itemsToFlush: Array<T> = []\n\n let observerList: Array<Observer<T>> = []\n let value = defaultValue\n\n const getValue = (): T => value\n\n const next = (newValue: T): void => {\n value = newValue\n\n // if (!WITH_FLUSHING) {\n // observerList.forEach((o) => { o.next(newValue) })\n //\n // return\n // }\n\n itemsToFlush.push(newValue)\n // observerList.forEach((o) => { o.next(newValue) })\n\n if (!isFlushing) {\n isFlushing = true\n void Promise.resolve().then(() => {\n observerList.forEach((o) => { o.next(itemsToFlush as T) })\n itemsToFlush = []\n isFlushing = false\n })\n }\n }\n\n const subscribe = (observer: Observer<T>): Subscription => {\n // Push cached value on subscribe\n if (getValueOnSubscribe) observer.next(value)\n // Store the observer to be notified\n observerList.push(observer)\n\n return {\n unsubscribe: () => {\n observerList = observerList.filter(o => o !== observer)\n },\n }\n }\n\n const unSubscribeAll = (): void => {\n observerList = []\n }\n\n return {\n getValue,\n next,\n subscribe,\n unSubscribeAll,\n }\n}\n"],"names":["nonReactiveObjectSymbol","Symbol","deepClone","obj","Array","isArray","newObj","map","item","hasOwnProperty","Object","entries","forEach","_ref","getOwnPropertySymbols","symbol","isObject","isReactElement","$$typeof","isValidReactiveObject","value","hasOwn","call","bind","proxifyStore","store$$","objectToProxify","opts","fieldPath","nestedFieldPath","_opts$nestedFieldPath","objectWithRootValue","_objectWithRootValue","ROOT_VALUE","rootFunctions","fromEntries","filter","v","Proxy","get","targetObject","propName","receiver","target","safeToJson","propertyValue","Reflect","_opts$parentObjectToP","_$fieldPath","parentObjectToProxify","afterChange","proxiedNestedObject","set","parentObject","key","newValue","_opts$parentObjectToP2","_opts","isRootTarget","previousValue","safeStringify","next","storeValue","change","realInnerObject","$value","nextStoreChange","replace","has","t","p","ownKeys","getOwnPropertyDescriptor","JSON","stringify","_key","i","props","type","globalThis","HTMLElement","content","innerHTML","o","nonReactive","initialValue","defineProperty","enumerable","writable","configurable","cervello","options","clonedInitialValue","defaultValue","getValueOnSubscribe","isFlushing","itemsToFlush","getValue","push","Promise","resolve","then","observerList","subscribe","observer","unsubscribe","unSubscribeAll","createCacheableSubject","proxiedStore","store","reset","useStore","_ref2","isInitialValueSet","useRef","current","selectFieldPaths","select","selectedFieldPathsForNestedObjects","fp","includes","useLayoutEffect","setValueOnMount","err","console","error","useSyncExternalStore","onStoreChange","subscription","sc","storeChanges","onChange","some","nextChange","find","startsWith"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cervello.esm.js","sources":["../src/types/shared.ts","../src/lib/utils/object.ts","../src/lib/helpers/new-proxify-store.ts","../src/lib/store/new-index.ts","../src/lib/utils/subject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nexport type WithoutType<T, V, WithNever = {\n [K in keyof T]: Exclude<T[K], undefined> extends V\n ? never\n : (T[K] extends Record<string, unknown>\n ? WithoutType<T[K], V>\n : T[K])\n}> = Pick<WithNever, {\n [K in keyof WithNever]: WithNever[K] extends never ? never : K\n}[keyof WithNever]>\n\n\n\nexport type ObjectFromAttributes<T, Attributes extends Array< keyof WithoutType<T, Function> > > = {\n [k in Attributes[number]]: T[k]\n}\n\nexport type Maybe<T> = T | undefined\n\n\n\nexport type UseSelector<T> = <Attributes extends Array< Exclude<keyof WithoutType<T, Function>, '$value'> >>(\n selectors: Attributes,\n isEqualFunction?: (previousState: ObjectFromAttributes<T, Attributes>, currentState: ObjectFromAttributes<T, Attributes>) => boolean,\n) => T\n\nexport type FieldPath<T extends Record<string, any>> = {\n [K in keyof Required<T>]: T[K] extends Record<string, any>\n ? K extends string\n\n ? T[K] extends Function\n ? never\n : T[K] extends Array<any>\n ? K\n : `${K}.*` | `${K}.${FieldPath<T[K]>}`\n : never\n : K extends string\n ? K\n : never\n}[keyof T]\n\nexport const nonReactiveObjectSymbol = Symbol('nonReactiveObject')\nexport type StoreChange<T extends Record<string, any>> = {\n change: {\n fieldPath: FieldPath<T>\n newValue: any\n previousValue: any\n }\n storeValue: T\n}\n","/* eslint-disable no-cond-assign */\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { INTERNAL_VALUE_PROP } from '../helpers/constants'\n\n\n/**\n * Clones all the provided object and nested properties and it also\n * iterates nested arrays to deepClone them\n *\n * @param obj - base object to be cloned\n * @returns new cloned object with new reference\n */\nexport function deepClone <T> (obj: T): T {\n if (!obj || typeof obj !== 'object')\n return obj\n\n let newObj = {} as any\n\n if (Array.isArray(obj)) {\n newObj = obj.map(item => deepClone(item))\n // eslint-disable-next-line no-prototype-builtins\n } else if (!obj.hasOwnProperty('$$typeof')) {\n Object.entries(obj).forEach(([key, value]) => {\n newObj[key] = deepClone(value)\n })\n Object.getOwnPropertySymbols(obj).forEach((symbol) => {\n newObj[symbol] = (obj as any)[symbol]\n })\n } else {\n newObj = obj\n }\n\n return newObj as T\n}\n\n// function copyBuffer (cur: ArrayBufferView) {\n// if (cur instanceof Buffer)\n// return Buffer.from(cur)\n//\n//\n// return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n// }\n\n\n// INFO: From `rfdc` (really-fast-deep-clone) package for faster cloning taking care of circular references\nexport function deepClone2 <T> (obj: T): T {\n const refs: Array<any> = []\n const refsNew: Array<any> = []\n\n const constructorHandlers = new Map()\n\n constructorHandlers.set(Date, (o: string | number | Date) => new Date(o))\n constructorHandlers.set(Map, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Set(cloneArray(Array.from(o), fn)))\n\n let handler = null\n\n return clone(obj)\n\n function cloneArray (a: any, fn: any): any {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as any\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n // } else if (ArrayBuffer.isView(cur)) {\n // a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n\n if (index !== -1)\n a2[k] = refsNew[index]\n else\n a2[k] = fn(cur)\n }\n }\n\n return a2\n }\n\n function clone (o: any): any {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor)))\n return handler(o, clone)\n\n const o2 = {} as any\n\n refs.push(o)\n refsNew.push(o2)\n\n\n Object.getOwnPropertySymbols(o).forEach((symbol) => {\n o2[symbol] = (o)[symbol]\n })\n\n for (const k in o) {\n if (!Object.hasOwnProperty.call(o, k)) continue\n const cur = o[k]\n\n\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n // } else if (ArrayBuffer.isView(cur)) {\n // o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n\n if (i !== -1)\n o2[k] = refsNew[i]\n else\n o2[k] = clone(cur)\n }\n }\n refs.pop()\n refsNew.pop()\n\n\n return o2\n }\n}\n\n/**\n * Guard to check is variable is an object\n * @param obj - variable to be checked\n * @returns boolean\n */\nexport const isObject = (obj: unknown): obj is Record<string | symbol, unknown> => (\n obj !== null\n && typeof obj === 'object'\n && !Array.isArray(obj)\n)\n\n\nexport const isReactElement = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n\n return !!(obj.$$typeof)\n}\n\n\n\nexport function isValidReactiveObject <T extends Record<string, any>> (value: T): boolean {\n return isObject(value) && !isReactElement(value) && !(value as any)[nonReactiveObjectSymbol]\n}\n\n\n\n/**\n * Returns the actual target value instead of root\n * object with internals props like $$value$$\n *\n * @param target - object from subscription or proxy\n * @returns actual value\n */\nexport const okTarget = (target: any): any => target[INTERNAL_VALUE_PROP] ?? target\n\n\n\n\n/**\n * Gets an object with just the properties requested\n * instead of the full object\n *\n * @param properties - object properties\n * @param obj - target to get the properties\n * @returns New object with just the requested properties\n */\nexport function getPartialObjectFromProperties<T> (properties: Array<keyof T>, obj: T): any {\n return properties.reduce<any>((acc, curr) => {\n acc[curr] = obj[curr]\n\n return acc\n }, {})\n}\n\n\n\nconst stringify = (obj: any): string => JSON.stringify(obj)\n\n/**\n * Compare 2 provided objects by stringing them\n * @param a - first object\n * @param b - second object\n * @returns boolean\n */\nexport const contentComparer = (a: any, b: any): boolean => stringify(a) === stringify(b)\n","\nimport { isReactElement, isValidReactiveObject } from '../utils/object'\n\nimport type { StoreChange } from '../../types/shared'\nimport type { CacheableSubject } from '../utils/subject'\n\n\n\n// @ts-expect-error - Object.hasOwn is not defined in older Safari's browsers\n('hasOwn' in Object) || (Object.hasOwn = Object.call.bind(Object.hasOwnProperty))\n\nconst ROOT_VALUE = Symbol('value')\n\n\nexport function proxifyStore <T extends Record<string | symbol, any>> (\n store$$: CacheableSubject<StoreChange<T>>,\n objectToProxify: T,\n opts: {\n nestedFieldPath?: string\n parentObjectToProxify?: any\n // beforeChange?: (storeChange: StoreChange<T>) => any\n afterChange?: (storeChange: Array<StoreChange<T>>) => void\n } = {},\n): T {\n const fieldPath = opts.nestedFieldPath ?? 'root'\n\n const objectWithRootValue = {\n [ROOT_VALUE]: objectToProxify,\n } as unknown as T\n\n const rootFunctions = fieldPath === 'root'\n ? Object.fromEntries(Object.entries(objectToProxify).filter(([,v]) => typeof v === 'function'))\n : {}\n\n return new Proxy(objectWithRootValue, {\n get (targetObject, propName, receiver) {\n // INFO: !Internal only.\n // Used to get the fieldPath of the object (it means it's a proxified object)\n if (propName === '_$fieldPath') return fieldPath\n\n const isRootTarget = Object.hasOwn(targetObject, ROOT_VALUE)\n const target = isRootTarget ? targetObject[ROOT_VALUE] : targetObject\n\n\n // Called when the object is converted to JSON or string (i.e. JSON.stringify)\n if (propName === 'toJSON') {\n return () => {\n // Remove react-elements with circular which have circular references\n // before stringifying to prevent JSON.stringify(storeProxy) from failing\n return safeToJson(target)\n // return removeCircularReferences(target)\n }\n }\n\n // Get the whole store value without the proxy\n if (propName === '$value') {\n // return getUnproxiedObject(target)\n return target\n }\n\n\n const propertyValue = Reflect.get(target, propName, receiver)\n\n if (typeof propName === 'symbol') return propertyValue\n\n if (typeof propertyValue === 'function')\n return (propertyValue as () => any).bind(receiver)\n\n\n // Check if it's correct to be a reactive object\n // & is not a circular reference or the same object\n if (isValidReactiveObject(propertyValue) && propertyValue !== target) {\n // const newNestedFieldPath = `${fieldPath}.${propName}`\n\n // If it's already a proxified object, return it\n // if (propertyValue._$fieldPath === newNestedFieldPath) return propertyValue\n if (propertyValue._$fieldPath) return propertyValue\n\n // Create a new proxified object\n const proxiedNestedObject = proxifyStore(\n store$$ as any,\n propertyValue,\n {\n nestedFieldPath: `${fieldPath}.${propName}`,\n parentObjectToProxify: opts.parentObjectToProxify ?? target,\n // beforeChange: opts.beforeChange,\n afterChange: opts.afterChange,\n },\n )\n\n return target[propName] = proxiedNestedObject\n }\n\n return propertyValue\n },\n\n\n set (parentObject, key, newValue, receiver) {\n if (typeof key === 'symbol') return true\n\n const value = newValue\n const isRootTarget = Object.hasOwn(parentObject, ROOT_VALUE)\n\n // INFO: !Internal only.\n // Used to set the value of the store without notifying the store\n if (isRootTarget && key === '$$value') {\n (parentObject as any)[ROOT_VALUE] = value\n\n return true\n }\n\n if (isRootTarget && key === '$value') {\n const previousValue = parentObject[ROOT_VALUE]\n\n if (value === previousValue) return true\n\n if (safeStringify(value) === safeStringify(previousValue)) return true\n // if (JSON.stringify(value) === JSON.stringify(previousValue)) return true\n\n if (fieldPath !== 'root') {\n (parentObject as any)[ROOT_VALUE] = value\n } else {\n (parentObject as any)[ROOT_VALUE] = {\n ...rootFunctions,\n ...value,\n }\n store$$.next({\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(targetObject[ROOT_VALUE])),\n storeValue: parentObject[ROOT_VALUE],\n change: {\n fieldPath: 'root' as any,\n newValue: value,\n previousValue,\n },\n })\n }\n\n return true\n }\n\n const realInnerObject = isRootTarget ? parentObject[ROOT_VALUE] : parentObject\n const previousValue = Reflect.get(realInnerObject, key, receiver)\n\n\n if (previousValue === value) return true\n\n\n // New object values, check if the field has already a proxy created to use it instead of reacreating a new instance\n if (isValidReactiveObject(value) && previousValue?._$fieldPath)\n previousValue.$value = value\n else\n Reflect.set(realInnerObject, key, value, realInnerObject)\n\n\n const nextStoreChange = {\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(opts?.parentObjectToProxify ?? target)),\n storeValue: opts?.parentObjectToProxify ?? realInnerObject,\n change: {\n fieldPath: `${fieldPath}.${key}`.replace('root.', '') as any,\n newValue: value,\n previousValue,\n },\n }\n\n store$$.next(nextStoreChange)\n opts.afterChange?.([nextStoreChange])\n\n return true\n },\n\n has (t, p) {\n return Reflect.has(t[ROOT_VALUE], p)\n },\n\n ownKeys (t) {\n return Reflect.ownKeys(t[ROOT_VALUE])\n },\n\n getOwnPropertyDescriptor (t, p) {\n return Reflect.getOwnPropertyDescriptor(t[ROOT_VALUE], p)\n },\n\n })\n}\n\n//\n// function getUnproxiedObject (obj: any): any {\n// if (obj && typeof obj === 'object') {\n// if (obj[ROOT_VALUE]?.[ROOT_VALUE]) return '[Circular reference]'\n//\n// // Check if the object is a proxy\n// if (obj[ROOT_VALUE])\n// return getUnproxiedObject(obj[ROOT_VALUE])\n//\n//\n// // If it's not a proxy, return the object itself\n// return obj\n// }\n//\n// // If it's not an object, return it as is\n// return obj\n// }\n\n\nfunction safeStringify (obj: any): string {\n // use removeCircularReferences to avoid circular references\n // const cleanedObj = removeCircularReferences(obj)\n\n return JSON.stringify(\n obj,\n (_key, value) => {\n if (Array.isArray(value)) return value.map(i => safeStringify(i))\n\n if (isReactElement(value)) {\n // console.log('React element detected', value)\n\n return { props: safeStringify(value.props), type: typeof value.type === 'string' ? value.type : '' }\n }\n\n if (globalThis?.HTMLElement && value instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: value.innerHTML }\n\n // console.log('Value', value)\n\n return value\n })\n}\n\n\nfunction safeToJson (obj: any): Record<string, any> {\n const o: Record<string, any> = {}\n\n if (typeof obj !== 'object' || obj == null)\n return obj\n\n if (Array.isArray(obj))\n return obj.map(item => safeToJson(item))\n\n if (isReactElement(obj))\n return { props: safeToJson(obj.props), type: typeof obj.type === 'string' ? obj.type : '' }\n\n if (globalThis?.HTMLElement && obj instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: obj.innerHTML }\n\n Object.entries(obj).forEach(([key, v]) => {\n o[key] = safeToJson(v)\n })\n\n return o\n}\n\n\n// function removeCircularReferences (obj: any): any {\n// const seen = new WeakSet()\n//\n// function traverse (value: any): any {\n// if (value && typeof value === 'object') {\n// // If the object has already been seen, it's a circular reference\n// if (seen.has(value))\n// return null\n//\n// seen.add(value)\n//\n// if (Array.isArray(value))\n// return value.map(traverse)\n//\n//\n// const result: any = {}\n//\n// for (const key in value) {\n// if (Object.prototype.hasOwnProperty.call(value, key)) {\n// if (key === '_owner' && value.$$typeof) continue\n//\n// result[key] = traverse(value[key])\n// }\n// }\n//\n// return result\n// }\n//\n// // Return primitive values as-is\n// return value\n// }\n//\n// return traverse(obj)\n// }\n","\nimport { useLayoutEffect, useRef, useSyncExternalStore } from 'react'\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { proxifyStore } from '../helpers/new-proxify-store'\nimport { deepClone } from '../utils/object'\nimport { createCacheableSubject } from '../utils/subject'\n\nimport type { FieldPath, StoreChange } from '../../types/shared'\n\n\n\n\n// export type CervelloOptions<StoreValue extends Record<string, any>> = {\n// beforeChange?: (storeChange: StoreChange<StoreValue>) => unknown | undefined\n// afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n// }\n\nexport type CervelloOptions<StoreValue extends Record<string, any>> = {\n afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\nexport type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {\n initialValue?: (currentStore: StoreValue) => StoreValue | null,\n setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>,\n select?:\n | Array<FieldPath<StoreValue>>\n | (() => Array<FieldPath<StoreValue>>)\n onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\ntype MutableStoreValue<T extends Record<string, any>> = {\n $value: T\n} & T\n\n\n\n\n\n\n\n\nexport function nonReactive <T extends Record<string, any>> (initialValue: T): T {\n Object.defineProperty(initialValue, nonReactiveObjectSymbol, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return initialValue\n}\n\n\nexport function cervello <StoreValue extends Record<PropertyKey, any>> (\n initialValue: StoreValue,\n options?: CervelloOptions<StoreValue>,\n): {\n store: MutableStoreValue<StoreValue>,\n reset: () => void,\n useStore: (options?: CervelloUseStoreOptions<StoreValue>) => MutableStoreValue<StoreValue>\n } {\n const {\n // beforeChange,\n afterChange,\n } = options ?? {}\n\n const clonedInitialValue = (initialValue)\n const store$$ = createCacheableSubject<StoreChange<StoreValue>>(clonedInitialValue as any)\n\n const proxiedStore = proxifyStore(\n store$$ as any,\n clonedInitialValue,\n // { beforeChange, afterChange },\n { afterChange },\n ) as MutableStoreValue<StoreValue>\n\n\n return {\n store: proxiedStore,\n reset: () => {\n proxiedStore.$value = deepClone(initialValue)\n },\n useStore: (options) => {\n // const i = useId()\n const initialValue = options?.initialValue?.(proxiedStore.$value)\n const isInitialValueSet = useRef(false)\n\n if (!isInitialValueSet.current && initialValue && initialValue !== proxiedStore) {\n isInitialValueSet.current = true;\n (proxiedStore as any).$value = initialValue\n }\n\n const selectFieldPaths = useRef(\n (typeof options?.select === 'function'\n ? options?.select?.()\n : options?.select)\n ?? [],\n )\n\n const selectedFieldPathsForNestedObjects = useRef(\n selectFieldPaths.current\n .filter(fp => fp.includes('.*'))\n .map(fp => fp.replace('.*', '')),\n )\n\n\n useLayoutEffect(() => {\n if (options?.setValueOnMount) {\n void options.setValueOnMount(proxiedStore.$value).then((value) => {\n proxiedStore.$value = value\n }).catch((err) => {\n console.error('Error setting initial value on mount', err)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n\n useSyncExternalStore(\n (onStoreChange) => {\n const subscription = store$$.subscribe({\n next: (sc) => {\n // console.log('Store change', sc, i)\n const storeChanges = Array.isArray(sc)\n ? sc as Array<StoreChange<StoreValue>>\n : [sc]\n\n if (!options?.select) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n\n return\n }\n\n if (storeChanges.some(nextChange => (\n nextChange.change.fieldPath === 'root'\n || selectFieldPaths.current.includes(nextChange.change.fieldPath))\n || selectedFieldPathsForNestedObjects.current.find(fp => nextChange.change.fieldPath.startsWith(fp)),\n )) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n }\n },\n })\n\n return () => {\n subscription.unsubscribe()\n }\n },\n () => store$$.getValue(),\n () => store$$.getValue(),\n )\n\n return proxiedStore\n },\n }\n}\n","\nexport type Noop = () => void\n\n\nexport type Observer<T> = {\n next: (value: T) => void\n}\n\nexport type Subscription = {\n unsubscribe: Noop\n}\n\nexport type CacheableSubject<T> = {\n getValue: () => T\n subscribe: (value: Observer<T>) => Subscription\n unSubscribeAll: Noop\n} & Observer<T>\n\n\n// const WITH_FLUSHING = true\n\nexport function createCacheableSubject<T> (defaultValue: T, getValueOnSubscribe = false): CacheableSubject<T> {\n let isFlushing = false\n let itemsToFlush: Array<T> = []\n\n let observerList: Array<Observer<T>> = []\n let value = defaultValue\n\n const getValue = (): T => value\n\n const next = (newValue: T): void => {\n value = newValue\n\n // if (!WITH_FLUSHING) {\n // observerList.forEach((o) => { o.next(newValue) })\n //\n // return\n // }\n\n itemsToFlush.push(newValue)\n // observerList.forEach((o) => { o.next(newValue) })\n\n if (!isFlushing) {\n isFlushing = true\n void Promise.resolve().then(() => {\n observerList.forEach((o) => { o.next(itemsToFlush as T) })\n itemsToFlush = []\n isFlushing = false\n })\n }\n }\n\n const subscribe = (observer: Observer<T>): Subscription => {\n // Push cached value on subscribe\n if (getValueOnSubscribe) observer.next(value)\n // Store the observer to be notified\n observerList.push(observer)\n\n return {\n unsubscribe: () => {\n observerList = observerList.filter(o => o !== observer)\n },\n }\n }\n\n const unSubscribeAll = (): void => {\n observerList = []\n }\n\n return {\n getValue,\n next,\n subscribe,\n unSubscribeAll,\n }\n}\n"],"names":["nonReactiveObjectSymbol","Symbol","deepClone","obj","Array","isArray","newObj","map","item","hasOwnProperty","Object","entries","forEach","_ref","getOwnPropertySymbols","symbol","isObject","isReactElement","$$typeof","isValidReactiveObject","value","hasOwn","call","bind","proxifyStore","store$$","objectToProxify","opts","fieldPath","nestedFieldPath","_opts$nestedFieldPath","objectWithRootValue","_objectWithRootValue","ROOT_VALUE","rootFunctions","fromEntries","filter","v","Proxy","get","targetObject","propName","receiver","target","safeToJson","propertyValue","Reflect","_opts$parentObjectToP","_$fieldPath","parentObjectToProxify","afterChange","proxiedNestedObject","set","parentObject","key","newValue","_opts$parentObjectToP2","_opts","isRootTarget","previousValue","safeStringify","next","storeValue","change","realInnerObject","$value","nextStoreChange","replace","has","t","p","ownKeys","getOwnPropertyDescriptor","JSON","stringify","_key","i","props","type","globalThis","HTMLElement","content","innerHTML","o","nonReactive","initialValue","defineProperty","enumerable","writable","configurable","cervello","options","clonedInitialValue","defaultValue","getValueOnSubscribe","isFlushing","itemsToFlush","getValue","push","Promise","resolve","then","observerList","subscribe","observer","unsubscribe","unSubscribeAll","createCacheableSubject","proxiedStore","store","reset","useStore","_ref2","isInitialValueSet","useRef","current","selectFieldPaths","select","selectedFieldPathsForNestedObjects","fp","includes","useLayoutEffect","setValueOnMount","err","console","error","useSyncExternalStore","onStoreChange","subscription","sc","storeChanges","onChange","some","nextChange","find","startsWith"],"mappings":"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"}
|
package/dist/cervello.umd.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cervello.umd.js","sources":["../src/types/shared.ts","../src/lib/utils/object.ts","../src/lib/helpers/new-proxify-store.ts","../src/lib/store/new-index.ts","../src/lib/utils/subject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nexport type WithoutType<T, V, WithNever = {\n [K in keyof T]: Exclude<T[K], undefined> extends V\n ? never\n : (T[K] extends Record<string, unknown>\n ? WithoutType<T[K], V>\n : T[K])\n}> = Pick<WithNever, {\n [K in keyof WithNever]: WithNever[K] extends never ? never : K\n}[keyof WithNever]>\n\n\n\nexport type ObjectFromAttributes<T, Attributes extends Array< keyof WithoutType<T, Function> > > = {\n [k in Attributes[number]]: T[k]\n}\n\nexport type Maybe<T> = T | undefined\n\n\n\nexport type UseSelector<T> = <Attributes extends Array< Exclude<keyof WithoutType<T, Function>, '$value'> >>(\n selectors: Attributes,\n isEqualFunction?: (previousState: ObjectFromAttributes<T, Attributes>, currentState: ObjectFromAttributes<T, Attributes>) => boolean,\n) => T\n\nexport type FieldPath<T extends Record<string, any>> = {\n [K in keyof Required<T>]: T[K] extends Record<string, any>\n ? K extends string\n\n ? T[K] extends Function\n ? never\n : T[K] extends Array<any>\n ? K\n : `${K}.*` | `${K}.${FieldPath<T[K]>}`\n : never\n : K extends string\n ? K\n : never\n}[keyof T]\n\nexport const nonReactiveObjectSymbol = Symbol('nonReactiveObject')\nexport type StoreChange<T extends Record<string, any>> = {\n change: {\n fieldPath: FieldPath<T>\n newValue: any\n previousValue: any\n }\n storeValue: T\n}\n","/* eslint-disable no-cond-assign */\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { INTERNAL_VALUE_PROP } from '../helpers/constants'\n\n\n/**\n * Clones all the provided object and nested properties and it also\n * iterates nested arrays to deepClone them\n *\n * @param obj - base object to be cloned\n * @returns new cloned object with new reference\n */\nexport function deepClone <T> (obj: T): T {\n if (!obj || typeof obj !== 'object')\n return obj\n\n let newObj = {} as any\n\n if (Array.isArray(obj)) {\n newObj = obj.map(item => deepClone(item))\n // eslint-disable-next-line no-prototype-builtins\n } else if (!obj.hasOwnProperty('$$typeof')) {\n Object.entries(obj).forEach(([key, value]) => {\n newObj[key] = deepClone(value)\n })\n Object.getOwnPropertySymbols(obj).forEach((symbol) => {\n newObj[symbol] = (obj as any)[symbol]\n })\n } else {\n newObj = obj\n }\n\n return newObj as T\n}\n\n// function copyBuffer (cur: ArrayBufferView) {\n// if (cur instanceof Buffer)\n// return Buffer.from(cur)\n//\n//\n// return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n// }\n\n\n// INFO: From `rfdc` (really-fast-deep-clone) package for faster cloning taking care of circular references\nexport function deepClone2 <T> (obj: T): T {\n const refs: Array<any> = []\n const refsNew: Array<any> = []\n\n const constructorHandlers = new Map()\n\n constructorHandlers.set(Date, (o: string | number | Date) => new Date(o))\n constructorHandlers.set(Map, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Set(cloneArray(Array.from(o), fn)))\n\n let handler = null\n\n return clone(obj)\n\n function cloneArray (a: any, fn: any): any {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as any\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n // } else if (ArrayBuffer.isView(cur)) {\n // a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n\n if (index !== -1)\n a2[k] = refsNew[index]\n else\n a2[k] = fn(cur)\n }\n }\n\n return a2\n }\n\n function clone (o: any): any {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor)))\n return handler(o, clone)\n\n const o2 = {} as any\n\n refs.push(o)\n refsNew.push(o2)\n\n\n Object.getOwnPropertySymbols(o).forEach((symbol) => {\n o2[symbol] = (o)[symbol]\n })\n\n for (const k in o) {\n if (!Object.hasOwnProperty.call(o, k)) continue\n const cur = o[k]\n\n\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n // } else if (ArrayBuffer.isView(cur)) {\n // o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n\n if (i !== -1)\n o2[k] = refsNew[i]\n else\n o2[k] = clone(cur)\n }\n }\n refs.pop()\n refsNew.pop()\n\n\n return o2\n }\n}\n\n/**\n * Guard to check is variable is an object\n * @param obj - variable to be checked\n * @returns boolean\n */\nexport const isObject = (obj: unknown): obj is Record<string | symbol, unknown> => (\n obj !== null\n && typeof obj === 'object'\n && !Array.isArray(obj)\n)\n\n\nexport const isReactElement = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n\n return !!(obj.$$typeof)\n}\n\n\n\nexport function isValidReactiveObject <T extends Record<string, any>> (value: T): boolean {\n return isObject(value) && !isReactElement(value) && !(value as any)[nonReactiveObjectSymbol]\n}\n\n\n\n/**\n * Returns the actual target value instead of root\n * object with internals props like $$value$$\n *\n * @param target - object from subscription or proxy\n * @returns actual value\n */\nexport const okTarget = (target: any): any => target[INTERNAL_VALUE_PROP] ?? target\n\n\n\n\n/**\n * Gets an object with just the properties requested\n * instead of the full object\n *\n * @param properties - object properties\n * @param obj - target to get the properties\n * @returns New object with just the requested properties\n */\nexport function getPartialObjectFromProperties<T> (properties: Array<keyof T>, obj: T): any {\n return properties.reduce<any>((acc, curr) => {\n acc[curr] = obj[curr]\n\n return acc\n }, {})\n}\n\n\n\nconst stringify = (obj: any): string => JSON.stringify(obj)\n\n/**\n * Compare 2 provided objects by stringing them\n * @param a - first object\n * @param b - second object\n * @returns boolean\n */\nexport const contentComparer = (a: any, b: any): boolean => stringify(a) === stringify(b)\n","\nimport { isReactElement, isValidReactiveObject } from '../utils/object'\n\nimport type { StoreChange } from '../../types/shared'\nimport type { CacheableSubject } from '../utils/subject'\n\n\n\n// @ts-expect-error - Object.hasOwn is not defined in older Safari's browsers\n('hasOwn' in Object) || (Object.hasOwn = Object.call.bind(Object.hasOwnProperty))\n\nconst ROOT_VALUE = Symbol('value')\n\n\nexport function proxifyStore <T extends Record<string | symbol, any>> (\n store$$: CacheableSubject<StoreChange<T>>,\n objectToProxify: T,\n opts: {\n nestedFieldPath?: string\n parentObjectToProxify?: any\n // beforeChange?: (storeChange: StoreChange<T>) => any\n afterChange?: (storeChange: Array<StoreChange<T>>) => void\n } = {},\n): T {\n const fieldPath = opts.nestedFieldPath ?? 'root'\n\n const objectWithRootValue = {\n [ROOT_VALUE]: objectToProxify,\n } as unknown as T\n\n const rootFunctions = fieldPath === 'root'\n ? Object.fromEntries(Object.entries(objectToProxify).filter(([,v]) => typeof v === 'function'))\n : {}\n\n return new Proxy(objectWithRootValue, {\n get (targetObject, propName, receiver) {\n // INFO: !Internal only.\n // Used to get the fieldPath of the object (it means it's a proxified object)\n if (propName === '_$fieldPath') return fieldPath\n\n const isRootTarget = Object.hasOwn(targetObject, ROOT_VALUE)\n const target = isRootTarget ? targetObject[ROOT_VALUE] : targetObject\n\n\n // Called when the object is converted to JSON or string (i.e. JSON.stringify)\n if (propName === 'toJSON') {\n return () => {\n // Remove react-elements with circular which have circular references\n // before stringifying to prevent JSON.stringify(storeProxy) from failing\n return safeToJson(target)\n // return removeCircularReferences(target)\n }\n }\n\n // Get the whole store value without the proxy\n if (propName === '$value') {\n // return getUnproxiedObject(target)\n return target\n }\n\n\n const propertyValue = Reflect.get(target, propName, receiver)\n\n if (typeof propName === 'symbol') return propertyValue\n\n if (typeof propertyValue === 'function')\n return (propertyValue as () => any).bind(receiver)\n\n\n // Check if it's correct to be a reactive object\n // & is not a circular reference or the same object\n if (isValidReactiveObject(propertyValue) && propertyValue !== target) {\n // const newNestedFieldPath = `${fieldPath}.${propName}`\n\n // If it's already a proxified object, return it\n // if (propertyValue._$fieldPath === newNestedFieldPath) return propertyValue\n if (propertyValue._$fieldPath) return propertyValue\n\n // Create a new proxified object\n const proxiedNestedObject = proxifyStore(\n store$$ as any,\n propertyValue,\n {\n nestedFieldPath: `${fieldPath}.${propName}`,\n parentObjectToProxify: opts.parentObjectToProxify ?? target,\n // beforeChange: opts.beforeChange,\n afterChange: opts.afterChange,\n },\n )\n\n return target[propName] = proxiedNestedObject\n }\n\n return propertyValue\n },\n\n\n set (parentObject, key, newValue, receiver) {\n if (typeof key === 'symbol') return true\n\n const value = newValue\n const isRootTarget = Object.hasOwn(parentObject, ROOT_VALUE)\n\n // INFO: !Internal only.\n // Used to set the value of the store without notifying the store\n if (isRootTarget && key === '$$value') {\n (parentObject as any)[ROOT_VALUE] = value\n\n return true\n }\n\n if (isRootTarget && key === '$value') {\n const previousValue = parentObject[ROOT_VALUE]\n\n if (value === previousValue) return true\n\n if (safeStringify(value) === safeStringify(previousValue)) return true\n // if (JSON.stringify(value) === JSON.stringify(previousValue)) return true\n\n if (fieldPath !== 'root') {\n (parentObject as any)[ROOT_VALUE] = value\n } else {\n (parentObject as any)[ROOT_VALUE] = {\n ...rootFunctions,\n ...value,\n }\n store$$.next({\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(targetObject[ROOT_VALUE])),\n storeValue: parentObject[ROOT_VALUE],\n change: {\n fieldPath: 'root' as any,\n newValue: value,\n previousValue,\n },\n })\n }\n\n return true\n }\n\n const realInnerObject = isRootTarget ? parentObject[ROOT_VALUE] : parentObject\n const previousValue = Reflect.get(realInnerObject, key, receiver)\n\n\n if (previousValue === value) return true\n\n\n // New object values, check if the field has already a proxy created to use it instead of reacreating a new instance\n if (isValidReactiveObject(value) && previousValue?._$fieldPath)\n previousValue.$value = value\n else\n Reflect.set(realInnerObject, key, value, realInnerObject)\n\n\n const nextStoreChange = {\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(opts?.parentObjectToProxify ?? target)),\n storeValue: opts?.parentObjectToProxify ?? realInnerObject,\n change: {\n fieldPath: `${fieldPath}.${key}`.replace('root.', '') as any,\n newValue: value,\n previousValue,\n },\n }\n\n store$$.next(nextStoreChange)\n opts.afterChange?.([nextStoreChange])\n\n return true\n },\n\n has (t, p) {\n return Reflect.has(t[ROOT_VALUE], p)\n },\n\n ownKeys (t) {\n return Reflect.ownKeys(t[ROOT_VALUE])\n },\n\n getOwnPropertyDescriptor (t, p) {\n return Reflect.getOwnPropertyDescriptor(t[ROOT_VALUE], p)\n },\n\n })\n}\n\n//\n// function getUnproxiedObject (obj: any): any {\n// if (obj && typeof obj === 'object') {\n// if (obj[ROOT_VALUE]?.[ROOT_VALUE]) return '[Circular reference]'\n//\n// // Check if the object is a proxy\n// if (obj[ROOT_VALUE])\n// return getUnproxiedObject(obj[ROOT_VALUE])\n//\n//\n// // If it's not a proxy, return the object itself\n// return obj\n// }\n//\n// // If it's not an object, return it as is\n// return obj\n// }\n\n\nfunction safeStringify (obj: any): string {\n // use removeCircularReferences to avoid circular references\n // const cleanedObj = removeCircularReferences(obj)\n\n return JSON.stringify(\n obj,\n (_key, value) => {\n if (Array.isArray(value)) return value.map(i => safeStringify(i))\n\n if (isReactElement(value)) {\n // console.log('React element detected', value)\n\n return { props: safeStringify(value.props), type: typeof value.type === 'string' ? value.type : '' }\n }\n\n if (globalThis?.HTMLElement && value instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: value.innerHTML }\n\n // console.log('Value', value)\n\n return value\n })\n}\n\n\nfunction safeToJson (obj: any): Record<string, any> {\n const o: Record<string, any> = {}\n\n if (typeof obj !== 'object' || obj == null)\n return obj\n\n if (Array.isArray(obj))\n return obj.map(item => safeToJson(item))\n\n if (isReactElement(obj))\n return { props: safeToJson(obj.props), type: typeof obj.type === 'string' ? obj.type : '' }\n\n if (globalThis?.HTMLElement && obj instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: obj.innerHTML }\n\n Object.entries(obj).forEach(([key, v]) => {\n o[key] = safeToJson(v)\n })\n\n return o\n}\n\n\n// function removeCircularReferences (obj: any): any {\n// const seen = new WeakSet()\n//\n// function traverse (value: any): any {\n// if (value && typeof value === 'object') {\n// // If the object has already been seen, it's a circular reference\n// if (seen.has(value))\n// return null\n//\n// seen.add(value)\n//\n// if (Array.isArray(value))\n// return value.map(traverse)\n//\n//\n// const result: any = {}\n//\n// for (const key in value) {\n// if (Object.prototype.hasOwnProperty.call(value, key)) {\n// if (key === '_owner' && value.$$typeof) continue\n//\n// result[key] = traverse(value[key])\n// }\n// }\n//\n// return result\n// }\n//\n// // Return primitive values as-is\n// return value\n// }\n//\n// return traverse(obj)\n// }\n","\nimport { useLayoutEffect, useRef, useSyncExternalStore } from 'react'\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { proxifyStore } from '../helpers/new-proxify-store'\nimport { deepClone } from '../utils/object'\nimport { createCacheableSubject } from '../utils/subject'\n\nimport type { FieldPath, StoreChange } from '../../types/shared'\n\n\n\n\n// export type CervelloOptions<StoreValue extends Record<string, any>> = {\n// beforeChange?: (storeChange: StoreChange<StoreValue>) => unknown | undefined\n// afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n// }\n\nexport type CervelloOptions<StoreValue extends Record<string, any>> = {\n afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\nexport type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {\n initialValue?: (currentStore: StoreValue) => StoreValue | undefined | null,\n setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>,\n select?:\n | Array<FieldPath<StoreValue>>\n | (() => Array<FieldPath<StoreValue>>)\n onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\ntype MutableStoreValue<T extends Record<string, any>> = {\n $value: T\n} & T\n\n\n\n\n\n\n\n\nexport function nonReactive <T extends Record<string, any>> (initialValue: T): T {\n Object.defineProperty(initialValue, nonReactiveObjectSymbol, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return initialValue\n}\n\n\nexport function cervello <StoreValue extends Record<PropertyKey, any>> (\n initialValue: StoreValue,\n options?: CervelloOptions<StoreValue>,\n): {\n store: MutableStoreValue<StoreValue>,\n reset: () => void,\n useStore: (options?: CervelloUseStoreOptions<StoreValue>) => MutableStoreValue<StoreValue>\n } {\n const {\n // beforeChange,\n afterChange,\n } = options ?? {}\n\n const clonedInitialValue = (initialValue)\n const store$$ = createCacheableSubject<StoreChange<StoreValue>>(clonedInitialValue as any)\n\n const proxiedStore = proxifyStore(\n store$$ as any,\n clonedInitialValue,\n // { beforeChange, afterChange },\n { afterChange },\n ) as MutableStoreValue<StoreValue>\n\n\n return {\n store: proxiedStore,\n reset: () => {\n proxiedStore.$value = deepClone(initialValue)\n },\n useStore: (options) => {\n // const i = useId()\n const initialValue = options?.initialValue?.(proxiedStore.$value)\n const isInitialValueSet = useRef(false)\n\n if (!isInitialValueSet.current && initialValue && initialValue !== proxiedStore) {\n isInitialValueSet.current = true;\n (proxiedStore as any).$value = initialValue\n }\n\n const selectFieldPaths = useRef(\n (typeof options?.select === 'function'\n ? options?.select?.()\n : options?.select)\n ?? [],\n )\n\n const selectedFieldPathsForNestedObjects = useRef(\n selectFieldPaths.current\n .filter(fp => fp.includes('.*'))\n .map(fp => fp.replace('.*', '')),\n )\n\n\n useLayoutEffect(() => {\n if (options?.setValueOnMount) {\n void options.setValueOnMount(proxiedStore.$value).then((value) => {\n proxiedStore.$value = value\n }).catch((err) => {\n console.error('Error setting initial value on mount', err)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n\n useSyncExternalStore(\n (onStoreChange) => {\n const subscription = store$$.subscribe({\n next: (sc) => {\n // console.log('Store change', sc, i)\n const storeChanges = Array.isArray(sc)\n ? sc as Array<StoreChange<StoreValue>>\n : [sc]\n\n if (!options?.select) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n\n return\n }\n\n if (storeChanges.some(nextChange => (\n nextChange.change.fieldPath === 'root'\n || selectFieldPaths.current.includes(nextChange.change.fieldPath))\n || selectedFieldPathsForNestedObjects.current.find(fp => nextChange.change.fieldPath.startsWith(fp)),\n )) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n }\n },\n })\n\n return () => {\n subscription.unsubscribe()\n }\n },\n () => store$$.getValue(),\n () => store$$.getValue(),\n )\n\n return proxiedStore\n },\n }\n}\n","\nexport type Noop = () => void\n\n\nexport type Observer<T> = {\n next: (value: T) => void\n}\n\nexport type Subscription = {\n unsubscribe: Noop\n}\n\nexport type CacheableSubject<T> = {\n getValue: () => T\n subscribe: (value: Observer<T>) => Subscription\n unSubscribeAll: Noop\n} & Observer<T>\n\n\n// const WITH_FLUSHING = true\n\nexport function createCacheableSubject<T> (defaultValue: T, getValueOnSubscribe = false): CacheableSubject<T> {\n let isFlushing = false\n let itemsToFlush: Array<T> = []\n\n let observerList: Array<Observer<T>> = []\n let value = defaultValue\n\n const getValue = (): T => value\n\n const next = (newValue: T): void => {\n value = newValue\n\n // if (!WITH_FLUSHING) {\n // observerList.forEach((o) => { o.next(newValue) })\n //\n // return\n // }\n\n itemsToFlush.push(newValue)\n // observerList.forEach((o) => { o.next(newValue) })\n\n if (!isFlushing) {\n isFlushing = true\n void Promise.resolve().then(() => {\n observerList.forEach((o) => { o.next(itemsToFlush as T) })\n itemsToFlush = []\n isFlushing = false\n })\n }\n }\n\n const subscribe = (observer: Observer<T>): Subscription => {\n // Push cached value on subscribe\n if (getValueOnSubscribe) observer.next(value)\n // Store the observer to be notified\n observerList.push(observer)\n\n return {\n unsubscribe: () => {\n observerList = observerList.filter(o => o !== observer)\n },\n }\n }\n\n const unSubscribeAll = (): void => {\n observerList = []\n }\n\n return {\n getValue,\n next,\n subscribe,\n unSubscribeAll,\n }\n}\n"],"names":["nonReactiveObjectSymbol","Symbol","deepClone","obj","Array","isArray","newObj","map","item","hasOwnProperty","Object","entries","forEach","_ref","getOwnPropertySymbols","symbol","isObject","isReactElement","$$typeof","isValidReactiveObject","value","hasOwn","call","bind","proxifyStore","store$$","objectToProxify","opts","fieldPath","nestedFieldPath","_opts$nestedFieldPath","objectWithRootValue","_objectWithRootValue","ROOT_VALUE","rootFunctions","fromEntries","filter","v","Proxy","get","targetObject","propName","receiver","target","safeToJson","propertyValue","Reflect","_opts$parentObjectToP","_$fieldPath","parentObjectToProxify","afterChange","proxiedNestedObject","set","parentObject","key","newValue","_opts$parentObjectToP2","_opts","isRootTarget","previousValue","safeStringify","next","storeValue","change","realInnerObject","$value","nextStoreChange","replace","has","t","p","ownKeys","getOwnPropertyDescriptor","JSON","stringify","_key","i","props","type","globalThis","HTMLElement","content","innerHTML","o","initialValue","options","clonedInitialValue","defaultValue","getValueOnSubscribe","isFlushing","itemsToFlush","getValue","push","Promise","resolve","then","observerList","subscribe","observer","unsubscribe","unSubscribeAll","createCacheableSubject","proxiedStore","store","reset","useStore","_ref2","isInitialValueSet","useRef","current","selectFieldPaths","select","selectedFieldPathsForNestedObjects","fp","includes","useLayoutEffect","setValueOnMount","err","console","error","useSyncExternalStore","onStoreChange","subscription","sc","storeChanges","onChange","some","nextChange","find","startsWith","nonReactive","defineProperty","enumerable","writable","configurable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cervello.umd.js","sources":["../src/types/shared.ts","../src/lib/utils/object.ts","../src/lib/helpers/new-proxify-store.ts","../src/lib/store/new-index.ts","../src/lib/utils/subject.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/ban-types */\nexport type WithoutType<T, V, WithNever = {\n [K in keyof T]: Exclude<T[K], undefined> extends V\n ? never\n : (T[K] extends Record<string, unknown>\n ? WithoutType<T[K], V>\n : T[K])\n}> = Pick<WithNever, {\n [K in keyof WithNever]: WithNever[K] extends never ? never : K\n}[keyof WithNever]>\n\n\n\nexport type ObjectFromAttributes<T, Attributes extends Array< keyof WithoutType<T, Function> > > = {\n [k in Attributes[number]]: T[k]\n}\n\nexport type Maybe<T> = T | undefined\n\n\n\nexport type UseSelector<T> = <Attributes extends Array< Exclude<keyof WithoutType<T, Function>, '$value'> >>(\n selectors: Attributes,\n isEqualFunction?: (previousState: ObjectFromAttributes<T, Attributes>, currentState: ObjectFromAttributes<T, Attributes>) => boolean,\n) => T\n\nexport type FieldPath<T extends Record<string, any>> = {\n [K in keyof Required<T>]: T[K] extends Record<string, any>\n ? K extends string\n\n ? T[K] extends Function\n ? never\n : T[K] extends Array<any>\n ? K\n : `${K}.*` | `${K}.${FieldPath<T[K]>}`\n : never\n : K extends string\n ? K\n : never\n}[keyof T]\n\nexport const nonReactiveObjectSymbol = Symbol('nonReactiveObject')\nexport type StoreChange<T extends Record<string, any>> = {\n change: {\n fieldPath: FieldPath<T>\n newValue: any\n previousValue: any\n }\n storeValue: T\n}\n","/* eslint-disable no-cond-assign */\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { INTERNAL_VALUE_PROP } from '../helpers/constants'\n\n\n/**\n * Clones all the provided object and nested properties and it also\n * iterates nested arrays to deepClone them\n *\n * @param obj - base object to be cloned\n * @returns new cloned object with new reference\n */\nexport function deepClone <T> (obj: T): T {\n if (!obj || typeof obj !== 'object')\n return obj\n\n let newObj = {} as any\n\n if (Array.isArray(obj)) {\n newObj = obj.map(item => deepClone(item))\n // eslint-disable-next-line no-prototype-builtins\n } else if (!obj.hasOwnProperty('$$typeof')) {\n Object.entries(obj).forEach(([key, value]) => {\n newObj[key] = deepClone(value)\n })\n Object.getOwnPropertySymbols(obj).forEach((symbol) => {\n newObj[symbol] = (obj as any)[symbol]\n })\n } else {\n newObj = obj\n }\n\n return newObj as T\n}\n\n// function copyBuffer (cur: ArrayBufferView) {\n// if (cur instanceof Buffer)\n// return Buffer.from(cur)\n//\n//\n// return new cur.constructor(cur.buffer.slice(), cur.byteOffset, cur.length)\n// }\n\n\n// INFO: From `rfdc` (really-fast-deep-clone) package for faster cloning taking care of circular references\nexport function deepClone2 <T> (obj: T): T {\n const refs: Array<any> = []\n const refsNew: Array<any> = []\n\n const constructorHandlers = new Map()\n\n constructorHandlers.set(Date, (o: string | number | Date) => new Date(o))\n constructorHandlers.set(Map, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Map(cloneArray(Array.from(o), fn)))\n constructorHandlers.set(Set, (o: Iterable<unknown> | ArrayLike<unknown>, fn: any) => new Set(cloneArray(Array.from(o), fn)))\n\n let handler = null\n\n return clone(obj)\n\n function cloneArray (a: any, fn: any): any {\n const keys = Object.keys(a)\n const a2 = new Array(keys.length) as any\n\n for (let i = 0; i < keys.length; i++) {\n const k = keys[i]\n const cur = a[k]\n\n if (typeof cur !== 'object' || cur === null) {\n a2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n a2[k] = handler(cur, fn)\n // } else if (ArrayBuffer.isView(cur)) {\n // a2[k] = copyBuffer(cur)\n } else {\n const index = refs.indexOf(cur)\n\n if (index !== -1)\n a2[k] = refsNew[index]\n else\n a2[k] = fn(cur)\n }\n }\n\n return a2\n }\n\n function clone (o: any): any {\n if (typeof o !== 'object' || o === null) return o\n if (Array.isArray(o)) return cloneArray(o, clone)\n if (o.constructor !== Object && (handler = constructorHandlers.get(o.constructor)))\n return handler(o, clone)\n\n const o2 = {} as any\n\n refs.push(o)\n refsNew.push(o2)\n\n\n Object.getOwnPropertySymbols(o).forEach((symbol) => {\n o2[symbol] = (o)[symbol]\n })\n\n for (const k in o) {\n if (!Object.hasOwnProperty.call(o, k)) continue\n const cur = o[k]\n\n\n if (typeof cur !== 'object' || cur === null) {\n o2[k] = cur\n } else if (cur.constructor !== Object && (handler = constructorHandlers.get(cur.constructor))) {\n o2[k] = handler(cur, clone)\n // } else if (ArrayBuffer.isView(cur)) {\n // o2[k] = copyBuffer(cur)\n } else {\n const i = refs.indexOf(cur)\n\n if (i !== -1)\n o2[k] = refsNew[i]\n else\n o2[k] = clone(cur)\n }\n }\n refs.pop()\n refsNew.pop()\n\n\n return o2\n }\n}\n\n/**\n * Guard to check is variable is an object\n * @param obj - variable to be checked\n * @returns boolean\n */\nexport const isObject = (obj: unknown): obj is Record<string | symbol, unknown> => (\n obj !== null\n && typeof obj === 'object'\n && !Array.isArray(obj)\n)\n\n\nexport const isReactElement = (obj: unknown): boolean => {\n if (!isObject(obj)) return false\n\n return !!(obj.$$typeof)\n}\n\n\n\nexport function isValidReactiveObject <T extends Record<string, any>> (value: T): boolean {\n return isObject(value) && !isReactElement(value) && !(value as any)[nonReactiveObjectSymbol]\n}\n\n\n\n/**\n * Returns the actual target value instead of root\n * object with internals props like $$value$$\n *\n * @param target - object from subscription or proxy\n * @returns actual value\n */\nexport const okTarget = (target: any): any => target[INTERNAL_VALUE_PROP] ?? target\n\n\n\n\n/**\n * Gets an object with just the properties requested\n * instead of the full object\n *\n * @param properties - object properties\n * @param obj - target to get the properties\n * @returns New object with just the requested properties\n */\nexport function getPartialObjectFromProperties<T> (properties: Array<keyof T>, obj: T): any {\n return properties.reduce<any>((acc, curr) => {\n acc[curr] = obj[curr]\n\n return acc\n }, {})\n}\n\n\n\nconst stringify = (obj: any): string => JSON.stringify(obj)\n\n/**\n * Compare 2 provided objects by stringing them\n * @param a - first object\n * @param b - second object\n * @returns boolean\n */\nexport const contentComparer = (a: any, b: any): boolean => stringify(a) === stringify(b)\n","\nimport { isReactElement, isValidReactiveObject } from '../utils/object'\n\nimport type { StoreChange } from '../../types/shared'\nimport type { CacheableSubject } from '../utils/subject'\n\n\n\n// @ts-expect-error - Object.hasOwn is not defined in older Safari's browsers\n('hasOwn' in Object) || (Object.hasOwn = Object.call.bind(Object.hasOwnProperty))\n\nconst ROOT_VALUE = Symbol('value')\n\n\nexport function proxifyStore <T extends Record<string | symbol, any>> (\n store$$: CacheableSubject<StoreChange<T>>,\n objectToProxify: T,\n opts: {\n nestedFieldPath?: string\n parentObjectToProxify?: any\n // beforeChange?: (storeChange: StoreChange<T>) => any\n afterChange?: (storeChange: Array<StoreChange<T>>) => void\n } = {},\n): T {\n const fieldPath = opts.nestedFieldPath ?? 'root'\n\n const objectWithRootValue = {\n [ROOT_VALUE]: objectToProxify,\n } as unknown as T\n\n const rootFunctions = fieldPath === 'root'\n ? Object.fromEntries(Object.entries(objectToProxify).filter(([,v]) => typeof v === 'function'))\n : {}\n\n return new Proxy(objectWithRootValue, {\n get (targetObject, propName, receiver) {\n // INFO: !Internal only.\n // Used to get the fieldPath of the object (it means it's a proxified object)\n if (propName === '_$fieldPath') return fieldPath\n\n const isRootTarget = Object.hasOwn(targetObject, ROOT_VALUE)\n const target = isRootTarget ? targetObject[ROOT_VALUE] : targetObject\n\n\n // Called when the object is converted to JSON or string (i.e. JSON.stringify)\n if (propName === 'toJSON') {\n return () => {\n // Remove react-elements with circular which have circular references\n // before stringifying to prevent JSON.stringify(storeProxy) from failing\n return safeToJson(target)\n // return removeCircularReferences(target)\n }\n }\n\n // Get the whole store value without the proxy\n if (propName === '$value') {\n // return getUnproxiedObject(target)\n return target\n }\n\n\n const propertyValue = Reflect.get(target, propName, receiver)\n\n if (typeof propName === 'symbol') return propertyValue\n\n if (typeof propertyValue === 'function')\n return (propertyValue as () => any).bind(receiver)\n\n\n // Check if it's correct to be a reactive object\n // & is not a circular reference or the same object\n if (isValidReactiveObject(propertyValue) && propertyValue !== target) {\n // const newNestedFieldPath = `${fieldPath}.${propName}`\n\n // If it's already a proxified object, return it\n // if (propertyValue._$fieldPath === newNestedFieldPath) return propertyValue\n if (propertyValue._$fieldPath) return propertyValue\n\n // Create a new proxified object\n const proxiedNestedObject = proxifyStore(\n store$$ as any,\n propertyValue,\n {\n nestedFieldPath: `${fieldPath}.${propName}`,\n parentObjectToProxify: opts.parentObjectToProxify ?? target,\n // beforeChange: opts.beforeChange,\n afterChange: opts.afterChange,\n },\n )\n\n return target[propName] = proxiedNestedObject\n }\n\n return propertyValue\n },\n\n\n set (parentObject, key, newValue, receiver) {\n if (typeof key === 'symbol') return true\n\n const value = newValue\n const isRootTarget = Object.hasOwn(parentObject, ROOT_VALUE)\n\n // INFO: !Internal only.\n // Used to set the value of the store without notifying the store\n if (isRootTarget && key === '$$value') {\n (parentObject as any)[ROOT_VALUE] = value\n\n return true\n }\n\n if (isRootTarget && key === '$value') {\n const previousValue = parentObject[ROOT_VALUE]\n\n if (value === previousValue) return true\n\n if (safeStringify(value) === safeStringify(previousValue)) return true\n // if (JSON.stringify(value) === JSON.stringify(previousValue)) return true\n\n if (fieldPath !== 'root') {\n (parentObject as any)[ROOT_VALUE] = value\n } else {\n (parentObject as any)[ROOT_VALUE] = {\n ...rootFunctions,\n ...value,\n }\n store$$.next({\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(targetObject[ROOT_VALUE])),\n storeValue: parentObject[ROOT_VALUE],\n change: {\n fieldPath: 'root' as any,\n newValue: value,\n previousValue,\n },\n })\n }\n\n return true\n }\n\n const realInnerObject = isRootTarget ? parentObject[ROOT_VALUE] : parentObject\n const previousValue = Reflect.get(realInnerObject, key, receiver)\n\n\n if (previousValue === value) return true\n\n\n // New object values, check if the field has already a proxy created to use it instead of reacreating a new instance\n if (isValidReactiveObject(value) && previousValue?._$fieldPath)\n previousValue.$value = value\n else\n Reflect.set(realInnerObject, key, value, realInnerObject)\n\n\n const nextStoreChange = {\n // To be disabled for performance and send same store reference\n // storeValue: JSON.parse(JSON.stringify(opts?.parentObjectToProxify ?? target)),\n storeValue: opts?.parentObjectToProxify ?? realInnerObject,\n change: {\n fieldPath: `${fieldPath}.${key}`.replace('root.', '') as any,\n newValue: value,\n previousValue,\n },\n }\n\n store$$.next(nextStoreChange)\n opts.afterChange?.([nextStoreChange])\n\n return true\n },\n\n has (t, p) {\n return Reflect.has(t[ROOT_VALUE], p)\n },\n\n ownKeys (t) {\n return Reflect.ownKeys(t[ROOT_VALUE])\n },\n\n getOwnPropertyDescriptor (t, p) {\n return Reflect.getOwnPropertyDescriptor(t[ROOT_VALUE], p)\n },\n\n })\n}\n\n//\n// function getUnproxiedObject (obj: any): any {\n// if (obj && typeof obj === 'object') {\n// if (obj[ROOT_VALUE]?.[ROOT_VALUE]) return '[Circular reference]'\n//\n// // Check if the object is a proxy\n// if (obj[ROOT_VALUE])\n// return getUnproxiedObject(obj[ROOT_VALUE])\n//\n//\n// // If it's not a proxy, return the object itself\n// return obj\n// }\n//\n// // If it's not an object, return it as is\n// return obj\n// }\n\n\nfunction safeStringify (obj: any): string {\n // use removeCircularReferences to avoid circular references\n // const cleanedObj = removeCircularReferences(obj)\n\n return JSON.stringify(\n obj,\n (_key, value) => {\n if (Array.isArray(value)) return value.map(i => safeStringify(i))\n\n if (isReactElement(value)) {\n // console.log('React element detected', value)\n\n return { props: safeStringify(value.props), type: typeof value.type === 'string' ? value.type : '' }\n }\n\n if (globalThis?.HTMLElement && value instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: value.innerHTML }\n\n // console.log('Value', value)\n\n return value\n })\n}\n\n\nfunction safeToJson (obj: any): Record<string, any> {\n const o: Record<string, any> = {}\n\n if (typeof obj !== 'object' || obj == null)\n return obj\n\n if (Array.isArray(obj))\n return obj.map(item => safeToJson(item))\n\n if (isReactElement(obj))\n return { props: safeToJson(obj.props), type: typeof obj.type === 'string' ? obj.type : '' }\n\n if (globalThis?.HTMLElement && obj instanceof globalThis.HTMLElement) return { type: '[HTMLElement]', content: obj.innerHTML }\n\n Object.entries(obj).forEach(([key, v]) => {\n o[key] = safeToJson(v)\n })\n\n return o\n}\n\n\n// function removeCircularReferences (obj: any): any {\n// const seen = new WeakSet()\n//\n// function traverse (value: any): any {\n// if (value && typeof value === 'object') {\n// // If the object has already been seen, it's a circular reference\n// if (seen.has(value))\n// return null\n//\n// seen.add(value)\n//\n// if (Array.isArray(value))\n// return value.map(traverse)\n//\n//\n// const result: any = {}\n//\n// for (const key in value) {\n// if (Object.prototype.hasOwnProperty.call(value, key)) {\n// if (key === '_owner' && value.$$typeof) continue\n//\n// result[key] = traverse(value[key])\n// }\n// }\n//\n// return result\n// }\n//\n// // Return primitive values as-is\n// return value\n// }\n//\n// return traverse(obj)\n// }\n","\nimport { useLayoutEffect, useRef, useSyncExternalStore } from 'react'\n\nimport { nonReactiveObjectSymbol } from '../../types/shared'\nimport { proxifyStore } from '../helpers/new-proxify-store'\nimport { deepClone } from '../utils/object'\nimport { createCacheableSubject } from '../utils/subject'\n\nimport type { FieldPath, StoreChange } from '../../types/shared'\n\n\n\n\n// export type CervelloOptions<StoreValue extends Record<string, any>> = {\n// beforeChange?: (storeChange: StoreChange<StoreValue>) => unknown | undefined\n// afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n// }\n\nexport type CervelloOptions<StoreValue extends Record<string, any>> = {\n afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\nexport type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {\n initialValue?: (currentStore: StoreValue) => StoreValue | null,\n setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>,\n select?:\n | Array<FieldPath<StoreValue>>\n | (() => Array<FieldPath<StoreValue>>)\n onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void\n}\n\ntype MutableStoreValue<T extends Record<string, any>> = {\n $value: T\n} & T\n\n\n\n\n\n\n\n\nexport function nonReactive <T extends Record<string, any>> (initialValue: T): T {\n Object.defineProperty(initialValue, nonReactiveObjectSymbol, {\n value: true,\n enumerable: false,\n writable: false,\n configurable: false,\n })\n\n return initialValue\n}\n\n\nexport function cervello <StoreValue extends Record<PropertyKey, any>> (\n initialValue: StoreValue,\n options?: CervelloOptions<StoreValue>,\n): {\n store: MutableStoreValue<StoreValue>,\n reset: () => void,\n useStore: (options?: CervelloUseStoreOptions<StoreValue>) => MutableStoreValue<StoreValue>\n } {\n const {\n // beforeChange,\n afterChange,\n } = options ?? {}\n\n const clonedInitialValue = (initialValue)\n const store$$ = createCacheableSubject<StoreChange<StoreValue>>(clonedInitialValue as any)\n\n const proxiedStore = proxifyStore(\n store$$ as any,\n clonedInitialValue,\n // { beforeChange, afterChange },\n { afterChange },\n ) as MutableStoreValue<StoreValue>\n\n\n return {\n store: proxiedStore,\n reset: () => {\n proxiedStore.$value = deepClone(initialValue)\n },\n useStore: (options) => {\n // const i = useId()\n const initialValue = options?.initialValue?.(proxiedStore.$value)\n const isInitialValueSet = useRef(false)\n\n if (!isInitialValueSet.current && initialValue && initialValue !== proxiedStore) {\n isInitialValueSet.current = true;\n (proxiedStore as any).$value = initialValue\n }\n\n const selectFieldPaths = useRef(\n (typeof options?.select === 'function'\n ? options?.select?.()\n : options?.select)\n ?? [],\n )\n\n const selectedFieldPathsForNestedObjects = useRef(\n selectFieldPaths.current\n .filter(fp => fp.includes('.*'))\n .map(fp => fp.replace('.*', '')),\n )\n\n\n useLayoutEffect(() => {\n if (options?.setValueOnMount) {\n void options.setValueOnMount(proxiedStore.$value).then((value) => {\n proxiedStore.$value = value\n }).catch((err) => {\n console.error('Error setting initial value on mount', err)\n })\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n\n useSyncExternalStore(\n (onStoreChange) => {\n const subscription = store$$.subscribe({\n next: (sc) => {\n // console.log('Store change', sc, i)\n const storeChanges = Array.isArray(sc)\n ? sc as Array<StoreChange<StoreValue>>\n : [sc]\n\n if (!options?.select) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n\n return\n }\n\n if (storeChanges.some(nextChange => (\n nextChange.change.fieldPath === 'root'\n || selectFieldPaths.current.includes(nextChange.change.fieldPath))\n || selectedFieldPathsForNestedObjects.current.find(fp => nextChange.change.fieldPath.startsWith(fp)),\n )) {\n onStoreChange()\n options?.onChange?.(storeChanges)\n }\n },\n })\n\n return () => {\n subscription.unsubscribe()\n }\n },\n () => store$$.getValue(),\n () => store$$.getValue(),\n )\n\n return proxiedStore\n },\n }\n}\n","\nexport type Noop = () => void\n\n\nexport type Observer<T> = {\n next: (value: T) => void\n}\n\nexport type Subscription = {\n unsubscribe: Noop\n}\n\nexport type CacheableSubject<T> = {\n getValue: () => T\n subscribe: (value: Observer<T>) => Subscription\n unSubscribeAll: Noop\n} & Observer<T>\n\n\n// const WITH_FLUSHING = true\n\nexport function createCacheableSubject<T> (defaultValue: T, getValueOnSubscribe = false): CacheableSubject<T> {\n let isFlushing = false\n let itemsToFlush: Array<T> = []\n\n let observerList: Array<Observer<T>> = []\n let value = defaultValue\n\n const getValue = (): T => value\n\n const next = (newValue: T): void => {\n value = newValue\n\n // if (!WITH_FLUSHING) {\n // observerList.forEach((o) => { o.next(newValue) })\n //\n // return\n // }\n\n itemsToFlush.push(newValue)\n // observerList.forEach((o) => { o.next(newValue) })\n\n if (!isFlushing) {\n isFlushing = true\n void Promise.resolve().then(() => {\n observerList.forEach((o) => { o.next(itemsToFlush as T) })\n itemsToFlush = []\n isFlushing = false\n })\n }\n }\n\n const subscribe = (observer: Observer<T>): Subscription => {\n // Push cached value on subscribe\n if (getValueOnSubscribe) observer.next(value)\n // Store the observer to be notified\n observerList.push(observer)\n\n return {\n unsubscribe: () => {\n observerList = observerList.filter(o => o !== observer)\n },\n }\n }\n\n const unSubscribeAll = (): void => {\n observerList = []\n }\n\n return {\n getValue,\n next,\n subscribe,\n unSubscribeAll,\n }\n}\n"],"names":["nonReactiveObjectSymbol","Symbol","deepClone","obj","Array","isArray","newObj","map","item","hasOwnProperty","Object","entries","forEach","_ref","getOwnPropertySymbols","symbol","isObject","isReactElement","$$typeof","isValidReactiveObject","value","hasOwn","call","bind","proxifyStore","store$$","objectToProxify","opts","fieldPath","nestedFieldPath","_opts$nestedFieldPath","objectWithRootValue","_objectWithRootValue","ROOT_VALUE","rootFunctions","fromEntries","filter","v","Proxy","get","targetObject","propName","receiver","target","safeToJson","propertyValue","Reflect","_opts$parentObjectToP","_$fieldPath","parentObjectToProxify","afterChange","proxiedNestedObject","set","parentObject","key","newValue","_opts$parentObjectToP2","_opts","isRootTarget","previousValue","safeStringify","next","storeValue","change","realInnerObject","$value","nextStoreChange","replace","has","t","p","ownKeys","getOwnPropertyDescriptor","JSON","stringify","_key","i","props","type","globalThis","HTMLElement","content","innerHTML","o","initialValue","options","clonedInitialValue","defaultValue","getValueOnSubscribe","isFlushing","itemsToFlush","getValue","push","Promise","resolve","then","observerList","subscribe","observer","unsubscribe","unSubscribeAll","createCacheableSubject","proxiedStore","store","reset","useStore","_ref2","isInitialValueSet","useRef","current","selectFieldPaths","select","selectedFieldPathsForNestedObjects","fp","includes","useLayoutEffect","setValueOnMount","err","console","error","useSyncExternalStore","onStoreChange","subscription","sc","storeChanges","onChange","some","nextChange","find","startsWith","nonReactive","defineProperty","enumerable","writable","configurable"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ export type CervelloOptions<StoreValue extends Record<string, any>> = {
|
|
|
3
3
|
afterChange?: (storeChange: Array<StoreChange<StoreValue>>) => void;
|
|
4
4
|
};
|
|
5
5
|
export type CervelloUseStoreOptions<StoreValue extends Record<string, any>> = {
|
|
6
|
-
initialValue?: (currentStore: StoreValue) => StoreValue |
|
|
6
|
+
initialValue?: (currentStore: StoreValue) => StoreValue | null;
|
|
7
7
|
setValueOnMount?: (currentStore: StoreValue) => Promise<StoreValue>;
|
|
8
8
|
select?: Array<FieldPath<StoreValue>> | (() => Array<FieldPath<StoreValue>>);
|
|
9
9
|
onChange?: (storeChange: Array<StoreChange<StoreValue>>) => void;
|