wana
Version:
Easy observable state for React
163 lines (152 loc) • 4.83 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var no = require('./shared/ffee02eb.js');
var is = require('@alloc/is');
var isDev = require('@alloc/is-dev');
var symbols = require('./shared/c9633b27.js');
var useChanges = require('./shared/4c241fe8.js');
var React = require('react');
require('react-layout-effect');
require('use-memo-one');
function format(message, values, styles = {}) {
const args = [];
const formatted = message.replace(/\$(\w+)/g, (_, key) => {
const value = key in styles && typeof values[key] == "object" ? JSON.stringify(values[key]) : values[key];
const style = key in styles ? styles[key] : is.is.string(value) ? "color: #5162FF" : null;
if (is.is.string(style)) {
args.push(style, String(value), "");
return "%c%s%c";
}
args.push(value);
return "%O";
});
return [formatted].concat(args);
}
let prevTime = Date.now();
function logChange(change, targetId) {
let verb;
let meta;
if (change.op == "add") {
verb = "Added";
meta = {value: change.value};
} else if (change.op == "remove") {
verb = "Removed";
meta = {oldValue: change.oldValue};
} else if (change.op == "replace") {
verb = "Replaced";
meta = {value: change.value, oldValue: change.oldValue};
} else if (change.op == "splice") {
verb = "Spliced";
meta = {value: change.value, oldValue: change.oldValue};
} else {
verb = "Cleared";
meta = {oldValue: change.oldValue};
}
console.log(...format("$verb $key of $targetId with", {
verb,
key: is.is.string(change.key) ? `"${change.key}"` : change.key,
targetId: targetId || (no.getDebug(change.target) || change.target.constructor).name
}, {
verb: "",
targetId: "color: #7BB347"
}), meta, change.target);
if (isDev.isDev && console.groupCollapsed) {
const now = Date.now();
console.groupCollapsed(`Stack trace (+${now - prevTime}ms)`);
console.trace();
console.groupEnd();
prevTime = now;
}
}
function logChanges(target, {name, onChange} = {}) {
const observable = target[symbols.$O];
if (!observable) {
throw Error("Expected an observable object");
}
const observers = observable.get(symbols.$O);
const observer = {
onChange: (change) => {
if (onChange) {
onChange(change);
}
logChange(change, name);
},
dispose: () => {
observers.delete(observer);
}
};
observers.add(observer);
return observer;
}
function useChangeLog(target, {name, onChange} = {}) {
useChanges.useChanges(target, (change) => {
if (onChange) {
onChange(change);
}
if (process.env.NODE_ENV !== "test") {
logChange(change, name);
}
});
}
function useObserverLog(name) {
const auto = no.getCurrentAuto();
if (!auto) {
throw Error('Cannot call "useObserverLog" outside a "withAuto" component');
}
React.useEffect(() => {
const {observer} = auto;
if (observer) {
const {observed} = observer;
let [message, ...args] = format("$count values were observed by $name", {count: observed.size, name: name || no.getDebug(auto).name}, {name: "color: #7BB347"});
observed.forEach(({key, owner}) => {
const [line, ...vars] = format("\n $key of $target", {
key: key == symbols.$O ? "all" : is.is.string(key) ? `"${key}"` : key,
target: owner.source
}, key == symbols.$O ? {key: ""} : void 0);
message += line;
args.push(...vars);
});
console.log(message, ...args);
}
});
}
function logRender(auto, depth, component) {
if (!component.displayName) {
console.warn('Component without "displayName" is harder to debug', component.__render || component);
}
const indent = " ".repeat(depth);
const debug = no.getDebug(auto);
console.debug(indent + "<" + debug.name + " />", "\u269B\uFE0F" + debug.renders, [
...debug.actions
]);
}
let lastComponent;
if (isDev.isDev) {
const {onRender} = symbols.globals;
symbols.globals.onRender = (auto, depth, component) => {
lastComponent = component;
if (onRender) {
onRender(auto, depth, component);
}
};
}
function useRenderLog() {
const depth = useChanges.useAutoDepth();
if (isDev.isDev) {
const auto = no.getCurrentAuto();
if (!auto || !lastComponent) {
throw Error('Cannot call "useRenderLog" outside a "withAuto" component');
}
logRender(auto, depth, lastComponent);
}
}
exports.addDebugAction = no.addDebugAction;
exports.getCurrentAuto = no.getCurrentAuto;
exports.getDebug = no.getDebug;
exports.setDebug = no.setDebug;
exports.logChange = logChange;
exports.logChanges = logChanges;
exports.useChangeLog = useChangeLog;
exports.useObserverLog = useObserverLog;
exports.useRenderLog = useRenderLog;
//# sourceMappingURL=debug.js.map