@xyo-network/react-node
Version:
Common React library for all XYO projects that use React
456 lines (425 loc) • 18.4 kB
JavaScript
// src/components/NodeDescriptionBox.tsx
import { FlexCol } from "@xylabs/react-flexbox";
// src/hooks/getModuleFilterOptions.ts
var getModuleFilterOptions = (config) => {
const {
direction,
identity,
maxDepth
} = config ?? {};
return {
direction,
identity,
maxDepth
};
};
// src/hooks/getWeakModuleFilterOptions.ts
var getWeakModuleFilterOptions = (config) => {
const {
direction,
identity,
maxDepth
} = config ?? {};
return {
direction,
identity,
maxDepth
};
};
// src/hooks/ModuleFromNodeConfig.ts
var getModuleFromNodeConfigLogger = (config) => {
return config?.logger;
};
// src/hooks/provided/useProvidedNode.tsx
import { NodeContext } from "@xyo-network/react-node-context";
import { use } from "react";
var useProvidedNode = () => {
const { node } = use(NodeContext);
return [node];
};
// src/hooks/provided/useWeakProvidedNode.tsx
import { NodeContext as NodeContext2 } from "@xyo-network/react-node-context";
import { use as use2, useMemo } from "react";
var useWeakProvidedNode = () => {
const { node } = use2(NodeContext2);
const weakNode = useMemo(() => node ? new WeakRef(node) : null, [node]);
return [weakNode];
};
// src/hooks/useModuleFromNode.ts
import { usePromise as usePromise2 } from "@xylabs/react-promise";
import { isModuleInstance } from "@xyo-network/module-model";
import { useState } from "react";
// src/hooks/useNode.ts
import { usePromise } from "@xylabs/react-promise";
import { asNodeInstance } from "@xyo-network/node-model";
// src/hooks/useNodeConfigNodeField.ts
import { useMemo as useMemo2 } from "react";
var useNodeConfigNodeField = (config) => {
const nodeAddress = useMemo2(() => typeof config?.node === "string" ? config?.node : void 0, [config?.node]);
const nodeInstance = useMemo2(() => typeof config?.node === "object" ? config?.node : void 0, [config?.node]);
return [nodeAddress, nodeInstance];
};
// src/hooks/useNode.ts
var useNode = (config) => {
const [nodeAddress, nodeInstance] = useNodeConfigNodeField(config);
const [providedNode] = useProvidedNode();
const [nodeAddressNode, error] = usePromise(async () => {
if (providedNode && nodeAddress) {
return asNodeInstance(await providedNode.resolve(nodeAddress), "Module is not a node");
}
}, [providedNode, nodeAddress]);
return [nodeAddressNode ?? nodeInstance ?? providedNode ?? void 0, error];
};
// src/hooks/useModuleFromNode.ts
var useModuleFromNode = (nameOrAddressOrInstance = void 0, config) => {
const [node, nodeError] = useNode(config);
const logger = getModuleFromNodeConfigLogger(config);
const filterOptions = getModuleFilterOptions(config);
const [result, setResult] = useState();
const [, error] = usePromise2(async () => {
logger?.debug("useModuleFromNode: resolving");
const identity = config?.identity ?? isModuleInstance;
if (node && nameOrAddressOrInstance) {
node.on("moduleAttached", ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`);
if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) {
setResult(identity(mod) ? mod : void 0);
}
});
node.on("moduleDetached", ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`);
if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) {
setResult(void 0);
}
});
if (identity(nameOrAddressOrInstance)) {
setResult(nameOrAddressOrInstance);
} else {
const result2 = await node.resolve(nameOrAddressOrInstance, filterOptions);
logger?.debug(`Result: ${result2?.address}`);
setResult(identity(result2) ? result2 : void 0);
}
return result;
}
logger?.debug("Result: No Node");
}, [node, nameOrAddressOrInstance]);
return [result, nodeError ?? error];
};
// src/hooks/useModulesFromNode.ts
import { exists } from "@xylabs/exists";
import { usePromise as usePromise3 } from "@xylabs/react-promise";
import { useState as useState2 } from "react";
var useModulesFromNode = (ids, config) => {
const [node, nodeError] = useNode(config);
const logger = config?.logger;
const filterOptions = getModuleFilterOptions();
const [result, setResult] = useState2();
const [, error] = usePromise3(async () => {
logger?.debug("useModuleFromNode: resolving");
if (node) {
const refreshModules = async () => {
const moduleInstances = ids ? (await Promise.all(ids.map((id) => node.resolve(id, filterOptions)))).filter(exists) : await node.resolve("*", filterOptions);
setResult(moduleInstances);
return moduleInstances;
};
node.on("moduleAttached", async ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`);
await refreshModules();
});
node.on("moduleDetached", async ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`);
await refreshModules();
});
return await refreshModules();
}
console.log("Result: No Node");
}, [node, ids]);
return [result, nodeError ?? error];
};
// src/hooks/useNodeDescription.ts
import { usePromise as usePromise4 } from "@xylabs/react-promise";
import { ModuleDescriptionSchema } from "@xyo-network/module-model";
import { isPayloadOfSchemaType } from "@xyo-network/payload-model";
var useNodeDescription = (config) => {
const [activeNode, nodeError] = useNode(config);
const [description, error] = usePromise4(async () => {
const state = await activeNode?.state();
return state?.find(isPayloadOfSchemaType(ModuleDescriptionSchema));
}, [activeNode]);
return [description, nodeError ?? error];
};
// src/hooks/useNodeFromNode.tsx
import { asNodeInstance as asNodeInstance2 } from "@xyo-network/node-model";
var useNodeFromNode = (nameOrAddressOrInstance, config) => {
const [mod, error] = useModuleFromNode(nameOrAddressOrInstance, config);
const instance = asNodeInstance2(mod);
if (mod && !instance) {
const error2 = new Error(`Resolved module is not a NodeInstance [${mod.config?.schema}:${mod.config?.name}:${mod.address}]`);
console.error(error2.message);
return [void 0, error2];
}
return [instance, error];
};
// src/hooks/useNodesFromNode.tsx
import { isNodeInstance } from "@xyo-network/node-model";
var useNodesFromNode = (ids, config) => {
const [modules, error] = useModulesFromNode(ids, config);
if (error) {
return [null, error];
}
return modules ? [
// eslint-disable-next-line unicorn/no-array-reduce
modules.reduce((prev, mod) => {
if (isNodeInstance(mod)) {
prev.push(mod);
}
return prev;
}, []),
void 0
] : [modules, error];
};
// src/hooks/useWeakModuleFromNode.ts
import { usePromise as usePromise6 } from "@xylabs/react-promise";
import { isModuleInstance as isModuleInstance2 } from "@xyo-network/module-model";
import { useState as useState3 } from "react";
// src/hooks/useWeakNode.ts
import { usePromise as usePromise5 } from "@xylabs/react-promise";
import { isDefined } from "@xylabs/typeof";
import { asNodeInstance as asNodeInstance3 } from "@xyo-network/node-model";
// src/hooks/useWeakNodeConfigNodeField.ts
import { useMemo as useMemo3 } from "react";
var useWeakNodeConfigNodeField = (config) => {
const nodeAddress = useMemo3(() => typeof config?.node === "string" ? config?.node : void 0, [config?.node]);
const nodeInstance = useMemo3(() => typeof config?.node === "object" ? config?.node : void 0, [config?.node]);
return [nodeAddress, nodeInstance];
};
// src/hooks/useWeakNode.ts
var useWeakNode = (config) => {
const [nodeAddress, nodeInstance] = useWeakNodeConfigNodeField(config);
const [providedNode] = useWeakProvidedNode();
const [nodeAddressNode, error] = usePromise5(async () => {
const providedNodeInstance = providedNode?.deref();
if (providedNodeInstance && isDefined(nodeAddress)) {
return new WeakRef(asNodeInstance3(await providedNodeInstance.resolve(nodeAddress), () => "Module is not a node", { required: true }));
}
}, [providedNode, nodeAddress]);
return [nodeAddressNode ?? nodeInstance ?? providedNode ?? void 0, error];
};
// src/hooks/WeakModuleFromNodeConfig.ts
var getWeakModuleFromNodeConfigLogger = (config) => {
return config?.logger;
};
// src/hooks/useWeakModuleFromNode.ts
var useWeakModuleFromNode = (nameOrAddressOrInstance = void 0, config) => {
const [node, nodeError] = useWeakNode(config);
const logger = getWeakModuleFromNodeConfigLogger(config);
const filterOptions = getWeakModuleFilterOptions(config);
const [result, setResult] = useState3();
const [, error] = usePromise6(async () => {
logger?.debug("useModuleFromNode: resolving");
const identity = config?.identity ?? isModuleInstance2;
const nodeInstance = node?.deref();
if (nodeInstance && nameOrAddressOrInstance) {
nodeInstance.on("moduleAttached", ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`);
if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) {
setResult(identity(mod) ? new WeakRef(mod) : void 0);
}
});
nodeInstance.on("moduleDetached", ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`);
if (mod.address === nameOrAddressOrInstance || mod.config?.name === nameOrAddressOrInstance) {
setResult(void 0);
}
});
if (identity(nameOrAddressOrInstance)) {
setResult(new WeakRef(nameOrAddressOrInstance));
} else {
const result2 = await nodeInstance.resolve(nameOrAddressOrInstance, filterOptions);
logger?.debug(`Result: ${result2?.address}`);
setResult(identity(result2) ? new WeakRef(result2) : void 0);
}
return result;
}
logger?.debug("Result: No Node");
}, [node, nameOrAddressOrInstance]);
return [result, nodeError ?? error];
};
// src/hooks/useWeakModulesFromNode.ts
import { exists as exists2 } from "@xylabs/exists";
import { usePromise as usePromise7 } from "@xylabs/react-promise";
import { useState as useState4 } from "react";
var useWeakModulesFromNode = (ids, config) => {
const [node, nodeError] = useNode(config);
const logger = config?.logger;
const filterOptions = getModuleFilterOptions();
const [result, setResult] = useState4();
const [, error] = usePromise7(async () => {
logger?.debug("useModuleFromNode: resolving");
const nodeInstance = node;
if (nodeInstance) {
const refreshModules = async () => {
const moduleInstances = ids ? (await Promise.all(ids.map((id) => node.resolve(id, filterOptions)))).filter(exists2) : await node.resolve("*", filterOptions);
setResult(moduleInstances.map((mod) => new WeakRef(mod)));
return moduleInstances;
};
nodeInstance.on("moduleAttached", async ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleAttached [${mod.config.name ?? mod.address}]`);
await refreshModules();
});
nodeInstance.on("moduleDetached", async ({ mod }) => {
logger?.debug(`useModuleFromNode: moduleDetached [${mod.config.name ?? mod.address}]`);
await refreshModules();
});
return await refreshModules();
}
console.log("Result: No Node");
return;
}, [node, ids]);
return [result, nodeError ?? error];
};
// src/hooks/useWeakNodeDescription.ts
import { usePromise as usePromise8 } from "@xylabs/react-promise";
import { ModuleDescriptionSchema as ModuleDescriptionSchema2 } from "@xyo-network/module-model";
import { isPayloadOfSchemaType as isPayloadOfSchemaType2 } from "@xyo-network/payload-model";
var useWeakNodeDescription = (config) => {
const [activeNode, nodeError] = useWeakNode(config);
const [description, error] = usePromise8(async () => {
const state = await activeNode?.deref()?.state();
return state?.find(isPayloadOfSchemaType2(ModuleDescriptionSchema2));
}, [activeNode]);
return [description, nodeError ?? error];
};
// src/hooks/useWeakNodeFromNode.tsx
import { isNodeInstance as isNodeInstance2 } from "@xyo-network/node-model";
var useWeakNodeFromNode = (nameOrAddressOrInstance, config) => {
return useWeakModuleFromNode(nameOrAddressOrInstance, { identity: isNodeInstance2, ...config });
};
// src/components/NodeDescriptionBox.tsx
import { jsx } from "react/jsx-runtime";
var NodeDescriptionBox = ({ node, ...props }) => {
const [description, error] = useWeakNodeDescription({ node });
return /* @__PURE__ */ jsx(FlexCol, { ...props, children: /* @__PURE__ */ jsx("code", { color: error ? "red" : void 0, children: error ? error.message : JSON.stringify(description, null, 2) }) });
};
// src/components/Node.tsx
import { jsx as jsx2 } from "react/jsx-runtime";
var NodeBox = ({ variant, ...props }) => {
switch (variant) {
// eslint-disable-next-line unicorn/no-useless-switch-case
case "description":
default: {
return /* @__PURE__ */ jsx2(NodeDescriptionBox, { ...props });
}
}
};
// src/components/NodeDrawer.tsx
import { Close as CloseIcon } from "@mui/icons-material";
import {
ClickAwayListener,
Drawer,
IconButton
} from "@mui/material";
import { FlexGrowCol, FlexRow } from "@xylabs/react-flexbox";
import { useNodeDrawer } from "@xyo-network/react-node-provider";
// src/components/render/ModuleDescriptionBox.tsx
import { ChevronRight as ChevronRightIcon, ExpandMore as ExpandMoreIcon } from "@mui/icons-material";
import { styled as styled2, Typography } from "@mui/material";
import { SimpleTreeView } from "@mui/x-tree-view";
import { useRef } from "react";
// src/components/render/RenderModule.tsx
import { styled } from "@mui/material";
import { TreeItem } from "@mui/x-tree-view";
import { useAsyncEffect } from "@xylabs/react-async-effect";
import { useState as useState5 } from "react";
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
var RenderModule = ({ mod, idRef }) => {
const [childModules, setChildModules] = useState5();
useAsyncEffect(
async (mounted) => {
const moduleInstance2 = mod.deref();
const { address: address2 } = moduleInstance2 ?? {};
if (moduleInstance2) {
const children = (await moduleInstance2.resolve("*")).filter((childModule) => childModule.address !== address2);
if (mounted()) {
setChildModules(children.map((childModule) => new WeakRef(childModule)));
}
}
},
[mod]
);
const increment = () => {
const newId = (idRef.current.idIncrementor++).toString();
idRef.current.ids.push(newId);
return newId;
};
const moduleInstance = mod.deref();
const { queries, address } = moduleInstance ?? {};
return /* @__PURE__ */ jsxs(StyledAddressTreeItem, { itemId: increment(), label: `address: ${address}`, children: [
queries?.map((query, index) => {
return /* @__PURE__ */ jsx3(TreeItem, { itemId: increment(), label: `query : ${query}`, sx: { mb: index === queries.length - 1 ? 1.5 : 0.5 } }, query);
}),
childModules && childModules.length > 0 ? /* @__PURE__ */ jsx3(TreeItem, { itemId: increment(), label: "children", sx: { mb: 0.5 }, children: childModules.map((childModuleRef) => {
const childModule = childModuleRef.deref();
return childModule ? /* @__PURE__ */ jsx3(RenderModule, { mod: childModuleRef, idRef }, childModule?.address) : null;
}) }) : null
] });
};
var StyledAddressTreeItem = styled(TreeItem, { name: "StyledAddressTreeItem" })(({ theme }) => ({ "& .MuiTreeItem-content": { marginBottom: theme.spacing(0.25) } }));
// src/components/render/ModuleDescriptionBox.tsx
import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
var ModuleDescriptionBox = ({ mod }) => {
const idRef = useRef({ idIncrementor: 0, ids: [] });
return /* @__PURE__ */ jsx4(Fragment, { children: mod ? /* @__PURE__ */ jsxs2(Fragment, { children: [
/* @__PURE__ */ jsx4(Typography, { variant: "h4", children: "Node Configuration" }),
/* @__PURE__ */ jsx4(
StyledTreeView,
{
"aria-label": "file system navigator",
slots: { collapseIcon: ExpandMoreIcon, expandIcon: ChevronRightIcon },
sx: { flexGrow: 1 },
children: /* @__PURE__ */ jsx4(RenderModule, { mod, idRef })
}
)
] }) : mod === null ? /* @__PURE__ */ jsx4(Typography, { variant: "h4", children: "Node loading..." }) : /* @__PURE__ */ jsx4(Typography, { variant: "h4", children: "Node not found" }) });
};
var StyledTreeView = styled2(SimpleTreeView, { name: "StyledTreeView" })(() => ({
height: "auto",
maxWidth: "auto"
}));
// src/components/NodeDrawer.tsx
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
var NodeDrawer = ({ children, ...props }) => {
const { open, setOpen } = useNodeDrawer();
const [node] = useWeakProvidedNode();
return /* @__PURE__ */ jsx5(Drawer, { open: open ?? false, anchor: "right", ...props, children: /* @__PURE__ */ jsx5(ClickAwayListener, { onClickAway: () => setOpen?.(false), children: /* @__PURE__ */ jsxs3(FlexGrowCol, { role: "presentation", justifyContent: "start", p: 2, rowGap: 2, minWidth: "33vw", children: [
/* @__PURE__ */ jsx5(FlexRow, { alignContent: "start", justifyContent: "start", width: "100%", children: /* @__PURE__ */ jsx5(IconButton, { onClick: () => setOpen?.(false), children: /* @__PURE__ */ jsx5(CloseIcon, {}) }) }),
/* @__PURE__ */ jsx5(ModuleDescriptionBox, { mod: node }),
children
] }) }) });
};
// src/index.ts
export * from "@xyo-network/react-node-context";
export * from "@xyo-network/react-node-provider";
export {
NodeBox,
NodeDrawer,
getModuleFilterOptions,
getModuleFromNodeConfigLogger,
getWeakModuleFilterOptions,
getWeakModuleFromNodeConfigLogger,
useModuleFromNode,
useModulesFromNode,
useNode,
useNodeConfigNodeField,
useNodeDescription,
useNodeFromNode,
useNodesFromNode,
useProvidedNode,
useWeakModuleFromNode,
useWeakModulesFromNode,
useWeakNodeConfigNodeField,
useWeakNodeDescription,
useWeakNodeFromNode,
useWeakProvidedNode
};
//# sourceMappingURL=index.mjs.map