@tari-project/tari-extension-query-builder 0.0.13 → 0.0.15

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/types.d.ts CHANGED
@@ -4,4 +4,9 @@ export interface TariFlowNodeDetails {
4
4
  templateAddress: string;
5
5
  functionName: string;
6
6
  }
7
+ declare global {
8
+ interface BigInt {
9
+ toJSON(): string | number;
10
+ }
11
+ }
7
12
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEhE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,WAAW,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEhE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,WAAW,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAGD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,MAAM,IAAI,MAAM,GAAG,MAAM,CAAC;KAC3B;CACF"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tari-project/tari-extension-query-builder",
3
3
  "private": false,
4
- "version": "0.0.13",
4
+ "version": "0.0.15",
5
5
  "type": "module",
6
6
  "main": "dist/tari-extension-query-builder.umd.js",
7
7
  "module": "dist/tari-extension-query-builder.es.js",
@@ -37,7 +37,7 @@
37
37
  "@radix-ui/react-separator": "^1.1.2",
38
38
  "@radix-ui/react-slot": "^1.1.2",
39
39
  "@radix-ui/react-tooltip": "^1.1.8",
40
- "@tari-project/tarijs-all": "^0.10.1",
40
+ "@tari-project/tarijs-all": "^0.11.0",
41
41
  "@xyflow/react": "^12.4.4",
42
42
  "class-variance-authority": "^0.7.1",
43
43
  "clsx": "^2.1.1",
@@ -48,12 +48,12 @@
48
48
  "tailwindcss-animate": "^1.0.7",
49
49
  "uuid": "^11.1.0",
50
50
  "zod": "^3.25.67",
51
- "@tari-project/tari-extension-common": "^0.0.13"
51
+ "@tari-project/tari-extension-common": "^0.0.15"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@eslint/js": "^9.21.0",
55
55
  "@tailwindcss/vite": "^4.0.12",
56
- "@tari-project/typescript-bindings": "^1.11.1",
56
+ "@tari-project/typescript-bindings": "^1.13.1",
57
57
  "@types/node": "^24.0.8",
58
58
  "@types/react": "^19.1.8",
59
59
  "@types/react-dom": "^19.1.6",
@@ -114,7 +114,7 @@ function GenericNode(props: NodeProps<GenericNode>) {
114
114
 
115
115
  {title && <h3 className="text-center font-bold pt-1 pb-3 border-b">{title}</h3>}
116
116
 
117
- {inputs && (
117
+ {inputs?.length ? (
118
118
  <form noValidate>
119
119
  {inputs.map((input) => {
120
120
  const type = new TariType(input.type);
@@ -185,7 +185,7 @@ function GenericNode(props: NodeProps<GenericNode>) {
185
185
  }
186
186
  })}
187
187
  </form>
188
- )}
188
+ ) : null}
189
189
 
190
190
  {outputType && renderOutputs(outputType, getOutputOffset)}
191
191
  </>
@@ -7,6 +7,9 @@ import {
7
7
  Viewport,
8
8
  Panel,
9
9
  MiniMap,
10
+ OnEdgesChange,
11
+ OnNodesChange,
12
+ OnConnect,
10
13
  } from "@xyflow/react";
11
14
  import {
12
15
  CALL_NODE_DRAG_DROP_TYPE,
@@ -94,6 +97,9 @@ export interface QueryBuilderProps {
94
97
  getTransactionProps?: () => Promise<TransactionProps>;
95
98
  executeTransaction?: (transaction: UnsignedTransactionV1) => Promise<void>;
96
99
  showGeneratedCode?: (code: string, type: GeneratedCodeType) => Promise<void>;
100
+ onEdgesChange?: OnEdgesChange;
101
+ onNodesChange?: OnNodesChange;
102
+ onConnect?: OnConnect;
97
103
  }
98
104
 
99
105
  const nodeTypes = {
@@ -111,6 +117,9 @@ function Flow({
111
117
  getTransactionProps,
112
118
  executeTransaction,
113
119
  showGeneratedCode,
120
+ onEdgesChange: onEdgesChangeCallback,
121
+ onNodesChange: onNodesChangeCallback,
122
+ onConnect: onConnectCallback,
114
123
  }: QueryBuilderProps) {
115
124
  const {
116
125
  nodes,
@@ -465,9 +474,18 @@ function Flow({
465
474
  edgeTypes={edgeTypes}
466
475
  nodes={nodes}
467
476
  edges={edges}
468
- onNodesChange={onNodesChange}
469
- onEdgesChange={onEdgesChange}
470
- onConnect={onConnect}
477
+ onNodesChange={(change) => {
478
+ onNodesChange(change);
479
+ onNodesChangeCallback?.(change);
480
+ }}
481
+ onEdgesChange={(change) => {
482
+ onEdgesChange(change);
483
+ onEdgesChangeCallback?.(change);
484
+ }}
485
+ onConnect={(connection) => {
486
+ onConnect(connection);
487
+ onConnectCallback?.(connection);
488
+ }}
471
489
  onMove={onMove}
472
490
  onDragOver={onDragOver}
473
491
  onDrop={onDrop}
@@ -21,11 +21,8 @@ export class TemplateReader {
21
21
  if (!fn) {
22
22
  return null;
23
23
  }
24
- const args = fn.arguments;
25
- if (!args.length) {
26
- return null;
27
- }
28
- const isMethod = args[0].name === "self";
24
+ const args = fn.arguments || [];
25
+ const isMethod = args[0]?.name === "self";
29
26
  const inputs = args.map((arg) => {
30
27
  if (arg.name === "self") {
31
28
  return {
@@ -1,7 +1,7 @@
1
1
  import { create } from "zustand";
2
2
  import { addEdge, applyNodeChanges, applyEdgeChanges } from "@xyflow/react";
3
3
  import { v4 as uuidv4 } from "uuid";
4
- import { CustomNode, InputConnectionType, NodeType, type QueryBuilderState } from "./types";
4
+ import { CustomNode, InputConnectionType, NodeType, type QueryBuilderState, SchemaAndVersion } from "./types";
5
5
  import { NODE_ENTRY, NODE_EXIT } from "@/components/query-builder/nodes/generic-node.types";
6
6
  import { getSchemaFullPath, latestVersionHandler, versionHandlers } from "./persistence/handlers";
7
7
  import { NEW_INPUT_PARAM } from "@/components/query-builder/nodes/input/constants";
@@ -12,6 +12,7 @@ import {
12
12
  CALL_NODE_RETURN_TUPLE_2,
13
13
  } from "@/components/query-builder/nodes/call-node.types";
14
14
  import { TariType } from "@/query-builder/tari-type";
15
+ import { LatestPersistedState } from "@/store/persistence/types.ts";
15
16
 
16
17
  const DROP_NODE_OFFSET_X = 200;
17
18
  const DROP_NODE_OFFSET_Y = 50;
@@ -242,43 +243,30 @@ const useStore = create<QueryBuilderState>((set, get) => ({
242
243
  }
243
244
  },
244
245
  saveStateToString: () => {
246
+ const { getState } = get();
247
+ const state = getState();
248
+ return JSON.stringify(state, undefined, 2);
249
+ },
250
+ loadStateFromString: (state) => {
251
+ let parsedState: SchemaAndVersion & LatestPersistedState;
252
+ try {
253
+ parsedState = JSON.parse(state) as SchemaAndVersion & LatestPersistedState;
254
+ } catch (error) {
255
+ throw new Error(`Failed to parse state: ${String(error)}`);
256
+ }
257
+
258
+ set(validateState(parsedState));
259
+ },
260
+ getState: () => {
245
261
  const state = get();
246
262
  const persistedState = latestVersionHandler.save(state);
247
- const withSchema = {
263
+ return {
248
264
  $schema: getSchemaFullPath(persistedState.version),
249
265
  ...persistedState,
250
266
  };
251
- return JSON.stringify(withSchema, undefined, 2);
252
267
  },
253
- loadStateFromString: (state) => {
254
- try {
255
- const parsedState = JSON.parse(state) as { version?: string } | undefined;
256
- if (typeof parsedState?.version !== "string") {
257
- throw new Error("Invalid persisted state: Missing or invalid version.");
258
- }
259
-
260
- const version = parsedState.version;
261
- const handler = versionHandlers[version];
262
-
263
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
264
- if (!handler) {
265
- throw new Error(`No handler found for version: ${version}`);
266
- }
267
-
268
- const validationResult = handler.load(parsedState);
269
-
270
- if (validationResult.success) {
271
- if (version === "1.0") {
272
- set({ nodes: validationResult.data.nodes, edges: validationResult.data.edges });
273
- } else {
274
- throw new Error(`Unsupported version: ${version}`);
275
- }
276
- } else {
277
- throw new Error(`Validation failed: ${validationResult.error.toString()}`);
278
- }
279
- } catch (error) {
280
- throw new Error(`Failed to load state: ${String(error)}`);
281
- }
268
+ setState: (state) => {
269
+ set(validateState(state));
282
270
  },
283
271
  isValidInputParamsTitle: (nodeId, title) => {
284
272
  if (!title.length || /\s/g.test(title) || !/^[a-zA-Z]/.test(title)) {
@@ -357,7 +345,7 @@ const useStore = create<QueryBuilderState>((set, get) => ({
357
345
  }
358
346
  },
359
347
  isValidInputParamsName: (nodeId, paramId, name) => {
360
- if (!name.length || /\s/g.test(name) || !!/^[a-zA-Z]/.test(name)) {
348
+ if (!name.length || /\s/g.test(name) || /^[a-zA-Z]/.test(name)) {
361
349
  return false;
362
350
  }
363
351
  const node = get().getNodeById(nodeId);
@@ -397,4 +385,35 @@ const useStore = create<QueryBuilderState>((set, get) => ({
397
385
  },
398
386
  }));
399
387
 
388
+ function validateState(state: (SchemaAndVersion & LatestPersistedState) | undefined) {
389
+ if (typeof state?.version !== "string") {
390
+ throw new Error("Invalid persisted state: Missing or invalid version.");
391
+ }
392
+
393
+ try {
394
+ const version = state.version;
395
+ const handler = versionHandlers[version];
396
+
397
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
398
+ if (!handler) {
399
+ throw new Error(`No handler found for version: ${version}`);
400
+ }
401
+
402
+ const validationResult = handler.load(state);
403
+
404
+ if (validationResult.success) {
405
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
406
+ if (version === "1.0") {
407
+ return { nodes: validationResult.data.nodes, edges: validationResult.data.edges };
408
+ } else {
409
+ throw new Error(`Unsupported version: ${String(version)}`);
410
+ }
411
+ } else {
412
+ throw new Error(`Validation failed: ${validationResult.error.toString()}`);
413
+ }
414
+ } catch (error) {
415
+ throw new Error(`Failed to load state: ${String(error)}`);
416
+ }
417
+ }
418
+
400
419
  export default useStore;
@@ -9,6 +9,7 @@ import {
9
9
  XYPosition,
10
10
  } from "@xyflow/react";
11
11
  import { SafeParseReturnType } from "zod";
12
+ import { LatestPersistedState } from "@/store/persistence/types.ts";
12
13
 
13
14
  export enum NodeType {
14
15
  GenericNode = "genericNode",
@@ -34,11 +35,13 @@ export interface CallNodeMetadata {
34
35
 
35
36
  export type GenericNodeMetadata = CallNodeMetadata;
36
37
  export type GenericNodeIcon = "enter" | "rocket" | "home" | "cube" | "check-circled" | "archive" | "component";
38
+
37
39
  export enum InputConnectionType {
38
40
  None = 0,
39
41
  Parameter,
40
42
  ComponentAddress,
41
43
  }
44
+
42
45
  export interface GenericNodeInputType {
43
46
  inputConnectionType: InputConnectionType;
44
47
  type: Type;
@@ -46,11 +49,13 @@ export interface GenericNodeInputType {
46
49
  label?: string;
47
50
  validValues?: string[];
48
51
  }
52
+
49
53
  export interface GenericNodeOutputType {
50
54
  type: Type;
51
55
  name: string;
52
56
  label?: string;
53
57
  }
58
+
54
59
  // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
55
60
  export type GenericNodeData = {
56
61
  type: GenericNodeType;
@@ -84,6 +89,11 @@ export type InputParamsNode = Node<InputParamsNodeData, NodeType.InputParamsNode
84
89
 
85
90
  export type CustomNode = GenericNode | InputParamsNode;
86
91
 
92
+ export interface SchemaAndVersion {
93
+ $schema: string;
94
+ version: string;
95
+ }
96
+
87
97
  export interface QueryBuilderState {
88
98
  readOnly: boolean;
89
99
  nodes: CustomNode[];
@@ -106,6 +116,8 @@ export interface QueryBuilderState {
106
116
  removeNode: (nodeId: string) => void;
107
117
  saveStateToString: () => string;
108
118
  loadStateFromString: (state: string) => void;
119
+ setState: (state: SchemaAndVersion & LatestPersistedState) => void;
120
+ getState: () => SchemaAndVersion & LatestPersistedState;
109
121
  isValidInputParamsTitle: (nodeId: string, title: string) => boolean;
110
122
  updateInputParamsTitle: (nodeId: string, title: string) => void;
111
123
  updateInputParamsNode: (nodeId: string, paramId: string, value: SafeParseReturnType<unknown, unknown>) => void;
package/src/types.ts CHANGED
@@ -5,3 +5,20 @@ export interface TariFlowNodeDetails {
5
5
  templateAddress: string;
6
6
  functionName: string;
7
7
  }
8
+
9
+ // Extend BigInt to support JSON serialization
10
+ declare global {
11
+ interface BigInt {
12
+ toJSON(): string | number;
13
+ }
14
+ }
15
+
16
+ BigInt.prototype.toJSON = function () {
17
+ // if the number is too large, return it as a string
18
+ // otherwise return it as a number
19
+ const int = this.valueOf();
20
+ if (int > BigInt(Number.MAX_SAFE_INTEGER) || int < BigInt(Number.MIN_SAFE_INTEGER)) {
21
+ return this.toString();
22
+ }
23
+ return Number(this);
24
+ };