flowquery 1.0.25 → 1.0.26

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/.github/workflows/release.yml +1 -0
  2. package/.husky/pre-commit +3 -2
  3. package/dist/flowquery.min.js +1 -1
  4. package/dist/parsing/parser.d.ts.map +1 -1
  5. package/dist/parsing/parser.js +1 -0
  6. package/dist/parsing/parser.js.map +1 -1
  7. package/docs/flowquery.min.js +1 -1
  8. package/flowquery-py/pyproject.toml +1 -1
  9. package/flowquery-py/src/parsing/parser.py +1 -0
  10. package/flowquery-py/tests/compute/test_runner.py +26 -0
  11. package/flowquery-py/tests/parsing/test_parser.py +18 -0
  12. package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
  13. package/jest.config.js +6 -9
  14. package/misc/apps/RAG/data/chats.json +302 -0
  15. package/misc/apps/RAG/data/emails.json +182 -0
  16. package/misc/apps/RAG/data/events.json +226 -0
  17. package/misc/apps/RAG/data/files.json +172 -0
  18. package/misc/apps/RAG/data/users.json +158 -0
  19. package/misc/apps/RAG/jest.config.js +21 -0
  20. package/misc/apps/RAG/package.json +9 -2
  21. package/misc/apps/RAG/src/App.tsx +5 -5
  22. package/misc/apps/RAG/src/components/ChatContainer.tsx +53 -124
  23. package/misc/apps/RAG/src/components/FlowQueryAgent.ts +151 -157
  24. package/misc/apps/RAG/src/components/index.ts +1 -1
  25. package/misc/apps/RAG/src/graph/index.ts +19 -0
  26. package/misc/apps/RAG/src/graph/initializeGraph.ts +254 -0
  27. package/misc/apps/RAG/src/index.tsx +25 -13
  28. package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +146 -231
  29. package/misc/apps/RAG/src/prompts/index.ts +4 -4
  30. package/misc/apps/RAG/src/tests/graph.test.ts +35 -0
  31. package/misc/apps/RAG/src/utils/FlowQueryExecutor.ts +20 -21
  32. package/misc/apps/RAG/src/utils/FlowQueryExtractor.ts +35 -30
  33. package/misc/apps/RAG/src/utils/Llm.ts +248 -0
  34. package/misc/apps/RAG/src/utils/index.ts +7 -4
  35. package/misc/apps/RAG/tsconfig.json +4 -3
  36. package/misc/apps/RAG/webpack.config.js +40 -40
  37. package/package.json +1 -1
  38. package/src/parsing/parser.ts +1 -0
  39. package/tests/compute/runner.test.ts +1 -1
  40. package/tests/parsing/parser.test.ts +16 -0
  41. package/misc/apps/RAG/src/plugins/README.md +0 -139
  42. package/misc/apps/RAG/src/plugins/index.ts +0 -72
  43. package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +0 -70
  44. package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +0 -65
  45. package/misc/apps/RAG/src/plugins/loaders/Form.ts +0 -594
  46. package/misc/apps/RAG/src/plugins/loaders/Llm.ts +0 -450
  47. package/misc/apps/RAG/src/plugins/loaders/MockData.ts +0 -101
  48. package/misc/apps/RAG/src/plugins/loaders/Table.ts +0 -274
  49. package/misc/apps/RAG/src/plugins/loaders/Weather.ts +0 -138
@@ -1,10 +1,9 @@
1
1
  /**
2
2
  * FlowQuery Executor Utility
3
- *
3
+ *
4
4
  * Executes FlowQuery statements and handles errors gracefully.
5
5
  */
6
-
7
- import { FlowQuery } from 'flowquery';
6
+ import { FlowQuery } from "flowquery";
8
7
 
