@arcanejs/toolkit 7.0.0 → 9.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 (71) hide show
  1. package/dist/backend/components/base.d.mts +2 -1
  2. package/dist/backend/components/base.d.ts +2 -1
  3. package/dist/backend/components/base.js +2 -2
  4. package/dist/backend/components/base.mjs +1 -1
  5. package/dist/backend/components/button.d.mts +2 -1
  6. package/dist/backend/components/button.d.ts +2 -1
  7. package/dist/backend/components/button.js +3 -3
  8. package/dist/backend/components/button.mjs +2 -2
  9. package/dist/backend/components/group.d.mts +2 -1
  10. package/dist/backend/components/group.d.ts +2 -1
  11. package/dist/backend/components/group.js +3 -3
  12. package/dist/backend/components/group.mjs +2 -2
  13. package/dist/backend/components/label.d.mts +2 -1
  14. package/dist/backend/components/label.d.ts +2 -1
  15. package/dist/backend/components/label.js +3 -3
  16. package/dist/backend/components/label.mjs +2 -2
  17. package/dist/backend/components/rect.d.mts +2 -1
  18. package/dist/backend/components/rect.d.ts +2 -1
  19. package/dist/backend/components/rect.js +3 -3
  20. package/dist/backend/components/rect.mjs +2 -2
  21. package/dist/backend/components/slider-button.d.mts +2 -1
  22. package/dist/backend/components/slider-button.d.ts +2 -1
  23. package/dist/backend/components/slider-button.js +3 -3
  24. package/dist/backend/components/slider-button.mjs +2 -2
  25. package/dist/backend/components/switch.d.mts +2 -1
  26. package/dist/backend/components/switch.d.ts +2 -1
  27. package/dist/backend/components/switch.js +3 -3
  28. package/dist/backend/components/switch.mjs +2 -2
  29. package/dist/backend/components/tabs.d.mts +2 -1
  30. package/dist/backend/components/tabs.d.ts +2 -1
  31. package/dist/backend/components/tabs.js +3 -3
  32. package/dist/backend/components/tabs.mjs +2 -2
  33. package/dist/backend/components/text-input.d.mts +2 -1
  34. package/dist/backend/components/text-input.d.ts +2 -1
  35. package/dist/backend/components/text-input.js +3 -3
  36. package/dist/backend/components/text-input.mjs +2 -2
  37. package/dist/backend/components/timeline.d.mts +2 -1
  38. package/dist/backend/components/timeline.d.ts +2 -1
  39. package/dist/backend/components/timeline.js +3 -3
  40. package/dist/backend/components/timeline.mjs +2 -2
  41. package/dist/{chunk-IV3AE3CW.js → chunk-2R23ER4K.js} +3 -3
  42. package/dist/{chunk-R5OA7LLZ.mjs → chunk-5K7DK7CW.mjs} +1 -1
  43. package/dist/{chunk-RJLYYTZ6.mjs → chunk-7WTSYZOS.mjs} +1 -1
  44. package/dist/{chunk-2K4UT5QB.js → chunk-AYMITMVR.js} +3 -3
  45. package/dist/{chunk-K6V55JTG.mjs → chunk-KO24S32V.mjs} +1 -1
  46. package/dist/{chunk-XSKWLJOQ.js → chunk-KRGLXKY2.js} +4 -4
  47. package/dist/{chunk-JHWFQLLE.mjs → chunk-MNEFCU3M.mjs} +1 -1
  48. package/dist/{chunk-TF7N4O5G.js → chunk-NEFCI6N6.js} +2 -2
  49. package/dist/{chunk-TULW7CRV.mjs → chunk-NJW4ZG4X.mjs} +1 -1
  50. package/dist/{chunk-MHSAHTVN.mjs → chunk-QBZB56TQ.mjs} +1 -1
  51. package/dist/{chunk-UHEZQR2Q.js → chunk-QHCNKTKW.js} +2 -2
  52. package/dist/{chunk-4AGKM5NT.js → chunk-RELZ3VTJ.js} +3 -3
  53. package/dist/{chunk-7MQHRTBE.mjs → chunk-RGLKNCJ3.mjs} +1 -1
  54. package/dist/{chunk-A3RWE7HZ.js → chunk-SPYBETRJ.js} +3 -3
  55. package/dist/{chunk-GONHNB6V.mjs → chunk-UTTTCTUQ.mjs} +26 -5
  56. package/dist/{chunk-GXJ3JRRK.mjs → chunk-VD6S32ED.mjs} +1 -1
  57. package/dist/{chunk-5B65Q7RL.js → chunk-VTNAO4KC.js} +2 -2
  58. package/dist/{chunk-6PS3Q66F.mjs → chunk-Y3NPWW27.mjs} +1 -1
  59. package/dist/{chunk-CVY55KAR.js → chunk-Y5FC42KD.js} +3 -3
  60. package/dist/{chunk-WN3GXVUE.js → chunk-YNOJTE3G.js} +26 -5
  61. package/dist/frontend/entrypoint.js +43 -2
  62. package/dist/frontend/entrypoint.js.map +2 -2
  63. package/dist/frontend/index.js +69 -12
  64. package/dist/frontend/index.mjs +69 -12
  65. package/dist/index.d.mts +3 -2
  66. package/dist/index.d.ts +3 -2
  67. package/dist/index.js +183 -64
  68. package/dist/index.mjs +154 -35
  69. package/dist/{toolkit-Bglbv3ix.d.ts → toolkit-CKA9A4r-.d.ts} +116 -93
  70. package/dist/{toolkit-BPqxbDbk.d.mts → toolkit-GNytD78y.d.mts} +116 -93
  71. package/package.json +8 -8
