flowquery 1.0.16 → 1.0.17

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 (318) hide show
  1. package/.github/workflows/python-publish.yml +97 -0
  2. package/dist/compute/runner.d.ts +3 -2
  3. package/dist/compute/runner.d.ts.map +1 -1
  4. package/dist/compute/runner.js +7 -7
  5. package/dist/compute/runner.js.map +1 -1
  6. package/dist/flowquery.min.js +1 -1
  7. package/dist/graph/data.d.ts +31 -0
  8. package/dist/graph/data.d.ts.map +1 -0
  9. package/dist/graph/data.js +110 -0
  10. package/dist/graph/data.js.map +1 -0
  11. package/dist/graph/database.d.ts +20 -0
  12. package/dist/graph/database.d.ts.map +1 -0
  13. package/dist/graph/database.js +77 -0
  14. package/dist/graph/database.js.map +1 -0
  15. package/dist/graph/hops.d.ts +11 -0
  16. package/dist/graph/hops.d.ts.map +1 -0
  17. package/dist/graph/hops.js +25 -0
  18. package/dist/graph/hops.js.map +1 -0
  19. package/dist/graph/node.d.ts +35 -0
  20. package/dist/graph/node.d.ts.map +1 -0
  21. package/dist/graph/node.js +113 -0
  22. package/dist/graph/node.js.map +1 -0
  23. package/dist/graph/node_data.d.ts +11 -0
  24. package/dist/graph/node_data.d.ts.map +1 -0
  25. package/dist/graph/node_data.js +20 -0
  26. package/dist/graph/node_data.js.map +1 -0
  27. package/dist/graph/node_reference.d.ts +10 -0
  28. package/dist/graph/node_reference.d.ts.map +1 -0
  29. package/dist/graph/node_reference.js +52 -0
  30. package/dist/graph/node_reference.js.map +1 -0
  31. package/dist/graph/pattern.d.ts +18 -0
  32. package/dist/graph/pattern.d.ts.map +1 -0
  33. package/dist/graph/pattern.js +114 -0
  34. package/dist/graph/pattern.js.map +1 -0
  35. package/dist/graph/pattern_expression.d.ts +14 -0
  36. package/dist/graph/pattern_expression.d.ts.map +1 -0
  37. package/dist/graph/pattern_expression.js +58 -0
  38. package/dist/graph/pattern_expression.js.map +1 -0
  39. package/dist/graph/patterns.d.ts +11 -0
  40. package/dist/graph/patterns.d.ts.map +1 -0
  41. package/dist/graph/patterns.js +49 -0
  42. package/dist/graph/patterns.js.map +1 -0
  43. package/dist/graph/physical_node.d.ts +10 -0
  44. package/dist/graph/physical_node.d.ts.map +1 -0
  45. package/dist/graph/physical_node.js +40 -0
  46. package/dist/graph/physical_node.js.map +1 -0
  47. package/dist/graph/physical_relationship.d.ts +10 -0
  48. package/dist/graph/physical_relationship.d.ts.map +1 -0
  49. package/dist/graph/physical_relationship.js +40 -0
  50. package/dist/graph/physical_relationship.js.map +1 -0
  51. package/dist/graph/relationship.d.ts +40 -0
  52. package/dist/graph/relationship.d.ts.map +1 -0
  53. package/dist/graph/relationship.js +124 -0
  54. package/dist/graph/relationship.js.map +1 -0
  55. package/dist/graph/relationship_data.d.ts +12 -0
  56. package/dist/graph/relationship_data.d.ts.map +1 -0
  57. package/dist/graph/relationship_data.js +40 -0
  58. package/dist/graph/relationship_data.js.map +1 -0
  59. package/dist/graph/relationship_match_collector.d.ts +19 -0
  60. package/dist/graph/relationship_match_collector.d.ts.map +1 -0
  61. package/dist/graph/relationship_match_collector.js +55 -0
  62. package/dist/graph/relationship_match_collector.js.map +1 -0
  63. package/dist/graph/relationship_reference.d.ts +8 -0
  64. package/dist/graph/relationship_reference.d.ts.map +1 -0
  65. package/dist/graph/relationship_reference.js +37 -0
  66. package/dist/graph/relationship_reference.js.map +1 -0
  67. package/dist/parsing/base_parser.d.ts +1 -0
  68. package/dist/parsing/base_parser.d.ts.map +1 -1
  69. package/dist/parsing/base_parser.js +4 -1
  70. package/dist/parsing/base_parser.js.map +1 -1
  71. package/dist/parsing/context.d.ts +2 -2
  72. package/dist/parsing/context.js +5 -5
  73. package/dist/parsing/expressions/boolean.d.ts +8 -0
  74. package/dist/parsing/expressions/boolean.d.ts.map +1 -0
  75. package/dist/parsing/expressions/boolean.js +26 -0
  76. package/dist/parsing/expressions/boolean.js.map +1 -0
  77. package/dist/parsing/expressions/expression.d.ts +4 -1
  78. package/dist/parsing/expressions/expression.d.ts.map +1 -1
  79. package/dist/parsing/expressions/expression.js +15 -8
  80. package/dist/parsing/expressions/expression.js.map +1 -1
  81. package/dist/parsing/expressions/operator.d.ts +1 -1
  82. package/dist/parsing/expressions/operator.d.ts.map +1 -1
  83. package/dist/parsing/expressions/operator.js.map +1 -1
  84. package/dist/parsing/functions/function_factory.d.ts +13 -13
  85. package/dist/parsing/functions/function_factory.d.ts.map +1 -1
  86. package/dist/parsing/functions/function_factory.js +20 -18
  87. package/dist/parsing/functions/function_factory.js.map +1 -1
  88. package/dist/parsing/operations/create_node.d.ts +14 -0
  89. package/dist/parsing/operations/create_node.d.ts.map +1 -0
  90. package/dist/parsing/operations/create_node.js +51 -0
  91. package/dist/parsing/operations/create_node.js.map +1 -0
  92. package/dist/parsing/operations/create_relationship.d.ts +14 -0
  93. package/dist/parsing/operations/create_relationship.d.ts.map +1 -0
  94. package/dist/parsing/operations/create_relationship.js +51 -0
  95. package/dist/parsing/operations/create_relationship.js.map +1 -0
  96. package/dist/parsing/operations/match.d.ts +15 -0
  97. package/dist/parsing/operations/match.d.ts.map +1 -0
  98. package/dist/parsing/operations/match.js +45 -0
  99. package/dist/parsing/operations/match.js.map +1 -0
  100. package/dist/parsing/operations/operation.d.ts +1 -0
  101. package/dist/parsing/operations/operation.d.ts.map +1 -1
  102. package/dist/parsing/operations/operation.js +6 -0
  103. package/dist/parsing/operations/operation.js.map +1 -1
  104. package/dist/parsing/operations/return.d.ts +1 -0
  105. package/dist/parsing/operations/return.d.ts.map +1 -1
  106. package/dist/parsing/operations/return.js +7 -1
  107. package/dist/parsing/operations/return.js.map +1 -1
  108. package/dist/parsing/operations/where.d.ts +1 -1
  109. package/dist/parsing/operations/where.d.ts.map +1 -1
  110. package/dist/parsing/operations/where.js +4 -0
  111. package/dist/parsing/operations/where.js.map +1 -1
  112. package/dist/parsing/parser.d.ts +10 -0
  113. package/dist/parsing/parser.d.ts.map +1 -1
  114. package/dist/parsing/parser.js +344 -5
  115. package/dist/parsing/parser.js.map +1 -1
  116. package/dist/parsing/token_to_node.d.ts.map +1 -1
  117. package/dist/parsing/token_to_node.js +7 -0
  118. package/dist/parsing/token_to_node.js.map +1 -1
  119. package/dist/tokenization/keyword.d.ts +1 -0
  120. package/dist/tokenization/keyword.d.ts.map +1 -1
  121. package/dist/tokenization/keyword.js +1 -0
  122. package/dist/tokenization/keyword.js.map +1 -1
  123. package/dist/tokenization/token.d.ts +4 -0
  124. package/dist/tokenization/token.d.ts.map +1 -1
  125. package/dist/tokenization/token.js +14 -1
  126. package/dist/tokenization/token.js.map +1 -1
  127. package/dist/tokenization/token_type.d.ts +1 -0
  128. package/dist/tokenization/token_type.d.ts.map +1 -1
  129. package/dist/tokenization/token_type.js +1 -0
  130. package/dist/tokenization/token_type.js.map +1 -1
  131. package/dist/tokenization/tokenizer.d.ts +2 -1
  132. package/dist/tokenization/tokenizer.d.ts.map +1 -1
  133. package/dist/tokenization/tokenizer.js +25 -12
  134. package/dist/tokenization/tokenizer.js.map +1 -1
  135. package/docs/flowquery.min.js +1 -1
  136. package/flowquery-py/README.md +166 -0
  137. package/flowquery-py/pyproject.toml +75 -0
  138. package/flowquery-py/setup_env.ps1 +92 -0
  139. package/flowquery-py/setup_env.sh +87 -0
  140. package/flowquery-py/src/__init__.py +34 -0
  141. package/flowquery-py/src/__main__.py +10 -0
  142. package/flowquery-py/src/compute/__init__.py +5 -0
  143. package/flowquery-py/src/compute/runner.py +60 -0
  144. package/flowquery-py/src/extensibility.py +52 -0
  145. package/flowquery-py/src/graph/__init__.py +31 -0
  146. package/flowquery-py/src/graph/data.py +118 -0
  147. package/flowquery-py/src/graph/database.py +82 -0
  148. package/flowquery-py/src/graph/hops.py +43 -0
  149. package/flowquery-py/src/graph/node.py +112 -0
  150. package/flowquery-py/src/graph/node_data.py +26 -0
  151. package/flowquery-py/src/graph/node_reference.py +49 -0
  152. package/flowquery-py/src/graph/pattern.py +125 -0
  153. package/flowquery-py/src/graph/pattern_expression.py +62 -0
  154. package/flowquery-py/src/graph/patterns.py +42 -0
  155. package/flowquery-py/src/graph/physical_node.py +40 -0
  156. package/flowquery-py/src/graph/physical_relationship.py +36 -0
  157. package/flowquery-py/src/graph/relationship.py +135 -0
  158. package/flowquery-py/src/graph/relationship_data.py +33 -0
  159. package/flowquery-py/src/graph/relationship_match_collector.py +77 -0
  160. package/flowquery-py/src/graph/relationship_reference.py +21 -0
  161. package/flowquery-py/src/io/__init__.py +5 -0
  162. package/flowquery-py/src/io/command_line.py +67 -0
  163. package/flowquery-py/src/parsing/__init__.py +17 -0
  164. package/flowquery-py/src/parsing/alias.py +20 -0
  165. package/flowquery-py/src/parsing/alias_option.py +11 -0
  166. package/flowquery-py/src/parsing/ast_node.py +146 -0
  167. package/flowquery-py/src/parsing/base_parser.py +84 -0
  168. package/flowquery-py/src/parsing/components/__init__.py +19 -0
  169. package/flowquery-py/src/parsing/components/csv.py +8 -0
  170. package/flowquery-py/src/parsing/components/from_.py +10 -0
  171. package/flowquery-py/src/parsing/components/headers.py +12 -0
  172. package/flowquery-py/src/parsing/components/json.py +8 -0
  173. package/flowquery-py/src/parsing/components/null.py +10 -0
  174. package/flowquery-py/src/parsing/components/post.py +8 -0
  175. package/flowquery-py/src/parsing/components/text.py +8 -0
  176. package/flowquery-py/src/parsing/context.py +50 -0
  177. package/flowquery-py/src/parsing/data_structures/__init__.py +15 -0
  178. package/flowquery-py/src/parsing/data_structures/associative_array.py +41 -0
  179. package/flowquery-py/src/parsing/data_structures/json_array.py +30 -0
  180. package/flowquery-py/src/parsing/data_structures/key_value_pair.py +38 -0
  181. package/flowquery-py/src/parsing/data_structures/lookup.py +49 -0
  182. package/flowquery-py/src/parsing/data_structures/range_lookup.py +42 -0
  183. package/flowquery-py/src/parsing/expressions/__init__.py +57 -0
  184. package/flowquery-py/src/parsing/expressions/boolean.py +20 -0
  185. package/flowquery-py/src/parsing/expressions/expression.py +138 -0
  186. package/flowquery-py/src/parsing/expressions/expression_map.py +26 -0
  187. package/flowquery-py/src/parsing/expressions/f_string.py +27 -0
  188. package/flowquery-py/src/parsing/expressions/identifier.py +20 -0
  189. package/flowquery-py/src/parsing/expressions/number.py +32 -0
  190. package/flowquery-py/src/parsing/expressions/operator.py +169 -0
  191. package/flowquery-py/src/parsing/expressions/reference.py +47 -0
  192. package/flowquery-py/src/parsing/expressions/string.py +27 -0
  193. package/flowquery-py/src/parsing/functions/__init__.py +75 -0
  194. package/flowquery-py/src/parsing/functions/aggregate_function.py +60 -0
  195. package/flowquery-py/src/parsing/functions/async_function.py +62 -0
  196. package/flowquery-py/src/parsing/functions/avg.py +55 -0
  197. package/flowquery-py/src/parsing/functions/collect.py +75 -0
  198. package/flowquery-py/src/parsing/functions/function.py +68 -0
  199. package/flowquery-py/src/parsing/functions/function_factory.py +173 -0
  200. package/flowquery-py/src/parsing/functions/function_metadata.py +149 -0
  201. package/flowquery-py/src/parsing/functions/functions.py +59 -0
  202. package/flowquery-py/src/parsing/functions/join.py +47 -0
  203. package/flowquery-py/src/parsing/functions/keys.py +34 -0
  204. package/flowquery-py/src/parsing/functions/predicate_function.py +46 -0
  205. package/flowquery-py/src/parsing/functions/predicate_sum.py +47 -0
  206. package/flowquery-py/src/parsing/functions/rand.py +28 -0
  207. package/flowquery-py/src/parsing/functions/range_.py +34 -0
  208. package/flowquery-py/src/parsing/functions/reducer_element.py +15 -0
  209. package/flowquery-py/src/parsing/functions/replace.py +37 -0
  210. package/flowquery-py/src/parsing/functions/round_.py +32 -0
  211. package/flowquery-py/src/parsing/functions/size.py +32 -0
  212. package/flowquery-py/src/parsing/functions/split.py +47 -0
  213. package/flowquery-py/src/parsing/functions/stringify.py +47 -0
  214. package/flowquery-py/src/parsing/functions/sum.py +51 -0
  215. package/flowquery-py/src/parsing/functions/to_json.py +33 -0
  216. package/flowquery-py/src/parsing/functions/type_.py +47 -0
  217. package/flowquery-py/src/parsing/functions/value_holder.py +24 -0
  218. package/flowquery-py/src/parsing/logic/__init__.py +15 -0
  219. package/flowquery-py/src/parsing/logic/case.py +29 -0
  220. package/flowquery-py/src/parsing/logic/else_.py +12 -0
  221. package/flowquery-py/src/parsing/logic/end.py +8 -0
  222. package/flowquery-py/src/parsing/logic/then.py +12 -0
  223. package/flowquery-py/src/parsing/logic/when.py +10 -0
  224. package/flowquery-py/src/parsing/operations/__init__.py +35 -0
  225. package/flowquery-py/src/parsing/operations/aggregated_return.py +24 -0
  226. package/flowquery-py/src/parsing/operations/aggregated_with.py +22 -0
  227. package/flowquery-py/src/parsing/operations/call.py +74 -0
  228. package/flowquery-py/src/parsing/operations/create_node.py +34 -0
  229. package/flowquery-py/src/parsing/operations/create_relationship.py +34 -0
  230. package/flowquery-py/src/parsing/operations/group_by.py +130 -0
  231. package/flowquery-py/src/parsing/operations/limit.py +22 -0
  232. package/flowquery-py/src/parsing/operations/load.py +140 -0
  233. package/flowquery-py/src/parsing/operations/match.py +29 -0
  234. package/flowquery-py/src/parsing/operations/operation.py +69 -0
  235. package/flowquery-py/src/parsing/operations/projection.py +21 -0
  236. package/flowquery-py/src/parsing/operations/return_op.py +50 -0
  237. package/flowquery-py/src/parsing/operations/unwind.py +37 -0
  238. package/flowquery-py/src/parsing/operations/where.py +41 -0
  239. package/flowquery-py/src/parsing/operations/with_op.py +18 -0
  240. package/flowquery-py/src/parsing/parser.py +1011 -0
  241. package/flowquery-py/src/parsing/token_to_node.py +109 -0
  242. package/flowquery-py/src/tokenization/__init__.py +23 -0
  243. package/flowquery-py/src/tokenization/keyword.py +48 -0
  244. package/flowquery-py/src/tokenization/operator.py +29 -0
  245. package/flowquery-py/src/tokenization/string_walker.py +158 -0
  246. package/flowquery-py/src/tokenization/symbol.py +19 -0
  247. package/flowquery-py/src/tokenization/token.py +659 -0
  248. package/flowquery-py/src/tokenization/token_mapper.py +52 -0
  249. package/flowquery-py/src/tokenization/token_type.py +21 -0
  250. package/flowquery-py/src/tokenization/tokenizer.py +214 -0
  251. package/flowquery-py/src/tokenization/trie.py +124 -0
  252. package/flowquery-py/src/utils/__init__.py +6 -0
  253. package/flowquery-py/src/utils/object_utils.py +20 -0
  254. package/flowquery-py/src/utils/string_utils.py +113 -0
  255. package/flowquery-py/tests/__init__.py +1 -0
  256. package/flowquery-py/tests/compute/__init__.py +1 -0
  257. package/flowquery-py/tests/compute/test_runner.py +1335 -0
  258. package/flowquery-py/tests/graph/__init__.py +1 -0
  259. package/flowquery-py/tests/graph/test_create.py +56 -0
  260. package/flowquery-py/tests/graph/test_data.py +73 -0
  261. package/flowquery-py/tests/graph/test_match.py +40 -0
  262. package/flowquery-py/tests/parsing/__init__.py +1 -0
  263. package/flowquery-py/tests/parsing/test_context.py +34 -0
  264. package/flowquery-py/tests/parsing/test_expression.py +49 -0
  265. package/flowquery-py/tests/parsing/test_parser.py +674 -0
  266. package/flowquery-py/tests/test_extensibility.py +611 -0
  267. package/flowquery-py/tests/tokenization/__init__.py +1 -0
  268. package/flowquery-py/tests/tokenization/test_token_mapper.py +60 -0
  269. package/flowquery-py/tests/tokenization/test_tokenizer.py +164 -0
  270. package/flowquery-py/tests/tokenization/test_trie.py +30 -0
  271. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  272. package/misc/apps/RAG/package.json +1 -1
  273. package/misc/apps/RAG/src/components/AdaptiveCardRenderer.tsx +76 -8
  274. package/misc/apps/RAG/src/components/index.ts +19 -10
  275. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +70 -140
  276. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +12 -0
  277. package/package.json +1 -1
  278. package/src/compute/runner.ts +24 -19
  279. package/src/graph/data.ts +112 -0
  280. package/src/graph/database.ts +63 -0
  281. package/src/graph/hops.ts +22 -0
  282. package/src/graph/node.ts +99 -0
  283. package/src/graph/node_data.ts +18 -0
  284. package/src/graph/node_reference.ts +33 -0
  285. package/src/graph/pattern.ts +101 -0
  286. package/src/graph/pattern_expression.ts +37 -0
  287. package/src/graph/patterns.ts +36 -0
  288. package/src/graph/physical_node.ts +23 -0
  289. package/src/graph/physical_relationship.ts +23 -0
  290. package/src/graph/relationship.ts +116 -0
  291. package/src/graph/relationship_data.ts +27 -0
  292. package/src/graph/relationship_match_collector.ts +58 -0
  293. package/src/graph/relationship_reference.ts +24 -0
  294. package/src/parsing/base_parser.ts +20 -14
  295. package/src/parsing/context.ts +14 -14
  296. package/src/parsing/expressions/boolean.ts +21 -0
  297. package/src/parsing/expressions/expression.ts +34 -26
  298. package/src/parsing/expressions/operator.ts +19 -1
  299. package/src/parsing/functions/function_factory.ts +45 -45
  300. package/src/parsing/operations/create_node.ts +39 -0
  301. package/src/parsing/operations/create_relationship.ts +38 -0
  302. package/src/parsing/operations/match.ts +31 -0
  303. package/src/parsing/operations/operation.ts +3 -0
  304. package/src/parsing/operations/return.ts +11 -7
  305. package/src/parsing/operations/where.ts +10 -6
  306. package/src/parsing/parser.ts +346 -8
  307. package/src/parsing/token_to_node.ts +6 -0
  308. package/src/tokenization/keyword.ts +41 -40
  309. package/src/tokenization/token.ts +21 -1
  310. package/src/tokenization/token_type.ts +2 -1
  311. package/src/tokenization/tokenizer.ts +52 -31
  312. package/tests/compute/runner.test.ts +654 -0
  313. package/tests/extensibility.test.ts +97 -93
  314. package/tests/graph/create.test.ts +36 -0
  315. package/tests/graph/data.test.ts +58 -0
  316. package/tests/graph/match.test.ts +29 -0
  317. package/tests/parsing/parser.test.ts +273 -2
  318. package/tests/tokenization/tokenizer.test.ts +90 -0
