@playfast/reform-remote 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +33 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +97 -0
- package/dist/client.js.map +1 -0
- package/dist/clientBinding.d.ts +18 -0
- package/dist/clientBinding.d.ts.map +1 -0
- package/dist/clientBinding.js +70 -0
- package/dist/clientBinding.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/memory.d.ts +7 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +21 -0
- package/dist/memory.js.map +1 -0
- package/dist/react.d.ts +15 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +16 -0
- package/dist/react.js.map +1 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +56 -0
- package/dist/server.js.map +1 -0
- package/dist/transport.d.ts +41 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +157 -0
- package/dist/transport.js.map +1 -0
- package/dist/wireNode.d.ts +24 -0
- package/dist/wireNode.d.ts.map +1 -0
- package/dist/wireNode.js +80 -0
- package/dist/wireNode.js.map +1 -0
- package/dist/wireRender.d.ts +20 -0
- package/dist/wireRender.d.ts.map +1 -0
- package/dist/wireRender.js +118 -0
- package/dist/wireRender.js.map +1 -0
- package/package.json +17 -5
- package/src/client-prop-decode.test.ts +98 -0
- package/src/client.ts +25 -9
- package/src/clientBinding.ts +103 -0
- package/src/counterFixtures.ts +142 -0
- package/src/fixtures.ts +10 -453
- package/src/listFixtures.ts +174 -0
- package/src/optionalFixtures.ts +64 -0
- package/src/react.ts +14 -3
- package/src/server.test.ts +6 -6
- package/src/server.ts +11 -349
- package/src/slottedFixtures.ts +120 -0
- package/src/transport.ts +15 -47
- package/src/wire-id-uniqueness.test.ts +287 -0
- package/src/wire-identity.test.ts +369 -0
- package/src/wire-keyed-identity.test.ts +434 -0
- package/src/wireNode.ts +153 -0
- package/src/wireRender.ts +249 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type MadeView, type UiContract } from '@playfast/reform';
|
|
3
|
+
import { type AnyUi, type UiReflection, type WiredUiManifest, type WireTree } from '@playfast/reform/internal';
|
|
4
|
+
export interface SlotPropsExternalApi {
|
|
5
|
+
readonly slotKey?: string;
|
|
6
|
+
}
|
|
7
|
+
export type RemoteView = (props: Record<string, unknown>, slots: Record<string, (slotProps?: SlotPropsExternalApi) => ReactNode>, events: Record<string, (payload: unknown) => void>) => ReactNode;
|
|
8
|
+
export interface RegisteredRemoteView {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly view: RemoteView;
|
|
11
|
+
}
|
|
12
|
+
type ViewRegistry = Readonly<Record<string, RegisteredRemoteView>>;
|
|
13
|
+
declare const ViewSetContract: unique symbol;
|
|
14
|
+
export type RemoteViewSet<C extends RemoteContract> = ViewRegistry & {
|
|
15
|
+
readonly [ViewSetContract]: (contract: C) => C;
|
|
16
|
+
};
|
|
17
|
+
type RemoteUi = UiReflection<UiContract, string> & AnyUi & {
|
|
18
|
+
readonly manifest: WiredUiManifest;
|
|
19
|
+
};
|
|
20
|
+
export type RemoteContract = Readonly<Record<string, RemoteUi>>;
|
|
21
|
+
export declare const remoteContract: <const C extends RemoteContract>(contract: C) => C;
|
|
22
|
+
type RemoteViewFor<U extends RemoteUi> = U extends UiReflection<infer Contract, infer Name> ? MadeView<Contract, Name, U> : never;
|
|
23
|
+
export type RemoteViews<C extends RemoteContract> = {
|
|
24
|
+
readonly [K in keyof C]: RemoteViewFor<C[K]>;
|
|
25
|
+
};
|
|
26
|
+
export declare const remoteViews: <C extends RemoteContract>(views: RemoteViews<C>) => RemoteViewSet<C>;
|
|
27
|
+
export interface ClientConfig<C extends RemoteContract> {
|
|
28
|
+
readonly views: RemoteViewSet<C>;
|
|
29
|
+
readonly invoke: (handle: string, payload: unknown) => void;
|
|
30
|
+
}
|
|
31
|
+
export declare const renderWireTree: <C extends RemoteContract>(tree: WireTree, config: ClientConfig<C>) => ReactNode;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,SAAS,EAAU,MAAM,OAAO,CAAA;AAEvE,OAAO,EAAE,KAAK,QAAQ,EAAM,KAAK,UAAU,EAAiC,MAAM,kBAAkB,CAAA;AACpG,OAAO,EAEL,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,eAAe,EAGpB,KAAK,QAAQ,EACd,MAAM,2BAA2B,CAAA;AAElC,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,MAAM,MAAM,UAAU,GAAG,CACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE,oBAAoB,KAAK,SAAS,CAAC,EACtE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC,KAC/C,SAAS,CAAA;AAEd,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAC1B;AAED,KAAK,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAAA;AAElE,QAAA,MAAM,eAAe,EAAE,OAAO,MAAsD,CAAA;AAEpF,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,cAAc,IAAI,YAAY,GAAG;IACnE,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAA;CAC/C,CAAA;AAED,KAAK,QAAQ,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,KAAK,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,CAAA;AACjG,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAA;AAE/D,eAAO,MAAM,cAAc,GAAI,KAAK,CAAC,CAAC,SAAS,cAAc,EAAE,UAAU,CAAC,KAAG,CAAa,CAAA;AAE1F,KAAK,aAAa,CAAC,CAAC,SAAS,QAAQ,IACnC,CAAC,SAAS,YAAY,CAAC,MAAM,QAAQ,EAAE,MAAM,IAAI,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,KAAK,CAAA;AAC1F,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,cAAc,IAAI;IAClD,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7C,CAAA;AAoDD,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,cAAc,EAAE,OAAO,WAAW,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAS5F,CAAA;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,cAAc;IACpD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAChC,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CAC5D;AAqFD,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,cAAc,EACrD,MAAM,QAAQ,EACd,QAAQ,YAAY,CAAC,CAAC,CAAC,KACtB,SAOA,CAAA"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { createElement, Fragment, useRef } from 'react';
|
|
2
|
+
import { Effect, Option, Record as Rec, Schema } from 'effect';
|
|
3
|
+
import { Ui, UiViewContract } from '@playfast/reform';
|
|
4
|
+
import { Wire, } from '@playfast/reform/internal';
|
|
5
|
+
const ViewSetContract = Symbol.for('reform-remote/view-set-contract');
|
|
6
|
+
export const remoteContract = (contract) => contract;
|
|
7
|
+
function bindSlots(slots) {
|
|
8
|
+
return slots;
|
|
9
|
+
}
|
|
10
|
+
function bindEvents(events) {
|
|
11
|
+
return events;
|
|
12
|
+
}
|
|
13
|
+
const registerView = (view) => view.capture((exact) => {
|
|
14
|
+
const contract = exact[UiViewContract];
|
|
15
|
+
const propsReflection = contract.manifest.props;
|
|
16
|
+
if (propsReflection === undefined) {
|
|
17
|
+
return Effect.runSync(Effect.dieMessage(`reform-remote: view ${contract.manifest.name} needs a wire props schema`));
|
|
18
|
+
}
|
|
19
|
+
const propsSchema = Schema.make(propsReflection.ast);
|
|
20
|
+
const decodeProps = Schema.decodeUnknownOption(propsSchema);
|
|
21
|
+
return {
|
|
22
|
+
name: contract.manifest.name,
|
|
23
|
+
// Props off the wire are untrusted — the envelope types a data prop as
|
|
24
|
+
// `Schema.Unknown`, so version skew against a differently-shaped server first
|
|
25
|
+
// shows up here, inside React's render phase. A throw would take the whole tree
|
|
26
|
+
// down; this node costs itself, which is what an unregistered node name already
|
|
27
|
+
// does one level up.
|
|
28
|
+
view: (encoded, slots, events) => Option.match(decodeProps(encoded), {
|
|
29
|
+
onNone: () => {
|
|
30
|
+
Effect.runSync(Effect.logWarning(`reform-remote: dropped node '${contract.manifest.name}' — props do not match its wire schema`));
|
|
31
|
+
return null;
|
|
32
|
+
},
|
|
33
|
+
onSome: (props) => exact(props, bindSlots(slots), bindEvents(events)),
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
export const remoteViews = (views) => {
|
|
38
|
+
const madeViews = Object.values(views);
|
|
39
|
+
const byName = Rec.fromEntries(madeViews.map((view) => {
|
|
40
|
+
const entry = registerView(view);
|
|
41
|
+
return [entry.name, entry];
|
|
42
|
+
}));
|
|
43
|
+
return { ...byName, [ViewSetContract]: (contract) => contract };
|
|
44
|
+
};
|
|
45
|
+
const WireNodeView = ({ node, tree, config }) => {
|
|
46
|
+
// Stable slot closures read current inputs through this ref.
|
|
47
|
+
const latest = useRef({ node, tree, config });
|
|
48
|
+
latest.current = { node, tree, config };
|
|
49
|
+
// Fresh slot component types remount descendants and reset their hooks.
|
|
50
|
+
const slotCache = useRef({});
|
|
51
|
+
const registered = config.views[node.name];
|
|
52
|
+
if (registered === undefined) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const encoded = Rec.fromEntries(node.props.flatMap((prop) => prop._tag === 'Data' ? [[prop.name, prop.value]] : []));
|
|
56
|
+
const eventEntries = node.props.flatMap((prop) => {
|
|
57
|
+
if (prop._tag !== 'Event') {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
return [[prop.name, (payload) => config.invoke(prop.handle, payload)]];
|
|
61
|
+
});
|
|
62
|
+
const events = Rec.fromEntries(eventEntries);
|
|
63
|
+
// slotKey selects one wire child; omitting it renders every child in the slot.
|
|
64
|
+
const slotFor = (slotName) => {
|
|
65
|
+
const cached = slotCache.current[slotName];
|
|
66
|
+
if (cached !== undefined) {
|
|
67
|
+
return cached;
|
|
68
|
+
}
|
|
69
|
+
const stable = (slotProps) => {
|
|
70
|
+
const { node: currentNode, tree: currentTree, config: currentConfig } = latest.current;
|
|
71
|
+
const requestedKey = slotProps?.slotKey;
|
|
72
|
+
return createElement(Fragment, null, ...Wire.childrenOf(currentTree, currentNode.id)
|
|
73
|
+
.filter((child) => child.slot === slotName)
|
|
74
|
+
.filter((child) => requestedKey === undefined || child.key === requestedKey)
|
|
75
|
+
.map((child) => createElement(WireNodeView, {
|
|
76
|
+
// Reconcile on the semantic key when the server sent one: node ids are
|
|
77
|
+
// positional, so a reorder would otherwise slide item state between rows.
|
|
78
|
+
// Matches the local host, which keys by `placement.key`.
|
|
79
|
+
// The node id, not the app's key: ids are derived from the key and so are
|
|
80
|
+
// stable across a reorder, but unlike a key they are unique by construction.
|
|
81
|
+
key: child.id,
|
|
82
|
+
node: child,
|
|
83
|
+
tree: currentTree,
|
|
84
|
+
config: currentConfig,
|
|
85
|
+
})));
|
|
86
|
+
};
|
|
87
|
+
slotCache.current[slotName] = stable;
|
|
88
|
+
return stable;
|
|
89
|
+
};
|
|
90
|
+
// Empty slots must still produce a callable component, not an invalid undefined element type.
|
|
91
|
+
const slots = new Proxy(Object.create(null), {
|
|
92
|
+
get: (_target, key) => (typeof key === 'string' ? slotFor(key) : undefined),
|
|
93
|
+
});
|
|
94
|
+
return registered.view(encoded, slots, events);
|
|
95
|
+
};
|
|
96
|
+
export const renderWireTree = (tree, config) => createElement(Fragment, null, ...Wire.roots(tree).map((node) => createElement(WireNodeView, { key: node.id, node, tree, config })));
|
|
97
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type WireTree } from '@playfast/reform/internal';
|
|
3
|
+
import { type RemoteContract, type RemoteViewSet } from './client.js';
|
|
4
|
+
import type { InvokeMessage, RemoteTransport, ServerMessage } from './transport.js';
|
|
5
|
+
export interface ClientBinding {
|
|
6
|
+
readonly node: () => ReactNode;
|
|
7
|
+
readonly subscribe: (listener: () => void) => () => void;
|
|
8
|
+
readonly snapshot: () => WireTree;
|
|
9
|
+
readonly dispose: () => void;
|
|
10
|
+
readonly close: () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface ConnectOptions<C extends RemoteContract> {
|
|
13
|
+
readonly transport: RemoteTransport<InvokeMessage, ServerMessage>;
|
|
14
|
+
readonly views: RemoteViewSet<C>;
|
|
15
|
+
readonly releaseWindowMs?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare const connect: <C extends RemoteContract>(options: ConnectOptions<C>) => ClientBinding;
|
|
18
|
+
//# sourceMappingURL=clientBinding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientBinding.d.ts","sourceRoot":"","sources":["../src/clientBinding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EAEnB,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,SAAS,CAAA;IAC9B,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;IACxD,QAAQ,CAAC,QAAQ,EAAE,MAAM,QAAQ,CAAA;IAEjC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAG5B,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,cAAc;IACtD,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IACjE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAGhC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAClC;AAYD,eAAO,MAAM,OAAO,GAAI,CAAC,SAAS,cAAc,EAAE,SAAS,cAAc,CAAC,CAAC,CAAC,KAAG,aA8D9E,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Match, MutableRef, Option, Predicate } from 'effect';
|
|
2
|
+
import { Wire } from '@playfast/reform/internal';
|
|
3
|
+
import { renderWireTree, } from './client.js';
|
|
4
|
+
// oxlint-disable-next-line reform-rules/no-magic-numbers -- the window's length is the value being named
|
|
5
|
+
const defaultReleaseWindowMs = 10_000;
|
|
6
|
+
// Browsers hand back a number, which has no `unref`.
|
|
7
|
+
const detachTimer = (handle) => {
|
|
8
|
+
if (Predicate.hasProperty(handle, 'unref') && Predicate.isFunction(handle.unref)) {
|
|
9
|
+
handle.unref();
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const connect = (options) => {
|
|
13
|
+
const { transport, views } = options;
|
|
14
|
+
const state = { tree: [] };
|
|
15
|
+
const listeners = new Set();
|
|
16
|
+
const config = {
|
|
17
|
+
views,
|
|
18
|
+
invoke: (handle, payload) => transport.send({ _tag: 'Invoke', handle, payload }),
|
|
19
|
+
};
|
|
20
|
+
const receive = (message) => {
|
|
21
|
+
state.tree = Match.value(message).pipe(Match.tag('Snapshot', ({ tree }) => tree), Match.tag('Patches', ({ patches }) => Wire.apply(state.tree, patches)), Match.exhaustive);
|
|
22
|
+
listeners.forEach((listener) => listener());
|
|
23
|
+
};
|
|
24
|
+
// Subscribed for the binding's whole life, not for the span React happens to be
|
|
25
|
+
// listening. Patches are deltas against the server's own baseline and a delete is
|
|
26
|
+
// never re-sent, so a frame missed while detached is a permanent phantom node —
|
|
27
|
+
// and an effect cleanup is not an unmount (StrictMode, <Suspense>, <Activity> all
|
|
28
|
+
// tear effects down and put them back). `dispose` therefore only goes quiet; the
|
|
29
|
+
// transport subscription is released by `close`, which the connection's owner calls.
|
|
30
|
+
const off = transport.onMessage(receive);
|
|
31
|
+
const pending = MutableRef.make(Option.none());
|
|
32
|
+
const close = () => {
|
|
33
|
+
listeners.clear();
|
|
34
|
+
MutableRef.set(pending, Option.none());
|
|
35
|
+
off();
|
|
36
|
+
};
|
|
37
|
+
// `dispose()` cannot know whether React is unmounting the host or merely hiding it,
|
|
38
|
+
// so it goes quiet and starts a clock. A `subscribe` inside the window is the host
|
|
39
|
+
// coming back and stops it; nothing inside the window means the host is gone, and
|
|
40
|
+
// the transport subscription is released rather than left to accumulate one dead
|
|
41
|
+
// handler per mount/unmount cycle.
|
|
42
|
+
const cancelClose = () => Option.match(MutableRef.get(pending), {
|
|
43
|
+
onNone: () => undefined,
|
|
44
|
+
onSome: (handle) => {
|
|
45
|
+
MutableRef.set(pending, Option.none());
|
|
46
|
+
clearTimeout(handle);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
node: () => renderWireTree(state.tree, config),
|
|
51
|
+
subscribe: (listener) => {
|
|
52
|
+
cancelClose();
|
|
53
|
+
listeners.add(listener);
|
|
54
|
+
return () => void listeners.delete(listener);
|
|
55
|
+
},
|
|
56
|
+
snapshot: () => state.tree,
|
|
57
|
+
dispose: () => {
|
|
58
|
+
listeners.clear();
|
|
59
|
+
if (Option.isSome(MutableRef.get(pending))) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// oxlint-disable-next-line reform-rules/no-set-timeout-interval -- must be unref-able; a binding waiting to be collected must not hold the host process open
|
|
63
|
+
const handle = setTimeout(close, options.releaseWindowMs ?? defaultReleaseWindowMs);
|
|
64
|
+
detachTimer(handle);
|
|
65
|
+
MutableRef.set(pending, Option.some(handle));
|
|
66
|
+
},
|
|
67
|
+
close,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=clientBinding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clientBinding.js","sourceRoot":"","sources":["../src/clientBinding.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * as Server from './server.js';
|
|
2
|
+
export * as Client from './client.js';
|
|
3
|
+
export * as Transport from './transport.js';
|
|
4
|
+
export * as Memory from './memory.js';
|
|
5
|
+
export * as React from './react.js';
|
|
6
|
+
export { makeRemoteServer, type RemoteServer, renderSceneToWire } from './server.js';
|
|
7
|
+
export { type ClientConfig, type RegisteredRemoteView, type RemoteContract, remoteContract, type RemoteView, type RemoteViews, type RemoteViewSet, remoteViews, renderWireTree, } from './client.js';
|
|
8
|
+
export { type ClientBinding, connect, type ConnectOptions, type InvokeMessage, type PatchesMessage, type RemoteTransport, serve, type ServeOptions, serveShared, type ServeSharedOptions, type ServerBinding, type ServerMessage, type SharedClientHandle, type SharedServerBinding, type SnapshotMessage, } from './transport.js';
|
|
9
|
+
export { inMemoryTransportPair, type TransportPair } from './memory.js';
|
|
10
|
+
export { RemoteUI, type RemoteUIProps, type StatusReporter, useConnectionStatus, useRemoteUI, } from './react.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAEhC,OAAO,EAAE,gBAAgB,EAAE,KAAK,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACjF,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,WAAW,EACX,cAAc,GACf,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,KAAK,aAAa,EAClB,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,EACL,KAAK,YAAY,EACjB,WAAW,EACX,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,qBAAqB,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAA;AACpE,OAAO,EACL,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,mBAAmB,EACnB,WAAW,GACZ,MAAM,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * as Server from './server.js';
|
|
2
|
+
export * as Client from './client.js';
|
|
3
|
+
export * as Transport from './transport.js';
|
|
4
|
+
export * as Memory from './memory.js';
|
|
5
|
+
export * as React from './react.js';
|
|
6
|
+
export { makeRemoteServer, renderSceneToWire } from './server.js';
|
|
7
|
+
export { remoteContract, remoteViews, renderWireTree, } from './client.js';
|
|
8
|
+
export { connect, serve, serveShared, } from './transport.js';
|
|
9
|
+
export { inMemoryTransportPair } from './memory.js';
|
|
10
|
+
export { RemoteUI, useConnectionStatus, useRemoteUI, } from './react.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AACxC,OAAO,KAAK,MAAM,MAAM,UAAU,CAAA;AAClC,OAAO,KAAK,KAAK,MAAM,SAAS,CAAA;AAEhC,OAAO,EAAE,gBAAgB,EAAqB,iBAAiB,EAAE,MAAM,UAAU,CAAA;AACjF,OAAO,EAIL,cAAc,EAId,WAAW,EACX,cAAc,GACf,MAAM,UAAU,CAAA;AACjB,OAAO,EAEL,OAAO,EAKP,KAAK,EAEL,WAAW,GAOZ,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,qBAAqB,EAAsB,MAAM,UAAU,CAAA;AACpE,OAAO,EACL,QAAQ,EAGR,mBAAmB,EACnB,WAAW,GACZ,MAAM,SAAS,CAAA"}
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RemoteTransport } from './transport.js';
|
|
2
|
+
export interface TransportPair<Server, Client> {
|
|
3
|
+
readonly server: RemoteTransport<Server, Client>;
|
|
4
|
+
readonly client: RemoteTransport<Client, Server>;
|
|
5
|
+
}
|
|
6
|
+
export declare const inMemoryTransportPair: <Server, Client>() => TransportPair<Server, Client>;
|
|
7
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD,MAAM,WAAW,aAAa,CAAC,MAAM,EAAE,MAAM;IAC3C,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChD,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjD;AAED,eAAO,MAAM,qBAAqB,GAAI,MAAM,EAAE,MAAM,OAAK,aAAa,CAAC,MAAM,EAAE,MAAM,CAmBpF,CAAA"}
|
package/dist/memory.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const inMemoryTransportPair = () => {
|
|
2
|
+
const serverHandlers = new Set();
|
|
3
|
+
const clientHandlers = new Set();
|
|
4
|
+
return {
|
|
5
|
+
server: {
|
|
6
|
+
send: (message) => clientHandlers.forEach((handler) => handler(message)),
|
|
7
|
+
onMessage: (handler) => {
|
|
8
|
+
serverHandlers.add(handler);
|
|
9
|
+
return () => void serverHandlers.delete(handler);
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
client: {
|
|
13
|
+
send: (message) => serverHandlers.forEach((handler) => handler(message)),
|
|
14
|
+
onMessage: (handler) => {
|
|
15
|
+
clientHandlers.add(handler);
|
|
16
|
+
return () => void clientHandlers.delete(handler);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAkD,EAAE;IACvF,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAA;IAC3D,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAA;IAC3D,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACxE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;gBACrB,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBAC3B,OAAO,GAAG,EAAE,CAAC,KAAK,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAClD,CAAC;SACF;QACD,MAAM,EAAE;YACN,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACxE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;gBACrB,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBAC3B,OAAO,GAAG,EAAE,CAAC,KAAK,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;YAClD,CAAC;SACF;KACF,CAAA;AACH,CAAC,CAAA"}
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type InvokeMessage, type RemoteTransport, type ServerMessage } from './transport.js';
|
|
3
|
+
import type { RemoteContract, RemoteViewSet } from './client.js';
|
|
4
|
+
export declare const useRemoteUI: <C extends RemoteContract>(transport: RemoteTransport<InvokeMessage, ServerMessage>, views: RemoteViewSet<C>) => ReactNode;
|
|
5
|
+
export interface RemoteUIProps<C extends RemoteContract> {
|
|
6
|
+
readonly transport: RemoteTransport<InvokeMessage, ServerMessage>;
|
|
7
|
+
readonly views: RemoteViewSet<C>;
|
|
8
|
+
}
|
|
9
|
+
export declare const RemoteUI: <C extends RemoteContract>({ transport, views, }: RemoteUIProps<C>) => ReactNode;
|
|
10
|
+
export interface StatusReporter<S> {
|
|
11
|
+
readonly status: () => S;
|
|
12
|
+
readonly onStatusChange: (listener: () => void) => () => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const useConnectionStatus: <S>(reporter: StatusReporter<S>) => S;
|
|
15
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAA2C,MAAM,OAAO,CAAA;AAC/E,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAA;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAE7D,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,cAAc,EAClD,WAAW,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,EACxD,OAAO,aAAa,CAAC,CAAC,CAAC,KACtB,SASF,CAAA;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,cAAc;IACrD,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IACjE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;CACjC;AAED,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,cAAc,EAAE,uBAGhD,aAAa,CAAC,CAAC,CAAC,KAAG,SAA0C,CAAA;AAEhE,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxB,QAAQ,CAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;CAC9D;AAED,eAAO,MAAM,mBAAmB,GAAI,CAAC,EAAE,UAAU,cAAc,CAAC,CAAC,CAAC,KAAG,CACY,CAAA"}
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Option } from 'effect';
|
|
2
|
+
import { useEffect, useRef, useSyncExternalStore } from 'react';
|
|
3
|
+
import { connect, } from './transport.js';
|
|
4
|
+
export const useRemoteUI = (transport, views) => {
|
|
5
|
+
// A ref, not `useState`: StrictMode double-invokes a state initializer, and the
|
|
6
|
+
// binding React discards would keep its transport subscription for good.
|
|
7
|
+
const held = useRef(Option.none());
|
|
8
|
+
const binding = Option.getOrElse(held.current, () => connect({ transport, views }));
|
|
9
|
+
held.current = Option.some(binding);
|
|
10
|
+
useEffect(() => () => binding.dispose(), [binding]);
|
|
11
|
+
useSyncExternalStore(binding.subscribe, binding.snapshot, binding.snapshot);
|
|
12
|
+
return binding.node();
|
|
13
|
+
};
|
|
14
|
+
export const RemoteUI = ({ transport, views, }) => useRemoteUI(transport, views);
|
|
15
|
+
export const useConnectionStatus = (reporter) => useSyncExternalStore(reporter.onStatusChange, reporter.status, reporter.status);
|
|
16
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAkB,SAAS,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAC/E,OAAO,EAEL,OAAO,GAIR,MAAM,aAAa,CAAA;AAGpB,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,SAAwD,EACxD,KAAuB,EACZ,EAAE;IACb,gFAAgF;IAChF,yEAAyE;IACzE,MAAM,IAAI,GAAG,MAAM,CAA+B,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;IAChE,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;IACnF,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACnC,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IACnD,oBAAoB,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC3E,OAAO,OAAO,CAAC,IAAI,EAAE,CAAA;AACvB,CAAC,CAAA;AAOD,MAAM,CAAC,MAAM,QAAQ,GAAG,CAA2B,EACjD,SAAS,EACT,KAAK,GACY,EAAa,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAA;AAOhE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAI,QAA2B,EAAK,EAAE,CACvE,oBAAoB,CAAC,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Effect, type ParseResult } from 'effect';
|
|
2
|
+
import { type CapturedScene, type UiContract } from '@playfast/reform';
|
|
3
|
+
import { type AnyScene, type WirePatch, type WireTree } from '@playfast/reform/internal';
|
|
4
|
+
import { type RenderSceneToWireOptions } from './wireRender.js';
|
|
5
|
+
export type { RenderSceneToWireOptions } from './wireRender.js';
|
|
6
|
+
export declare const renderSceneToWire: <C extends UiContract, S extends ReadonlyArray<unknown>, Services, P, N extends string, Identity>(scene: CapturedScene<C, S, Services, P, N, Identity>, options?: RenderSceneToWireOptions) => Effect.Effect<WireTree, ParseResult.ParseError, Services>;
|
|
7
|
+
export interface RemoteServer {
|
|
8
|
+
readonly render: () => Promise<WireTree>;
|
|
9
|
+
readonly renderDiff: () => Promise<ReadonlyArray<WirePatch>>;
|
|
10
|
+
readonly invoke: (handle: string, encodedPayload: unknown) => Promise<void>;
|
|
11
|
+
readonly subscribe: (listener: () => void) => () => void;
|
|
12
|
+
readonly currentTree: () => WireTree;
|
|
13
|
+
readonly dispose: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare const makeRemoteServer: (scene: AnyScene) => RemoteServer;
|
|
16
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAIN,KAAK,WAAW,EAGjB,MAAM,QAAQ,CAAA;AACf,OAAO,EAAE,KAAK,aAAa,EAAsB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC1F,OAAO,EACL,KAAK,QAAQ,EAKb,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAGL,KAAK,wBAAwB,EAG9B,MAAM,cAAc,CAAA;AAGrB,YAAY,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAA;AAG5D,eAAO,MAAM,iBAAiB,GAC5B,CAAC,SAAS,UAAU,EACpB,CAAC,SAAS,aAAa,CAAC,OAAO,CAAC,EAChC,QAAQ,EACR,CAAC,EACD,CAAC,SAAS,MAAM,EAChB,QAAQ,EAER,OAAO,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,EACpD,UAAU,wBAAwB,KACjC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,UAAU,EAAE,QAAQ,CAUxD,CAAA;AAEH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAA;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAA;IAC5D,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC3E,QAAQ,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;IACxD,QAAQ,CAAC,WAAW,EAAE,MAAM,QAAQ,CAAA;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACtC;AA2GD,eAAO,MAAM,gBAAgB,GAAI,OAAO,QAAQ,KAAG,YAYhD,CAAA"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Effect, Layer, ManagedRuntime, Option, PubSub, Queue, } from 'effect';
|
|
2
|
+
import { forceSync, publish } from '@playfast/reform';
|
|
3
|
+
import { Bus, Triggers, Wire, } from '@playfast/reform/internal';
|
|
4
|
+
import { capturedSlotProvider, renderCapturedComposition, renderSceneWith, serviceFromContext, } from './wireRender.js';
|
|
5
|
+
import { handlesOf, settleDrain } from './wireNode.js';
|
|
6
|
+
// oxlint-disable-next-line reform-rules/prefer-effect-fn -- exported binding: Effect.fn's inferred type isn't portable under isolatedDeclarations
|
|
7
|
+
export const renderSceneToWire = (scene, options) => Effect.context().pipe(Effect.flatMap((context) => renderSceneWith(scene, options, (slotDefinition) => capturedSlotProvider(context, slotDefinition), (composition, props) => renderCapturedComposition(context, composition, props))));
|
|
8
|
+
const makeCapturedRemoteServer = (scene) => {
|
|
9
|
+
const layer = scene.provide.reduce((acc, provided) => Layer.merge(acc, provided));
|
|
10
|
+
const runtime = ManagedRuntime.make(layer);
|
|
11
|
+
const registry = forceSync(() => runtime.runSync(Triggers.make));
|
|
12
|
+
const context = forceSync(() => runtime.runSync(Effect.context()));
|
|
13
|
+
const busFromContext = serviceFromContext(context, Bus, 'reform-remote: scene does not provide Bus');
|
|
14
|
+
const renderEffect = settleDrain.pipe(Effect.zipRight(renderSceneWith(scene, { register: registry.register }, (slotDefinition) => capturedSlotProvider(context, slotDefinition), (composition, props) => renderCapturedComposition(context, composition, props))));
|
|
15
|
+
const changeListeners = new Set();
|
|
16
|
+
const notifyChange = () => {
|
|
17
|
+
changeListeners.forEach((listener) => listener());
|
|
18
|
+
};
|
|
19
|
+
runtime.runFork(Effect.scoped(Effect.gen(function* () {
|
|
20
|
+
const bus = yield* busFromContext;
|
|
21
|
+
const subscription = yield* PubSub.subscribe(bus);
|
|
22
|
+
// The transport debounces; settling here would perturb the drain's scheduling.
|
|
23
|
+
yield* Queue.take(subscription).pipe(Effect.zipRight(Effect.sync(notifyChange)), Effect.forever);
|
|
24
|
+
})));
|
|
25
|
+
runtime.runSync(Effect.forEach(Option.getOrElse(Option.fromNullable(scene.boot), () => []), (event) => busFromContext.pipe(Effect.flatMap((bus) => publish('High', event).pipe(Effect.provideService(Bus, bus))))));
|
|
26
|
+
const frame = { tree: [] };
|
|
27
|
+
const render = () => runtime.runPromise(renderEffect.pipe(Effect.tap((tree) => Effect.sync(() => {
|
|
28
|
+
frame.tree = tree;
|
|
29
|
+
}))));
|
|
30
|
+
const renderDiff = () => runtime.runPromise(Effect.gen(function* () {
|
|
31
|
+
const next = yield* renderEffect;
|
|
32
|
+
const previous = frame.tree;
|
|
33
|
+
const patches = Wire.diff(previous, next);
|
|
34
|
+
frame.tree = next;
|
|
35
|
+
const nextIds = new Set(next.map((node) => node.id));
|
|
36
|
+
const staleHandles = previous.filter((node) => !nextIds.has(node.id)).flatMap(handlesOf);
|
|
37
|
+
yield* Effect.forEach(staleHandles, (handle) => registry.revoke(handle));
|
|
38
|
+
return patches;
|
|
39
|
+
}));
|
|
40
|
+
return {
|
|
41
|
+
render,
|
|
42
|
+
renderDiff,
|
|
43
|
+
invoke: (handle, encodedPayload) => runtime.runPromise(Effect.gen(function* () {
|
|
44
|
+
yield* registry.invoke(handle, encodedPayload);
|
|
45
|
+
yield* settleDrain;
|
|
46
|
+
})),
|
|
47
|
+
subscribe: (listener) => {
|
|
48
|
+
changeListeners.add(listener);
|
|
49
|
+
return () => void changeListeners.delete(listener);
|
|
50
|
+
},
|
|
51
|
+
currentTree: () => frame.tree,
|
|
52
|
+
dispose: () => runtime.dispose(),
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
export const makeRemoteServer = (scene) => scene.captureAny((exactScene) => makeCapturedRemoteServer(exactScene));
|
|
56
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,KAAK,EACL,cAAc,EACd,MAAM,EAEN,MAAM,EACN,KAAK,GACN,MAAM,QAAQ,CAAA;AACf,OAAO,EAAsB,SAAS,EAAE,OAAO,EAAmB,MAAM,kBAAkB,CAAA;AAC1F,OAAO,EAEL,GAAG,EACH,QAAQ,EAER,IAAI,GAGL,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACL,oBAAoB,EACpB,yBAAyB,EAEzB,eAAe,EACf,kBAAkB,GACnB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAInD,kJAAkJ;AAClJ,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAQ/B,KAAoD,EACpD,OAAkC,EACyB,EAAE,CAC7D,MAAM,CAAC,OAAO,EAAY,CAAC,IAAI,CAC7B,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CACzB,eAAe,CACb,KAAK,EACL,OAAO,EACP,CAAC,cAAc,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC,EACjE,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,yBAAyB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,CAC/E,CACF,CACF,CAAA;AAWH,MAAM,wBAAwB,GAAG,CAQ/B,KAAoD,EACtC,EAAE;IAChB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAA;IACjF,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1C,MAAM,QAAQ,GAAuB,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;IACpF,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,EAAY,CAAC,CAAC,CAAA;IAC5E,MAAM,cAAc,GAAG,kBAAkB,CACvC,OAAO,EACP,GAAG,EACH,2CAA2C,CAC5C,CAAA;IAED,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CACnC,MAAM,CAAC,QAAQ,CACb,eAAe,CACb,KAAK,EACL,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,EAC/B,CAAC,cAAc,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC,EACjE,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,yBAAyB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,CAC/E,CACF,CACF,CAAA;IAED,MAAM,eAAe,GAAG,IAAI,GAAG,EAAc,CAAA;IAC7C,MAAM,YAAY,GAAG,GAAS,EAAE;QAC9B,eAAe,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAA;IACnD,CAAC,CAAA;IACD,OAAO,CAAC,OAAO,CACb,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,cAAc,CAAA;QACjC,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QACjD,+EAA+E;QAC/E,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAClC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,EAC1C,MAAM,CAAC,OAAO,CACf,CAAA;IACH,CAAC,CAAC,CACH,CACF,CAAA;IAED,OAAO,CAAC,OAAO,CACb,MAAM,CAAC,OAAO,CACZ,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAC3D,CAAC,KAAK,EAAE,EAAE,CACR,cAAc,CAAC,IAAI,CACjB,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CACtF,CACJ,CACF,CAAA;IAED,MAAM,KAAK,GAAuB,EAAE,IAAI,EAAE,EAAE,EAAE,CAAA;IAE9C,MAAM,MAAM,GAAG,GAAsB,EAAE,CACrC,OAAO,CAAC,UAAU,CAChB,YAAY,CAAC,IAAI,CACf,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAClB,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;QACf,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;IACnB,CAAC,CAAC,CACH,CACF,CACF,CAAA;IAEH,MAAM,UAAU,GAAG,GAAsC,EAAE,CACzD,OAAO,CAAC,UAAU,CAChB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;QAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAA;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QACzC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;QACjB,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAA;QACpD,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;QACxF,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAA;QACxE,OAAO,OAAO,CAAA;IAChB,CAAC,CAAC,CACH,CAAA;IAEH,OAAO;QACL,MAAM;QACN,UAAU;QACV,MAAM,EAAE,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,CACjC,OAAO,CAAC,UAAU,CAChB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;YAC9C,KAAK,CAAC,CAAC,WAAW,CAAA;QACpB,CAAC,CAAC,CACH;QACH,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE;YACtB,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;YAC7B,OAAO,GAAG,EAAE,CAAC,KAAK,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QACpD,CAAC;QACD,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI;QAC7B,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;KACjC,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAe,EAAgB,EAAE,CAChE,KAAK,CAAC,UAAU,CACd,CAQE,UAAyD,EACzD,EAAE,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAC1C,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type AnyScene, type WirePatch, type WireTree } from '@playfast/reform/internal';
|
|
2
|
+
export interface SnapshotMessage {
|
|
3
|
+
readonly _tag: 'Snapshot';
|
|
4
|
+
readonly tree: WireTree;
|
|
5
|
+
}
|
|
6
|
+
export interface PatchesMessage {
|
|
7
|
+
readonly _tag: 'Patches';
|
|
8
|
+
readonly patches: ReadonlyArray<WirePatch>;
|
|
9
|
+
}
|
|
10
|
+
export type ServerMessage = SnapshotMessage | PatchesMessage;
|
|
11
|
+
export interface InvokeMessage {
|
|
12
|
+
readonly _tag: 'Invoke';
|
|
13
|
+
readonly handle: string;
|
|
14
|
+
readonly payload: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface RemoteTransport<Out, In> {
|
|
17
|
+
readonly send: (message: Out) => void;
|
|
18
|
+
readonly onMessage: (handler: (message: In) => void) => () => void;
|
|
19
|
+
}
|
|
20
|
+
export interface ServerBinding {
|
|
21
|
+
readonly start: () => Promise<void>;
|
|
22
|
+
readonly dispose: () => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export interface ServeOptions {
|
|
25
|
+
readonly scene: AnyScene;
|
|
26
|
+
readonly transport: RemoteTransport<ServerMessage, InvokeMessage>;
|
|
27
|
+
}
|
|
28
|
+
export declare const serve: (options: ServeOptions) => ServerBinding;
|
|
29
|
+
export interface SharedClientHandle {
|
|
30
|
+
readonly remove: () => void;
|
|
31
|
+
}
|
|
32
|
+
export interface SharedServerBinding {
|
|
33
|
+
readonly addClient: (transport: RemoteTransport<ServerMessage, InvokeMessage>) => SharedClientHandle;
|
|
34
|
+
readonly dispose: () => Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export interface ServeSharedOptions {
|
|
37
|
+
readonly scene: AnyScene;
|
|
38
|
+
}
|
|
39
|
+
export declare const serveShared: (options: ServeSharedOptions) => SharedServerBinding;
|
|
40
|
+
export { type ClientBinding, connect, type ConnectOptions } from './clientBinding.js';
|
|
41
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,2BAA2B,CAAA;AAGxF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAA;CAC3C;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,cAAc,CAAA;AAE5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,eAAe,CAAC,GAAG,EAAE,EAAE;IACtC,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,IAAI,CAAA;IACrC,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;CACnE;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACtC;AAID,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;CAClE;AAED,eAAO,MAAM,KAAK,GAAI,SAAS,YAAY,KAAG,aAqF7C,CAAA;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,CAClB,SAAS,EAAE,eAAe,CAAC,aAAa,EAAE,aAAa,CAAC,KACrD,kBAAkB,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACtC;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;CACzB;AAED,eAAO,MAAM,WAAW,GAAI,SAAS,kBAAkB,KAAG,mBAkHzD,CAAA;AAED,OAAO,EAAE,KAAK,aAAa,EAAE,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA"}
|