@prodo/core
Version:
Core package for [Prodo](https://prodo.dev). See [documentation](https://docs.prodo.dev) for more info.
227 lines • 10 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var React = require("react");
var logger_1 = require("./logger");
var utils_1 = require("./utils");
var watch_1 = require("./watch");
exports.ProdoContext = React.createContext(null);
var pathSymbol = Symbol("path");
exports.createUniverseWatcher = function (universePath) {
var readProxy = function (path) {
return new Proxy({}, {
get: function (_target, key) {
return key === pathSymbol ? path : readProxy(path.concat([key.toString()]));
},
});
};
return readProxy([universePath]);
};
var getValue = function (path, obj) {
return path.reduce(function (x, y) { return x && x[y]; }, obj);
};
var valueExtractor = function (store, watched) { return function (x) {
var path = x[pathSymbol];
var pathKey = utils_1.joinPath(path);
var value = getValue(path, store.universe);
watched[pathKey] = value;
return value;
}; };
exports.shallowEqual = function (objA, objB) {
if (Object.is(objA, objB)) {
return true;
}
if (typeof objA !== "object" ||
objA === null ||
typeof objB !== "object" ||
objB === null) {
return false;
}
var keysA = Object.keys(objA);
var keysB = Object.keys(objB);
if (keysA.length !== keysB.length) {
return false;
}
// Test for A's keys different from B.
// tslint:disable-next-line:prefer-for-of
for (var i = 0; i < keysA.length; i++) {
if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) ||
!Object.is(objA[keysA[i]], objB[keysA[i]])) {
return false;
}
}
return true;
};
var _compIdCnt = 1;
exports.connect = function (func, name) {
if (name === void 0) { name = "(anonymous)"; }
var _a;
return _a = /** @class */ (function (_super) {
__extends(ConnectComponent, _super);
function ConnectComponent(props) {
var _this = _super.call(this, props) || this;
_this.state = {};
_this.watched = {};
_this.prevWatched = {};
_this.pathNodes = {};
_this.compId = _compIdCnt++;
_this.name = name + "." + _this.compId;
_this.store = _this.context;
var setState = _this.setState.bind(_this);
_this.status = { unmounted: false };
_this.comp = {
name: _this.name,
compId: _this.compId,
};
_this.eventIdCnt = 0;
_this.subscribe = function (path, unsubscribe) {
var pathKey = utils_1.joinPath(path);
var node = _this.pathNodes[pathKey] || __assign({ pathKey: pathKey, status: _this.status, setState: setState,
unsubscribe: unsubscribe }, _this.comp);
_this.pathNodes[pathKey] = node;
watch_1.subscribe(_this.store, path, node);
};
_this.unsubscribe = function (path) {
var pathKey = utils_1.joinPath(path);
var node = _this.pathNodes[pathKey];
if (node != null) {
watch_1.unsubscribe(_this.store, path, node);
delete _this.pathNodes[pathKey];
}
};
_this._watch = function (x) { return x; };
_this._dispatch = function (func) { return function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return (_a = _this.store).exec.apply(_a, __spreadArrays([{
id: _this.comp.name + "/event." + _this.eventIdCnt++,
parentId: _this.comp.name,
},
func], args));
}; };
_this._renderFunc = function (props) {
return func(_this._viewCtx)(props);
};
logger_1.default.info("[constructing] " + _this.name);
return _this;
}
ConnectComponent.prototype.componentDidMount = function () {
var _this = this;
logger_1.default.info("[did mount] " + this.name);
Object.keys(this.watched).forEach(function (pathKey) {
logger_1.default.info("[start watching] " + _this.name + ": < " + pathKey + " >");
_this.subscribe(utils_1.splitPath(pathKey));
});
logger_1.default.debug("store", this.store);
this.prevWatched = __assign({}, this.watched);
this.setState(this.watched);
this.watched = {};
};
ConnectComponent.prototype.shouldComponentUpdate = function (nextProps, nextState) {
var test = !exports.shallowEqual(this.props, nextProps) ||
!exports.shallowEqual(this.state, nextState);
logger_1.default.info("[should update] " + this.name, test);
return test;
};
ConnectComponent.prototype.componentDidUpdate = function () {
var _this = this;
logger_1.default.info("[did update] " + this.name);
Object.keys(this.watched).forEach(function (pathKey) {
var keyExisted = _this.prevWatched.hasOwnProperty(pathKey);
if (!keyExisted) {
logger_1.default.info("[update] " + _this.name + ": now watching < " + pathKey + " >");
_this.subscribe(utils_1.splitPath(pathKey));
}
});
Object.keys(this.prevWatched).forEach(function (pathKey) {
var keyDeleted = !_this.watched.hasOwnProperty(pathKey);
if (keyDeleted) {
logger_1.default.info("[update] " + _this.name + ": stop watching < " + pathKey + " >");
_this.unsubscribe(utils_1.splitPath(pathKey));
}
});
this.prevWatched = __assign({}, this.watched);
this.watched = {};
};
ConnectComponent.prototype.componentWillUnmount = function () {
var _this = this;
logger_1.default.info("[will unmount]: " + this.name, this.state);
Object.keys(this.state).forEach(function (pathKey) {
logger_1.default.info("[unmount] " + _this.name + ": stop watching < " + pathKey + " >");
_this.unsubscribe(utils_1.splitPath(pathKey));
});
logger_1.default.debug("store", this.store);
this.status.unmounted = true;
};
ConnectComponent.prototype.render = function () {
this.createViewCtx();
var Comp = this._renderFunc;
return React.createElement(Comp, __assign({}, this.props));
};
ConnectComponent.prototype.createViewCtx = function () {
var _this = this;
this.store = this.context;
this._state = exports.createUniverseWatcher("state");
this._watch = valueExtractor(this.store, this.watched);
var subscribe = function (path, unsubscribe) {
var pathKey = utils_1.joinPath(path);
_this.watched[pathKey] = getValue(path, _this.store.universe);
_this.subscribe(path, unsubscribe);
};
var ctx = {
dispatch: this._dispatch,
state: this._state,
watch: this._watch,
subscribe: subscribe,
};
this.store.plugins.forEach(function (p) {
if (p._internals.viewCtx) {
ctx.dispatch = _this._dispatch;
p._internals.viewCtx({
ctx: ctx,
universe: _this.store.universe,
comp: _this.comp,
}, _this.store.config);
}
});
this._viewCtx = ctx;
};
return ConnectComponent;
}(React.Component)),
_a.contextType = exports.ProdoContext,
_a;
};
//# sourceMappingURL=connect.js.map