@arcanejs/toolkit 5.0.0 → 6.0.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.
Files changed (31) hide show
  1. package/dist/backend/components/base.d.mts +1 -1
  2. package/dist/backend/components/base.d.ts +1 -1
  3. package/dist/backend/components/button.d.mts +1 -1
  4. package/dist/backend/components/button.d.ts +1 -1
  5. package/dist/backend/components/group.d.mts +1 -1
  6. package/dist/backend/components/group.d.ts +1 -1
  7. package/dist/backend/components/label.d.mts +1 -1
  8. package/dist/backend/components/label.d.ts +1 -1
  9. package/dist/backend/components/rect.d.mts +1 -1
  10. package/dist/backend/components/rect.d.ts +1 -1
  11. package/dist/backend/components/slider-button.d.mts +1 -1
  12. package/dist/backend/components/slider-button.d.ts +1 -1
  13. package/dist/backend/components/switch.d.mts +1 -1
  14. package/dist/backend/components/switch.d.ts +1 -1
  15. package/dist/backend/components/tabs.d.mts +1 -1
  16. package/dist/backend/components/tabs.d.ts +1 -1
  17. package/dist/backend/components/text-input.d.mts +1 -1
  18. package/dist/backend/components/text-input.d.ts +1 -1
  19. package/dist/backend/components/timeline.d.mts +1 -1
  20. package/dist/backend/components/timeline.d.ts +1 -1
  21. package/dist/frontend/entrypoint.js +29 -22
  22. package/dist/frontend/entrypoint.js.map +2 -2
  23. package/dist/frontend/index.js +32 -22
  24. package/dist/frontend/index.mjs +33 -23
  25. package/dist/index.d.mts +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +56 -24
  28. package/dist/index.mjs +47 -15
  29. package/dist/{toolkit-C37sQAkD.d.ts → toolkit-C_2Y8N9R.d.ts} +10 -1
  30. package/dist/{toolkit-CQMnQMOF.d.mts → toolkit-CohVRj6u.d.mts} +10 -1
  31. package/package.json +3 -3
@@ -18,6 +18,9 @@ var _styledcomponents = require('styled-components');
18
18
 
19
19
 
20
20
  var _styling = require('@arcanejs/toolkit-frontend/styling');
21
+
22
+
23
+
21
24
  var _toolkitfrontend = require('@arcanejs/toolkit-frontend');
22
25
 
23
26
  // ../toolkit-frontend/src/styling.tsx
@@ -300,7 +303,9 @@ var Stage = ({ className, renderers }) => {
300
303
  void 0
301
304
  );
302
305
  const socket = _react.useRef.call(void 0, null);