package/dist/index.mjs CHANGED
@@ -1,38 +1,38 @@
1
1
  import {
2
2
  Tab,
3
3
  Tabs
4
- } from "./chunk-R5OA7LLZ.mjs";
4
+ } from "./chunk-5K7DK7CW.mjs";
5
5
  import {
6
6
  TextInput
7
- } from "./chunk-GXJ3JRRK.mjs";
7
+ } from "./chunk-VD6S32ED.mjs";
8
8
  import {
9
9
  Timeline
10
- } from "./chunk-6PS3Q66F.mjs";
10
+ } from "./chunk-Y3NPWW27.mjs";
11
11
  import {
12
12
  IDMap
13
13
  } from "./chunk-RGHJEMWG.mjs";
14
14
  import {
15
15
  Button
16
- } from "./chunk-7MQHRTBE.mjs";
16
+ } from "./chunk-RGLKNCJ3.mjs";
17
17
  import {
18
18
  Group,
19
19
  GroupHeader
20
- } from "./chunk-TULW7CRV.mjs";
20
+ } from "./chunk-NJW4ZG4X.mjs";
21
21
  import {
22
22
  Label
23
- } from "./chunk-JHWFQLLE.mjs";
23
+ } from "./chunk-MNEFCU3M.mjs";
24
24
  import {
25
25
  Rect
26
- } from "./chunk-RJLYYTZ6.mjs";
26
+ } from "./chunk-7WTSYZOS.mjs";
27
27
  import {
28
28
  SliderButton
29
- } from "./chunk-K6V55JTG.mjs";
29
+ } from "./chunk-KO24S32V.mjs";
30
30
  import {
31
31
  Switch
32
- } from "./chunk-MHSAHTVN.mjs";
32
+ } from "./chunk-QBZB56TQ.mjs";
33
33
  import {
34
34
  EventEmitter
35
- } from "./chunk-GONHNB6V.mjs";
35
+ } from "./chunk-UTTTCTUQ.mjs";
36
36
  import {
37
37
  __require
38
38
  } from "./chunk-Y6FXYEAI.mjs";
@@ -69,12 +69,16 @@ var distDir = () => {
69
69
  throw new Error(`Server running from unknown location: ${__dirname}`);
70
70
  }
71
71
  };