@@ -235,10 +235,16 @@ export class AdaptiveCardRenderer extends React.Component<AdaptiveCardRendererPr
235
235
  this.containerRef.current.innerHTML = '';
236
236
 
237
237
  try {
238
+ // Normalize the card to standard Adaptive Card format
239
+ let cardPayload = normalizeAdaptiveCard(card);
240
+
241
+ if (!cardPayload) {
242
+ throw new Error('Invalid Adaptive Card format');
243
+ }
244
+
238
245
  // Apply data binding if data is provided
239
- let cardPayload = card;
240
246
  if (data) {
241
- const template = new ACData.Template(card);
247
+ const template = new ACData.Template(cardPayload);
242
248
  cardPayload = template.expand({
243
249
  $root: data
244
250
  });
@@ -299,14 +305,76 @@ export class AdaptiveCardRenderer extends React.Component<AdaptiveCardRendererPr
299
305
  }
300
306
 
301
307
  /**
302
- * Helper function to check if an object looks like an Adaptive Card
308
+ * Helper function to check if an object looks like an Adaptive Card.
309
+ * Supports both standard format (type: 'AdaptiveCard') and alternative format (cardType: 'AdaptiveCard').
303
310
  */
304
311
  export function isAdaptiveCard(obj: unknown): obj is Record<string, unknown> {
305
- return (
306
- typeof obj === 'object' &&
307
- obj !== null &&
308
- (obj as Record<string, unknown>).type === 'AdaptiveCard'
309
- );
312
+ if (typeof obj !== 'object' || obj === null) {
313
+ return false;
314
+ }
315
+
316
+ const card = obj as Record<string, unknown>;
317
+
318
+ // Standard Adaptive Card format
319
+ if (card.type === 'AdaptiveCard') {
320
+ return true;
321
+ }
322
+
323
+ // Alternative format with cardType/cardBody
324
+ if (card.cardType === 'AdaptiveCard') {
325
+ return true;
326
+ }
327
+
328
+ // Check if it's an array containing Adaptive Cards
329
+ if (Array.isArray(obj) && obj.length > 0) {
330
+ return obj.some(item => isAdaptiveCard(item));
331
+ }
332
+
333
+ return false;
334
+ }
335
+
336
+ /**
337
+ * Normalizes a card payload to the standard Adaptive Card format.
338
+ * Handles:
339
+ * - Arrays of cards (returns the first card)
340
+ * - Alternative format with cardType/cardBody properties
341
+ * - Standard format (passed through unchanged)
342
+ */
343
+ export function normalizeAdaptiveCard(obj: unknown): Record<string, unknown> | null {
344
+ if (typeof obj !== 'object' || obj === null) {
345
+ return null;
346
+ }
347
+
348
+ // Handle arrays - extract the first valid card
349
+ if (Array.isArray(obj)) {
350
+ for (const item of obj) {
351
+ const normalized = normalizeAdaptiveCard(item);
352
+ if (normalized) {
353
+ return normalized;
354
+ }
355
+ }
356
+ return null;
357
+ }
358
+
359
+ const card = obj as Record<string, unknown>;
360
+
361
+ // Standard format - return as-is
362
+ if (card.type === 'AdaptiveCard') {
363
+ return card;
364
+ }
365
+
366
+ // Alternative format - convert to standard format
367
+ if (card.cardType === 'AdaptiveCard') {
368
+ return {
369
+ type: 'AdaptiveCard',
370
+ $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
371
+ version: (card.version as string) || '1.5',
372
+ body: card.cardBody || card.body || [],
373
+ actions: card.actions || []
374
+ };
375
+ }
376
+
377
+ return null;
310
378
  }
311
379
 
312
380
  export default AdaptiveCardRenderer;
@@ -1,19 +1,28 @@
1
1
  // Chat components exports
2
- export { ChatContainer } from './ChatContainer';
3
- export { ChatMessage } from './ChatMessage';
4
- export { ChatInput } from './ChatInput';
5
- export { ApiKeySettings } from './ApiKeySettings';
2
+ export { ChatContainer } from "./ChatContainer";
3
+ export { ChatMessage } from "./ChatMessage";
4
+ export { ChatInput } from "./ChatInput";
5
+ export { ApiKeySettings } from "./ApiKeySettings";
6
6
 
7
7
  // FlowQuery Runner
8
- export { FlowQueryRunner } from './FlowQueryRunner';
8
+ export { FlowQueryRunner } from "./FlowQueryRunner";
9
9
 
10
10
  // Adaptive Card Renderer
11
- export { AdaptiveCardRenderer, isAdaptiveCard } from './AdaptiveCardRenderer';
11
+ export {
12
+ AdaptiveCardRenderer,
13
+ isAdaptiveCard,
14
+ normalizeAdaptiveCard,
15
+ } from "./AdaptiveCardRenderer";
12
16
 
13
17
  // FlowQuery Agent
14
- export { processQuery, processQueryStream } from './FlowQueryAgent';
15
- export type { AgentStep, AgentResult, FlowQueryAgentOptions, AgentStreamCallback } from './FlowQueryAgent';
18
+ export { processQuery, processQueryStream } from "./FlowQueryAgent";
19
+ export type {
20
+ AgentStep,
21
+ AgentResult,
22
+ FlowQueryAgentOptions,
23
+ AgentStreamCallback,
24
+ } from "./FlowQueryAgent";
16
25
 
17
26
  // Types
18
- export type { Message } from './ChatMessage';
19
- export type { AdaptiveCardRendererProps } from './AdaptiveCardRenderer';
27
+ export type { Message } from "./ChatMessage";
28
+ export type { AdaptiveCardRendererProps } from "./AdaptiveCardRenderer";
@@ -1,171 +1,101 @@
1
- /**
2
- * Example plugin: Generate mock data for testing.
3
- *
4
- * Usage in FlowQuery:
5
- * CALL mockUsers(10) YIELD name, email
6
- */
7
1
  import { AsyncFunction, FunctionDef } from "flowquery/extensibility";
8
2
 
9
- /**
10
- * MockUsers class - generates mock user data for testing.
11
- */
3
+ const usersData = [
4
+ { id: 1, name: "Alice Johnson", email: "alice@example.com", age: 28 },
5
+ { id: 2, name: "Bob Smith", email: "bob@example.com", age: 34 },
6
+ { id: 3, name: "Charlie Brown", email: "charlie@example.com", age: 22 },
7
+ { id: 4, name: "Diana Ross", email: "diana@example.com", age: 45 },
8
+ { id: 5, name: "Eve Wilson", email: "eve@example.com", age: 31 },
9
+ ];
10
+
11
+ const productsData = [
12
+ { id: 101, name: "Laptop", price: 999.99, category: "Electronics", stock: 50 },
13
+ { id: 102, name: "Headphones", price: 149.99, category: "Electronics", stock: 200 },
14
+ { id: 103, name: "Coffee Mug", price: 12.99, category: "Kitchen", stock: 500 },
15
+ { id: 104, name: "Notebook", price: 8.99, category: "Office", stock: 300 },
16
+ { id: 105, name: "Backpack", price: 59.99, category: "Accessories", stock: 75 },
17
+ ];
18
+
19
+ const ordersData = [
20
+ { id: 1001, userId: 1, productId: 101, quantity: 1, total: 999.99, date: "2025-12-01" },
21
+ { id: 1002, userId: 2, productId: 102, quantity: 2, total: 299.98, date: "2025-12-05" },
22
+ { id: 1003, userId: 1, productId: 103, quantity: 4, total: 51.96, date: "2025-12-10" },
23
+ { id: 1004, userId: 3, productId: 104, quantity: 10, total: 89.9, date: "2025-12-15" },
24
+ { id: 1005, userId: 4, productId: 105, quantity: 1, total: 59.99, date: "2025-12-20" },
25
+ { id: 1006, userId: 5, productId: 101, quantity: 1, total: 999.99, date: "2025-12-25" },
26
+ ];
27
+
12
28
  @FunctionDef({
13
- description: "Generates mock user data for testing purposes",
29
+ description: "Returns mock user data",
14
30
  category: "async",
15
- parameters: [
16
- {
17
- name: "count",
18
- description: "Number of mock users to generate",
19
- type: "number",
20
- required: false,
21
- default: 5,
22
- },
23
- ],
31
+ parameters: [],
24
32
  output: {
25
- description: "Mock user object",
33
+ description: "User object",
26
34
  type: "object",
27
35
  properties: {
28
36
  id: { description: "User ID", type: "number" },
29
- name: { description: "Full name", type: "string" },
30
- email: { description: "Email address", type: "string" },
31
- age: { description: "Age in years", type: "number" },
32
- active: { description: "Whether user is active", type: "boolean" },
37
+ name: { description: "User name", type: "string" },
38
+ email: { description: "User email", type: "string" },
39
+ age: { description: "User age", type: "number" },
33
40
  },
34
41
  },
35
- examples: [
36
- "CALL mockUsers(10) YIELD name, email",
37
- "CALL mockUsers(20) YIELD name, email, active WHERE active = true",
38
- ],
42
+ examples: ["CALL users() YIELD id, name, email, age"],
39
43
  })
40
- export class MockUsers extends AsyncFunction {
41
- private readonly firstNames: string[];
42
- private readonly lastNames: string[];
43
- private readonly domains: string[];
44
-
45
- constructor(
46
- firstNames: string[] = [
47
- "Alice",
48
- "Bob",
49
- "Charlie",
50
- "Diana",
51
- "Eve",
52
- "Frank",
53
- "Grace",
54
- "Henry",
55
- "Ivy",
56
- "Jack",
57
- ],
58
- lastNames: string[] = [
59
- "Smith",
60
- "Johnson",
61
- "Williams",
62
- "Brown",
63
- "Jones",
64
- "Garcia",
65
- "Miller",
66
- "Davis",
67
- "Rodriguez",
68
- "Martinez",
69
- ],
70
- domains: string[] = ["example.com", "test.org", "demo.net"]
71
- ) {
72
- super();
73
- this.firstNames = firstNames;
74
- this.lastNames = lastNames;
75
- this.domains = domains;
76
- }
77
-
78
- /**
79
- * Generates mock user data.
80
- *
81
- * @param count - Number of mock users to generate
82
- */
83
- async *generate(count: number = 5): AsyncGenerator<any, void, unknown> {
84
- for (let i = 0; i < count; i++) {
85
- const firstName = this.firstNames[Math.floor(Math.random() * this.firstNames.length)];
86
- const lastName = this.lastNames[Math.floor(Math.random() * this.lastNames.length)];
87
- const domain = this.domains[Math.floor(Math.random() * this.domains.length)];
88
-
89
- yield {
90
- id: i + 1,
91
- name: `${firstName} ${lastName}`,
92
- email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@${domain}`,
93
- age: Math.floor(Math.random() * 50) + 18,
94
- active: Math.random() > 0.3,
95
- };
44
+ export class Users extends AsyncFunction {
45
+ async *generate(): AsyncGenerator<any, void, unknown> {
46
+ for (const user of usersData) {
47
+ yield user;
96
48
  }
97
49
  }
98
50
  }
99
51
 
100
- /**
101
- * MockProducts class - generates mock product data for testing.
102
- */
103
52
  @FunctionDef({
104
- description: "Generates mock product data for testing purposes",
53
+ description: "Returns mock product data",
105
54
  category: "async",
106
- parameters: [
107
- {
108
- name: "count",
109
- description: "Number of mock products to generate",
110
- type: "number",
111
- required: false,
112
- default: 5,
113
- },
114
- ],
55
+ parameters: [],
115
56
  output: {
116
- description: "Mock product object",
57
+ description: "Product object",
117
58
  type: "object",
118
59
  properties: {
119
60
  id: { description: "Product ID", type: "number" },
120
61
  name: { description: "Product name", type: "string" },
62
+ price: { description: "Product price", type: "number" },
121
63
  category: { description: "Product category", type: "string" },
122
- price: { description: "Price in dollars", type: "number" },
123
- inStock: { description: "Whether product is in stock", type: "boolean" },
124
- rating: { description: "Customer rating (0-5)", type: "number" },
64
+ stock: { description: "Stock quantity", type: "number" },
125
65
  },
126
66
  },
127
- examples: [
128
- "CALL mockProducts(10) YIELD name, price",
129
- "CALL mockProducts(50) YIELD name, price, category WHERE category = 'Electronics'",
130
- ],
67
+ examples: ["CALL products() YIELD id, name, price, category, stock"],
131
68
  })
132
- export class MockProducts extends AsyncFunction {
133
- private readonly categories: string[];
134
- private readonly adjectives: string[];
135
- private readonly nouns: string[];
136
-
137
- constructor(
138
- categories: string[] = ["Electronics", "Clothing", "Books", "Home", "Sports"],
139
- adjectives: string[] = ["Premium", "Basic", "Pro", "Ultra", "Classic"],
140
- nouns: string[] = ["Widget", "Gadget", "Item", "Product", "Thing"]
141
- ) {
142
- super();
143
- this.categories = categories;
144
- this.adjectives = adjectives;
145
- this.nouns = nouns;
69
+ export class Products extends AsyncFunction {
70
+ async *generate(): AsyncGenerator<any, void, unknown> {
71
+ for (const product of productsData) {
72
+ yield product;
73
+ }
146
74
  }
75
+ }
147
76
 
148
- /**
149
- * Generates mock product data.
150
- *
151
- * @param count - Number of mock products to generate
152
- */
153
- async *generate(count: number = 5): AsyncGenerator<any, void, unknown> {
154
- for (let i = 0; i < count; i++) {
155
- const adj = this.adjectives[Math.floor(Math.random() * this.adjectives.length)];
156
- const noun = this.nouns[Math.floor(Math.random() * this.nouns.length)];
157
- const category = this.categories[Math.floor(Math.random() * this.categories.length)];
158
-
159
- yield {
160
- id: i + 1,
161
- name: `${adj} ${noun} ${i + 1}`,
162
- category,
163
- price: Math.round(Math.random() * 1000 * 100) / 100,
164
- inStock: Math.random() > 0.2,
165
- rating: Math.round(Math.random() * 50) / 10,
166
- };
77
+ @FunctionDef({
78
+ description: "Returns mock order data",
79
+ category: "async",
80
+ parameters: [],
81
+ output: {
82
+ description: "Order object",
83
+ type: "object",
84
+ properties: {
85
+ id: { description: "Order ID", type: "number" },
86
+ userId: { description: "User ID who placed the order", type: "number" },
87
+ productId: { description: "Product ID ordered", type: "number" },
88
+ quantity: { description: "Quantity ordered", type: "number" },
89
+ total: { description: "Order total", type: "number" },
90
+ date: { description: "Order date", type: "string" },
91
+ },
92
+ },
93
+ examples: ["CALL orders() YIELD id, userId, productId, quantity, total, date"],
94
+ })
95
+ export class Orders extends AsyncFunction {
96
+ async *generate(): AsyncGenerator<any, void, unknown> {
97
+ for (const order of ordersData) {
98
+ yield order;
167
99
  }
168
100
  }
169
101
  }
170
-
171
- export { MockUsers as default };
@@ -69,6 +69,18 @@ FlowQuery is a declarative query language for data processing pipelines. It uses
69
69
  UNWIND myArray AS item
70
70
  UNWIND range(0, 10) AS index
71
71
  \`\`\`
72
+
73
+ **IMPORTANT**: An UNWIND statement cannot be followed directly by a WHERE statement. If you need to filter after unwinding, use a WITH clause in between:
74
+ \`\`\`
75
+ // WRONG - UNWIND cannot be directly followed by WHERE:
76
+ // UNWIND items AS item
77
+ // WHERE item.active = true
78
+
79
+ // CORRECT - use WITH between UNWIND and WHERE:
80
+ UNWIND items AS item
81
+ WITH item
82
+ WHERE item.active = true
83
+ \`\`\`
72
84
 
73
85
  6. **WHERE** - Filter results
74
86
  \`\`\`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowquery",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "A declarative query language for data processing pipelines.",
5
5
  "main": "dist/index.node.js",
6
6
  "types": "dist/index.node.d.ts",
@@ -1,14 +1,15 @@
1
+ import ASTNode from "../parsing/ast_node";
2
+ import Function from "../parsing/functions/function";
3
+ import { FunctionMetadata } from "../parsing/functions/function_metadata";
1
4
  import Operation from "../parsing/operations/operation";
2
5
  import Parser from "../parsing/parser";
3
- import { FunctionMetadata } from "../parsing/functions/function_metadata";
4
- import Function from "../parsing/functions/function";
5
6
 
6
7
  /**
7
8
  * Executes a FlowQuery statement and retrieves the results.
8
- *
9
+ *
9
10
  * The Runner class parses a FlowQuery statement into an AST and executes it,
10
11
  * managing the execution flow from the first operation to the final return statement.
11
- *
12
+ *
12
13
  * @example
13
14
  * ```typescript
14
15
  * const runner = new Runner("WITH 1 as x RETURN x");
@@ -24,7 +25,11 @@ class Runner {
24
25
  * List all registered functions with their metadata.
25
26
  * Added dynamically in index.browser.ts / index.node.ts
26
27
  */
27
- static listFunctions: (options?: { category?: string; asyncOnly?: boolean; syncOnly?: boolean }) => FunctionMetadata[];
28
+ static listFunctions: (options?: {
29
+ category?: string;
30
+ asyncOnly?: boolean;
31
+ syncOnly?: boolean;
32
+ }) => FunctionMetadata[];
28
33
 
29
34
  /**
30
35
  * Get metadata for a specific function.
@@ -37,32 +42,32 @@ class Runner {
37
42
  * Added dynamically in index.browser.ts / index.node.ts
38
43
  */
39
44
  static Function: typeof Function;
40
-
45
+
41
46
  /**
42
47
  * Creates a new Runner instance and parses the FlowQuery statement.
43
- *
48
+ *
44
49
  * @param statement - The FlowQuery statement to execute
45
50
  * @throws {Error} If the statement is null, empty, or contains syntax errors
46
51
  */
47
- constructor(statement: string | null = null) {
48
- if(statement === null || statement === "") {
49
- throw new Error("Statement cannot be null or empty");
52
+ constructor(statement: string | null = null, ast: ASTNode | null = null) {
53
+ if ((statement === null || statement === "") && ast === null) {
54
+ throw new Error("Either statement or AST must be provided");
50
55
  }
51
- const parser = new Parser();
52
- const ast = parser.parse(statement);
53
- this.first = ast.firstChild() as Operation;
54
- this.last = ast.lastChild() as Operation;
56
+ const _ast = ast !== null ? ast : new Parser().parse(statement!);
57
+ this.first = _ast.firstChild() as Operation;
58
+ this.last = _ast.lastChild() as Operation;
55
59
  }
56
-
60
+
57
61
  /**
58
62
  * Executes the parsed FlowQuery statement.
59
- *
63
+ *
60
64
  * @returns A promise that resolves when execution completes
61
65
  * @throws {Error} If an error occurs during execution
62
66
  */
63
67
  public async run(): Promise<void> {
64
68
  return new Promise<void>(async (resolve, reject) => {
65
69
  try {
70
+ await this.first.initialize();
66
71
  await this.first.run();
67
72
  await this.first.finish();
68
73
  resolve();
@@ -71,10 +76,10 @@ class Runner {
71
76
  }
72
77
  });
73
78
  }
74
-
79
+
75
80
  /**
76
81
  * Gets the results from the executed statement.
77
- *
82
+ *
78
83
  * @returns The results from the last operation (typically a RETURN statement)
79
84
  */
80
85
  public get results(): any {
@@ -82,4 +87,4 @@ class Runner {
82
87
  }
83
88
  }
84
89
 
85
- export default Runner;
90
+ export default Runner;
@@ -0,0 +1,112 @@
1
+ class IndexEntry {
2
+ private _positions: number[];
3
+ private _index: number = -1;
4
+
5
+ constructor(positions: number[] = []) {
6
+ this._positions = positions;
7
+ }
8
+ public add(position: number): void {
9
+ this._positions.push(position);
10
+ }
11
+ public get position(): number {
12
+ return this._positions[this._index];
13
+ }
14
+ public reset(): void {
15
+ this._index = -1;
16
+ }
17
+ public next(): boolean {
18
+ if (this._index < this._positions.length - 1) {
19
+ this._index++;
20
+ return true;
21
+ }
22
+ return false;
23
+ }
24
+ public clone(): IndexEntry {
25
+ return new IndexEntry([...this._positions]);
26
+ }
27
+ }
28
+
29
+ class Layer {
30
+ private _index: Map<string, IndexEntry> = new Map();
31
+ private _current: number = -1;
32
+ constructor(index: Map<string, IndexEntry>) {
33
+ this._index = index;
34
+ }
35
+ public get index(): Map<string, IndexEntry> {
36
+ return this._index;
37
+ }
38
+ public get current(): number {
39
+ return this._current;
40
+ }
41
+ public set current(value: number) {
42
+ this._current = value;
43
+ }
44
+ }
45
+
46
+ class Data {
47
+ protected _records: Record<string, any>[] = [];
48
+ private _layers: Map<number, Layer> = new Map();
49
+
50
+ constructor(records: Record<string, any>[] = []) {
51
+ this._records = records;
52
+ this._layers.set(0, new Layer(new Map()));
53
+ }
54
+ protected _buildIndex(key: string, level: number = 0): void {
55
+ this.layer(level).index.clear();
56
+ this._records.forEach((record, idx) => {
57
+ if (record.hasOwnProperty(key)) {
58
+ if (!this.layer(level).index.has(record[key])) {
59
+ this.layer(level).index.set(record[key], new IndexEntry());
60
+ }
61
+ this.layer(level).index.get(record[key])!.add(idx);
62
+ }
63
+ });
64
+ }
65
+ public layer(level: number = 0): Layer {
66
+ if (!this._layers.has(level)) {
67
+ const first = this._layers.get(0)!;
68
+ const cloned = new Map<string, IndexEntry>();
69
+ for (const [key, entry] of first.index) {
70
+ cloned.set(key, entry.clone());
71
+ }
72
+ this._layers.set(level, new Layer(cloned));
73
+ }
74
+ return this._layers.get(level)!;
75
+ }
76
+ protected _find(key: string, level: number = 0): boolean {
77
+ if (!this.layer(level).index.has(key)) {
78
+ this.layer(level).current = this._records.length; // Move to end
79
+ return false;
80
+ } else {
81
+ const entry = this.layer(level).index.get(key)!;
82
+ const more = entry.next();
83
+ if (!more) {
84
+ this.layer(level).current = this._records.length; // Move to end
85
+ return false;
86
+ }
87
+ this.layer(level).current = entry.position;
88
+ return true;
89
+ }
90
+ }
91
+ public reset(): void {
92
+ this.layer(0).current = -1;
93
+ for (const entry of this.layer(0).index.values()) {
94
+ entry.reset();
95
+ }
96
+ }
97
+ public next(level: number = 0): boolean {
98
+ if (this.layer(level).current < this._records.length - 1) {
99
+ this.layer(level).current++;
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+ public current(level: number = 0): Record<string, any> | null {
105
+ if (this.layer(level).current < this._records.length) {
106
+ return this._records[this.layer(level).current];
107
+ }
108
+ return null;
109
+ }
110
+ }
111
+
112
+ export default Data;