Skip to content

Instantly share code, notes, and snippets.

@dmaretskyi
Created May 29, 2023 16:41
Show Gist options
  • Save dmaretskyi/8e580357c84a50794353b56a02ff5e39 to your computer and use it in GitHub Desktop.
Save dmaretskyi/8e580357c84a50794353b56a02ff5e39 to your computer and use it in GitHub Desktop.
const createStore = <T,> (initialValue: T): T => {
return initialValue;
}
type S<T> = T
interface Atom<T> {
// Get
(): T
}
const createAtom = <T,> (initialValue: T): Atom<T> => {
return () => initialValue;
}
const set = <T,>(storeOrAtom: T, newValue: T): void => {}
const effect = (fn: () => void) => {
}
type Subscription = {
update: (selection: any[]) => void;
}
const createSubscription = (cb: () => void): Subscription => null as any;
///////
const computed = <T,>(fn: () => T): T => {
const store = createStore(???);
effect(() => {
store.set(fn())
})
return store;
}
///////
type GraphNode = {
title: string
}
/**
CHANGE node1.title
EFFECT in getNodes(node1): children1
change children1
*/
interface GraphPlugin {
getNodes: (parent?: GraphNode) => GraphNode[]
}
////////
// type FullNode = {
// head: GraphNode
// children: GraphNode[]
// mounted: boolean
// }
// const getFullGraph = (plugins: GraphPlugin[]): FullNode[] => {
// const state = createStore<Record<string, FullNode>>({})
// // nodes, state, state[node.id]
// const insertNodes = (nodes: GraphNode[]) => {
// for(const node of nodes) {
// if(state[node.id]) {
// state[node.id].head = node;
// } else {
// state[node.id] = createStore({
// head: node,
// children: [],
// mounted: false
// })
// }
// }
// }
// // Roots effect: plugins, plugin.getNodes(), plugin.getNodes()[i], state
// effect(() => {
// for(const plugin of plugins) {
// const roots = plugin.getNodes()
// insertNodes(roots)
// }
// })
// // state
// effect(() => {
// for(const node of Object.values(state)) {
// // node, plugins
// effect(() => {
// for(const plugin of plugins) {
// const children = plugin.getNodes(node.head)
// insertNodes(children)
// }
// })
// }
// })
// return computed(() => Object.values(state))
// }
type FullNode = {
head: GraphNode | null
parent: FullNode | null
children: S<FullNode[]>
// subscription: Subscription
}
/**
* - Ignoring `plugins` being reactive
*
* TODO:
* - We iterate the map on every update
* - We don't unsubscribe when nodes get removed
*/
const getFullGraph = (plugins: GraphPlugin[]): S<FullNode[]> => {
const state = new Map<GraphNode, FullNode>() // key === value.head
const root: FullNode = {
head: null,
parent: null,
// unified node store
children: createStore([]),
}
const subscribeToNodesWithParent = (parent: FullNode) => {
for(const plugin of plugins) {
const nodes = plugin.getNodes(parent.head ?? undefined)
createSubscription(() => {
for(const node of nodes) {
if(state.has(node)) {
continue;
}
const fullNode: FullNode = {
head: node,
parent,
children: createStore([]),
}
state.set(node, fullNode)
subscribeToNodesWithParent(fullNode)
}
const newChildren = Array.from(state.values()).filter(node => node.parent === parent)
set(parent.children, newChildren)
}).update(nodes)
}
}
subscribeToNodesWithParent(root);
return root.children;
}
////
const example1: GraphPlugin = {
getNodes: (parent) => computed<GraphNode[]>(() => {
if(parent === undefined) {
return [{ title: 'foo' }]
} else {
return []
}
})
}
const example2: GraphPlugin = {
getNodes: (parent) => computed<GraphNode[]>(() => {
return parent?.title.split('').map(x => ({
title: x
})) ?? []
})
}
// createEffect(() => {
// }).react([nodes])....
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment