@vaultgradient/pipequery-lang 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +301 -0
- package/dist/engine/index.cjs +2102 -0
- package/dist/engine/index.d.cts +203 -0
- package/dist/engine/index.d.ts +203 -0
- package/dist/engine/index.js +2102 -0
- package/dist/highlighting/index.cjs +562 -0
- package/dist/highlighting/index.d.cts +136 -0
- package/dist/highlighting/index.d.ts +136 -0
- package/dist/highlighting/index.js +562 -0
- package/dist/react/index.cjs +1374 -0
- package/dist/react/index.d.cts +120 -0
- package/dist/react/index.d.ts +120 -0
- package/dist/react/index.js +1374 -0
- package/package.json +137 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 andreadito
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<h1 align="center">| PipeQuery</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
A pipe-based query language for filtering, transforming, and aggregating data in JavaScript/TypeScript.
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://github.com/andreadito/pipequery/releases/latest"><img src="https://img.shields.io/github/v/release/andreadito/pipequery?label=release&color=orange" alt="release" /></a>
|
|
9
|
+
<a href="https://github.com/andreadito/pipequery/pkgs/npm/pipequery-lang"><img src="https://img.shields.io/badge/npm-@andreadito/pipequery--lang-cb3837?logo=npm" alt="engine package" /></a>
|
|
10
|
+
<a href="https://github.com/andreadito/pipequery/pkgs/npm/pq"><img src="https://img.shields.io/badge/npm-@andreadito/pq-cb3837?logo=npm" alt="cli package" /></a>
|
|
11
|
+
<a href="https://github.com/andreadito/pipequery/pkgs/container/pipequery"><img src="https://img.shields.io/badge/ghcr.io-pipequery-blue?logo=docker" alt="docker" /></a>
|
|
12
|
+
<a href="https://github.com/andreadito/pipequery/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license" /></a>
|
|
13
|
+
<a href="https://github.com/andreadito/pipequery"><img src="https://img.shields.io/badge/TypeScript-100%25-blue.svg" alt="TypeScript" /></a>
|
|
14
|
+
<a href="https://andreadito.github.io/pipequery"><img src="https://img.shields.io/badge/demo-playground-blueviolet.svg" alt="playground" /></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- **Pipe-based syntax** — chain operations with `|`, inspired by Unix pipes and SQL
|
|
22
|
+
- **Minimal dependencies** — lightweight core engine
|
|
23
|
+
- **TypeScript-first** — full type definitions included
|
|
24
|
+
- **25+ aggregate functions** — basic, statistical, and financial aggregations
|
|
25
|
+
- **LiveQuery** — streaming queries with delta/patch support
|
|
26
|
+
- **Editor support** — CodeMirror 6, Monaco, and TextMate grammars
|
|
27
|
+
- **React components** — visual pipeline builder out of the box
|
|
28
|
+
|
|
29
|
+
## Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @andreadito/pipequery-lang
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## CLI — `pq`
|
|
36
|
+
|
|
37
|
+
PipeQuery also ships a CLI tool for building data pipelines, REST APIs, and rich terminal dashboards.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install -g @andreadito/pq
|
|
41
|
+
|
|
42
|
+
pq init # scaffold a project
|
|
43
|
+
pq serve -d # start the server as a daemon
|
|
44
|
+
pq dashboard # launch the TUI dashboard
|
|
45
|
+
pq query "crypto | sort(price desc) | first(5)"
|
|
46
|
+
pq stop # stop the server
|
|
47
|
+
|
|
48
|
+
# Create a live API endpoint on the fly — no config needed
|
|
49
|
+
pq endpoint add /api/top-coins -q "crypto | sort(market_cap desc) | first(10)"
|
|
50
|
+
# → http://localhost:3000/api/top-coins is instantly available
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Create API endpoints on the fly without editing config files — just `pq endpoint add` with a PipeQuery expression and your endpoint is live immediately.
|
|
54
|
+
|
|
55
|
+
### Run with Docker
|
|
56
|
+
|
|
57
|
+
The server and CLI are fully decoupled — deploy the server anywhere with Docker and control it from your local terminal:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Run the server in Docker
|
|
61
|
+
docker run -p 3000:3000 ghcr.io/andreadito/pipequery
|
|
62
|
+
|
|
63
|
+
# From any folder on your machine, connect and start working
|
|
64
|
+
pq remote connect http://localhost:3000
|
|
65
|
+
pq source add crypto -t rest -u "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&per_page=20" -i 30s
|
|
66
|
+
pq endpoint add /api/top -q "crypto | sort(market_cap desc) | first(5)"
|
|
67
|
+
curl http://localhost:3000/api/top
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Works the same with a remote server — just `pq remote connect https://my-server.example.com:3000`.
|
|
71
|
+
|
|
72
|
+
The dashboard features a resizable 2-column grid with live SSE updates and 7 visualization types. See [`cli/README.md`](./cli/README.md) for full documentation.
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { query } from '@andreadito/pipequery-lang';
|
|
78
|
+
|
|
79
|
+
const data = [
|
|
80
|
+
{ name: 'Laptop', price: 999, category: 'Electronics' },
|
|
81
|
+
{ name: 'Mouse', price: 29, category: 'Electronics' },
|
|
82
|
+
{ name: 'Desk', price: 349, category: 'Furniture' },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
// Filter and sort
|
|
86
|
+
query(data, 'where(price > 100) | sort(price desc)');
|
|
87
|
+
// → [{ name: 'Laptop', ... }, { name: 'Desk', ... }]
|
|
88
|
+
|
|
89
|
+
// Aggregate
|
|
90
|
+
query(data, 'rollup(sum(price) as total, count() as n)');
|
|
91
|
+
// → [{ total: 1377, n: 3 }]
|
|
92
|
+
|
|
93
|
+
// Group and aggregate
|
|
94
|
+
query(data, 'groupBy(category) | rollup(avg(price) as avgPrice)');
|
|
95
|
+
// → [{ category: 'Electronics', avgPrice: 514 }, { category: 'Furniture', avgPrice: 349 }]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Query Syntax
|
|
99
|
+
|
|
100
|
+
PipeQuery chains operations with the `|` pipe operator:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
source | operation1(...) | operation2(...) | ...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Operations
|
|
107
|
+
|
|
108
|
+
| Operation | Description | Example |
|
|
109
|
+
|-----------|-------------|---------|
|
|
110
|
+
| `where(expr)` | Filter rows | `where(price > 100)` |
|
|
111
|
+
| `select(fields...)` | Pick fields | `select(name, price)` |
|
|
112
|
+
| `sort(expr dir)` | Sort rows | `sort(price desc)` |
|
|
113
|
+
| `groupBy(keys...)` | Group rows | `groupBy(category)` |
|
|
114
|
+
| `rollup(aggs...)` | Group + aggregate | `rollup(sum(price) as total)` |
|
|
115
|
+
| `join(source, cond)` | Join tables | `join(orders, id == orderId)` |
|
|
116
|
+
| `first(n)` | Take first N | `first(10)` |
|
|
117
|
+
| `last(n)` | Take last N | `last(5)` |
|
|
118
|
+
| `distinct(fields?)` | Remove duplicates | `distinct(category)` |
|
|
119
|
+
| `map(exprs...)` | Transform rows | `map(price * 1.1 as newPrice)` |
|
|
120
|
+
| `pivot(field, aggs)` | Pivot table | `pivot(region, sum(sales))` |
|
|
121
|
+
| `flatten(field?)` | Flatten arrays | `flatten(tags)` |
|
|
122
|
+
| `transpose(header?)` | Transpose matrix | `transpose(name)` |
|
|
123
|
+
| `reduce(init, acc)` | Reduce to scalar | `reduce(0, $acc + price)` |
|
|
124
|
+
|
|
125
|
+
### Aggregate Functions
|
|
126
|
+
|
|
127
|
+
| Category | Functions |
|
|
128
|
+
|----------|-----------|
|
|
129
|
+
| **Basic** | `sum`, `avg`, `min`, `max`, `count` |
|
|
130
|
+
| **Statistical** | `median`, `stddev`, `var`, `percentile`, `skew`, `kurt` |
|
|
131
|
+
| **Financial** | `vwap`, `wavg`, `drawdown`, `sharpe`, `calmar`, `sortino`, `info_ratio` |
|
|
132
|
+
| **Utility** | `distinct_count`, `sum_abs`, `first_value`, `last_value`, `pct` |
|
|
133
|
+
|
|
134
|
+
### Built-in Functions
|
|
135
|
+
|
|
136
|
+
| Category | Functions |
|
|
137
|
+
|----------|-----------|
|
|
138
|
+
| **String** | `lower`, `upper`, `len`, `concat`, `trim`, `contains`, `startsWith`, `endsWith`, `substring`, `replace` |
|
|
139
|
+
| **Logic** | `if`, `coalesce` |
|
|
140
|
+
| **Math** | `abs`, `round` |
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
where(contains(name, "Bitcoin")) // substring search
|
|
144
|
+
where(startsWith(symbol, "BT")) // prefix match
|
|
145
|
+
where(endsWith(email, ".com")) // suffix match
|
|
146
|
+
select(trim(name) as name) // strip whitespace
|
|
147
|
+
select(substring(name, 0, 5) as short) // extract first 5 chars
|
|
148
|
+
select(replace(name, "old", "new") as r) // replace all occurrences
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Window Functions
|
|
152
|
+
|
|
153
|
+
`running_sum`, `running_avg`, `running_count`, `running_min`, `running_max`, `row_number`, `lag`, `lead`
|
|
154
|
+
|
|
155
|
+
### Expressions
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
price > 100 && category == 'Electronics' // boolean logic
|
|
159
|
+
price * 0.9 as discounted // arithmetic + alias
|
|
160
|
+
nested.field.path // dot access
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## API
|
|
164
|
+
|
|
165
|
+
### `query(data, expression)`
|
|
166
|
+
|
|
167
|
+
Execute a query on data. Accepts a raw array or a named `DataContext` for multi-table queries.
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
import { query } from '@andreadito/pipequery-lang';
|
|
171
|
+
|
|
172
|
+
// Array shorthand
|
|
173
|
+
query(items, 'where(price > 50) | sort(name asc)');
|
|
174
|
+
|
|
175
|
+
// Named context (for joins)
|
|
176
|
+
query(
|
|
177
|
+
{ orders, customers },
|
|
178
|
+
'orders | join(customers, customerId == id) | select(orderId, name, total)'
|
|
179
|
+
);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### `compile(expression)`
|
|
183
|
+
|
|
184
|
+
Pre-compile a query for repeated use. Returns a reusable function.
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { compile } from '@andreadito/pipequery-lang';
|
|
188
|
+
|
|
189
|
+
const fn = compile('where(price > 100) | sort(price desc)');
|
|
190
|
+
const result = fn({ _data: items });
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### `parseQuery(expression)`
|
|
194
|
+
|
|
195
|
+
Parse a query into its AST without executing.
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { parseQuery } from '@andreadito/pipequery-lang';
|
|
199
|
+
|
|
200
|
+
const ast = parseQuery('items | where(price > 100)');
|
|
201
|
+
// Inspect tokens, operations, expressions
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### `liveQuery(data, expression, options)`
|
|
205
|
+
|
|
206
|
+
Streaming query evaluator that accepts data patches and re-executes efficiently.
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { liveQuery } from '@andreadito/pipequery-lang';
|
|
210
|
+
|
|
211
|
+
const lq = liveQuery(initialData, 'where(active == true) | sort(updatedAt desc)', {
|
|
212
|
+
key: 'id',
|
|
213
|
+
throttle: 100,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
lq.subscribe((result, stats) => {
|
|
217
|
+
console.log(`${stats.rowCount} rows in ${stats.totalMs}ms`);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Push incremental updates
|
|
221
|
+
lq.patch([{ id: 1, active: true, updatedAt: Date.now() }]);
|
|
222
|
+
|
|
223
|
+
// Clean up
|
|
224
|
+
lq.dispose();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### `clearCache()`
|
|
228
|
+
|
|
229
|
+
Clear the internal compiled-query LRU cache (128 entries by default).
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import { clearCache } from '@andreadito/pipequery-lang';
|
|
233
|
+
|
|
234
|
+
clearCache();
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Error Handling
|
|
238
|
+
|
|
239
|
+
All errors include position info (`position`, `line`, `column`) for editor integration.
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
import { LexerError, ParseError, RuntimeError, DataWeaveError } from '@andreadito/pipequery-lang';
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
query(data, 'where(price >)');
|
|
246
|
+
} catch (e) {
|
|
247
|
+
if (e instanceof ParseError) {
|
|
248
|
+
console.log(`Syntax error at line ${e.line}, column ${e.column}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Sub-packages
|
|
254
|
+
|
|
255
|
+
### Syntax Highlighting
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
// CodeMirror 6
|
|
259
|
+
import { pipeQuery } from '@andreadito/pipequery-lang/highlighting';
|
|
260
|
+
|
|
261
|
+
// Monaco Editor
|
|
262
|
+
import { registerPipeQuery } from '@andreadito/pipequery-lang/highlighting';
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
A TextMate grammar is included at `dist/highlighting/textmate/pipequery.tmLanguage.json` for VS Code, IntelliJ, and Sublime Text.
|
|
266
|
+
|
|
267
|
+
**Peer dependencies:** `@codemirror/language`, `@codemirror/state`, `@codemirror/view`, `@lezer/highlight` (CodeMirror only)
|
|
268
|
+
|
|
269
|
+
### React Components
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
import { PipeQueryBuilder } from '@andreadito/pipequery-lang/react';
|
|
273
|
+
|
|
274
|
+
<PipeQueryBuilder
|
|
275
|
+
datasets={datasets}
|
|
276
|
+
onQueryChange={(query) => console.log(query)}
|
|
277
|
+
/>
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
A visual pipeline builder component for constructing queries with drag-and-drop.
|
|
281
|
+
|
|
282
|
+
**Peer dependencies:** `react`, `react-dom`, `@mui/material`, `@emotion/react`, `@emotion/styled`, `@mui/icons-material`
|
|
283
|
+
|
|
284
|
+
## Browser Support
|
|
285
|
+
|
|
286
|
+
Works in all modern browsers and Node.js 18+. The core engine uses only standard ES2020 features.
|
|
287
|
+
|
|
288
|
+
## Contributing
|
|
289
|
+
|
|
290
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
git clone https://github.com/andreadito/pipequery.git
|
|
294
|
+
cd pipequery
|
|
295
|
+
npm install
|
|
296
|
+
npm test
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
[MIT](./LICENSE) © andreadito
|