@avaprotocol/sdk-js 2.4.3 → 2.5.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 (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +791 -255
  4. package/dist/index.mjs +799 -258
  5. package/dist/models/node/contractRead.d.ts +14 -0
  6. package/dist/models/node/contractRead.d.ts.map +1 -1
  7. package/dist/models/node/contractRead.js +27 -18
  8. package/dist/models/node/contractWrite.d.ts +14 -0
  9. package/dist/models/node/contractWrite.d.ts.map +1 -1
  10. package/dist/models/node/contractWrite.js +25 -16
  11. package/dist/models/node/customCode.d.ts +10 -1
  12. package/dist/models/node/customCode.d.ts.map +1 -1
  13. package/dist/models/node/customCode.js +19 -9
  14. package/dist/models/node/ethTransfer.d.ts +9 -0
  15. package/dist/models/node/ethTransfer.d.ts.map +1 -1
  16. package/dist/models/node/ethTransfer.js +14 -5
  17. package/dist/models/node/filter.d.ts.map +1 -1
  18. package/dist/models/node/filter.js +22 -3
  19. package/dist/models/node/graphqlQuery.d.ts +10 -0
  20. package/dist/models/node/graphqlQuery.d.ts.map +1 -1
  21. package/dist/models/node/graphqlQuery.js +20 -12
  22. package/dist/models/node/loop.d.ts +5 -1
  23. package/dist/models/node/loop.d.ts.map +1 -1
  24. package/dist/models/node/loop.js +151 -99
  25. package/dist/models/node/restApi.d.ts +11 -0
  26. package/dist/models/node/restApi.d.ts.map +1 -1
  27. package/dist/models/node/restApi.js +21 -13
  28. package/dist/models/step.d.ts.map +1 -1
  29. package/dist/models/step.js +239 -21
  30. package/dist/models/trigger/manual.d.ts +6 -10
  31. package/dist/models/trigger/manual.d.ts.map +1 -1
  32. package/dist/models/trigger/manual.js +108 -25
  33. package/dist/models/workflow.d.ts.map +1 -1
  34. package/dist/models/workflow.js +0 -2
  35. package/dist/utils.d.ts +0 -14
  36. package/dist/utils.d.ts.map +1 -1
  37. package/dist/utils.js +0 -62
  38. package/package.json +2 -2
@@ -1,6 +1,12 @@
1
1
  import * as avs_pb from "@/grpc_codegen/avs_pb";
2
2
  import Node from "./interface";
3
- import { NodeType, } from "@avaprotocol/types";
3
+ import CustomCodeNode from "./customCode";
4
+ import ETHTransferNode from "./ethTransfer";
5
+ import RestAPINode from "./restApi";
6
+ import GraphQLQueryNode from "./graphqlQuery";
7
+ import ContractReadNode from "./contractRead";
8
+ import ContractWriteNode from "./contractWrite";
9
+ import { NodeType, ExecutionMode, } from "@avaprotocol/types";
4
10
  import { convertInputToProtobuf, extractInputFromProtobuf } from "../../utils";
5
11
  class LoopNode extends Node {
6
12
  constructor(props) {
@@ -16,16 +22,13 @@ class LoopNode extends Node {
16
22
  const configData = loopNode.getConfig()?.toObject();
17
23
  const loopNodeData = loopNode.toObject();
18
24
  // Since LoopNodeData is now Config.AsObject, we need to merge the config properties
19
- // with the nested node data from the full object
25
+ // with the runner data from the protobuf structure
20
26
  const data = {
21
27
  ...configData,
22
- // Keep the nested node structures from the full object
23
- restApi: loopNodeData.restApi,
24
- customCode: loopNodeData.customCode,
25
- ethTransfer: loopNodeData.ethTransfer,
26
- contractRead: loopNodeData.contractRead,
27
- contractWrite: loopNodeData.contractWrite,
28
- graphqlDataQuery: loopNodeData.graphqlDataQuery,
28
+ // Extract runner data from the oneof runner field
29
+ runner: this.extractRunnerFromProtobuf(loopNodeData),
30
+ // Map execution mode from protobuf enum to ExecutionMode enum
31
+ executionMode: this.mapExecutionModeFromProtobuf(configData?.executionMode),
29
32
  };
30
33
  // Extract input data from top-level TaskNode.input field (not nested LoopNode.input)
31
34
  // This matches where we set it in toRequest() and where the Go backend looks for it
@@ -40,6 +43,61 @@ class LoopNode extends Node {
40
43
  input: input,
41
44
  });
42
45
  }
46
+ static extractRunnerFromProtobuf(loopNodeData) {
47
+ // Define a mapping of runner types to their corresponding data keys
48
+ const runnerMapping = {
49
+ restApi: "restApi",
50
+ customCode: "customCode",
51
+ ethTransfer: "ethTransfer",
52
+ contractRead: "contractRead",
53
+ contractWrite: "contractWrite",
54
+ graphqlDataQuery: "graphqlDataQuery",
55
+ };
56
+ // Iterate over the mapping to find the matching runner type
57
+ for (const [type, key] of Object.entries(runnerMapping)) {
58
+ if (loopNodeData[key]) {
59
+ return { type, data: loopNodeData[key] };
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ static mapExecutionModeFromProtobuf(executionMode) {
65
+ // Map protobuf ExecutionMode enum to ExecutionMode enum
66
+ // EXECUTION_MODE_SEQUENTIAL = 0, EXECUTION_MODE_PARALLEL = 1
67
+ switch (executionMode) {
68
+ case 0:
69
+ return ExecutionMode.Sequential;
70
+ case 1:
71
+ return ExecutionMode.Parallel;
72
+ default:
73
+ return ExecutionMode.Sequential; // Default to sequential for safety
74
+ }
75
+ }
76
+ mapExecutionModeToProtobuf(executionMode) {
77
+ // Map ExecutionMode enum or string to protobuf ExecutionMode enum
78
+ // EXECUTION_MODE_SEQUENTIAL = 0, EXECUTION_MODE_PARALLEL = 1
79
+ if (!executionMode) {
80
+ return 0; // Default to sequential for safety
81
+ }
82
+ if (typeof executionMode === "string") {
83
+ switch (executionMode.toLowerCase()) {
84
+ case "parallel":
85
+ return 1;
86
+ case "sequential":
87
+ default:
88
+ return 0; // Default to sequential for safety
89
+ }
90
+ }
91
+ else {
92
+ switch (executionMode) {
93
+ case ExecutionMode.Parallel:
94
+ return 1;
95
+ case ExecutionMode.Sequential:
96
+ default:
97
+ return 0; // Default to sequential for safety
98
+ }
99
+ }
100
+ }
43
101
  toRequest() {
44
102
  const node = new avs_pb.TaskNode();
45
103
  const loopNode = new avs_pb.LoopNode();
@@ -51,6 +109,9 @@ class LoopNode extends Node {
51
109
  config.setSourceId(data.sourceId || "");
52
110
  config.setIterVal(data.iterVal || "");
53
111
  config.setIterKey(data.iterKey || "");
112
+ // Set execution mode - map ExecutionMode enum to protobuf enum
113
+ const executionMode = this.mapExecutionModeToProtobuf(data.executionMode);
114
+ config.setExecutionMode(executionMode);
54
115
  loopNode.setConfig(config);
55
116
  // Set input data on the top-level TaskNode, not the nested LoopNode
56
117
  // This matches where the Go backend's ExtractNodeInputData() looks for it
@@ -58,106 +119,97 @@ class LoopNode extends Node {
58
119
  if (inputValue) {
59
120
  node.setInput(inputValue);
60
121
  }
61
- // Handle nested nodes - these still use the nested structure within LoopNodeData
62
- if (data.ethTransfer) {
63
- const ethTransfer = new avs_pb.ETHTransferNode();
64
- if (data.ethTransfer.config) {
65
- const config = new avs_pb.ETHTransferNode.Config();
66
- config.setDestination(data.ethTransfer.config.destination);
67
- config.setAmount(data.ethTransfer.config.amount);
68
- ethTransfer.setConfig(config);
69
- }
70
- loopNode.setEthTransfer(ethTransfer);
122
+ // Handle runner - check the runner field and set the appropriate oneof field
123
+ if (data.runner) {
124
+ this.setRunnerOnProtobuf(loopNode, data.runner);
71
125
  }
72
- else if (data.contractWrite) {
73
- const contractWrite = new avs_pb.ContractWriteNode();
74
- if (data.contractWrite.config) {
75
- const config = new avs_pb.ContractWriteNode.Config();
76
- config.setContractAddress(data.contractWrite.config.contractAddress);
77
- config.setCallData(data.contractWrite.config.callData);
78
- config.setContractAbi(data.contractWrite.config.contractAbi);
79
- // Handle method calls array for ContractWrite
80
- const methodCalls = data.contractWrite.config.methodCallsList || [];
81
- methodCalls.forEach((methodCall) => {
82
- const methodCallMsg = new avs_pb.ContractWriteNode.MethodCall();
83
- methodCallMsg.setCallData(methodCall.callData);
84
- if (methodCall.methodName) {
85
- methodCallMsg.setMethodName(methodCall.methodName);
86
- }
87
- config.addMethodCalls(methodCallMsg);
88
- });
89
- contractWrite.setConfig(config);
90
- }
91
- loopNode.setContractWrite(contractWrite);
126
+ node.setLoop(loopNode);
127
+ return node;
128
+ }
129
+ setRunnerOnProtobuf(loopNode, runner) {
130
+ if (!runner || !runner.type || !runner.data) {
131
+ return;
92
132
  }
93
- else if (data.contractRead) {
94
- const contractRead = new avs_pb.ContractReadNode();
95
- if (data.contractRead.config) {
96
- const config = new avs_pb.ContractReadNode.Config();
97
- config.setContractAddress(data.contractRead.config.contractAddress);
98
- config.setContractAbi(data.contractRead.config.contractAbi);
99
- // Handle method calls array
100
- const methodCalls = data.contractRead.config.methodCallsList || [];
101
- methodCalls.forEach((methodCall) => {
102
- const methodCallMsg = new avs_pb.ContractReadNode.MethodCall();
103
- methodCallMsg.setCallData(methodCall.callData);
104
- if (methodCall.methodName) {
105
- methodCallMsg.setMethodName(methodCall.methodName);
106
- }
107
- if (methodCall.applyToFields) {
108
- methodCallMsg.setApplyToFieldsList(methodCall.applyToFields);
109
- }
110
- config.addMethodCalls(methodCallMsg);
111
- });
112
- contractRead.setConfig(config);
133
+ switch (runner.type) {
134
+ case "ethTransfer": {
135
+ const ethTransferData = runner.data;
136
+ if (ethTransferData.config) {
137
+ const ethConfig = ethTransferData.config;
138
+ const ethTransfer = ETHTransferNode.createProtobufNode({
139
+ destination: ethConfig.destination,
140
+ amount: ethConfig.amount,
141
+ });
142
+ loopNode.setEthTransfer(ethTransfer);
143
+ }
144
+ break;
113
145
  }
114
- loopNode.setContractRead(contractRead);
115
- }
116
- else if (data.graphqlDataQuery) {
117
- const graphqlQuery = new avs_pb.GraphQLQueryNode();
118
- if (data.graphqlDataQuery.config) {
119
- const config = new avs_pb.GraphQLQueryNode.Config();
120
- config.setUrl(data.graphqlDataQuery.config.url);
121
- config.setQuery(data.graphqlDataQuery.config.query);
122
- if (data.graphqlDataQuery.config.variablesMap &&
123
- data.graphqlDataQuery.config.variablesMap.length > 0) {
124
- data.graphqlDataQuery.config.variablesMap.forEach(([key, value]) => {
125
- config.getVariablesMap().set(key, value);
146
+ case "contractWrite": {
147
+ const contractWriteData = runner.data;
148
+ if (contractWriteData.config) {
149
+ const writeConfig = contractWriteData.config;
150
+ const contractWrite = ContractWriteNode.createProtobufNode({
151
+ contractAddress: writeConfig.contractAddress,
152
+ callData: writeConfig.callData,
153
+ contractAbi: writeConfig.contractAbi,
154
+ methodCalls: writeConfig.methodCallsList || [],
126
155
  });
156
+ loopNode.setContractWrite(contractWrite);
127
157
  }
128
- graphqlQuery.setConfig(config);
158
+ break;
129
159
  }
130
- loopNode.setGraphqlDataQuery(graphqlQuery);
131
- }
132
- else if (data.restApi) {
133
- const restApi = new avs_pb.RestAPINode();
134
- if (data.restApi.config) {
135
- const config = new avs_pb.RestAPINode.Config();
136
- config.setUrl(data.restApi.config.url);
137
- config.setMethod(data.restApi.config.method);
138
- config.setBody(data.restApi.config.body || "");
139
- if (data.restApi.config.headersMap &&
140
- data.restApi.config.headersMap.length > 0) {
141
- data.restApi.config.headersMap.forEach(([key, value]) => {
142
- config.getHeadersMap().set(key, value);
160
+ case "contractRead": {
161
+ const contractReadData = runner.data;
162
+ if (contractReadData.config) {
163
+ const readConfig = contractReadData.config;
164
+ const contractRead = ContractReadNode.createProtobufNode({
165
+ contractAddress: readConfig.contractAddress,
166
+ contractAbi: readConfig.contractAbi,
167
+ methodCalls: readConfig.methodCallsList || [],
143
168
  });
169
+ loopNode.setContractRead(contractRead);
144
170
  }
145
- restApi.setConfig(config);
171
+ break;
146
172
  }
147
- loopNode.setRestApi(restApi);
148
- }
149
- else if (data.customCode) {
150
- const customCode = new avs_pb.CustomCodeNode();
151
- if (data.customCode.config) {
152
- const config = new avs_pb.CustomCodeNode.Config();
153
- config.setLang(data.customCode.config.lang);
154
- config.setSource(data.customCode.config.source);
155
- customCode.setConfig(config);
173
+ case "graphqlDataQuery": {
174
+ const graphqlData = runner.data;
175
+ if (graphqlData.config) {
176
+ const gqlConfig = graphqlData.config;
177
+ const graphqlQuery = GraphQLQueryNode.createProtobufNode({
178
+ url: gqlConfig.url,
179
+ query: gqlConfig.query,
180
+ variablesMap: gqlConfig.variablesMap,
181
+ });
182
+ loopNode.setGraphqlDataQuery(graphqlQuery);
183
+ }
184
+ break;
185
+ }
186
+ case "restApi": {
187
+ const restApiData = runner.data;
188
+ if (restApiData.config) {
189
+ const apiConfig = restApiData.config;
190
+ const restApi = RestAPINode.createProtobufNode({
191
+ url: apiConfig.url,
192
+ method: apiConfig.method,
193
+ body: apiConfig.body || "",
194
+ headersMap: apiConfig.headersMap,
195
+ });
196
+ loopNode.setRestApi(restApi);
197
+ }
198
+ break;
199
+ }
200
+ case "customCode": {
201
+ const customCodeData = runner.data;
202
+ if (customCodeData.config) {
203
+ const codeConfig = customCodeData.config;
204
+ const customCode = CustomCodeNode.createProtobufNode({
205
+ lang: codeConfig.lang,
206
+ source: codeConfig.source,
207
+ });
208
+ loopNode.setCustomCode(customCode);
209
+ }
210
+ break;
156
211
  }
157
- loopNode.setCustomCode(customCode);
158
212
  }
159
- node.setLoop(loopNode);
160
- return node;
161
213
  }
162
214
  static fromOutputData(outputData) {
163
215
  // For immediate execution, data comes as CustomCode format
@@ -182,7 +234,7 @@ class LoopNode extends Node {
182
234
  try {
183
235
  return JSON.parse(loopObj.data);
184
236
  }
185
- catch (e) {
237
+ catch {
186
238
  // If JSON parsing fails, return the raw data
187
239
  return loopObj.data;
188
240
  }
@@ -3,6 +3,17 @@ import * as avs_pb from "@/grpc_codegen/avs_pb";
3
3
  import { RestAPINodeProps } from "@avaprotocol/types";
4
4
  declare class RestAPINode extends Node {
5
5
  constructor(props: RestAPINodeProps);
6
+ /**
7
+ * Create a protobuf RestAPINode from config data
8
+ * @param configData - The configuration data for the REST API node
9
+ * @returns Configured avs_pb.RestAPINode
10
+ */
11
+ static createProtobufNode(configData: {
12
+ url: string;
13
+ method: string;
14
+ body?: string;
15
+ headersMap?: Array<[string, string]>;
16
+ }): avs_pb.RestAPINode;
6
17
  static fromResponse(raw: avs_pb.TaskNode): RestAPINode;
7
18
  toRequest(): avs_pb.TaskNode;
8
19
  static fromOutputData(outputData: avs_pb.RunNodeWithInputsResp): any;
@@ -1 +1 @@
1
- {"version":3,"file":"restApi.d.ts","sourceRoot":"","sources":["../../../src/models/node/restApi.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,aAAa,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAGL,gBAAgB,EAEjB,MAAM,oBAAoB,CAAC;AAS5B,cAAM,WAAY,SAAQ,IAAI;gBAChB,KAAK,EAAE,gBAAgB;IAInC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,GAAG,WAAW;IAmBtD,SAAS,IAAI,MAAM,CAAC,QAAQ;IAyC5B,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,qBAAqB,GAAG,GAAG;CAerE;AAED,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"restApi.d.ts","sourceRoot":"","sources":["../../../src/models/node/restApi.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,aAAa,CAAC;AAC/B,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAGL,gBAAgB,EAEjB,MAAM,oBAAoB,CAAC;AAS5B,cAAM,WAAY,SAAQ,IAAI;gBAChB,KAAK,EAAE,gBAAgB;IAInC;;;;OAIG;IACH,MAAM,CAAC,kBAAkB,CAAC,UAAU,EAAE;QACpC,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KACtC,GAAG,MAAM,CAAC,WAAW;IAmBtB,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,GAAG,WAAW;IAmBtD,SAAS,IAAI,MAAM,CAAC,QAAQ;IAwB5B,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,qBAAqB,GAAG,GAAG;CAerE;AAED,eAAe,WAAW,CAAC"}
@@ -7,6 +7,26 @@ class RestAPINode extends Node {
7
7
  constructor(props) {
8
8
  super({ ...props, type: NodeType.RestAPI, data: props.data });
9
9
  }
10
+ /**
11
+ * Create a protobuf RestAPINode from config data
12
+ * @param configData - The configuration data for the REST API node
13
+ * @returns Configured avs_pb.RestAPINode
14
+ */
15
+ static createProtobufNode(configData) {
16
+ const node = new avs_pb.RestAPINode();
17
+ const config = new avs_pb.RestAPINode.Config();
18
+ config.setUrl(configData.url);
19
+ config.setMethod(configData.method);
20
+ config.setBody(configData.body || "");
21
+ if (configData.headersMap && configData.headersMap.length > 0) {
22
+ const headersMap = config.getHeadersMap();
23
+ configData.headersMap.forEach(([key, value]) => {
24
+ headersMap.set(key, value);
25
+ });
26
+ }
27
+ node.setConfig(config);
28
+ return node;
29
+ }
10
30
  static fromResponse(raw) {
11
31
  // Convert the raw object to RestAPINodeProps, which should keep name and id
12
32
  const obj = raw.toObject();
@@ -27,19 +47,7 @@ class RestAPINode extends Node {
27
47
  const request = new avs_pb.TaskNode();
28
48
  request.setId(this.id);
29
49
  request.setName(this.name);
30
- const nodeData = new avs_pb.RestAPINode();
31
- const config = new avs_pb.RestAPINode.Config();
32
- config.setUrl(this.data.url);
33
- config.setMethod(this.data.method);
34
- config.setBody(this.data.body || "");
35
- if (this.data.headersMap &&
36
- this.data.headersMap.length > 0) {
37
- const headersMap = config.getHeadersMap();
38
- this.data.headersMap.forEach(([key, value]) => {
39
- headersMap.set(key, value);
40
- });
41
- }
42
- nodeData.setConfig(config);
50
+ const nodeData = RestAPINode.createProtobufNode(this.data);
43
51
  // Use the standard utility function to convert input field to protobuf format
44
52
  const inputValue = convertInputToProtobuf(this.input);
45
53
  if (inputValue) {
@@ -1 +1 @@
1
- {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/models/step.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAMhD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEhE,cAAM,IAAK,YAAW,SAAS;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;gBAEF,KAAK,EAAE,SAAS;IAc5B;;;OAGG;IACH,MAAM,IAAI,SAAS;IAgBnB,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,eAAe;IAiX9D,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI;CAqFvD;AAED,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/models/step.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,uBAAuB,CAAC;AAMhD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAEhE,cAAM,IAAK,YAAW,SAAS;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;gBAEF,KAAK,EAAE,SAAS;IAc5B;;;OAGG;IACH,MAAM,IAAI,SAAS;IAgBnB,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,eAAe;IAslB9D,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI;CAqFvD;AAED,eAAe,IAAI,CAAC"}