@arcanejs/toolkit 5.0.1 → 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 +55 -24
  28. package/dist/index.mjs +46 -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
@@ -191,7 +191,8 @@ var Toolkit = (_class2 = class {
191
191
  __init6() {this.rootGroup = null}
192
192
  /** @hidden */
193
193
  __init7() {this.events = new (0, _chunkWN3GXVUEjs.EventEmitter)()}
194
- 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);
195
196
  this.options = {
196
197
  ...DEFAULT_LIGHT_DESK_OPTIONS,
197
198
  ...options
@@ -201,25 +202,20 @@ var Toolkit = (_class2 = class {
201
202
  `path must start and end with "/", set to: ${this.options.path}`
202
203
  );
203
204
  }
204
- }
205
- __init8() {this.addListener = this.events.addListener}
206
- __init9() {this.removeListener = this.events.removeListener}
207
- __init10() {this.start = (opts) => {
208
- const server = new Server(
205
+ this.server = new Server(
209
206
  this.options,
210
207
  this.onNewConnection,
211
208
  this.onClosedConnection,
212
209
  this.onMessage,
213
210
  this.options.log
214
211
  );
212
+ }
213
+ __init8() {this.addListener = this.events.addListener}
214
+ __init9() {this.removeListener = this.events.removeListener}
215
+ __init10() {this.start = (opts) => {
215
216
  if (opts.mode === "automatic") {
216
- const httpServer = _http.createServer.call(void 0, server.handleHttpRequest);
217
- const wss = new (0, _ws.WebSocketServer)({
218
- server: httpServer
219
- });
220
- wss.on("connection", server.handleWsConnection);
221
- const url = `http://localhost:${opts.port}${this.options.path}`;
222
- httpServer.listen(opts.port, () => {
217
+ this.listen({ port: opts.port }).then(() => {
218
+ const url = `http://localhost:${opts.port}${this.options.path}`;
223
219
  _optionalChain([opts, 'access', _49 => _49.onReady, 'optionalCall', _50 => _50(url)]);
224
220
  _optionalChain([this, 'access', _51 => _51.options, 'access', _52 => _52.log, 'optionalAccess', _53 => _53.info, 'call', _54 => _54(`Light Desk Started: ${url}`)]);
225
221
  });
@@ -227,15 +223,50 @@ var Toolkit = (_class2 = class {
227
223
  const wss = new (0, _ws.WebSocketServer)({
228
224
  server: opts.server
229
225
  });
230
- wss.on("connection", server.handleWsConnection);
231
- 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);
232
228
  } else if (opts.mode === "manual") {
233
- opts.setup(server);
229
+ opts.setup(this.server);
234
230
  } else {
235
231
  throw new Error(`Unsupported mode`);
236
232
  }
237
233
  }}
238
- __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) => {
239
270
  if (this.rootGroup) {
240
271
  throw new Error("Can only set root group once");
241
272
  }
@@ -245,10 +276,10 @@ var Toolkit = (_class2 = class {
245
276
  log() {
246
277
  return _nullishCoalesce(this.options.log, () => ( null));
247
278
  }
248
- __init12() {this.getConnections = () => {
279
+ __init13() {this.getConnections = () => {
249
280
  return [...this.connections.values()].map((c) => c.publicConnection);
250
281
  }}
251
- __init13() {this.updateTree = _lodash2.default.throttle(
282
+ __init14() {this.updateTree = _lodash2.default.throttle(
252
283
  () => {
253
284
  setImmediate(() => {
254
285
  if (!this.rootGroup) return;
@@ -265,13 +296,13 @@ var Toolkit = (_class2 = class {
265
296
  10,
266
297
  { leading: true, trailing: true }
267
298
  )}
268
- __init14() {this.removeChild = (component) => {
299
+ __init15() {this.removeChild = (component) => {
269
300
  if (this.rootGroup === component) {
270
301
  this.rootGroup = null;
271
302
  component.setParent(null);
272
303
  }
273
304
  }}
274
- __init15() {this.onNewConnection = (connection) => {
305
+ __init16() {this.onNewConnection = (connection) => {
275
306
  const lastTreeSent = _nullishCoalesce(_optionalChain([this, 'access', _55 => _55.rootGroup, 'optionalAccess', _56 => _56.getProtoInfo, 'call', _57 => _57(this.componentIDMap)]), () => ( void 0));
276
307
  const uuid = _uuid.v4.call(void 0, );
277
308
  const publicConnection = {
@@ -292,7 +323,7 @@ var Toolkit = (_class2 = class {
292
323
  });
293
324
  }
294
325
  }}
295
- __init16() {this.onClosedConnection = (connection) => {
326
+ __init17() {this.onClosedConnection = (connection) => {
296
327
  _optionalChain([this, 'access', _58 => _58.log, 'call', _59 => _59(), 'optionalAccess', _60 => _60.debug, 'call', _61 => _61("removing connection")]);
297
328
  const con = this.connections.get(connection);
298
329
  this.connections.delete(connection);
@@ -300,7 +331,7 @@ var Toolkit = (_class2 = class {
300
331
  this.events.emit("closed-connection", con.publicConnection);
301
332
  }
302
333
  }}
303
- __init17() {this.handleCall = async (connection, publicConnection, call) => {
334
+ __init18() {this.handleCall = async (connection, publicConnection, call) => {
304
335
  try {
305
336
  const rg = this.rootGroup;
306
337
  if (rg) {
@@ -330,7 +361,7 @@ var Toolkit = (_class2 = class {
330
361
  });
331
362
  }
332
363
  }}
333
- __init18() {this.onMessage = (connection, message) => {
364
+ __init19() {this.onMessage = (connection, message) => {
334
365
  const con = this.connections.get(connection);
335
366
  if (!con) {
336
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
@@ -191,6 +191,7 @@ var Toolkit = class {
191
191
  rootGroup = null;
192
192
  /** @hidden */
193
193
  events = new EventEmitter();
194
+ server;
194
195
  constructor(options = {}) {
195
196
  this.options = {
196
197
  ...DEFAULT_LIGHT_DESK_OPTIONS,
@@ -201,25 +202,20 @@ var Toolkit = class {
201
202
  `path must start and end with "/", set to: ${this.options.path}`
202
203
  );
203
204
  }
204
- }
205
- addListener = this.events.addListener;
206
- removeListener = this.events.removeListener;
207
- start = (opts) => {
208
- const server = new Server(
205
+ this.server = new Server(
209
206
  this.options,
210
207
  this.onNewConnection,
211
208
  this.onClosedConnection,
212
209
  this.onMessage,
213
210
  this.options.log
214
211
  );
212
+ }
213
+ addListener = this.events.addListener;
214
+ removeListener = this.events.removeListener;
215
+ start = (opts) => {
215
216
  if (opts.mode === "automatic") {
216
- const httpServer = createServer(server.handleHttpRequest);
217
- const wss = new WebSocketServer({
218
- server: httpServer
219
- });
220
- wss.on("connection", server.handleWsConnection);
221
- const url = `http://localhost:${opts.port}${this.options.path}`;
222
- httpServer.listen(opts.port, () => {
217
+ this.listen({ port: opts.port }).then(() => {
218
+ const url = `http://localhost:${opts.port}${this.options.path}`;
223
219
  opts.onReady?.(url);
224
220
  this.options.log?.info(`Light Desk Started: ${url}`);
225
221
  });
@@ -227,14 +223,49 @@ var Toolkit = class {
227
223
  const wss = new WebSocketServer({
228
224
  server: opts.server
229
225
  });
230
- wss.on("connection", server.handleWsConnection);
231
- 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);
232
228
  } else if (opts.mode === "manual") {
233
- opts.setup(server);
229
+ opts.setup(this.server);
234
230
  } else {
235
231
  throw new Error(`Unsupported mode`);
236
232
  }
237
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
+ };
238
269
  setRoot = (group) => {
239
270
  if (this.rootGroup) {
240
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.1",
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,8 +114,8 @@
114
114
  "styled-components": "^6.1.13",
115
115
  "tsup": "^8.1.0",
116
116
  "typescript": "^5.3.3",
117
+ "@arcanejs/toolkit-frontend": "^0.9.0",
117
118
  "@arcanejs/eslint-config": "^0.0.0",
118
- "@arcanejs/toolkit-frontend": "^0.8.0",
119
119
  "@arcanejs/typescript-config": "^0.0.0"
120
120
  },
121
121
  "dependencies": {
@@ -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": {