flowquery 1.0.6 → 1.0.8

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 (49) hide show
  1. package/README.md +30 -138
  2. package/dist/compute/runner.d.ts +1 -22
  3. package/dist/compute/runner.d.ts.map +1 -1
  4. package/dist/compute/runner.js.map +1 -1
  5. package/dist/extensibility.d.ts +28 -2
  6. package/dist/extensibility.d.ts.map +1 -1
  7. package/dist/extensibility.js +39 -15
  8. package/dist/extensibility.js.map +1 -1
  9. package/dist/flowquery.min.js +1 -1
  10. package/dist/index.browser.d.ts.map +1 -1
  11. package/dist/index.browser.js +0 -80
  12. package/dist/index.browser.js.map +1 -1
  13. package/dist/index.node.d.ts +3 -3
  14. package/dist/index.node.d.ts.map +1 -1
  15. package/dist/index.node.js +0 -80
  16. package/dist/index.node.js.map +1 -1
  17. package/dist/parsing/functions/function_factory.d.ts +3 -80
  18. package/dist/parsing/functions/function_factory.d.ts.map +1 -1
  19. package/dist/parsing/functions/function_factory.js +8 -127
  20. package/dist/parsing/functions/function_factory.js.map +1 -1
  21. package/dist/parsing/functions/function_metadata.d.ts +28 -35
  22. package/dist/parsing/functions/function_metadata.d.ts.map +1 -1
  23. package/dist/parsing/functions/function_metadata.js +88 -61
  24. package/dist/parsing/functions/function_metadata.js.map +1 -1
  25. package/docs/flowquery.min.js +1 -1
  26. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  27. package/misc/apps/RAG/package.json +1 -1
  28. package/misc/apps/RAG/src/plugins/index.ts +29 -33
  29. package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +28 -32
  30. package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +29 -33
  31. package/misc/apps/RAG/src/plugins/loaders/Llm.ts +55 -59
  32. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +61 -71
  33. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +8 -8
  34. package/package.json +1 -1
  35. package/src/compute/runner.ts +1 -26
  36. package/src/extensibility.ts +38 -2
  37. package/src/index.browser.ts +2 -88
  38. package/src/index.node.ts +3 -92
  39. package/src/parsing/functions/function_factory.ts +13 -154
  40. package/src/parsing/functions/function_metadata.ts +96 -94
  41. package/tests/extensibility.test.ts +601 -0
  42. package/dist/parsing/functions/extensibility/index.d.ts +0 -37
  43. package/dist/parsing/functions/extensibility/index.d.ts.map +0 -1
  44. package/dist/parsing/functions/extensibility/index.js +0 -50
  45. package/dist/parsing/functions/extensibility/index.js.map +0 -1
  46. package/misc/apps/RAG/src/plugins/PluginRegistry.ts +0 -136
  47. package/misc/apps/RAG/src/plugins/types.ts +0 -52
  48. package/src/parsing/functions/extensibility/index.ts +0 -54
  49. package/tests/parsing/function_plugins.test.ts +0 -369
@@ -4,24 +4,78 @@ exports.FunctionDef = FunctionDef;
4
4
  exports.getRegisteredFunctionMetadata = getRegisteredFunctionMetadata;
5
5
  exports.getRegisteredFunctionFactory = getRegisteredFunctionFactory;
6
6
  exports.getFunctionMetadata = getFunctionMetadata;
7
+ exports.getRegisteredAsyncProvider = getRegisteredAsyncProvider;
7
8
  /**
8
- * Registry for function metadata collected via decorators.
9
+ * Centralized registry for function metadata, factories, and async providers.
10
+ * Encapsulates all registration logic for the @FunctionDef decorator.
9
11
  */