9
8
  /**
10
9
  * Result of executing a FlowQuery statement.
@@ -24,7 +23,7 @@ export interface FlowQueryExecutionResult {
24
23
 
25
24
  /**
26
25
  * FlowQuery Executor class for executing FlowQuery statements.
27
- *
26
+ *
28
27
  * @example
29
28
  * ```typescript
30
29
  * const executor = new FlowQueryExecutor();
@@ -49,52 +48,52 @@ export class FlowQueryExecutor {
49
48
 
50
49
  /**
51
50
  * Execute a FlowQuery statement and return the results.
52
- *
51
+ *
53
52
  * @param query - The FlowQuery statement to execute
54
53
  * @returns The execution result including success status, results or error
55
54
  */
56
55
  async execute(query: string): Promise<FlowQueryExecutionResult> {
57
56
  const startTime = performance.now();
58
-
57
+
59
58
  try {
60
59
  // Validate the query is not empty
61
- if (!query || query.trim() === '') {
60
+ if (!query || query.trim() === "") {
62
61
  return {
63
62
  success: false,
64
63
  query,
65
- error: 'Query cannot be empty',
66
- executionTime: performance.now() - startTime
64
+ error: "Query cannot be empty",
65
+ executionTime: performance.now() - startTime,
67
66
  };
68
67
  }
69
68
 
70
69
  // Create a runner and execute the query
71
70
  const runner = new FlowQuery(query);
72
71
  await runner.run();
73
-
72
+
74
73
  // Get the results
75
74
  const results = runner.results;
76
-
75
+
77
76
  return {
78
77
  success: true,
79
78
  query,
80
79
  results: Array.isArray(results) ? results : [results],
81
- executionTime: performance.now() - startTime
80
+ executionTime: performance.now() - startTime,
82
81
  };
83
82
  } catch (error) {
84
83
  const errorMessage = error instanceof Error ? error.message : String(error);
85
-
84
+
86
85
  return {
87
86
  success: false,
88
87
  query,
89
88
  error: errorMessage,
90
- executionTime: performance.now() - startTime
89
+ executionTime: performance.now() - startTime,
91
90
  };
92
91
  }
93
92
  }
94
93
 
95
94
  /**
96
95
  * Format execution results for display or LLM consumption.
97
- *
96
+ *
98
97
  * @param result - The execution result to format
99
98
  * @param maxItems - Maximum number of items to include (uses default if not specified)
100
99
  * @returns A formatted string representation of the results
@@ -109,21 +108,21 @@ export class FlowQueryExecutor {
109
108
  const results = result.results || [];
110
109
  const totalCount = results.length;
111
110
  const displayResults = results.slice(0, limit);
112
-
111
+
113
112
  let output = `Execution successful (${result.executionTime.toFixed(2)}ms)\n`;
114
113
  output += `Total results: ${totalCount}\n\n`;
115
-
114
+
116
115
  if (totalCount === 0) {
117
- output += 'No results returned.';
116
+ output += "No results returned.";
118
117
  } else {
119
- output += 'Results:\n';
118
+ output += "Results:\n";
120
119
  output += JSON.stringify(displayResults, null, 2);
121
-
120
+
122
121
  if (totalCount > limit) {
123
122
  output += `\n\n... and ${totalCount - limit} more results`;
124
123
  }
125
124
  }
126
-
125
+
127
126
  return output;
128
127
  }
129
128
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * FlowQuery Extraction Utility
3
- *
3
+ *
4
4
  * Extracts FlowQuery statements from LLM responses.
5
5
  */
6
6
 
@@ -22,10 +22,10 @@ export interface FlowQueryExtraction {
22
22
 
23
23
  /**
24
24
  * FlowQuery Extractor class for extracting FlowQuery statements from LLM responses.
25
- *
25
+ *
26
26
  * Looks for code blocks with flowquery, cypher, or sql language tags,
27
27
  * or generic code blocks that appear to contain FlowQuery syntax.
28
- *
28
+ *
29
29
  * @example
30
30
  * ```typescript
31
31
  * const extractor = new FlowQueryExtractor();
@@ -34,7 +34,7 @@ export interface FlowQueryExtraction {
34
34
  * LOAD JSON FROM somePlugin(5) AS item
35
35
  * RETURN item.text
36
36
  * \`\`\``;
37
- *
37
+ *
38
38
  * const extraction = extractor.extract(response);
39
39
  * console.log(extraction.query); // "LOAD JSON FROM somePlugin(5) AS item\nRETURN item.text"
40
40
  * ```
@@ -44,47 +44,47 @@ export class FlowQueryExtractor {
44
44
  private readonly codeBlockPatterns: RegExp[] = [
45
45
  /```(?:flowquery|cypher|fql)\s*\n([\s\S]*?)```/i,
46
46
  /```(?:sql)\s*\n([\s\S]*?)```/i,
47
- /```\s*\n([\s\S]*?)```/, // Generic code block
47
+ /```\s*\n([\s\S]*?)```/, // Generic code block
48
48
  ];
49
49
 
50
50
  /** Keywords that indicate a FlowQuery statement */
51
51
  private readonly flowQueryKeywords: RegExp[] = [
52
+ /\bMATCH\b/i,
53
+ /\bCREATE\b/i,
52
54
  /\bWITH\b/i,
53
55
  /\bLOAD\s+JSON\s+FROM\b/i,
54
56
  /\bUNWIND\b/i,
55
57
  /\bRETURN\b/i,
56
58
  /\bWHERE\b/i,
57
- /\bORDER\s+BY\b/i,
58
- /\bLIMIT\b/i,
59
59
  ];
60
60
 
61
61
  /** Keywords that can start a FlowQuery statement */
62
- private readonly startKeywords = /^(WITH|LOAD\s+JSON\s+FROM|UNWIND)\b/i;
62
+ private readonly startKeywords = /^(MATCH|CREATE|WITH|LOAD\s+JSON\s+FROM|UNWIND|CALL)\b/i;
63
63
 
64
64
  /** Keywords that can continue a FlowQuery statement */
65
- private readonly continueKeywords = /^(WITH|LOAD|UNWIND|WHERE|RETURN|ORDER|LIMIT|SKIP|HEADERS|POST|AS)\b/i;
65
+ private readonly continueKeywords =
66
+ /^(MATCH|CREATE|WITH|LOAD|UNWIND|WHERE|RETURN|CALL|YIELD|HEADERS|POST|AS)\b/i;
66
67
 
67
68
  /**
68
69
  * Extract a FlowQuery statement from an LLM response.
69
- *
70
+ *
70
71
  * @param llmResponse - The full text response from the LLM
71
72
  * @returns The extraction result
72
73
  */
73
74
  public extract(llmResponse: string): FlowQueryExtraction {
74
- if (!llmResponse || llmResponse.trim() === '') {
75
+ if (!llmResponse || llmResponse.trim() === "") {
75
76
  return { query: null, found: false };
76
77
  }
77
78
 
78
79
  // Check for explicit "NO_QUERY_NEEDED" marker
79
- if (llmResponse.includes('[NO_QUERY_NEEDED]') ||
80
- llmResponse.includes('NO_QUERY_NEEDED')) {
80
+ if (llmResponse.includes("[NO_QUERY_NEEDED]") || llmResponse.includes("NO_QUERY_NEEDED")) {
81
81
  // Extract the direct response after the marker
82
82
  const directMatch = llmResponse.match(/\[NO_QUERY_NEEDED\]\s*([\s\S]*)/i);
83
83
  return {
84
84
  query: null,
85
85
  found: false,
86
86
  noQueryNeeded: true,
87
- directResponse: directMatch ? directMatch[1].trim() : llmResponse
87
+ directResponse: directMatch ? directMatch[1].trim() : llmResponse,
88
88
  };
89
89
  }
90
90
 
@@ -93,16 +93,18 @@ export class FlowQueryExtractor {
93
93
  const match = llmResponse.match(pattern);
94
94
  if (match && match[1]) {
95
95
  const query = match[1].trim();
96
-
96
+
97
97
  // Verify it looks like a FlowQuery statement
98
98
  if (this.isLikelyFlowQuery(query)) {
99
99
  // Extract explanation text before the code block
100
- const beforeMatch = llmResponse.substring(0, llmResponse.indexOf(match[0])).trim();
101
-
100
+ const beforeMatch = llmResponse
101
+ .substring(0, llmResponse.indexOf(match[0]))
102
+ .trim();
103
+
102
104
  return {
103
105
  query,
104
106
  found: true,
105
- explanation: beforeMatch || undefined
107
+ explanation: beforeMatch || undefined,
106
108
  };
107
109
  }
108
110
  }
@@ -114,7 +116,7 @@ export class FlowQueryExtractor {
114
116
  if (inlineQuery) {
115
117
  return {
116
118
  query: inlineQuery,
117
- found: true
119
+ found: true,
118
120
  };
119
121
  }
120
122
 
@@ -124,7 +126,7 @@ export class FlowQueryExtractor {
124
126
  /**
125
127
  * Extract multiple FlowQuery statements from an LLM response.
126
128
  * Useful when the LLM provides alternative queries.
127
- *
129
+ *
128
130
  * @param llmResponse - The full text response from the LLM
129
131
  * @returns Array of extracted queries
130
132
  */
@@ -133,7 +135,7 @@ export class FlowQueryExtractor {
133
135
 
134
136
  const queries: string[] = [];
135
137
  const codeBlockPattern = /```(?:flowquery|cypher|fql|sql)?\s*\n([\s\S]*?)```/gi;
136
-
138
+
137
139
  let match;
138
140
  while ((match = codeBlockPattern.exec(llmResponse)) !== null) {
139
141
  if (match[1]) {
@@ -152,31 +154,34 @@ export class FlowQueryExtractor {
152
154
  */
153
155
  private isLikelyFlowQuery(text: string): boolean {
154
156
  // Must contain at least one FlowQuery keyword
155
- return this.flowQueryKeywords.some(pattern => pattern.test(text));
157
+ return this.flowQueryKeywords.some((pattern) => pattern.test(text));
156
158
  }
157
159
 
158
160
  /**
159
161
  * Try to extract a FlowQuery statement that's not in a code block.
160
162
  */
161
163
  private extractInlineQuery(text: string): string | null {
162
- const lines = text.split('\n');
164
+ const lines = text.split("\n");
163
165
  const queryLines: string[] = [];
164
166
  let inQuery = false;
165
167
 
166
168
  for (const line of lines) {
167
169
  const trimmedLine = line.trim();
168
-
170
+
169
171
  if (!inQuery && this.startKeywords.test(trimmedLine)) {
170
172
  inQuery = true;
171
173
  queryLines.push(trimmedLine);
172
174
  } else if (inQuery) {
173
175
  // Check if this line continues the query
174
- if (this.continueKeywords.test(trimmedLine) ||
175
- trimmedLine.startsWith('{') ||
176
- trimmedLine.startsWith('}') ||
177
- trimmedLine === '' ||
176
+ if (
177
+ this.continueKeywords.test(trimmedLine) ||
178
+ trimmedLine.startsWith("{") ||
179
+ trimmedLine.startsWith("}") ||
180
+ trimmedLine === "" ||
178
181
  /^[A-Za-z_][A-Za-z0-9_]*\./.test(trimmedLine) ||
179
- /^\s+/.test(line)) { // Indented line
182
+ /^\s+/.test(line)
183
+ ) {
184
+ // Indented line
180
185
  queryLines.push(trimmedLine);
181
186
  } else {
182
187
  // End of query
@@ -185,7 +190,7 @@ export class FlowQueryExtractor {
185
190
  }
186
191
  }
187
192
 
188
- const query = queryLines.join('\n').trim();
193
+ const query = queryLines.join("\n").trim();
189
194
  return query && this.isLikelyFlowQuery(query) ? query : null;
190
195
  }
191
196
  }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * LLM (Large Language Model) Client
3
+ *
4
+ * Provides functions for making OpenAI-compatible API calls.
5
+ * Supports both regular and streaming responses.
6
+ */
7
+ import { getStoredApiConfig } from "../components/ApiKeySettings";
8
+
9
+ export interface LlmOptions {
10
+ /** System prompt to use */
11
+ systemPrompt?: string;
12
+ /** Conversation history */
13
+ messages?: Array<{ role: "user" | "assistant" | "system"; content: string }>;
14
+ /** Model to use (defaults to stored model or gpt-4o-mini) */
15
+ model?: string;
16
+ /** Temperature for response generation (0-2, default 0.7) */
17
+ temperature?: number;
18
+ /** Maximum tokens in response */
19
+ maxTokens?: number;
20
+ /** API key override (uses stored key if not provided) */
21
+ apiKey?: string;
22
+ /** Organization ID override (uses stored org if not provided) */
23
+ organizationId?: string;
24
+ /** Base URL for API (defaults to OpenAI) */
25
+ baseUrl?: string;
26
+ }
27
+
28
+ export interface LlmMessage {
29
+ role: "user" | "assistant" | "system";
30
+ content: string;
31
+ }
32
+
33
+ export interface LlmChoice {
34
+ index: number;
35
+ message: LlmMessage;
36
+ finish_reason: string;
37
+ }
38
+
39
+ export interface LlmResponse {
40
+ id: string;
41
+ object: string;
42
+ created: number;
43
+ model: string;
44
+ choices: LlmChoice[];
45
+ usage?: {
46
+ prompt_tokens: number;
47
+ completion_tokens: number;
48
+ total_tokens: number;
49
+ };
50
+ }
51
+
52
+ export interface LlmStreamChoice {
53
+ index: number;
54
+ delta: {
55
+ role?: string;
56
+ content?: string;
57
+ };
58
+ finish_reason: string | null;
59
+ }
60
+
61
+ export interface LlmStreamChunk {
62
+ id: string;
63
+ object: string;
64
+ created: number;
65
+ model: string;
66
+ choices: LlmStreamChoice[];
67
+ }
68
+
69
+ /**
70
+ * Get the API configuration, merging stored config with provided options.
71
+ */
72
+ function getApiConfig(options: LlmOptions): {
73
+ apiKey: string;
74
+ orgId?: string;
75
+ model: string;
76
+ baseUrl: string;
77
+ } {
78
+ const storedConfig = getStoredApiConfig();
79
+
80
+ const apiKey = options.apiKey || storedConfig?.apiKey;
81
+ if (!apiKey) {
82
+ throw new Error("No API key configured. Please set your OpenAI API key in settings.");
83
+ }
84
+
85
+ return {
86
+ apiKey,
87
+ orgId: options.organizationId || storedConfig?.organizationId,
88
+ model: options.model || storedConfig?.model || "gpt-4o-mini",
89
+ baseUrl: options.baseUrl || "https://api.openai.com/v1",
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Build the messages array for the API request.
95
+ */
96
+ function buildMessages(content: string, options: LlmOptions): LlmMessage[] {
97
+ const messages: LlmMessage[] = [];
98
+
99
+ // Add system prompt if provided
100
+ if (options.systemPrompt) {
101
+ messages.push({
102
+ role: "system",
103
+ content: options.systemPrompt,
104
+ });
105
+ }
106
+
107
+ // Add conversation history if provided
108
+ if (options.messages && options.messages.length > 0) {
109
+ messages.push(...options.messages);
110
+ }
111
+
112
+ // Add the current user message
113
+ messages.push({
114
+ role: "user",
115
+ content,
116
+ });
117
+
118
+ return messages;
119
+ }
120
+
121
+ /**
122
+ * Make a non-streaming LLM API call.
123
+ *
124
+ * @param content - The user's message content
125
+ * @param options - LLM options including system prompt and conversation history
126
+ * @returns Promise resolving to the LLM response
127
+ */
128
+ export async function llm(content: string, options: LlmOptions = {}): Promise<LlmResponse> {
129
+ const config = getApiConfig(options);
130
+ const messages = buildMessages(content, options);
131
+
132
+ const headers: Record<string, string> = {
133
+ "Content-Type": "application/json",
134
+ Authorization: `Bearer ${config.apiKey}`,
135
+ };
136
+
137
+ if (config.orgId) {
138
+ headers["OpenAI-Organization"] = config.orgId;
139
+ }
140
+
141
+ const response = await fetch(`${config.baseUrl}/chat/completions`, {
142
+ method: "POST",
143
+ headers,
144
+ body: JSON.stringify({
145
+ model: config.model,
146
+ messages,
147
+ temperature: options.temperature ?? 0.7,
148
+ max_tokens: options.maxTokens,
149
+ }),
150
+ });
151
+
152
+ if (!response.ok) {
153
+ const errorBody = await response.text();
154
+ throw new Error(`LLM API error (${response.status}): ${errorBody}`);
155
+ }
156
+
157
+ return response.json();
158
+ }
159
+
160
+ /**
161
+ * Make a streaming LLM API call.
162
+ *
163
+ * @param content - The user's message content
164
+ * @param options - LLM options including system prompt and conversation history
165
+ * @yields LLM stream chunks as they arrive
166
+ */
167
+ export async function* llmStream(
168
+ content: string,
169
+ options: LlmOptions = {}
170
+ ): AsyncGenerator<LlmStreamChunk, void, unknown> {
171
+ const config = getApiConfig(options);
172
+ const messages = buildMessages(content, options);
173
+
174
+ const headers: Record<string, string> = {
175
+ "Content-Type": "application/json",
176
+ Authorization: `Bearer ${config.apiKey}`,
177
+ };
178
+
179
+ if (config.orgId) {
180
+ headers["OpenAI-Organization"] = config.orgId;
181
+ }
182
+
183
+ const response = await fetch(`${config.baseUrl}/chat/completions`, {
184
+ method: "POST",
185
+ headers,
186
+ body: JSON.stringify({
187
+ model: config.model,
188
+ messages,
189
+ temperature: options.temperature ?? 0.7,
190
+ max_tokens: options.maxTokens,
191
+ stream: true,
192
+ }),
193
+ });
194
+
195
+ if (!response.ok) {
196
+ const errorBody = await response.text();
197
+ throw new Error(`LLM API error (${response.status}): ${errorBody}`);
198
+ }
199
+
200
+ if (!response.body) {
201
+ throw new Error("Response body is null");
202
+ }
203
+
204
+ const reader = response.body.getReader();
205
+ const decoder = new TextDecoder();
206
+ let buffer = "";
207
+
208
+ try {
209
+ while (true) {
210
+ const { done, value } = await reader.read();
211
+
212
+ if (done) {
213
+ break;
214
+ }
215
+
216
+ buffer += decoder.decode(value, { stream: true });
217
+
218
+ // Process complete SSE messages
219
+ const lines = buffer.split("\n");
220
+ buffer = lines.pop() || ""; // Keep incomplete line in buffer
221
+
222
+ for (const line of lines) {
223
+ const trimmedLine = line.trim();
224
+
225
+ if (!trimmedLine || trimmedLine === ":") {
226
+ continue;
227
+ }
228
+
229
+ if (trimmedLine === "data: [DONE]") {
230
+ return;
231
+ }
232
+
233
+ if (trimmedLine.startsWith("data: ")) {
234
+ const jsonStr = trimmedLine.slice(6);
235
+ try {
236
+ const chunk = JSON.parse(jsonStr) as LlmStreamChunk;
237
+ yield chunk;
238
+ } catch {
239
+ // Skip invalid JSON chunks
240
+ console.warn("Failed to parse LLM stream chunk:", jsonStr);
241
+ }
242
+ }
243
+ }
244
+ }
245
+ } finally {
246
+ reader.releaseLock();
247
+ }
248
+ }
@@ -2,8 +2,11 @@
2
2
  * Utils module exports
3
3
  */
4
4
 
5
- export { FlowQueryExecutor } from './FlowQueryExecutor';
6
- export type { FlowQueryExecutionResult } from './FlowQueryExecutor';
5
+ export { FlowQueryExecutor } from "./FlowQueryExecutor";
6
+ export type { FlowQueryExecutionResult } from "./FlowQueryExecutor";
7
7
 
8
- export { FlowQueryExtractor, extractFlowQuery, extractAllFlowQueries } from './FlowQueryExtractor';
9
- export type { FlowQueryExtraction } from './FlowQueryExtractor';
8
+ export { FlowQueryExtractor, extractFlowQuery, extractAllFlowQueries } from "./FlowQueryExtractor";
9
+ export type { FlowQueryExtraction } from "./FlowQueryExtractor";
10
+
11
+ export { llm, llmStream } from "./Llm";
12
+ export type { LlmOptions, LlmResponse, LlmStreamChunk } from "./Llm";
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "outDir": "./dist",
4
- "rootDir": "./src",
4
+ "rootDir": ".",
5
5
  "target": "ES2020",
6
6
  "module": "ESNext",
7
7
  "moduleResolution": "bundler",
8
+ "experimentalDecorators": true,
8
9
  "esModuleInterop": true,
9
10
  "forceConsistentCasingInFileNames": true,
10
11
  "strict": true,
@@ -14,8 +15,8 @@
14
15
  "resolveJsonModule": true,
15
16
  "jsx": "react-jsx",
16
17
  "lib": ["DOM", "DOM.Iterable", "ESNext"],
17
- "types": ["node"]
18
+ "types": ["node", "jest"]
18
19
  },
19
- "include": ["src/**/*"],
20
+ "include": ["src/**/*", "data/**/*"],
20
21
  "exclude": ["node_modules", "dist"]
21
22
  }
@@ -1,43 +1,43 @@
1
- const path = require('path');
2
- const HtmlWebpackPlugin = require('html-webpack-plugin');
1
+ const path = require("path");
2
+ const HtmlWebpackPlugin = require("html-webpack-plugin");
3
3
 
4
4
  module.exports = {
5
- mode: 'development',
6
- entry: './src/index.tsx',
7
- target: 'web',
8
- output: {
9
- filename: 'bundle.js',
10
- path: path.resolve(__dirname, 'dist'),
11
- clean: true
12
- },
13
- resolve: {
14
- extensions: ['.tsx', '.ts', '.js', '.jsx']
15
- },
16
- module: {
17
- rules: [
18
- {
19
- test: /\.tsx?$/,
20
- use: 'ts-loader',
21
- exclude: /node_modules/
22
- },
23
- {
24
- test: /\.css$/,
25
- use: ['style-loader', 'css-loader']
26
- }
27
- ]
28
- },
29
- plugins: [
30
- new HtmlWebpackPlugin({
31
- template: './public/index.html'
32
- }),
33
- ],
34
- devServer: {
35
- static: './dist',
36
- port: 3000,
37
- open: true,
38
- hot: true
39
- },
40
- optimization: {
41
- minimize: false
42
- }
5
+ mode: "development",
6
+ entry: "./src/index.tsx",
7
+ target: "web",
8
+ output: {
9
+ filename: "bundle.js",
10
+ path: path.resolve(__dirname, "dist"),
11
+ clean: true,
12
+ },
13
+ resolve: {
14
+ extensions: [".tsx", ".ts", ".js", ".jsx"],
15
+ },
16
+ module: {
17
+ rules: [
18
+ {
19
+ test: /\.tsx?$/,
20
+ use: "ts-loader",
21
+ exclude: /node_modules/,
22
+ },
23
+ {
24
+ test: /\.css$/,
25
+ use: ["style-loader", "css-loader"],
26
+ },
27
+ ],
28
+ },
29
+ plugins: [
30
+ new HtmlWebpackPlugin({
31
+ template: "./public/index.html",
32
+ }),
33
+ ],
34
+ devServer: {
35
+ static: ["./dist", { directory: path.resolve(__dirname, "data"), publicPath: "/data" }],
36
+ port: 3000,
37
+ open: true,
38
+ hot: true,
39
+ },
40
+ optimization: {
41
+ minimize: false,
42
+ },
43
43
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowquery",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
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",