From 3cc950d8c9674a5be1d550282ef1d62fe88c3876 Mon Sep 17 00:00:00 2001 From: Ivan S Glazunov Date: Mon, 22 Jul 2024 12:44:58 +0000 Subject: [PATCH] 0.0.394 --- imports/client-handler.tsx | 203 ++++++++++++++++++++++++++++++------- imports/client.tsx | 23 +++-- package.json | 2 +- 3 files changed, 180 insertions(+), 48 deletions(-) diff --git a/imports/client-handler.tsx b/imports/client-handler.tsx index bb474572..55a1a396 100644 --- a/imports/client-handler.tsx +++ b/imports/client-handler.tsx @@ -1,6 +1,52 @@ -import { DeepClient } from './client.js'; +import { memo, useEffect, useRef, useState } from 'react'; +import { DeepClient, useDeep, useDeepSubscription } from './client.js'; import { gql } from '@apollo/client/index.js'; +import React from 'react'; +import { Id } from './minilinks.js'; + +export class CatchErrors extends React.Component<{ + error?: any; + onMounted?: (setError: (error?: any) => void) => void; + errorRenderer?: (error: Error, reset: () => any) => React.ReactNode; + reset?: () => any; + children: any; +},any> { + reset: () => any; + + constructor(props) { + super(props); + this.state = { error: undefined }; + + this.reset = () => { + this.setState({ error: undefined }); + this?.props?.reset && this?.props?.reset(); + }; + } + + static getDerivedStateFromError(error) { + console.log('getDerivedStateFromError', error); + return { error }; + } + componentDidCatch(error, errorInfo) { + console.log('componentDidCatch', error, errorInfo); + } + componentDidMounted() { + this?.props?.onMounted && this?.props?.onMounted((error) => this.setState({ error: error })); + } + + errorRenderer = (error, reset) => <>; + + render() { + const error = this.props.error || this.state.error; + if (error) { + return this?.props?.errorRenderer ? this?.props?.errorRenderer(error, this.reset) : this?.errorRenderer(error, this.reset); + } + + return this.props.children; + } +} + /** * Evaluates a client handler * @returns A promise that resolves to an object with either an error property that contains error or data property that contains result of the handler. @@ -39,40 +85,121 @@ export async function evalClientHandler(options: { return {}; } -// export async function callClientHandler({ -// linkId, -// deep, -// isolation_provider_id, -// execution_provider_id, -// }: { -// linkId: Id; -// deep: DeepClient; -// isolation_provider_id: Id; -// execution_provider_id: Id; -// }): Promise<{ -// error?: any; -// data?: any; -// }> { -// const { data: handlers } = await deep.select({ -// src_id: { _eq: linkId }, -// isolation_provider_id: { _eq: isolation_provider_id }, -// execution_provider_id: { _eq: execution_provider_id }, -// }, { -// table: 'handlers', -// returning: ` -// src_id -// dist_id -// dist { -// value -// } -// handler_id -// isolation_provider_id -// execution_provider_id -// `, -// }); -// const handler = handlers[0]; -// if (handler) return { error: '!handler' }; -// const value = handler?.dist?.value?.value; -// if (handler?.dist?.value?.value) return { error: '!value' }; -// return evalClientHandler({ value, deep }); -// } \ No newline at end of file +export const ClientHandler = memo(function ClientHandler(_props: ClientHandlerProps) { + const { + linkId, + handlerId, + context = [], + ml, + onClose, + fillSize, + error: outerError, + ErrorComponent, + ...props + } = _props; + const deep = useDeep(); + const _ml = ml || deep?.minilinks; + const hid = useFindClientHandler(_props); + const [file] = deep.useMinilinksQuery({ + id: hid?.dist_id || 0, + }); + + const [{ Component, errored } = {} as any, setState] = useState({ Component: undefined, errored: undefined }); + + // console.log('ClientHandler root', { linkId, handlerId, context, file, hid, files, Component }); + const lastEvalRef = useRef(0); + useEffect(() => { + if (!hid) return; + const value = file?.value?.value; + if (!value) { + return; + } + const evalId = ++lastEvalRef.current; + evalClientHandler({ value, deep }).then(({ data, error }) => { + if (evalId === lastEvalRef.current) { + console.log('ClientHandler evalClientHandler setState', { file, data, error }); + if (!error) { + setState(() => ({ Component: data })); + erroredResetRef?.current && (erroredResetRef?.current(), erroredResetRef.current = undefined); + } + else { + setErrorRef.current && setErrorRef.current(error); + setState({ Component: undefined, errored: error }); + } + } else { + console.log('ClientHandler evalClientHandler outdated', { file, data, error, evalId, 'lastEvalRef.current': lastEvalRef.current }); + } + }); + }, [file?.value?.value, hid]); + + const erroredResetRef = useRef(); + const setErrorRef = useRef(); + + return (<> + { + erroredResetRef.current = reset; + return + }} + onMounted={(setError) => setErrorRef.current = setError} + > + {(typeof (Component) === 'function') ? <> + {[]} + : <>} + + ); +}); +export interface ClientHandlerRendererProps { + Component: any; + fillSize?: boolean; + onClose?: () => any; + [key: string]: any; +}; + +export const ClientHandlerRenderer = React.memo(function ClientHandlerRenderer({ + Component, + fillSize = false, + onClose, + ...props +}: ClientHandlerRendererProps) { + return <>{typeof (Component) === 'function' && }; +}); + +export interface ClientHandlerProps extends Partial { + linkId: Id; + handlerId?: Id; + context?: Id[]; + ml?: any; + error?: any; + onClose?: () => any; + ErrorComponent: any; + [key: string]: any; +} + +export function useFindClientHandler({ + linkId, + handlerId, + context = [], + ml, + onClose, + fillSize, + ...props +}: ClientHandlerProps) { + const deep = useDeep(); + const [hid, setHid] = useState(); + useEffect(() => { (async () => { + if (hid) return; + const handler = await deep._findHandler({ context, handlerId }); + if (handler) setHid(handler); + })(); }, [context, handlerId, hid]); + return hid; +} \ No newline at end of file diff --git a/imports/client.tsx b/imports/client.tsx index 60df93dc..27a5344e 100644 --- a/imports/client.tsx +++ b/imports/client.tsx @@ -2118,15 +2118,20 @@ export function useDeepGenerator(generatorOptions?: DeepClientOptions>) if (!apolloClient?.jwt_token) { log({ token, apolloClient }); } - return new DeepClient({ - ...otherGeneratorOptions, - apolloClient, linkId, token, - minilinks, - handleAuth: (linkId, token) => { - setToken(token); - setLinkId(linkId); - }, - }); + try { + return new DeepClient({ + ...otherGeneratorOptions, + apolloClient, linkId, token, + minilinks, + handleAuth: (linkId, token) => { + setToken(token); + setLinkId(linkId); + }, + }); + } catch(error) { + console.error(error); + return undefined; + } }, [apolloClient]); log({deep}) return deep; diff --git a/package.json b/package.json index b943ec5c..fb4b4d88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@deep-foundation/deeplinks", - "version": "0.0.393", + "version": "0.0.394", "license": "Unlicense", "type": "module", "scripts": {