@querykitjs/web 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.
@@ -0,0 +1,417 @@
1
+ import * as Core from '@querykitjs/core';
2
+
3
+ /**
4
+ * Filter/query DSL tiplari — `@querykitjs/core`dan, entity maydoni (`FieldKey`)
5
+ * bilan ixtisoslashtirilgan. querykit backend (`@querykitjs/drizzle-pg`) qabul
6
+ * qiladigan wire-format bilan mos (`{key, operation, value}`).
7
+ */
8
+
9
+ type FilterOperator = Core.FilterOperator;
10
+ type FilterScalar = Core.FilterScalar;
11
+ type FilterValue = Core.FilterValue;
12
+ /** Entity ustun (maydon) kaliti. */
13
+ type FieldKey<T> = Extract<keyof T, string>;
14
+ /** Bitta maydon sharti (`operation` default `"="`). */
15
+ type FieldCondition<T = Record<string, unknown>> = Core.FieldCondition<FieldKey<T>>;
16
+ type AndGroup<T = Record<string, unknown>> = Core.AndGroup<FieldKey<T>>;
17
+ type OrGroup<T = Record<string, unknown>> = Core.OrGroup<FieldKey<T>>;
18
+ type NotGroup<T = Record<string, unknown>> = Core.NotGroup<FieldKey<T>>;
19
+ /** Filter daraxti tuguni: shart yoki mantiqiy guruh. */
20
+ type FilterNode<T = Record<string, unknown>> = Core.FilterNode<FieldKey<T>>;
21
+ /**
22
+ * Public filter: daraxt/tugun yoki flat massiv. Flat massiv implicit `AND` va
23
+ * legacy backend (idistr) `IFilter[]` bilan to'liq mos.
24
+ */
25
+ type Filter<T = Record<string, unknown>> = Core.Filter<FieldKey<T>>;
26
+ type SortDirection = Core.SortDirection;
27
+ interface Sort {
28
+ name?: string;
29
+ direction?: SortDirection;
30
+ }
31
+ /** Sort kirishi: `"-createdAt"` (sortType string) yoki `{ name, direction }`. */
32
+ type SortInput = string | Sort;
33
+ interface Params<T = Record<string, unknown>> {
34
+ filter?: Filter<T>;
35
+ sort?: SortInput;
36
+ columns?: Record<string, boolean>;
37
+ /** Yuklanadigan relationlar (default `with` deb yuboriladi). */
38
+ with?: Record<string, unknown>;
39
+ /** Soft-delete qilingan qatorlarni ham qo'shish (backend read'lari uchun). */
40
+ withDeleted?: boolean;
41
+ }
42
+ /** Offset (sahifali) paginatsiya kirishi. */
43
+ interface ListParams<T = Record<string, unknown>> extends Params<T> {
44
+ page?: number;
45
+ perPage?: number;
46
+ }
47
+ /** Infinite-scroll (limit + offset) paginatsiya kirishi. */
48
+ interface InfiniteParams<T = Record<string, unknown>> extends Params<T> {
49
+ limit?: number;
50
+ offset?: number;
51
+ }
52
+ /** Cursor (keyset) paginatsiya kirishi. */
53
+ interface CursorParams<T = Record<string, unknown>> extends Params<T> {
54
+ limit?: number;
55
+ cursor?: string | null;
56
+ cursorKey?: string;
57
+ order?: SortDirection;
58
+ direction?: "forward" | "backward";
59
+ }
60
+ /** Normalizatsiya qilingan payload (default field nomlari bilan). */
61
+ interface QueryPayload {
62
+ filter: FilterNode | FieldCondition[];
63
+ sort: Sort;
64
+ columns: Record<string, boolean>;
65
+ with: Record<string, unknown>;
66
+ }
67
+ interface ListPayload extends QueryPayload {
68
+ page: number;
69
+ perPage: number;
70
+ }
71
+ interface InfinitePayload extends QueryPayload {
72
+ limit: number;
73
+ offset: number;
74
+ }
75
+ /** Cursor payload — `sort` o'rniga `order`/`direction` boshqaradi. */
76
+ interface CursorPayload {
77
+ filter: FilterNode | FieldCondition[];
78
+ columns: Record<string, boolean>;
79
+ with: Record<string, unknown>;
80
+ limit: number;
81
+ cursor: string | null;
82
+ order: SortDirection;
83
+ direction: "forward" | "backward";
84
+ cursorKey?: string;
85
+ }
86
+ /**
87
+ * Xom (server, snake_case) meta tiplari — `@querykitjs/core`dan (adapter shu
88
+ * shaklda qaytaradi). Server ba'zi maydonlarni bermasligi mumkinligi uchun
89
+ * mapper'lar `Partial` qabul qiladi.
90
+ */
91
+ type RawMeta = Partial<Core.OffsetMeta>;
92
+ type RawInfiniteMeta = Partial<Core.InfiniteMeta>;
93
+ type RawCursorMeta = Partial<Core.CursorMeta>;
94
+ /** Offset (list) — normalizatsiya qilingan meta (camelCase). */
95
+ interface Meta {
96
+ totalPages: number;
97
+ totalCount: number;
98
+ currentPage: number;
99
+ perPage: number;
100
+ hasNext: boolean;
101
+ hasPrev: boolean;
102
+ }
103
+ /** Infinite-scroll — normalizatsiya qilingan meta. */
104
+ interface InfiniteMeta {
105
+ limit: number;
106
+ offset: number;
107
+ count: number;
108
+ hasMore: boolean;
109
+ nextOffset: number | null;
110
+ }
111
+ /** Cursor — normalizatsiya qilingan meta. */
112
+ interface CursorMeta {
113
+ limit: number;
114
+ hasNext: boolean;
115
+ hasPrev: boolean;
116
+ nextCursor: string | null;
117
+ prevCursor: string | null;
118
+ }
119
+
120
+ /** Keys of `T` whose value is assignable to `V`. */
121
+ type ValueKeys<T, V> = {
122
+ [K in keyof T]-?: NonNullable<T[K]> extends V ? Extract<K, string> : never;
123
+ }[keyof T];
124
+ /** String-valued field keys (for `contains`/`startsWith`/`like`/…). */
125
+ type StringKeys<T> = ValueKeys<T, string>;
126
+ /** Comparable field keys — string/number/bigint/Date (for `gt`/`between`/…). */
127
+ type ComparableKeys<T> = ValueKeys<T, string | number | bigint | Date>;
128
+ type Node<T> = FilterNode<T>;
129
+ /**
130
+ * Field-type-aware filter builder: string-match operators are offered only for
131
+ * string fields, comparison only for comparable fields, so nonsensical filters
132
+ * (e.g. `contains` on a number) are compile errors. Runtime is
133
+ * `@querykitjs/core`'s builder unchanged.
134
+ */
135
+ interface TypedFilters<T> {
136
+ eq<K extends FieldKey<T>>(key: K, value: FilterValue): FieldCondition<T>;
137
+ ne<K extends FieldKey<T>>(key: K, value: FilterValue): FieldCondition<T>;
138
+ gt<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;
139
+ gte<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;
140
+ lt<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;
141
+ lte<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;
142
+ between<K extends ComparableKeys<T>>(key: K, min: FilterScalar | Date, max: FilterScalar | Date): FieldCondition<T>;
143
+ range<K extends ComparableKeys<T>>(key: K, from: FilterScalar | Date, to: FilterScalar | Date): FieldCondition<T>[];
144
+ contains<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;
145
+ startsWith<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;
146
+ endsWith<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;
147
+ like<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;
148
+ ilike<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;
149
+ notLike<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;
150
+ in<K extends FieldKey<T>>(key: K, value: Array<string | number>): FieldCondition<T>;
151
+ notIn<K extends FieldKey<T>>(key: K, value: Array<string | number>): FieldCondition<T>;
152
+ isNull<K extends FieldKey<T>>(key: K): FieldCondition<T>;
153
+ isNotNull<K extends FieldKey<T>>(key: K): FieldCondition<T>;
154
+ and(...nodes: Node<T>[]): AndGroup<T>;
155
+ or(...nodes: Node<T>[]): OrGroup<T>;
156
+ not(node: Node<T>): NotGroup<T>;
157
+ }
158
+ /**
159
+ * Typed, ergonomic filter builder for an entity — field-name autocomplete plus
160
+ * field-type-aware operators (see {@link TypedFilters}).
161
+ *
162
+ * @typeParam T - the list entity type (`Buyer`, `Product`, …).
163
+ * @example
164
+ * ```ts
165
+ * const f = createFilters<Buyer>();
166
+ * const filter = f.and(f.contains("buyerName", s), f.gte("age", 18));
167
+ * // f.contains("age", …) → compile error (age is a number)
168
+ * ```
169
+ */
170
+ declare function createFilters<T = Record<string, unknown>>(): TypedFilters<T>;
171
+
172
+ /** Forbids the listed keys (`?: never`) so modes can't be mixed. */
173
+ type Without<K extends string> = {
174
+ [P in K]?: never;
175
+ };
176
+ /** Filter-key override, shared by the single-key modes. */
177
+ interface KeyBase {
178
+ /** Backend field key (defaults to the schema param name). */
179
+ key?: string;
180
+ }
181
+ /**
182
+ * **Simple** mode — one URL param → one condition. `operation` defaults to `"="`;
183
+ * `trim`/`default`/`split` shape the value.
184
+ */
185
+ interface SimpleField extends KeyBase {
186
+ /** Filter operation (default `"="`). */
187
+ operation?: FilterOperator;
188
+ /** Trim the string value. */
189
+ trim?: boolean;
190
+ /** Value used when the URL param is absent. */
191
+ default?: FilterValue;
192
+ /**
193
+ * For array operations (`in`/`notIn`): split a comma-string into an array.
194
+ * `true` → delimiter `","`; or a custom delimiter. Guarded: absent/empty →
195
+ * pruned; parts trimmed, empties dropped.
196
+ */
197
+ split?: boolean | string;
198
+ }
199
+ /** **Range** mode — `[fromParam, toParam]` → two inclusive conditions (`>=`, `<=`). */
200
+ interface RangeField extends KeyBase {
201
+ range: [string, string];
202
+ }
203
+ /** **Between** mode — `[fromParam, toParam]` → one `between` condition (2-tuple). */
204
+ interface BetweenField extends KeyBase {
205
+ between: [string, string];
206
+ }
207
+ /** **Search** mode — one URL param → OR of `contains` across these field keys. */
208
+ interface SearchField {
209
+ search: string[];
210
+ trim?: boolean;
211
+ default?: FilterValue;
212
+ }
213
+ /**
214
+ * One list field's URL→filter mapping. Exactly **one mode** per descriptor —
215
+ * Simple / Range / Between / Search — enforced at compile time (mixing e.g.
216
+ * `range` + `search`, or `range` + `between`, is a type error).
217
+ */
218
+ type FieldDescriptor = (SimpleField & Without<"range" | "between" | "search">) | (RangeField & Without<"operation" | "trim" | "default" | "split" | "between" | "search">) | (BetweenField & Without<"operation" | "trim" | "default" | "split" | "range" | "search">) | (SearchField & Without<"key" | "operation" | "split" | "range" | "between">);
219
+ /** URL param → {@link FieldDescriptor} map. */
220
+ type ListSchema = Record<string, FieldDescriptor>;
221
+ /**
222
+ * Declares a list filter schema (identity helper — preserves the literal type).
223
+ * Maps URL params to `{key, operation, value}` conditions so pages never build
224
+ * `IFilter[]` by hand.
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * const buyersSchema = defineListSchema({
229
+ * id: { operation: "=" },
230
+ * status: { operation: "=", default: "active" },
231
+ * ids: { operation: "in", split: true },
232
+ * q: { search: ["name", "email"] },
233
+ * createdAt: { range: ["fromDate", "toDate"] },
234
+ * });
235
+ * ```
236
+ */
237
+ declare function defineListSchema<S extends ListSchema>(schema: S): S;
238
+
239
+ /** URL param nomlari (sahifa/o'lcham/sort) — sozlanadigan. */
240
+ interface UrlConfig {
241
+ pageParam?: string;
242
+ sizeParam?: string;
243
+ sortParam?: string;
244
+ }
245
+ /** `"-createdAt"` → `{ name, direction }` (bo'sh bo'lsa `undefined`). */
246
+ declare function decodeSort(value: string | null | undefined): Sort | undefined;
247
+ /** `{ name, direction }` → `"-createdAt"` / `"createdAt"` (nomsiz bo'lsa `""`). */
248
+ declare function encodeSort(sort: Sort): string;
249
+ /**
250
+ * Schema + searchParams → filter. Applies `range`/`between`/`search`/`split`/
251
+ * `default`/`trim`; empty/absent params are dropped. Returns a flat
252
+ * `FieldCondition[]` (implicit AND), or a tree when a `search` OR-group is
253
+ * present (`{ and: [orGroup, …conditions] }`).
254
+ */
255
+ declare function schemaToFilter(schema: ListSchema, searchParams: URLSearchParams): Filter;
256
+ /** searchParams → normalizatsiyalanmagan {@link ListParams} (filter/sort/page/perPage). */
257
+ declare function readListParams(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): ListParams;
258
+ /** searchParams → to'liq, yuborishga tayyor {@link ListPayload}. */
259
+ declare function searchParamsToPayload(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): ListPayload;
260
+ /** Filter param'ini o'rnatadi/o'chiradi va `page`ni reset qiladi. */
261
+ declare function setParam(searchParams: URLSearchParams, name: string, value: string | null | undefined, url?: UrlConfig): URLSearchParams;
262
+ /** Sahifani o'rnatadi (`page` reset qilinmaydi). */
263
+ declare function setPage(searchParams: URLSearchParams, page: number, url?: UrlConfig): URLSearchParams;
264
+ /** Sahifa o'lchamini o'rnatadi va `page`ni reset qiladi. */
265
+ declare function setSize(searchParams: URLSearchParams, size: number, url?: UrlConfig): URLSearchParams;
266
+ /** Sortni o'rnatadi (`"-createdAt"` yoki `{name,direction}`) va `page`ni reset qiladi. */
267
+ declare function setSort(searchParams: URLSearchParams, sort: SortInput, url?: UrlConfig): URLSearchParams;
268
+ /** Barcha list param'larini tozalaydi (ixtiyoriy saqlanadigan kalitlar bilan). */
269
+ declare function resetParams(searchParams: URLSearchParams, keep?: string[]): URLSearchParams;
270
+
271
+ /**
272
+ * Per-backend `with` (relation-loading) config shapes. querykit unifies
273
+ * filter/sort/pagination, but relation loading differs per ORM — so the registry
274
+ * types `with` from the chosen `adapter`. Only JSON-serializable, wire-safe
275
+ * options are typed; function callbacks (e.g. Drizzle `where: (f,op)=>…`) and raw
276
+ * SQL are deliberately **never** included — you can't send them over JSON.
277
+ */
278
+ /** Mongoose `populate` config (serializable subset). */
279
+ interface MongoosePopulate {
280
+ select?: string;
281
+ match?: Record<string, unknown>;
282
+ options?: Record<string, unknown>;
283
+ populate?: string | MongoosePopulate | Record<string, boolean | MongoosePopulate>;
284
+ }
285
+ /** Drizzle relational `with` config (serializable subset — no `where`/`orderBy` fns, no SQL). */
286
+ interface DrizzleWith {
287
+ columns?: Record<string, boolean>;
288
+ with?: Record<string, boolean | DrizzleWith>;
289
+ limit?: number;
290
+ offset?: number;
291
+ }
292
+ /** Prisma relation config (serializable subset). */
293
+ interface PrismaInclude {
294
+ select?: Record<string, boolean>;
295
+ include?: Record<string, boolean | PrismaInclude>;
296
+ where?: Record<string, unknown>;
297
+ orderBy?: Record<string, unknown>;
298
+ take?: number;
299
+ skip?: number;
300
+ }
301
+ /** Supported registry backend adapters. */
302
+ type AdapterName = "mongoose" | "drizzle-pg" | "drizzle-sqlite" | "prisma-pg";
303
+ /** The per-relation `with` value shape for each adapter. */
304
+ interface AdapterWithConfig {
305
+ mongoose: boolean | MongoosePopulate;
306
+ "drizzle-pg": boolean | DrizzleWith;
307
+ "drizzle-sqlite": boolean | DrizzleWith;
308
+ "prisma-pg": boolean | PrismaInclude;
309
+ }
310
+ /** `with` map typed for an adapter: relation name → its config (boolean or object). */
311
+ type WithFor<A extends AdapterName> = Record<string, AdapterWithConfig[A]>;
312
+
313
+ type ResourceListParams<T, A extends AdapterName> = Omit<ListParams<T>, "with"> & {
314
+ with?: WithFor<A>;
315
+ };
316
+ type ResourceInfiniteParams<T, A extends AdapterName> = Omit<InfiniteParams<T>, "with"> & {
317
+ with?: WithFor<A>;
318
+ };
319
+ type ResourceCursorParams<T, A extends AdapterName> = Omit<CursorParams<T>, "with"> & {
320
+ with?: WithFor<A>;
321
+ };
322
+ type ResourceParams<T, A extends AdapterName> = Omit<Params<T>, "with"> & {
323
+ with?: WithFor<A>;
324
+ };
325
+ interface RawResponse<T, M> {
326
+ data?: T[];
327
+ meta?: M | null;
328
+ }
329
+ interface ListResult<T> {
330
+ data: T[];
331
+ meta: Meta;
332
+ }
333
+ interface InfiniteResult<T> {
334
+ data: T[];
335
+ meta: InfiniteMeta;
336
+ }
337
+ interface CursorResult<T> {
338
+ data: T[];
339
+ meta: CursorMeta;
340
+ }
341
+ interface ResourceKeys {
342
+ all: readonly unknown[];
343
+ list(payload: unknown): readonly unknown[];
344
+ infinite(payload: unknown): readonly unknown[];
345
+ cursor(payload: unknown): readonly unknown[];
346
+ detail(id: unknown): readonly unknown[];
347
+ }
348
+ interface Resource<T, A extends AdapterName> {
349
+ /** Build an offset (page) payload. */
350
+ list(input?: ResourceListParams<T, A>): ListPayload;
351
+ /** Build an infinite (limit/offset) payload. */
352
+ infinite(input?: ResourceInfiniteParams<T, A>): InfinitePayload;
353
+ /** Build a cursor (keyset) payload. */
354
+ cursor(input?: ResourceCursorParams<T, A>): CursorPayload;
355
+ /** Build a paginationless payload (filter/sort/columns/with). */
356
+ params(input?: ResourceParams<T, A>): QueryPayload;
357
+ /** Filter builder typed to `T`'s fields. */
358
+ f: ReturnType<typeof createFilters<T>>;
359
+ /** Search preset — OR of `contains` across `fields` (e.g. one input → many columns). */
360
+ search(term: string, fields: FieldKey<T>[]): Filter<T>;
361
+ /** Declare a URL↔filter schema (identity helper). */
362
+ schema<S extends ListSchema>(s: S): S;
363
+ /** Build a list payload from URL search params (SSR — the non-hook `useListParams`). */
364
+ fromSearchParams(searchParams: URLSearchParams, options: {
365
+ schema: ListSchema;
366
+ url?: UrlConfig;
367
+ with?: WithFor<A>;
368
+ }): ListPayload;
369
+ /** Stable query keys for TanStack/SWR caches. */
370
+ keys: ResourceKeys;
371
+ /** Map a list response's meta to camelCase (`data` typed to `T`). */
372
+ parseList(raw?: RawResponse<T, RawMeta> | null): ListResult<T>;
373
+ parseInfinite(raw?: RawResponse<T, RawInfiniteMeta> | null): InfiniteResult<T>;
374
+ parseCursor(raw?: RawResponse<T, RawCursorMeta> | null): CursorResult<T>;
375
+ }
376
+ interface RegistryDefaults {
377
+ /** `list` page size. */
378
+ perPage?: number;
379
+ /** `infinite` + `cursor` page size. */
380
+ limit?: number;
381
+ /** `list`/`infinite` sort (`"-createdAt"` or `{name,direction}`). */
382
+ sort?: SortInput;
383
+ /** Cursor-only defaults. */
384
+ cursor?: {
385
+ order?: SortDirection;
386
+ };
387
+ }
388
+ interface RegistryConfig<A extends AdapterName> {
389
+ adapter: A;
390
+ defaults?: RegistryDefaults;
391
+ /** Drop empty filter values built from form inputs (default `true`). */
392
+ pruneEmpty?: boolean;
393
+ }
394
+ interface Registry<A extends AdapterName> {
395
+ readonly adapter: A;
396
+ /** Entity-typed builders + filters + schema + keys + parsers. `name` = cache-key namespace (required, must be unique). */
397
+ resource<T>(name: string): Resource<T, A>;
398
+ /** Registry-level meta parsing (entity-agnostic — `data: unknown[]`). */
399
+ parseList(raw?: RawResponse<unknown, RawMeta> | null): ListResult<unknown>;
400
+ parseInfinite(raw?: RawResponse<unknown, RawInfiniteMeta> | null): InfiniteResult<unknown>;
401
+ parseCursor(raw?: RawResponse<unknown, RawCursorMeta> | null): CursorResult<unknown>;
402
+ }
403
+ /**
404
+ * Create a web query registry — configure defaults + backend adapter once, then
405
+ * `registry.resource<T>()` yields entity-typed, adapter-aware query builders,
406
+ * filters, a URL↔filter schema, cache keys and meta parsers.
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * export const qk = createRegistry({ adapter: "mongoose", defaults: { perPage: 20, sort: "-createdAt" } });
411
+ * const users = qk.resource<IUser>("users");
412
+ * const body = users.list({ filter: users.f.eq("status", "active"), page });
413
+ * ```
414
+ */
415
+ declare function createRegistry<A extends AdapterName>(config: RegistryConfig<A>): Registry<A>;
416
+
417
+ export { resetParams as $, type AdapterName as A, type ResourceCursorParams as B, type CursorParams as C, type DrizzleWith as D, type ResourceInfiniteParams as E, type Filter as F, type ResourceKeys as G, type ResourceListParams as H, type InfiniteParams as I, type ResourceParams as J, type SortDirection as K, type ListParams as L, type Meta as M, type NotGroup as N, type OrGroup as O, type Params as P, type QueryPayload as Q, type RawCursorMeta as R, type Sort as S, createFilters as T, type UrlConfig as U, createRegistry as V, type WithFor as W, decodeSort as X, defineListSchema as Y, encodeSort as Z, readListParams as _, type CursorPayload as a, schemaToFilter as a0, searchParamsToPayload as a1, setPage as a2, setParam as a3, setSize as a4, setSort as a5, type InfinitePayload as b, type ListPayload as c, type FieldCondition as d, type FilterNode as e, type SortInput as f, type AndGroup as g, type CursorMeta as h, type CursorResult as i, type FieldDescriptor as j, type FieldKey as k, type FilterOperator as l, type FilterScalar as m, type FilterValue as n, type InfiniteMeta as o, type InfiniteResult as p, type ListResult as q, type ListSchema as r, type MongoosePopulate as s, type PrismaInclude as t, type RawInfiniteMeta as u, type RawMeta as v, type Registry as w, type RegistryConfig as x, type RegistryDefaults as y, type Resource as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@querykitjs/web",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Frontend query-building for querykit — typed filters, pagination params & URL sync. Zero-dependency; you send the request.",
5
5
  "type": "module",
6
6
  "author": {
@@ -50,19 +50,24 @@
50
50
  "test:smoke": "bun run test/smoke.ts"
51
51
  },
52
52
  "dependencies": {
53
- "@querykitjs/core": "1.0.0"
53
+ "@querykitjs/core": "^1.0.0"
54
54
  },
55
55
  "peerDependencies": {
56
- "react": ">=18"
56
+ "react": ">=18",
57
+ "react-router-dom": ">=6"
57
58
  },
58
59
  "peerDependenciesMeta": {
59
60
  "react": {
60
61
  "optional": true
62
+ },
63
+ "react-router-dom": {
64
+ "optional": true
61
65
  }
62
66
  },
63
67
  "devDependencies": {
64
68
  "@types/react": "^19.0.0",
65
- "react": "^19.0.0"
69
+ "react": "^19.0.0",
70
+ "react-router-dom": "^7.0.0"
66
71
  },
67
72
  "keywords": [
68
73
  "querykit",
@@ -1,180 +0,0 @@
1
- import * as _querykitjs_core from '@querykitjs/core';
2
-
3
- /**
4
- * Filter/query DSL tiplari — `@querykitjs/core`dan, entity maydoni (`FieldKey`)
5
- * bilan ixtisoslashtirilgan. querykit backend (`@querykitjs/drizzle-pg`) qabul
6
- * qiladigan wire-format bilan mos (`{key, operation, value}`).
7
- */
8
-
9
- type FilterOperator = _querykitjs_core.FilterOperator;
10
- type FilterScalar = _querykitjs_core.FilterScalar;
11
- type FilterValue = _querykitjs_core.FilterValue;
12
- /** Entity ustun (maydon) kaliti. */
13
- type FieldKey<T> = Extract<keyof T, string>;
14
- /** Bitta maydon sharti (`operation` default `"="`). */
15
- type FieldCondition<T = Record<string, unknown>> = _querykitjs_core.FieldCondition<FieldKey<T>>;
16
- type AndGroup<T = Record<string, unknown>> = _querykitjs_core.AndGroup<FieldKey<T>>;
17
- type OrGroup<T = Record<string, unknown>> = _querykitjs_core.OrGroup<FieldKey<T>>;
18
- type NotGroup<T = Record<string, unknown>> = _querykitjs_core.NotGroup<FieldKey<T>>;
19
- /** Filter daraxti tuguni: shart yoki mantiqiy guruh. */
20
- type FilterNode<T = Record<string, unknown>> = _querykitjs_core.FilterNode<FieldKey<T>>;
21
- /**
22
- * Public filter: daraxt/tugun yoki flat massiv. Flat massiv implicit `AND` va
23
- * legacy backend (idistr) `IFilter[]` bilan to'liq mos.
24
- */
25
- type Filter<T = Record<string, unknown>> = _querykitjs_core.Filter<FieldKey<T>>;
26
- type SortDirection = _querykitjs_core.SortDirection;
27
- interface Sort {
28
- name?: string;
29
- direction?: SortDirection;
30
- }
31
- /** Sort kirishi: `"-createdAt"` (sortType string) yoki `{ name, direction }`. */
32
- type SortInput = string | Sort;
33
- interface Params<T = Record<string, unknown>> {
34
- filter?: Filter<T>;
35
- sort?: SortInput;
36
- columns?: Record<string, boolean>;
37
- /** Yuklanadigan relationlar (default `with` deb yuboriladi). */
38
- with?: Record<string, unknown>;
39
- /** Soft-delete qilingan qatorlarni ham qo'shish (backend read'lari uchun). */
40
- withDeleted?: boolean;
41
- }
42
- /** Offset (sahifali) paginatsiya kirishi. */
43
- interface ListParams<T = Record<string, unknown>> extends Params<T> {
44
- page?: number;
45
- perPage?: number;
46
- }
47
- /** Infinite-scroll (limit + offset) paginatsiya kirishi. */
48
- interface InfiniteParams<T = Record<string, unknown>> extends Params<T> {
49
- limit?: number;
50
- offset?: number;
51
- }
52
- /** Cursor (keyset) paginatsiya kirishi. */
53
- interface CursorParams<T = Record<string, unknown>> extends Params<T> {
54
- limit?: number;
55
- cursor?: string | null;
56
- cursorKey?: string;
57
- order?: SortDirection;
58
- direction?: "forward" | "backward";
59
- }
60
- /** Normalizatsiya qilingan payload (default field nomlari bilan). */
61
- interface QueryPayload {
62
- filter: FilterNode | FieldCondition[];
63
- sort: Sort;
64
- columns: Record<string, boolean>;
65
- with: Record<string, unknown>;
66
- }
67
- interface ListPayload extends QueryPayload {
68
- page: number;
69
- perPage: number;
70
- }
71
- interface InfinitePayload extends QueryPayload {
72
- limit: number;
73
- offset: number;
74
- }
75
- /** Cursor payload — `sort` o'rniga `order`/`direction` boshqaradi. */
76
- interface CursorPayload {
77
- filter: FilterNode | FieldCondition[];
78
- columns: Record<string, boolean>;
79
- with: Record<string, unknown>;
80
- limit: number;
81
- cursor: string | null;
82
- order: SortDirection;
83
- direction: "forward" | "backward";
84
- cursorKey?: string;
85
- }
86
- /**
87
- * Xom (server, snake_case) meta tiplari — `@querykitjs/core`dan (adapter shu
88
- * shaklda qaytaradi). Server ba'zi maydonlarni bermasligi mumkinligi uchun
89
- * mapper'lar `Partial` qabul qiladi.
90
- */
91
- type RawMeta = Partial<_querykitjs_core.OffsetMeta>;
92
- type RawInfiniteMeta = Partial<_querykitjs_core.InfiniteMeta>;
93
- type RawCursorMeta = Partial<_querykitjs_core.CursorMeta>;
94
- /** Offset (list) — normalizatsiya qilingan meta (camelCase). */
95
- interface Meta {
96
- totalPages: number;
97
- totalCount: number;
98
- currentPage: number;
99
- perPage: number;
100
- hasNext: boolean;
101
- hasPrev: boolean;
102
- }
103
- /** Infinite-scroll — normalizatsiya qilingan meta. */
104
- interface InfiniteMeta {
105
- limit: number;
106
- offset: number;
107
- count: number;
108
- hasMore: boolean;
109
- nextOffset: number | null;
110
- }
111
- /** Cursor — normalizatsiya qilingan meta. */
112
- interface CursorMeta {
113
- limit: number;
114
- hasNext: boolean;
115
- hasPrev: boolean;
116
- nextCursor: string | null;
117
- prevCursor: string | null;
118
- }
119
-
120
- /**
121
- * Bitta list maydonining deklarativ ta'rifi: URL param → filter shartiga qanday
122
- * aylantirilishi. `key` berilmasa param nomi ishlatiladi; `operation` default `=`.
123
- */
124
- interface FieldDescriptor {
125
- /** Backend ustun kaliti (default — schema'dagi param nomi). */
126
- key?: string;
127
- /** Filter operatori (default `"="`). */
128
- operation?: FilterOperator;
129
- /** String qiymatni trim qilish. */
130
- trim?: boolean;
131
- /** Diapazon: `[fromParam, toParam]` URL param nomlari → `>=` va `<=` shartlar. */
132
- range?: [string, string];
133
- }
134
- /** URL param → {@link FieldDescriptor} tavsiflar to'plami. */
135
- type ListSchema = Record<string, FieldDescriptor>;
136
- /**
137
- * List filter schema'sini e'lon qiladi (identity helper — tiplarni saqlaydi).
138
- * URL param'larni `{key, operation}` shartlariga bog'laydi, shu bilan har
139
- * sahifada qo'lda `IFilter[]` qurishni bartaraf qiladi.
140
- *
141
- * @example
142
- * ```ts
143
- * const buyersSchema = defineListSchema({
144
- * id: { operation: "=" },
145
- * buyerName: { operation: "%_%", trim: true },
146
- * status: { operation: "=" },
147
- * createdAt: { range: ["fromDate", "toDate"] },
148
- * });
149
- * ```
150
- */
151
- declare function defineListSchema<S extends ListSchema>(schema: S): S;
152
-
153
- /** URL param nomlari (sahifa/o'lcham/sort) — sozlanadigan. */
154
- interface UrlConfig {
155
- pageParam?: string;
156
- sizeParam?: string;
157
- sortParam?: string;
158
- }
159
- /** `"-createdAt"` → `{ name, direction }` (bo'sh bo'lsa `undefined`). */
160
- declare function decodeSort(value: string | null | undefined): Sort | undefined;
161
- /** `{ name, direction }` → `"-createdAt"` / `"createdAt"` (nomsiz bo'lsa `""`). */
162
- declare function encodeSort(sort: Sort): string;
163
- /** Schema + searchParams → `FieldCondition[]` (bo'sh param'lar tashlanadi). */
164
- declare function schemaToFilter(schema: ListSchema, searchParams: URLSearchParams): FieldCondition[];
165
- /** searchParams → normalizatsiyalanmagan {@link ListParams} (filter/sort/page/perPage). */
166
- declare function readListParams(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): ListParams;
167
- /** searchParams → to'liq, yuborishga tayyor {@link ListPayload}. */
168
- declare function searchParamsToPayload(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): ListPayload;
169
- /** Filter param'ini o'rnatadi/o'chiradi va `page`ni reset qiladi. */
170
- declare function setParam(searchParams: URLSearchParams, name: string, value: string | null | undefined, url?: UrlConfig): URLSearchParams;
171
- /** Sahifani o'rnatadi (`page` reset qilinmaydi). */
172
- declare function setPage(searchParams: URLSearchParams, page: number, url?: UrlConfig): URLSearchParams;
173
- /** Sahifa o'lchamini o'rnatadi va `page`ni reset qiladi. */
174
- declare function setSize(searchParams: URLSearchParams, size: number, url?: UrlConfig): URLSearchParams;
175
- /** Sortni o'rnatadi (`"-createdAt"` yoki `{name,direction}`) va `page`ni reset qiladi. */
176
- declare function setSort(searchParams: URLSearchParams, sort: SortInput, url?: UrlConfig): URLSearchParams;
177
- /** Barcha list param'larini tozalaydi (ixtiyoriy saqlanadigan kalitlar bilan). */
178
- declare function resetParams(searchParams: URLSearchParams, keep?: string[]): URLSearchParams;
179
-
180
- export { type AndGroup as A, setSize as B, type CursorParams as C, setSort as D, type FieldKey as F, type InfiniteParams as I, type ListParams as L, type Meta as M, type NotGroup as N, type OrGroup as O, type Params as P, type QueryPayload as Q, type RawCursorMeta as R, type Sort as S, type UrlConfig as U, type CursorPayload as a, type InfinitePayload as b, type ListPayload as c, type Filter as d, type FieldCondition as e, type FilterNode as f, type SortInput as g, type CursorMeta as h, type RawInfiniteMeta as i, type InfiniteMeta as j, type RawMeta as k, type FieldDescriptor as l, type FilterOperator as m, type FilterScalar as n, type FilterValue as o, type ListSchema as p, type SortDirection as q, decodeSort as r, defineListSchema as s, encodeSort as t, readListParams as u, resetParams as v, schemaToFilter as w, searchParamsToPayload as x, setPage as y, setParam as z };