@anvailabs/proximadb-client 0.3.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 (65) hide show
  1. package/README.md +160 -0
  2. package/dist/client.d.ts +319 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +681 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/collection.d.ts +227 -0
  7. package/dist/collection.d.ts.map +1 -0
  8. package/dist/collection.js +436 -0
  9. package/dist/collection.js.map +1 -0
  10. package/dist/esm/client.js +674 -0
  11. package/dist/esm/client.js.map +1 -0
  12. package/dist/esm/collection.js +428 -0
  13. package/dist/esm/collection.js.map +1 -0
  14. package/dist/esm/filter.js +228 -0
  15. package/dist/esm/filter.js.map +1 -0
  16. package/dist/esm/generated/schema.js +6 -0
  17. package/dist/esm/generated/schema.js.map +1 -0
  18. package/dist/esm/graph.js +678 -0
  19. package/dist/esm/graph.js.map +1 -0
  20. package/dist/esm/index.js +86 -0
  21. package/dist/esm/index.js.map +1 -0
  22. package/dist/esm/search.js +317 -0
  23. package/dist/esm/search.js.map +1 -0
  24. package/dist/esm/transport.js +33 -0
  25. package/dist/esm/transport.js.map +1 -0
  26. package/dist/esm/types.js +181 -0
  27. package/dist/esm/types.js.map +1 -0
  28. package/dist/filter.d.ts +51 -0
  29. package/dist/filter.d.ts.map +1 -0
  30. package/dist/filter.js +241 -0
  31. package/dist/filter.js.map +1 -0
  32. package/dist/generated/schema.d.ts +4271 -0
  33. package/dist/generated/schema.d.ts.map +1 -0
  34. package/dist/generated/schema.js +7 -0
  35. package/dist/generated/schema.js.map +1 -0
  36. package/dist/graph.d.ts +350 -0
  37. package/dist/graph.d.ts.map +1 -0
  38. package/dist/graph.js +690 -0
  39. package/dist/graph.js.map +1 -0
  40. package/dist/index.d.ts +58 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +126 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/search.d.ts +160 -0
  45. package/dist/search.d.ts.map +1 -0
  46. package/dist/search.js +322 -0
  47. package/dist/search.js.map +1 -0
  48. package/dist/transport.d.ts +40 -0
  49. package/dist/transport.d.ts.map +1 -0
  50. package/dist/transport.js +39 -0
  51. package/dist/transport.js.map +1 -0
  52. package/dist/types.d.ts +632 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +185 -0
  55. package/dist/types.js.map +1 -0
  56. package/package.json +72 -0
  57. package/src/client.ts +856 -0
  58. package/src/collection.ts +578 -0
  59. package/src/filter.ts +280 -0
  60. package/src/generated/schema.ts +4271 -0
  61. package/src/graph.ts +811 -0
  62. package/src/index.ts +184 -0
  63. package/src/search.ts +401 -0
  64. package/src/transport.ts +52 -0
  65. package/src/types.ts +726 -0
