Skip to content

Commit

Permalink
remove json patch
Browse files Browse the repository at this point in the history
  • Loading branch information
rmorshea committed Jan 21, 2023
1 parent d1a69f6 commit 5461add
Show file tree
Hide file tree
Showing 19 changed files with 201 additions and 242 deletions.
32 changes: 29 additions & 3 deletions src/client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/client/packages/idom-client-react/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"author": "Ryan Morshead",
"dependencies": {
"fast-json-patch": "^3.1.1",
"htm": "^3.0.3"
"htm": "^3.0.3",
"json-pointer": "^0.6.2"
},
"description": "A client for IDOM implemented in React",
"devDependencies": {
Expand Down
26 changes: 22 additions & 4 deletions src/client/packages/idom-client-react/src/components.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from "react";
import ReactDOM from "react-dom";
import htm from "htm";
import { set as setJsonPointer } from "json-pointer";

import { useJsonPatchCallback } from "./json-patch.js";
import { useImportSource } from "./import-source.js";
import { LayoutContext } from "./contexts.js";

Expand All @@ -14,17 +14,30 @@ import {
const html = htm.bind(React.createElement);

export function Layout({ saveUpdateHook, sendEvent, loadImportSource }) {
const [model, patchModel] = useJsonPatchCallback({});
const currentModel = React.useState({})[0];
const forceUpdate = useForceUpdate();

const patchModel = React.useCallback(
({ path, model }) => {
if (!path) {
Object.assign(currentModel, model);
} else {
setJsonPointer(currentModel, path, model);
}
forceUpdate();
},
[currentModel]
);

React.useEffect(() => saveUpdateHook(patchModel), [patchModel]);

if (!Object.keys(model).length) {
if (!Object.keys(currentModel).length) {
return html`<${React.Fragment} />`;
}

return html`
<${LayoutContext.Provider} value=${{ sendEvent, loadImportSource }}>
<${Element} model=${model} />
<${Element} model=${currentModel} />
<//>
`;
}
Expand Down Expand Up @@ -200,3 +213,8 @@ function _ImportedElement({ model, importSource }) {

return html`<div ref=${mountPoint} />`;
}

function useForceUpdate() {
const [, updateState] = React.useState();
return React.useCallback(() => updateState({}), []);
}
1 change: 1 addition & 0 deletions src/client/packages/idom-client-react/src/element-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function createEventHandler(eventName, sendEvent, eventSpec) {
sendEvent({
data: data,
target: eventSpec["target"],
type: "layout-event",
});
};
}
60 changes: 0 additions & 60 deletions src/client/packages/idom-client-react/src/json-patch.js

This file was deleted.

4 changes: 2 additions & 2 deletions src/client/packages/idom-client-react/src/mount.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ function mountLayoutWithReconnectingWebSocket(
};

socket.onmessage = (event) => {
const [pathPrefix, patch] = JSON.parse(event.data);
updateHookPromise.promise.then((update) => update(pathPrefix, patch));
const message = JSON.parse(event.data);
updateHookPromise.promise.then((update) => update(message));
};

socket.onclose = (event) => {
Expand Down
6 changes: 6 additions & 0 deletions src/idom/backend/default.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import annotations

import asyncio
from logging import getLogger
from sys import exc_info
from typing import Any, NoReturn

from idom.types import RootComponentConstructor
Expand All @@ -9,6 +11,9 @@
from .utils import all_implementations


logger = getLogger(__name__)


def configure(
app: Any, component: RootComponentConstructor, options: None = None
) -> None:
Expand Down Expand Up @@ -53,6 +58,7 @@ def _default_implementation() -> BackendImplementation[Any]:
try:
implementation = next(all_implementations())
except StopIteration: # pragma: no cover
logger.debug("Backend implementation import failed", exc_info=exc_info())
raise RuntimeError("No built-in server implementation installed.")
else:
_DEFAULT_IMPLEMENTATION = implementation
Expand Down
26 changes: 11 additions & 15 deletions src/idom/backend/flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@
from idom.backend.hooks import ConnectionContext
from idom.backend.hooks import use_connection as _use_connection
from idom.backend.types import Connection, Location
from idom.core.layout import LayoutEvent, LayoutUpdate
from idom.core.serve import serve_json_patch
from idom.core.serve import serve_layout
from idom.core.types import ComponentType, RootComponentConstructor
from idom.utils import Ref

Expand Down Expand Up @@ -182,8 +181,8 @@ def model_stream(ws: WebSocket, path: str = "") -> None:
def send(value: Any) -> None:
ws.send(json.dumps(value))

def recv() -> LayoutEvent:
return LayoutEvent(**json.loads(ws.receive()))
def recv() -> Any:
return json.loads(ws.receive())

_dispatch_in_thread(
ws,
Expand All @@ -203,7 +202,7 @@ def _dispatch_in_thread(
path: str,
component: ComponentType,
send: Callable[[Any], None],
recv: Callable[[], Optional[LayoutEvent]],
recv: Callable[[], Optional[Any]],
) -> NoReturn:
dispatch_thread_info_created = ThreadEvent()
dispatch_thread_info_ref: idom.Ref[Optional[_DispatcherThreadInfo]] = idom.Ref(None)
Expand All @@ -213,18 +212,15 @@ def run_dispatcher() -> None:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

thread_send_queue: "ThreadQueue[LayoutUpdate]" = ThreadQueue()
async_recv_queue: "AsyncQueue[LayoutEvent]" = AsyncQueue()
thread_send_queue: "ThreadQueue[Any]" = ThreadQueue()
async_recv_queue: "AsyncQueue[Any]" = AsyncQueue()

async def send_coro(value: Any) -> None:
thread_send_queue.put(value)

async def recv_coro() -> Any:
return await async_recv_queue.get()

async def main() -> None:
search = request.query_string.decode()
await serve_json_patch(
await serve_layout(
idom.Layout(
ConnectionContext(
component,
Expand All @@ -239,7 +235,7 @@ async def main() -> None:
),
),
send_coro,
recv_coro,
async_recv_queue.get,
)

main_future = asyncio.ensure_future(main(), loop=loop)
Expand Down Expand Up @@ -282,9 +278,9 @@ def run_send() -> None:

class _DispatcherThreadInfo(NamedTuple):
dispatch_loop: asyncio.AbstractEventLoop
dispatch_future: "asyncio.Future[Any]"
thread_send_queue: "ThreadQueue[LayoutUpdate]"
async_recv_queue: "AsyncQueue[LayoutEvent]"
dispatch_future: asyncio.Future[Any]
thread_send_queue: ThreadQueue[Any]
async_recv_queue: AsyncQueue[Any]


@dataclass
Expand Down
18 changes: 6 additions & 12 deletions src/idom/backend/sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,8 @@
from sanic_cors import CORS

from idom.backend.types import Connection, Location
from idom.core.layout import Layout, LayoutEvent
from idom.core.serve import (
RecvCoroutine,
SendCoroutine,
Stop,
VdomJsonPatch,
serve_json_patch,
)
from idom.core.layout import Layout
from idom.core.serve import RecvCoroutine, SendCoroutine, Stop, serve_layout
from idom.core.types import RootComponentConstructor

from ._common import (
Expand Down Expand Up @@ -169,7 +163,7 @@ async def model_stream(
scope = asgi_app.transport.scope

send, recv = _make_send_recv_callbacks(socket)
await serve_json_patch(
await serve_layout(
Layout(
ConnectionContext(
constructor(),
Expand Down Expand Up @@ -198,14 +192,14 @@ async def model_stream(
def _make_send_recv_callbacks(
socket: WebSocketConnection,
) -> Tuple[SendCoroutine, RecvCoroutine]:
async def sock_send(value: VdomJsonPatch) -> None:
async def sock_send(value: Any) -> None:
await socket.send(json.dumps(value))

async def sock_recv() -> LayoutEvent:
async def sock_recv() -> Any:
data = await socket.recv()
if data is None:
raise Stop()
return LayoutEvent(**json.loads(data))
return json.loads(data)

return sock_send, sock_recv

Expand Down
Loading

0 comments on commit 5461add

Please sign in to comment.