@@ -1,62 +1,73 @@
11import { useCallback, useState } from 'react';
2−import ob from 'urbit-ob';
3−
4−import SolarisClient from 'lib/SolarisClient';
5−import useDeepEqualReference from './useDeepEqualReference';
62
73const STATE = {
8− NOT_FOUND: 'NOT_FOUND',
4+ // container states
5+ UNKNOWN: 'UNKNOWN',
6+ MISSING: 'MISSING',
97 RUNNING: 'RUNNING',
8+ PENDING: 'PENDING',
9+ // api states
10+ QUERYING: 'QUERYING',
1011 BOOTING: 'BOOTING',
1112 CONNECTING: 'CONNECTING',
13+ // connection states
1214 CONNECTED: 'CONNECTED',
13− UNKNOWN: 'UNKNOWN',
1415};
1516
16−export function useHostedShip(point, endpoint = 'http://localhost:3030') {
17− const patp = ob.patp(point.value);
18− const client = new SolarisClient(endpoint);
19−
17+export function useHostedShip(client, patp) {
2018 const [state, setState] = useState(STATE.UNKNOWN);
21− const [events, setEvents] = useState([]);
22− const [error, _setError] = useState();
2319
20+ const [sysEvents, setSysEvents] = useState([]);
21+ const [newEvents, setNewEvents] = useState([]);
22+ const [runEvents, setRunEvents] = useState([]);
23+
24+ const [error, _setError] = useState();
2425 const setError = useCallback(
2526 error => {
2627 _setError(error);
27− setState(STATE.UNKNOWN);
2828 if (error) {
29+ setState(STATE.UNKNOWN);
2930 console.error(error);
3031 }
3132 },
32− [_setError]
33+ [_setError, setState]
3334 );
3435
35− const addEvent = event => {
36− setEvents(current => current.push(event));
37− };
38−
39− const notFound = state === STATE.NOT_FOUND;
36+ const unknown = state === STATE.UNKNOWN;
37+ const missing = state === STATE.MISSING;
4038 const running = state === STATE.RUNNING;
39+ const pending = state === STATE.PENDING;
40+ const querying = state === STATE.QUERYING;
4141 const booting = state === STATE.BOOTING;
4242 const connecting = state === STATE.CONNECTING;
4343 const connected = state === STATE.CONNECTED;
44− const unknown = state === STATE.UNKNOWN;
4544
46− const checkShipExists = useCallback(async () => {
45+ const resetEvents = useCallback(() => {
46+ setSysEvents([]);
47+ setNewEvents([]);
48+ setRunEvents([]);
49+ }, []);
50+
51+ const getStatus = useCallback(async () => {
4752 try {
4853 setError(undefined);
4954
55+ resetEvents();
56+
57+ setState(STATE.QUERYING);
58+
5059 const response = await client.getShipsByPatp(patp);
5160
5261 if (response.status === 404) {
53− setState(STATE.NOT_FOUND);
62+ setState(STATE.MISSING);
5463 } else if (!response.ok) {
5564 setError(response.statusText);
5665 } else {
5766 const ship = await response.json();
5867
59− if (ship.status === 'Running') {
68+ if (ship.status === 'Pending') {
69+ setState(STATE.PENDING);
70+ } else if (ship.status === 'Running') {
6071 setState(STATE.RUNNING);
6172 } else {
6273 setError(ship);
@@ -65,44 +76,47 @@ export function useHostedShip(point, endpoint = 'http://localhost:3030') {
6576 } catch (error) {
6677 setError(error);
6778 }
68− }, [client, patp, setError]);
79+ }, [client, patp, resetEvents, setError]);
6980
70− const getShipEvents = useCallback(async () => {
81+ const getEvents = useCallback(() => {
7182 try {
7283 setError(undefined);
73− setState(STATE.CONNECTING);
7484
75− const response = await client.getShipsByPatpEvents(patp);
85+ resetEvents();
7686
77− if (!response.ok) {
78− setError(response.statusText);
79− } else {
80− const reader = response.body.getReader();
87+ setState(STATE.CONNECTING);
88+
89+ const url = client.getShipsByPatpUrl(patp) + '/events';
90+ const source = new EventSource(url);
8191
82− reader.read().then(function yieldEvent({ done, value }) {
83− setState(STATE.CONNECTED);
92+ source.onopen = () => setState(STATE.CONNECTED);
93+ // source.onerror = () => setState(STATE.UNKNOWN);
94+ // source.onmessage = console.log;
8495
85− // Result objects contain two properties:
86− // done - true if the stream has already given you all its data.
87− // value - some data. Always undefined when done is true.
88− if (done) {
89− return;
90− }
96+ source.addEventListener('sys', event => {
97+ setSysEvents(previous => [...previous, JSON.parse(event.data)]);
98+ });
9199
92− addEvent(JSON.parse(value));
100+ source.addEventListener('new', event => {
101+ if (event.data !== '') {
102+ setNewEvents(previous => [...previous, event.data]);
103+ }
104+ });
93105
94− // Read some more, and call this function again
95− return reader.read().then(yieldEvent);
96− });
97− }
106+ source.addEventListener('run', event => {
107+ if (event.data !== '') {
108+ setRunEvents(previous => [...previous, event.data]);
109+ }
110+ });
98111 } catch (error) {
99112 setError(error);
100113 }
101− }, [client, patp, setError]);
114+ }, [setError, resetEvents, client, patp, setState]);
102115
103− const createNewShip = useCallback(async () => {
116+ const create = useCallback(async () => {
104117 try {
105118 setError(undefined);
119+
106120 setState(STATE.BOOTING);
107121
108122 const response = await client.postShips({
@@ -113,26 +127,33 @@ export function useHostedShip(point, endpoint = 'http://localhost:3030') {
113127 if (!response.ok) {
114128 setError(response.statusText);
115129 } else {
116− checkShipExists();
130+ getEvents();
117131 }
118132 } catch (error) {
119133 setError(error);
120134 }
121− }, [checkShipExists, client, patp, setError]);
135+ }, [setError, client, patp, getEvents]);
122136
123− const values = useDeepEqualReference({
137+ return {
124138 error,
125− notFound,
139+ unknown,
140+ missing,
126141 running,
142+ pending,
143+ querying,
127144 booting,
128145 connecting,
129146 connected,
130− unknown,
131− events,
132− checkShipExists,
133− getShipEvents,
134− createNewShip,
135− });
136147
137− return { ...values, bind: values };
148+ sysEvents,
149+ newEvents,
150+ runEvents,
151+
152+ getStatus,
153+ getEvents,
154+ create,
155+
156+ // debugging
157+ state,
158+ };
138159}