@querykitjs/class-validator 1.0.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 +68 -15
- package/README.md +68 -15
- package/dist/chunk-BZRPXHJC.cjs +81 -0
- package/dist/chunk-BZRPXHJC.cjs.map +1 -0
- package/dist/chunk-F3KZNLYZ.js +76 -0
- package/dist/chunk-F3KZNLYZ.js.map +1 -0
- package/dist/chunk-KT5JRG6S.js +194 -0
- package/dist/chunk-KT5JRG6S.js.map +1 -0
- package/dist/chunk-KXCJO556.cjs +207 -0
- package/dist/chunk-KXCJO556.cjs.map +1 -0
- package/dist/chunk-UICYH7OH.js +85 -0
- package/dist/chunk-UICYH7OH.js.map +1 -0
- package/dist/chunk-X7HMP7H7.cjs +89 -0
- package/dist/chunk-X7HMP7H7.cjs.map +1 -0
- package/dist/decorators.cjs +33 -0
- package/dist/decorators.cjs.map +1 -0
- package/dist/decorators.js +4 -0
- package/dist/decorators.js.map +1 -0
- package/dist/index.cjs +94 -408
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -10
- package/dist/index.d.ts +82 -10
- package/dist/index.js +20 -394
- package/dist/index.js.map +1 -1
- package/dist/legacy-dto.cjs +26 -0
- package/dist/legacy-dto.cjs.map +1 -0
- package/dist/legacy-dto.js +5 -0
- package/dist/legacy-dto.js.map +1 -0
- package/dist/validate.cjs +20 -0
- package/dist/validate.cjs.map +1 -0
- package/dist/validate.js +3 -0
- package/dist/validate.js.map +1 -0
- package/package.json +20 -11
- package/skills/querykit-class-validator/SKILL.md +124 -0
package/README.en.md
CHANGED
|
@@ -27,6 +27,17 @@ import "reflect-metadata";
|
|
|
27
27
|
|
|
28
28
|
Without it, class-transformer's `@Type()` throws `Reflect.getMetadata is not a function`.
|
|
29
29
|
|
|
30
|
+
### Requirements
|
|
31
|
+
|
|
32
|
+
| | Version | Tested (`bun run test:matrix`) |
|
|
33
|
+
| ---------------------------------- | ------------------- | ------------------------------ |
|
|
34
|
+
| Node.js | `>=22.12` | 24 |
|
|
35
|
+
| `class-validator` (peer) | `>=0.14 <0.16` | 0.14.4, 0.15.1 |
|
|
36
|
+
| `class-transformer` (peer) | `^0.5` | 0.5.1 |
|
|
37
|
+
| `reflect-metadata` (optional peer) | `^0.1.13 \|\| ^0.2` | 0.1.14, 0.2.2 |
|
|
38
|
+
|
|
39
|
+
Node 20 is no longer supported (`engines`: `>=22.12`). Peer ranges cover the last two majors; both ends are tested.
|
|
40
|
+
|
|
30
41
|
## Usage (NestJS)
|
|
31
42
|
|
|
32
43
|
`main.ts`:
|
|
@@ -79,17 +90,18 @@ Both flags are **required**, otherwise the guarantees are only half in place:
|
|
|
79
90
|
|
|
80
91
|
- **Filter** — a flat array (`{key, operation, value}[]`) or a nested `and`/`or`/`not` tree.
|
|
81
92
|
- **Operators** — the full core set: `= != > >= < <=`, `like/ilike/notLike`, `contains/startsWith/endsWith` (+ tokens `%_%`/`%_`/`_%`), `in/notIn`, `between/notBetween`, `isNull/isNotNull`.
|
|
82
|
-
- **Sort** — `{ key, direction }[]` (multi-field).
|
|
83
|
-
- **
|
|
93
|
+
- **Sort** — `{ key, direction }[]` (multi-field, at most 3).
|
|
94
|
+
- **Request limits** — filter size, sort fields, offset depth ([Limits](#limits)).
|
|
95
|
+
- **Pagination** — offset (`page`/`perPage`/`withTotal` — `false` ⇒ no count, totals `null`), infinite (`limit`/`offset`), cursor (`limit`/`cursor`/`cursorKey`/`order`/`direction`).
|
|
84
96
|
- **Values** — a scalar or an array of scalars. Because the wire is JSON, a `Date` object, `NaN` and `Infinity` are **rejected** (dates arrive as ISO strings).
|
|
85
|
-
- **A field allowlist** (`allowedKeys`)
|
|
97
|
+
- **A field allowlist** (`allowedKeys`) — zod has none, see below.
|
|
86
98
|
- The legacy `type` field is **ignored** (not rejected) — easy migration.
|
|
87
99
|
|
|
88
100
|
## Safe by default
|
|
89
101
|
|
|
90
102
|
| Layer | Default behaviour |
|
|
91
103
|
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
92
|
-
| `perPage` / `limit` | Capped at core's `DEFAULT_MAX_PER_PAGE` / `DEFAULT_MAX_LIMIT` (200). `page` is uncapped
|
|
104
|
+
| `perPage` / `limit` | Capped at core's `DEFAULT_MAX_PER_PAGE` / `DEFAULT_MAX_LIMIT` (200). `page` itself is uncapped, but `(page - 1) × perPage` ≤ `maxOffset` (10 000). |
|
|
93
105
|
| `columns` / `with` / `withDeleted` | Declared on no DTO, so `whitelist: true` strips them. Only `allow` opens them. |
|
|
94
106
|
| `allowedKeys` | Omitted (`undefined`), any key passes — the allowlist is **opt-in** (zod parity). Provided, an unknown key is **rejected**; `[]` allows nothing, so an allowlist computed from an empty set fails closed rather than open. |
|
|
95
107
|
| `maxDepth` | `5`. An unbounded recursive tree is a DoS surface. |
|
|
@@ -98,16 +110,19 @@ If you do open a field with `allow`, add the **second layer at the repository**:
|
|
|
98
110
|
|
|
99
111
|
## Options
|
|
100
112
|
|
|
113
|
+
> ⚠️ The constant DTOs (`BaseParamsDto`, `OffsetParamsDto`, `InfiniteParamsDto`, `CursorParamsDto`) are `@deprecated` (task 014) and go away in the next major. Use `make*ParamsDto` in new code.
|
|
114
|
+
|
|
101
115
|
`makeOffsetParamsDto` / `makeInfiniteParamsDto` / `makeCursorParamsDto`:
|
|
102
116
|
|
|
103
|
-
| Option | Default | Meaning
|
|
104
|
-
| ------------- | --------------------------------- |
|
|
105
|
-
| `allowedKeys` | — | Shared allowlist shorthand for `filter` and `sort`
|
|
106
|
-
| `filter` | — | Full options for `filter` (below) — wins over the shorthand
|
|
107
|
-
| `sort` | — | `allowedKeys` / `messageStyle` for `sort`
|
|
108
|
-
| `maxPerPage` | core `DEFAULT_MAX_PER_PAGE` (200) | `perPage` ceiling. `Infinity` disables the cap (⚠️ DoS)
|
|
109
|
-
| `maxLimit` | core `DEFAULT_MAX_LIMIT` (200) | `limit` ceiling
|
|
110
|
-
| `allow` | `[]` | Deliberately open `"columns"` / `"with"` / `"withDeleted"`
|
|
117
|
+
| Option | Default | Meaning |
|
|
118
|
+
| ------------- | --------------------------------- | --------------------------------------------------------------------------------- |
|
|
119
|
+
| `allowedKeys` | — | Shared allowlist shorthand for `filter` and `sort` |
|
|
120
|
+
| `filter` | — | Full options for `filter` (below) — wins over the shorthand |
|
|
121
|
+
| `sort` | — | `allowedKeys` / `messageStyle` for `sort` |
|
|
122
|
+
| `maxPerPage` | core `DEFAULT_MAX_PER_PAGE` (200) | `perPage` ceiling. `Infinity` disables the cap (⚠️ DoS) |
|
|
123
|
+
| `maxLimit` | core `DEFAULT_MAX_LIMIT` (200) | `limit` ceiling |
|
|
124
|
+
| `allow` | `[]` | Deliberately open `"columns"` / `"with"` / `"withDeleted"` |
|
|
125
|
+
| `limits` | core `DEFAULT_QUERY_LIMITS` | request limits ([Limits](#limits)); a dedicated `filter.*` / `sort.*` option wins |
|
|
111
126
|
|
|
112
127
|
`@IsQueryFilter(options)` (and `options.filter`):
|
|
113
128
|
|
|
@@ -115,12 +130,50 @@ If you do open a field with `allow`, add the **second layer at the repository**:
|
|
|
115
130
|
| ------------------ | ------------------------ | ------------------------------------------------------------------------------------------ |
|
|
116
131
|
| `allowedKeys` | — | When set, an unknown filter key is rejected |
|
|
117
132
|
| `allowedOperators` | every `FILTER_OPERATORS` | Narrow the accepted operator set |
|
|
118
|
-
| `maxDepth` | `5` |
|
|
133
|
+
| `maxDepth` | `5` | root-to-leaf node count |
|
|
134
|
+
| `maxConditions` | `30` | condition count |
|
|
135
|
+
| `maxInItems` | `200` | items in an array value |
|
|
136
|
+
| `maxStringLength` | `256` | length of a string value |
|
|
119
137
|
| `strictValue` | `false` | `in`/`notIn` → array, `between`/`notBetween` → two values, `isNull`/`isNotNull` → no value |
|
|
120
138
|
| `messageStyle` | `"text"` | `"key"` returns the i18n key instead of a sentence |
|
|
121
139
|
| `rootPath` | the property name | Root of the reported path (`filter[0].operation`) |
|
|
122
140
|
|
|
123
|
-
`@IsQuerySort(options)` — `allowedKeys`, `messageStyle`, `rootPath`.
|
|
141
|
+
`@IsQuerySort(options)` — `allowedKeys`, `maxSortFields` (`3`), `messageStyle`, `rootPath`.
|
|
142
|
+
|
|
143
|
+
`@IsWithinMaxOffset({ mode, maxOffset? })` — `mode: "page"` (`(page - 1) × perPage`) or `"offset"`; `maxOffset` defaults to `10 000`.
|
|
144
|
+
|
|
145
|
+
## Limits
|
|
146
|
+
|
|
147
|
+
Every DTO and `validateFilter` / `validateSort` apply the core request limits — the same values as `@querykitjs/zod` (`DEFAULT_QUERY_LIMITS`).
|
|
148
|
+
|
|
149
|
+
| Limit | Default | What counts | Where |
|
|
150
|
+
| ----------------- | -------- | --------------------------------------------------------------------------------- | ---------------------------------------------------- |
|
|
151
|
+
| `maxDepth` | `5` | root-to-leaf nodes: the root is 1, every `and`/`or`/`not` and the condition add 1 | `@IsQueryFilter` / `validateFilter` |
|
|
152
|
+
| `maxConditions` | `30` | conditions (leaves) across all groups | `@IsQueryFilter` / `validateFilter` |
|
|
153
|
+
| `maxInItems` | `200` | items in one array value | `@IsQueryFilter` / `validateFilter` |
|
|
154
|
+
| `maxStringLength` | `256` | characters in one string value, also inside an array | `@IsQueryFilter` / `validateFilter` |
|
|
155
|
+
| `maxSortFields` | `3` | fields in the `sort` array | `@IsQuerySort` / `validateSort` |
|
|
156
|
+
| `maxOffset` | `10 000` | `(page - 1) × perPage` (20 without `perPage`); infinite `offset` | `@IsWithinMaxOffset` (`page` / `offset` in the DTOs) |
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// raise a limit for one endpoint — the others keep their defaults
|
|
160
|
+
const ImportDto = makeOffsetParamsDto({ limits: { maxInItems: 500 } });
|
|
161
|
+
|
|
162
|
+
// a dedicated option wins over `limits`
|
|
163
|
+
const DeepDto = makeOffsetParamsDto({ limits: { maxDepth: 6 }, filter: { maxDepth: 8 } }); // 8
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- Filter size is checked iteratively, **before** the shape check: a 10 000-level `not` chain does not fill the stack.
|
|
167
|
+
- The error text names the limit and its value (`filter[0].value exceeds maxInItems (200)`). Keys: `querykit.filter.max_depth` for depth, `querykit.limit.exceeded` for the other five (args `limit`, `max`) — in the en/uz/ru catalogs.
|
|
168
|
+
- Pages deeper than `maxOffset` use cursor pagination (`makeCursorParamsDto`).
|
|
169
|
+
- `Infinity` turns a limit off — ⚠️ a DoS surface.
|
|
170
|
+
|
|
171
|
+
## Migrating (DTO limits)
|
|
172
|
+
|
|
173
|
+
- A payload past a limit is now rejected — by the static DTOs and by the factories: an `in` with 201 items, a 257-char string, 31 conditions, 4 sort fields, `page=502, perPage=20` or `offset=10001` now return 400. Raise a limit with `limits` where you need it.
|
|
174
|
+
- `page` now carries `@IsWithinMaxOffset({ mode: "page" })`; if your DTO redeclares `page`, add that decorator too.
|
|
175
|
+
- The `querykit.filter.max_depth` text changed (it now says `maxDepth (5)`); rely on the key, not the text.
|
|
176
|
+
- `DEFAULT_MAX_FILTER_DEPTH` is now re-exported from `@querykitjs/core` (same value, 5).
|
|
124
177
|
|
|
125
178
|
## i18n (more than one language)
|
|
126
179
|
|
|
@@ -181,7 +234,7 @@ if (issues.length > 0) {
|
|
|
181
234
|
| Contract, operators | from core | **the same** |
|
|
182
235
|
| Stripping unknown fields | automatic | via `ValidationPipe({ whitelist: true })` |
|
|
183
236
|
| Field allowlist | none | `allowedKeys` |
|
|
184
|
-
|
|
|
237
|
+
| Request limits | the same (core) | the same (core) — `limits` |
|
|
185
238
|
| `NaN` / `Infinity` | `Infinity` passes | both rejected (neither exists in JSON) |
|
|
186
239
|
| i18n | — | `querykit.*` keys + en/uz/ru catalogs |
|
|
187
240
|
|
package/README.md
CHANGED
|
@@ -27,6 +27,17 @@ import "reflect-metadata";
|
|
|
27
27
|
|
|
28
28
|
Usiz class-transformer'ning `@Type()` dekoratori `Reflect.getMetadata is not a function` xatosini beradi.
|
|
29
29
|
|
|
30
|
+
### Talablar
|
|
31
|
+
|
|
32
|
+
| | Versiya | Tekshiriladi (`bun run test:matrix`) |
|
|
33
|
+
| ----------------------------------- | ------------------- | ------------------------------------ |
|
|
34
|
+
| Node.js | `>=22.12` | 24 |
|
|
35
|
+
| `class-validator` (peer) | `>=0.14 <0.16` | 0.14.4, 0.15.1 |
|
|
36
|
+
| `class-transformer` (peer) | `^0.5` | 0.5.1 |
|
|
37
|
+
| `reflect-metadata` (ixtiyoriy peer) | `^0.1.13 \|\| ^0.2` | 0.1.14, 0.2.2 |
|
|
38
|
+
|
|
39
|
+
Node 20 endi qo'llab-quvvatlanmaydi (`engines`: `>=22.12`). Peer diapazoni — oxirgi ikki major; ikkala cheti testda.
|
|
40
|
+
|
|
30
41
|
## Foydalanish (NestJS)
|
|
31
42
|
|
|
32
43
|
`main.ts`:
|
|
@@ -79,17 +90,18 @@ Ikkala flag ham **zarur**, aks holda kafolatlar yarim ishlaydi:
|
|
|
79
90
|
|
|
80
91
|
- **Filter** — flat massiv (`{key, operation, value}[]`) yoki nested `and`/`or`/`not` daraxt.
|
|
81
92
|
- **Operatorlar** — core'ning to'liq to'plami: `= != > >= < <=`, `like/ilike/notLike`, `contains/startsWith/endsWith` (+ token `%_%`/`%_`/`_%`), `in/notIn`, `between/notBetween`, `isNull/isNotNull`.
|
|
82
|
-
- **Sort** — `{ key, direction }[]` (ko'p-maydon).
|
|
83
|
-
- **
|
|
93
|
+
- **Sort** — `{ key, direction }[]` (ko'p-maydon, ko'pi bilan 3).
|
|
94
|
+
- **So'rov limitlari** — filtr hajmi, sort soni, offset chuqurligi ([Limits](#limits)).
|
|
95
|
+
- **Paginatsiya** — offset (`page`/`perPage`/`withTotal` — `false` ⇒ count yo'q, totals `null`), infinite (`limit`/`offset`), cursor (`limit`/`cursor`/`cursorKey`/`order`/`direction`).
|
|
84
96
|
- **Qiymat** — skalyar yoki skalyar massiv. Wire JSON bo'lgani uchun `Date` obyekti, `NaN` va `Infinity` **rad etiladi** (sana ISO string sifatida keladi).
|
|
85
|
-
- **Field allowlist** (`allowedKeys`)
|
|
97
|
+
- **Field allowlist** (`allowedKeys`) — zod'da yo'q, quyiga qarang.
|
|
86
98
|
- Eski `type` maydoni **e'tiborsiz** qoldiriladi (rad etilmaydi) — migratsiya oson.
|
|
87
99
|
|
|
88
100
|
## Xavfsiz default
|
|
89
101
|
|
|
90
102
|
| Qatlam | Default xulq |
|
|
91
103
|
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
92
|
-
| `perPage` / `limit` | core `DEFAULT_MAX_PER_PAGE` / `DEFAULT_MAX_LIMIT` (200) bilan cheklangan. `page` cheklanmagan
|
|
104
|
+
| `perPage` / `limit` | core `DEFAULT_MAX_PER_PAGE` / `DEFAULT_MAX_LIMIT` (200) bilan cheklangan. `page` o'zi cheklanmagan, lekin `(page - 1) × perPage` ≤ `maxOffset` (10 000). |
|
|
93
105
|
| `columns` / `with` / `withDeleted` | Hech qaysi DTO'da e'lon qilinmagan → `whitelist: true` ularni o'chiradi. Ochish faqat `allow` bilan. |
|
|
94
106
|
| `allowedKeys` | Berilmasa (`undefined`) istalgan kalit o'tadi — allowlist **opt-in** (zod bilan parity). Berilsa, noma'lum kalit **rad etiladi**; `[]` esa hech biriga ruxsat bermaydi (hisoblab chiqarilgan bo'sh ro'yxat fail-open bo'lib qolmasin). |
|
|
95
107
|
| `maxDepth` | `5`. Cheklovsiz rekursiv daraxt DoS yuzasi. |
|
|
@@ -98,16 +110,19 @@ Ikkala flag ham **zarur**, aks holda kafolatlar yarim ishlaydi:
|
|
|
98
110
|
|
|
99
111
|
## Opsiyalar
|
|
100
112
|
|
|
113
|
+
> ⚠️ Konstanta DTO'lar (`BaseParamsDto`, `OffsetParamsDto`, `InfiniteParamsDto`, `CursorParamsDto`) `@deprecated` (task 014): keyingi major'da olib tashlanadi. Yangi kod uchun `make*ParamsDto`.
|
|
114
|
+
|
|
101
115
|
`makeOffsetParamsDto` / `makeInfiniteParamsDto` / `makeCursorParamsDto`:
|
|
102
116
|
|
|
103
|
-
| Opsiya | Default | Ma'nosi
|
|
104
|
-
| ------------- | --------------------------------- |
|
|
105
|
-
| `allowedKeys` | — | `filter` va `sort` uchun umumiy allowlist qisqartmasi
|
|
106
|
-
| `filter` | — | `filter` uchun to'liq opsiyalar (quyiga qarang) — `allowedKeys` shorthand'dan ustun
|
|
107
|
-
| `sort` | — | `sort` uchun `allowedKeys` / `messageStyle`
|
|
108
|
-
| `maxPerPage` | core `DEFAULT_MAX_PER_PAGE` (200) | `perPage` yuqori chegarasi. `Infinity` — cap yo'q (⚠️ DoS)
|
|
109
|
-
| `maxLimit` | core `DEFAULT_MAX_LIMIT` (200) | `limit` yuqori chegarasi
|
|
110
|
-
| `allow` | `[]` | `"columns"` / `"with"` / `"withDeleted"`ni ataylab ochish
|
|
117
|
+
| Opsiya | Default | Ma'nosi |
|
|
118
|
+
| ------------- | --------------------------------- | ------------------------------------------------------------------------------------- |
|
|
119
|
+
| `allowedKeys` | — | `filter` va `sort` uchun umumiy allowlist qisqartmasi |
|
|
120
|
+
| `filter` | — | `filter` uchun to'liq opsiyalar (quyiga qarang) — `allowedKeys` shorthand'dan ustun |
|
|
121
|
+
| `sort` | — | `sort` uchun `allowedKeys` / `messageStyle` |
|
|
122
|
+
| `maxPerPage` | core `DEFAULT_MAX_PER_PAGE` (200) | `perPage` yuqori chegarasi. `Infinity` — cap yo'q (⚠️ DoS) |
|
|
123
|
+
| `maxLimit` | core `DEFAULT_MAX_LIMIT` (200) | `limit` yuqori chegarasi |
|
|
124
|
+
| `allow` | `[]` | `"columns"` / `"with"` / `"withDeleted"`ni ataylab ochish |
|
|
125
|
+
| `limits` | core `DEFAULT_QUERY_LIMITS` | so'rov limitlari ([Limits](#limits)); `filter.*` / `sort.*` dagi alohida opsiya ustun |
|
|
111
126
|
|
|
112
127
|
`@IsQueryFilter(options)` (va `options.filter`):
|
|
113
128
|
|
|
@@ -115,12 +130,50 @@ Ikkala flag ham **zarur**, aks holda kafolatlar yarim ishlaydi:
|
|
|
115
130
|
| ------------------ | ------------------------- | ------------------------------------------------------------------------------------------ |
|
|
116
131
|
| `allowedKeys` | — | Berilsa, noma'lum filter kaliti rad etiladi |
|
|
117
132
|
| `allowedOperators` | barcha `FILTER_OPERATORS` | Ruxsat etilgan operatorlar to'plamini toraytirish |
|
|
118
|
-
| `maxDepth` | `5` |
|
|
133
|
+
| `maxDepth` | `5` | ildizdan bargacha tugunlar soni |
|
|
134
|
+
| `maxConditions` | `30` | shartlar soni |
|
|
135
|
+
| `maxInItems` | `200` | massiv qiymat elementlari |
|
|
136
|
+
| `maxStringLength` | `256` | satr qiymat uzunligi |
|
|
119
137
|
| `strictValue` | `false` | `in`/`notIn` → massiv, `between`/`notBetween` → 2 qiymat, `isNull`/`isNotNull` → qiymatsiz |
|
|
120
138
|
| `messageStyle` | `"text"` | `"key"` — xato o'rniga i18n kaliti qaytariladi |
|
|
121
139
|
| `rootPath` | property nomi | Xato yo'lining ildizi (`filter[0].operation`) |
|
|
122
140
|
|
|
123
|
-
`@IsQuerySort(options)` — `allowedKeys`, `messageStyle`, `rootPath`.
|
|
141
|
+
`@IsQuerySort(options)` — `allowedKeys`, `maxSortFields` (`3`), `messageStyle`, `rootPath`.
|
|
142
|
+
|
|
143
|
+
`@IsWithinMaxOffset({ mode, maxOffset? })` — `mode: "page"` (`(page - 1) × perPage`) yoki `"offset"`; `maxOffset` default `10 000`.
|
|
144
|
+
|
|
145
|
+
## Limits
|
|
146
|
+
|
|
147
|
+
Har DTO va `validateFilter` / `validateSort` core so'rov limitlarini qo'llaydi — `@querykitjs/zod` bilan bir xil qiymatlar (`DEFAULT_QUERY_LIMITS`).
|
|
148
|
+
|
|
149
|
+
| Limit | Default | Nima sanaladi | Qayerda |
|
|
150
|
+
| ----------------- | -------- | --------------------------------------------------------------------- | -------------------------------------------------- |
|
|
151
|
+
| `maxDepth` | `5` | ildizdan bargacha tugunlar: ildiz 1, har `and`/`or`/`not` va shart +1 | `@IsQueryFilter` / `validateFilter` |
|
|
152
|
+
| `maxConditions` | `30` | barcha guruhlardagi shartlar (barglar) | `@IsQueryFilter` / `validateFilter` |
|
|
153
|
+
| `maxInItems` | `200` | bitta massiv qiymatdagi elementlar | `@IsQueryFilter` / `validateFilter` |
|
|
154
|
+
| `maxStringLength` | `256` | bitta satr qiymatdagi belgilar (massiv ichida ham) | `@IsQueryFilter` / `validateFilter` |
|
|
155
|
+
| `maxSortFields` | `3` | `sort` massividagi maydonlar | `@IsQuerySort` / `validateSort` |
|
|
156
|
+
| `maxOffset` | `10 000` | `(page - 1) × perPage` (`perPage` yo'q bo'lsa 20); infinite `offset` | `@IsWithinMaxOffset` (DTO'larda `page` / `offset`) |
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// bitta endpoint uchun limitni oshirish — qolganlari default
|
|
160
|
+
const ImportDto = makeOffsetParamsDto({ limits: { maxInItems: 500 } });
|
|
161
|
+
|
|
162
|
+
// alohida opsiya `limits`dan ustun
|
|
163
|
+
const DeepDto = makeOffsetParamsDto({ limits: { maxDepth: 6 }, filter: { maxDepth: 8 } }); // 8
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
- Filtr hajmi iterativ, shakl tekshiruvidan **oldin** tekshiriladi: 10 000 darajali `not` zanjiri stekni to'ldirmaydi.
|
|
167
|
+
- Xato matni limit nomi va qiymatini aytadi (`filter[0].value exceeds maxInItems (200)`). Kalitlar: chuqurlik uchun `querykit.filter.max_depth`, qolgan beshtasi uchun `querykit.limit.exceeded` (args `limit`, `max`) — en/uz/ru kataloglarda.
|
|
168
|
+
- `maxOffset`dan chuqur sahifalar — cursor paginatsiya (`makeCursorParamsDto`).
|
|
169
|
+
- `Infinity` limitni o'chiradi — ⚠️ DoS yuzasi.
|
|
170
|
+
|
|
171
|
+
## Migrating (DTO limitlari)
|
|
172
|
+
|
|
173
|
+
- Limitdan oshgan payload endi rad etiladi — static DTO'larda ham, factory'larda ham: `in` 201 element, 257 belgili satr, 31 shart, 4 sort maydoni, `page=502, perPage=20` yoki `offset=10001` endi 400 beradi. Kerak bo'lsa `limits` bilan oshiring.
|
|
174
|
+
- `page` endi `@IsWithinMaxOffset({ mode: "page" })` bilan; o'z DTO'ngizda `page`ni qayta e'lon qilsangiz, shu dekoratorni ham qo'ying.
|
|
175
|
+
- `querykit.filter.max_depth` matni o'zgardi (endi `maxDepth (5)` deydi); matnga emas, kalitga tayaning.
|
|
176
|
+
- `DEFAULT_MAX_FILTER_DEPTH` endi `@querykitjs/core`dan qayta eksport (qiymat o'sha — 5).
|
|
124
177
|
|
|
125
178
|
## i18n (bir nechta til)
|
|
126
179
|
|
|
@@ -181,7 +234,7 @@ if (issues.length > 0) {
|
|
|
181
234
|
| Kontrakt, operatorlar | core'dan | **aynan o'sha** |
|
|
182
235
|
| Noma'lum maydonni strip qilish | avtomatik | `ValidationPipe({ whitelist: true })` orqali |
|
|
183
236
|
| Field allowlist | yo'q | `allowedKeys` |
|
|
184
|
-
|
|
|
237
|
+
| So'rov limitlari | bir xil (core) | bir xil (core) — `limits` |
|
|
185
238
|
| `NaN` / `Infinity` | `Infinity` o'tadi | ikkalasi ham rad etiladi (JSON'da mavjud emas) |
|
|
186
239
|
| i18n | — | `querykit.*` kalitlari + en/uz/ru kataloglar |
|
|
187
240
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkX7HMP7H7_cjs = require('./chunk-X7HMP7H7.cjs');
|
|
4
|
+
var chunkKXCJO556_cjs = require('./chunk-KXCJO556.cjs');
|
|
5
|
+
var classTransformer = require('class-transformer');
|
|
6
|
+
var classValidator = require('class-validator');
|
|
7
|
+
var core = require('@querykitjs/core');
|
|
8
|
+
|
|
9
|
+
var BaseParamsDto = class {
|
|
10
|
+
};
|
|
11
|
+
chunkKXCJO556_cjs.__decorateClass([
|
|
12
|
+
classValidator.IsOptional(),
|
|
13
|
+
chunkX7HMP7H7_cjs.IsQueryFilter()
|
|
14
|
+
], BaseParamsDto.prototype, "filter", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
15
|
+
classValidator.IsOptional(),
|
|
16
|
+
chunkX7HMP7H7_cjs.IsQuerySort()
|
|
17
|
+
], BaseParamsDto.prototype, "sort", 2);
|
|
18
|
+
var OffsetParamsDto = class extends BaseParamsDto {
|
|
19
|
+
};
|
|
20
|
+
chunkKXCJO556_cjs.__decorateClass([
|
|
21
|
+
classValidator.IsOptional(),
|
|
22
|
+
classTransformer.Type(() => Number),
|
|
23
|
+
classValidator.IsInt(),
|
|
24
|
+
classValidator.IsPositive(),
|
|
25
|
+
chunkX7HMP7H7_cjs.IsWithinMaxOffset({ mode: "page" })
|
|
26
|
+
], OffsetParamsDto.prototype, "page", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
27
|
+
classValidator.IsOptional(),
|
|
28
|
+
classTransformer.Type(() => Number),
|
|
29
|
+
classValidator.IsInt(),
|
|
30
|
+
classValidator.IsPositive(),
|
|
31
|
+
classValidator.Max(core.DEFAULT_MAX_PER_PAGE)
|
|
32
|
+
], OffsetParamsDto.prototype, "perPage", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
33
|
+
classValidator.IsOptional(),
|
|
34
|
+
classValidator.IsBoolean()
|
|
35
|
+
], OffsetParamsDto.prototype, "withTotal", 2);
|
|
36
|
+
var InfiniteParamsDto = class extends BaseParamsDto {
|
|
37
|
+
};
|
|
38
|
+
chunkKXCJO556_cjs.__decorateClass([
|
|
39
|
+
classValidator.IsOptional(),
|
|
40
|
+
classTransformer.Type(() => Number),
|
|
41
|
+
classValidator.IsInt(),
|
|
42
|
+
classValidator.IsPositive(),
|
|
43
|
+
classValidator.Max(core.DEFAULT_MAX_LIMIT)
|
|
44
|
+
], InfiniteParamsDto.prototype, "limit", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
45
|
+
classValidator.IsOptional(),
|
|
46
|
+
classTransformer.Type(() => Number),
|
|
47
|
+
classValidator.IsInt(),
|
|
48
|
+
classValidator.Min(0),
|
|
49
|
+
chunkX7HMP7H7_cjs.IsWithinMaxOffset({ mode: "offset" })
|
|
50
|
+
], InfiniteParamsDto.prototype, "offset", 2);
|
|
51
|
+
var CursorParamsDto = class {
|
|
52
|
+
};
|
|
53
|
+
chunkKXCJO556_cjs.__decorateClass([
|
|
54
|
+
classValidator.IsOptional(),
|
|
55
|
+
chunkX7HMP7H7_cjs.IsQueryFilter()
|
|
56
|
+
], CursorParamsDto.prototype, "filter", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
57
|
+
classValidator.IsOptional(),
|
|
58
|
+
classTransformer.Type(() => Number),
|
|
59
|
+
classValidator.IsInt(),
|
|
60
|
+
classValidator.IsPositive(),
|
|
61
|
+
classValidator.Max(core.DEFAULT_MAX_LIMIT)
|
|
62
|
+
], CursorParamsDto.prototype, "limit", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
63
|
+
classValidator.IsOptional(),
|
|
64
|
+
classValidator.IsString()
|
|
65
|
+
], CursorParamsDto.prototype, "cursor", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
66
|
+
classValidator.IsOptional(),
|
|
67
|
+
classValidator.IsString()
|
|
68
|
+
], CursorParamsDto.prototype, "cursorKey", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
69
|
+
classValidator.IsOptional(),
|
|
70
|
+
classValidator.IsIn(["asc", "desc"])
|
|
71
|
+
], CursorParamsDto.prototype, "order", 2), chunkKXCJO556_cjs.__decorateClass([
|
|
72
|
+
classValidator.IsOptional(),
|
|
73
|
+
classValidator.IsIn(["forward", "backward"])
|
|
74
|
+
], CursorParamsDto.prototype, "direction", 2);
|
|
75
|
+
|
|
76
|
+
exports.BaseParamsDto = BaseParamsDto;
|
|
77
|
+
exports.CursorParamsDto = CursorParamsDto;
|
|
78
|
+
exports.InfiniteParamsDto = InfiniteParamsDto;
|
|
79
|
+
exports.OffsetParamsDto = OffsetParamsDto;
|
|
80
|
+
//# sourceMappingURL=chunk-BZRPXHJC.cjs.map
|
|
81
|
+
//# sourceMappingURL=chunk-BZRPXHJC.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/legacy-dto.ts"],"names":["__decorateClass","IsOptional","IsQueryFilter","IsQuerySort","Type","IsInt","IsPositive","IsWithinMaxOffset","Max","DEFAULT_MAX_PER_PAGE","IsBoolean","DEFAULT_MAX_LIMIT","Min","IsString","IsIn"],"mappings":"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","file":"chunk-BZRPXHJC.cjs","sourcesContent":["/**\n * Static param DTOs (deprecated, task 014 P3) — `class ListUsersDto extends OffsetParamsDto`.\n * Kept in their own module (task 016): their decorators register class-validator metadata\n * when the module loads, so a bundle that does not import them drops the whole module.\n * New code uses the `make*ParamsDto` factories (`./dto`).\n */\nimport { Type } from \"class-transformer\";\nimport { IsIn, IsInt, IsOptional, IsPositive, IsString, Max, Min, IsBoolean } from \"class-validator\";\nimport { DEFAULT_MAX_LIMIT, DEFAULT_MAX_PER_PAGE } from \"@querykitjs/core\";\nimport type { Filter, Sort, SortDirection } from \"@querykitjs/core\";\nimport { IsQueryFilter, IsQuerySort, IsWithinMaxOffset } from \"./decorators\";\n\n/**\n * Paginatsiyasiz umumiy params — `filter` + `sort`.\n *\n * @deprecated Use `makeOffsetParamsDto` / `makeInfiniteParamsDto` / `makeCursorParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class BaseParamsDto {\n @IsOptional()\n @IsQueryFilter()\n filter?: Filter;\n\n @IsOptional()\n @IsQuerySort()\n sort?: Sort;\n}\n\n/**\n * Offset (sahifali) params — `page` + `perPage` (`perPage` ≤ core cap).\n *\n * @deprecated Use `makeOffsetParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class OffsetParamsDto extends BaseParamsDto {\n /* `page`ning o'zida cap yo'q — chegara `(page - 1) × perPage` ≤ `DEFAULT_MAX_OFFSET`\n * (`@querykitjs/zod` factory'lari ham aynan shunday). */\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @IsWithinMaxOffset({ mode: \"page\" })\n page?: number;\n\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @Max(DEFAULT_MAX_PER_PAGE)\n perPage?: number;\n\n /** `false` — no count; the meta totals are `null` (task 013). */\n @IsOptional()\n @IsBoolean()\n withTotal?: boolean;\n}\n\n/**\n * Infinite-scroll params — `limit` + `offset`.\n *\n * @deprecated Use `makeInfiniteParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class InfiniteParamsDto extends BaseParamsDto {\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @Max(DEFAULT_MAX_LIMIT)\n limit?: number;\n\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @Min(0)\n @IsWithinMaxOffset({ mode: \"offset\" })\n offset?: number;\n}\n\n/**\n * Cursor (keyset) params. `sort` **yo'q**: tartib `order` + `direction` bilan\n * boshqariladi. Shu sababli `BaseParamsDto`dan meros olinmaydi — aks holda\n * `sort` kontraktga qarshi ravishda meros bo'lib qolardi.\n *\n * @deprecated Use `makeCursorParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class CursorParamsDto {\n @IsOptional()\n @IsQueryFilter()\n filter?: Filter;\n\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @Max(DEFAULT_MAX_LIMIT)\n limit?: number;\n\n @IsOptional()\n @IsString()\n cursor?: string | null;\n\n @IsOptional()\n @IsString()\n cursorKey?: string;\n\n @IsOptional()\n @IsIn([\"asc\", \"desc\"])\n order?: SortDirection;\n\n @IsOptional()\n @IsIn([\"forward\", \"backward\"])\n direction?: \"forward\" | \"backward\";\n}\n"]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IsQueryFilter, IsQuerySort, IsWithinMaxOffset } from './chunk-UICYH7OH.js';
|
|
2
|
+
import { __decorateClass } from './chunk-KT5JRG6S.js';
|
|
3
|
+
import { Type } from 'class-transformer';
|
|
4
|
+
import { IsOptional, IsInt, IsPositive, Max, IsBoolean, Min, IsString, IsIn } from 'class-validator';
|
|
5
|
+
import { DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_LIMIT } from '@querykitjs/core';
|
|
6
|
+
|
|
7
|
+
var BaseParamsDto = class {
|
|
8
|
+
};
|
|
9
|
+
__decorateClass([
|
|
10
|
+
IsOptional(),
|
|
11
|
+
IsQueryFilter()
|
|
12
|
+
], BaseParamsDto.prototype, "filter", 2), __decorateClass([
|
|
13
|
+
IsOptional(),
|
|
14
|
+
IsQuerySort()
|
|
15
|
+
], BaseParamsDto.prototype, "sort", 2);
|
|
16
|
+
var OffsetParamsDto = class extends BaseParamsDto {
|
|
17
|
+
};
|
|
18
|
+
__decorateClass([
|
|
19
|
+
IsOptional(),
|
|
20
|
+
Type(() => Number),
|
|
21
|
+
IsInt(),
|
|
22
|
+
IsPositive(),
|
|
23
|
+
IsWithinMaxOffset({ mode: "page" })
|
|
24
|
+
], OffsetParamsDto.prototype, "page", 2), __decorateClass([
|
|
25
|
+
IsOptional(),
|
|
26
|
+
Type(() => Number),
|
|
27
|
+
IsInt(),
|
|
28
|
+
IsPositive(),
|
|
29
|
+
Max(DEFAULT_MAX_PER_PAGE)
|
|
30
|
+
], OffsetParamsDto.prototype, "perPage", 2), __decorateClass([
|
|
31
|
+
IsOptional(),
|
|
32
|
+
IsBoolean()
|
|
33
|
+
], OffsetParamsDto.prototype, "withTotal", 2);
|
|
34
|
+
var InfiniteParamsDto = class extends BaseParamsDto {
|
|
35
|
+
};
|
|
36
|
+
__decorateClass([
|
|
37
|
+
IsOptional(),
|
|
38
|
+
Type(() => Number),
|
|
39
|
+
IsInt(),
|
|
40
|
+
IsPositive(),
|
|
41
|
+
Max(DEFAULT_MAX_LIMIT)
|
|
42
|
+
], InfiniteParamsDto.prototype, "limit", 2), __decorateClass([
|
|
43
|
+
IsOptional(),
|
|
44
|
+
Type(() => Number),
|
|
45
|
+
IsInt(),
|
|
46
|
+
Min(0),
|
|
47
|
+
IsWithinMaxOffset({ mode: "offset" })
|
|
48
|
+
], InfiniteParamsDto.prototype, "offset", 2);
|
|
49
|
+
var CursorParamsDto = class {
|
|
50
|
+
};
|
|
51
|
+
__decorateClass([
|
|
52
|
+
IsOptional(),
|
|
53
|
+
IsQueryFilter()
|
|
54
|
+
], CursorParamsDto.prototype, "filter", 2), __decorateClass([
|
|
55
|
+
IsOptional(),
|
|
56
|
+
Type(() => Number),
|
|
57
|
+
IsInt(),
|
|
58
|
+
IsPositive(),
|
|
59
|
+
Max(DEFAULT_MAX_LIMIT)
|
|
60
|
+
], CursorParamsDto.prototype, "limit", 2), __decorateClass([
|
|
61
|
+
IsOptional(),
|
|
62
|
+
IsString()
|
|
63
|
+
], CursorParamsDto.prototype, "cursor", 2), __decorateClass([
|
|
64
|
+
IsOptional(),
|
|
65
|
+
IsString()
|
|
66
|
+
], CursorParamsDto.prototype, "cursorKey", 2), __decorateClass([
|
|
67
|
+
IsOptional(),
|
|
68
|
+
IsIn(["asc", "desc"])
|
|
69
|
+
], CursorParamsDto.prototype, "order", 2), __decorateClass([
|
|
70
|
+
IsOptional(),
|
|
71
|
+
IsIn(["forward", "backward"])
|
|
72
|
+
], CursorParamsDto.prototype, "direction", 2);
|
|
73
|
+
|
|
74
|
+
export { BaseParamsDto, CursorParamsDto, InfiniteParamsDto, OffsetParamsDto };
|
|
75
|
+
//# sourceMappingURL=chunk-F3KZNLYZ.js.map
|
|
76
|
+
//# sourceMappingURL=chunk-F3KZNLYZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/legacy-dto.ts"],"names":[],"mappings":"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","file":"chunk-F3KZNLYZ.js","sourcesContent":["/**\n * Static param DTOs (deprecated, task 014 P3) — `class ListUsersDto extends OffsetParamsDto`.\n * Kept in their own module (task 016): their decorators register class-validator metadata\n * when the module loads, so a bundle that does not import them drops the whole module.\n * New code uses the `make*ParamsDto` factories (`./dto`).\n */\nimport { Type } from \"class-transformer\";\nimport { IsIn, IsInt, IsOptional, IsPositive, IsString, Max, Min, IsBoolean } from \"class-validator\";\nimport { DEFAULT_MAX_LIMIT, DEFAULT_MAX_PER_PAGE } from \"@querykitjs/core\";\nimport type { Filter, Sort, SortDirection } from \"@querykitjs/core\";\nimport { IsQueryFilter, IsQuerySort, IsWithinMaxOffset } from \"./decorators\";\n\n/**\n * Paginatsiyasiz umumiy params — `filter` + `sort`.\n *\n * @deprecated Use `makeOffsetParamsDto` / `makeInfiniteParamsDto` / `makeCursorParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class BaseParamsDto {\n @IsOptional()\n @IsQueryFilter()\n filter?: Filter;\n\n @IsOptional()\n @IsQuerySort()\n sort?: Sort;\n}\n\n/**\n * Offset (sahifali) params — `page` + `perPage` (`perPage` ≤ core cap).\n *\n * @deprecated Use `makeOffsetParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class OffsetParamsDto extends BaseParamsDto {\n /* `page`ning o'zida cap yo'q — chegara `(page - 1) × perPage` ≤ `DEFAULT_MAX_OFFSET`\n * (`@querykitjs/zod` factory'lari ham aynan shunday). */\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @IsWithinMaxOffset({ mode: \"page\" })\n page?: number;\n\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @Max(DEFAULT_MAX_PER_PAGE)\n perPage?: number;\n\n /** `false` — no count; the meta totals are `null` (task 013). */\n @IsOptional()\n @IsBoolean()\n withTotal?: boolean;\n}\n\n/**\n * Infinite-scroll params — `limit` + `offset`.\n *\n * @deprecated Use `makeInfiniteParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class InfiniteParamsDto extends BaseParamsDto {\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @Max(DEFAULT_MAX_LIMIT)\n limit?: number;\n\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @Min(0)\n @IsWithinMaxOffset({ mode: \"offset\" })\n offset?: number;\n}\n\n/**\n * Cursor (keyset) params. `sort` **yo'q**: tartib `order` + `direction` bilan\n * boshqariladi. Shu sababli `BaseParamsDto`dan meros olinmaydi — aks holda\n * `sort` kontraktga qarshi ravishda meros bo'lib qolardi.\n *\n * @deprecated Use `makeCursorParamsDto` (safe defaults, task 014 P3). Removed in the next major.\n */\nexport class CursorParamsDto {\n @IsOptional()\n @IsQueryFilter()\n filter?: Filter;\n\n @IsOptional()\n @Type(() => Number)\n @IsInt()\n @IsPositive()\n @Max(DEFAULT_MAX_LIMIT)\n limit?: number;\n\n @IsOptional()\n @IsString()\n cursor?: string | null;\n\n @IsOptional()\n @IsString()\n cursorKey?: string;\n\n @IsOptional()\n @IsIn([\"asc\", \"desc\"])\n order?: SortDirection;\n\n @IsOptional()\n @IsIn([\"forward\", \"backward\"])\n direction?: \"forward\" | \"backward\";\n}\n"]}
|