@osqd/jql 0.1.1
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/CHANGELOG.md +220 -0
- package/LICENSE +102 -0
- package/README.md +84 -0
- package/bin/jql.mjs +5 -0
- package/conformance/cases.json +290 -0
- package/dist/array.d.ts +11 -0
- package/dist/async.d.ts +44 -0
- package/dist/canonical.d.ts +18 -0
- package/dist/cjs/array.d.ts +11 -0
- package/dist/cjs/async.d.ts +44 -0
- package/dist/cjs/canonical.d.ts +18 -0
- package/dist/cjs/cli.d.ts +15 -0
- package/dist/cjs/collections.d.ts +34 -0
- package/dist/cjs/core.d.ts +117 -0
- package/dist/cjs/errors.d.ts +17 -0
- package/dist/cjs/explain.d.ts +30 -0
- package/dist/cjs/global.d.ts +90 -0
- package/dist/cjs/group.d.ts +47 -0
- package/dist/cjs/index.d.ts +25 -0
- package/dist/cjs/internal/closest.d.ts +9 -0
- package/dist/cjs/internal/duration.d.ts +15 -0
- package/dist/cjs/internal/equal.d.ts +34 -0
- package/dist/cjs/internal/glob.d.ts +30 -0
- package/dist/cjs/internal/order.d.ts +24 -0
- package/dist/cjs/internal/path.d.ts +109 -0
- package/dist/cjs/internal/record.d.ts +18 -0
- package/dist/cjs/internal/values.d.ts +41 -0
- package/dist/cjs/limits.d.ts +64 -0
- package/dist/cjs/operators.d.ts +81 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/plan.d.ts +79 -0
- package/dist/cjs/search.d.ts +42 -0
- package/dist/cjs/targets/mongo.d.ts +55 -0
- package/dist/cjs/text/index.d.ts +12 -0
- package/dist/cjs/text/parse.d.ts +91 -0
- package/dist/cjs/text/suggest.d.ts +16 -0
- package/dist/cjs/text/write.d.ts +34 -0
- package/dist/cjs/types.d.ts +236 -0
- package/dist/cjs/vocabulary.d.ts +106 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.js +2729 -0
- package/dist/cli.js.map +1 -0
- package/dist/collections.d.ts +34 -0
- package/dist/core.d.ts +117 -0
- package/dist/errors.d.ts +17 -0
- package/dist/explain.d.ts +30 -0
- package/dist/global.cjs +1953 -0
- package/dist/global.cjs.map +1 -0
- package/dist/global.d.ts +90 -0
- package/dist/global.js +1950 -0
- package/dist/global.js.map +1 -0
- package/dist/group.d.ts +47 -0
- package/dist/index.cjs +2529 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +2495 -0
- package/dist/index.js.map +1 -0
- package/dist/internal/closest.d.ts +9 -0
- package/dist/internal/duration.d.ts +15 -0
- package/dist/internal/equal.d.ts +34 -0
- package/dist/internal/glob.d.ts +30 -0
- package/dist/internal/order.d.ts +24 -0
- package/dist/internal/path.d.ts +109 -0
- package/dist/internal/record.d.ts +18 -0
- package/dist/internal/values.d.ts +41 -0
- package/dist/limits.d.ts +64 -0
- package/dist/mongo.cjs +357 -0
- package/dist/mongo.cjs.map +1 -0
- package/dist/mongo.js +354 -0
- package/dist/mongo.js.map +1 -0
- package/dist/operators.d.ts +81 -0
- package/dist/plan.d.ts +79 -0
- package/dist/search.d.ts +42 -0
- package/dist/targets/mongo.d.ts +55 -0
- package/dist/text/index.d.ts +12 -0
- package/dist/text/parse.d.ts +91 -0
- package/dist/text/suggest.d.ts +16 -0
- package/dist/text/write.d.ts +34 -0
- package/dist/text.cjs +674 -0
- package/dist/text.cjs.map +1 -0
- package/dist/text.js +667 -0
- package/dist/text.js.map +1 -0
- package/dist/types.d.ts +236 -0
- package/dist/vocabulary.d.ts +106 -0
- package/docs/course/01-first-query.md +217 -0
- package/docs/course/02-operators.md +285 -0
- package/docs/course/03-arrays-and-paths.md +239 -0
- package/docs/course/04-combining.md +221 -0
- package/docs/course/05-dates.md +214 -0
- package/docs/course/06-typed-queries.md +240 -0
- package/docs/course/07-requests.md +261 -0
- package/docs/course/08-grouping.md +210 -0
- package/docs/course/09-explaining.md +171 -0
- package/docs/course/10-vocabulary.md +276 -0
- package/docs/course/11-the-search-box.md +349 -0
- package/docs/course/12-untrusted.md +257 -0
- package/docs/course/13-saved-filters.md +199 -0
- package/docs/course/14-streams-and-cli.md +276 -0
- package/docs/course/15-pushdown.md +240 -0
- package/docs/course/16-extending.md +199 -0
- package/docs/course/index.md +185 -0
- package/docs/design/decisions.md +198 -0
- package/docs/design/performance.md +102 -0
- package/docs/guides/adopting.md +81 -0
- package/docs/guides/pushdown.md +147 -0
- package/docs/guides/typescript.md +115 -0
- package/docs/guides/untrusted-input.md +86 -0
- package/docs/index.md +102 -0
- package/docs/reference/api.md +266 -0
- package/docs/reference/cli.md +103 -0
- package/docs/reference/index.md +12 -0
- package/docs/reference/specification.md +549 -0
- package/docs/reference/text-syntax.md +152 -0
- package/docs/start/quick-start.md +84 -0
- package/package.json +136 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Text syntax
|
|
2
|
+
|
|
3
|
+
What people can type into a search box, and the JQL document each piece becomes.
|
|
4
|
+
|
|
5
|
+
← [Documentation](../index.md) · [Reference](index.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
`parseText` from `@osqd/jql/text` turns a line of text into a JQL query. It has no matcher of
|
|
10
|
+
its own: the text *is* a way of writing JSON, and the engine runs the JSON. So a filter typed
|
|
11
|
+
into a dashboard, saved, and later run by a service that only understands JSON finds exactly
|
|
12
|
+
the same things.
|
|
13
|
+
|
|
14
|
+
The syntax is BotHandler's feed filter, moved here so every project shares one.
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { parseText } from "@osqd/jql/text";
|
|
18
|
+
|
|
19
|
+
parseText("actor:203.0.113.4 -path:/health score:>70", { vocabulary });
|
|
20
|
+
// { $and: [
|
|
21
|
+
// { actor: { $word: "203.0.113.4", $options: "i" } },
|
|
22
|
+
// { $not: { path: { $contains: "/health", $options: "i" } } },
|
|
23
|
+
// { score: { $gt: 70 } } ] }
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Terms
|
|
27
|
+
|
|
28
|
+
| You type | Means | Becomes |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| `checkout` | the text appears anywhere | `{ "$text": "checkout" }` |
|
|
31
|
+
| `"GET /api/v2"` | a phrase, spaces and all | `{ "$text": "GET /api/v2" }` |
|
|
32
|
+
| `path:/api` | the field matches the value (how depends on the field's kind, below) | `{ "path": { "$contains": "/api", "$options": "i" } }` |
|
|
33
|
+
| `-path:/health` or `!path:/health` | not | `{ "$not": { … } }` |
|
|
34
|
+
| `path:$in(/a, /b)` | any of these | `{ "path": { "$contains": ["/a", "/b"], "$options": "i" } }` |
|
|
35
|
+
| `path:$notin(/a, /b)` | none of these | `{ "$not": { "path": … } }` |
|
|
36
|
+
| `has:rule` | the field has a value | `{ "rule": { "$exists": true } }` |
|
|
37
|
+
| `-has:rule` | the field has none | `{ "$not": { "rule": { "$exists": true } } }` |
|
|
38
|
+
|
|
39
|
+
Any quote works — `"…"`, `'…'`, and the curly `“…”` and `‘…’` that smart punctuation produces
|
|
40
|
+
when a filter is pasted from chat or documentation. A single quote counts as a quote only
|
|
41
|
+
where a value begins, so the apostrophe in `don't` is still an apostrophe. Inside a set, a
|
|
42
|
+
comma separates values only outside quotes: `$in("a,b", c)` is two values.
|
|
43
|
+
|
|
44
|
+
## Operators
|
|
45
|
+
|
|
46
|
+
| You type | Means |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `a b` or `a $and b` | both |
|
|
49
|
+
| `a $or b` | either |
|
|
50
|
+
| `$not a` | not — the same as `-a` |
|
|
51
|
+
| `(a $or b) $and c` | grouping |
|
|
52
|
+
|
|
53
|
+
`$not` binds tightest, then `$and`, then `$or`, so `a $or b $and c` reads as `a $or (b $and c)`.
|
|
54
|
+
|
|
55
|
+
**Operators carry a `$`.** A bare `or` is a word that appears in paths and User-Agents, and a
|
|
56
|
+
language where an ordinary search word silently becomes an operator lies about what it
|
|
57
|
+
matched. Typing `or` searches for the text `or`.
|
|
58
|
+
|
|
59
|
+
## Field kinds
|
|
60
|
+
|
|
61
|
+
How `field:value` reads the value is the field's `kind` in the [vocabulary](../guides/typescript.md#vocabularies):
|
|
62
|
+
|
|
63
|
+
| Kind | `field:value` becomes | For |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| `text` (default) | `$contains`, ignoring case | prose, paths, User-Agents |
|
|
66
|
+
| `word` | `$word`, ignoring case — `1.2.3.4` does not find `1.2.3.45` | addresses, identifiers |
|
|
67
|
+
| `exact` | `$eq` (or `$in` for a set), ignoring case | closed sets: verdicts, methods, statuses |
|
|
68
|
+
| `number` | a comparison: `>70`, `>=70`, `<5`, `<=5`, `=42`, `42`, and ranges `10..20`, `10..`, `..20` | scores, sizes, durations |
|
|
69
|
+
| `date` | the same comparisons on `{ "$date": … }`: `>2026-09-01`, `2026-09-01..2026-09-30`, and the relative `>-1h`, `<+30m`, `-1h..now` | timestamps |
|
|
70
|
+
| `boolean` | `true`/`false`, `yes`/`no`, `1`/`0`, `on`/`off` | flags |
|
|
71
|
+
|
|
72
|
+
**A relative instant carries its sign**: `-1h` is an hour ago, `+30m` is half an hour from
|
|
73
|
+
now, `now` is now. The sign is what says a duration was meant — a bare `1h` is as likely to be
|
|
74
|
+
part of something somebody is searching for, and reading it as a time would be reading
|
|
75
|
+
something into what was typed. A filter written this way goes on meaning "the last hour"
|
|
76
|
+
whenever it is run, because the query it becomes holds `{ "$ago": "1h" }` rather than an
|
|
77
|
+
instant.
|
|
78
|
+
|
|
79
|
+
`has:` asks about the field rather than its value, so its value is a field name. A name the
|
|
80
|
+
vocabulary does not know falls through and is searched for as text, like any other.
|
|
81
|
+
|
|
82
|
+
A value that does not read as its kind — `score:high`, `certain:maybe` — matches nothing, as
|
|
83
|
+
does an empty set. A search box that widened while somebody was still typing would be lying
|
|
84
|
+
about what it found.
|
|
85
|
+
|
|
86
|
+
## Which names are fields
|
|
87
|
+
|
|
88
|
+
With a vocabulary, only its names and aliases are fields. Anything else before a colon is
|
|
89
|
+
searched as text, because a path, a URL or a User-Agent can contain a colon: `foo:bar` looks
|
|
90
|
+
for the text `foo:bar`.
|
|
91
|
+
|
|
92
|
+
Without a vocabulary there is nothing to check a name against, so any name that looks like a
|
|
93
|
+
path (`address.city:London`) is a field of kind `text` — except that a value written as an
|
|
94
|
+
explicit comparison (`age:>=30`, `age:30..40`) compares as a number, since nobody typing `>30`
|
|
95
|
+
means the characters. A bare `age:30` stays text. A URL then has to be quoted:
|
|
96
|
+
`"http://example.com"`. Pass `fields: "vocabulary"` or `fields: "any"` to choose either
|
|
97
|
+
behaviour explicitly.
|
|
98
|
+
|
|
99
|
+
A bare word searches the vocabulary's `text` fields when it names some, and the whole item
|
|
100
|
+
otherwise.
|
|
101
|
+
|
|
102
|
+
## Nothing typed is an error
|
|
103
|
+
|
|
104
|
+
`parseText` never throws. Half-written input is the normal state of a search box: an unclosed
|
|
105
|
+
bracket, a dangling `$or`, a `$in(` with nothing after it all parse to the best reading of what
|
|
106
|
+
is there. Input past 8 KB is cut, and brackets nested past 16 levels are ignored, so a hostile
|
|
107
|
+
link cannot overflow the stack of whoever opens it.
|
|
108
|
+
|
|
109
|
+
That is the opposite of the JSON engine, which refuses anything it does not understand — on
|
|
110
|
+
purpose. JSON is written by a program that can be told it is wrong; a search box is written by
|
|
111
|
+
a person who has not finished typing.
|
|
112
|
+
|
|
113
|
+
## Completion
|
|
114
|
+
|
|
115
|
+
`suggest(input, caret, vocabulary)` returns the completions for the token under the caret and
|
|
116
|
+
the span they replace. Field names come from the vocabulary; a field with a closed set of
|
|
117
|
+
`values` completes its values and offers `$in(` and `$notin(`; a token starting with `$`
|
|
118
|
+
completes to an operator. A field that takes anything gets no suggestions, because guessing
|
|
119
|
+
there would be inventing options rather than completing them.
|
|
120
|
+
|
|
121
|
+
## Writing a query back out
|
|
122
|
+
|
|
123
|
+
`toText` is the other direction, for a dashboard that stores filters as JSON and has to put
|
|
124
|
+
one back in the box when somebody opens it to edit:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const { text, complete, unexpressed } = toText(saved, { vocabulary });
|
|
128
|
+
box.value = text;
|
|
129
|
+
if (!complete) warn(`${unexpressed.length} part(s) of this filter cannot be shown here`);
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The text is **exact for what it says** — parsed back with the same vocabulary it means
|
|
133
|
+
precisely the clauses it carries — but it is not total, and the parts it cannot say are
|
|
134
|
+
returned rather than dropped quietly. Showing only the sayable half would be showing a filter
|
|
135
|
+
wider than the one that is running.
|
|
136
|
+
|
|
137
|
+
A few things have no spelling even though they look as if they should: a bare word cannot
|
|
138
|
+
begin with `-` or be an operator's name, because the parser strips quotes before it decides
|
|
139
|
+
what a word is; and a condition that cares about case cannot be written, because the box
|
|
140
|
+
never does.
|
|
141
|
+
|
|
142
|
+
## What the box cannot say
|
|
143
|
+
|
|
144
|
+
`$elemMatch`, `$size`, `$length`, `$glob` and `{ "$field": … }` have no spelling here. Each
|
|
145
|
+
would need a syntax of its own, and a search box that grew one per operator would stop being
|
|
146
|
+
something people can type without a manual. They are all reachable in the JSON, which is what
|
|
147
|
+
a saved filter stores anyway.
|
|
148
|
+
|
|
149
|
+
## Related
|
|
150
|
+
|
|
151
|
+
- [The specification](specification.md) — what the JSON each term becomes means
|
|
152
|
+
- [TypeScript](../guides/typescript.md#vocabularies) — defining a vocabulary
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Quick start
|
|
2
|
+
|
|
3
|
+
Install it, ask a question, and know where to go next.
|
|
4
|
+
|
|
5
|
+
← [Documentation](../index.md)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @osqd/jql
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## A query is JSON
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { filter, find } from "@osqd/jql";
|
|
17
|
+
|
|
18
|
+
const users = [
|
|
19
|
+
{ id: 1, name: "Ada", roles: ["admin"], address: { city: "London" } },
|
|
20
|
+
{ id: 2, name: "Grace", roles: ["editor"], address: { city: "New York" } },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
find(users, { id: 2 }); // Grace
|
|
24
|
+
filter(users, { roles: "admin" }); // [Ada] — a value matches any element
|
|
25
|
+
filter(users, { "address.city": { $startsWith: "New" } }); // [Grace]
|
|
26
|
+
filter(users, { $or: [{ id: 1 }, { name: { $contains: "gra", $options: "i" } }] });
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Because the query is plain data, the same object can be stored, put in a URL, sent to
|
|
30
|
+
another service, and it finds the same thing there. The [specification](../reference/specification.md)
|
|
31
|
+
says exactly what each operator means.
|
|
32
|
+
|
|
33
|
+
## Or a method on the array
|
|
34
|
+
|
|
35
|
+
The methods are opt-in, because patching a built-in is the application's decision:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import "@osqd/jql/global";
|
|
39
|
+
|
|
40
|
+
const arr = [{ id: 1 }, { id: 2 }];
|
|
41
|
+
const object2 = arr.jqlSearch({ id: 2 });
|
|
42
|
+
const same = Array.jqlSearch(arr, { id: 2 }); // any array, iterable, Set or Map
|
|
43
|
+
new Map([["a", { n: 1 }]]).jqlFilter({ n: 1 }); // a Map in, a Map out
|
|
44
|
+
[3, 8, 1].jqlFilter({ $gt: 2 }); // [3, 8] — a condition on the item itself
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The element type is inferred, so a field that does not exist is a compile error rather than a
|
|
48
|
+
filter that quietly matches nothing. See [TypeScript](../guides/typescript.md).
|
|
49
|
+
|
|
50
|
+
## Compile once in a loop
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { compile } from "@osqd/jql";
|
|
54
|
+
|
|
55
|
+
const isOpen = compile<Order>({ status: "open", total: { $gte: 100 } });
|
|
56
|
+
orders.filter(isOpen);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Every helper compiles the query it is given; `compile` lets you do that once and keep the
|
|
60
|
+
predicate. See [Performance](../design/performance.md).
|
|
61
|
+
|
|
62
|
+
## Sort, page and pick fields
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { search } from "@osqd/jql";
|
|
66
|
+
|
|
67
|
+
search(orders, { where: { status: "open" }, sort: { total: -1 }, skip: 20, limit: 20, fields: ["id", "total"] });
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Let people type
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { parseText } from "@osqd/jql/text";
|
|
74
|
+
|
|
75
|
+
orders.jqlFilter(parseText('status:open total:>100 -"test account"'));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The text becomes a JQL document; nothing about it is matched separately. See
|
|
79
|
+
[Text syntax](../reference/text-syntax.md).
|
|
80
|
+
|
|
81
|
+
## Related
|
|
82
|
+
|
|
83
|
+
- [The specification](../reference/specification.md) — every operator, precisely
|
|
84
|
+
- [Queries from outside](../guides/untrusted-input.md) — before you accept one from a URL
|
package/package.json
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@osqd/jql",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "JSON Query Language — one MongoDB-style query document for every place the OSQD projects filter data, with a zero-dependency TypeScript engine that compiles each query once into a plain predicate.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"query",
|
|
7
|
+
"json",
|
|
8
|
+
"filter",
|
|
9
|
+
"mongodb",
|
|
10
|
+
"search",
|
|
11
|
+
"predicate",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"author": "Michał Płatosz <platosz.michal@gmail.com>",
|
|
15
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/OSQD-ts/JQL.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/OSQD-ts/JQL#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/OSQD-ts/JQL/issues"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.cjs",
|
|
29
|
+
"module": "./dist/index.js",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"typesVersions": {
|
|
32
|
+
"*": {
|
|
33
|
+
"text": [
|
|
34
|
+
"./dist/text/index.d.ts"
|
|
35
|
+
],
|
|
36
|
+
"global": [
|
|
37
|
+
"./dist/global.d.ts"
|
|
38
|
+
],
|
|
39
|
+
"mongo": [
|
|
40
|
+
"./dist/targets/mongo.d.ts"
|
|
41
|
+
],
|
|
42
|
+
"cli": [
|
|
43
|
+
"./dist/cli.d.ts"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"exports": {
|
|
48
|
+
".": {
|
|
49
|
+
"import": {
|
|
50
|
+
"types": "./dist/index.d.ts",
|
|
51
|
+
"default": "./dist/index.js"
|
|
52
|
+
},
|
|
53
|
+
"require": {
|
|
54
|
+
"types": "./dist/cjs/index.d.ts",
|
|
55
|
+
"default": "./dist/index.cjs"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"./text": {
|
|
59
|
+
"import": {
|
|
60
|
+
"types": "./dist/text/index.d.ts",
|
|
61
|
+
"default": "./dist/text.js"
|
|
62
|
+
},
|
|
63
|
+
"require": {
|
|
64
|
+
"types": "./dist/cjs/text/index.d.ts",
|
|
65
|
+
"default": "./dist/text.cjs"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"./global": {
|
|
69
|
+
"import": {
|
|
70
|
+
"types": "./dist/global.d.ts",
|
|
71
|
+
"default": "./dist/global.js"
|
|
72
|
+
},
|
|
73
|
+
"require": {
|
|
74
|
+
"types": "./dist/cjs/global.d.ts",
|
|
75
|
+
"default": "./dist/global.cjs"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"./package.json": "./package.json",
|
|
79
|
+
"./mongo": {
|
|
80
|
+
"import": {
|
|
81
|
+
"types": "./dist/targets/mongo.d.ts",
|
|
82
|
+
"default": "./dist/mongo.js"
|
|
83
|
+
},
|
|
84
|
+
"require": {
|
|
85
|
+
"types": "./dist/cjs/targets/mongo.d.ts",
|
|
86
|
+
"default": "./dist/mongo.cjs"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"./cli": {
|
|
90
|
+
"types": "./dist/cli.d.ts",
|
|
91
|
+
"import": "./dist/cli.js"
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"sideEffects": [
|
|
95
|
+
"./dist/global.js",
|
|
96
|
+
"./dist/global.cjs"
|
|
97
|
+
],
|
|
98
|
+
"files": [
|
|
99
|
+
"dist",
|
|
100
|
+
"docs",
|
|
101
|
+
"conformance",
|
|
102
|
+
"bin",
|
|
103
|
+
"README.md",
|
|
104
|
+
"CHANGELOG.md",
|
|
105
|
+
"LICENSE"
|
|
106
|
+
],
|
|
107
|
+
"scripts": {
|
|
108
|
+
"check": "npm run typecheck && npm run lint && npm test && npm run docs:check",
|
|
109
|
+
"typecheck": "tsc -p tsconfig.typecheck.json",
|
|
110
|
+
"lint": "biome check .",
|
|
111
|
+
"format": "biome check --write .",
|
|
112
|
+
"test": "vitest run",
|
|
113
|
+
"test:watch": "vitest",
|
|
114
|
+
"docs:check": "node scripts/check-links.mjs",
|
|
115
|
+
"build": "tsup && tsc --emitDeclarationOnly && tsc -p tsconfig.cli.json && node scripts/cjs-types.mjs",
|
|
116
|
+
"build:watch": "tsup --watch",
|
|
117
|
+
"check:package": "npm run build && tsx scripts/check-package.ts",
|
|
118
|
+
"bench": "tsx --expose-gc scripts/bench.ts",
|
|
119
|
+
"bench:guard": "tsx scripts/bench-guard.ts",
|
|
120
|
+
"example": "tsx --tsconfig tsconfig.typecheck.json examples/basic.ts",
|
|
121
|
+
"prepack": "npm run build",
|
|
122
|
+
"prepublishOnly": "npm run build",
|
|
123
|
+
"cli": "tsx src/cli-run.ts"
|
|
124
|
+
},
|
|
125
|
+
"devDependencies": {
|
|
126
|
+
"@biomejs/biome": "^2.4.0",
|
|
127
|
+
"@types/node": "^26.3.0",
|
|
128
|
+
"tsup": "^8.5.1",
|
|
129
|
+
"tsx": "^4.23.12",
|
|
130
|
+
"typescript": "^5.9.3",
|
|
131
|
+
"vitest": "^4.1.11"
|
|
132
|
+
},
|
|
133
|
+
"bin": {
|
|
134
|
+
"jql": "./bin/jql.mjs"
|
|
135
|
+
}
|
|
136
|
+
}
|