10
- const functionMetadataRegistry = new Map();
11
- /**
12
- * Registry for function factories collected via decorators.
13
- * Allows @FunctionDef to automatically register functions for instantiation.
14
- */
15
- const functionFactoryRegistry = new Map();
12
+ class FunctionRegistry {
13
+ /** Derives a camelCase display name from a class name, removing 'Loader' suffix. */
14
+ static deriveDisplayName(className) {
15
+ const baseName = className.endsWith('Loader') ? className.slice(0, -6) : className;
16
+ return baseName.charAt(0).toLowerCase() + baseName.slice(1);
17
+ }
18
+ /** Registers an async data provider class. */
19
+ static registerAsync(constructor, options) {
20
+ const displayName = this.deriveDisplayName(constructor.name);
21
+ const registryKey = displayName.toLowerCase();
22
+ this.metadata.set(registryKey, Object.assign({ name: displayName }, options));
23
+ this.asyncProviders.set(registryKey, (...args) => new constructor().fetch(...args));
24
+ }
25
+ /** Registers a regular function class. */
26
+ static registerFunction(constructor, options) {
27
+ var _a;
28
+ const instance = new constructor();
29
+ const baseName = (((_a = instance.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || constructor.name.toLowerCase());
30
+ const displayName = baseName.includes(':') ? baseName.split(':')[0] : baseName;
31
+ const registryKey = options.category ? `${displayName}:${options.category}` : displayName;
32
+ this.metadata.set(registryKey, Object.assign({ name: displayName }, options));
33
+ if (options.category !== 'predicate') {
34
+ this.factories.set(displayName, () => new constructor());
35
+ }
36
+ this.factories.set(registryKey, () => new constructor());
37
+ }
38
+ static getAllMetadata() {
39
+ return Array.from(this.metadata.values());
40
+ }
41
+ static getMetadata(name, category) {
42
+ const lowerName = name.toLowerCase();
43
+ if (category)
44
+ return this.metadata.get(`${lowerName}:${category}`);
45
+ for (const meta of this.metadata.values()) {
46
+ if (meta.name === lowerName)
47
+ return meta;
48
+ }
49
+ return undefined;
50
+ }
51
+ static getFactory(name, category) {
52
+ const lowerName = name.toLowerCase();
53
+ if (category)
54
+ return this.factories.get(`${lowerName}:${category}`);
55
+ return this.factories.get(lowerName);
56
+ }
57
+ static getAsyncProvider(name) {
58
+ return this.asyncProviders.get(name.toLowerCase());
59
+ }
60
+ }
61
+ FunctionRegistry.metadata = new Map();
62
+ FunctionRegistry.factories = new Map();
63
+ FunctionRegistry.asyncProviders = new Map();
16
64
  /**
17
65
  * Class decorator that registers function metadata.
18
- * The function name is derived from the class's constructor call to super().
66
+ * The function name is derived from the class's constructor call to super() for regular functions,
67
+ * or from the class name for async providers.
68
+ *
69
+ * For async providers (category: "async"), the class must have a `fetch` method that returns
70
+ * an AsyncGenerator. The function name is derived from the class name (removing 'Loader' suffix
71
+ * if present) and converted to camelCase.
19
72
  *
20
73
  * @param options - Function metadata (excluding name)
21
74
  * @returns Class decorator
22
75
  *
23
76
  * @example
24
77
  * ```typescript
78
+ * // Regular function
25
79
  * @FunctionDef({
26
80
  * description: "Calculates the sum of numeric values",
27
81
  * category: "aggregate",
@@ -30,80 +84,53 @@ const functionFactoryRegistry = new Map();
30
84
  * examples: ["WITH [1, 2, 3] AS nums UNWIND nums AS n RETURN sum(n)"]
31
85
  * })
32
86
  * class Sum extends AggregateFunction { ... }
87
+ *
88
+ * // Async data provider
89
+ * @FunctionDef({
90
+ * description: "Fetches random cat facts from the Cat Facts API",
91
+ * category: "async",
92
+ * parameters: [{ name: "count", description: "Number of facts", type: "number", required: false, default: 1 }],
93
+ * output: { description: "Cat fact object", type: "object" },
94
+ * examples: ["LOAD JSON FROM catFacts(5) AS fact RETURN fact.text"]
95
+ * })
96
+ * class CatFactsLoader {
97
+ * async *fetch(count: number = 1): AsyncGenerator<any> { ... }
98
+ * }
33
99
  * ```
34
100
  */
35
101
  function FunctionDef(options) {
36
102
  return function (constructor) {
37
- var _a;
38
- // Create an instance to get the function name from super() call
39
- const instance = new constructor();
40
- const baseName = ((_a = instance.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || constructor.name.toLowerCase();
41
- // Use category-qualified key to avoid collisions (e.g., sum vs sum:predicate)
42
- // but store the display name without the qualifier
43
- const displayName = baseName.includes(':') ? baseName.split(':')[0] : baseName;
44
- const registryKey = options.category ? `${displayName}:${options.category}` : displayName;
45
- // Register metadata with display name but category-qualified key
46
- const metadata = Object.assign({ name: displayName }, options);
47
- functionMetadataRegistry.set(registryKey, metadata);
48
- // Register factory function for automatic instantiation
49
- // Only register to the simple name if no collision exists (predicate functions use qualified keys)
50
- if (options.category !== 'predicate') {
51
- functionFactoryRegistry.set(displayName, () => new constructor());
103
+ if (options.category === 'async') {
104
+ FunctionRegistry.registerAsync(constructor, options);
105
+ }
106
+ else {
107
+ FunctionRegistry.registerFunction(constructor, options);
52
108
  }
53
- functionFactoryRegistry.set(registryKey, () => new constructor());
54
109
  return constructor;
55
110
  };
56
111
  }
57
112
  /**
58
113
  * Gets all registered function metadata from decorators.
59
- *
60
- * @returns Array of function metadata
61
114
  */
62
115
  function getRegisteredFunctionMetadata() {
63
- return Array.from(functionMetadataRegistry.values());
116
+ return FunctionRegistry.getAllMetadata();
64
117
  }
65
118
  /**
66
119
  * Gets a registered function factory by name.
67
- * Used by FunctionFactory to instantiate decorator-registered functions.
68
- *
69
- * @param name - Function name (case-insensitive)
70
- * @param category - Optional category to disambiguate (e.g., 'predicate')
71
- * @returns Factory function or undefined
72
120
  */
73
121
  function getRegisteredFunctionFactory(name, category) {
74
- const lowerName = name.toLowerCase();
75
- // If category specified, look for exact match
76
- if (category) {
77
- return functionFactoryRegistry.get(`${lowerName}:${category}`);
78
- }
79
- // Try direct match first
80
- if (functionFactoryRegistry.has(lowerName)) {
81
- return functionFactoryRegistry.get(lowerName);
82
- }
83
- return undefined;
122
+ return FunctionRegistry.getFactory(name, category);
84
123
  }
85
124
  /**
86
125
  * Gets metadata for a specific function by name.
87
- * If multiple functions share the same name (e.g., aggregate vs predicate),
88
- * optionally specify the category to get the specific one.
89
- *
90
- * @param name - Function name (case-insensitive)
91
- * @param category - Optional category to disambiguate
92
- * @returns Function metadata or undefined
93
126
  */
94
127
  function getFunctionMetadata(name, category) {
95
- const lowerName = name.toLowerCase();
96
- // If category specified, look for exact match
97
- if (category) {
98
- return functionMetadataRegistry.get(`${lowerName}:${category}`);
99
- }
100
- // Otherwise, first try direct match (for functions without category conflicts)
101
- // Then search for any function with matching name
102
- for (const [key, meta] of functionMetadataRegistry) {
103
- if (meta.name === lowerName) {
104
- return meta;
105
- }
106
- }
107
- return undefined;
128
+ return FunctionRegistry.getMetadata(name, category);
129
+ }
130
+ /**
131
+ * Gets a registered async data provider by name.
132
+ */
133
+ function getRegisteredAsyncProvider(name) {
134
+ return FunctionRegistry.getAsyncProvider(name);
108
135
  }
109
136
  //# sourceMappingURL=function_metadata.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"function_metadata.js","sourceRoot":"","sources":["../../../src/parsing/functions/function_metadata.ts"],"names":[],"mappings":";;AA6HA,kCA2BC;AAOD,sEAEC;AAUD,oEAcC;AAWD,kDAiBC;AA3HD;;GAEG;AACH,MAAM,wBAAwB,GAAkC,IAAI,GAAG,EAAE,CAAC;AAE1E;;;GAGG;AACH,MAAM,uBAAuB,GAA2B,IAAI,GAAG,EAAE,CAAC;AAOlE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,WAAW,CAAC,OAA2B;IACnD,OAAO,UAAiD,WAAc;;QAClE,gEAAgE;QAChE,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,CAAA,MAAA,QAAQ,CAAC,IAAI,0CAAE,WAAW,EAAE,KAAI,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAEhF,8EAA8E;QAC9E,mDAAmD;QACnD,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC/E,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,WAAW,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;QAE1F,iEAAiE;QACjE,MAAM,QAAQ,mBACV,IAAI,EAAE,WAAW,IACd,OAAO,CACb,CAAC;QACF,wBAAwB,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAEpD,wDAAwD;QACxD,mGAAmG;QACnG,IAAI,OAAO,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;YACnC,uBAAuB,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,uBAAuB,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC;QAElE,OAAO,WAAW,CAAC;IACvB,CAAC,CAAC;AACN,CAAC;AAED;;;;GAIG;AACH,SAAgB,6BAA6B;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,MAAM,EAAE,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,4BAA4B,CAAC,IAAY,EAAE,QAAiB;IACxE,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAErC,8CAA8C;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,uBAAuB,CAAC,GAAG,CAAC,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,yBAAyB;IACzB,IAAI,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACzC,OAAO,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAClD,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CAAC,IAAY,EAAE,QAAiB;IAC/D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAErC,8CAA8C;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACX,OAAO,wBAAwB,CAAC,GAAG,CAAC,GAAG,SAAS,IAAI,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;IAED,+EAA+E;IAC/E,kDAAkD;IAClD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,wBAAwB,EAAE,CAAC;QACjD,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"function_metadata.js","sourceRoot":"","sources":["../../../src/parsing/functions/function_metadata.ts"],"names":[],"mappings":"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"}