@3plate/graph-core 0.1.9 → 0.1.10
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/index.cjs +104 -98
- package/dist/index.d.cts +45 -11
- package/dist/index.d.ts +45 -11
- package/dist/index.js +104 -98
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3717,11 +3717,11 @@ var WebSocketSource = class {
|
|
|
3717
3717
|
connectStartTime = null;
|
|
3718
3718
|
totalTimeoutMs = 1e4;
|
|
3719
3719
|
totalTimeoutTimer = null;
|
|
3720
|
-
constructor(
|
|
3721
|
-
this.url = url;
|
|
3722
|
-
this.onMessage = onMessage;
|
|
3723
|
-
this.onStatus = onStatus;
|
|
3724
|
-
this.reconnectMs = reconnectMs;
|
|
3720
|
+
constructor(args) {
|
|
3721
|
+
this.url = args.url;
|
|
3722
|
+
this.onMessage = args.onMessage;
|
|
3723
|
+
this.onStatus = args.onStatus;
|
|
3724
|
+
this.reconnectMs = args.reconnectMs ?? 1500;
|
|
3725
3725
|
}
|
|
3726
3726
|
connect() {
|
|
3727
3727
|
this.closedByUser = false;
|
|
@@ -3822,11 +3822,11 @@ var FileSource = class {
|
|
|
3822
3822
|
lastContent = "";
|
|
3823
3823
|
intervalMs = 1e3;
|
|
3824
3824
|
closed = false;
|
|
3825
|
-
constructor(
|
|
3826
|
-
this.url = url;
|
|
3827
|
-
this.onMessage = onMessage;
|
|
3828
|
-
this.onStatus = onStatus;
|
|
3829
|
-
this.intervalMs = intervalMs;
|
|
3825
|
+
constructor(args) {
|
|
3826
|
+
this.url = args.url;
|
|
3827
|
+
this.onMessage = args.onMessage;
|
|
3828
|
+
this.onStatus = args.onStatus;
|
|
3829
|
+
this.intervalMs = args.intervalMs ?? 1e3;
|
|
3830
3830
|
}
|
|
3831
3831
|
async connect() {
|
|
3832
3832
|
this.closed = false;
|
|
@@ -3888,6 +3888,68 @@ var FileSource = class {
|
|
|
3888
3888
|
}
|
|
3889
3889
|
};
|
|
3890
3890
|
|
|
3891
|
+
// src/api/sources/FileSystemSource.ts
|
|
3892
|
+
var FileSystemSource = class {
|
|
3893
|
+
handle = null;
|
|
3894
|
+
onMessage;
|
|
3895
|
+
onStatus;
|
|
3896
|
+
timer = null;
|
|
3897
|
+
lastSize = 0;
|
|
3898
|
+
filename;
|
|
3899
|
+
intervalMs;
|
|
3900
|
+
constructor(args) {
|
|
3901
|
+
this.filename = args.filename;
|
|
3902
|
+
this.onMessage = args.onMessage;
|
|
3903
|
+
this.onStatus = args.onStatus;
|
|
3904
|
+
this.intervalMs = args.intervalMs ?? 1e3;
|
|
3905
|
+
}
|
|
3906
|
+
async openDirectory() {
|
|
3907
|
+
try {
|
|
3908
|
+
const dir = await window.showDirectoryPicker?.();
|
|
3909
|
+
if (!dir) throw new Error("File System Access not supported or cancelled");
|
|
3910
|
+
const handle = await dir.getFileHandle(this.filename, { create: false });
|
|
3911
|
+
this.handle = handle;
|
|
3912
|
+
this.onStatus?.("opened", { file: this.filename });
|
|
3913
|
+
this.lastSize = 0;
|
|
3914
|
+
this.startPolling();
|
|
3915
|
+
} catch (e) {
|
|
3916
|
+
this.onStatus?.("error", e);
|
|
3917
|
+
}
|
|
3918
|
+
}
|
|
3919
|
+
close() {
|
|
3920
|
+
if (this.timer) {
|
|
3921
|
+
window.clearInterval(this.timer);
|
|
3922
|
+
this.timer = null;
|
|
3923
|
+
}
|
|
3924
|
+
this.handle = null;
|
|
3925
|
+
this.onStatus?.("closed");
|
|
3926
|
+
}
|
|
3927
|
+
startPolling() {
|
|
3928
|
+
if (this.timer) window.clearInterval(this.timer);
|
|
3929
|
+
this.timer = window.setInterval(() => this.readNewLines(), this.intervalMs);
|
|
3930
|
+
}
|
|
3931
|
+
async readNewLines() {
|
|
3932
|
+
try {
|
|
3933
|
+
if (!this.handle) return;
|
|
3934
|
+
this.onStatus?.("reading");
|
|
3935
|
+
const file = await this.handle.getFile();
|
|
3936
|
+
if (file.size === this.lastSize) return;
|
|
3937
|
+
const slice = await file.slice(this.lastSize).text();
|
|
3938
|
+
this.lastSize = file.size;
|
|
3939
|
+
const lines = slice.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
3940
|
+
for (const line of lines) {
|
|
3941
|
+
try {
|
|
3942
|
+
const obj = JSON.parse(line);
|
|
3943
|
+
this.onMessage(obj);
|
|
3944
|
+
} catch {
|
|
3945
|
+
}
|
|
3946
|
+
}
|
|
3947
|
+
} catch (e) {
|
|
3948
|
+
this.onStatus?.("error", e);
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3951
|
+
};
|
|
3952
|
+
|
|
3891
3953
|
// src/api/api.ts
|
|
3892
3954
|
var log11 = logger("api");
|
|
3893
3955
|
var API = class {
|
|
@@ -3970,29 +4032,19 @@ var API = class {
|
|
|
3970
4032
|
/** Connect to the configured ingestion source */
|
|
3971
4033
|
connectIngestion() {
|
|
3972
4034
|
if (!this.ingestionConfig || !this.ingest) return;
|
|
3973
|
-
const
|
|
3974
|
-
this.
|
|
4035
|
+
const args = {
|
|
4036
|
+
...this.ingestionConfig,
|
|
4037
|
+
onMessage: (msg) => {
|
|
4038
|
+
this.ingest.apply(msg);
|
|
4039
|
+
}
|
|
3975
4040
|
};
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
);
|
|
3984
|
-
this.ingestionSource.connect();
|
|
3985
|
-
break;
|
|
3986
|
-
case "file":
|
|
3987
|
-
this.ingestionSource = new FileSource(
|
|
3988
|
-
this.ingestionConfig.url,
|
|
3989
|
-
handleMessage,
|
|
3990
|
-
void 0,
|
|
3991
|
-
this.ingestionConfig.intervalMs
|
|
3992
|
-
);
|
|
3993
|
-
this.ingestionSource.connect();
|
|
3994
|
-
break;
|
|
3995
|
-
}
|
|
4041
|
+
const source = {
|
|
4042
|
+
"websocket": WebSocketSource,
|
|
4043
|
+
"file": FileSource,
|
|
4044
|
+
"filesystem": FileSystemSource
|
|
4045
|
+
}[this.ingestionConfig.type];
|
|
4046
|
+
this.ingestionSource = new source[this.ingestionConfig.type](args);
|
|
4047
|
+
this.ingestionSource?.connect();
|
|
3996
4048
|
}
|
|
3997
4049
|
/** Disconnect from the ingestion source */
|
|
3998
4050
|
disconnectIngestion() {
|
|
@@ -4578,68 +4630,6 @@ function shallowEqualUpdate(a, b) {
|
|
|
4578
4630
|
return true;
|
|
4579
4631
|
}
|
|
4580
4632
|
|
|
4581
|
-
// src/api/sources/FileSystemSource.ts
|
|
4582
|
-
var FileSystemSource = class {
|
|
4583
|
-
handle = null;
|
|
4584
|
-
onMessage;
|
|
4585
|
-
onStatus;
|
|
4586
|
-
timer = null;
|
|
4587
|
-
lastSize = 0;
|
|
4588
|
-
filename;
|
|
4589
|
-
intervalMs;
|
|
4590
|
-
constructor(onMessage, onStatus, filename = "graph.ndjson", intervalMs = 1e3) {
|
|
4591
|
-
this.onMessage = onMessage;
|
|
4592
|
-
this.onStatus = onStatus;
|
|
4593
|
-
this.filename = filename;
|
|
4594
|
-
this.intervalMs = intervalMs;
|
|
4595
|
-
}
|
|
4596
|
-
async openDirectory() {
|
|
4597
|
-
try {
|
|
4598
|
-
const dir = await window.showDirectoryPicker?.();
|
|
4599
|
-
if (!dir) throw new Error("File System Access not supported or cancelled");
|
|
4600
|
-
const handle = await dir.getFileHandle(this.filename, { create: false });
|
|
4601
|
-
this.handle = handle;
|
|
4602
|
-
this.onStatus?.("opened", { file: this.filename });
|
|
4603
|
-
this.lastSize = 0;
|
|
4604
|
-
this.startPolling();
|
|
4605
|
-
} catch (e) {
|
|
4606
|
-
this.onStatus?.("error", e);
|
|
4607
|
-
}
|
|
4608
|
-
}
|
|
4609
|
-
close() {
|
|
4610
|
-
if (this.timer) {
|
|
4611
|
-
window.clearInterval(this.timer);
|
|
4612
|
-
this.timer = null;
|
|
4613
|
-
}
|
|
4614
|
-
this.handle = null;
|
|
4615
|
-
this.onStatus?.("closed");
|
|
4616
|
-
}
|
|
4617
|
-
startPolling() {
|
|
4618
|
-
if (this.timer) window.clearInterval(this.timer);
|
|
4619
|
-
this.timer = window.setInterval(() => this.readNewLines(), this.intervalMs);
|
|
4620
|
-
}
|
|
4621
|
-
async readNewLines() {
|
|
4622
|
-
try {
|
|
4623
|
-
if (!this.handle) return;
|
|
4624
|
-
this.onStatus?.("reading");
|
|
4625
|
-
const file = await this.handle.getFile();
|
|
4626
|
-
if (file.size === this.lastSize) return;
|
|
4627
|
-
const slice = await file.slice(this.lastSize).text();
|
|
4628
|
-
this.lastSize = file.size;
|
|
4629
|
-
const lines = slice.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
4630
|
-
for (const line of lines) {
|
|
4631
|
-
try {
|
|
4632
|
-
const obj = JSON.parse(line);
|
|
4633
|
-
this.onMessage(obj);
|
|
4634
|
-
} catch {
|
|
4635
|
-
}
|
|
4636
|
-
}
|
|
4637
|
-
} catch (e) {
|
|
4638
|
-
this.onStatus?.("error", e);
|
|
4639
|
-
}
|
|
4640
|
-
}
|
|
4641
|
-
};
|
|
4642
|
-
|
|
4643
4633
|
// src/playground/playground.ts
|
|
4644
4634
|
var import_styles2 = __toESM(require("./styles.css?raw"), 1);
|
|
4645
4635
|
var Playground = class {
|
|
@@ -4918,10 +4908,18 @@ var Playground = class {
|
|
|
4918
4908
|
this.disconnectAllSources();
|
|
4919
4909
|
if (example.source.type === "websocket") {
|
|
4920
4910
|
this.wsUrl = example.source.url;
|
|
4921
|
-
this.wsSource = new WebSocketSource(
|
|
4911
|
+
this.wsSource = new WebSocketSource({
|
|
4912
|
+
url: example.source.url,
|
|
4913
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
4914
|
+
onStatus: this.updateWsStatus
|
|
4915
|
+
});
|
|
4922
4916
|
this.wsSource.connect();
|
|
4923
4917
|
} else if (example.source.type === "file") {
|
|
4924
|
-
this.fileSource = new FileSource(
|
|
4918
|
+
this.fileSource = new FileSource({
|
|
4919
|
+
url: example.source.path,
|
|
4920
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
4921
|
+
onStatus: this.updateFileStatus
|
|
4922
|
+
});
|
|
4925
4923
|
this.fileSource.connect();
|
|
4926
4924
|
}
|
|
4927
4925
|
}
|
|
@@ -5321,7 +5319,11 @@ var Playground = class {
|
|
|
5321
5319
|
if (this.wsSource) {
|
|
5322
5320
|
this.wsSource.disconnect();
|
|
5323
5321
|
}
|
|
5324
|
-
this.wsSource = new WebSocketSource(
|
|
5322
|
+
this.wsSource = new WebSocketSource({
|
|
5323
|
+
url,
|
|
5324
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
5325
|
+
onStatus: this.updateWsStatus
|
|
5326
|
+
});
|
|
5325
5327
|
this.wsSource.connect();
|
|
5326
5328
|
this.updateSourceModal();
|
|
5327
5329
|
}
|
|
@@ -5342,7 +5344,11 @@ var Playground = class {
|
|
|
5342
5344
|
}
|
|
5343
5345
|
async handleOpenFolder() {
|
|
5344
5346
|
if (!this.fsSource) {
|
|
5345
|
-
this.fsSource = new FileSystemSource(
|
|
5347
|
+
this.fsSource = new FileSystemSource({
|
|
5348
|
+
filename: "graph.ndjson",
|
|
5349
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
5350
|
+
onStatus: this.updateFsStatus
|
|
5351
|
+
});
|
|
5346
5352
|
}
|
|
5347
5353
|
this.updateSourceModal();
|
|
5348
5354
|
await this.fsSource.openDirectory();
|
package/dist/index.d.cts
CHANGED
|
@@ -3,6 +3,7 @@ type MergeOrder = Side[];
|
|
|
3
3
|
type NodeAlign = 'natural' | 'top' | 'bottom' | 'left' | 'right';
|
|
4
4
|
type Orientation = 'TB' | 'BT' | 'LR' | 'RL';
|
|
5
5
|
type Nav = 'first' | 'last' | 'prev' | 'next';
|
|
6
|
+
type PortStyle = 'inside' | 'outside' | 'custom';
|
|
6
7
|
type LayoutStep = 'alignChildren' | 'alignParents' | 'compact';
|
|
7
8
|
type Dims = {
|
|
8
9
|
w: number;
|
|
@@ -11,19 +12,33 @@ type Dims = {
|
|
|
11
12
|
|
|
12
13
|
type MarkerType = 'arrow' | 'circle' | 'diamond' | 'bar' | 'none';
|
|
13
14
|
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
* Used to connect to an external data source for graph updates.
|
|
17
|
-
*/
|
|
18
|
-
type IngestionConfig = {
|
|
15
|
+
/** WebSocket ingestion configuration */
|
|
16
|
+
type WebSocketIngestionConfig = {
|
|
19
17
|
type: 'websocket';
|
|
18
|
+
/** WebSocket URL */
|
|
20
19
|
url: string;
|
|
20
|
+
/** Reconnect interval in milliseconds */
|
|
21
21
|
reconnectMs?: number;
|
|
22
|
-
|
|
22
|
+
/** Callback when the WebSocket connection is established */
|
|
23
|
+
onConnect?: () => void;
|
|
24
|
+
/** Callback when the WebSocket connection is closed */
|
|
25
|
+
onDisconnect?: () => void;
|
|
26
|
+
/** Callback when the WebSocket connection encounters an error */
|
|
27
|
+
onError?: (error: Error) => void;
|
|
28
|
+
};
|
|
29
|
+
/** File ingestion configuration */
|
|
30
|
+
type FileIngestionConfig = {
|
|
23
31
|
type: 'file';
|
|
32
|
+
/** File URL */
|
|
24
33
|
url: string;
|
|
34
|
+
/** Polling interval in milliseconds */
|
|
25
35
|
intervalMs?: number;
|
|
26
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Ingestion source configuration.
|
|
39
|
+
* Used to connect to an external data source for graph updates.
|
|
40
|
+
*/
|
|
41
|
+
type IngestionConfig = WebSocketIngestionConfig | FileIngestionConfig;
|
|
27
42
|
/**
|
|
28
43
|
* Arguments to the API constructor.
|
|
29
44
|
*
|
|
@@ -518,7 +533,14 @@ declare class Ingest<N, E> {
|
|
|
518
533
|
apply(msg: IngestMessage<N, E>): Promise<void>;
|
|
519
534
|
}
|
|
520
535
|
|
|
521
|
-
type
|
|
536
|
+
type WebSocketStatus = 'connecting' | 'connected' | 'reconnecting' | 'closed' | 'error';
|
|
537
|
+
type WebSocketStatusListener = (status: WebSocketStatus, detail?: any) => void;
|
|
538
|
+
type WebSocketSourceArgs<N, E> = {
|
|
539
|
+
url: string;
|
|
540
|
+
onMessage: (msg: IngestMessage<N, E>) => void;
|
|
541
|
+
onStatus?: WebSocketStatusListener;
|
|
542
|
+
reconnectMs?: number;
|
|
543
|
+
};
|
|
522
544
|
declare class WebSocketSource<N, E> {
|
|
523
545
|
private url;
|
|
524
546
|
private ws;
|
|
@@ -529,7 +551,7 @@ declare class WebSocketSource<N, E> {
|
|
|
529
551
|
private connectStartTime;
|
|
530
552
|
private totalTimeoutMs;
|
|
531
553
|
private totalTimeoutTimer;
|
|
532
|
-
constructor(
|
|
554
|
+
constructor(args: WebSocketSourceArgs<N, E>);
|
|
533
555
|
connect(): void;
|
|
534
556
|
disconnect(): void;
|
|
535
557
|
private startTotalTimeout;
|
|
@@ -538,6 +560,12 @@ declare class WebSocketSource<N, E> {
|
|
|
538
560
|
}
|
|
539
561
|
|
|
540
562
|
type StatusListener$1 = (status: 'idle' | 'opened' | 'reading' | 'error' | 'closed', detail?: any) => void;
|
|
563
|
+
type FileSystemSourceArgs<N, E> = {
|
|
564
|
+
filename: string;
|
|
565
|
+
onMessage: (msg: IngestMessage<N, E>) => void;
|
|
566
|
+
onStatus?: StatusListener$1;
|
|
567
|
+
intervalMs?: number;
|
|
568
|
+
};
|
|
541
569
|
declare class FileSystemSource<N, E> {
|
|
542
570
|
private handle;
|
|
543
571
|
private onMessage;
|
|
@@ -546,7 +574,7 @@ declare class FileSystemSource<N, E> {
|
|
|
546
574
|
private lastSize;
|
|
547
575
|
private filename;
|
|
548
576
|
private intervalMs;
|
|
549
|
-
constructor(
|
|
577
|
+
constructor(args: FileSystemSourceArgs<N, E>);
|
|
550
578
|
openDirectory(): Promise<void>;
|
|
551
579
|
close(): void;
|
|
552
580
|
private startPolling;
|
|
@@ -554,6 +582,12 @@ declare class FileSystemSource<N, E> {
|
|
|
554
582
|
}
|
|
555
583
|
|
|
556
584
|
type StatusListener = (status: 'idle' | 'opened' | 'reading' | 'error' | 'closed', detail?: any) => void;
|
|
585
|
+
type FileSourceArgs<N, E> = {
|
|
586
|
+
url: string;
|
|
587
|
+
onMessage: (msg: IngestMessage<N, E>) => void;
|
|
588
|
+
onStatus?: StatusListener;
|
|
589
|
+
intervalMs?: number;
|
|
590
|
+
};
|
|
557
591
|
declare class FileSource<N, E> {
|
|
558
592
|
private url;
|
|
559
593
|
private onMessage;
|
|
@@ -563,7 +597,7 @@ declare class FileSource<N, E> {
|
|
|
563
597
|
private lastContent;
|
|
564
598
|
private intervalMs;
|
|
565
599
|
private closed;
|
|
566
|
-
constructor(
|
|
600
|
+
constructor(args: FileSourceArgs<N, E>);
|
|
567
601
|
connect(): Promise<void>;
|
|
568
602
|
close(): void;
|
|
569
603
|
private startPolling;
|
|
@@ -685,4 +719,4 @@ declare class Playground {
|
|
|
685
719
|
|
|
686
720
|
declare function graph<N, E>(args?: APIArguments<N, E>): Promise<API<N, E>>;
|
|
687
721
|
|
|
688
|
-
export { API, type APIArguments, type APIOptions, type EventsOptions, type Example, type ExampleEdge, type ExampleNode, type ExampleOptions, FileSource, FileSystemSource, type HistoryMessage, Ingest, type IngestMessage, type IngestionConfig, Playground, type PlaygroundOptions, type SnapshotMessage, type Update, type UpdateMessage, Updater, WebSocketSource, graph as default, graph };
|
|
722
|
+
export { API, type APIArguments, type APIOptions, type CanvasTheme, type ColorMode, type EdgeProps, type EdgeTheme, type EventsOptions, type Example, type ExampleEdge, type ExampleNode, type ExampleOptions, FileSource, type FileSourceArgs, FileSystemSource, type FileSystemSourceArgs, type HistoryMessage, Ingest, type IngestMessage, type IngestionConfig, type NewEdge, type NewNode, type NodeAlign, type NodeProps, type NodeTheme, type Orientation, Playground, type PlaygroundOptions, type PortProps, type PortStyle, type PortTheme, type RenderNode, type SnapshotMessage, type ThemeVars, type Update, type UpdateMessage, Updater, WebSocketSource, type WebSocketSourceArgs, type WebSocketStatus, type WebSocketStatusListener, graph as default, graph };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ type MergeOrder = Side[];
|
|
|
3
3
|
type NodeAlign = 'natural' | 'top' | 'bottom' | 'left' | 'right';
|
|
4
4
|
type Orientation = 'TB' | 'BT' | 'LR' | 'RL';
|
|
5
5
|
type Nav = 'first' | 'last' | 'prev' | 'next';
|
|
6
|
+
type PortStyle = 'inside' | 'outside' | 'custom';
|
|
6
7
|
type LayoutStep = 'alignChildren' | 'alignParents' | 'compact';
|
|
7
8
|
type Dims = {
|
|
8
9
|
w: number;
|
|
@@ -11,19 +12,33 @@ type Dims = {
|
|
|
11
12
|
|
|
12
13
|
type MarkerType = 'arrow' | 'circle' | 'diamond' | 'bar' | 'none';
|
|
13
14
|
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
* Used to connect to an external data source for graph updates.
|
|
17
|
-
*/
|
|
18
|
-
type IngestionConfig = {
|
|
15
|
+
/** WebSocket ingestion configuration */
|
|
16
|
+
type WebSocketIngestionConfig = {
|
|
19
17
|
type: 'websocket';
|
|
18
|
+
/** WebSocket URL */
|
|
20
19
|
url: string;
|
|
20
|
+
/** Reconnect interval in milliseconds */
|
|
21
21
|
reconnectMs?: number;
|
|
22
|
-
|
|
22
|
+
/** Callback when the WebSocket connection is established */
|
|
23
|
+
onConnect?: () => void;
|
|
24
|
+
/** Callback when the WebSocket connection is closed */
|
|
25
|
+
onDisconnect?: () => void;
|
|
26
|
+
/** Callback when the WebSocket connection encounters an error */
|
|
27
|
+
onError?: (error: Error) => void;
|
|
28
|
+
};
|
|
29
|
+
/** File ingestion configuration */
|
|
30
|
+
type FileIngestionConfig = {
|
|
23
31
|
type: 'file';
|
|
32
|
+
/** File URL */
|
|
24
33
|
url: string;
|
|
34
|
+
/** Polling interval in milliseconds */
|
|
25
35
|
intervalMs?: number;
|
|
26
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Ingestion source configuration.
|
|
39
|
+
* Used to connect to an external data source for graph updates.
|
|
40
|
+
*/
|
|
41
|
+
type IngestionConfig = WebSocketIngestionConfig | FileIngestionConfig;
|
|
27
42
|
/**
|
|
28
43
|
* Arguments to the API constructor.
|
|
29
44
|
*
|
|
@@ -518,7 +533,14 @@ declare class Ingest<N, E> {
|
|
|
518
533
|
apply(msg: IngestMessage<N, E>): Promise<void>;
|
|
519
534
|
}
|
|
520
535
|
|
|
521
|
-
type
|
|
536
|
+
type WebSocketStatus = 'connecting' | 'connected' | 'reconnecting' | 'closed' | 'error';
|
|
537
|
+
type WebSocketStatusListener = (status: WebSocketStatus, detail?: any) => void;
|
|
538
|
+
type WebSocketSourceArgs<N, E> = {
|
|
539
|
+
url: string;
|
|
540
|
+
onMessage: (msg: IngestMessage<N, E>) => void;
|
|
541
|
+
onStatus?: WebSocketStatusListener;
|
|
542
|
+
reconnectMs?: number;
|
|
543
|
+
};
|
|
522
544
|
declare class WebSocketSource<N, E> {
|
|
523
545
|
private url;
|
|
524
546
|
private ws;
|
|
@@ -529,7 +551,7 @@ declare class WebSocketSource<N, E> {
|
|
|
529
551
|
private connectStartTime;
|
|
530
552
|
private totalTimeoutMs;
|
|
531
553
|
private totalTimeoutTimer;
|
|
532
|
-
constructor(
|
|
554
|
+
constructor(args: WebSocketSourceArgs<N, E>);
|
|
533
555
|
connect(): void;
|
|
534
556
|
disconnect(): void;
|
|
535
557
|
private startTotalTimeout;
|
|
@@ -538,6 +560,12 @@ declare class WebSocketSource<N, E> {
|
|
|
538
560
|
}
|
|
539
561
|
|
|
540
562
|
type StatusListener$1 = (status: 'idle' | 'opened' | 'reading' | 'error' | 'closed', detail?: any) => void;
|
|
563
|
+
type FileSystemSourceArgs<N, E> = {
|
|
564
|
+
filename: string;
|
|
565
|
+
onMessage: (msg: IngestMessage<N, E>) => void;
|
|
566
|
+
onStatus?: StatusListener$1;
|
|
567
|
+
intervalMs?: number;
|
|
568
|
+
};
|
|
541
569
|
declare class FileSystemSource<N, E> {
|
|
542
570
|
private handle;
|
|
543
571
|
private onMessage;
|
|
@@ -546,7 +574,7 @@ declare class FileSystemSource<N, E> {
|
|
|
546
574
|
private lastSize;
|
|
547
575
|
private filename;
|
|
548
576
|
private intervalMs;
|
|
549
|
-
constructor(
|
|
577
|
+
constructor(args: FileSystemSourceArgs<N, E>);
|
|
550
578
|
openDirectory(): Promise<void>;
|
|
551
579
|
close(): void;
|
|
552
580
|
private startPolling;
|
|
@@ -554,6 +582,12 @@ declare class FileSystemSource<N, E> {
|
|
|
554
582
|
}
|
|
555
583
|
|
|
556
584
|
type StatusListener = (status: 'idle' | 'opened' | 'reading' | 'error' | 'closed', detail?: any) => void;
|
|
585
|
+
type FileSourceArgs<N, E> = {
|
|
586
|
+
url: string;
|
|
587
|
+
onMessage: (msg: IngestMessage<N, E>) => void;
|
|
588
|
+
onStatus?: StatusListener;
|
|
589
|
+
intervalMs?: number;
|
|
590
|
+
};
|
|
557
591
|
declare class FileSource<N, E> {
|
|
558
592
|
private url;
|
|
559
593
|
private onMessage;
|
|
@@ -563,7 +597,7 @@ declare class FileSource<N, E> {
|
|
|
563
597
|
private lastContent;
|
|
564
598
|
private intervalMs;
|
|
565
599
|
private closed;
|
|
566
|
-
constructor(
|
|
600
|
+
constructor(args: FileSourceArgs<N, E>);
|
|
567
601
|
connect(): Promise<void>;
|
|
568
602
|
close(): void;
|
|
569
603
|
private startPolling;
|
|
@@ -685,4 +719,4 @@ declare class Playground {
|
|
|
685
719
|
|
|
686
720
|
declare function graph<N, E>(args?: APIArguments<N, E>): Promise<API<N, E>>;
|
|
687
721
|
|
|
688
|
-
export { API, type APIArguments, type APIOptions, type EventsOptions, type Example, type ExampleEdge, type ExampleNode, type ExampleOptions, FileSource, FileSystemSource, type HistoryMessage, Ingest, type IngestMessage, type IngestionConfig, Playground, type PlaygroundOptions, type SnapshotMessage, type Update, type UpdateMessage, Updater, WebSocketSource, graph as default, graph };
|
|
722
|
+
export { API, type APIArguments, type APIOptions, type CanvasTheme, type ColorMode, type EdgeProps, type EdgeTheme, type EventsOptions, type Example, type ExampleEdge, type ExampleNode, type ExampleOptions, FileSource, type FileSourceArgs, FileSystemSource, type FileSystemSourceArgs, type HistoryMessage, Ingest, type IngestMessage, type IngestionConfig, type NewEdge, type NewNode, type NodeAlign, type NodeProps, type NodeTheme, type Orientation, Playground, type PlaygroundOptions, type PortProps, type PortStyle, type PortTheme, type RenderNode, type SnapshotMessage, type ThemeVars, type Update, type UpdateMessage, Updater, WebSocketSource, type WebSocketSourceArgs, type WebSocketStatus, type WebSocketStatusListener, graph as default, graph };
|
package/dist/index.js
CHANGED
|
@@ -3674,11 +3674,11 @@ var WebSocketSource = class {
|
|
|
3674
3674
|
connectStartTime = null;
|
|
3675
3675
|
totalTimeoutMs = 1e4;
|
|
3676
3676
|
totalTimeoutTimer = null;
|
|
3677
|
-
constructor(
|
|
3678
|
-
this.url = url;
|
|
3679
|
-
this.onMessage = onMessage;
|
|
3680
|
-
this.onStatus = onStatus;
|
|
3681
|
-
this.reconnectMs = reconnectMs;
|
|
3677
|
+
constructor(args) {
|
|
3678
|
+
this.url = args.url;
|
|
3679
|
+
this.onMessage = args.onMessage;
|
|
3680
|
+
this.onStatus = args.onStatus;
|
|
3681
|
+
this.reconnectMs = args.reconnectMs ?? 1500;
|
|
3682
3682
|
}
|
|
3683
3683
|
connect() {
|
|
3684
3684
|
this.closedByUser = false;
|
|
@@ -3779,11 +3779,11 @@ var FileSource = class {
|
|
|
3779
3779
|
lastContent = "";
|
|
3780
3780
|
intervalMs = 1e3;
|
|
3781
3781
|
closed = false;
|
|
3782
|
-
constructor(
|
|
3783
|
-
this.url = url;
|
|
3784
|
-
this.onMessage = onMessage;
|
|
3785
|
-
this.onStatus = onStatus;
|
|
3786
|
-
this.intervalMs = intervalMs;
|
|
3782
|
+
constructor(args) {
|
|
3783
|
+
this.url = args.url;
|
|
3784
|
+
this.onMessage = args.onMessage;
|
|
3785
|
+
this.onStatus = args.onStatus;
|
|
3786
|
+
this.intervalMs = args.intervalMs ?? 1e3;
|
|
3787
3787
|
}
|
|
3788
3788
|
async connect() {
|
|
3789
3789
|
this.closed = false;
|
|
@@ -3845,6 +3845,68 @@ var FileSource = class {
|
|
|
3845
3845
|
}
|
|
3846
3846
|
};
|
|
3847
3847
|
|
|
3848
|
+
// src/api/sources/FileSystemSource.ts
|
|
3849
|
+
var FileSystemSource = class {
|
|
3850
|
+
handle = null;
|
|
3851
|
+
onMessage;
|
|
3852
|
+
onStatus;
|
|
3853
|
+
timer = null;
|
|
3854
|
+
lastSize = 0;
|
|
3855
|
+
filename;
|
|
3856
|
+
intervalMs;
|
|
3857
|
+
constructor(args) {
|
|
3858
|
+
this.filename = args.filename;
|
|
3859
|
+
this.onMessage = args.onMessage;
|
|
3860
|
+
this.onStatus = args.onStatus;
|
|
3861
|
+
this.intervalMs = args.intervalMs ?? 1e3;
|
|
3862
|
+
}
|
|
3863
|
+
async openDirectory() {
|
|
3864
|
+
try {
|
|
3865
|
+
const dir = await window.showDirectoryPicker?.();
|
|
3866
|
+
if (!dir) throw new Error("File System Access not supported or cancelled");
|
|
3867
|
+
const handle = await dir.getFileHandle(this.filename, { create: false });
|
|
3868
|
+
this.handle = handle;
|
|
3869
|
+
this.onStatus?.("opened", { file: this.filename });
|
|
3870
|
+
this.lastSize = 0;
|
|
3871
|
+
this.startPolling();
|
|
3872
|
+
} catch (e) {
|
|
3873
|
+
this.onStatus?.("error", e);
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
close() {
|
|
3877
|
+
if (this.timer) {
|
|
3878
|
+
window.clearInterval(this.timer);
|
|
3879
|
+
this.timer = null;
|
|
3880
|
+
}
|
|
3881
|
+
this.handle = null;
|
|
3882
|
+
this.onStatus?.("closed");
|
|
3883
|
+
}
|
|
3884
|
+
startPolling() {
|
|
3885
|
+
if (this.timer) window.clearInterval(this.timer);
|
|
3886
|
+
this.timer = window.setInterval(() => this.readNewLines(), this.intervalMs);
|
|
3887
|
+
}
|
|
3888
|
+
async readNewLines() {
|
|
3889
|
+
try {
|
|
3890
|
+
if (!this.handle) return;
|
|
3891
|
+
this.onStatus?.("reading");
|
|
3892
|
+
const file = await this.handle.getFile();
|
|
3893
|
+
if (file.size === this.lastSize) return;
|
|
3894
|
+
const slice = await file.slice(this.lastSize).text();
|
|
3895
|
+
this.lastSize = file.size;
|
|
3896
|
+
const lines = slice.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
3897
|
+
for (const line of lines) {
|
|
3898
|
+
try {
|
|
3899
|
+
const obj = JSON.parse(line);
|
|
3900
|
+
this.onMessage(obj);
|
|
3901
|
+
} catch {
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
} catch (e) {
|
|
3905
|
+
this.onStatus?.("error", e);
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
};
|
|
3909
|
+
|
|
3848
3910
|
// src/api/api.ts
|
|
3849
3911
|
var log11 = logger("api");
|
|
3850
3912
|
var API = class {
|
|
@@ -3927,29 +3989,19 @@ var API = class {
|
|
|
3927
3989
|
/** Connect to the configured ingestion source */
|
|
3928
3990
|
connectIngestion() {
|
|
3929
3991
|
if (!this.ingestionConfig || !this.ingest) return;
|
|
3930
|
-
const
|
|
3931
|
-
this.
|
|
3992
|
+
const args = {
|
|
3993
|
+
...this.ingestionConfig,
|
|
3994
|
+
onMessage: (msg) => {
|
|
3995
|
+
this.ingest.apply(msg);
|
|
3996
|
+
}
|
|
3932
3997
|
};
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
);
|
|
3941
|
-
this.ingestionSource.connect();
|
|
3942
|
-
break;
|
|
3943
|
-
case "file":
|
|
3944
|
-
this.ingestionSource = new FileSource(
|
|
3945
|
-
this.ingestionConfig.url,
|
|
3946
|
-
handleMessage,
|
|
3947
|
-
void 0,
|
|
3948
|
-
this.ingestionConfig.intervalMs
|
|
3949
|
-
);
|
|
3950
|
-
this.ingestionSource.connect();
|
|
3951
|
-
break;
|
|
3952
|
-
}
|
|
3998
|
+
const source = {
|
|
3999
|
+
"websocket": WebSocketSource,
|
|
4000
|
+
"file": FileSource,
|
|
4001
|
+
"filesystem": FileSystemSource
|
|
4002
|
+
}[this.ingestionConfig.type];
|
|
4003
|
+
this.ingestionSource = new source[this.ingestionConfig.type](args);
|
|
4004
|
+
this.ingestionSource?.connect();
|
|
3953
4005
|
}
|
|
3954
4006
|
/** Disconnect from the ingestion source */
|
|
3955
4007
|
disconnectIngestion() {
|
|
@@ -4535,68 +4587,6 @@ function shallowEqualUpdate(a, b) {
|
|
|
4535
4587
|
return true;
|
|
4536
4588
|
}
|
|
4537
4589
|
|
|
4538
|
-
// src/api/sources/FileSystemSource.ts
|
|
4539
|
-
var FileSystemSource = class {
|
|
4540
|
-
handle = null;
|
|
4541
|
-
onMessage;
|
|
4542
|
-
onStatus;
|
|
4543
|
-
timer = null;
|
|
4544
|
-
lastSize = 0;
|
|
4545
|
-
filename;
|
|
4546
|
-
intervalMs;
|
|
4547
|
-
constructor(onMessage, onStatus, filename = "graph.ndjson", intervalMs = 1e3) {
|
|
4548
|
-
this.onMessage = onMessage;
|
|
4549
|
-
this.onStatus = onStatus;
|
|
4550
|
-
this.filename = filename;
|
|
4551
|
-
this.intervalMs = intervalMs;
|
|
4552
|
-
}
|
|
4553
|
-
async openDirectory() {
|
|
4554
|
-
try {
|
|
4555
|
-
const dir = await window.showDirectoryPicker?.();
|
|
4556
|
-
if (!dir) throw new Error("File System Access not supported or cancelled");
|
|
4557
|
-
const handle = await dir.getFileHandle(this.filename, { create: false });
|
|
4558
|
-
this.handle = handle;
|
|
4559
|
-
this.onStatus?.("opened", { file: this.filename });
|
|
4560
|
-
this.lastSize = 0;
|
|
4561
|
-
this.startPolling();
|
|
4562
|
-
} catch (e) {
|
|
4563
|
-
this.onStatus?.("error", e);
|
|
4564
|
-
}
|
|
4565
|
-
}
|
|
4566
|
-
close() {
|
|
4567
|
-
if (this.timer) {
|
|
4568
|
-
window.clearInterval(this.timer);
|
|
4569
|
-
this.timer = null;
|
|
4570
|
-
}
|
|
4571
|
-
this.handle = null;
|
|
4572
|
-
this.onStatus?.("closed");
|
|
4573
|
-
}
|
|
4574
|
-
startPolling() {
|
|
4575
|
-
if (this.timer) window.clearInterval(this.timer);
|
|
4576
|
-
this.timer = window.setInterval(() => this.readNewLines(), this.intervalMs);
|
|
4577
|
-
}
|
|
4578
|
-
async readNewLines() {
|
|
4579
|
-
try {
|
|
4580
|
-
if (!this.handle) return;
|
|
4581
|
-
this.onStatus?.("reading");
|
|
4582
|
-
const file = await this.handle.getFile();
|
|
4583
|
-
if (file.size === this.lastSize) return;
|
|
4584
|
-
const slice = await file.slice(this.lastSize).text();
|
|
4585
|
-
this.lastSize = file.size;
|
|
4586
|
-
const lines = slice.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
4587
|
-
for (const line of lines) {
|
|
4588
|
-
try {
|
|
4589
|
-
const obj = JSON.parse(line);
|
|
4590
|
-
this.onMessage(obj);
|
|
4591
|
-
} catch {
|
|
4592
|
-
}
|
|
4593
|
-
}
|
|
4594
|
-
} catch (e) {
|
|
4595
|
-
this.onStatus?.("error", e);
|
|
4596
|
-
}
|
|
4597
|
-
}
|
|
4598
|
-
};
|
|
4599
|
-
|
|
4600
4590
|
// src/playground/playground.ts
|
|
4601
4591
|
import styles2 from "./styles.css?raw";
|
|
4602
4592
|
var Playground = class {
|
|
@@ -4875,10 +4865,18 @@ var Playground = class {
|
|
|
4875
4865
|
this.disconnectAllSources();
|
|
4876
4866
|
if (example.source.type === "websocket") {
|
|
4877
4867
|
this.wsUrl = example.source.url;
|
|
4878
|
-
this.wsSource = new WebSocketSource(
|
|
4868
|
+
this.wsSource = new WebSocketSource({
|
|
4869
|
+
url: example.source.url,
|
|
4870
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
4871
|
+
onStatus: this.updateWsStatus
|
|
4872
|
+
});
|
|
4879
4873
|
this.wsSource.connect();
|
|
4880
4874
|
} else if (example.source.type === "file") {
|
|
4881
|
-
this.fileSource = new FileSource(
|
|
4875
|
+
this.fileSource = new FileSource({
|
|
4876
|
+
url: example.source.path,
|
|
4877
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
4878
|
+
onStatus: this.updateFileStatus
|
|
4879
|
+
});
|
|
4882
4880
|
this.fileSource.connect();
|
|
4883
4881
|
}
|
|
4884
4882
|
}
|
|
@@ -5278,7 +5276,11 @@ var Playground = class {
|
|
|
5278
5276
|
if (this.wsSource) {
|
|
5279
5277
|
this.wsSource.disconnect();
|
|
5280
5278
|
}
|
|
5281
|
-
this.wsSource = new WebSocketSource(
|
|
5279
|
+
this.wsSource = new WebSocketSource({
|
|
5280
|
+
url,
|
|
5281
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
5282
|
+
onStatus: this.updateWsStatus
|
|
5283
|
+
});
|
|
5282
5284
|
this.wsSource.connect();
|
|
5283
5285
|
this.updateSourceModal();
|
|
5284
5286
|
}
|
|
@@ -5299,7 +5301,11 @@ var Playground = class {
|
|
|
5299
5301
|
}
|
|
5300
5302
|
async handleOpenFolder() {
|
|
5301
5303
|
if (!this.fsSource) {
|
|
5302
|
-
this.fsSource = new FileSystemSource(
|
|
5304
|
+
this.fsSource = new FileSystemSource({
|
|
5305
|
+
filename: "graph.ndjson",
|
|
5306
|
+
onMessage: this.handleIngestMessage.bind(this),
|
|
5307
|
+
onStatus: this.updateFsStatus
|
|
5308
|
+
});
|
|
5303
5309
|
}
|
|
5304
5310
|
this.updateSourceModal();
|
|
5305
5311
|
await this.fsSource.openDirectory();
|