feat: gathered HMR!!

This commit is contained in:
cha0s 2021-03-26 10:51:24 -05:00
parent b525489b7e
commit 34170ed0f9
2 changed files with 67 additions and 24 deletions

View File

@ -6,6 +6,8 @@ import {camelCase} from './string';
const debug = D('@latus/core/gather'); const debug = D('@latus/core/gather');
export const hotGathered = new Map();
export const decorateWithLatus = ( export const decorateWithLatus = (
context, context,
{ {
@ -47,30 +49,11 @@ export const gatherWithLatus = (
})) }))
); );
export default ( const wrapperClass = (Class, id, idAttribute, type, typeAttribute) => {
latus,
{
type,
idAttribute = 'id',
typeAttribute = 'type',
check = () => {},
},
) => {
const gathered = latus.invokeReduce(type);
check(gathered, type);
const composed = latus.invokeComposed(`${type}.decorate`, gathered);
check(composed, `${type}.decorate`);
let uid = 1;
const fromId = {};
const fromType = Object.fromEntries(
Object.entries(composed)
.sort(([lname], [rname]) => (lname < rname ? -1 : 1))
.map(([type, Class]) => {
const thisUid = uid++;
class Subclass extends Class { class Subclass extends Class {
static get [idAttribute]() { static get [idAttribute]() {
return thisUid; return id;
} }
static get [typeAttribute]() { static get [typeAttribute]() {
@ -78,20 +61,76 @@ export default (
} }
} }
if (!Subclass.name) { return Subclass;
Subclass.name = type; };
}
fromId[thisUid] = Subclass; export default (
latus,
{
type: hook,
idAttribute = 'id',
typeAttribute = 'type',
check = () => {},
},
) => {
const raw = latus.invokeReduce(hook);
check(raw, hook);
const composed = latus.invokeComposed(`${hook}.decorate`, raw);
check(composed, `${hook}.decorate`);
let uid = 1;
const fromId = {};
const fromType = Object.fromEntries(
Object.entries(composed)
.sort(([lname], [rname]) => (lname < rname ? -1 : 1))
.map(([type, Class]) => {
const id = uid++;
const Subclass = wrapperClass(Class, id, idAttribute, type, typeAttribute);
fromId[id] = Subclass;
return [ return [
type, type,
Subclass, Subclass,
]; ];
}), }),
); );
const result = { const gathered = {
...fromId, ...fromId,
...fromType, ...fromType,
}; };
debug("gathered '%s': %O", type, result); hotGathered.set(hook, {
return result; idAttribute,
gathered,
typeAttribute,
});
debug("gathered '%s': %O", hook, gathered);
return gathered;
};
export const refresh = (path, latus) => {
const it = hotGathered.entries();
for (let current = it.next(); current.done !== true; current = it.next()) {
const {
value: [
hook,
{
idAttribute,
gathered,
typeAttribute,
},
],
} = current;
const updates = latus.invokePlugin(hook, path);
if (!updates) {
// eslint-disable-next-line no-continue
continue;
}
const entries = Object.entries(updates);
for (let i = 0; i < entries.length; ++i) {
const [type, Class] = entries[i];
const {[type]: {[idAttribute]: id}} = gathered;
const Subclass = wrapperClass(Class, id, idAttribute, type, typeAttribute);
gathered[type] = Subclass;
gathered[id] = Subclass;
latus.invoke('@latus/core/gathered/hmr', Subclass, hook);
}
}
}; };

View File

@ -1,3 +1,6 @@
// eslint-disable-next-line max-classes-per-file
import {refresh} from './gather';
export { export {
unique as arrayUnique, unique as arrayUnique,
flatten as arrayFlatten, flatten as arrayFlatten,
@ -22,5 +25,6 @@ export default {
'@latus/core/config': () => ({ '@latus/core/config': () => ({
id: 'latus', id: 'latus',
}), }),
'@latus/core/hmr': refresh,
}, },
}; };