72
+ var UPLOAD_URL = /^\/upload\/([0-9a-f]+)$/;
73
+ var DOWNLOAD_URL = /^\/download\/([0-9a-f]+)$/;
72
74
  var Server = class {
73
- constructor(options, onNewConnection, onClosedConnection, onMessage, log) {
75
+ constructor(options, onNewConnection, onClosedConnection, onMessage, onUpload, onDownload, log) {
74
76
  this.options = options;
75
77
  this.onNewConnection = onNewConnection;
76
78
  this.onClosedConnection = onClosedConnection;
77
79
  this.onMessage = onMessage;
80
+ this.onUpload = onUpload;
81
+ this.onDownload = onDownload;
78
82
  this.log = log;
79
83
  this.title = options.title ?? "@arcanejs";
80
84
  }
@@ -273,8 +277,45 @@ var Server = class {
273
277
  }
274
278
  }
275
279
  }
276
- res.writeHead(404, { "Content-Type": "text/plain" });
277
- res.end("not found", "utf-8");
280
+ const [uploadMatch, downloadMatch] = [
281
+ UPLOAD_URL.exec(pathname),
282
+ DOWNLOAD_URL.exec(pathname)
283
+ ];
284
+ if (uploadMatch?.[1]) {
285
+ const id = uploadMatch[1];
286
+ this.log?.debug("Upload request for id: %s", id);
287
+ this.onUpload(id, req).then(() => {
288
+ res.writeHead(200, { "Content-Type": "text/plain" });
289
+ res.end("Upload successful", "utf-8");
290
+ }).catch((cause) => {
291
+ const error = new Error(`Error handling upload for id ${id}`, {
292
+ cause
293
+ });
294
+ this.log?.error(error);
295
+ res.writeHead(500, { "Content-Type": "text/plain" });
296
+ res.end("Error handling upload", "utf-8");
297
+ });
298
+ } else if (downloadMatch?.[1]) {
299
+ const id = downloadMatch[1];
300
+ this.log?.debug("Download request for id: %s", id);
301
+ this.onDownload(id).then((handler) => handler()).then(({ stream, headers }) => {
302
+ res.writeHead(200, {
303
+ "Content-Type": "application/octet-stream",
304
+ ...headers
305
+ });
306
+ stream.pipe(res);
307
+ }).catch((cause) => {
308
+ const error = new Error(`Error handling download for id ${id}`, {
309
+ cause
310
+ });
311
+ this.log?.error(error);
312
+ res.writeHead(500, { "Content-Type": "text/plain" });
313
+ res.end("Error handling download", "utf-8");
314
+ });
315
+ } else {
316
+ res.writeHead(404, { "Content-Type": "text/plain" });
317
+ res.end("not found", "utf-8");
318
+ }
278
319
  };
