@methodjs/store
Version:
Store for React Functional Componets
291 lines (283 loc) • 9.46 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var tslib = require('tslib');
var react = require('react');
var __ = require('..');
function createSetValueCallback(key, setValueCallbackArray) {
return function (value, payload) {
setValueCallbackArray.forEach(function (_a) {
var test = _a.test, behavior = _a.behavior;
if (test(key)) {
behavior(value, key, payload);
}
});
};
}
function createUpdateInformation(key, updateInformationArray) {
return function (information, value) {
updateInformationArray.forEach(function (_a) {
var test = _a.test, behavior = _a.behavior;
if (test(key)) {
behavior(information, value);
}
});
};
}
function createBehaviorStore() {
var setValueCallbackArray = [];
var updateInformationArray = [];
function getBehavior(key) {
return {
setValueCallback: createSetValueCallback(key, setValueCallbackArray),
updateInformation: createUpdateInformation(key, updateInformationArray),
};
}
function createBehavior(test, behavior) {
var isAlive = false;
var nextTest = function (key) {
if (isAlive) {
return test(key);
}
return false;
};
if (behavior.setValueCallback !== undefined) {
setValueCallbackArray.push({
test: nextTest,
behavior: behavior.setValueCallback,
});
}
if (behavior.updateInformation !== undefined) {
updateInformationArray.push({
test: nextTest,
behavior: behavior.updateInformation,
});
}
function startBehavior() {
isAlive = true;
}
function stopBehavior() {
isAlive = false;
}
return [startBehavior, stopBehavior];
}
return { getBehavior: getBehavior, createBehavior: createBehavior };
}
var _a = createBehaviorStore(), getBehavior = _a.getBehavior, createBehavior = _a.createBehavior;
var INITIALIZE = 'INITIALIZE';
function isSetValueAction(next) {
if (typeof next === 'function') {
return true;
}
return false;
}
function isSetValueWithMapperAction(next) {
if (typeof next === 'function') {
return true;
}
return false;
}
function isCreateStoreOptionWithMapper(option) {
if (option !== undefined &&
option.mapper !== undefined) {
return true;
}
return false;
}
function isLazyIntializedValue(next) {
if (typeof next === 'function') {
return true;
}
return false;
}
function createStore(initialValue, option) {
var current;
var key = (option === null || option === void 0 ? void 0 : option.key) || "store-".concat(Math.random());
var onValueSet = new Set();
var activatedHookIdSet = new Set();
var information = {
key: key,
transactionId: 0,
activated: false,
updated: null,
payload: null,
};
function getIntializedValue() {
if (isLazyIntializedValue(initialValue)) {
return initialValue();
}
else {
return initialValue;
}
}
function updateInformation(next, value) {
information = tslib.__assign(tslib.__assign({}, information), next);
var behavior = getBehavior(key);
behavior.updateInformation(information, value);
}
var getValue = function getValue() {
if (current === undefined) {
current = getIntializedValue();
updateInformation({
transactionId: information.transactionId + 1,
updated: new Date(),
payload: { action: INITIALIZE },
}, current);
return current;
}
else {
return current;
}
};
function subscribe(onValue) {
onValueSet.add(onValue);
function unsubscribe() {
if (onValueSet.has(onValue)) {
onValueSet.delete(onValue);
}
}
return unsubscribe;
}
function useValue() {
var _a = react.useState(getValue), state = _a[0], setState = _a[1];
react.useEffect(function () {
function onValue() {
var nextState = getValue();
setState(nextState);
}
// Hook 가 mount 되는 동안, 변경된 값으로 갱신한다.
onValue();
var unsubscribe = subscribe(onValue);
return unsubscribe;
}, []);
react.useEffect(function () {
var id = "Hook-".concat(Date.now());
activatedHookIdSet.add(id);
updateInformation({ activated: true }, getValue());
return function () {
activatedHookIdSet.delete(id);
if (activatedHookIdSet.size === 0) {
updateInformation({ activated: false }, getValue());
}
};
}, []);
return state;
}
function setValueCallback(payload) {
onValueSet.forEach(function (onValue) { return onValue(); });
updateInformation({
transactionId: information.transactionId + 1,
updated: new Date(),
payload: payload || null,
}, getValue());
var behavior = getBehavior(key);
behavior.setValueCallback(getValue(), payload);
}
if (isCreateStoreOptionWithMapper(option)) {
var mapper_1 = option.mapper;
var setValue = function setValue(next, payload) {
var pre = getValue();
if (isSetValueWithMapperAction(next)) {
current = mapper_1(next(pre), pre, payload);
}
else {
current = mapper_1(next, pre, payload);
}
setValueCallback(payload);
};
return [useValue, setValue, getValue];
}
else {
var setValue = function setValue(next, payload) {
if (isSetValueAction(next)) {
current = next(getValue());
}
else {
current = next;
}
setValueCallback(payload);
};
return [useValue, setValue, getValue];
}
}
function createQuery(query, keys) {
var onValueSet = new Set();
function test(key) {
return keys.includes(key);
}
function setValueCallback() {
onValueSet.forEach(function (onValue) { return onValue(); });
}
var startBehavior = __.createBehavior(test, { setValueCallback: setValueCallback })[0];
function subscribe(onValue) {
onValueSet.add(onValue);
function unsubscribe() {
if (onValueSet.has(onValue)) {
onValueSet.delete(onValue);
}
}
return unsubscribe;
}
function useView() {
var _a = react.useState(query()), state = _a[0], setState = _a[1];
react.useEffect(function () {
startBehavior();
function onValue() {
setState(query());
}
var unsubscribe = subscribe(onValue);
return unsubscribe;
}, []);
return state;
}
return useView;
}
function createAsyncQuery(asyncQuery, keys) {
var onValueSet = new Set();
function test(key) {
return keys.includes(key);
}
function setValueCallback() {
onValueSet.forEach(function (onValue) { return onValue(); });
}
var startBehavior = __.createBehavior(test, { setValueCallback: setValueCallback })[0];
function subscribe(onValue) {
onValueSet.add(onValue);
function unsubscribe() {
if (onValueSet.has(onValue)) {
onValueSet.delete(onValue);
}
}
return unsubscribe;
}
function useView() {
var _a = react.useState(), state = _a[0], setState = _a[1];
react.useEffect(function () {
Promise.resolve(asyncQuery()).then(setState);
startBehavior();
function onValue() {
Promise.resolve(asyncQuery()).then(setState);
}
var unsubscribe = subscribe(onValue);
return unsubscribe;
}, []);
return state;
}
return useView;
}
function createDevToolsBehavior(test) {
var updateInformation = function (information, value) {
var _a;
if (((_a = window.__METHODJS_DEV_TOOLS_WORKER__) === null || _a === void 0 ? void 0 : _a.updateStoreInformation) !== undefined) {
window.__METHODJS_DEV_TOOLS_WORKER__.updateStoreInformation(information, value);
}
};
var nextTest = test === undefined ? function () { return true; } : test;
return createBehavior(nextTest, {
updateInformation: updateInformation,
});
}
exports.createAsyncQuery = createAsyncQuery;
exports.createBehavior = createBehavior;
exports.createDevToolsBehavior = createDevToolsBehavior;
exports.createQuery = createQuery;
exports.createStore = createStore;