Skip to content

Instantly share code, notes, and snippets.

@VldMrgnn
Created August 18, 2024 09:46
Show Gist options
  • Save VldMrgnn/210171c19b1c31530b4bfbcc49366d95 to your computer and use it in GitHub Desktop.
Save VldMrgnn/210171c19b1c31530b4bfbcc49366d95 to your computer and use it in GitHub Desktop.
Get the slices that are hit by a selector using a proxy
import { createSelector } from 'starfx';
/* SELECTORS */
/**
* Creates a proxy around an object to track accessed properties.
*
* @param {object} obj - The object to create a proxy for.
* @returns {[object, Set<string>]} An array containing the proxy object and a Set of accessed property names.
*/
function trackAccesses(obj) {
const accessedProps = new Set();
const handler = {
get(target, prop) {
accessedProps.add(prop);
return target[prop];
},
};
return [new Proxy(obj, handler), accessedProps];
}
/**
* Creates a selector that captures the accessed data slices
*
* @param {*} dataSelector
* @returns {*} an array of accessed data slices
*/
export const metaSelector = (dataSelector) => {
return createSelector(
(dataState) => dataState,
(dataState) => {
try {
// Collects the accessed data slices as path-like information
const [stateProxy, accessedSlices] = trackAccesses(dataState);
// Invokes the data selector to capture relevant slices
const _ = dataSelector(stateProxy);
return Array.from(accessedSlices);
} catch (e) {
console.error(e);
return [];
}
}
);
};
const useCombineLoaders = (loaders) => {
// mocking the combine the loaders
return useLoader(loaders[0]);
}
/*
idea:
somehow we need to map the thunks to the slices (????)
> on thunk register create a thunk-key-context
> on schema slice update(add, set, remove etc), read the thunk-key-context in which the schema-slice is updated.
and create the corresponding thunk > slice map
*/
const mapOfThunks = new Map<string, keyof AppState[]>(); // or a custom slice //
const getThunksAffecting = (slice: keyof AppState) => {
const thunks = [];
for (const [key, value] of mapOfThunks) {
if (Array.isArray(value) && value.includes(slice)) {
thunks.push(key);
} else if (typeof value === 'string' && value.includes(slice)) {
thunks.push(key);
}
}
return thunks;
}
export const useMetaSelector = (selector) =>{
const loaders = []
const slices = useFxSelector(metaSelector(selector));
for (const slice of slices) {
// get the all the thunks that are hitting this slice
const thunks = getThunksAffecting(slice);
// for each of this thunks we should get the loder
for (const thunk of thunks) {
const loader = useFxLoader(thunk);
loaders.push(loader);
}
}
const aggregateLoader = useCombineLoaders(loaders);
return {
loader: aggregateLoader,
data: useFxSelector(selector)
};
}
/*
example usage:
const selectCollectedInvoices = createSelector(
schema.invoices.selectTableAsList,
schema.collections.selectTableAsList,
(invoices, collections) => {
return invoices.filter((invoice) => collections.includes(invoice.id));}
);
// we would have an aggregate loader for invoices and collections,
const { loader, data } = useMetaSelector(selectCollectedInvoices);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment