@querykitjs/core 1.2.0 → 2.0.0
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/README.en.md +36 -0
- package/README.md +36 -0
- package/dist/chunk-NHNDPIPM.js +54 -0
- package/dist/chunk-NHNDPIPM.js.map +1 -0
- package/dist/chunk-VD7XT52J.cjs +72 -0
- package/dist/chunk-VD7XT52J.cjs.map +1 -0
- package/dist/index.cjs +67 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -173
- package/dist/index.d.ts +23 -173
- package/dist/index.js +4 -26
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +357 -0
- package/dist/internal.cjs.map +1 -0
- package/dist/internal.d.cts +249 -0
- package/dist/internal.d.ts +249 -0
- package/dist/internal.js +327 -0
- package/dist/internal.js.map +1 -0
- package/dist/raw-Bx8c-TrC.d.cts +290 -0
- package/dist/raw-Bx8c-TrC.d.ts +290 -0
- package/package.json +32 -6
- package/skills/querykit-core/SKILL.md +160 -0
package/README.en.md
CHANGED
|
@@ -17,6 +17,34 @@ You usually **don't install this directly** — it's the shared foundation used
|
|
|
17
17
|
- **`FilterScalar` / `FilterValue`**, **`SortDirection`**.
|
|
18
18
|
- **`createFilters<TKey, TRaw>()`** + **`f`** — ergonomic builder (eq/ne/…, contains/…, like/ilike/notLike, in/notIn, between, range, isNull/isNotNull, and/or/not).
|
|
19
19
|
- **Wire meta** (server response, snake_case) — `OffsetMeta`, `InfiniteMeta`, `CursorMeta`.
|
|
20
|
+
- **`Filterable`** and the skip / refusal reasons (`SkipReason`: `unknown-key`, `invalid-value`, `forbidden-key`, `forbidden-operator`, `limit-exceeded`, `empty-filter`; `SkipSite` + `page`, `mutation`, `with`) — policy reasons and an empty mutation filter are never dropped silently, always a `QueryKitError`.
|
|
21
|
+
- **`QueryKitTimeoutError`** (`code: "QUERYKIT_TIMEOUT"`) — a read ran past its time limit (mongoose `maxTimeMS`). Kept apart from `QueryKitError`: the request was valid, the database was slow — map it to 503/504.
|
|
22
|
+
- **`raw(value)`** — the brand for a driver's own filter object (a Prisma `where`, a Mongo filter) (R19). An adapter accepts a raw node only when it is branded with `raw()`; an unbranded plain object (it can come from a JSON body) → `QueryKitError` `forbidden-key`. ⚠️ A raw node is server code — `filterable` does not look inside it; never build one from request data.
|
|
23
|
+
- **Request limits** — `QueryLimits`, `DEFAULT_QUERY_LIMITS`, `resolveLimits(partial)` and one constant per limit (table below).
|
|
24
|
+
|
|
25
|
+
- **`@querykitjs/core/internal`** — **adapter and validator authors only**: cursor tokens, skip diagnostics, the per-call repository context, sort normalization, pagination metas, the limit walk (`findFilterLimitViolation`) and the request policy (`resolvePolicy`: `filterable` / `sortable` / `limits`) shared by every querykit package. Not application API; it may change in a minor release.
|
|
26
|
+
|
|
27
|
+
## Limits
|
|
28
|
+
|
|
29
|
+
Every filter and pagination request is bounded in size at parse time. `@querykitjs/zod` and `@querykitjs/class-validator` reject a payload past any limit; `@querykitjs/web` does not build a payload past the offset or sort limit.
|
|
30
|
+
|
|
31
|
+
| Limit | Constant | Default | What counts |
|
|
32
|
+
| ------------------ | ---------------------------- | -------- | --------------------------------------------------------------------------------------- |
|
|
33
|
+
| `maxDepth` | `DEFAULT_MAX_FILTER_DEPTH` | `5` | root-to-leaf nodes: the root is 1, every `and`/`or`/`not` and the condition add 1 |
|
|
34
|
+
| `maxConditions` | `DEFAULT_MAX_CONDITIONS` | `30` | `FieldCondition` leaves across all groups |
|
|
35
|
+
| `maxInItems` | `DEFAULT_MAX_IN_ITEMS` | `200` | items in one array value (`in`, `notIn`, …) |
|
|
36
|
+
| `maxStringLength` | `DEFAULT_MAX_STRING_LENGTH` | `256` | characters in one string value, also inside an array |
|
|
37
|
+
| `maxOffset` | `DEFAULT_MAX_OFFSET` | `10 000` | offset: `(page - 1) × perPage`; infinite: `offset`. Deeper — use a cursor |
|
|
38
|
+
| `maxSortFields` | `DEFAULT_MAX_SORT_FIELDS` | `3` | fields in the `sort` array |
|
|
39
|
+
| `maxLikeWildcards` | `DEFAULT_MAX_LIKE_WILDCARDS` | `2` | `%`/`_` in one `like`/`ilike`/`notLike` pattern (a run of `%%` is one) — adapter policy |
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { resolveLimits } from "@querykitjs/core";
|
|
43
|
+
|
|
44
|
+
resolveLimits({ maxInItems: 500 }); // the other five keep their defaults
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Raise a limit for one schema or DTO with its `limits` option; `Infinity` turns a limit off (⚠️ a DoS surface).
|
|
20
48
|
|
|
21
49
|
## Usage (inside an adapter)
|
|
22
50
|
|
|
@@ -30,6 +58,14 @@ const f = createFilters<"status" | "age", MyRawSql>();
|
|
|
30
58
|
f.and(f.eq("status", "active"), f.gte("age", 18));
|
|
31
59
|
```
|
|
32
60
|
|
|
61
|
+
### Requirements
|
|
62
|
+
|
|
63
|
+
| | Version | Tested (`bun run test:matrix`) |
|
|
64
|
+
| ------- | --------- | ------------------------------ |
|
|
65
|
+
| Node.js | `>=22.12` | 24 |
|
|
66
|
+
|
|
67
|
+
Node 20 is no longer supported (`engines`: `>=22.12`). Peer ranges cover the last two majors; both ends are tested.
|
|
68
|
+
|
|
33
69
|
## License
|
|
34
70
|
|
|
35
71
|
MIT © Suhrobbek Soatov
|
package/README.md
CHANGED
|
@@ -17,6 +17,34 @@ Bu paketni odatda **to'g'ridan-to'g'ri o'rnatmaysiz** — u `@querykitjs/drizzle
|
|
|
17
17
|
- **`FilterScalar` / `FilterValue`**, **`SortDirection`**.
|
|
18
18
|
- **`createFilters<TKey, TRaw>()`** + **`f`** — ergonomik builder (eq/ne/…, contains/…, like/ilike/notLike, in/notIn, between, range, isNull/isNotNull, and/or/not).
|
|
19
19
|
- **Wire meta** (server javobi, snake_case) — `OffsetMeta`, `InfiniteMeta`, `CursorMeta`.
|
|
20
|
+
- **`Filterable`** va skip/rad etish sabablari (`SkipReason`: `unknown-key`, `invalid-value`, `forbidden-key`, `forbidden-operator`, `limit-exceeded`, `empty-filter`; `SkipSite` + `page`, `mutation`, `with`) — siyosat sabablari va bo'sh mutatsiya filtri hech qachon jim tashlanmaydi, har doim `QueryKitError`.
|
|
21
|
+
- **`QueryKitTimeoutError`** (`code: "QUERYKIT_TIMEOUT"`) — o'qish vaqt chegarasidan oshdi (mongoose `maxTimeMS`). `QueryKitError`dan alohida: so'rov to'g'ri, baza sekin — 503/504 qiling.
|
|
22
|
+
- **`raw(value)`** — drayverning o'z filtr obyekti (Prisma `where`, Mongo filtri) uchun brend (R19). Adapter raw tugunni faqat `raw()` bilan belgilangan bo'lsa qabul qiladi; brendsiz oddiy obyekt (JSON body'dan kelishi mumkin) → `QueryKitError` `forbidden-key`. ⚠️ Raw tugun — server kodi, `filterable` uni tekshirmaydi; uni hech qachon so'rov ma'lumotidan qurmang.
|
|
23
|
+
- **So'rov limitlari** — `QueryLimits`, `DEFAULT_QUERY_LIMITS`, `resolveLimits(partial)` va alohida konstantalar (pastdagi jadval).
|
|
24
|
+
|
|
25
|
+
- **`@querykitjs/core/internal`** — **faqat adapter va validator yozuvchilar uchun**: cursor tokenlari, skip diagnostikasi, har chaqiruv uchun repository konteksti, sort normalizatsiyasi, pagination meta'lari, limit tekshiruvi (`findFilterLimitViolation`) va so'rov siyosati (`resolvePolicy`: `filterable` / `sortable` / `limits`) — hamma querykit paketlari uchun umumiy. Ilova API'si emas; minor relizda o'zgarishi mumkin.
|
|
26
|
+
|
|
27
|
+
## Limits
|
|
28
|
+
|
|
29
|
+
Har filtr va paginatsiya so'rovi parse paytida hajm bo'yicha chegaralanadi. `@querykitjs/zod` va `@querykitjs/class-validator` limitdan oshgan payload'ni rad etadi; `@querykitjs/web` offset va sort limitidan oshgan payload'ni yasamaydi.
|
|
30
|
+
|
|
31
|
+
| Limit | Konstanta | Default | Nima sanaladi |
|
|
32
|
+
| ------------------ | ---------------------------- | -------- | ------------------------------------------------------------------------------------------- |
|
|
33
|
+
| `maxDepth` | `DEFAULT_MAX_FILTER_DEPTH` | `5` | ildizdan bargacha tugunlar: ildiz 1, har `and`/`or`/`not` va shart +1 |
|
|
34
|
+
| `maxConditions` | `DEFAULT_MAX_CONDITIONS` | `30` | barcha guruhlardagi `FieldCondition` barglari |
|
|
35
|
+
| `maxInItems` | `DEFAULT_MAX_IN_ITEMS` | `200` | bitta massiv qiymatdagi elementlar (`in`, `notIn`, …) |
|
|
36
|
+
| `maxStringLength` | `DEFAULT_MAX_STRING_LENGTH` | `256` | bitta satr qiymatdagi belgilar (massiv ichida ham) |
|
|
37
|
+
| `maxOffset` | `DEFAULT_MAX_OFFSET` | `10 000` | offset: `(page - 1) × perPage`; infinite: `offset`. Chuqurrog'i — cursor |
|
|
38
|
+
| `maxSortFields` | `DEFAULT_MAX_SORT_FIELDS` | `3` | `sort` massividagi maydonlar |
|
|
39
|
+
| `maxLikeWildcards` | `DEFAULT_MAX_LIKE_WILDCARDS` | `2` | bitta `like`/`ilike`/`notLike` naqshidagi `%`/`_` (ketma-ket `%%` bitta) — adapter siyosati |
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { resolveLimits } from "@querykitjs/core";
|
|
43
|
+
|
|
44
|
+
resolveLimits({ maxInItems: 500 }); // qolgan beshtasi — default
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Limitni bitta schema/DTO uchun `limits` opsiyasi bilan oshiring; `Infinity` limitni o'chiradi (⚠️ DoS yuzasi).
|
|
20
48
|
|
|
21
49
|
## Foydalanish (adapter ichida)
|
|
22
50
|
|
|
@@ -30,6 +58,14 @@ const f = createFilters<"status" | "age", MyRawSql>();
|
|
|
30
58
|
f.and(f.eq("status", "active"), f.gte("age", 18));
|
|
31
59
|
```
|
|
32
60
|
|
|
61
|
+
### Talablar
|
|
62
|
+
|
|
63
|
+
| | Versiya | Tekshiriladi (`bun run test:matrix`) |
|
|
64
|
+
| ------- | --------- | ------------------------------------ |
|
|
65
|
+
| Node.js | `>=22.12` | 24 |
|
|
66
|
+
|
|
67
|
+
Node 20 endi qo'llab-quvvatlanmaydi (`engines`: `>=22.12`). Peer diapazoni — oxirgi ikki major; ikkala cheti testda.
|
|
68
|
+
|
|
33
69
|
## Litsenziya
|
|
34
70
|
|
|
35
71
|
MIT © Suhrobbek Soatov
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/defaults.ts
|
|
6
|
+
var DEFAULT_PER_PAGE = 20, DEFAULT_LIMIT = 20, DEFAULT_MAX_PER_PAGE = 200, DEFAULT_MAX_LIMIT = 200, DEFAULT_MAX_FILTER_DEPTH = 5, DEFAULT_MAX_CONDITIONS = 30, DEFAULT_MAX_IN_ITEMS = 200, DEFAULT_MAX_STRING_LENGTH = 256, DEFAULT_MAX_OFFSET = 1e4, DEFAULT_MAX_SORT_FIELDS = 3, DEFAULT_MAX_LIKE_WILDCARDS = 2, DEFAULT_QUERY_LIMITS = Object.freeze({
|
|
7
|
+
maxDepth: 5,
|
|
8
|
+
maxConditions: 30,
|
|
9
|
+
maxInItems: 200,
|
|
10
|
+
maxStringLength: 256,
|
|
11
|
+
maxOffset: 1e4,
|
|
12
|
+
maxSortFields: 3,
|
|
13
|
+
maxLikeWildcards: 2
|
|
14
|
+
});
|
|
15
|
+
function resolveLimits(limits = {}) {
|
|
16
|
+
let resolved = { ...DEFAULT_QUERY_LIMITS };
|
|
17
|
+
for (let name of Object.keys(DEFAULT_QUERY_LIMITS)) {
|
|
18
|
+
let value = limits[name];
|
|
19
|
+
value !== void 0 && (resolved[name] = value);
|
|
20
|
+
}
|
|
21
|
+
return resolved;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/raw.ts
|
|
25
|
+
var RAW = /* @__PURE__ */ Symbol.for("querykit.raw");
|
|
26
|
+
function raw(value) {
|
|
27
|
+
return Object.defineProperty(value, RAW, { value: true, enumerable: false }), value;
|
|
28
|
+
}
|
|
29
|
+
var isRaw = (node) => typeof node == "object" && node !== null && node[RAW] === true;
|
|
30
|
+
|
|
31
|
+
// src/errors.ts
|
|
32
|
+
var QueryKitError = class extends Error {
|
|
33
|
+
constructor(info) {
|
|
34
|
+
super(`querykit: ${info.reason} \u2014 "${info.key}" (${info.site}) on "${info.source}".`);
|
|
35
|
+
/** Barqaror kod — `instanceof` ishlamaydigan chegaralarda (RPC, worker) tekshirish uchun. */
|
|
36
|
+
__publicField(this, "code", "QUERYKIT_INVALID_CONDITION");
|
|
37
|
+
/** Tashlab yuborilgan shart haqida to'liq ma'lumot (hook argumenti bilan bir xil shakl). */
|
|
38
|
+
__publicField(this, "info");
|
|
39
|
+
this.name = "QueryKitError", this.info = info;
|
|
40
|
+
}
|
|
41
|
+
}, QueryKitTimeoutError = class extends Error {
|
|
42
|
+
constructor(source, maxTimeMS, options) {
|
|
43
|
+
super(`querykit: a read on "${source}" ran past maxTimeMS (${maxTimeMS} ms).`, options);
|
|
44
|
+
__publicField(this, "source", source);
|
|
45
|
+
__publicField(this, "maxTimeMS", maxTimeMS);
|
|
46
|
+
/** Stable code for boundaries where `instanceof` does not work. */
|
|
47
|
+
__publicField(this, "code", "QUERYKIT_TIMEOUT");
|
|
48
|
+
this.name = "QueryKitTimeoutError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { DEFAULT_LIMIT, DEFAULT_MAX_CONDITIONS, DEFAULT_MAX_FILTER_DEPTH, DEFAULT_MAX_IN_ITEMS, DEFAULT_MAX_LIKE_WILDCARDS, DEFAULT_MAX_LIMIT, DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_MAX_STRING_LENGTH, DEFAULT_PER_PAGE, DEFAULT_QUERY_LIMITS, QueryKitError, QueryKitTimeoutError, isRaw, raw, resolveLimits };
|
|
53
|
+
//# sourceMappingURL=chunk-NHNDPIPM.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-NHNDPIPM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/defaults.ts","../src/raw.ts","../src/errors.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,gBAAA,GAAmB,EAAA,CAAA,CAGnB,aAAA,GAAgB,EAAA,CAAA,CAOhB,oBAAA,GAAuB,KAGvB,iBAAA,GAAoB,GAAA,CAAA,CASpB,wBAAA,GAA2B,CAAA,CAAA,CAG3B,sBAAA,GAAyB,EAAA,CAAA,CAGzB,uBAAuB,GAAA,CAAA,CAGvB,yBAAA,GAA4B,GAAA,CAAA,CAG5B,kBAAA,GAAqB,GAAA,CAAA,CAGrB,uBAAA,GAA0B,GAO1B,0BAAA,GAA6B,CAAA,CAAA,CAc7B,oBAAA,GAA8C,MAAA,CAAO,MAAA,CAAO;AAAA,EACvE,QAAA,EAAU,CAAA;AAAA,EACV,aAAA,EAAe,EAAA;AAAA,EACf,UAAA,EAAY,GAAA;AAAA,EACZ,eAAA,EAAiB,GAAA;AAAA,EACjB,SAAA,EAAW,GAAA;AAAA,EACX,aAAA,EAAe,CAAA;AAAA,EACf,gBAAA,EAAkB;AACpB,CAAC;AAWM,SAAS,aAAA,CAAc,MAAA,GAA+B,EAAC,EAAgB;AAC5E,EAAA,IAAM,QAAA,GAAW,EAAE,GAAG,oBAAA,EAAqB;AAC3C,EAAA,KAAA,IAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,oBAAoB,CAAA,EAA4B;AAC7E,IAAA,IAAM,KAAA,GAAQ,OAAO,IAAI,CAAA;AACzB,IAAI,KAAA,KAAU,MAAA,KAAW,QAAA,CAAS,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,QAAA;AACT;;;AClFA,IAAM,GAAA,mBAAM,MAAA,CAAO,GAAA,CAAI,cAAc,CAAA;AAa9B,SAAS,IAAsB,KAAA,EAAa;AACjD,EAAA,OAAA,MAAA,CAAO,cAAA,CAAe,OAAO,GAAA,EAAK,EAAE,OAAO,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,CAAA,EAC7D,KAAA;AACT;AAGO,IAAM,KAAA,GAAQ,CAAC,IAAA,KAA2B,OAAO,IAAA,IAAS,YAAY,IAAA,KAAS,IAAA,IAAS,IAAA,CAAiC,GAAG,CAAA,KAAM;;;ACRlI,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EAOvC,YAAY,IAAA,EAAwB;AAClC,IAAA,KAAA,CAAM,CAAA,UAAA,EAAa,IAAA,CAAK,MAAM,CAAA,SAAA,EAAO,IAAA,CAAK,GAAG,CAAA,GAAA,EAAM,IAAA,CAAK,IAAI,CAAA,MAAA,EAAS,IAAA,CAAK,MAAM,CAAA,EAAA,CAAI,CAAA;AANtF;AAAA,IAAA,aAAA,CAAA,IAAA,EAAS,MAAA,EAAO,4BAAA,CAAA;AAGhB;AAAA,IAAA,aAAA,CAAA,IAAA,EAAS,MAAA,CAAA;AAIP,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA,EACZ,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF,CAAA,CAAA,CAOa,oBAAA,GAAN,cAAmC,KAAA,CAAM;AAAA,EAI9C,WAAA,CAEW,MAAA,EAEA,SAAA,EACT,OAAA,EACA;AACA,IAAA,KAAA,CAAM,CAAA,qBAAA,EAAwB,MAAM,CAAA,sBAAA,EAAyB,SAAS,SAAS,OAAO,CAAA;AAL7E,IAAA,aAAA,CAAA,IAAA,EAAA,QAAA,EAAA,MAAA,CAAA;AAEA,IAAA,aAAA,CAAA,IAAA,EAAA,WAAA,EAAA,SAAA,CAAA;AANX;AAAA,IAAA,aAAA,CAAA,IAAA,EAAS,MAAA,EAAO,kBAAA,CAAA;AAUd,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,EACd;AACF","file":"chunk-NHNDPIPM.js","sourcesContent":["/**\n * Umumiy pagination default'lari — yagona manba. Backend adapter (`createRegistry`\n * options) va frontend (`createQuery` config) shu qiymatlarni fallback sifatida\n * ishlatadi, shuning uchun ular hech qachon bir-biridan farq qilmaydi.\n */\n\n/** Offset (list) sahifa o'lchami default'i. */\nexport const DEFAULT_PER_PAGE = 20;\n\n/** Infinite/cursor `limit` default'i. */\nexport const DEFAULT_LIMIT = 20;\n\n/**\n * `perPage` uchun yuqori chegara — cap'siz paginatsiya DoS yuzasi. Validatsiya\n * (`@querykitjs/zod` factory'lari), backend repositorylari va frontend `createQuery`\n * shu bitta qiymatga tayanadi, shuning uchun ular hech qachon farq qilmaydi.\n */\nexport const DEFAULT_MAX_PER_PAGE = 200;\n\n/** Infinite/cursor `limit` uchun yuqori chegara. Qarang: {@link DEFAULT_MAX_PER_PAGE}. */\nexport const DEFAULT_MAX_LIMIT = 200;\n\n/* ----------------------------- request limits ------------------------------ */\n/* Parse-time size limits for every filter and pagination request. The\n * validators (`@querykitjs/zod`, `@querykitjs/class-validator`) reject a payload\n * past any of them; `@querykitjs/web` refuses to build one past the offset or\n * sort limit. Raise one per schema/DTO with `limits`, never globally. */\n\n/** Longest root-to-leaf path of a filter tree, in nodes: the root is level 1, every `and`/`or`/`not` and the condition itself add one. */\nexport const DEFAULT_MAX_FILTER_DEPTH = 5;\n\n/** Field conditions (leaves) in one filter, across all groups. */\nexport const DEFAULT_MAX_CONDITIONS = 30;\n\n/** Items in one array filter value (`in`, `notIn`, …). */\nexport const DEFAULT_MAX_IN_ITEMS = 200;\n\n/** Characters in one string filter value, also inside an array value. */\nexport const DEFAULT_MAX_STRING_LENGTH = 256;\n\n/** Rows skipped before a page: `(page - 1) × perPage` for offset pagination, `offset` for infinite. Deeper pages need a cursor. */\nexport const DEFAULT_MAX_OFFSET = 10_000;\n\n/** Fields in one `sort` array. */\nexport const DEFAULT_MAX_SORT_FIELDS = 3;\n\n/**\n * Wildcards (`%`, `_`) in one `like` / `ilike` / `notLike` pattern, after a run\n * of `%` counts as one. Each extra wildcard multiplies the matcher's backtracking\n * (`%a%a%a…%b`), on MongoDB's regex engine and on Postgres alike.\n */\nexport const DEFAULT_MAX_LIKE_WILDCARDS = 2;\n\n/** The six request limits, by the option name every package uses. */\nexport interface QueryLimits {\n maxDepth: number;\n maxConditions: number;\n maxInItems: number;\n maxStringLength: number;\n maxOffset: number;\n maxSortFields: number;\n maxLikeWildcards: number;\n}\n\n/** The core defaults as one object. */\nexport const DEFAULT_QUERY_LIMITS: Readonly<QueryLimits> = Object.freeze({\n maxDepth: DEFAULT_MAX_FILTER_DEPTH,\n maxConditions: DEFAULT_MAX_CONDITIONS,\n maxInItems: DEFAULT_MAX_IN_ITEMS,\n maxStringLength: DEFAULT_MAX_STRING_LENGTH,\n maxOffset: DEFAULT_MAX_OFFSET,\n maxSortFields: DEFAULT_MAX_SORT_FIELDS,\n maxLikeWildcards: DEFAULT_MAX_LIKE_WILDCARDS,\n});\n\n/**\n * The defaults with the given limits on top; an `undefined` entry keeps the\n * default. `Infinity` turns a limit off (⚠️ a DoS surface).\n *\n * @example\n * ```ts\n * resolveLimits({ maxInItems: 50 }); // { maxDepth: 5, …, maxInItems: 50, … }\n * ```\n */\nexport function resolveLimits(limits: Partial<QueryLimits> = {}): QueryLimits {\n const resolved = { ...DEFAULT_QUERY_LIMITS };\n for (const name of Object.keys(DEFAULT_QUERY_LIMITS) as (keyof QueryLimits)[]) {\n const value = limits[name];\n if (value !== undefined) resolved[name] = value;\n }\n return resolved;\n}\n","/**\n * The branded raw-filter escape hatch (REQUIREMENTS R19). A driver's own `where`\n * object (Prisma `where`, Mongo filter) is accepted inside a querykit filter only\n * when server code wraps it in `raw(...)`: the brand is a `Symbol`, which no JSON\n * body can carry. An unbranded plain object is refused (`forbidden-key`).\n *\n * ⚠️ A raw node is server code — the `filterable` policy does **not** look inside it.\n * Never build one from request data.\n */\nconst RAW = Symbol.for(\"querykit.raw\");\n\n/**\n * Brand a driver-native filter object so an adapter accepts it as a filter node.\n * The object itself is returned (non-enumerable brand), so the driver receives\n * exactly what you wrote.\n *\n * @example\n * ```ts\n * import { raw } from \"@querykitjs/core\";\n * repo.findAll({ filter: { and: [{ key: \"status\", value: \"active\" }, raw({ posts: { some: { published: true } } })] } });\n * ```\n */\nexport function raw<T extends object>(value: T): T {\n Object.defineProperty(value, RAW, { value: true, enumerable: false });\n return value;\n}\n\n/** Whether a filter node was branded with {@link raw}. */\nexport const isRaw = (node: unknown): boolean => typeof node === \"object\" && node !== null && (node as Record<symbol, unknown>)[RAW] === true;\n","/**\n * querykit xatolari. Backend adapterlari (`drizzle-pg`, `mongoose`) `strict`\n * rejimda shu bitta klassni tashlaydi — ya'ni ikkala backend uchun xatoni\n * ushlash usuli bir xil.\n */\nimport type { SkippedCondition } from \"./types\";\n\n/**\n * `strict` rejimda noto'g'ri so'rov shartida tashlanadi (noma'lum kalit yoki\n * operatorga mos kelmagan qiymat). Backend'da 400 qilib qaytarish uchun:\n *\n * ```ts\n * try {\n * return await usersRepository.findList(params);\n * } catch (err) {\n * if (err instanceof QueryKitError) return c.json({ error: err.message }, 400);\n * throw err;\n * }\n * ```\n */\nexport class QueryKitError extends Error {\n /** Barqaror kod — `instanceof` ishlamaydigan chegaralarda (RPC, worker) tekshirish uchun. */\n readonly code = \"QUERYKIT_INVALID_CONDITION\";\n\n /** Tashlab yuborilgan shart haqida to'liq ma'lumot (hook argumenti bilan bir xil shakl). */\n readonly info: SkippedCondition;\n\n constructor(info: SkippedCondition) {\n super(`querykit: ${info.reason} — \"${info.key}\" (${info.site}) on \"${info.source}\".`);\n this.name = \"QueryKitError\";\n this.info = info;\n }\n}\n\n/**\n * A read ran past its time limit (`maxTimeMS` on MongoDB). Kept apart from\n * {@link QueryKitError}: the request was valid, the database was slow — map it to\n * 503 / 504, not 400.\n */\nexport class QueryKitTimeoutError extends Error {\n /** Stable code for boundaries where `instanceof` does not work. */\n readonly code = \"QUERYKIT_TIMEOUT\";\n\n constructor(\n /** Collection / model name. */\n readonly source: string,\n /** The limit that was hit, in milliseconds. */\n readonly maxTimeMS: number,\n options?: { cause?: unknown },\n ) {\n super(`querykit: a read on \"${source}\" ran past maxTimeMS (${maxTimeMS} ms).`, options);\n this.name = \"QueryKitTimeoutError\";\n }\n}\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
|
|
6
|
+
|
|
7
|
+
// src/defaults.ts
|
|
8
|
+
var DEFAULT_PER_PAGE = 20, DEFAULT_LIMIT = 20, DEFAULT_MAX_PER_PAGE = 200, DEFAULT_MAX_LIMIT = 200, DEFAULT_MAX_FILTER_DEPTH = 5, DEFAULT_MAX_CONDITIONS = 30, DEFAULT_MAX_IN_ITEMS = 200, DEFAULT_MAX_STRING_LENGTH = 256, DEFAULT_MAX_OFFSET = 1e4, DEFAULT_MAX_SORT_FIELDS = 3, DEFAULT_MAX_LIKE_WILDCARDS = 2, DEFAULT_QUERY_LIMITS = Object.freeze({
|
|
9
|
+
maxDepth: 5,
|
|
10
|
+
maxConditions: 30,
|
|
11
|
+
maxInItems: 200,
|
|
12
|
+
maxStringLength: 256,
|
|
13
|
+
maxOffset: 1e4,
|
|
14
|
+
maxSortFields: 3,
|
|
15
|
+
maxLikeWildcards: 2
|
|
16
|
+
});
|
|
17
|
+
function resolveLimits(limits = {}) {
|
|
18
|
+
let resolved = { ...DEFAULT_QUERY_LIMITS };
|
|
19
|
+
for (let name of Object.keys(DEFAULT_QUERY_LIMITS)) {
|
|
20
|
+
let value = limits[name];
|
|
21
|
+
value !== void 0 && (resolved[name] = value);
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/raw.ts
|
|
27
|
+
var RAW = /* @__PURE__ */ Symbol.for("querykit.raw");
|
|
28
|
+
function raw(value) {
|
|
29
|
+
return Object.defineProperty(value, RAW, { value: true, enumerable: false }), value;
|
|
30
|
+
}
|
|
31
|
+
var isRaw = (node) => typeof node == "object" && node !== null && node[RAW] === true;
|
|
32
|
+
|
|
33
|
+
// src/errors.ts
|
|
34
|
+
var QueryKitError = class extends Error {
|
|
35
|
+
constructor(info) {
|
|
36
|
+
super(`querykit: ${info.reason} \u2014 "${info.key}" (${info.site}) on "${info.source}".`);
|
|
37
|
+
/** Barqaror kod — `instanceof` ishlamaydigan chegaralarda (RPC, worker) tekshirish uchun. */
|
|
38
|
+
__publicField(this, "code", "QUERYKIT_INVALID_CONDITION");
|
|
39
|
+
/** Tashlab yuborilgan shart haqida to'liq ma'lumot (hook argumenti bilan bir xil shakl). */
|
|
40
|
+
__publicField(this, "info");
|
|
41
|
+
this.name = "QueryKitError", this.info = info;
|
|
42
|
+
}
|
|
43
|
+
}, QueryKitTimeoutError = class extends Error {
|
|
44
|
+
constructor(source, maxTimeMS, options) {
|
|
45
|
+
super(`querykit: a read on "${source}" ran past maxTimeMS (${maxTimeMS} ms).`, options);
|
|
46
|
+
__publicField(this, "source", source);
|
|
47
|
+
__publicField(this, "maxTimeMS", maxTimeMS);
|
|
48
|
+
/** Stable code for boundaries where `instanceof` does not work. */
|
|
49
|
+
__publicField(this, "code", "QUERYKIT_TIMEOUT");
|
|
50
|
+
this.name = "QueryKitTimeoutError";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
exports.DEFAULT_LIMIT = DEFAULT_LIMIT;
|
|
55
|
+
exports.DEFAULT_MAX_CONDITIONS = DEFAULT_MAX_CONDITIONS;
|
|
56
|
+
exports.DEFAULT_MAX_FILTER_DEPTH = DEFAULT_MAX_FILTER_DEPTH;
|
|
57
|
+
exports.DEFAULT_MAX_IN_ITEMS = DEFAULT_MAX_IN_ITEMS;
|
|
58
|
+
exports.DEFAULT_MAX_LIKE_WILDCARDS = DEFAULT_MAX_LIKE_WILDCARDS;
|
|
59
|
+
exports.DEFAULT_MAX_LIMIT = DEFAULT_MAX_LIMIT;
|
|
60
|
+
exports.DEFAULT_MAX_OFFSET = DEFAULT_MAX_OFFSET;
|
|
61
|
+
exports.DEFAULT_MAX_PER_PAGE = DEFAULT_MAX_PER_PAGE;
|
|
62
|
+
exports.DEFAULT_MAX_SORT_FIELDS = DEFAULT_MAX_SORT_FIELDS;
|
|
63
|
+
exports.DEFAULT_MAX_STRING_LENGTH = DEFAULT_MAX_STRING_LENGTH;
|
|
64
|
+
exports.DEFAULT_PER_PAGE = DEFAULT_PER_PAGE;
|
|
65
|
+
exports.DEFAULT_QUERY_LIMITS = DEFAULT_QUERY_LIMITS;
|
|
66
|
+
exports.QueryKitError = QueryKitError;
|
|
67
|
+
exports.QueryKitTimeoutError = QueryKitTimeoutError;
|
|
68
|
+
exports.isRaw = isRaw;
|
|
69
|
+
exports.raw = raw;
|
|
70
|
+
exports.resolveLimits = resolveLimits;
|
|
71
|
+
//# sourceMappingURL=chunk-VD7XT52J.cjs.map
|
|
72
|
+
//# sourceMappingURL=chunk-VD7XT52J.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/defaults.ts","../src/raw.ts","../src/errors.ts"],"names":[],"mappings":";;;;;;;AAOO,IAAM,gBAAA,GAAmB,EAAA,CAAA,CAGnB,aAAA,GAAgB,EAAA,CAAA,CAOhB,oBAAA,GAAuB,KAGvB,iBAAA,GAAoB,GAAA,CAAA,CASpB,wBAAA,GAA2B,CAAA,CAAA,CAG3B,sBAAA,GAAyB,EAAA,CAAA,CAGzB,uBAAuB,GAAA,CAAA,CAGvB,yBAAA,GAA4B,GAAA,CAAA,CAG5B,kBAAA,GAAqB,GAAA,CAAA,CAGrB,uBAAA,GAA0B,GAO1B,0BAAA,GAA6B,CAAA,CAAA,CAc7B,oBAAA,GAA8C,MAAA,CAAO,MAAA,CAAO;AAAA,EACvE,QAAA,EAAU,CAAA;AAAA,EACV,aAAA,EAAe,EAAA;AAAA,EACf,UAAA,EAAY,GAAA;AAAA,EACZ,eAAA,EAAiB,GAAA;AAAA,EACjB,SAAA,EAAW,GAAA;AAAA,EACX,aAAA,EAAe,CAAA;AAAA,EACf,gBAAA,EAAkB;AACpB,CAAC;AAWM,SAAS,aAAA,CAAc,MAAA,GAA+B,EAAC,EAAgB;AAC5E,EAAA,IAAM,QAAA,GAAW,EAAE,GAAG,oBAAA,EAAqB;AAC3C,EAAA,KAAA,IAAW,IAAA,IAAQ,MAAA,CAAO,IAAA,CAAK,oBAAoB,CAAA,EAA4B;AAC7E,IAAA,IAAM,KAAA,GAAQ,OAAO,IAAI,CAAA;AACzB,IAAI,KAAA,KAAU,MAAA,KAAW,QAAA,CAAS,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,QAAA;AACT;;;AClFA,IAAM,GAAA,mBAAM,MAAA,CAAO,GAAA,CAAI,cAAc,CAAA;AAa9B,SAAS,IAAsB,KAAA,EAAa;AACjD,EAAA,OAAA,MAAA,CAAO,cAAA,CAAe,OAAO,GAAA,EAAK,EAAE,OAAO,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,CAAA,EAC7D,KAAA;AACT;AAGO,IAAM,KAAA,GAAQ,CAAC,IAAA,KAA2B,OAAO,IAAA,IAAS,YAAY,IAAA,KAAS,IAAA,IAAS,IAAA,CAAiC,GAAG,CAAA,KAAM;;;ACRlI,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EAOvC,YAAY,IAAA,EAAwB;AAClC,IAAA,KAAA,CAAM,CAAA,UAAA,EAAa,IAAA,CAAK,MAAM,CAAA,SAAA,EAAO,IAAA,CAAK,GAAG,CAAA,GAAA,EAAM,IAAA,CAAK,IAAI,CAAA,MAAA,EAAS,IAAA,CAAK,MAAM,CAAA,EAAA,CAAI,CAAA;AANtF;AAAA,IAAA,aAAA,CAAA,IAAA,EAAS,MAAA,EAAO,4BAAA,CAAA;AAGhB;AAAA,IAAA,aAAA,CAAA,IAAA,EAAS,MAAA,CAAA;AAIP,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA,EACZ,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AACF,CAAA,CAAA,CAOa,oBAAA,GAAN,cAAmC,KAAA,CAAM;AAAA,EAI9C,WAAA,CAEW,MAAA,EAEA,SAAA,EACT,OAAA,EACA;AACA,IAAA,KAAA,CAAM,CAAA,qBAAA,EAAwB,MAAM,CAAA,sBAAA,EAAyB,SAAS,SAAS,OAAO,CAAA;AAL7E,IAAA,aAAA,CAAA,IAAA,EAAA,QAAA,EAAA,MAAA,CAAA;AAEA,IAAA,aAAA,CAAA,IAAA,EAAA,WAAA,EAAA,SAAA,CAAA;AANX;AAAA,IAAA,aAAA,CAAA,IAAA,EAAS,MAAA,EAAO,kBAAA,CAAA;AAUd,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AAAA,EACd;AACF","file":"chunk-VD7XT52J.cjs","sourcesContent":["/**\n * Umumiy pagination default'lari — yagona manba. Backend adapter (`createRegistry`\n * options) va frontend (`createQuery` config) shu qiymatlarni fallback sifatida\n * ishlatadi, shuning uchun ular hech qachon bir-biridan farq qilmaydi.\n */\n\n/** Offset (list) sahifa o'lchami default'i. */\nexport const DEFAULT_PER_PAGE = 20;\n\n/** Infinite/cursor `limit` default'i. */\nexport const DEFAULT_LIMIT = 20;\n\n/**\n * `perPage` uchun yuqori chegara — cap'siz paginatsiya DoS yuzasi. Validatsiya\n * (`@querykitjs/zod` factory'lari), backend repositorylari va frontend `createQuery`\n * shu bitta qiymatga tayanadi, shuning uchun ular hech qachon farq qilmaydi.\n */\nexport const DEFAULT_MAX_PER_PAGE = 200;\n\n/** Infinite/cursor `limit` uchun yuqori chegara. Qarang: {@link DEFAULT_MAX_PER_PAGE}. */\nexport const DEFAULT_MAX_LIMIT = 200;\n\n/* ----------------------------- request limits ------------------------------ */\n/* Parse-time size limits for every filter and pagination request. The\n * validators (`@querykitjs/zod`, `@querykitjs/class-validator`) reject a payload\n * past any of them; `@querykitjs/web` refuses to build one past the offset or\n * sort limit. Raise one per schema/DTO with `limits`, never globally. */\n\n/** Longest root-to-leaf path of a filter tree, in nodes: the root is level 1, every `and`/`or`/`not` and the condition itself add one. */\nexport const DEFAULT_MAX_FILTER_DEPTH = 5;\n\n/** Field conditions (leaves) in one filter, across all groups. */\nexport const DEFAULT_MAX_CONDITIONS = 30;\n\n/** Items in one array filter value (`in`, `notIn`, …). */\nexport const DEFAULT_MAX_IN_ITEMS = 200;\n\n/** Characters in one string filter value, also inside an array value. */\nexport const DEFAULT_MAX_STRING_LENGTH = 256;\n\n/** Rows skipped before a page: `(page - 1) × perPage` for offset pagination, `offset` for infinite. Deeper pages need a cursor. */\nexport const DEFAULT_MAX_OFFSET = 10_000;\n\n/** Fields in one `sort` array. */\nexport const DEFAULT_MAX_SORT_FIELDS = 3;\n\n/**\n * Wildcards (`%`, `_`) in one `like` / `ilike` / `notLike` pattern, after a run\n * of `%` counts as one. Each extra wildcard multiplies the matcher's backtracking\n * (`%a%a%a…%b`), on MongoDB's regex engine and on Postgres alike.\n */\nexport const DEFAULT_MAX_LIKE_WILDCARDS = 2;\n\n/** The six request limits, by the option name every package uses. */\nexport interface QueryLimits {\n maxDepth: number;\n maxConditions: number;\n maxInItems: number;\n maxStringLength: number;\n maxOffset: number;\n maxSortFields: number;\n maxLikeWildcards: number;\n}\n\n/** The core defaults as one object. */\nexport const DEFAULT_QUERY_LIMITS: Readonly<QueryLimits> = Object.freeze({\n maxDepth: DEFAULT_MAX_FILTER_DEPTH,\n maxConditions: DEFAULT_MAX_CONDITIONS,\n maxInItems: DEFAULT_MAX_IN_ITEMS,\n maxStringLength: DEFAULT_MAX_STRING_LENGTH,\n maxOffset: DEFAULT_MAX_OFFSET,\n maxSortFields: DEFAULT_MAX_SORT_FIELDS,\n maxLikeWildcards: DEFAULT_MAX_LIKE_WILDCARDS,\n});\n\n/**\n * The defaults with the given limits on top; an `undefined` entry keeps the\n * default. `Infinity` turns a limit off (⚠️ a DoS surface).\n *\n * @example\n * ```ts\n * resolveLimits({ maxInItems: 50 }); // { maxDepth: 5, …, maxInItems: 50, … }\n * ```\n */\nexport function resolveLimits(limits: Partial<QueryLimits> = {}): QueryLimits {\n const resolved = { ...DEFAULT_QUERY_LIMITS };\n for (const name of Object.keys(DEFAULT_QUERY_LIMITS) as (keyof QueryLimits)[]) {\n const value = limits[name];\n if (value !== undefined) resolved[name] = value;\n }\n return resolved;\n}\n","/**\n * The branded raw-filter escape hatch (REQUIREMENTS R19). A driver's own `where`\n * object (Prisma `where`, Mongo filter) is accepted inside a querykit filter only\n * when server code wraps it in `raw(...)`: the brand is a `Symbol`, which no JSON\n * body can carry. An unbranded plain object is refused (`forbidden-key`).\n *\n * ⚠️ A raw node is server code — the `filterable` policy does **not** look inside it.\n * Never build one from request data.\n */\nconst RAW = Symbol.for(\"querykit.raw\");\n\n/**\n * Brand a driver-native filter object so an adapter accepts it as a filter node.\n * The object itself is returned (non-enumerable brand), so the driver receives\n * exactly what you wrote.\n *\n * @example\n * ```ts\n * import { raw } from \"@querykitjs/core\";\n * repo.findAll({ filter: { and: [{ key: \"status\", value: \"active\" }, raw({ posts: { some: { published: true } } })] } });\n * ```\n */\nexport function raw<T extends object>(value: T): T {\n Object.defineProperty(value, RAW, { value: true, enumerable: false });\n return value;\n}\n\n/** Whether a filter node was branded with {@link raw}. */\nexport const isRaw = (node: unknown): boolean => typeof node === \"object\" && node !== null && (node as Record<symbol, unknown>)[RAW] === true;\n","/**\n * querykit xatolari. Backend adapterlari (`drizzle-pg`, `mongoose`) `strict`\n * rejimda shu bitta klassni tashlaydi — ya'ni ikkala backend uchun xatoni\n * ushlash usuli bir xil.\n */\nimport type { SkippedCondition } from \"./types\";\n\n/**\n * `strict` rejimda noto'g'ri so'rov shartida tashlanadi (noma'lum kalit yoki\n * operatorga mos kelmagan qiymat). Backend'da 400 qilib qaytarish uchun:\n *\n * ```ts\n * try {\n * return await usersRepository.findList(params);\n * } catch (err) {\n * if (err instanceof QueryKitError) return c.json({ error: err.message }, 400);\n * throw err;\n * }\n * ```\n */\nexport class QueryKitError extends Error {\n /** Barqaror kod — `instanceof` ishlamaydigan chegaralarda (RPC, worker) tekshirish uchun. */\n readonly code = \"QUERYKIT_INVALID_CONDITION\";\n\n /** Tashlab yuborilgan shart haqida to'liq ma'lumot (hook argumenti bilan bir xil shakl). */\n readonly info: SkippedCondition;\n\n constructor(info: SkippedCondition) {\n super(`querykit: ${info.reason} — \"${info.key}\" (${info.site}) on \"${info.source}\".`);\n this.name = \"QueryKitError\";\n this.info = info;\n }\n}\n\n/**\n * A read ran past its time limit (`maxTimeMS` on MongoDB). Kept apart from\n * {@link QueryKitError}: the request was valid, the database was slow — map it to\n * 503 / 504, not 400.\n */\nexport class QueryKitTimeoutError extends Error {\n /** Stable code for boundaries where `instanceof` does not work. */\n readonly code = \"QUERYKIT_TIMEOUT\";\n\n constructor(\n /** Collection / model name. */\n readonly source: string,\n /** The limit that was hit, in milliseconds. */\n readonly maxTimeMS: number,\n options?: { cause?: unknown },\n ) {\n super(`querykit: a read on \"${source}\" ran past maxTimeMS (${maxTimeMS} ms).`, options);\n this.name = \"QueryKitTimeoutError\";\n }\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
5
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
3
|
+
var chunkVD7XT52J_cjs = require('./chunk-VD7XT52J.cjs');
|
|
6
4
|
|
|
7
5
|
// src/filters.ts
|
|
8
6
|
function field(key, operation, value) {
|
|
@@ -38,26 +36,7 @@ function createFilters() {
|
|
|
38
36
|
not: (node) => ({ not: node })
|
|
39
37
|
};
|
|
40
38
|
}
|
|
41
|
-
var f = createFilters();
|
|
42
|
-
|
|
43
|
-
// src/defaults.ts
|
|
44
|
-
var DEFAULT_PER_PAGE = 20;
|
|
45
|
-
var DEFAULT_LIMIT = 20;
|
|
46
|
-
var DEFAULT_MAX_PER_PAGE = 200;
|
|
47
|
-
var DEFAULT_MAX_LIMIT = 200;
|
|
48
|
-
|
|
49
|
-
// src/errors.ts
|
|
50
|
-
var QueryKitError = class extends Error {
|
|
51
|
-
constructor(info) {
|
|
52
|
-
super(`querykit: ${info.reason} \u2014 "${info.key}" (${info.site}) on "${info.source}".`);
|
|
53
|
-
/** Barqaror kod — `instanceof` ishlamaydigan chegaralarda (RPC, worker) tekshirish uchun. */
|
|
54
|
-
__publicField(this, "code", "QUERYKIT_INVALID_CONDITION");
|
|
55
|
-
/** Tashlab yuborilgan shart haqida to'liq ma'lumot (hook argumenti bilan bir xil shakl). */
|
|
56
|
-
__publicField(this, "info");
|
|
57
|
-
this.name = "QueryKitError";
|
|
58
|
-
this.info = info;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
39
|
+
var f = /* @__PURE__ */ createFilters();
|
|
61
40
|
|
|
62
41
|
// src/operators.ts
|
|
63
42
|
var FILTER_OPERATORS = [
|
|
@@ -91,8 +70,7 @@ var FILTER_OPERATORS = [
|
|
|
91
70
|
"notBetween",
|
|
92
71
|
"isNull",
|
|
93
72
|
"isNotNull"
|
|
94
|
-
]
|
|
95
|
-
var TEXT_FILTER_OPERATORS = [
|
|
73
|
+
], TEXT_FILTER_OPERATORS = [
|
|
96
74
|
"like",
|
|
97
75
|
"ilike",
|
|
98
76
|
"notLike",
|
|
@@ -104,12 +82,71 @@ var TEXT_FILTER_OPERATORS = [
|
|
|
104
82
|
"_%"
|
|
105
83
|
];
|
|
106
84
|
|
|
107
|
-
exports
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
85
|
+
Object.defineProperty(exports, "DEFAULT_LIMIT", {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_LIMIT; }
|
|
88
|
+
});
|
|
89
|
+
Object.defineProperty(exports, "DEFAULT_MAX_CONDITIONS", {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_CONDITIONS; }
|
|
92
|
+
});
|
|
93
|
+
Object.defineProperty(exports, "DEFAULT_MAX_FILTER_DEPTH", {
|
|
94
|
+
enumerable: true,
|
|
95
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_FILTER_DEPTH; }
|
|
96
|
+
});
|
|
97
|
+
Object.defineProperty(exports, "DEFAULT_MAX_IN_ITEMS", {
|
|
98
|
+
enumerable: true,
|
|
99
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_IN_ITEMS; }
|
|
100
|
+
});
|
|
101
|
+
Object.defineProperty(exports, "DEFAULT_MAX_LIKE_WILDCARDS", {
|
|
102
|
+
enumerable: true,
|
|
103
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_LIKE_WILDCARDS; }
|
|
104
|
+
});
|
|
105
|
+
Object.defineProperty(exports, "DEFAULT_MAX_LIMIT", {
|
|
106
|
+
enumerable: true,
|
|
107
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_LIMIT; }
|
|
108
|
+
});
|
|
109
|
+
Object.defineProperty(exports, "DEFAULT_MAX_OFFSET", {
|
|
110
|
+
enumerable: true,
|
|
111
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_OFFSET; }
|
|
112
|
+
});
|
|
113
|
+
Object.defineProperty(exports, "DEFAULT_MAX_PER_PAGE", {
|
|
114
|
+
enumerable: true,
|
|
115
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_PER_PAGE; }
|
|
116
|
+
});
|
|
117
|
+
Object.defineProperty(exports, "DEFAULT_MAX_SORT_FIELDS", {
|
|
118
|
+
enumerable: true,
|
|
119
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_SORT_FIELDS; }
|
|
120
|
+
});
|
|
121
|
+
Object.defineProperty(exports, "DEFAULT_MAX_STRING_LENGTH", {
|
|
122
|
+
enumerable: true,
|
|
123
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_MAX_STRING_LENGTH; }
|
|
124
|
+
});
|
|
125
|
+
Object.defineProperty(exports, "DEFAULT_PER_PAGE", {
|
|
126
|
+
enumerable: true,
|
|
127
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_PER_PAGE; }
|
|
128
|
+
});
|
|
129
|
+
Object.defineProperty(exports, "DEFAULT_QUERY_LIMITS", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
get: function () { return chunkVD7XT52J_cjs.DEFAULT_QUERY_LIMITS; }
|
|
132
|
+
});
|
|
133
|
+
Object.defineProperty(exports, "QueryKitError", {
|
|
134
|
+
enumerable: true,
|
|
135
|
+
get: function () { return chunkVD7XT52J_cjs.QueryKitError; }
|
|
136
|
+
});
|
|
137
|
+
Object.defineProperty(exports, "QueryKitTimeoutError", {
|
|
138
|
+
enumerable: true,
|
|
139
|
+
get: function () { return chunkVD7XT52J_cjs.QueryKitTimeoutError; }
|
|
140
|
+
});
|
|
141
|
+
Object.defineProperty(exports, "raw", {
|
|
142
|
+
enumerable: true,
|
|
143
|
+
get: function () { return chunkVD7XT52J_cjs.raw; }
|
|
144
|
+
});
|
|
145
|
+
Object.defineProperty(exports, "resolveLimits", {
|
|
146
|
+
enumerable: true,
|
|
147
|
+
get: function () { return chunkVD7XT52J_cjs.resolveLimits; }
|
|
148
|
+
});
|
|
111
149
|
exports.FILTER_OPERATORS = FILTER_OPERATORS;
|
|
112
|
-
exports.QueryKitError = QueryKitError;
|
|
113
150
|
exports.TEXT_FILTER_OPERATORS = TEXT_FILTER_OPERATORS;
|
|
114
151
|
exports.createFilters = createFilters;
|
|
115
152
|
exports.f = f;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/filters.ts","../src/
|
|
1
|
+
{"version":3,"sources":["../src/filters.ts","../src/operators.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AndGroup, FieldCondition, FilterNode, FilterOperator, FilterScalar, FilterValue, NotGroup, OrGroup } from \"./types\";\n\nfunction field<TKey extends string>(key: TKey, operation: FilterOperator, value?: FilterValue): FieldCondition<TKey> {\n return { key, operation, value };\n}\n\n/**\n * Filter shartlarini tipli, ergonomik quruvchilar to'plamini qaytaradi. Kalit\n * tipiga (`TKey`) bog'lanadi; adapterlar uni o'z ustun/maydon kaliti bilan\n * chaqiradi. `TRaw` — guruhlarga (`and/or/not`) qo'shsa bo'ladigan raw tugun tipi.\n *\n * @typeParam TKey - ustun/maydon kaliti (string union).\n * @typeParam TRaw - raw escape-hatch tugun tipi (masalan Drizzle `SQL`).\n * @example\n * ```ts\n * const f = createFilters<\"status\" | \"age\">();\n * f.and(f.eq(\"status\", \"active\"), f.gte(\"age\", 18));\n * ```\n */\nexport function createFilters<TKey extends string = string, TRaw = never>() {\n type Node = FilterNode<TKey, TRaw>;\n\n return {\n eq: (key: TKey, value: FilterValue) => field(key, \"=\", value),\n ne: (key: TKey, value: FilterValue) => field(key, \"!=\", value),\n gt: (key: TKey, value: FilterValue) => field(key, \">\", value),\n gte: (key: TKey, value: FilterValue) => field(key, \">=\", value),\n lt: (key: TKey, value: FilterValue) => field(key, \"<\", value),\n lte: (key: TKey, value: FilterValue) => field(key, \"<=\", value),\n\n contains: (key: TKey, value: string) => field(key, \"%_%\", value),\n startsWith: (key: TKey, value: string) => field(key, \"%_\", value),\n endsWith: (key: TKey, value: string) => field(key, \"_%\", value),\n like: (key: TKey, value: string) => field(key, \"like\", value),\n ilike: (key: TKey, value: string) => field(key, \"ilike\", value),\n notLike: (key: TKey, value: string) => field(key, \"notLike\", value),\n\n in: (key: TKey, value: Array<string | number>) => field(key, \"in\", value),\n notIn: (key: TKey, value: Array<string | number>) => field(key, \"notIn\", value),\n between: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => field(key, \"between\", [min, max] as FilterValue),\n notBetween: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => field(key, \"notBetween\", [min, max] as FilterValue),\n /** Diapazon — ikkita shart (`>=` va `<=`) massivi (flat filterga spread qilinadi). */\n range: (key: TKey, from: FilterScalar | Date, to: FilterScalar | Date): FieldCondition<TKey>[] => [\n field(key, \">=\", from as FilterValue),\n field(key, \"<=\", to as FilterValue),\n ],\n\n isNull: (key: TKey) => field(key, \"isNull\"),\n isNotNull: (key: TKey) => field(key, \"isNotNull\"),\n\n and: (...nodes: Node[]): AndGroup<TKey, TRaw> => ({ and: nodes }),\n or: (...nodes: Node[]): OrGroup<TKey, TRaw> => ({ or: nodes }),\n not: (node: Node): NotGroup<TKey, TRaw> => ({ not: node }),\n };\n}\n\n/** Tipsiz (kalitga bog'lanmagan) filter quruvchilar — tez foydalanish uchun. */\nexport const f = /* @__PURE__ */ createFilters();\n","/**\n * Filter operatorlari — yagona runtime manba. `FilterOperator` tipi (`types.ts`)\n * shundan chiqadi; `@querykitjs/zod` shu massivdan zod enum quradi.\n */\nexport const FILTER_OPERATORS = [\n \"=\",\n \"!=\",\n \">\",\n \">=\",\n \"<\",\n \"<=\",\n \"eq\",\n \"ne\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"like\",\n \"ilike\",\n \"notLike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"%_%\", // contains\n \"%_\", // startsWith\n \"_%\", // endsWith\n \"in\",\n \"notIn\",\n \"between\",\n \"notBetween\",\n \"isNull\",\n \"isNotNull\",\n] as const;\n\n/**\n * Qiymati **text pattern** bo'lgan operatorlar. Backend adapterlari wire qiymatni\n * ustun/path tipiga cast qilishda shularni chetlab o'tadi — aks holda\n * `ilike(dateColumn, \"%2026%\")` ISO string o'rniga `String(Date)` olardi\n * (`\"Mon Jul 28 2026 …\"`). Ro'yxat ikki adapterda divergent bo'lmasligi uchun\n * shu yerda — yagona manba.\n */\nexport const TEXT_FILTER_OPERATORS = [\n \"like\",\n \"ilike\",\n \"notLike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"%_%\",\n \"%_\",\n \"_%\",\n] as const satisfies readonly (typeof FILTER_OPERATORS)[number][];\n"]}
|