package/dist/graph.js ADDED
@@ -0,0 +1,690 @@
1
+ "use strict";
2
+ /**
3
+ * ProximaDB TypeScript SDK - Graph Operations
4
+ *
5
+ * Provides a fluent API for graph database operations including
6
+ * node and edge management, traversal queries, and graph analytics.
7
+ *
8
+ * Copyright 2025 ProximaDB Contributors
9
+ * Licensed under the Apache License, Version 2.0
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.GraphBuilder = exports.GraphHandle = exports.TraversalBuilder = exports.EdgeBuilder = exports.NodeBuilder = void 0;
13
+ exports.createNode = createNode;
14
+ exports.node = node;
15
+ exports.createEdge = createEdge;
16
+ exports.edge = edge;
17
+ const types_1 = require("./types");
18
+ // ============================================================================
19
+ // NODE BUILDER
20
+ // ============================================================================
21
+ /**
22
+ * Builder for creating graph nodes
23
+ */
24
+ class NodeBuilder {
25
+ handle;
26
+ nodeId = null;
27
+ nodeLabel = null;
28
+ nodeProperties = {};
29
+ nodeVector = null;
30
+ constructor(handle) {
31
+ this.handle = handle;
32
+ }
33
+ /**
34
+ * Set the node ID
35
+ */
36
+ id(nodeId) {
37
+ this.nodeId = nodeId;
38
+ return this;
39
+ }
40
+ /**
41
+ * Set the node label (type)
42
+ */
43
+ label(nodeLabel) {
44
+ this.nodeLabel = nodeLabel;
45
+ return this;
46
+ }
47
+ /**
48
+ * Add a property to the node
49
+ */
50
+ property(key, value) {
51
+ this.nodeProperties[key] = value;
52
+ return this;
53
+ }
54
+ /**
55
+ * Add multiple properties at once
56
+ */
57
+ properties(props) {
58
+ Object.assign(this.nodeProperties, props);
59
+ return this;
60
+ }
61
+ /**
62
+ * Set the embedding vector for semantic operations
63
+ */
64
+ vector(vec) {
65
+ this.nodeVector = vec;
66
+ return this;
67
+ }
68
+ /**
69
+ * Execute the node addition.
70
+ *
71
+ * Wire endpoint: POST /api/v2/graphs/{graph_id}/nodes
72
+ * OpenAPI operationId: createNode
73
+ *
74
+ * Body shape (server-true, per `CreateNodeRequest`):
75
+ * `{ node: NodeInput }` — NodeInput = `{ id, labels?, properties?, embedding? }`.
76
+ */
77
+ async execute() {
78
+ if (this.nodeId === null) {
79
+ throw new Error("Node ID is required");
80
+ }
81
+ const node = { id: this.nodeId };
82
+ if (this.nodeLabel !== null) {
83
+ node.labels = [this.nodeLabel];
84
+ }
85
+ if (Object.keys(this.nodeProperties).length > 0) {
86
+ node.properties = this.nodeProperties;
87
+ }
88
+ if (this.nodeVector !== null) {
89
+ const embedding = { vector: this.nodeVector };
90
+ node.embedding = embedding;
91
+ }
92
+ const request = { node };
93
+ await this.handle.getClient().createNodeRequest(this.handle.getName(), request);
94
+ }
95
+ /**
96
+ * Build the node without executing
97
+ */
98
+ build() {
99
+ if (this.nodeId === null) {
100
+ throw new Error("Node ID is required");
101
+ }
102
+ return {
103
+ id: this.nodeId,
104
+ label: this.nodeLabel ?? undefined,
105
+ properties: this.nodeProperties,
106
+ vector: this.nodeVector ?? undefined,
107
+ };
108
+ }
109
+ }
110
+ exports.NodeBuilder = NodeBuilder;
111
+ // ============================================================================
112
+ // EDGE BUILDER
113
+ // ============================================================================
114
+ /**
115
+ * Builder for creating graph edges
116
+ */
117
+ class EdgeBuilder {
118
+ handle;
119
+ edgeId = null;
120
+ sourceNode = null;
121
+ targetNode = null;
122
+ relationshipType = null;
123
+ edgeProperties = {};
124
+ edgeWeight = null;
125
+ constructor(handle) {
126
+ this.handle = handle;
127
+ }
128
+ /**
129
+ * Set the edge ID (required by server `EdgeInput.id`).
130
+ */
131
+ id(edgeId) {
132
+ this.edgeId = edgeId;
133
+ return this;
134
+ }
135
+ /**
136
+ * Set the source node ID
137
+ */
138
+ from(nodeId) {
139
+ this.sourceNode = nodeId;
140
+ return this;
141
+ }
142
+ /**
143
+ * Set the target node ID
144
+ */
145
+ to(nodeId) {
146
+ this.targetNode = nodeId;
147
+ return this;
148
+ }
149
+ /**
150
+ * Set the relationship / edge type (server field: `edge_type`).
151
+ */
152
+ relationship(relType) {
153
+ this.relationshipType = relType;
154
+ return this;
155
+ }
156
+ /**
157
+ * Alias for `relationship(...)` matching the server-side field name.
158
+ */
159
+ edgeType(edgeType) {
160
+ this.relationshipType = edgeType;
161
+ return this;
162
+ }
163
+ /**
164
+ * Add a property to the edge
165
+ */
166
+ property(key, value) {
167
+ this.edgeProperties[key] = value;
168
+ return this;
169
+ }
170
+ /**
171
+ * Add multiple properties at once
172
+ */
173
+ properties(props) {
174
+ Object.assign(this.edgeProperties, props);
175
+ return this;
176
+ }
177
+ /**
178
+ * Set the edge weight
179
+ */
180
+ weight(w) {
181
+ this.edgeWeight = w;
182
+ return this;
183
+ }
184
+ /**
185
+ * Execute the edge addition.
186
+ *
187
+ * Wire endpoint: POST /api/v2/graphs/{graph_id}/edges
188
+ * OpenAPI operationId: createEdge
189
+ *
190
+ * Body shape (server-true, per `CreateEdgeRequest`):
191
+ * `{ edge: EdgeInput }` — EdgeInput = `{ id, from_node_id, to_node_id,
192
+ * edge_type, properties?, weight? }`.
193
+ */
194
+ async execute() {
195
+ if (this.edgeId === null) {
196
+ throw new Error("Edge ID is required (call .id(...))");
197
+ }
198
+ if (this.sourceNode === null) {
199
+ throw new Error("Source node ID is required");
200
+ }
201
+ if (this.targetNode === null) {
202
+ throw new Error("Target node ID is required");
203
+ }
204
+ if (this.relationshipType === null) {
205
+ throw new Error("Edge type / relationship is required");
206
+ }
207
+ const edge = {
208
+ id: this.edgeId,
209
+ from_node_id: this.sourceNode,
210
+ to_node_id: this.targetNode,
211
+ edge_type: this.relationshipType,
212
+ };
213
+ if (Object.keys(this.edgeProperties).length > 0) {
214
+ edge.properties = this.edgeProperties;
215
+ }
216
+ if (this.edgeWeight !== null) {
217
+ edge.weight = this.edgeWeight;
218
+ }
219
+ const request = { edge };
220
+ await this.handle.getClient().createEdgeRequest(this.handle.getName(), request);
221
+ }
222
+ /**
223
+ * Build the edge without executing
224
+ */
225
+ build() {
226
+ if (this.sourceNode === null) {
227
+ throw new Error("Source node ID is required");
228
+ }
229
+ if (this.targetNode === null) {
230
+ throw new Error("Target node ID is required");
231
+ }
232
+ if (this.relationshipType === null) {
233
+ throw new Error("Relationship type is required");
234
+ }
235
+ return {
236
+ source: this.sourceNode,
237
+ target: this.targetNode,
238
+ relationship: this.relationshipType,
239
+ properties: this.edgeProperties,
240
+ weight: this.edgeWeight ?? undefined,
241
+ };
242
+ }
243
+ }
244
+ exports.EdgeBuilder = EdgeBuilder;
245
+ // ============================================================================
246
+ // TRAVERSAL BUILDER
247
+ // ============================================================================
248
+ /**
249
+ * Builder for graph traversal queries
250
+ */
251
+ class TraversalBuilder {
252
+ handle;
253
+ startNodeId = null;
254
+ relationshipTypes = [];
255
+ nodeLabelsList = [];
256
+ traversalDirection = types_1.TraversalDirection.Outgoing;
257
+ maxDepthValue = 3;
258
+ limitValue = null;
259
+ algorithmValue = null;
260
+ filterExpr = null;
261
+ constructor(handle) {
262
+ this.handle = handle;
263
+ }
264
+ /**
265
+ * Set the starting node
266
+ */
267
+ start(nodeId) {
268
+ this.startNodeId = nodeId;
269
+ return this;
270
+ }
271
+ /**
272
+ * Add a relationship type to follow
273
+ */
274
+ relationship(relType) {
275
+ this.relationshipTypes.push(relType);
276
+ return this;
277
+ }
278
+ /**
279
+ * Add multiple relationship types
280
+ */
281
+ relationships(relTypes) {
282
+ this.relationshipTypes.push(...relTypes);
283
+ return this;
284
+ }
285
+ /**
286
+ * Set the traversal direction
287
+ */
288
+ direction(dir) {
289
+ this.traversalDirection = dir;
290
+ return this;
291
+ }
292
+ /**
293
+ * Traverse outgoing edges only
294
+ */
295
+ outgoing() {
296
+ this.traversalDirection = types_1.TraversalDirection.Outgoing;
297
+ return this;
298
+ }
299
+ /**
300
+ * Traverse incoming edges only
301
+ */
302
+ incoming() {
303
+ this.traversalDirection = types_1.TraversalDirection.Incoming;
304
+ return this;
305
+ }
306
+ /**
307
+ * Traverse both directions
308
+ */
309
+ both() {
310
+ this.traversalDirection = types_1.TraversalDirection.Both;
311
+ return this;
312
+ }
313
+ /**
314
+ * Set the maximum traversal depth
315
+ */
316
+ maxDepth(depth) {
317
+ this.maxDepthValue = depth;
318
+ return this;
319
+ }
320
+ /**
321
+ * Set the maximum number of results
322
+ */
323
+ limit(lim) {
324
+ this.limitValue = lim;
325
+ return this;
326
+ }
327
+ /**
328
+ * Add a label to filter visited nodes by.
329
+ */
330
+ nodeLabel(label) {
331
+ this.nodeLabelsList.push(label);
332
+ return this;
333
+ }
334
+ /**
335
+ * Replace the set of node-label filters.
336
+ */
337
+ nodeLabels(labels) {
338
+ this.nodeLabelsList = [...labels];
339
+ return this;
340
+ }
341
+ /**
342
+ * Select traversal algorithm (server accepts `bfs`, `dfs`, or `shortest_path`).
343
+ */
344
+ algorithm(name) {
345
+ this.algorithmValue = name;
346
+ return this;
347
+ }
348
+ /**
349
+ * Add a filter expression for nodes (client-side helper, not sent on wire).
350
+ */
351
+ filter(filterStr) {
352
+ this.filterExpr = filterStr;
353
+ return this;
354
+ }
355
+ /**
356
+ * Execute the traversal.
357
+ *
358
+ * Wire endpoint: POST /api/v2/graphs/{graph_id}/traverse
359
+ * OpenAPI operationId: traverseGraph
360
+ *
361
+ * Body shape (server-true, per `TraverseRequest`):
362
+ * `{ start_node_id, max_depth, edge_types?, node_labels?, algorithm?, limit? }`.
363
+ * Note: spec is flat (no `graph` wrapper — `graph_id` is the URL path
364
+ * parameter) and has no `direction` field; legacy `direction` /
365
+ * `start_node` / `relationships` keys are intentionally not sent.
366
+ */
367
+ async execute() {
368
+ if (this.startNodeId === null) {
369
+ throw new Error("Start node is required for traversal");
370
+ }
371
+ const request = {
372
+ start_node_id: this.startNodeId,
373
+ max_depth: this.maxDepthValue,
374
+ };
375
+ if (this.relationshipTypes.length > 0) {
376
+ request.edge_types = this.relationshipTypes;
377
+ }
378
+ if (this.nodeLabelsList.length > 0) {
379
+ request.node_labels = this.nodeLabelsList;
380
+ }
381
+ if (this.algorithmValue !== null) {
382
+ request.algorithm = this.algorithmValue;
383
+ }
384
+ if (this.limitValue !== null) {
385
+ request.limit = this.limitValue;
386
+ }
387
+ // Note: direction (this.traversalDirection) and filter (this.filterExpr)
388
+ // are intentionally NOT sent — the server `TraverseRequest` does not
389
+ // accept them. The setters remain for SDK ergonomic continuity.
390
+ void this.traversalDirection;
391
+ void this.filterExpr;
392
+ const data = await this.handle.getClient().traverseGraphRequest(this.handle.getName(), request);
393
+ return data;
394
+ }
395
+ }
396
+ exports.TraversalBuilder = TraversalBuilder;
397
+ // ============================================================================
398
+ // GRAPH HANDLE
399
+ // ============================================================================
400
+ /**
401
+ * Handle to a graph for fluent operations
402
+ */
403
+ class GraphHandle {
404
+ client;
405
+ graphName;
406
+ constructor(client, name) {
407
+ this.client = client;
408
+ this.graphName = name;
409
+ }
410
+ /**
411
+ * Get the graph name
412
+ */
413
+ getName() {
414
+ return this.graphName;
415
+ }
416
+ /**
417
+ * Get the HTTP client (internal use)
418
+ */
419
+ getClient() {
420
+ return this.client;
421
+ }
422
+ /**
423
+ * Start building a node addition
424
+ */
425
+ addNode() {
426
+ return new NodeBuilder(this);
427
+ }
428
+ /**
429
+ * Start building an edge addition
430
+ */
431
+ addEdge() {
432
+ return new EdgeBuilder(this);
433
+ }
434
+ /**
435
+ * Start building a traversal query
436
+ */
437
+ traverse() {
438
+ return new TraversalBuilder(this);
439
+ }
440
+ /**
441
+ * Add a batch of nodes.
442
+ *
443
+ * Wire endpoint: POST /api/v2/graphs/{graph_id}/nodes/batch
444
+ * OpenAPI operationId: batchCreateNodes
445
+ *
446
+ * Body shape (server-true, per `BatchCreateNodesRequest`):
447
+ * `{ nodes: [NodeInput, ...] }`. `graph_id` lives in the URL path.
448
+ *
449
+ * Accepts either spec-true `NodeInput[]` or legacy `GraphNode[]`; the
450
+ * latter is normalized (singular `label` → `labels: [label]`,
451
+ * `vector` → `embedding.vector`).
452
+ */
453
+ async addNodes(nodes) {
454
+ const normalized = nodes.map(n => normalizeNodeInput(n));
455
+ const request = { nodes: normalized };
456
+ const response = (await this.client.batchCreateNodesRequest(this.graphName, request));
457
+ return response?.data?.count ?? response?.count ?? normalized.length;
458
+ }
459
+ /**
460
+ * Add a batch of edges.
461
+ *
462
+ * Wire endpoint: POST /api/v2/graphs/{graph_id}/edges/batch
463
+ * OpenAPI operationId: batchCreateEdges
464
+ *
465
+ * Body shape (server-true, per `BatchCreateEdgesRequest`):
466
+ * `{ edges: [EdgeInput, ...] }`. `graph_id` lives in the URL path.
467
+ *
468
+ * Accepts either spec-true `EdgeInput[]` or legacy `GraphEdge[]`; the
469
+ * latter is normalized (`source` → `from_node_id`, `target` →
470
+ * `to_node_id`, `relationship` → `edge_type`). Legacy `GraphEdge` has no
471
+ * `id` field; callers MUST upgrade to `EdgeInput` for batch use (the
472
+ * normalizer throws if `id` is missing).
473
+ */
474
+ async addEdges(edges) {
475
+ const normalized = edges.map(e => normalizeEdgeInput(e));
476
+ const request = { edges: normalized };
477
+ const response = (await this.client.batchCreateEdgesRequest(this.graphName, request));
478
+ return response?.data?.count ?? response?.count ?? normalized.length;
479
+ }
480
+ /**
481
+ * Get a node by ID
482
+ */
483
+ async getNode(nodeId) {
484
+ try {
485
+ const data = await this.client.getNodeRequest(this.graphName, nodeId);
486
+ return data;
487
+ }
488
+ catch (e) {
489
+ // The facade maps a 404 to a ProximaDBError (statusCode 404, message =
490
+ // server body). Treat "not found" as a null result, preserving the
491
+ // pre-rebase behavior; match on status or the body text.
492
+ const status = e.statusCode;
493
+ if (status === 404) {
494
+ return null;
495
+ }
496
+ if (e instanceof Error && e.message.includes("404")) {
497
+ return null;
498
+ }
499
+ throw e;
500
+ }
501
+ }
502
+ /**
503
+ * Delete a node by ID
504
+ */
505
+ async deleteNode(nodeId) {
506
+ await this.client.deleteNodeRequest(this.graphName, nodeId);
507
+ }
508
+ // deleteEdge is intentionally LEFT facade-built (generic URL path): the
509
+ // generated REST client has no matching typed op for this 3-segment route
510
+ // shape. The OpenAPI spec / generated client model edge deletion as
511
+ // `DELETE /api/v2/graphs/{graph_id}/edges/{edge_id}` (single `edge_id`),
512
+ // whereas this SDK's public signature is `(source, target, relationship)` →
513
+ // `/edges/{source}/{target}/{relationship}`. Until the SDK signature is
514
+ // reconciled to `{edge_id}` (separate change), this cannot route through the
515
+ // generated client. Tracked separately.
516
+ /**
517
+ * Delete an edge
518
+ */
519
+ async deleteEdge(source, target, relationship) {
520
+ const url = this.client.url() + "/api/v2/graphs/" + this.graphName + "/edges/" + source + "/" + target + "/" + relationship;
521
+ await this.client.delete(url);
522
+ }
523
+ /**
524
+ * Get graph statistics.
525
+ *
526
+ * Routed through the generated typed transport (TD-126 Phase 4).
527
+ * Wire endpoint: GET /api/v2/graphs/{graph_id} (getGraph)
528
+ */
529
+ async info() {
530
+ const data = await this.client.getGraphRequest(this.graphName);
531
+ return data;
532
+ }
533
+ }
534
+ exports.GraphHandle = GraphHandle;
535
+ // ============================================================================
536
+ // GRAPH BUILDER
537
+ // ============================================================================
538
+ /**
539
+ * Builder for creating graphs
540
+ */
541
+ class GraphBuilder {
542
+ client;
543
+ graphId;
544
+ graphDisplayName = null;
545
+ graphDescription = null;
546
+ constructor(client, graphId) {
547
+ this.client = client;
548
+ this.graphId = graphId;
549
+ }
550
+ /**
551
+ * Set an optional human-readable name (defaults server-side to graph_id).
552
+ */
553
+ name(displayName) {
554
+ this.graphDisplayName = displayName;
555
+ return this;
556
+ }
557
+ /**
558
+ * Set the graph description
559
+ */
560
+ description(desc) {
561
+ this.graphDescription = desc;
562
+ return this;
563
+ }
564
+ /**
565
+ * Execute the graph creation.
566
+ *
567
+ * Wire endpoint: POST /api/v2/graphs
568
+ * OpenAPI operationId: createGraph
569
+ *
570
+ * Body shape (server-true, per `CreateGraphRequest`):
571
+ * `{ graph_id, name?, description? }`.
572
+ */
573
+ async execute() {
574
+ const request = { graph_id: this.graphId };
575
+ if (this.graphDisplayName !== null) {
576
+ request.name = this.graphDisplayName;
577
+ }
578
+ if (this.graphDescription !== null) {
579
+ request.description = this.graphDescription;
580
+ }
581
+ await this.client.createGraphRequest(request);
582
+ }
583
+ }
584
+ exports.GraphBuilder = GraphBuilder;
585
+ // ============================================================================
586
+ // INTERNAL: legacy -> spec normalizers
587
+ // ============================================================================
588
+ function normalizeNodeInput(input) {
589
+ // Distinguish legacy `GraphNode` (has singular `label` and/or `vector`) from
590
+ // spec-true `NodeInput` (has `labels[]` / `embedding`). Field absence is
591
+ // fine — `NodeInput` only requires `id`.
592
+ const out = { id: input.id };
593
+ // Inline structural check avoids a hard cross-cast.
594
+ const legacy = input;
595
+ const spec = input;
596
+ if (spec.labels !== undefined) {
597
+ out.labels = spec.labels;
598
+ }
599
+ else if (legacy.label !== undefined) {
600
+ out.labels = [legacy.label];
601
+ }
602
+ if (spec.properties !== undefined) {
603
+ out.properties = spec.properties;
604
+ }
605
+ else if (legacy.properties !== undefined) {
606
+ out.properties = legacy.properties;
607
+ }
608
+ if (spec.embedding !== undefined) {
609
+ out.embedding = spec.embedding;
610
+ }
611
+ else if (legacy.vector !== undefined) {
612
+ out.embedding = { vector: legacy.vector };
613
+ }
614
+ return out;
615
+ }
616
+ function normalizeEdgeInput(input) {
617
+ const spec = input;
618
+ const legacy = input;
619
+ // Spec edge has `id` (required), legacy has none. If absent on a legacy
620
+ // value, surface a hard error — server `EdgeInput.id` is required.
621
+ if (spec.id === undefined) {
622
+ throw new Error("addEdges: edge.id is required by EdgeInput (legacy GraphEdge has no id; pass an EdgeInput)");
623
+ }
624
+ const out = {
625
+ id: spec.id,
626
+ from_node_id: spec.from_node_id ?? legacy.source,
627
+ to_node_id: spec.to_node_id ?? legacy.target,
628
+ edge_type: spec.edge_type ?? legacy.relationship,
629
+ };
630
+ if (spec.properties !== undefined) {
631
+ out.properties = spec.properties;
632
+ }
633
+ else if (legacy.properties !== undefined) {
634
+ out.properties = legacy.properties;
635
+ }
636
+ if (spec.weight !== undefined) {
637
+ out.weight = spec.weight;
638
+ }
639
+ else if (legacy.weight !== undefined) {
640
+ out.weight = legacy.weight;
641
+ }
642
+ return out;
643
+ }
644
+ // ============================================================================
645
+ // CONVENIENCE FUNCTIONS
646
+ // ============================================================================
647
+ /**
648
+ * Create a new GraphNode
649
+ */
650
+ function createNode(id) {
651
+ return {
652
+ id,
653
+ properties: {},
654
+ };
655
+ }
656
+ /**
657
+ * Create a new GraphNode with builder pattern
658
+ */
659
+ function node(id) {
660
+ const n = { id, properties: {} };
661
+ return {
662
+ label: (l) => { n.label = l; return node(id); },
663
+ property: (k, v) => { n.properties[k] = v; return node(id); },
664
+ vector: (v) => { n.vector = v; return node(id); },
665
+ build: () => n,
666
+ };
667
+ }
668
+ /**
669
+ * Create a new GraphEdge
670
+ */
671
+ function createEdge(source, target, relationship) {
672
+ return {
673
+ source,
674
+ target,
675
+ relationship,
676
+ properties: {},
677
+ };
678
+ }
679
+ /**
680
+ * Create a new GraphEdge with builder pattern
681
+ */
682
+ function edge(source, target, relationship) {
683
+ const e = { source, target, relationship, properties: {} };
684
+ return {
685
+ property: (k, v) => { e.properties[k] = v; return edge(source, target, relationship); },
686
+ weight: (w) => { e.weight = w; return edge(source, target, relationship); },
687
+ build: () => e,
688
+ };
689
+ }
690
+ //# sourceMappingURL=graph.js.map