279
320
  parsePathname = (url) => {
280
321
  if (!url) return "";
@@ -327,6 +368,7 @@ var Server = class {
327
368
  import { WebSocketServer } from "ws";
328
369
  import { createServer } from "http";
329
370
  import { v4 as uuidv4 } from "uuid";
371
+ import { randomBytes } from "node:crypto";
330
372
  var normalizeClockSyncOptions = (clockSync) => {
331
373
  if (!clockSync) {
332
374
  return null;
@@ -353,6 +395,8 @@ var Toolkit = class {
353
395
  /** @hidden */
354
396
  events = new EventEmitter();
355
397
  server;
398
+ uploads = /* @__PURE__ */ new Map();
399
+ downloads = /* @__PURE__ */ new Map();
356
400
  constructor(options = {}) {
357
401
  this.options = {
358
402
  ...DEFAULT_LIGHT_DESK_OPTIONS,
@@ -369,6 +413,8 @@ var Toolkit = class {
369
413
  this.onNewConnection,
370
414
  this.onClosedConnection,
371
415
  this.onMessage,
416
+ this.onUpload,
417
+ this.onDownload,
372
418
  this.options.log
373
419
  );
374
420
  }
@@ -502,6 +548,25 @@ var Toolkit = class {
502
548
  const con = this.connections.get(connection);
503
549
  this.connections.delete(connection);
504
550
  if (con) {
551
+ let inProgressUploads = 0;
552
+ let inProgressDownloads = 0;
553
+ for (const [id, upload] of this.uploads.entries()) {
554
+ if (upload.connection === connection) {
555
+ this.uploads.delete(id);
556
+ inProgressUploads++;
557
+ }
558
+ }
559
+ for (const [id, download] of this.downloads.entries()) {
560
+ if (download.connection === connection) {
561
+ this.downloads.delete(id);
562
+ inProgressDownloads++;
563
+ }
564
+ }
565
+ if (inProgressUploads > 0 || inProgressDownloads > 0) {
566
+ this.log()?.info(
567
+ `Connection closed with ${inProgressUploads} in-progress uploads and ${inProgressDownloads} in-progress downloads`
568
+ );
569
+ }
505
570
  this.events.emit("closed-connection", con.publicConnection);
506
571
  }
507
572
  };
@@ -509,12 +574,32 @@ var Toolkit = class {
509
574
  try {
510
575
  const rg = this.rootGroup;
511
576
  if (rg) {
512
- const returnValue = await new Promise(
577
+ const handlerValue = await new Promise(
513
578
  (resolve2, reject) => rg.routeCall(this.componentIDMap, call, publicConnection, {
514
579
  resolve: resolve2,
515
580
  reject
516
581
  })
517
582
  );
583
+ let returnValue;
584
+ if (call.type === "component-call") {
585
+ returnValue = handlerValue;
586
+ } else if (call.type === "component-call-upload") {
587
+ const uploadHandler = handlerValue;
588
+ const secureId = randomBytes(32).toString("hex");
589
+ this.uploads.set(secureId, {
590
+ connection,
591
+ handler: uploadHandler
592
+ });
593
+ returnValue = secureId;
594
+ } else if (call.type === "component-call-download") {
595
+ const downloadHandler = handlerValue;
596
+ const secureId = randomBytes(32).toString("hex");
597
+ this.downloads.set(secureId, {
598
+ connection,
599
+ handler: downloadHandler
600
+ });
601
+ returnValue = secureId;
602
+ }
518
603
  connection.sendMessage({
519
604
  type: "call-response",
520
605
  namespace: call.namespace,
@@ -525,13 +610,15 @@ var Toolkit = class {
525
610
  } else {
526
611
  throw new Error("No root group set");
527
612
  }
528
- } catch (err) {
613
+ } catch (cause) {
614
+ const error = new Error(`Error handling call`, { cause });
615
+ this.log()?.error(error);
529
616
  connection.sendMessage({
530
617
  type: "call-response",
531
618
  namespace: call.namespace,
532
619
  requestId: call.requestId,
533
620
  success: false,
534
- errorMessage: `${err}`
621
+ errorMessage: `${cause}`
535
622
  });
536
623
  }
537
624
  };
@@ -547,25 +634,57 @@ var Toolkit = class {
547
634
  message,
548
635
  publicConnection.uuid
549
636
  );
550
- switch (message.type) {
551
- case "component-message":
552
- if (this.rootGroup)
553
- this.rootGroup.routeMessage(
554
- this.componentIDMap,
555
- message,
556
- publicConnection
557
- );
558
- break;
559
- case "component-call":
560
- this.handleCall(connection, publicConnection, message);
561
- break;
562
- case "ping": {
563
- connection.sendMessage({
564
- type: "pong",
565
- pingId: message.pingId,
566
- serverTimeMillis: Date.now()
567
- });
568
- break;
637
+ try {
638
+ switch (message.type) {
639
+ case "component-message":
640
+ if (this.rootGroup)
641
+ this.rootGroup.routeMessage(
642
+ this.componentIDMap,
643
+ message,
644
+ publicConnection
645
+ );
646
+ break;
647
+ case "component-call":
648
+ case "component-call-upload":
649
+ case "component-call-download":
650
+ this.handleCall(connection, publicConnection, message);
651
+ break;
652
+ case "ping": {
653
+ connection.sendMessage({
654
+ type: "pong",
655
+ pingId: message.pingId,
656
+ serverTimeMillis: Date.now()
657
+ });
658
+ break;
659
+ }
660
+ }
661
+ } catch (cause) {
662
+ const error = new Error(
663
+ `Error handling message: ${JSON.stringify(message)}`,
664
+ { cause }
665
+ );
666
+ this.log()?.error(error);
667
+ }
668
+ };
669
+ onUpload = async (id, data) => {
670
+ const upload = this.uploads.get(id);
671
+ if (!upload) {
672
+ throw new Error(`No upload handler found for id: ${id}`);
673
+ }
674
+ await upload.handler(data);
675
+ this.uploads.delete(id);
676
+ };
677
+ onDownload = async (id) => {
678
+ const download = this.downloads.get(id);
679
+ if (!download) {
680
+ throw new Error(`No download handler found for id: ${id}`);
681
+ }
682
+ return download.handler;
683
+ };
684
+ sendNotification = (notification, filter) => {
685
+ for (const [connection, meta] of this.connections.entries()) {
686
+ if (!filter || filter(meta.publicConnection)) {
687
+ connection.sendMessage(notification);
569
688
  }
570
689
  }
571
690
  };
@@ -4,10 +4,115 @@ import _ from 'lodash';
4
4
  import * as http from 'http';
5
5
  import { Application } from 'express';
6
6
  import { WebSocket } from 'ws';
7
- import { ClientMessage, ServerMessage, BaseComponentProto, AnyClientComponentMessage, AnyClientComponentCall, ReturnForPair } from '@arcanejs/protocol';
7
+ import { BaseComponentProto, AnyClientComponentMessage, AnyClientComponentCall, AnyClientComponentCallUpload, AnyClientComponentCallDownload, ReturnForPair, ClientMessage, ServerMessage, BaseNotificationMessage } from '@arcanejs/protocol';
8
+ import { Readable } from 'node:stream';
9
+ import { I as IDMap } from './id-map-DxQ3_gyA.js';
8
10
  import * as proto from '@arcanejs/protocol/core';
9
11
  import { GroupComponentStyle } from '@arcanejs/protocol/styles';
10
- import { I as IDMap } from './id-map-DxQ3_gyA.js';
12
+
13
+ type CallUploadResponse = (data: Readable) => Promise<void>;
14
+ type CallDownloadResponse = () => Promise<{
15
+ stream: Readable;
16
+ headers: Record<string, string>;
17
+ }>;
18
+ declare abstract class Base<Namespace extends string, Proto extends BaseComponentProto<Namespace, string>, Props, CallPairs = any, CallActions extends string & keyof CallPairs = any> {
19
+ /** @hidden */
20
+ private parent;
21
+ /** @hidden */
22
+ private readonly defaultProps;
23
+ /** @hidden */
24
+ private _props;
25
+ /** @hidden */
26
+ private _onPropsUpdated;
27
+ constructor(defaultProps: Props, props?: Partial<Props>, options?: {
28
+ onPropsUpdated?: (oldProps: Props) => void;
29
+ });
30
+ /**
31
+ * Call if
32
+ */
33
+ triggerInitialPropsUpdate: () => void;
34
+ log: () => Logger | null;
35
+ get props(): Props;
36
+ set props(props: Partial<Props>);
37
+ setProps: (props: Partial<Props>) => void;
38
+ updateProps: (updates: Partial<Props>) => void;
39
+ /** @hidden */
40
+ setParent(parent: Parent | null): void;
41
+ /** @hidden */
42
+ updateTree(): void;
43
+ /** @hidden */
44
+ abstract getProtoInfo(idMap: IDMap, context: ToolkitRenderContext): Proto;
45
+ /** @hidden */
46
+ handleMessage(_message: AnyClientComponentMessage, _connection: ToolkitConnection): void;
47
+ /** @hidden */
48
+ handleAnyCall(message: AnyClientComponentCall | AnyClientComponentCallUpload | AnyClientComponentCallDownload, _connection: ToolkitConnection): Promise<ReturnForPair<CallPairs, CallActions> | CallUploadResponse | CallDownloadResponse>;
49
+ /** @hidden */
50
+ handleCall(_call: AnyClientComponentCall, _connection: ToolkitConnection): Promise<ReturnForPair<CallPairs, CallActions>>;
51
+ /** @hidden */
52
+ handleCallUpload(_call: AnyClientComponentCallUpload, _connection: ToolkitConnection): Promise<CallUploadResponse>;
53
+ /** @hidden */
54
+ handleCallDownload(_call: AnyClientComponentCallDownload, _connection: ToolkitConnection): Promise<CallDownloadResponse>;
55
+ routeMessage(_idMap: IDMap, _message: AnyClientComponentMessage, _connection: ToolkitConnection): void;
56
+ routeCall(_idMap: IDMap, _call: AnyClientComponentCall | AnyClientComponentCallUpload | AnyClientComponentCallDownload, _connection: ToolkitConnection, _callbacks: {
57
+ resolve: (result: unknown) => void;
58
+ reject: (error: unknown) => void;
59
+ }): void;
60
+ }
61
+ type AnyComponent = Base<string, BaseComponentProto<string, string>, any>;
62
+ /** @hidden */
63
+ interface Parent {
64
+ updateTree(): void;
65
+ removeChild(component: AnyComponent): void;
66
+ log(): Logger | null;
67
+ }
68
+ declare abstract class BaseParent<Namespace extends string, Proto extends BaseComponentProto<Namespace, string>, T, CallPairs = any, CallActions extends string & keyof CallPairs = any> extends Base<Namespace, Proto, T, CallPairs, CallActions> implements Parent {
69
+ /** @hidden */
70
+ private children;
71
+ abstract validateChildren(children: AnyComponent[]): void;
72
+ appendChildren: <CS extends AnyComponent[]>(...children: CS) => CS;
73
+ appendChild: <C extends AnyComponent>(child: C) => C;
74
+ removeChild: (component: AnyComponent) => void;
75
+ removeAllChildren: () => void;
76
+ /**
77
+ * Return all children components that messages need to be routed to
78
+ */
79
+ getChildren: () => readonly AnyComponent[];
80
+ /**
81
+ * TODO: we can do this better, right now it broadcasts the message to all
82
+ * components of the tree
83
+ *
84
+ * @hidden
85
+ */
86
+ routeMessage(idMap: IDMap, message: AnyClientComponentMessage, connection: ToolkitConnection): void;
87
+ routeCall(idMap: IDMap, call: AnyClientComponentCall | AnyClientComponentCallUpload | AnyClientComponentCallDownload, connection: ToolkitConnection, callbacks: {
88
+ resolve: (result: unknown) => void;
89
+ reject: (error: unknown) => void;
90
+ }): Promise<void>;
91
+ insertBefore(child: AnyComponent, beforeChild: AnyComponent): void;
92
+ }
93
+ interface Listenable<Map extends Record<string, (...args: any[]) => void>> {
94
+ addListener<T extends keyof Map>(type: T, listener: Map[T]): void;
95
+ removeListener<T extends keyof Map>(type: T, listener: Map[T]): void;
96
+ }
97
+ declare class EventEmitter<Map extends Record<string, (...args: any[]) => void>> implements Listenable<Map> {
98
+ private readonly listeners;
99
+ addListener: <T extends keyof Map>(type: T, listener: Map[T]) => void;
100
+ removeListener: <T extends keyof Map>(type: T, listener: Map[T]) => void;
101
+ emit: <T extends keyof Map>(type: T, ...args: Parameters<Map[T]>) => Promise<ReturnType<Map[T]>[]>;
102
+ /**
103
+ * Like {@link emit},
104
+ * but ensures only a single listener exists and returns its result.
105
+ */
106
+ call: <T extends keyof Map>(type: T, ...args: Parameters<Map[T]>) => Promise<ReturnType<Map[T]>>;
107
+ /**
108
+ * Process prop changes to update listeners
109
+ */
110
+ processPropChanges: <Mapping extends Record<string, keyof Map>, Props extends { [key in keyof Mapping]?: Map[Mapping[key]] | null | undefined; }>(
111
+ /**
112
+ * Mapping from prop key to event name
113
+ */
114
+ mapping: Mapping, oldProps: Props, newProps: Props) => void;
115
+ }
11
116
 
12
117
  interface Connection {
13
118
  sendMessage(msg: ServerMessage): void;
@@ -17,12 +122,14 @@ declare class Server<TAdditionalFiles extends ToolkitAdditionalFiles = Record<ne
17
122
  private readonly onNewConnection;
18
123
  private readonly onClosedConnection;
19
124
  private readonly onMessage;
125
+ private readonly onUpload;
126
+ private readonly onDownload;
20
127
  private readonly log?;
21
128
  private staticFiles;
22
129
  private htmlContext;
23
130
  private staticFilesInitPromise;
24
131
  private readonly title;
25
- constructor(options: ToolkitOptions<TAdditionalFiles>, onNewConnection: (connection: Connection) => void, onClosedConnection: (connection: Connection) => void, onMessage: (connection: Connection, message: ClientMessage) => void, log?: Logger | undefined);
132
+ constructor(options: ToolkitOptions<TAdditionalFiles>, onNewConnection: (connection: Connection) => void, onClosedConnection: (connection: Connection) => void, onMessage: (connection: Connection, message: ClientMessage) => void, onUpload: (id: string, data: Readable) => Promise<void>, onDownload: (id: string) => Promise<CallDownloadResponse>, log?: Logger | undefined);
26
133
  private getEntrypointPaths;
27
134
  private fileExists;
28
135
  private ensureStaticFilesInitialized;
@@ -147,95 +254,6 @@ type InitializationOptions<TAdditionalFiles extends ToolkitAdditionalFiles = Rec
147
254
  setup: (server: Server<TAdditionalFiles>) => void;
148
255
  };
149
256
 
150
- declare abstract class Base<Namespace extends string, Proto extends BaseComponentProto<Namespace, string>, Props, CallPairs = any, CallActions extends string & keyof CallPairs = any> {
151
- /** @hidden */
152
- private parent;
153
- /** @hidden */
154
- private readonly defaultProps;
155
- /** @hidden */
156
- private _props;
157
- /** @hidden */
158
- private _onPropsUpdated;
159
- constructor(defaultProps: Props, props?: Partial<Props>, options?: {
160
- onPropsUpdated?: (oldProps: Props) => void;
161
- });
162
- /**
163
- * Call if
164
- */
165
- triggerInitialPropsUpdate: () => void;
166
- log: () => Logger | null;
167
- get props(): Props;
168
- set props(props: Partial<Props>);
169
- setProps: (props: Partial<Props>) => void;
170
- updateProps: (updates: Partial<Props>) => void;
171
- /** @hidden */
172
- setParent(parent: Parent | null): void;
173
- /** @hidden */
174
- updateTree(): void;
175
- /** @hidden */
176
- abstract getProtoInfo(idMap: IDMap, context: ToolkitRenderContext): Proto;
177
- /** @hidden */
178
- handleMessage(_message: AnyClientComponentMessage, _connection: ToolkitConnection): void;
179
- /** @hidden */
180
- handleCall(_call: AnyClientComponentCall, _connection: ToolkitConnection): Promise<ReturnForPair<CallPairs, CallActions>>;
181
- routeMessage(_idMap: IDMap, _message: AnyClientComponentMessage, _connection: ToolkitConnection): void;
182
- routeCall(_idMap: IDMap, _call: AnyClientComponentCall, _connection: ToolkitConnection, _callbacks: {
183
- resolve: (result: unknown) => void;
184
- reject: (error: unknown) => void;
185
- }): void;
186
- }
187
- type AnyComponent = Base<string, BaseComponentProto<string, string>, any>;
188
- /** @hidden */
189
- interface Parent {
190
- updateTree(): void;
191
- removeChild(component: AnyComponent): void;
192
- log(): Logger | null;
193
- }
194
- declare abstract class BaseParent<Namespace extends string, Proto extends BaseComponentProto<Namespace, string>, T, CallPairs = any, CallActions extends string & keyof CallPairs = any> extends Base<Namespace, Proto, T, CallPairs, CallActions> implements Parent {
195
- /** @hidden */
196
- private children;
197
- abstract validateChildren(children: AnyComponent[]): void;
198
- appendChildren: <CS extends AnyComponent[]>(...children: CS) => CS;
199
- appendChild: <C extends AnyComponent>(child: C) => C;
200
- removeChild: (component: AnyComponent) => void;
201
- removeAllChildren: () => void;
202
- /**
203
- * Return all children components that messages need to be routed to
204
- */
205
- getChildren: () => readonly AnyComponent[];
206
- /**
207
- * TODO: we can do this better, right now it broadcasts the message to all
208
- * components of the tree
209
- *
210
- * @hidden
211
- */
212
- routeMessage(idMap: IDMap, message: AnyClientComponentMessage, connection: ToolkitConnection): void;
213
- routeCall(idMap: IDMap, call: AnyClientComponentCall, connection: ToolkitConnection, callbacks: {
214
- resolve: (result: unknown) => void;
215
- reject: (error: unknown) => void;
216
- }): Promise<void>;
217
- insertBefore(child: AnyComponent, beforeChild: AnyComponent): void;
218
- }
219
- interface Listenable<Map extends Record<string, (...args: any[]) => void>> {
220
- addListener<T extends keyof Map>(type: T, listener: Map[T]): void;
221
- removeListener<T extends keyof Map>(type: T, listener: Map[T]): void;
222
- }
223
- declare class EventEmitter<Map extends Record<string, (...args: any[]) => void>> implements Listenable<Map> {
224
- private readonly listeners;
225
- addListener: <T extends keyof Map>(type: T, listener: Map[T]) => void;
226
- removeListener: <T extends keyof Map>(type: T, listener: Map[T]) => void;
227
- emit: <T extends keyof Map>(type: T, ...args: Parameters<Map[T]>) => Promise<ReturnType<Map[T]>[]>;
228
- /**
229
- * Like {@link emit},
230
- * but ensures only a single listener exists and returns its result.
231
- */
232
- call: <T extends keyof Map>(type: T, ...args: Parameters<Map[T]>) => Promise<ReturnType<Map[T]>>;
233
- /**
234
- * Process prop changes to update listeners
235
- */
236
- processPropChanges: <Mapping extends Record<string, keyof Map>, Props extends { [key in keyof Mapping]?: Map[Mapping[key]] | null | undefined; }>(mapping: Mapping, oldProps: Props, newProps: Props) => void;
237
- }
238
-
239
257
  type Events$2 = {
240
258
  click: (connection: ToolkitConnection) => void | Promise<void>;
241
259
  };
@@ -338,6 +356,8 @@ declare class Toolkit<TAdditionalFiles extends ToolkitAdditionalFiles = Record<n
338
356
  /** @hidden */
339
357
  private readonly events;
340
358
  private readonly server;
359
+ private readonly uploads;
360
+ private readonly downloads;
341
361
  constructor(options?: Partial<ToolkitOptions<TAdditionalFiles>>);
342
362
  addListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
343
363
  removeListener: <T extends keyof Events>(type: T, listener: Events[T]) => void;
@@ -352,6 +372,9 @@ declare class Toolkit<TAdditionalFiles extends ToolkitAdditionalFiles = Record<n
352
372
  private onClosedConnection;
353
373
  private handleCall;
354
374
  private onMessage;
375
+ private onUpload;
376
+ private onDownload;
377
+ sendNotification: (notification: BaseNotificationMessage<string, string>, filter?: (connection: ToolkitConnection) => boolean) => void;
355
378
  }
356
379
 
357
- 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 ToolkitRenderContext as b, type ToolkitServerListenerOptions as c, type ToolkitServerListener as d, type ToolkitAdditionalFiles as e, type ToolkitClockSyncOptions as f, type ToolkitCoreAssetRelativePath as g, type ToolkitHtmlPageContext as h, type ToolkitOptions as i, type ToolkitStaticFile as j, type ToolkitStaticFileResolver as k, GroupHeader as l, Base as m, BaseParent as n, type Events$2 as o, type ButtonMode as p, type Props$1 as q, type Events$1 as r, type InternalProps as s, type Props as t };
380
+ export { type AnyComponent as A, Button as B, type CallUploadResponse as C, 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 ToolkitRenderContext as b, type ToolkitServerListenerOptions as c, type ToolkitServerListener as d, type ToolkitAdditionalFiles as e, type ToolkitClockSyncOptions as f, type ToolkitCoreAssetRelativePath as g, type ToolkitHtmlPageContext as h, type ToolkitOptions as i, type ToolkitStaticFile as j, type ToolkitStaticFileResolver as k, GroupHeader as l, Base as m, BaseParent as n, type CallDownloadResponse as o, type Events$2 as p, type ButtonMode as q, type Props$1 as r, type Events$1 as s, type InternalProps as t, type Props as u };