303
- const uuid = _react.useRef.call(void 0, null);
306
+ const [connection, setConnection] = _react.useState.call(void 0, {
307
+ state: "connecting"
308
+ });
304
309
  const calls = _react.useRef.call(void 0, {
305
310
  nextId: 1,
306
311
  calls: /* @__PURE__ */ new Map()
@@ -325,7 +330,7 @@ var Stage = ({ className, renderers }) => {
325
330
  const handleMessage = _react.useCallback.call(void 0, (msg) => {
326
331
  switch (msg.type) {
327
332
  case "metadata":
328
- uuid.current = msg.connectionUuid;
333
+ setConnection({ state: "connected", uuid: msg.connectionUuid });
329
334
  return;
330
335
  case "tree-full":
331
336
  setRoot(msg.root);
@@ -352,29 +357,39 @@ var Stage = ({ className, renderers }) => {
352
357
  }
353
358
  }, []);
354
359
  const initializeWebsocket = _react.useCallback.call(void 0, async () => {
360
+ if (socket.current) {
361
+ socket.current.then((s) => s.close()).catch((err) => console.error(err));
362
+ socket.current = null;
363
+ }
355
364
  console.log("initializing websocket");
356
365
  const wsUrl = new URL(window.location.href);
357
366
  wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
358
- const ws = new WebSocket(
359
- `ws://${window.location.hostname}:${window.location.port}${window.location.pathname}`
360
- );
367
+ const ws = new WebSocket(wsUrl.href);
361
368
  ws.onmessage = (event) => {
362
369
  handleMessage(JSON.parse(event.data));
363
370
  };
364
371
  ws.onclose = () => {
372
+ setConnection({ state: "closed" });
365
373
  console.log("socket closed");
366
374
  socket.current = null;
367
375
  };
368
376
  socket.current = new Promise((resolve, reject) => {
369
377
  ws.onopen = () => {
378
+ console.log("socket opened");
379
+ setConnection({ state: "connected", uuid: null });
370
380
  resolve(ws);
371
381
  };
372
382
  ws.onerror = (err) => {
383
+ setConnection({
384
+ state: "error",
385
+ error: err instanceof Error ? err : new Error("Unable to connect", { cause: err })
386
+ });
387
+ console.error("socket error", err);
373
388
  reject(err);
374
389
  socket.current = null;
375
390
  };
376
391
  });
377
- return ws;
392
+ return socket.current;
378
393
  }, []);
379
394
  const sendMessage = _react.useCallback.call(void 0, async (msg) => {
380
395
  (await (socket.current || initializeWebsocket())).send(JSON.stringify(msg));
@@ -404,23 +419,18 @@ var Stage = ({ className, renderers }) => {
404
419
  _react.useEffect.call(void 0, () => {
405
420
  initializeWebsocket();
406
421
  }, [initializeWebsocket]);
407
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
408
- _toolkitfrontend.StageContext.Provider,
409
- {
410
- value: {
411
- sendMessage,
412
- renderComponent,
413
- call,
414
- get connectionUuid() {
415
- if (!uuid.current) {
416
- throw new Error("Unexpected missing UUID");
417
- }
418
- return uuid.current;
419
- }
420
- },
421
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _toolkitfrontend.GroupStateWrapper, { openByDefault: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className, children: root ? renderComponent(root) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "no-root", children: "No root has been added to the light desk" }) }) })
422
- }
422
+ const stageContext = _react.useMemo.call(void 0,
423
+ () => ({
424
+ sendMessage,
425
+ renderComponent,
426
+ call,
427
+ connectionUuid: connection.state === "connected" ? connection.uuid : null,
428
+ connection,
429
+ reconnect: () => void initializeWebsocket()
430
+ }),
431
+ [sendMessage, renderComponent, call, initializeWebsocket, connection]
423
432
  );
433
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _toolkitfrontend.StageContext.Provider, { value: stageContext, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _toolkitfrontend.GroupStateWrapper, { openByDefault: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className, children: root ? renderComponent(root) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "no-root", children: "No root has been added to the light desk" }) }) }) });
424
434
  };
425
435
  var StyledStage = _styledcomponents.styled.call(void 0, Stage)`
426
436
  width: 100%;
@@ -18,7 +18,10 @@ import {
18
18
  DARK_THEME as DARK_THEME2,
19
19
  LIGHT_THEME as LIGHT_THEME2
20
20
  } from "@arcanejs/toolkit-frontend/styling";
21
- import { GroupStateWrapper, StageContext } from "@arcanejs/toolkit-frontend";
21
+ import {
22
+ GroupStateWrapper,
23
+ StageContext
24
+ } from "@arcanejs/toolkit-frontend";
22
25
 
23
26
  // ../toolkit-frontend/src/styling.tsx
24
27
  import {
@@ -300,7 +303,9 @@ var Stage = ({ className, renderers }) => {
300
303
  void 0
301
304
  );
302
305
  const socket = useRef(null);
303
- const uuid = useRef(null);
306
+ const [connection, setConnection] = useState3({
307
+ state: "connecting"
308
+ });
304
309
  const calls = useRef({
305
310
  nextId: 1,
306
311
  calls: /* @__PURE__ */ new Map()
@@ -325,7 +330,7 @@ var Stage = ({ className, renderers }) => {
325
330
  const handleMessage = useCallback((msg) => {
326
331
  switch (msg.type) {
327
332
  case "metadata":
328
- uuid.current = msg.connectionUuid;
333
+ setConnection({ state: "connected", uuid: msg.connectionUuid });
329
334
  return;
330
335
  case "tree-full":
331
336
  setRoot(msg.root);
@@ -352,29 +357,39 @@ var Stage = ({ className, renderers }) => {
352
357
  }
353
358
  }, []);
354
359
  const initializeWebsocket = useCallback(async () => {
360
+ if (socket.current) {
361
+ socket.current.then((s) => s.close()).catch((err) => console.error(err));
362
+ socket.current = null;
363
+ }
355
364
  console.log("initializing websocket");
356
365
  const wsUrl = new URL(window.location.href);
357
366
  wsUrl.protocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
358
- const ws = new WebSocket(
359
- `ws://${window.location.hostname}:${window.location.port}${window.location.pathname}`
360
- );
367
+ const ws = new WebSocket(wsUrl.href);
361
368
  ws.onmessage = (event) => {
362
369
  handleMessage(JSON.parse(event.data));
363
370
  };
364
371
  ws.onclose = () => {
372
+ setConnection({ state: "closed" });
365
373
  console.log("socket closed");
366
374
  socket.current = null;
367
375
  };
368
376
  socket.current = new Promise((resolve, reject) => {
369
377
  ws.onopen = () => {
378
+ console.log("socket opened");
379
+ setConnection({ state: "connected", uuid: null });
370
380
  resolve(ws);
371
381
  };
372
382
  ws.onerror = (err) => {
383
+ setConnection({
384
+ state: "error",
385
+ error: err instanceof Error ? err : new Error("Unable to connect", { cause: err })
386
+ });
387
+ console.error("socket error", err);
373
388
  reject(err);
374
389
  socket.current = null;
375
390
  };
376
391
  });
377
- return ws;
392
+ return socket.current;
378
393
  }, []);
379
394
  const sendMessage = useCallback(async (msg) => {
380
395
  (await (socket.current || initializeWebsocket())).send(JSON.stringify(msg));
@@ -404,23 +419,18 @@ var Stage = ({ className, renderers }) => {
404
419
  useEffect2(() => {
405
420
  initializeWebsocket();
406
421
  }, [initializeWebsocket]);
407
- return /* @__PURE__ */ jsx2(
408
- StageContext.Provider,
409
- {
410
- value: {
411
- sendMessage,
412
- renderComponent,
413
- call,
414
- get connectionUuid() {
415
- if (!uuid.current) {
416
- throw new Error("Unexpected missing UUID");
417
- }
418
- return uuid.current;
419
- }
420
- },
421
- children: /* @__PURE__ */ jsx2(GroupStateWrapper, { openByDefault: false, children: /* @__PURE__ */ jsx2("div", { className, children: root ? renderComponent(root) : /* @__PURE__ */ jsx2("div", { className: "no-root", children: "No root has been added to the light desk" }) }) })
422
- }
422
+ const stageContext = useMemo(
423
+ () => ({
424
+ sendMessage,
425
+ renderComponent,
426
+ call,
427
+ connectionUuid: connection.state === "connected" ? connection.uuid : null,
428
+ connection,
429
+ reconnect: () => void initializeWebsocket()
430
+ }),
431
+ [sendMessage, renderComponent, call, initializeWebsocket, connection]
423
432
  );
433
+ return /* @__PURE__ */ jsx2(StageContext.Provider, { value: stageContext, children: /* @__PURE__ */ jsx2(GroupStateWrapper, { openByDefault: false, children: /* @__PURE__ */ jsx2("div", { className, children: root ? renderComponent(root) : /* @__PURE__ */ jsx2("div", { className: "no-root", children: "No root has been added to the light desk" }) }) }) });
424
434
  };
425
435
  var StyledStage = styled(Stage)`
426
436
  width: 100%;
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AnyComponent, B as Button, G as Group, c as GroupHeader, T as Toolkit, a as ToolkitConnection, b as ToolkitOptions } from './toolkit-CQMnQMOF.mjs';
1
+ export { A as AnyComponent, B as Button, G as Group, e as GroupHeader, T as Toolkit, a as ToolkitConnection, d as ToolkitOptions, c as ToolkitServerListener, b as ToolkitServerListenerOptions } from './toolkit-CohVRj6u.mjs';
2
2
  export { Label } from './backend/components/label.mjs';
3
3
  export { Rect } from './backend/components/rect.mjs';
4
4
  export { SliderButton } from './backend/components/slider-button.mjs';
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AnyComponent, B as Button, G as Group, c as GroupHeader, T as Toolkit, a as ToolkitConnection, b as ToolkitOptions } from './toolkit-C37sQAkD.js';
1
+ export { A as AnyComponent, B as Button, G as Group, e as GroupHeader, T as Toolkit, a as ToolkitConnection, d as ToolkitOptions, c as ToolkitServerListener, b as ToolkitServerListenerOptions } from './toolkit-C_2Y8N9R.js';
2
2
  export { Label } from './backend/components/label.js';
3
3
  export { Rect } from './backend/components/rect.js';
4
4
  export { SliderButton } from './backend/components/slider-button.js';
package/dist/index.js CHANGED
@@ -108,6 +108,7 @@ var Server = (_class = class {
108
108
  <html>
109
109
  <head>
110
110
  <title>${this.title}</title>
111
+ <meta charset="utf-8">
111
112
  <meta name="viewport" content="width=device-width, initial-scale=1">
112
113
  <style type="text/css">
113
114
  @font-face {
@@ -190,7 +191,8 @@ var Toolkit = (_class2 = class {
190
191
  __init6() {this.rootGroup = null}
191
192
  /** @hidden */
192
193
  __init7() {this.events = new (0, _chunkWN3GXVUEjs.EventEmitter)()}
193
- constructor(options = {}) {;_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);
194
+
195
+ constructor(options = {}) {;_class2.prototype.__init4.call(this);_class2.prototype.__init5.call(this);_class2.prototype.__init6.call(this);_class2.prototype.__init7.call(this);_class2.prototype.__init8.call(this);_class2.prototype.__init9.call(this);_class2.prototype.__init10.call(this);_class2.prototype.__init11.call(this);_class2.prototype.__init12.call(this);_class2.prototype.__init13.call(this);_class2.prototype.__init14.call(this);_class2.prototype.__init15.call(this);_class2.prototype.__init16.call(this);_class2.prototype.__init17.call(this);_class2.prototype.__init18.call(this);_class2.prototype.__init19.call(this);
194
196
  this.options = {
195
197
  ...DEFAULT_LIGHT_DESK_OPTIONS,
196
198
  ...options
@@ -200,25 +202,20 @@ var Toolkit = (_class2 = class {
200
202
  `path must start and end with "/", set to: ${this.options.path}`
201
203
  );
202
204
  }
203
- }
204
- __init8() {this.addListener = this.events.addListener}
205
- __init9() {this.removeListener = this.events.removeListener}
206
- __init10() {this.start = (opts) => {
207
- const server = new Server(
205
+ this.server = new Server(
208
206
  this.options,
209
207
  this.onNewConnection,
210
208
  this.onClosedConnection,
211
209
  this.onMessage,
212
210
  this.options.log
213
211
  );
212
+ }
213
+ __init8() {this.addListener = this.events.addListener}
214
+ __init9() {this.removeListener = this.events.removeListener}
215
+ __init10() {this.start = (opts) => {
214
216
  if (opts.mode === "automatic") {
215
- const httpServer = _http.createServer.call(void 0, server.handleHttpRequest);
216
- const wss = new (0, _ws.WebSocketServer)({
217
- server: httpServer
218
- });
219
- wss.on("connection", server.handleWsConnection);
220
- const url = `http://localhost:${opts.port}${this.options.path}`;
221
- httpServer.listen(opts.port, () => {
217
+ this.listen({ port: opts.port }).then(() => {
218
+ const url = `http://localhost:${opts.port}${this.options.path}`;
222
219
  _optionalChain([opts, 'access', _49 => _49.onReady, 'optionalCall', _50 => _50(url)]);
223
220
  _optionalChain([this, 'access', _51 => _51.options, 'access', _52 => _52.log, 'optionalAccess', _53 => _53.info, 'call', _54 => _54(`Light Desk Started: ${url}`)]);
224
221
  });
@@ -226,15 +223,50 @@ var Toolkit = (_class2 = class {
226
223
  const wss = new (0, _ws.WebSocketServer)({
227
224
  server: opts.server
228
225
  });
229
- wss.on("connection", server.handleWsConnection);
230
- opts.express.get(`${this.options.path}*`, server.handleHttpRequest);
226
+ wss.on("connection", this.server.handleWsConnection);
227
+ opts.express.get(`${this.options.path}*`, this.server.handleHttpRequest);
231
228
  } else if (opts.mode === "manual") {
232
- opts.setup(server);
229
+ opts.setup(this.server);
233
230
  } else {
234
231
  throw new Error(`Unsupported mode`);
235
232
  }
236
233
  }}
237
- __init11() {this.setRoot = (group) => {
234
+ __init11() {this.listen = ({
235
+ port,
236
+ host
237
+ }) => {
238
+ const httpServer = _http.createServer.call(void 0, this.server.handleHttpRequest);
239
+ const wss = new (0, _ws.WebSocketServer)({
240
+ server: httpServer
241
+ });
242
+ wss.on("connection", this.server.handleWsConnection);
243
+ const close = () => {
244
+ wss.close();
245
+ httpServer.close();
246
+ httpServer.closeAllConnections();
247
+ setTimeout(() => {
248
+ wss.clients.forEach((client) => client.terminate());
249
+ }, 1e3);
250
+ };
251
+ return new Promise((resolve2, reject) => {
252
+ httpServer.on("error", (err) => {
253
+ reject(err);
254
+ });
255
+ wss.on("error", (err) => {
256
+ reject(err);
257
+ });
258
+ try {
259
+ httpServer.listen({ port, host }, () => {
260
+ resolve2({
261
+ close
262
+ });
263
+ });
264
+ } catch (err) {
265
+ reject(err);
266
+ }
267
+ });
268
+ }}
269
+ __init12() {this.setRoot = (group) => {
238
270
  if (this.rootGroup) {
239
271
  throw new Error("Can only set root group once");
240
272
  }
@@ -244,10 +276,10 @@ var Toolkit = (_class2 = class {
244
276
  log() {
245
277
  return _nullishCoalesce(this.options.log, () => ( null));
246
278
  }
247
- __init12() {this.getConnections = () => {
279
+ __init13() {this.getConnections = () => {
248
280
  return [...this.connections.values()].map((c) => c.publicConnection);
249
281
  }}
250
- __init13() {this.updateTree = _lodash2.default.throttle(
282
+ __init14() {this.updateTree = _lodash2.default.throttle(
251
283
  () => {
252
284
  setImmediate(() => {
253
285
  if (!this.rootGroup) return;
@@ -264,13 +296,13 @@ var Toolkit = (_class2 = class {
264
296
  10,
265
297
  { leading: true, trailing: true }
266
298
  )}
267
- __init14() {this.removeChild = (component) => {
299
+ __init15() {this.removeChild = (component) => {
268
300
  if (this.rootGroup === component) {
269
301
  this.rootGroup = null;
270
302
  component.setParent(null);
271
303
  }
272
304
  }}
273
- __init15() {this.onNewConnection = (connection) => {
305
+ __init16() {this.onNewConnection = (connection) => {
274
306
  const lastTreeSent = _nullishCoalesce(_optionalChain([this, 'access', _55 => _55.rootGroup, 'optionalAccess', _56 => _56.getProtoInfo, 'call', _57 => _57(this.componentIDMap)]), () => ( void 0));
275
307
  const uuid = _uuid.v4.call(void 0, );
276
308
  const publicConnection = {
@@ -291,7 +323,7 @@ var Toolkit = (_class2 = class {
291
323
  });
292
324
  }
293
325
  }}
294
- __init16() {this.onClosedConnection = (connection) => {
326
+ __init17() {this.onClosedConnection = (connection) => {
295
327
  _optionalChain([this, 'access', _58 => _58.log, 'call', _59 => _59(), 'optionalAccess', _60 => _60.debug, 'call', _61 => _61("removing connection")]);
296
328
  const con = this.connections.get(connection);
297
329
  this.connections.delete(connection);
@@ -299,7 +331,7 @@ var Toolkit = (_class2 = class {
299
331
  this.events.emit("closed-connection", con.publicConnection);
300
332
  }
301
333
  }}
302
- __init17() {this.handleCall = async (connection, publicConnection, call) => {
334
+ __init18() {this.handleCall = async (connection, publicConnection, call) => {
303
335
  try {
304
336
  const rg = this.rootGroup;
305
337
  if (rg) {
@@ -329,7 +361,7 @@ var Toolkit = (_class2 = class {
329
361
  });
330
362
  }
331
363
  }}
332
- __init18() {this.onMessage = (connection, message) => {
364
+ __init19() {this.onMessage = (connection, message) => {
333
365
  const con = this.connections.get(connection);
334
366
  if (!con) {
335
367
  _optionalChain([this, 'access', _62 => _62.log, 'call', _63 => _63(), 'optionalAccess', _64 => _64.warn, 'call', _65 => _65(`got message from unknown connection`)]);
package/dist/index.mjs CHANGED
@@ -108,6 +108,7 @@ var Server = class {
108
108
  <html>
109
109
  <head>
110
110
  <title>${this.title}</title>
111
+ <meta charset="utf-8">
111
112
  <meta name="viewport" content="width=device-width, initial-scale=1">
112
113
  <style type="text/css">
113
114
  @font-face {
@@ -190,6 +191,7 @@ var Toolkit = class {
190
191
  rootGroup = null;
191
192
  /** @hidden */
192
193
  events = new EventEmitter();
194
+ server;
193
195
  constructor(options = {}) {
194
196
  this.options = {
195
197
  ...DEFAULT_LIGHT_DESK_OPTIONS,
@@ -200,25 +202,20 @@ var Toolkit = class {
200
202
  `path must start and end with "/", set to: ${this.options.path}`
201
203
  );
202
204
  }
203
- }
204
- addListener = this.events.addListener;
205
- removeListener = this.events.removeListener;
206
- start = (opts) => {
207
- const server = new Server(
205
+ this.server = new Server(
208
206
  this.options,
209
207
  this.onNewConnection,
210
208
  this.onClosedConnection,
211
209
  this.onMessage,
212
210
  this.options.log
213
211
  );
212
+ }
213
+ addListener = this.events.addListener;
214
+ removeListener = this.events.removeListener;
215
+ start = (opts) => {
214
216
  if (opts.mode === "automatic") {
215
- const httpServer = createServer(server.handleHttpRequest);
216
- const wss = new WebSocketServer({
217
- server: httpServer
218
- });
219
- wss.on("connection", server.handleWsConnection);
220
- const url = `http://localhost:${opts.port}${this.options.path}`;
221
- httpServer.listen(opts.port, () => {
217
+ this.listen({ port: opts.port }).then(() => {
218
+ const url = `http://localhost:${opts.port}${this.options.path}`;
222
219
  opts.onReady?.(url);
223
220
  this.options.log?.info(`Light Desk Started: ${url}`);
224
221
  });
@@ -226,14 +223,49 @@ var Toolkit = class {
226
223
  const wss = new WebSocketServer({
227
224
  server: opts.server
228
225
  });
229
- wss.on("connection", server.handleWsConnection);
230
- opts.express.get(`${this.options.path}*`, server.handleHttpRequest);
226
+ wss.on("connection", this.server.handleWsConnection);
227
+ opts.express.get(`${this.options.path}*`, this.server.handleHttpRequest);
231
228
  } else if (opts.mode === "manual") {
232
- opts.setup(server);
229
+ opts.setup(this.server);
233
230
  } else {
234
231
  throw new Error(`Unsupported mode`);
235
232
  }
236
233
  };
234
+ listen = ({
235
+ port,
236
+ host
237
+ }) => {
238
+ const httpServer = createServer(this.server.handleHttpRequest);
239
+ const wss = new WebSocketServer({
240
+ server: httpServer
241
+ });
242
+ wss.on("connection", this.server.handleWsConnection);
243
+ const close = () => {
244
+ wss.close();
245
+ httpServer.close();
246
+ httpServer.closeAllConnections();
247
+ setTimeout(() => {
248
+ wss.clients.forEach((client) => client.terminate());
249
+ }, 1e3);
250
+ };
251
+ return new Promise((resolve2, reject) => {
252
+ httpServer.on("error", (err) => {
253
+ reject(err);
254
+ });
255
+ wss.on("error", (err) => {
256
+ reject(err);
257
+ });
258
+ try {
259
+ httpServer.listen({ port, host }, () => {
260
+ resolve2({
261
+ close
262
+ });
263
+ });
264
+ } catch (err) {
265
+ reject(err);
266
+ }
267
+ });
268
+ };
237
269
  setRoot = (group) => {
238
270
  if (this.rootGroup) {
239
271
  throw new Error("Can only set root group once");
@@ -257,6 +257,13 @@ type Events = {
257
257
  'new-connection': (connection: ToolkitConnection) => void;
258
258
  'closed-connection': (connection: ToolkitConnection) => void;
259
259
  };
260
+ type ToolkitServerListenerOptions = {
261
+ port: number;
262
+ host?: string;
263
+ };
264
+ type ToolkitServerListener = {
265
+ close: () => void;
266
+ };
260
267
  declare class Toolkit implements Parent, Listenable<Events> {
261
268
  private readonly options;
262
269
  /**
@@ -267,10 +274,12 @@ declare class Toolkit implements Parent, Listenable<Events> {
267
274
  private rootGroup;
268
275
  /** @hidden */
269
276
  private readonly events;
277
+ private readonly server;
270
278
  constructor(options?: Partial<ToolkitOptions>);
271
279
  addListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
272
280
  removeListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
273
281
  start: (opts: InitializationOptions) => void;
282
+ listen: ({ port, host, }: ToolkitServerListenerOptions) => Promise<ToolkitServerListener>;
274
283
  setRoot: (group: Group) => void;
275
284
  log(): _arcanejs_protocol_logging.Logger | null;
276
285
  getConnections: () => ToolkitConnection[];
@@ -282,4 +291,4 @@ declare class Toolkit implements Parent, Listenable<Events> {
282
291
  private onMessage;
283
292
  }
284
293
 
285
- export { type AnyComponent as A, Button as B, EventEmitter as E, Group as G, type InternalProps$1 as I, type Listenable as L, type Parent as P, Toolkit as T, type ToolkitConnection as a, type ToolkitOptions as b, GroupHeader as c, Base as d, BaseParent as e, type Events$2 as f, type ButtonMode as g, type Props$1 as h, type Events$1 as i, type InternalProps as j, type Props as k };
294
+ export { type AnyComponent as A, Button as B, EventEmitter as E, Group as G, type InternalProps$1 as I, type Listenable as L, type Parent as P, Toolkit as T, type ToolkitConnection as a, type ToolkitServerListenerOptions as b, type ToolkitServerListener as c, type ToolkitOptions as d, GroupHeader as e, Base as f, BaseParent as g, type Events$2 as h, type ButtonMode as i, type Props$1 as j, type Events$1 as k, type InternalProps as l, type Props as m };
@@ -257,6 +257,13 @@ type Events = {
257
257
  'new-connection': (connection: ToolkitConnection) => void;
258
258
  'closed-connection': (connection: ToolkitConnection) => void;
259
259
  };
260
+ type ToolkitServerListenerOptions = {
261
+ port: number;
262
+ host?: string;
263
+ };
264
+ type ToolkitServerListener = {
265
+ close: () => void;
266
+ };
260
267
  declare class Toolkit implements Parent, Listenable<Events> {
261
268
  private readonly options;
262
269
  /**
@@ -267,10 +274,12 @@ declare class Toolkit implements Parent, Listenable<Events> {
267
274
  private rootGroup;
268
275
  /** @hidden */
269
276
  private readonly events;
277
+ private readonly server;
270
278
  constructor(options?: Partial<ToolkitOptions>);
271
279
  addListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
272
280
  removeListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
273
281
  start: (opts: InitializationOptions) => void;
282
+ listen: ({ port, host, }: ToolkitServerListenerOptions) => Promise<ToolkitServerListener>;
274
283
  setRoot: (group: Group) => void;
275
284
  log(): _arcanejs_protocol_logging.Logger | null;
276
285
  getConnections: () => ToolkitConnection[];
@@ -282,4 +291,4 @@ declare class Toolkit implements Parent, Listenable<Events> {
282
291
  private onMessage;
283
292
  }
284
293
 
285
- export { type AnyComponent as A, Button as B, EventEmitter as E, Group as G, type InternalProps$1 as I, type Listenable as L, type Parent as P, Toolkit as T, type ToolkitConnection as a, type ToolkitOptions as b, GroupHeader as c, Base as d, BaseParent as e, type Events$2 as f, type ButtonMode as g, type Props$1 as h, type Events$1 as i, type InternalProps as j, type Props as k };
294
+ export { type AnyComponent as A, Button as B, EventEmitter as E, Group as G, type InternalProps$1 as I, type Listenable as L, type Parent as P, Toolkit as T, type ToolkitConnection as a, type ToolkitServerListenerOptions as b, type ToolkitServerListener as c, type ToolkitOptions as d, GroupHeader as e, Base as f, BaseParent as g, type Events$2 as h, type ButtonMode as i, type Props$1 as j, type Events$1 as k, type InternalProps as l, type Props as m };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcanejs/toolkit",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "private": false,
5
5
  "description": "Build web-accessible control interfaces for your long-running Node.js processes",
6
6
  "keywords": [
@@ -114,7 +114,7 @@
114
114
  "styled-components": "^6.1.13",
115
115
  "tsup": "^8.1.0",
116
116
  "typescript": "^5.3.3",
117
- "@arcanejs/toolkit-frontend": "^0.8.0",
117
+ "@arcanejs/toolkit-frontend": "^0.9.0",
118
118
  "@arcanejs/eslint-config": "^0.0.0",
119
119
  "@arcanejs/typescript-config": "^0.0.0"
120
120
  },
@@ -132,7 +132,7 @@
132
132
  "react": "^18",
133
133
  "react-dom": "18.3.1",
134
134
  "styled-components": "^6.1.13",
135
- "@arcanejs/toolkit-frontend": "^0.8.0"
135
+ "@arcanejs/toolkit-frontend": "^0.9.0"
136
136
  },
137
137
  "peerDependenciesMeta": {
138
138
  "@arcanejs/toolkit-frontend": {