@querykitjs/web 4.0.0 → 4.1.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 +101 -15
- package/README.md +102 -16
- package/dist/angular/index.cjs +2 -0
- package/dist/angular/index.cjs.map +1 -0
- package/dist/angular/index.d.cts +70 -0
- package/dist/angular/index.d.ts +70 -0
- package/dist/angular/index.js +2 -0
- package/dist/angular/index.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -4
- package/dist/index.d.ts +48 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/dist/{registry-DOVi_zCU.d.cts → registry-CEq4xFui.d.cts} +46 -44
- package/dist/{registry-DOVi_zCU.d.ts → registry-CEq4xFui.d.ts} +46 -44
- package/dist/vue/index.cjs +2 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.cts +64 -0
- package/dist/vue/index.d.ts +64 -0
- package/dist/vue/index.js +2 -0
- package/dist/vue/index.js.map +1 -0
- package/package.json +67 -6
- package/skills/querykit-web/SKILL.md +63 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/route-query.ts","../../src/url.ts","../../src/list-state.ts","../../src/angular/inject-list-params-base.ts","../../src/angular/inject-list-params.ts"],"names":["searchParamsToQuery","searchParams","query","key","values","URL_DEFAULTS","encodeSort","sort","i","clone","setParam","name","value","url","cfg","next","setPage","page","setSize","size","setSort","encoded","resetParams","keep","createListState","resource","options","schema","withRel","params","injectListParamsBase","setSearchParams","state","read","computed","actions","paramMapToSearchParams","paramMap","injectListParams","route","inject","ActivatedRoute","router","Router","toSignal"],"mappings":"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","file":"index.js","sourcesContent":["/**\n^ * A route query as vue-router gives it: v4 has `string | null | (string | null)[]` per key,\n * v5 always an array. `null` is a key without `=` (`?q`).\n */\nexport type RouteQuery = Record<string, string | null | (string | null)[] | undefined>;\n\n/** Route query → search params: a repeated key keeps every value; `null` becomes an empty value. */\nexport function queryToSearchParams(query: RouteQuery): URLSearchParams {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n for (const item of Array.isArray(value) ? value : [value]) {\n if (item !== undefined) searchParams.append(key, item ?? \"\");\n }\n }\n return searchParams;\n}\n\n/** Search params → route query for `router.push({ query })`: one value → string, a repeated key → array. */\nexport function searchParamsToQuery(searchParams: URLSearchParams): Record<string, string | string[]> {\n const query: Record<string, string | string[]> = {};\n for (const key of new Set(searchParams.keys())) {\n const values = searchParams.getAll(key);\n query[key] = values.length > 1 ? values : (values[0] ?? \"\");\n }\n return query;\n}\n","import { DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_PER_PAGE } from \"@querykitjs/core\";\n\nimport { buildListParams, clampInt } from \"./query\";\nimport type { FieldDescriptor, ListSchema } from \"./schema\";\nimport type { FieldCondition, Filter, FilterNode, FilterValue, ListParams, ListPayload, Sort, SortDirection, SortInput } from \"./types\";\n\n/** URL param nomlari (sahifa/o'lcham/sort) — sozlanadigan. */\nexport interface UrlConfig {\n pageParam?: string;\n sizeParam?: string;\n sortParam?: string;\n}\n\nconst URL_DEFAULTS: Required<UrlConfig> = {\n pageParam: \"page\",\n sizeParam: \"size\",\n sortParam: \"sortType\",\n};\n\n/**\n * `\"-createdAt,id,-appNumber\"` → `[{ key, direction }, …]` — comma-separated,\n * order preserved, `-` prefix = `desc` (else `asc`). Empty → `undefined`.\n */\nexport function decodeSort(value: string | null | undefined): Sort | undefined {\n if (!value) return undefined;\n const items = value\n .split(\",\")\n .map(s => s.trim())\n .filter(Boolean)\n .map(tok => {\n const desc = tok.startsWith(\"-\");\n return { key: desc ? tok.slice(1) : tok, direction: (desc ? \"desc\" : \"asc\") as SortDirection };\n })\n .filter(i => i.key); // drop empty keys (e.g. a lone \"-\")\n return items.length ? items : undefined;\n}\n\n/** `[{ key, direction }, …]` (or `\"-field\"` shorthand strings) → `\"-createdAt,id,-appNumber\"` (empty → `\"\"`). */\nexport function encodeSort(sort: SortInput): string {\n return sort\n .map(i => (typeof i === \"string\" ? i.trim() : i && i.key ? (i.direction === \"desc\" ? \"-\" : \"\") + i.key : \"\"))\n .filter(Boolean)\n .join(\",\");\n}\n\n/**\n * Schema + searchParams → filter. Applies `range`/`between`/`search`/`split`/\n * `default`/`trim`; empty/absent params are dropped. Returns a flat\n * `FieldCondition[]` (implicit AND), or a tree when a `search` OR-group is\n * present (`{ and: [orGroup, …conditions] }`).\n */\nexport function schemaToFilter(schema: ListSchema, searchParams: URLSearchParams): Filter {\n const conditions: FieldCondition[] = [];\n const groups: FilterNode[] = [];\n\n for (const [param, d] of Object.entries(schema) as [string, FieldDescriptor][]) {\n const key = d.key ?? param;\n\n // range → two inclusive conditions (>= , <=)\n if (d.range) {\n const from = searchParams.get(d.range[0]);\n const to = searchParams.get(d.range[1]);\n if (from) conditions.push(cond(key, \">=\", from));\n if (to) conditions.push(cond(key, \"<=\", to));\n continue;\n }\n\n // between → one condition with a 2-tuple value\n if (d.between) {\n const from = searchParams.get(d.between[0]);\n const to = searchParams.get(d.between[1]);\n if (from && to) conditions.push(cond(key, \"between\", [from, to]));\n continue;\n }\n\n // read value, falling back to `default` only when the param is ABSENT\n // (an empty `?x=` means the user cleared the filter → prune, don't default).\n const raw = searchParams.get(param);\n let value: FilterValue | undefined = raw !== null ? raw : d.default;\n if (typeof value === \"string\" && d.trim) value = value.trim();\n if (value === undefined || value === null || value === \"\") continue;\n if (Array.isArray(value) && value.length === 0) continue;\n\n // search → OR of `contains` across the listed fields (needs a string)\n if (d.search && typeof value === \"string\") {\n groups.push({ or: d.search.map(field => cond(field, \"%_%\", value as string)) });\n continue;\n }\n\n // split → comma-string → array (for `in`/`notIn`); guarded against empties\n if (d.split && typeof value === \"string\") {\n const delimiter = d.split === true ? \",\" : d.split;\n const parts = value\n .split(delimiter)\n .map(s => s.trim())\n .filter(Boolean);\n if (parts.length === 0) continue;\n value = parts;\n }\n\n conditions.push(cond(key, d.operation ?? \"=\", value));\n }\n\n return groups.length === 0 ? conditions : { and: [...groups, ...conditions] };\n}\n\nfunction cond(key: string, operation: FieldCondition[\"operation\"], value: FilterValue): FieldCondition {\n return { key, operation, value };\n}\n\n/**\n * The bounds the URL readers clamp to — the builder's own (`createRegistry`\n * `defaults`); an absent one is the core default.\n */\nexport interface UrlLimits {\n perPage?: number;\n maxPerPage?: number;\n maxOffset?: number;\n maxSortFields?: number;\n}\n\n/** {@link ListParams} read from a URL. `clamped` — the URL's page or sort was cut to the limits. */\nexport type UrlListParams = ListParams & { clamped: boolean };\n\n/**\n * A list payload built from a URL. `clamped` is non-enumerable: readable in code,\n * never serialized, so the wire payload is unchanged.\n */\nexport type UrlListPayload = ListPayload & { readonly clamped?: boolean };\n\n/** Marks a payload with a non-enumerable `clamped` flag. */\nexport function withClamped(payload: ListPayload, clamped: boolean): UrlListPayload {\n return Object.defineProperty(payload, \"clamped\", { value: clamped, enumerable: false });\n}\n\n/** The last page the builder accepts: `(page - 1) × perPage ≤ maxOffset`. */\nfunction lastPage(perPage: number | undefined, limits: UrlLimits): number {\n const resolved = clampInt(perPage, limits.perPage ?? DEFAULT_PER_PAGE, limits.maxPerPage ?? DEFAULT_MAX_PER_PAGE);\n return Math.floor((limits.maxOffset ?? DEFAULT_MAX_OFFSET) / resolved) + 1;\n}\n\n/**\n * searchParams → normalizatsiyalanmagan {@link ListParams} (filter/sort/page/perPage).\n * The URL is user input: a page past `maxOffset` becomes the last allowed page and a\n * sort past `maxSortFields` keeps its first fields, with `clamped: true` — so a\n * hand-edited `?page=9999` never throws during render. The builders still throw\n * for a direct call.\n */\nexport function readListParams(schema: ListSchema, searchParams: URLSearchParams, url: UrlConfig = {}, limits: UrlLimits = {}): UrlListParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const size = searchParams.get(cfg.sizeParam);\n const perPage = size ? Number(size) : undefined;\n const page = Math.trunc(Number(searchParams.get(cfg.pageParam))) || 1;\n const sort = decodeSort(searchParams.get(cfg.sortParam));\n const maxPage = lastPage(perPage, limits);\n const maxSortFields = limits.maxSortFields ?? DEFAULT_MAX_SORT_FIELDS;\n const isPageClamped = page > maxPage;\n const isSortClamped = sort !== undefined && sort.length > maxSortFields;\n return {\n filter: schemaToFilter(schema, searchParams),\n sort: isSortClamped ? sort.slice(0, maxSortFields) : sort,\n page: isPageClamped ? maxPage : page,\n perPage,\n clamped: isPageClamped || isSortClamped,\n };\n}\n\n/** searchParams → to'liq, yuborishga tayyor {@link ListPayload} (core default limits; clamped like {@link readListParams}). */\nexport function searchParamsToPayload(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): UrlListPayload {\n const params = readListParams(schema, searchParams, url);\n return withClamped(buildListParams(params), params.clamped);\n}\n\n/* ------------------------- URL yozish (immutable) ------------------------- */\n/* Har biri YANGI URLSearchParams qaytaradi; filter/sort o'zgarsa `page` reset. */\n\nfunction clone(searchParams: URLSearchParams): URLSearchParams {\n return new URLSearchParams(searchParams);\n}\n\n/** Filter param'ini o'rnatadi/o'chiradi va `page`ni reset qiladi. */\nexport function setParam(searchParams: URLSearchParams, name: string, value: string | null | undefined, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n if (value === null || value === undefined || value === \"\") next.delete(name);\n else next.set(name, value);\n return next;\n}\n\n/** Sahifani o'rnatadi (`page` reset qilinmaydi). */\nexport function setPage(searchParams: URLSearchParams, page: number, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.set(cfg.pageParam, String(page));\n return next;\n}\n\n/** Sahifa o'lchamini o'rnatadi va `page`ni reset qiladi. */\nexport function setSize(searchParams: URLSearchParams, size: number, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n next.set(cfg.sizeParam, String(size));\n return next;\n}\n\n/** Sortni o'rnatadi (`[{ key, direction }, …]`) va `page`ni reset qiladi. */\nexport function setSort(searchParams: URLSearchParams, sort: SortInput, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n const encoded = encodeSort(sort);\n if (encoded) next.set(cfg.sortParam, encoded);\n else next.delete(cfg.sortParam);\n return next;\n}\n\n/** Barcha list param'larini tozalaydi (ixtiyoriy saqlanadigan kalitlar bilan). */\nexport function resetParams(searchParams: URLSearchParams, keep: string[] = []): URLSearchParams {\n const next = new URLSearchParams();\n for (const key of keep) {\n const value = searchParams.get(key);\n if (value !== null) next.set(key, value);\n }\n return next;\n}\n","import type { AdapterName, WithFor } from \"./adapter\";\nimport type { Resource } from \"./registry\";\nimport type { ListSchema } from \"./schema\";\nimport type { ListPayload, SortInput } from \"./types\";\nimport type { UrlConfig } from \"./url\";\nimport { resetParams, setPage, setParam, setSize, setSort } from \"./url\";\n\nexport interface ListStateOptions<A extends AdapterName> {\n /** URL↔filter schema ({@link defineListSchema} / `resource.schema`). */\n schema: ListSchema;\n /** URL param names (page/size/sortType) — optional. */\n url?: UrlConfig;\n /** Fixed relations to load on every request (not URL-driven). */\n with?: WithFor<A>;\n}\n\nexport interface ListStateRead {\n /** Ready-to-send list payload (built from the URL via the resource's defaults). */\n params: ListPayload;\n /** The URL's page or sort was past the limits and was clamped (`?page=9999` → the last allowed page). */\n clamped: boolean;\n}\n\n/** URL setters: each returns the NEXT search params and never mutates the given ones. */\nexport interface ListStateActions {\n /** Set/clear a filter param (resets `page`). */\n setParam: (name: string, value: string | null | undefined) => URLSearchParams;\n setPage: (page: number) => URLSearchParams;\n /** Resets `page`. */\n setSize: (size: number) => URLSearchParams;\n /** Resets `page`; an empty sort clears the param. */\n setSort: (sort: SortInput) => URLSearchParams;\n /** Clears every param except `keep`. */\n reset: (keep?: string[]) => URLSearchParams;\n}\n\nexport interface ListState {\n read: (searchParams: URLSearchParams) => ListStateRead;\n actions: (searchParams: URLSearchParams) => ListStateActions;\n}\n\n/**\n * Framework-free list URL state — the logic behind `useListParams` in `@querykitjs/web/react`\n * and `@querykitjs/web/vue`, for any other framework (Svelte, Solid, vanilla). Pure: it reads\n * search params and returns the next ones; navigating is the caller's job.\n *\n * @example\n * ```ts\n * const list = createListState(users, { schema: usersSchema });\n * const { params, clamped } = list.read(new URLSearchParams(location.search));\n * history.pushState(null, \"\", `?${list.actions(new URLSearchParams(location.search)).setPage(2)}`);\n * ```\n */\nexport function createListState<T, A extends AdapterName>(resource: Resource<T, A>, options: ListStateOptions<A>): ListState {\n const { schema, url, with: withRel } = options;\n return {\n read(searchParams) {\n const params = resource.fromSearchParams(searchParams, { schema, url, with: withRel });\n return { params, clamped: params.clamped === true };\n },\n actions(searchParams) {\n return {\n setParam: (name, value) => setParam(searchParams, name, value, url),\n setPage: page => setPage(searchParams, page, url),\n setSize: size => setSize(searchParams, size, url),\n setSort: sort => setSort(searchParams, sort, url),\n reset: keep => resetParams(searchParams, keep),\n };\n },\n };\n}\n","import { computed, type Signal } from \"@angular/core\";\n\nimport type { AdapterName, WithFor } from \"../adapter\";\nimport { createListState } from \"../list-state\";\nimport type { Resource } from \"../registry\";\nimport type { ListSchema } from \"../schema\";\nimport type { ListPayload, SortInput } from \"../types\";\nimport type { UrlConfig } from \"../url\";\n\nexport interface InjectListParamsBaseOptions<A extends AdapterName> {\n /** URL↔filter schema ({@link defineListSchema} / `resource.schema`). */\n schema: ListSchema;\n /** Current URL search params as a signal (from your router). */\n searchParams: Signal<URLSearchParams>;\n /** Apply new search params (`(next) => void`). */\n setSearchParams: (next: URLSearchParams) => void;\n /** URL param names (page/size/sortType) — optional. */\n url?: UrlConfig;\n /** Fixed relations to load on every request (not URL-driven). */\n with?: WithFor<A>;\n}\n\nexport interface InjectListParamsResult {\n /** Ready-to-send list payload (built from the URL via the resource's defaults). */\n params: Signal<ListPayload>;\n /**\n * The URL's page or sort was past the limits and was clamped (`?page=9999` → the last\n * allowed page). The app may rewrite the URL (`setPage(params().page)`).\n */\n clamped: Signal<boolean>;\n searchParams: Signal<URLSearchParams>;\n /** Set/clear a filter param (resets `page`). */\n setParam: (name: string, value: string | null | undefined) => void;\n setPage: (page: number) => void;\n /** Resets `page`. */\n setSize: (size: number) => void;\n /** Resets `page`; an empty sort clears the param. */\n setSort: (sort: SortInput) => void;\n /** Clears every param except `keep`. */\n reset: (keep?: string[]) => void;\n}\n\n/**\n * Router-agnostic list URL state as signals — the Angular twin of the React and Vue\n * `useListParamsBase`: the same reads, clamping and setters. Bring your own\n * `searchParams` signal and `setSearchParams`.\n */\nexport function injectListParamsBase<T, A extends AdapterName>(resource: Resource<T, A>, options: InjectListParamsBaseOptions<A>): InjectListParamsResult {\n const { schema, searchParams, setSearchParams, url, with: withRel } = options;\n const state = createListState(resource, { schema, url, with: withRel });\n const read = computed(() => state.read(searchParams()));\n const actions = () => state.actions(searchParams());\n\n return {\n params: computed(() => read().params),\n clamped: computed(() => read().clamped),\n searchParams,\n setParam: (name, value) => setSearchParams(actions().setParam(name, value)),\n setPage: page => setSearchParams(actions().setPage(page)),\n setSize: size => setSearchParams(actions().setSize(size)),\n setSort: sort => setSearchParams(actions().setSort(sort)),\n reset: keep => setSearchParams(actions().reset(keep)),\n };\n}\n","import { computed, inject } from \"@angular/core\";\nimport { toSignal } from \"@angular/core/rxjs-interop\";\nimport { ActivatedRoute, type ParamMap, Router } from \"@angular/router\";\n\nimport type { AdapterName, WithFor } from \"../adapter\";\nimport type { Resource } from \"../registry\";\nimport { searchParamsToQuery } from \"../route-query\";\nimport type { ListSchema } from \"../schema\";\nimport type { UrlConfig } from \"../url\";\nimport { injectListParamsBase, type InjectListParamsResult } from \"./inject-list-params-base\";\n\nexport interface InjectListParamsOptions<A extends AdapterName> {\n /** URL↔filter schema ({@link defineListSchema} / `resource.schema`). */\n schema: ListSchema;\n /** URL param names (page/size/sortType) — optional. */\n url?: UrlConfig;\n /** Fixed relations to load on every request (not URL-driven). */\n with?: WithFor<A>;\n}\n\nfunction paramMapToSearchParams(paramMap: ParamMap): URLSearchParams {\n return new URLSearchParams(paramMap.keys.flatMap(key => paramMap.getAll(key).map(value => [key, value])));\n}\n\n/**\n * List URL state as signals, with the Angular **Router** (`ActivatedRoute` + `Router`).\n * Reads filters/sort/page from the query params via the schema, builds a ready-to-send\n * payload through the `resource`, and returns URL setters that `router.navigate` (a new\n * history entry; filter/sort/size changes reset `page`). Does **not** fetch. Call it in an\n * injection context (a field initializer or a constructor); elsewhere Angular throws `NG0203`.\n *\n * @example\n * ```ts\n * @Component({ template: `<button (click)=\"list.setPage(2)\">2</button>` })\n * class UsersPage {\n * readonly list = injectListParams(users, { schema: usersSchema });\n * readonly payload = computed(() => this.list.params());\n * }\n * ```\n */\nexport function injectListParams<T, A extends AdapterName>(resource: Resource<T, A>, options: InjectListParamsOptions<A>): InjectListParamsResult {\n const route = inject(ActivatedRoute);\n const router = inject(Router);\n // `queryParamMap` replays its current value on subscribe, so the signal is never empty.\n const paramMap = toSignal(route.queryParamMap, { requireSync: true });\n return injectListParamsBase(resource, {\n ...options,\n searchParams: computed(() => paramMapToSearchParams(paramMap())),\n setSearchParams: next => void router.navigate([], { relativeTo: route, queryParams: searchParamsToQuery(next) }),\n });\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var core=require('@querykitjs/core');function k(){return core.createFilters()}var P={filterField:"filter",sortField:"sort",columnsField:"columns",withField:"with",withDeletedField:"withDeleted",withTotalField:"withTotal",pageField:"page",perPageField:"perPage",limitField:"limit",offsetField:"offset",cursorField:"cursor",defaultPerPage:core.DEFAULT_PER_PAGE,defaultLimit:core.DEFAULT_LIMIT,maxPerPage:core.DEFAULT_MAX_PER_PAGE,maxLimit:core.DEFAULT_MAX_LIMIT,maxOffset:core.DEFAULT_MAX_OFFSET,maxSortFields:core.DEFAULT_MAX_SORT_FIELDS,defaultSort:[{key:"createdAt",direction:"desc"}],pruneEmpty:true};function
|
|
1
|
+
'use strict';var core=require('@querykitjs/core');function k(){return core.createFilters()}var P={filterField:"filter",sortField:"sort",columnsField:"columns",withField:"with",withDeletedField:"withDeleted",withTotalField:"withTotal",pageField:"page",perPageField:"perPage",limitField:"limit",offsetField:"offset",cursorField:"cursor",defaultPerPage:core.DEFAULT_PER_PAGE,defaultLimit:core.DEFAULT_LIMIT,maxPerPage:core.DEFAULT_MAX_PER_PAGE,maxLimit:core.DEFAULT_MAX_LIMIT,maxOffset:core.DEFAULT_MAX_OFFSET,maxSortFields:core.DEFAULT_MAX_SORT_FIELDS,defaultSort:[{key:"createdAt",direction:"desc"}],pruneEmpty:true};function se(e){return !!(e==null||e===""||Array.isArray(e)&&e.length===0)}function le(e){if(typeof e=="string"){let t=e.startsWith("-"),r=(t?e.slice(1):e).trim();return r?{key:r,direction:t?"desc":"asc"}:void 0}return e&&e.key?{key:e.key,direction:e.direction??"asc"}:void 0}function L(e,t){if(!e||e.length===0)return t;let r=e.map(le).filter(n=>n!==void 0);return r.length?r:t}function D(e,t){let r=e.operation??"=",n=r==="isNull"||r==="isNotNull",a=e.value;if(!n&&t&&se(a))return;let i={key:e.key,operation:r};return n||(i.value=a),i}function h(e,t){if("and"in e){let r=e.and.map(n=>h(n,t)).filter(n=>!!n);return r.length?{and:r}:void 0}if("or"in e){let r=e.or.map(n=>h(n,t)).filter(n=>!!n);return r.length?{or:r}:void 0}if("not"in e){let r=h(e.not,t);return r?{not:r}:void 0}return D(e,t)}function _(e,t){return e?Array.isArray(e)?e.map(r=>D(r,t)).filter(r=>!!r):h(e,t)??[]:[]}function Q(e,t){let r={[t.filterField]:_(e.filter,t.pruneEmpty),[t.columnsField]:e.columns??{},[t.withField]:e.with??{}};return e.withDeleted!==void 0&&(r[t.withDeletedField]=e.withDeleted),r}function c(e,t,r=1/0){let n=e===void 0||e<1||Number.isNaN(e)?t:Math.trunc(e);return Math.min(r,n)}function b(e,t,r,n=""){return new Error(`querykit: ${e} exceeds ${t} (${r})${n}`)}function T(e,t){let r=L(e.sort,t.defaultSort);if(r.length>t.maxSortFields)throw b(`sort with ${r.length} fields`,"maxSortFields",t.maxSortFields);return {...Q(e,t),[t.sortField]:r}}var V="; use cursor pagination for deeper pages";function v(e,t){let r=c(e.page,1),n=c(e.perPage,t.defaultPerPage,t.maxPerPage);if((r-1)*n>t.maxOffset)throw b(`page ${r} \xD7 perPage ${n}`,"maxOffset",t.maxOffset,V);let a={...T(e,t),[t.pageField]:r,[t.perPageField]:n};return e.withTotal!==void 0&&(a[t.withTotalField]=e.withTotal),a}function z(e,t){let r=e.offset&&e.offset>0?Math.trunc(e.offset):0;if(r>t.maxOffset)throw b(`offset ${r}`,"maxOffset",t.maxOffset,V);return {...T(e,t),[t.limitField]:c(e.limit,t.defaultLimit,t.maxLimit),[t.offsetField]:r}}function W(e,t){let r={...Q(e,t),[t.limitField]:c(e.limit,t.defaultLimit,t.maxLimit),[t.cursorField]:e.cursor??null,order:e.order??"asc",direction:e.direction??"forward"};return e.cursorKey!==void 0&&(r.cursorKey=e.cursorKey),r}function K(e={}){let t={...P,...e};return {params:(r={})=>T(r,t),list:(r={})=>v(r,t),infinite:(r={})=>z(r,t),cursor:(r={})=>W(r,t)}}function ue(e={}){return T(e,P)}function A(e={}){return v(e,P)}function de(e={}){return z(e,P)}function me(e={}){return W(e,P)}var B=e=>e===null?null:e??0;function q(e){return {totalPages:B(e?.total_pages),totalCount:B(e?.total_items),currentPage:e?.current_page??0,perPage:e?.per_page??0,hasNext:e?.has_next??false,hasPrev:e?.has_prev??false}}function G(e){return {limit:e?.limit??0,offset:e?.offset??0,count:e?.count??0,hasMore:e?.has_more??false,nextOffset:e?.next_offset??null}}function $(e){return {limit:e?.limit??0,hasNext:e?.has_next??false,hasPrev:e?.has_prev??false,nextCursor:e?.next_cursor??null,prevCursor:e?.prev_cursor??null}}function pe(e){return e}var F={pageParam:"page",sizeParam:"size",sortParam:"sortType"};function X(e){if(!e)return;let t=e.split(",").map(r=>r.trim()).filter(Boolean).map(r=>{let n=r.startsWith("-");return {key:n?r.slice(1):r,direction:n?"desc":"asc"}}).filter(r=>r.key);return t.length?t:void 0}function j(e){return e.map(t=>typeof t=="string"?t.trim():t&&t.key?(t.direction==="desc"?"-":"")+t.key:"").filter(Boolean).join(",")}function H(e,t){let r=[],n=[];for(let[a,i]of Object.entries(e)){let o=i.key??a;if(i.range){let u=t.get(i.range[0]),d=t.get(i.range[1]);u&&r.push(g(o,">=",u)),d&&r.push(g(o,"<=",d));continue}if(i.between){let u=t.get(i.between[0]),d=t.get(i.between[1]);u&&d&&r.push(g(o,"between",[u,d]));continue}let p=t.get(a),l=p!==null?p:i.default;if(typeof l=="string"&&i.trim&&(l=l.trim()),!(l==null||l==="")&&!(Array.isArray(l)&&l.length===0)){if(i.search&&typeof l=="string"){n.push({or:i.search.map(u=>g(u,"%_%",l))});continue}if(i.split&&typeof l=="string"){let u=i.split===true?",":i.split,d=l.split(u).map(f=>f.trim()).filter(Boolean);if(d.length===0)continue;l=d;}r.push(g(o,i.operation??"=",l));}}return n.length===0?r:{and:[...n,...r]}}function g(e,t,r){return {key:e,operation:t,value:r}}function U(e,t){return Object.defineProperty(e,"clamped",{value:t,enumerable:false})}function ge(e,t){let r=c(e,t.perPage??core.DEFAULT_PER_PAGE,t.maxPerPage??core.DEFAULT_MAX_PER_PAGE);return Math.floor((t.maxOffset??core.DEFAULT_MAX_OFFSET)/r)+1}function w(e,t,r={},n={}){let a={...F,...r},i=t.get(a.sizeParam),o=i?Number(i):void 0,p=Math.trunc(Number(t.get(a.pageParam)))||1,l=X(t.get(a.sortParam)),u=ge(o,n),d=n.maxSortFields??core.DEFAULT_MAX_SORT_FIELDS,f=p>u,x=l!==void 0&&l.length>d;return {filter:H(e,t),sort:x?l.slice(0,d):l,page:f?u:p,perPage:o,clamped:f||x}}function Fe(e,t,r){let n=w(e,t,r);return U(A(n),n.clamped)}function C(e){return new URLSearchParams(e)}function I(e,t,r,n={}){let a={...F,...n},i=C(e);return i.delete(a.pageParam),r==null||r===""?i.delete(t):i.set(t,r),i}function M(e,t,r={}){let n={...F,...r},a=C(e);return a.set(n.pageParam,String(t)),a}function N(e,t,r={}){let n={...F,...r},a=C(e);return a.delete(n.pageParam),a.set(n.sizeParam,String(t)),a}function E(e,t,r={}){let n={...F,...r},a=C(e);a.delete(n.pageParam);let i=j(t);return i?a.set(n.sortParam,i):a.delete(n.sortParam),a}function O(e,t=[]){let r=new URLSearchParams;for(let n of t){let a=e.get(n);a!==null&&r.set(n,a);}return r}function xe(e){let t=e.defaults??{},r=e.timestamps?.createdAt,n=r?[{key:r,direction:"desc"}]:[],a=L(t.sort,n),i=t.cursor?.order??"asc",o={};t.perPage!==void 0&&(o.defaultPerPage=t.perPage),t.limit!==void 0&&(o.defaultLimit=t.limit),t.maxPerPage!==void 0&&(o.maxPerPage=t.maxPerPage),t.maxLimit!==void 0&&(o.maxLimit=t.maxLimit),t.maxOffset!==void 0&&(o.maxOffset=t.maxOffset),t.maxSortFields!==void 0&&(o.maxSortFields=t.maxSortFields),a.length&&(o.defaultSort=a),e.pruneEmpty!==void 0&&(o.pruneEmpty=e.pruneEmpty);let p=K(o),l={perPage:t.perPage,maxPerPage:t.maxPerPage,maxOffset:t.maxOffset,maxSortFields:t.maxSortFields},u=m=>({data:m?.data??[],meta:q(m?.meta)}),d=m=>({data:m?.data??[],meta:G(m?.meta)}),f=m=>({data:m?.data??[],meta:$(m?.meta)});function x(m){let Y=k();return {list:s=>p.list(s),infinite:s=>p.infinite(s),cursor:s=>p.cursor({...s,order:s?.order??i}),params:s=>p.params(s),f:Y,search:(s,y,S)=>core.f.or(...y.map(Z=>core.f[S?.operation??"contains"](Z,s))),schema:s=>s,fromSearchParams:(s,y)=>{let S=w(y.schema,s,y.url,l);return U(p.list({...S,with:y.with}),S.clamped)},keys:{all:[m],list:s=>[m,"list",s],infinite:s=>[m,"infinite",s],cursor:s=>[m,"cursor",s],detail:s=>[m,"detail",s]},parseList:s=>u(s),parseInfinite:s=>d(s),parseCursor:s=>f(s)}}return {adapter:e.adapter,resource:x,parseList:u,parseInfinite:d,parseCursor:f}}var Se={"unknown-key":true,"invalid-value":true,"forbidden-key":true,"forbidden-operator":true,"limit-exceeded":true,"empty-filter":true},Re={filter:true,sort:true,cursorKey:true,aggregate:true,page:true,mutation:true,with:true},J=(e,t)=>typeof t=="string"&&Object.hasOwn(e,t);function he(e){if(typeof e!="object"||e===null)return false;let t=e;return J(Se,t.reason)&&J(Re,t.site)&&typeof t.key=="string"}function Le(e,t){let{schema:r,url:n,with:a}=t;return {read(i){let o=e.fromSearchParams(i,{schema:r,url:n,with:a});return {params:o,clamped:o.clamped===true}},actions(i){return {setParam:(o,p)=>I(i,o,p,n),setPage:o=>M(i,o,n),setSize:o=>N(i,o,n),setSort:o=>E(i,o,n),reset:o=>O(i,o)}}}}Object.defineProperty(exports,"f",{enumerable:true,get:function(){return core.f}});exports.buildCursorParams=me;exports.buildInfiniteParams=de;exports.buildListParams=A;exports.buildParams=ue;exports.createFilters=k;exports.createListState=Le;exports.createQuery=K;exports.createRegistry=xe;exports.decodeSort=X;exports.defineListSchema=pe;exports.encodeSort=j;exports.isQueryKitError=he;exports.normalizeFilter=_;exports.normalizeSort=L;exports.readListParams=w;exports.resetParams=O;exports.schemaToFilter=H;exports.searchParamsToPayload=Fe;exports.setPage=M;exports.setParam=I;exports.setSize=N;exports.setSort=E;//# sourceMappingURL=index.cjs.map
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/filters.ts","../src/query.ts","../src/meta.ts","../src/schema.ts","../src/url.ts","../src/registry.ts","../src/errors.ts"],"names":["createFilters","coreCreateFilters","DEFAULTS","DEFAULT_PER_PAGE","DEFAULT_LIMIT","DEFAULT_MAX_PER_PAGE","DEFAULT_MAX_LIMIT","DEFAULT_MAX_OFFSET","DEFAULT_MAX_SORT_FIELDS","isEmptyValue","value","toSortItem","item","desc","key","normalizeSort","input","fallback","items","i","normalizeCondition","condition","prune","operation","noValue","out","normalizeNode","node","kids","inner","normalizeFilter","filter","c","buildBase","cfg","base","clampInt","max","resolved","limitError","what","limit","hint","build","sort","CURSOR_HINT","buildList","page","perPage","payload","buildInfinite","offset","buildCursor","createQuery","config","buildParams","buildListParams","buildInfiniteParams","buildCursorParams","total","mapMeta","raw","mapInfiniteMeta","mapCursorMeta","defineListSchema","schema","URL_DEFAULTS","decodeSort","s","tok","encodeSort","schemaToFilter","searchParams","conditions","groups","param","d","from","to","cond","field","delimiter","parts","withClamped","clamped","lastPage","limits","readListParams","url","size","maxPage","maxSortFields","isPageClamped","isSortClamped","searchParamsToPayload","params","clone","setParam","name","next","setPage","setSize","setSort","encoded","resetParams","keep","createRegistry","defaults","createdAt","timestampSort","cursorOrder","qcfg","q","urlLimits","parseList","parseInfinite","parseCursor","resource","f","term","fields","options","read","p","id","REASONS","SITES","isMember","table","isQueryKitError","body","candidate"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createFilters as coreCreateFilters, f } from \"@querykitjs/core\";\n\nimport type { AndGroup, FieldCondition, FieldKey, FilterNode, FilterScalar, FilterValue, NotGroup, OrGroup } from \"./types\";\n\n/** Keys of `T` whose value is assignable to `V`. */\ntype ValueKeys<T, V> = { [K in keyof T]-?: NonNullable<T[K]> extends V ? Extract<K, string> : never }[keyof T];\n/** String-valued field keys (for `contains`/`startsWith`/`like`/…). */\ntype StringKeys<T> = ValueKeys<T, string>;\n/** Comparable field keys — string/number/bigint/Date (for `gt`/`between`/…). */\ntype ComparableKeys<T> = ValueKeys<T, string | number | bigint | Date>;\n\ntype Node<T> = FilterNode<T>;\n\n/**\n * Field-type-aware filter builder: string-match operators are offered only for\n * string fields, comparison only for comparable fields, so nonsensical filters\n * (e.g. `contains` on a number) are compile errors. Runtime is\n * `@querykitjs/core`'s builder unchanged.\n */\nexport interface TypedFilters<T> {\n eq<K extends FieldKey<T>>(key: K, value: FilterValue): FieldCondition<T>;\n ne<K extends FieldKey<T>>(key: K, value: FilterValue): FieldCondition<T>;\n\n gt<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n gte<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n lt<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n lte<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n between<K extends ComparableKeys<T>>(key: K, min: FilterScalar | Date, max: FilterScalar | Date): FieldCondition<T>;\n range<K extends ComparableKeys<T>>(key: K, from: FilterScalar | Date, to: FilterScalar | Date): FieldCondition<T>[];\n\n contains<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n startsWith<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n endsWith<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n like<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n ilike<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n notLike<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n\n in<K extends FieldKey<T>>(key: K, value: Array<string | number>): FieldCondition<T>;\n notIn<K extends FieldKey<T>>(key: K, value: Array<string | number>): FieldCondition<T>;\n\n isNull<K extends FieldKey<T>>(key: K): FieldCondition<T>;\n isNotNull<K extends FieldKey<T>>(key: K): FieldCondition<T>;\n\n and(...nodes: Node<T>[]): AndGroup<T>;\n or(...nodes: Node<T>[]): OrGroup<T>;\n not(node: Node<T>): NotGroup<T>;\n}\n\n/**\n * Typed, ergonomic filter builder for an entity — field-name autocomplete plus\n * field-type-aware operators (see {@link TypedFilters}).\n *\n * @typeParam T - the list entity type (`Buyer`, `Product`, …).\n * @example\n * ```ts\n * const f = createFilters<Buyer>();\n * const filter = f.and(f.contains(\"buyerName\", s), f.gte(\"age\", 18));\n * // f.contains(\"age\", …) → compile error (age is a number)\n * ```\n */\nexport function createFilters<T = Record<string, unknown>>(): TypedFilters<T> {\n return coreCreateFilters<FieldKey<T>>() as unknown as TypedFilters<T>;\n}\n\n/** Untyped (entity-agnostic) filter builder — quick use, no field-type checks. */\nexport { f };\n","import { DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_PER_PAGE } from \"@querykitjs/core\";\n\nimport type {\n CursorParams,\n CursorPayload,\n FieldCondition,\n Filter,\n FilterNode,\n FilterValue,\n InfiniteParams,\n InfinitePayload,\n ListParams,\n ListPayload,\n Params,\n QueryPayload,\n Sort,\n SortInput,\n} from \"./types\";\n\n/** {@link createQuery} sozlamalari — wire field nomlari va default qiymatlar. */\nexport interface QueryConfig {\n filterField?: string;\n sortField?: string;\n columnsField?: string;\n withField?: string;\n withDeletedField?: string;\n withTotalField?: string;\n pageField?: string;\n perPageField?: string;\n limitField?: string;\n offsetField?: string;\n cursorField?: string;\n defaultPerPage?: number;\n defaultLimit?: number;\n /**\n * `perPage` yuqori chegarasi (core `DEFAULT_MAX_PER_PAGE` = 200) — backend\n * repositorylari va `@querykitjs/zod` factory'lari bilan **bir xil manba**,\n * shuning uchun front rad etiladigan so'rovni umuman yubormaydi.\n */\n maxPerPage?: number;\n /** `limit` yuqori chegarasi (core `DEFAULT_MAX_LIMIT` = 200). */\n maxLimit?: number;\n /**\n * Sahifa chuqurligi: list'da `(page - 1) × perPage`, infinite'da `offset` (core\n * `DEFAULT_MAX_OFFSET` = 10 000). Oshsa builder `Error` tashlaydi — jim kesish\n * so'rov ma'nosini o'zgartirardi. Chuqurroq sahifalar — cursor.\n */\n maxOffset?: number;\n /** `sort` maydonlari soni (core `DEFAULT_MAX_SORT_FIELDS` = 3). Oshsa — `Error`. */\n maxSortFields?: number;\n defaultSort?: Sort;\n /** Bo'sh qiymatli filterlarni tashlash (default `true`). */\n pruneEmpty?: boolean;\n}\n\nconst DEFAULTS: Required<QueryConfig> = {\n filterField: \"filter\",\n sortField: \"sort\",\n columnsField: \"columns\",\n withField: \"with\",\n withDeletedField: \"withDeleted\",\n withTotalField: \"withTotal\",\n pageField: \"page\",\n perPageField: \"perPage\",\n limitField: \"limit\",\n offsetField: \"offset\",\n cursorField: \"cursor\",\n defaultPerPage: DEFAULT_PER_PAGE,\n defaultLimit: DEFAULT_LIMIT,\n maxPerPage: DEFAULT_MAX_PER_PAGE,\n maxLimit: DEFAULT_MAX_LIMIT,\n maxOffset: DEFAULT_MAX_OFFSET,\n maxSortFields: DEFAULT_MAX_SORT_FIELDS,\n defaultSort: [{ key: \"createdAt\", direction: \"desc\" }],\n pruneEmpty: true,\n};\n\n/** Bo'sh (yuborilmaydigan) qiymatmi: undefined/null/\"\"/[] . `false`/`0` — bo'sh emas. */\nfunction isEmptyValue(value: FilterValue | undefined): boolean {\n if (value === undefined || value === null || value === \"\") return true;\n if (Array.isArray(value) && value.length === 0) return true;\n return false;\n}\n\n/** A `\"-field\"`/`\"field\"` shorthand string or a `{ key, direction }` item → a `SortItem`. */\nfunction toSortItem(item: Sort[number] | string): Sort[number] | undefined {\n if (typeof item === \"string\") {\n const desc = item.startsWith(\"-\");\n const key = (desc ? item.slice(1) : item).trim();\n return key ? { key, direction: desc ? \"desc\" : \"asc\" } : undefined;\n }\n return item && item.key ? { key: item.key, direction: item.direction ?? \"asc\" } : undefined;\n}\n\n/** Normalize a sort array (objects and/or `\"-field\"` strings) → canonical `SortItem[]`; empty → fallback. */\nexport function normalizeSort(input: SortInput | undefined, fallback: Sort): Sort {\n if (!input || input.length === 0) return fallback;\n const items = input.map(toSortItem).filter((i): i is Sort[number] => i !== undefined);\n return items.length ? items : fallback;\n}\n\nfunction normalizeCondition(condition: FieldCondition, prune: boolean): FieldCondition | undefined {\n const operation = condition.operation ?? \"=\";\n const noValue = operation === \"isNull\" || operation === \"isNotNull\";\n const value = condition.value as FilterValue;\n\n if (!noValue && prune && isEmptyValue(value)) return undefined;\n\n const out: FieldCondition = { key: condition.key, operation };\n if (!noValue) out.value = value;\n return out;\n}\n\nfunction normalizeNode(node: FilterNode, prune: boolean): FilterNode | undefined {\n if (\"and\" in node) {\n const kids = node.and.map(n => normalizeNode(n, prune)).filter((n): n is FilterNode => !!n);\n return kids.length ? { and: kids } : undefined;\n }\n if (\"or\" in node) {\n const kids = node.or.map(n => normalizeNode(n, prune)).filter((n): n is FilterNode => !!n);\n return kids.length ? { or: kids } : undefined;\n }\n if (\"not\" in node) {\n const inner = normalizeNode(node.not, prune);\n return inner ? { not: inner } : undefined;\n }\n return normalizeCondition(node, prune);\n}\n\n/** Filterni normalizatsiya qiladi: bo'sh shartlarni prune. Massiv → flat massiv. */\nexport function normalizeFilter(filter: Filter | undefined, prune: boolean): FieldCondition[] | FilterNode {\n if (!filter) return [];\n if (Array.isArray(filter)) {\n return filter.map(c => normalizeCondition(c, prune)).filter((c): c is FieldCondition => !!c);\n }\n return normalizeNode(filter, prune) ?? [];\n}\n\n/** Umumiy qism: filter/columns/with (+ withDeleted). Sort qo'shilmaydi. */\nfunction buildBase(input: Params, cfg: Required<QueryConfig>): Record<string, unknown> {\n const base: Record<string, unknown> = {\n [cfg.filterField]: normalizeFilter(input.filter, cfg.pruneEmpty),\n [cfg.columnsField]: input.columns ?? {},\n [cfg.withField]: input.with ?? {},\n };\n if (input.withDeleted !== undefined) base[cfg.withDeletedField] = input.withDeleted;\n return base;\n}\n\n/** A positive integer (fraction truncated); absent, < 1 or NaN → `fallback`; capped at `max`. */\nexport function clampInt(value: number | undefined, fallback: number, max = Infinity): number {\n const resolved = value === undefined || value < 1 || Number.isNaN(value) ? fallback : Math.trunc(value);\n return Math.min(max, resolved);\n}\n\n/**\n * The server rejects a request past a limit; the builder refuses to make one.\n * Filter limits stay with the server (task 008, Locked decision 5).\n */\nfunction limitError(what: string, limit: \"maxOffset\" | \"maxSortFields\", max: number, hint = \"\"): Error {\n return new Error(`querykit: ${what} exceeds ${limit} (${max})${hint}`);\n}\n\nfunction build(input: Params, cfg: Required<QueryConfig>): Record<string, unknown> {\n const sort = normalizeSort(input.sort, cfg.defaultSort);\n if (sort.length > cfg.maxSortFields) throw limitError(`sort with ${sort.length} fields`, \"maxSortFields\", cfg.maxSortFields);\n return { ...buildBase(input, cfg), [cfg.sortField]: sort };\n}\n\nconst CURSOR_HINT = \"; use cursor pagination for deeper pages\";\n\nfunction buildList(input: ListParams, cfg: Required<QueryConfig>): Record<string, unknown> {\n const page = clampInt(input.page, 1); // page >= 1 (kasr/0/manfiy → 1)\n const perPage = clampInt(input.perPage, cfg.defaultPerPage, cfg.maxPerPage);\n if ((page - 1) * perPage > cfg.maxOffset) throw limitError(`page ${page} × perPage ${perPage}`, \"maxOffset\", cfg.maxOffset, CURSOR_HINT);\n const payload: Record<string, unknown> = { ...build(input, cfg), [cfg.pageField]: page, [cfg.perPageField]: perPage };\n if (input.withTotal !== undefined) payload[cfg.withTotalField] = input.withTotal;\n return payload;\n}\n\nfunction buildInfinite(input: InfiniteParams, cfg: Required<QueryConfig>): Record<string, unknown> {\n const offset = input.offset && input.offset > 0 ? Math.trunc(input.offset) : 0;\n if (offset > cfg.maxOffset) throw limitError(`offset ${offset}`, \"maxOffset\", cfg.maxOffset, CURSOR_HINT);\n return {\n ...build(input, cfg),\n [cfg.limitField]: clampInt(input.limit, cfg.defaultLimit, cfg.maxLimit),\n [cfg.offsetField]: offset,\n };\n}\n\nfunction buildCursor(input: CursorParams, cfg: Required<QueryConfig>): Record<string, unknown> {\n const payload: Record<string, unknown> = {\n ...buildBase(input, cfg),\n [cfg.limitField]: clampInt(input.limit, cfg.defaultLimit, cfg.maxLimit),\n [cfg.cursorField]: input.cursor ?? null,\n order: input.order ?? \"asc\",\n direction: input.direction ?? \"forward\",\n };\n if (input.cursorKey !== undefined) payload.cursorKey = input.cursorKey;\n return payload;\n}\n\n/**\n * Config bilan bog'langan query quruvchilarni qaytaradi. Boshqa backend field\n * nomlari (masalan `perPage`, `withPopulates`) uchun.\n *\n * @example\n * ```ts\n * const q = createQuery({ withField: \"withPopulates\", defaultPerPage: 20 });\n * const params = q.list({ filter, page, perPage });\n * ```\n */\nexport function createQuery(config: QueryConfig = {}) {\n const cfg = { ...DEFAULTS, ...config };\n return {\n params: (input: Params = {}) => build(input, cfg),\n list: (input: ListParams = {}) => buildList(input, cfg),\n infinite: (input: InfiniteParams = {}) => buildInfinite(input, cfg),\n cursor: (input: CursorParams = {}) => buildCursor(input, cfg),\n };\n}\n\n/**\n * Params'ni normalizatsiya qiladi (paginatsiyasiz): filter prune, sort decode,\n * `with`/`columns` pass-through. Default querykit wire-format.\n *\n * @example\n * ```ts\n * const payload = buildParams({\n * filter: [{ key: \"name\", operation: \"%_%\", value: s }],\n * sort: [{ key: \"createdAt\", direction: \"desc\" }],\n * with: { supervisor: true },\n * });\n * ```\n */\nexport function buildParams(input: Params = {}): QueryPayload {\n return build(input, DEFAULTS) as unknown as QueryPayload;\n}\n\n/**\n * {@link buildParams} + `page`/`perPage` (default `perPage = 20`, `@querykitjs/core`).\n *\n * @example\n * ```ts\n * const payload = buildListParams({ filter, sort: [{ key: \"createdAt\", direction: \"desc\" }], page: 2, perPage: 20 });\n * // -> { filter, sort: [{ key, direction }], columns, with, page, perPage }\n * ```\n */\nexport function buildListParams(input: ListParams = {}): ListPayload {\n return buildList(input, DEFAULTS) as unknown as ListPayload;\n}\n\n/**\n * Infinite-scroll payload — {@link buildParams} + `limit`/`offset` (default\n * `limit = 20`).\n *\n * @example\n * ```ts\n * const payload = buildInfiniteParams({ filter, limit: 20, offset: 40 });\n * // -> { filter, sort, columns, with, limit, offset }\n * ```\n */\nexport function buildInfiniteParams(input: InfiniteParams = {}): InfinitePayload {\n return buildInfinite(input, DEFAULTS) as unknown as InfinitePayload;\n}\n\n/**\n * Cursor (keyset) payload — `sort` o'rniga `order`/`direction`. `cursor`\n * oldingi javob meta'sidagi `next_cursor`/`prev_cursor` tokeni.\n *\n * @example\n * ```ts\n * const payload = buildCursorParams({ filter, limit: 20, cursor, order: \"asc\" });\n * // -> { filter, columns, with, limit, cursor, order, direction }\n * ```\n */\nexport function buildCursorParams(input: CursorParams = {}): CursorPayload {\n return buildCursor(input, DEFAULTS) as unknown as CursorPayload;\n}\n","import type { CursorMeta, InfiniteMeta, Meta, RawCursorMeta, RawInfiniteMeta, RawMeta } from \"./types\";\n\n/** A server `null` total means \"not counted\" (`withTotal: false`) and stays `null`; an absent one is `0`. */\nconst total = (value: number | null | undefined): number | null => (value === null ? null : (value ?? 0));\n\n/**\n * **Offset** (list) meta'sini snake_case → camelCase map qiladi.\n *\n * @example\n * ```ts\n * const { data, meta } = (await http.post(\"/buyers/list\", params)).data;\n * setMeta(mapMeta(meta)); // { totalPages, totalCount, currentPage, perPage, hasNext, hasPrev }\n * ```\n */\nexport function mapMeta(raw?: RawMeta | null): Meta {\n return {\n totalPages: total(raw?.total_pages),\n totalCount: total(raw?.total_items),\n currentPage: raw?.current_page ?? 0,\n perPage: raw?.per_page ?? 0,\n hasNext: raw?.has_next ?? false,\n hasPrev: raw?.has_prev ?? false,\n };\n}\n\n/**\n * **Infinite-scroll** meta'sini map qiladi.\n *\n * @example\n * ```ts\n * const m = mapInfiniteMeta(res.meta); // { limit, offset, count, hasMore, nextOffset }\n * if (m.hasMore) load(m.nextOffset);\n * ```\n */\nexport function mapInfiniteMeta(raw?: RawInfiniteMeta | null): InfiniteMeta {\n return {\n limit: raw?.limit ?? 0,\n offset: raw?.offset ?? 0,\n count: raw?.count ?? 0,\n hasMore: raw?.has_more ?? false,\n nextOffset: raw?.next_offset ?? null,\n };\n}\n\n/**\n * **Cursor** (keyset) meta'sini map qiladi.\n *\n * @example\n * ```ts\n * const m = mapCursorMeta(res.meta); // { limit, hasNext, hasPrev, nextCursor, prevCursor }\n * ```\n */\nexport function mapCursorMeta(raw?: RawCursorMeta | null): CursorMeta {\n return {\n limit: raw?.limit ?? 0,\n hasNext: raw?.has_next ?? false,\n hasPrev: raw?.has_prev ?? false,\n nextCursor: raw?.next_cursor ?? null,\n prevCursor: raw?.prev_cursor ?? null,\n };\n}\n","import type { FilterOperator, FilterValue } from \"./types\";\n\n/** Forbids the listed keys (`?: never`) so modes can't be mixed. */\ntype Without<K extends string> = { [P in K]?: never };\n\n/** Filter-key override, shared by the single-key modes. */\ninterface KeyBase {\n /** Backend field key (defaults to the schema param name). */\n key?: string;\n}\n\n/**\n * **Simple** mode — one URL param → one condition. `operation` defaults to `\"=\"`;\n * `trim`/`default`/`split` shape the value.\n */\nexport interface SimpleField extends KeyBase {\n /** Filter operation (default `\"=\"`). */\n operation?: FilterOperator;\n /** Trim the string value. */\n trim?: boolean;\n /** Value used when the URL param is absent. */\n default?: FilterValue;\n /**\n * For array operations (`in`/`notIn`): split a comma-string into an array.\n * `true` → delimiter `\",\"`; or a custom delimiter. Guarded: absent/empty →\n * pruned; parts trimmed, empties dropped.\n */\n split?: boolean | string;\n}\n\n/** **Range** mode — `[fromParam, toParam]` → two inclusive conditions (`>=`, `<=`). */\nexport interface RangeField extends KeyBase {\n range: [string, string];\n}\n\n/** **Between** mode — `[fromParam, toParam]` → one `between` condition (2-tuple). */\nexport interface BetweenField extends KeyBase {\n between: [string, string];\n}\n\n/** **Search** mode — one URL param → OR of `contains` across these field keys. */\nexport interface SearchField {\n search: string[];\n trim?: boolean;\n default?: FilterValue;\n}\n\n/**\n * One list field's URL→filter mapping. Exactly **one mode** per descriptor —\n * Simple / Range / Between / Search — enforced at compile time (mixing e.g.\n * `range` + `search`, or `range` + `between`, is a type error).\n */\nexport type FieldDescriptor =\n | (SimpleField & Without<\"range\" | \"between\" | \"search\">)\n | (RangeField & Without<\"operation\" | \"trim\" | \"default\" | \"split\" | \"between\" | \"search\">)\n | (BetweenField & Without<\"operation\" | \"trim\" | \"default\" | \"split\" | \"range\" | \"search\">)\n | (SearchField & Without<\"key\" | \"operation\" | \"split\" | \"range\" | \"between\">);\n\n/** URL param → {@link FieldDescriptor} map. */\nexport type ListSchema = Record<string, FieldDescriptor>;\n\n/**\n * Declares a list filter schema (identity helper — preserves the literal type).\n * Maps URL params to `{key, operation, value}` conditions so pages never build\n * `IFilter[]` by hand.\n *\n * @example\n * ```ts\n * const buyersSchema = defineListSchema({\n * id: { operation: \"=\" },\n * status: { operation: \"=\", default: \"active\" },\n * ids: { operation: \"in\", split: true },\n * q: { search: [\"name\", \"email\"] },\n * createdAt: { range: [\"fromDate\", \"toDate\"] },\n * });\n * ```\n */\nexport function defineListSchema<S extends ListSchema>(schema: S): S {\n return schema;\n}\n","import { DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_PER_PAGE } from \"@querykitjs/core\";\n\nimport { buildListParams, clampInt } from \"./query\";\nimport type { FieldDescriptor, ListSchema } from \"./schema\";\nimport type { FieldCondition, Filter, FilterNode, FilterValue, ListParams, ListPayload, Sort, SortDirection, SortInput } from \"./types\";\n\n/** URL param nomlari (sahifa/o'lcham/sort) — sozlanadigan. */\nexport interface UrlConfig {\n pageParam?: string;\n sizeParam?: string;\n sortParam?: string;\n}\n\nconst URL_DEFAULTS: Required<UrlConfig> = {\n pageParam: \"page\",\n sizeParam: \"size\",\n sortParam: \"sortType\",\n};\n\n/**\n * `\"-createdAt,id,-appNumber\"` → `[{ key, direction }, …]` — comma-separated,\n * order preserved, `-` prefix = `desc` (else `asc`). Empty → `undefined`.\n */\nexport function decodeSort(value: string | null | undefined): Sort | undefined {\n if (!value) return undefined;\n const items = value\n .split(\",\")\n .map(s => s.trim())\n .filter(Boolean)\n .map(tok => {\n const desc = tok.startsWith(\"-\");\n return { key: desc ? tok.slice(1) : tok, direction: (desc ? \"desc\" : \"asc\") as SortDirection };\n })\n .filter(i => i.key); // drop empty keys (e.g. a lone \"-\")\n return items.length ? items : undefined;\n}\n\n/** `[{ key, direction }, …]` (or `\"-field\"` shorthand strings) → `\"-createdAt,id,-appNumber\"` (empty → `\"\"`). */\nexport function encodeSort(sort: SortInput): string {\n return sort\n .map(i => (typeof i === \"string\" ? i.trim() : i && i.key ? (i.direction === \"desc\" ? \"-\" : \"\") + i.key : \"\"))\n .filter(Boolean)\n .join(\",\");\n}\n\n/**\n * Schema + searchParams → filter. Applies `range`/`between`/`search`/`split`/\n * `default`/`trim`; empty/absent params are dropped. Returns a flat\n * `FieldCondition[]` (implicit AND), or a tree when a `search` OR-group is\n * present (`{ and: [orGroup, …conditions] }`).\n */\nexport function schemaToFilter(schema: ListSchema, searchParams: URLSearchParams): Filter {\n const conditions: FieldCondition[] = [];\n const groups: FilterNode[] = [];\n\n for (const [param, d] of Object.entries(schema) as [string, FieldDescriptor][]) {\n const key = d.key ?? param;\n\n // range → two inclusive conditions (>= , <=)\n if (d.range) {\n const from = searchParams.get(d.range[0]);\n const to = searchParams.get(d.range[1]);\n if (from) conditions.push(cond(key, \">=\", from));\n if (to) conditions.push(cond(key, \"<=\", to));\n continue;\n }\n\n // between → one condition with a 2-tuple value\n if (d.between) {\n const from = searchParams.get(d.between[0]);\n const to = searchParams.get(d.between[1]);\n if (from && to) conditions.push(cond(key, \"between\", [from, to]));\n continue;\n }\n\n // read value, falling back to `default` only when the param is ABSENT\n // (an empty `?x=` means the user cleared the filter → prune, don't default).\n const raw = searchParams.get(param);\n let value: FilterValue | undefined = raw !== null ? raw : d.default;\n if (typeof value === \"string\" && d.trim) value = value.trim();\n if (value === undefined || value === null || value === \"\") continue;\n if (Array.isArray(value) && value.length === 0) continue;\n\n // search → OR of `contains` across the listed fields (needs a string)\n if (d.search && typeof value === \"string\") {\n groups.push({ or: d.search.map(field => cond(field, \"%_%\", value as string)) });\n continue;\n }\n\n // split → comma-string → array (for `in`/`notIn`); guarded against empties\n if (d.split && typeof value === \"string\") {\n const delimiter = d.split === true ? \",\" : d.split;\n const parts = value\n .split(delimiter)\n .map(s => s.trim())\n .filter(Boolean);\n if (parts.length === 0) continue;\n value = parts;\n }\n\n conditions.push(cond(key, d.operation ?? \"=\", value));\n }\n\n return groups.length === 0 ? conditions : { and: [...groups, ...conditions] };\n}\n\nfunction cond(key: string, operation: FieldCondition[\"operation\"], value: FilterValue): FieldCondition {\n return { key, operation, value };\n}\n\n/**\n * The bounds the URL readers clamp to — the builder's own (`createRegistry`\n * `defaults`); an absent one is the core default.\n */\nexport interface UrlLimits {\n perPage?: number;\n maxPerPage?: number;\n maxOffset?: number;\n maxSortFields?: number;\n}\n\n/** {@link ListParams} read from a URL. `clamped` — the URL's page or sort was cut to the limits. */\nexport type UrlListParams = ListParams & { clamped: boolean };\n\n/**\n * A list payload built from a URL. `clamped` is non-enumerable: readable in code,\n * never serialized, so the wire payload is unchanged.\n */\nexport type UrlListPayload = ListPayload & { readonly clamped?: boolean };\n\n/** Marks a payload with a non-enumerable `clamped` flag. */\nexport function withClamped(payload: ListPayload, clamped: boolean): UrlListPayload {\n return Object.defineProperty(payload, \"clamped\", { value: clamped, enumerable: false });\n}\n\n/** The last page the builder accepts: `(page - 1) × perPage ≤ maxOffset`. */\nfunction lastPage(perPage: number | undefined, limits: UrlLimits): number {\n const resolved = clampInt(perPage, limits.perPage ?? DEFAULT_PER_PAGE, limits.maxPerPage ?? DEFAULT_MAX_PER_PAGE);\n return Math.floor((limits.maxOffset ?? DEFAULT_MAX_OFFSET) / resolved) + 1;\n}\n\n/**\n * searchParams → normalizatsiyalanmagan {@link ListParams} (filter/sort/page/perPage).\n * The URL is user input: a page past `maxOffset` becomes the last allowed page and a\n * sort past `maxSortFields` keeps its first fields, with `clamped: true` — so a\n * hand-edited `?page=9999` never throws during render. The builders still throw\n * for a direct call (task 008).\n */\nexport function readListParams(schema: ListSchema, searchParams: URLSearchParams, url: UrlConfig = {}, limits: UrlLimits = {}): UrlListParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const size = searchParams.get(cfg.sizeParam);\n const perPage = size ? Number(size) : undefined;\n const page = Math.trunc(Number(searchParams.get(cfg.pageParam))) || 1;\n const sort = decodeSort(searchParams.get(cfg.sortParam));\n const maxPage = lastPage(perPage, limits);\n const maxSortFields = limits.maxSortFields ?? DEFAULT_MAX_SORT_FIELDS;\n const isPageClamped = page > maxPage;\n const isSortClamped = sort !== undefined && sort.length > maxSortFields;\n return {\n filter: schemaToFilter(schema, searchParams),\n sort: isSortClamped ? sort.slice(0, maxSortFields) : sort,\n page: isPageClamped ? maxPage : page,\n perPage,\n clamped: isPageClamped || isSortClamped,\n };\n}\n\n/** searchParams → to'liq, yuborishga tayyor {@link ListPayload} (core default limits; clamped like {@link readListParams}). */\nexport function searchParamsToPayload(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): UrlListPayload {\n const params = readListParams(schema, searchParams, url);\n return withClamped(buildListParams(params), params.clamped);\n}\n\n/* ------------------------- URL yozish (immutable) ------------------------- */\n/* Har biri YANGI URLSearchParams qaytaradi; filter/sort o'zgarsa `page` reset. */\n\nfunction clone(searchParams: URLSearchParams): URLSearchParams {\n return new URLSearchParams(searchParams);\n}\n\n/** Filter param'ini o'rnatadi/o'chiradi va `page`ni reset qiladi. */\nexport function setParam(searchParams: URLSearchParams, name: string, value: string | null | undefined, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n if (value === null || value === undefined || value === \"\") next.delete(name);\n else next.set(name, value);\n return next;\n}\n\n/** Sahifani o'rnatadi (`page` reset qilinmaydi). */\nexport function setPage(searchParams: URLSearchParams, page: number, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.set(cfg.pageParam, String(page));\n return next;\n}\n\n/** Sahifa o'lchamini o'rnatadi va `page`ni reset qiladi. */\nexport function setSize(searchParams: URLSearchParams, size: number, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n next.set(cfg.sizeParam, String(size));\n return next;\n}\n\n/** Sortni o'rnatadi (`[{ key, direction }, …]`) va `page`ni reset qiladi. */\nexport function setSort(searchParams: URLSearchParams, sort: SortInput, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n const encoded = encodeSort(sort);\n if (encoded) next.set(cfg.sortParam, encoded);\n else next.delete(cfg.sortParam);\n return next;\n}\n\n/** Barcha list param'larini tozalaydi (ixtiyoriy saqlanadigan kalitlar bilan). */\nexport function resetParams(searchParams: URLSearchParams, keep: string[] = []): URLSearchParams {\n const next = new URLSearchParams();\n for (const key of keep) {\n const value = searchParams.get(key);\n if (value !== null) next.set(key, value);\n }\n return next;\n}\n","import { createQuery, normalizeSort, type QueryConfig } from \"./query\";\nimport { createFilters, f as rawF } from \"./filters\";\nimport { mapMeta, mapInfiniteMeta, mapCursorMeta } from \"./meta\";\nimport { defineListSchema, type ListSchema } from \"./schema\";\nimport { readListParams, withClamped, type UrlConfig, type UrlLimits, type UrlListPayload } from \"./url\";\nimport type { AdapterName, WithFor } from \"./adapter\";\nimport type {\n CursorMeta,\n CursorParams,\n CursorPayload,\n FieldKey,\n Filter,\n InfiniteMeta,\n InfiniteParams,\n InfinitePayload,\n ListParams,\n ListPayload,\n Meta,\n Params,\n QueryPayload,\n RawCursorMeta,\n RawInfiniteMeta,\n RawMeta,\n Sort,\n SortDirection,\n SortInput,\n} from \"./types\";\n\n/* ---------------- resource inputs: entity-typed, adapter-aware `with` ------ */\n\nexport type ResourceListParams<T, A extends AdapterName> = Omit<ListParams<T>, \"with\"> & { with?: WithFor<A> };\nexport type ResourceInfiniteParams<T, A extends AdapterName> = Omit<InfiniteParams<T>, \"with\"> & { with?: WithFor<A> };\nexport type ResourceCursorParams<T, A extends AdapterName> = Omit<CursorParams<T>, \"with\"> & { with?: WithFor<A> };\nexport type ResourceParams<T, A extends AdapterName> = Omit<Params<T>, \"with\"> & { with?: WithFor<A> };\n\n/** `resource.search` options. */\nexport interface SearchOptions {\n /** The string operator per field (default `\"contains\"`). */\n operation?: \"contains\" | \"startsWith\" | \"endsWith\";\n}\n\n/* ---------------------------- responses / results ------------------------- */\n\ninterface RawResponse<T, M> {\n data?: T[];\n meta?: M | null;\n}\nexport interface ListResult<T> {\n data: T[];\n meta: Meta;\n}\nexport interface InfiniteResult<T> {\n data: T[];\n meta: InfiniteMeta;\n}\nexport interface CursorResult<T> {\n data: T[];\n meta: CursorMeta;\n}\n\n/* -------------------------------- query keys ------------------------------ */\n\nexport interface ResourceKeys {\n all: readonly unknown[];\n list(payload: unknown): readonly unknown[];\n infinite(payload: unknown): readonly unknown[];\n cursor(payload: unknown): readonly unknown[];\n detail(id: unknown): readonly unknown[];\n}\n\n/* -------------------------------- resource -------------------------------- */\n\nexport interface Resource<T, A extends AdapterName> {\n /** Build an offset (page) payload. */\n list(input?: ResourceListParams<T, A>): ListPayload;\n /** Build an infinite (limit/offset) payload. */\n infinite(input?: ResourceInfiniteParams<T, A>): InfinitePayload;\n /** Build a cursor (keyset) payload. */\n cursor(input?: ResourceCursorParams<T, A>): CursorPayload;\n /** Build a paginationless payload (filter/sort/columns/with). */\n params(input?: ResourceParams<T, A>): QueryPayload;\n /** Filter builder typed to `T`'s fields. */\n f: ReturnType<typeof createFilters<T>>;\n /**\n * Search preset — OR of `operation` (default `contains`) across `fields` (one input → many columns).\n * Each field must be `filterable` with that operator on the server.\n */\n search(term: string, fields: FieldKey<T>[], options?: SearchOptions): Filter<T>;\n /** Declare a URL↔filter schema (identity helper). */\n schema<S extends ListSchema>(s: S): S;\n /**\n * Build a list payload from URL search params (SSR — the non-hook `useListParams`).\n * A page or sort past the registry limits is clamped (`clamped`, non-enumerable — never sent).\n */\n fromSearchParams(searchParams: URLSearchParams, options: { schema: ListSchema; url?: UrlConfig; with?: WithFor<A> }): UrlListPayload;\n /** Stable query keys for TanStack/SWR caches. */\n keys: ResourceKeys;\n /** Map a list response's meta to camelCase (`data` typed to `T`). */\n parseList(raw?: RawResponse<T, RawMeta> | null): ListResult<T>;\n parseInfinite(raw?: RawResponse<T, RawInfiniteMeta> | null): InfiniteResult<T>;\n parseCursor(raw?: RawResponse<T, RawCursorMeta> | null): CursorResult<T>;\n}\n\n/* -------------------------------- registry -------------------------------- */\n\nexport interface RegistryDefaults {\n /** `list` page size. */\n perPage?: number;\n /** `infinite` + `cursor` page size. */\n limit?: number;\n /**\n * `perPage` upper bound (core `DEFAULT_MAX_PER_PAGE` = 200) — the same constant\n * the zod factories and both backend repositories use, so the frontend never\n * sends a request the server would reject.\n */\n maxPerPage?: number;\n /** `limit` upper bound (core `DEFAULT_MAX_LIMIT` = 200). */\n maxLimit?: number;\n /** Page depth bound (core `DEFAULT_MAX_OFFSET` = 10 000) — a deeper `list`/`infinite` request throws. */\n maxOffset?: number;\n /** Sort field count bound (core `DEFAULT_MAX_SORT_FIELDS` = 3) — more fields throw. */\n maxSortFields?: number;\n /** `list`/`infinite` sort — `[{key,direction}]` or `[\"-createdAt\", \"id\"]` shorthand. */\n sort?: SortInput;\n /** Cursor-only defaults. */\n cursor?: { order?: SortDirection };\n}\n\n/** The backend registry's `timestamps` field names, so the web default sort names the same field. */\nexport interface RegistryTimestamps {\n /** The createdAt field (default `\"createdAt\"`) — the default `list`/`infinite` sort is `[{ key: createdAt, direction: \"desc\" }]`. */\n createdAt?: string;\n}\n\nexport interface RegistryConfig<A extends AdapterName> {\n adapter: A;\n defaults?: RegistryDefaults;\n /** Same as the backend registry's `timestamps`; `defaults.sort` wins over it. */\n timestamps?: RegistryTimestamps;\n /** Drop empty filter values built from form inputs (default `true`). */\n pruneEmpty?: boolean;\n}\n\nexport interface Registry<A extends AdapterName> {\n readonly adapter: A;\n /** Entity-typed builders + filters + schema + keys + parsers. `name` = cache-key namespace (required, must be unique). */\n resource<T>(name: string): Resource<T, A>;\n /** Registry-level meta parsing (entity-agnostic — `data: unknown[]`). */\n parseList(raw?: RawResponse<unknown, RawMeta> | null): ListResult<unknown>;\n parseInfinite(raw?: RawResponse<unknown, RawInfiniteMeta> | null): InfiniteResult<unknown>;\n parseCursor(raw?: RawResponse<unknown, RawCursorMeta> | null): CursorResult<unknown>;\n}\n\n/**\n * Create a web query registry — configure defaults + backend adapter once, then\n * `registry.resource<T>()` yields entity-typed, adapter-aware query builders,\n * filters, a URL↔filter schema, cache keys and meta parsers.\n *\n * @example\n * ```ts\n * export const qk = createRegistry({ adapter: \"mongoose\", defaults: { perPage: 20, sort: [\"-createdAt\"] } });\n * const users = qk.resource<IUser>(\"users\");\n * const body = users.list({ filter: users.f.eq(\"status\", \"active\"), page });\n * ```\n */\nexport function createRegistry<A extends AdapterName>(config: RegistryConfig<A>): Registry<A> {\n const defaults = config.defaults ?? {};\n const createdAt = config.timestamps?.createdAt;\n const timestampSort: Sort = createdAt ? [{ key: createdAt, direction: \"desc\" }] : [];\n const sort: Sort = normalizeSort(defaults.sort, timestampSort); // accepts {key,direction}[] or \"-field\"[] shorthand\n const cursorOrder: SortDirection = defaults.cursor?.order ?? \"asc\";\n\n // Only set keys that are provided — createQuery merges over its own defaults,\n // and passing `undefined` would clobber them.\n const qcfg: QueryConfig = {};\n if (defaults.perPage !== undefined) qcfg.defaultPerPage = defaults.perPage;\n if (defaults.limit !== undefined) qcfg.defaultLimit = defaults.limit;\n if (defaults.maxPerPage !== undefined) qcfg.maxPerPage = defaults.maxPerPage;\n if (defaults.maxLimit !== undefined) qcfg.maxLimit = defaults.maxLimit;\n if (defaults.maxOffset !== undefined) qcfg.maxOffset = defaults.maxOffset;\n if (defaults.maxSortFields !== undefined) qcfg.maxSortFields = defaults.maxSortFields;\n if (sort.length) qcfg.defaultSort = sort; // only override when a real sort is given\n if (config.pruneEmpty !== undefined) qcfg.pruneEmpty = config.pruneEmpty;\n const q = createQuery(qcfg);\n const urlLimits: UrlLimits = {\n perPage: defaults.perPage,\n maxPerPage: defaults.maxPerPage,\n maxOffset: defaults.maxOffset,\n maxSortFields: defaults.maxSortFields,\n };\n\n const parseList = (raw?: RawResponse<unknown, RawMeta> | null): ListResult<unknown> => ({ data: raw?.data ?? [], meta: mapMeta(raw?.meta) });\n const parseInfinite = (raw?: RawResponse<unknown, RawInfiniteMeta> | null): InfiniteResult<unknown> => ({\n data: raw?.data ?? [],\n meta: mapInfiniteMeta(raw?.meta),\n });\n const parseCursor = (raw?: RawResponse<unknown, RawCursorMeta> | null): CursorResult<unknown> => ({\n data: raw?.data ?? [],\n meta: mapCursorMeta(raw?.meta),\n });\n\n function resource<T>(name: string): Resource<T, A> {\n const f = createFilters<T>();\n const keys: ResourceKeys = {\n all: [name],\n list: p => [name, \"list\", p],\n infinite: p => [name, \"infinite\", p],\n cursor: p => [name, \"cursor\", p],\n detail: id => [name, \"detail\", id],\n };\n return {\n list: input => q.list(input as unknown as ListParams) as unknown as ListPayload,\n infinite: input => q.infinite(input as unknown as InfiniteParams) as unknown as InfinitePayload,\n cursor: input => q.cursor({ ...(input as unknown as CursorParams), order: input?.order ?? cursorOrder }) as unknown as CursorPayload,\n params: input => q.params(input as unknown as Params) as unknown as QueryPayload,\n f,\n search: (term, fields, options) => rawF.or(...fields.map(field => rawF[options?.operation ?? \"contains\"](field, term))) as unknown as Filter<T>,\n schema: s => defineListSchema(s),\n fromSearchParams: (searchParams, options) => {\n const read = readListParams(options.schema, searchParams, options.url, urlLimits);\n return withClamped(q.list({ ...read, with: options.with } as unknown as ListParams) as unknown as ListPayload, read.clamped);\n },\n keys,\n parseList: raw => parseList(raw) as ListResult<T>,\n parseInfinite: raw => parseInfinite(raw) as InfiniteResult<T>,\n parseCursor: raw => parseCursor(raw) as CursorResult<T>,\n };\n }\n\n return { adapter: config.adapter, resource, parseList, parseInfinite, parseCursor };\n}\n","import type { SkipReason, SkippedCondition, SkipSite } from \"@querykitjs/core\";\n\n/**\n * The `QueryKitError.info` shape a backend may put in its 400 response body. The\n * response envelope is the project's own; web only types this part.\n */\nexport type QueryKitErrorBody = Pick<SkippedCondition, \"site\" | \"key\" | \"reason\"> & Partial<Pick<SkippedCondition, \"source\" | \"operation\">>;\n\n/* Records keyed by the core unions: a new core reason or site fails the typecheck here until it is listed. */\nconst REASONS: Record<SkipReason, true> = {\n \"unknown-key\": true,\n \"invalid-value\": true,\n \"forbidden-key\": true,\n \"forbidden-operator\": true,\n \"limit-exceeded\": true,\n \"empty-filter\": true,\n};\nconst SITES: Record<SkipSite, true> = { filter: true, sort: true, cursorKey: true, aggregate: true, page: true, mutation: true, with: true };\n\nconst isMember = <K extends string>(table: Record<K, true>, value: unknown): value is K => typeof value === \"string\" && Object.hasOwn(table, value);\n\n/**\n * Is `body` a querykit error (`reason`, `site`, `key`)? Lets the frontend tell a\n * rejected query (forbidden key, limit exceeded, …) from any other 400.\n *\n * @example\n * ```ts\n * const body = error.response?.data?.error;\n * if (isQueryKitError(body) && body.reason === \"forbidden-key\") showFieldError(body.key);\n * ```\n */\nexport function isQueryKitError(body: unknown): body is QueryKitErrorBody {\n if (typeof body !== \"object\" || body === null) return false;\n const candidate = body as Record<string, unknown>;\n return isMember(REASONS, candidate.reason) && isMember(SITES, candidate.site) && typeof candidate.key === \"string\";\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/filters.ts","../src/query.ts","../src/meta.ts","../src/schema.ts","../src/url.ts","../src/registry.ts","../src/errors.ts","../src/list-state.ts"],"names":["createFilters","coreCreateFilters","DEFAULTS","DEFAULT_PER_PAGE","DEFAULT_LIMIT","DEFAULT_MAX_PER_PAGE","DEFAULT_MAX_LIMIT","DEFAULT_MAX_OFFSET","DEFAULT_MAX_SORT_FIELDS","isEmptyValue","value","toSortItem","item","desc","key","normalizeSort","input","fallback","items","i","normalizeCondition","condition","prune","operation","noValue","out","normalizeNode","node","kids","inner","normalizeFilter","filter","c","buildBase","cfg","base","clampInt","max","resolved","limitError","what","limit","hint","build","sort","CURSOR_HINT","buildList","page","perPage","payload","buildInfinite","offset","buildCursor","createQuery","config","buildParams","buildListParams","buildInfiniteParams","buildCursorParams","total","mapMeta","raw","mapInfiniteMeta","mapCursorMeta","defineListSchema","schema","URL_DEFAULTS","decodeSort","s","tok","encodeSort","schemaToFilter","searchParams","conditions","groups","param","d","from","to","cond","field","delimiter","parts","withClamped","clamped","lastPage","limits","readListParams","url","size","maxPage","maxSortFields","isPageClamped","isSortClamped","searchParamsToPayload","params","clone","setParam","name","next","setPage","setSize","setSort","encoded","resetParams","keep","createRegistry","defaults","createdAt","timestampSort","cursorOrder","qcfg","q","urlLimits","parseList","parseInfinite","parseCursor","resource","f","term","fields","options","read","p","id","REASONS","SITES","isMember","table","isQueryKitError","body","candidate","createListState","withRel"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createFilters as coreCreateFilters, f } from \"@querykitjs/core\";\n\nimport type { AndGroup, FieldCondition, FieldKey, FilterNode, FilterScalar, FilterValue, NotGroup, OrGroup } from \"./types\";\n\n/** Keys of `T` whose value is assignable to `V`. */\ntype ValueKeys<T, V> = { [K in keyof T]-?: NonNullable<T[K]> extends V ? Extract<K, string> : never }[keyof T];\n/** String-valued field keys (for `contains`/`startsWith`/`like`/…). */\ntype StringKeys<T> = ValueKeys<T, string>;\n/** Comparable field keys — string/number/bigint/Date (for `gt`/`between`/…). */\ntype ComparableKeys<T> = ValueKeys<T, string | number | bigint | Date>;\n\ntype Node<T> = FilterNode<T>;\n\n/**\n * Field-type-aware filter builder: string-match operators are offered only for\n * string fields, comparison only for comparable fields, so nonsensical filters\n * (e.g. `contains` on a number) are compile errors. Runtime is\n * `@querykitjs/core`'s builder unchanged.\n */\nexport interface TypedFilters<T> {\n eq<K extends FieldKey<T>>(key: K, value: FilterValue): FieldCondition<T>;\n ne<K extends FieldKey<T>>(key: K, value: FilterValue): FieldCondition<T>;\n\n gt<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n gte<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n lt<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n lte<K extends ComparableKeys<T>>(key: K, value: FilterValue): FieldCondition<T>;\n between<K extends ComparableKeys<T>>(key: K, min: FilterScalar | Date, max: FilterScalar | Date): FieldCondition<T>;\n range<K extends ComparableKeys<T>>(key: K, from: FilterScalar | Date, to: FilterScalar | Date): FieldCondition<T>[];\n\n contains<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n startsWith<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n endsWith<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n like<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n ilike<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n notLike<K extends StringKeys<T>>(key: K, value: string): FieldCondition<T>;\n\n in<K extends FieldKey<T>>(key: K, value: Array<string | number>): FieldCondition<T>;\n notIn<K extends FieldKey<T>>(key: K, value: Array<string | number>): FieldCondition<T>;\n\n isNull<K extends FieldKey<T>>(key: K): FieldCondition<T>;\n isNotNull<K extends FieldKey<T>>(key: K): FieldCondition<T>;\n\n and(...nodes: Node<T>[]): AndGroup<T>;\n or(...nodes: Node<T>[]): OrGroup<T>;\n not(node: Node<T>): NotGroup<T>;\n}\n\n/**\n * Typed, ergonomic filter builder for an entity — field-name autocomplete plus\n * field-type-aware operators (see {@link TypedFilters}).\n *\n * @typeParam T - the list entity type (`Buyer`, `Product`, …).\n * @example\n * ```ts\n * const f = createFilters<Buyer>();\n * const filter = f.and(f.contains(\"buyerName\", s), f.gte(\"age\", 18));\n * // f.contains(\"age\", …) → compile error (age is a number)\n * ```\n */\nexport function createFilters<T = Record<string, unknown>>(): TypedFilters<T> {\n return coreCreateFilters<FieldKey<T>>() as unknown as TypedFilters<T>;\n}\n\n/** Untyped (entity-agnostic) filter builder — quick use, no field-type checks. */\nexport { f };\n","import { DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_PER_PAGE } from \"@querykitjs/core\";\n\nimport type {\n CursorParams,\n CursorPayload,\n FieldCondition,\n Filter,\n FilterNode,\n FilterValue,\n InfiniteParams,\n InfinitePayload,\n ListParams,\n ListPayload,\n Params,\n QueryPayload,\n Sort,\n SortInput,\n} from \"./types\";\n\n/** {@link createQuery} sozlamalari — wire field nomlari va default qiymatlar. */\nexport interface QueryConfig {\n filterField?: string;\n sortField?: string;\n columnsField?: string;\n withField?: string;\n withDeletedField?: string;\n withTotalField?: string;\n pageField?: string;\n perPageField?: string;\n limitField?: string;\n offsetField?: string;\n cursorField?: string;\n defaultPerPage?: number;\n defaultLimit?: number;\n /**\n * `perPage` yuqori chegarasi (core `DEFAULT_MAX_PER_PAGE` = 200) — backend\n * repositorylari va `@querykitjs/zod` factory'lari bilan **bir xil manba**,\n * shuning uchun front rad etiladigan so'rovni umuman yubormaydi.\n */\n maxPerPage?: number;\n /** `limit` yuqori chegarasi (core `DEFAULT_MAX_LIMIT` = 200). */\n maxLimit?: number;\n /**\n * Sahifa chuqurligi: list'da `(page - 1) × perPage`, infinite'da `offset` (core\n * `DEFAULT_MAX_OFFSET` = 10 000). Oshsa builder `Error` tashlaydi — jim kesish\n * so'rov ma'nosini o'zgartirardi. Chuqurroq sahifalar — cursor.\n */\n maxOffset?: number;\n /** `sort` maydonlari soni (core `DEFAULT_MAX_SORT_FIELDS` = 3). Oshsa — `Error`. */\n maxSortFields?: number;\n defaultSort?: Sort;\n /** Bo'sh qiymatli filterlarni tashlash (default `true`). */\n pruneEmpty?: boolean;\n}\n\nconst DEFAULTS: Required<QueryConfig> = {\n filterField: \"filter\",\n sortField: \"sort\",\n columnsField: \"columns\",\n withField: \"with\",\n withDeletedField: \"withDeleted\",\n withTotalField: \"withTotal\",\n pageField: \"page\",\n perPageField: \"perPage\",\n limitField: \"limit\",\n offsetField: \"offset\",\n cursorField: \"cursor\",\n defaultPerPage: DEFAULT_PER_PAGE,\n defaultLimit: DEFAULT_LIMIT,\n maxPerPage: DEFAULT_MAX_PER_PAGE,\n maxLimit: DEFAULT_MAX_LIMIT,\n maxOffset: DEFAULT_MAX_OFFSET,\n maxSortFields: DEFAULT_MAX_SORT_FIELDS,\n defaultSort: [{ key: \"createdAt\", direction: \"desc\" }],\n pruneEmpty: true,\n};\n\n/** Bo'sh (yuborilmaydigan) qiymatmi: undefined/null/\"\"/[] . `false`/`0` — bo'sh emas. */\nfunction isEmptyValue(value: FilterValue | undefined): boolean {\n if (value === undefined || value === null || value === \"\") return true;\n if (Array.isArray(value) && value.length === 0) return true;\n return false;\n}\n\n/** A `\"-field\"`/`\"field\"` shorthand string or a `{ key, direction }` item → a `SortItem`. */\nfunction toSortItem(item: Sort[number] | string): Sort[number] | undefined {\n if (typeof item === \"string\") {\n const desc = item.startsWith(\"-\");\n const key = (desc ? item.slice(1) : item).trim();\n return key ? { key, direction: desc ? \"desc\" : \"asc\" } : undefined;\n }\n return item && item.key ? { key: item.key, direction: item.direction ?? \"asc\" } : undefined;\n}\n\n/** Normalize a sort array (objects and/or `\"-field\"` strings) → canonical `SortItem[]`; empty → fallback. */\nexport function normalizeSort(input: SortInput | undefined, fallback: Sort): Sort {\n if (!input || input.length === 0) return fallback;\n const items = input.map(toSortItem).filter((i): i is Sort[number] => i !== undefined);\n return items.length ? items : fallback;\n}\n\nfunction normalizeCondition(condition: FieldCondition, prune: boolean): FieldCondition | undefined {\n const operation = condition.operation ?? \"=\";\n const noValue = operation === \"isNull\" || operation === \"isNotNull\";\n const value = condition.value as FilterValue;\n\n if (!noValue && prune && isEmptyValue(value)) return undefined;\n\n const out: FieldCondition = { key: condition.key, operation };\n if (!noValue) out.value = value;\n return out;\n}\n\nfunction normalizeNode(node: FilterNode, prune: boolean): FilterNode | undefined {\n if (\"and\" in node) {\n const kids = node.and.map(n => normalizeNode(n, prune)).filter((n): n is FilterNode => !!n);\n return kids.length ? { and: kids } : undefined;\n }\n if (\"or\" in node) {\n const kids = node.or.map(n => normalizeNode(n, prune)).filter((n): n is FilterNode => !!n);\n return kids.length ? { or: kids } : undefined;\n }\n if (\"not\" in node) {\n const inner = normalizeNode(node.not, prune);\n return inner ? { not: inner } : undefined;\n }\n return normalizeCondition(node, prune);\n}\n\n/** Filterni normalizatsiya qiladi: bo'sh shartlarni prune. Massiv → flat massiv. */\nexport function normalizeFilter(filter: Filter | undefined, prune: boolean): FieldCondition[] | FilterNode {\n if (!filter) return [];\n if (Array.isArray(filter)) {\n return filter.map(c => normalizeCondition(c, prune)).filter((c): c is FieldCondition => !!c);\n }\n return normalizeNode(filter, prune) ?? [];\n}\n\n/** Umumiy qism: filter/columns/with (+ withDeleted). Sort qo'shilmaydi. */\nfunction buildBase(input: Params, cfg: Required<QueryConfig>): Record<string, unknown> {\n const base: Record<string, unknown> = {\n [cfg.filterField]: normalizeFilter(input.filter, cfg.pruneEmpty),\n [cfg.columnsField]: input.columns ?? {},\n [cfg.withField]: input.with ?? {},\n };\n if (input.withDeleted !== undefined) base[cfg.withDeletedField] = input.withDeleted;\n return base;\n}\n\n/** A positive integer (fraction truncated); absent, < 1 or NaN → `fallback`; capped at `max`. */\nexport function clampInt(value: number | undefined, fallback: number, max = Infinity): number {\n const resolved = value === undefined || value < 1 || Number.isNaN(value) ? fallback : Math.trunc(value);\n return Math.min(max, resolved);\n}\n\n/**\n * The server rejects a request past a limit; the builder refuses to make one.\n * Filter limits stay with the server.\n */\nfunction limitError(what: string, limit: \"maxOffset\" | \"maxSortFields\", max: number, hint = \"\"): Error {\n return new Error(`querykit: ${what} exceeds ${limit} (${max})${hint}`);\n}\n\nfunction build(input: Params, cfg: Required<QueryConfig>): Record<string, unknown> {\n const sort = normalizeSort(input.sort, cfg.defaultSort);\n if (sort.length > cfg.maxSortFields) throw limitError(`sort with ${sort.length} fields`, \"maxSortFields\", cfg.maxSortFields);\n return { ...buildBase(input, cfg), [cfg.sortField]: sort };\n}\n\nconst CURSOR_HINT = \"; use cursor pagination for deeper pages\";\n\nfunction buildList(input: ListParams, cfg: Required<QueryConfig>): Record<string, unknown> {\n const page = clampInt(input.page, 1); // page >= 1 (kasr/0/manfiy → 1)\n const perPage = clampInt(input.perPage, cfg.defaultPerPage, cfg.maxPerPage);\n if ((page - 1) * perPage > cfg.maxOffset) throw limitError(`page ${page} × perPage ${perPage}`, \"maxOffset\", cfg.maxOffset, CURSOR_HINT);\n const payload: Record<string, unknown> = { ...build(input, cfg), [cfg.pageField]: page, [cfg.perPageField]: perPage };\n if (input.withTotal !== undefined) payload[cfg.withTotalField] = input.withTotal;\n return payload;\n}\n\nfunction buildInfinite(input: InfiniteParams, cfg: Required<QueryConfig>): Record<string, unknown> {\n const offset = input.offset && input.offset > 0 ? Math.trunc(input.offset) : 0;\n if (offset > cfg.maxOffset) throw limitError(`offset ${offset}`, \"maxOffset\", cfg.maxOffset, CURSOR_HINT);\n return {\n ...build(input, cfg),\n [cfg.limitField]: clampInt(input.limit, cfg.defaultLimit, cfg.maxLimit),\n [cfg.offsetField]: offset,\n };\n}\n\nfunction buildCursor(input: CursorParams, cfg: Required<QueryConfig>): Record<string, unknown> {\n const payload: Record<string, unknown> = {\n ...buildBase(input, cfg),\n [cfg.limitField]: clampInt(input.limit, cfg.defaultLimit, cfg.maxLimit),\n [cfg.cursorField]: input.cursor ?? null,\n order: input.order ?? \"asc\",\n direction: input.direction ?? \"forward\",\n };\n if (input.cursorKey !== undefined) payload.cursorKey = input.cursorKey;\n return payload;\n}\n\n/**\n * Config bilan bog'langan query quruvchilarni qaytaradi. Boshqa backend field\n * nomlari (masalan `perPage`, `withPopulates`) uchun.\n *\n * @example\n * ```ts\n * const q = createQuery({ withField: \"withPopulates\", defaultPerPage: 20 });\n * const params = q.list({ filter, page, perPage });\n * ```\n */\nexport function createQuery(config: QueryConfig = {}) {\n const cfg = { ...DEFAULTS, ...config };\n return {\n params: (input: Params = {}) => build(input, cfg),\n list: (input: ListParams = {}) => buildList(input, cfg),\n infinite: (input: InfiniteParams = {}) => buildInfinite(input, cfg),\n cursor: (input: CursorParams = {}) => buildCursor(input, cfg),\n };\n}\n\n/**\n * Params'ni normalizatsiya qiladi (paginatsiyasiz): filter prune, sort decode,\n * `with`/`columns` pass-through. Default querykit wire-format.\n *\n * @example\n * ```ts\n * const payload = buildParams({\n * filter: [{ key: \"name\", operation: \"%_%\", value: s }],\n * sort: [{ key: \"createdAt\", direction: \"desc\" }],\n * with: { supervisor: true },\n * });\n * ```\n */\nexport function buildParams(input: Params = {}): QueryPayload {\n return build(input, DEFAULTS) as unknown as QueryPayload;\n}\n\n/**\n * {@link buildParams} + `page`/`perPage` (default `perPage = 20`, `@querykitjs/core`).\n *\n * @example\n * ```ts\n * const payload = buildListParams({ filter, sort: [{ key: \"createdAt\", direction: \"desc\" }], page: 2, perPage: 20 });\n * // -> { filter, sort: [{ key, direction }], columns, with, page, perPage }\n * ```\n */\nexport function buildListParams(input: ListParams = {}): ListPayload {\n return buildList(input, DEFAULTS) as unknown as ListPayload;\n}\n\n/**\n * Infinite-scroll payload — {@link buildParams} + `limit`/`offset` (default\n * `limit = 20`).\n *\n * @example\n * ```ts\n * const payload = buildInfiniteParams({ filter, limit: 20, offset: 40 });\n * // -> { filter, sort, columns, with, limit, offset }\n * ```\n */\nexport function buildInfiniteParams(input: InfiniteParams = {}): InfinitePayload {\n return buildInfinite(input, DEFAULTS) as unknown as InfinitePayload;\n}\n\n/**\n * Cursor (keyset) payload — `sort` o'rniga `order`/`direction`. `cursor`\n * oldingi javob meta'sidagi `next_cursor`/`prev_cursor` tokeni.\n *\n * @example\n * ```ts\n * const payload = buildCursorParams({ filter, limit: 20, cursor, order: \"asc\" });\n * // -> { filter, columns, with, limit, cursor, order, direction }\n * ```\n */\nexport function buildCursorParams(input: CursorParams = {}): CursorPayload {\n return buildCursor(input, DEFAULTS) as unknown as CursorPayload;\n}\n","import type { CursorMeta, InfiniteMeta, Meta, RawCursorMeta, RawInfiniteMeta, RawMeta } from \"./types\";\n\n/** A server `null` total means \"not counted\" (`withTotal: false`) and stays `null`; an absent one is `0`. */\nconst total = (value: number | null | undefined): number | null => (value === null ? null : (value ?? 0));\n\n/**\n * **Offset** (list) meta'sini snake_case → camelCase map qiladi.\n *\n * @example\n * ```ts\n * const { data, meta } = (await http.post(\"/buyers/list\", params)).data;\n * setMeta(mapMeta(meta)); // { totalPages, totalCount, currentPage, perPage, hasNext, hasPrev }\n * ```\n */\nexport function mapMeta(raw?: RawMeta | null): Meta {\n return {\n totalPages: total(raw?.total_pages),\n totalCount: total(raw?.total_items),\n currentPage: raw?.current_page ?? 0,\n perPage: raw?.per_page ?? 0,\n hasNext: raw?.has_next ?? false,\n hasPrev: raw?.has_prev ?? false,\n };\n}\n\n/**\n * **Infinite-scroll** meta'sini map qiladi.\n *\n * @example\n * ```ts\n * const m = mapInfiniteMeta(res.meta); // { limit, offset, count, hasMore, nextOffset }\n * if (m.hasMore) load(m.nextOffset);\n * ```\n */\nexport function mapInfiniteMeta(raw?: RawInfiniteMeta | null): InfiniteMeta {\n return {\n limit: raw?.limit ?? 0,\n offset: raw?.offset ?? 0,\n count: raw?.count ?? 0,\n hasMore: raw?.has_more ?? false,\n nextOffset: raw?.next_offset ?? null,\n };\n}\n\n/**\n * **Cursor** (keyset) meta'sini map qiladi.\n *\n * @example\n * ```ts\n * const m = mapCursorMeta(res.meta); // { limit, hasNext, hasPrev, nextCursor, prevCursor }\n * ```\n */\nexport function mapCursorMeta(raw?: RawCursorMeta | null): CursorMeta {\n return {\n limit: raw?.limit ?? 0,\n hasNext: raw?.has_next ?? false,\n hasPrev: raw?.has_prev ?? false,\n nextCursor: raw?.next_cursor ?? null,\n prevCursor: raw?.prev_cursor ?? null,\n };\n}\n","import type { FilterOperator, FilterValue } from \"./types\";\n\n/** Forbids the listed keys (`?: never`) so modes can't be mixed. */\ntype Without<K extends string> = { [P in K]?: never };\n\n/** Filter-key override, shared by the single-key modes. */\ninterface KeyBase {\n /** Backend field key (defaults to the schema param name). */\n key?: string;\n}\n\n/**\n * **Simple** mode — one URL param → one condition. `operation` defaults to `\"=\"`;\n * `trim`/`default`/`split` shape the value.\n */\nexport interface SimpleField extends KeyBase {\n /** Filter operation (default `\"=\"`). */\n operation?: FilterOperator;\n /** Trim the string value. */\n trim?: boolean;\n /** Value used when the URL param is absent. */\n default?: FilterValue;\n /**\n * For array operations (`in`/`notIn`): split a comma-string into an array.\n * `true` → delimiter `\",\"`; or a custom delimiter. Guarded: absent/empty →\n * pruned; parts trimmed, empties dropped.\n */\n split?: boolean | string;\n}\n\n/** **Range** mode — `[fromParam, toParam]` → two inclusive conditions (`>=`, `<=`). */\nexport interface RangeField extends KeyBase {\n range: [string, string];\n}\n\n/** **Between** mode — `[fromParam, toParam]` → one `between` condition (2-tuple). */\nexport interface BetweenField extends KeyBase {\n between: [string, string];\n}\n\n/** **Search** mode — one URL param → OR of `contains` across these field keys. */\nexport interface SearchField {\n search: string[];\n trim?: boolean;\n default?: FilterValue;\n}\n\n/**\n * One list field's URL→filter mapping. Exactly **one mode** per descriptor —\n * Simple / Range / Between / Search — enforced at compile time (mixing e.g.\n * `range` + `search`, or `range` + `between`, is a type error).\n */\nexport type FieldDescriptor =\n | (SimpleField & Without<\"range\" | \"between\" | \"search\">)\n | (RangeField & Without<\"operation\" | \"trim\" | \"default\" | \"split\" | \"between\" | \"search\">)\n | (BetweenField & Without<\"operation\" | \"trim\" | \"default\" | \"split\" | \"range\" | \"search\">)\n | (SearchField & Without<\"key\" | \"operation\" | \"split\" | \"range\" | \"between\">);\n\n/** URL param → {@link FieldDescriptor} map. */\nexport type ListSchema = Record<string, FieldDescriptor>;\n\n/**\n * Declares a list filter schema (identity helper — preserves the literal type).\n * Maps URL params to `{key, operation, value}` conditions so pages never build\n * `IFilter[]` by hand.\n *\n * @example\n * ```ts\n * const buyersSchema = defineListSchema({\n * id: { operation: \"=\" },\n * status: { operation: \"=\", default: \"active\" },\n * ids: { operation: \"in\", split: true },\n * q: { search: [\"name\", \"email\"] },\n * createdAt: { range: [\"fromDate\", \"toDate\"] },\n * });\n * ```\n */\nexport function defineListSchema<S extends ListSchema>(schema: S): S {\n return schema;\n}\n","import { DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_PER_PAGE } from \"@querykitjs/core\";\n\nimport { buildListParams, clampInt } from \"./query\";\nimport type { FieldDescriptor, ListSchema } from \"./schema\";\nimport type { FieldCondition, Filter, FilterNode, FilterValue, ListParams, ListPayload, Sort, SortDirection, SortInput } from \"./types\";\n\n/** URL param nomlari (sahifa/o'lcham/sort) — sozlanadigan. */\nexport interface UrlConfig {\n pageParam?: string;\n sizeParam?: string;\n sortParam?: string;\n}\n\nconst URL_DEFAULTS: Required<UrlConfig> = {\n pageParam: \"page\",\n sizeParam: \"size\",\n sortParam: \"sortType\",\n};\n\n/**\n * `\"-createdAt,id,-appNumber\"` → `[{ key, direction }, …]` — comma-separated,\n * order preserved, `-` prefix = `desc` (else `asc`). Empty → `undefined`.\n */\nexport function decodeSort(value: string | null | undefined): Sort | undefined {\n if (!value) return undefined;\n const items = value\n .split(\",\")\n .map(s => s.trim())\n .filter(Boolean)\n .map(tok => {\n const desc = tok.startsWith(\"-\");\n return { key: desc ? tok.slice(1) : tok, direction: (desc ? \"desc\" : \"asc\") as SortDirection };\n })\n .filter(i => i.key); // drop empty keys (e.g. a lone \"-\")\n return items.length ? items : undefined;\n}\n\n/** `[{ key, direction }, …]` (or `\"-field\"` shorthand strings) → `\"-createdAt,id,-appNumber\"` (empty → `\"\"`). */\nexport function encodeSort(sort: SortInput): string {\n return sort\n .map(i => (typeof i === \"string\" ? i.trim() : i && i.key ? (i.direction === \"desc\" ? \"-\" : \"\") + i.key : \"\"))\n .filter(Boolean)\n .join(\",\");\n}\n\n/**\n * Schema + searchParams → filter. Applies `range`/`between`/`search`/`split`/\n * `default`/`trim`; empty/absent params are dropped. Returns a flat\n * `FieldCondition[]` (implicit AND), or a tree when a `search` OR-group is\n * present (`{ and: [orGroup, …conditions] }`).\n */\nexport function schemaToFilter(schema: ListSchema, searchParams: URLSearchParams): Filter {\n const conditions: FieldCondition[] = [];\n const groups: FilterNode[] = [];\n\n for (const [param, d] of Object.entries(schema) as [string, FieldDescriptor][]) {\n const key = d.key ?? param;\n\n // range → two inclusive conditions (>= , <=)\n if (d.range) {\n const from = searchParams.get(d.range[0]);\n const to = searchParams.get(d.range[1]);\n if (from) conditions.push(cond(key, \">=\", from));\n if (to) conditions.push(cond(key, \"<=\", to));\n continue;\n }\n\n // between → one condition with a 2-tuple value\n if (d.between) {\n const from = searchParams.get(d.between[0]);\n const to = searchParams.get(d.between[1]);\n if (from && to) conditions.push(cond(key, \"between\", [from, to]));\n continue;\n }\n\n // read value, falling back to `default` only when the param is ABSENT\n // (an empty `?x=` means the user cleared the filter → prune, don't default).\n const raw = searchParams.get(param);\n let value: FilterValue | undefined = raw !== null ? raw : d.default;\n if (typeof value === \"string\" && d.trim) value = value.trim();\n if (value === undefined || value === null || value === \"\") continue;\n if (Array.isArray(value) && value.length === 0) continue;\n\n // search → OR of `contains` across the listed fields (needs a string)\n if (d.search && typeof value === \"string\") {\n groups.push({ or: d.search.map(field => cond(field, \"%_%\", value as string)) });\n continue;\n }\n\n // split → comma-string → array (for `in`/`notIn`); guarded against empties\n if (d.split && typeof value === \"string\") {\n const delimiter = d.split === true ? \",\" : d.split;\n const parts = value\n .split(delimiter)\n .map(s => s.trim())\n .filter(Boolean);\n if (parts.length === 0) continue;\n value = parts;\n }\n\n conditions.push(cond(key, d.operation ?? \"=\", value));\n }\n\n return groups.length === 0 ? conditions : { and: [...groups, ...conditions] };\n}\n\nfunction cond(key: string, operation: FieldCondition[\"operation\"], value: FilterValue): FieldCondition {\n return { key, operation, value };\n}\n\n/**\n * The bounds the URL readers clamp to — the builder's own (`createRegistry`\n * `defaults`); an absent one is the core default.\n */\nexport interface UrlLimits {\n perPage?: number;\n maxPerPage?: number;\n maxOffset?: number;\n maxSortFields?: number;\n}\n\n/** {@link ListParams} read from a URL. `clamped` — the URL's page or sort was cut to the limits. */\nexport type UrlListParams = ListParams & { clamped: boolean };\n\n/**\n * A list payload built from a URL. `clamped` is non-enumerable: readable in code,\n * never serialized, so the wire payload is unchanged.\n */\nexport type UrlListPayload = ListPayload & { readonly clamped?: boolean };\n\n/** Marks a payload with a non-enumerable `clamped` flag. */\nexport function withClamped(payload: ListPayload, clamped: boolean): UrlListPayload {\n return Object.defineProperty(payload, \"clamped\", { value: clamped, enumerable: false });\n}\n\n/** The last page the builder accepts: `(page - 1) × perPage ≤ maxOffset`. */\nfunction lastPage(perPage: number | undefined, limits: UrlLimits): number {\n const resolved = clampInt(perPage, limits.perPage ?? DEFAULT_PER_PAGE, limits.maxPerPage ?? DEFAULT_MAX_PER_PAGE);\n return Math.floor((limits.maxOffset ?? DEFAULT_MAX_OFFSET) / resolved) + 1;\n}\n\n/**\n * searchParams → normalizatsiyalanmagan {@link ListParams} (filter/sort/page/perPage).\n * The URL is user input: a page past `maxOffset` becomes the last allowed page and a\n * sort past `maxSortFields` keeps its first fields, with `clamped: true` — so a\n * hand-edited `?page=9999` never throws during render. The builders still throw\n * for a direct call.\n */\nexport function readListParams(schema: ListSchema, searchParams: URLSearchParams, url: UrlConfig = {}, limits: UrlLimits = {}): UrlListParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const size = searchParams.get(cfg.sizeParam);\n const perPage = size ? Number(size) : undefined;\n const page = Math.trunc(Number(searchParams.get(cfg.pageParam))) || 1;\n const sort = decodeSort(searchParams.get(cfg.sortParam));\n const maxPage = lastPage(perPage, limits);\n const maxSortFields = limits.maxSortFields ?? DEFAULT_MAX_SORT_FIELDS;\n const isPageClamped = page > maxPage;\n const isSortClamped = sort !== undefined && sort.length > maxSortFields;\n return {\n filter: schemaToFilter(schema, searchParams),\n sort: isSortClamped ? sort.slice(0, maxSortFields) : sort,\n page: isPageClamped ? maxPage : page,\n perPage,\n clamped: isPageClamped || isSortClamped,\n };\n}\n\n/** searchParams → to'liq, yuborishga tayyor {@link ListPayload} (core default limits; clamped like {@link readListParams}). */\nexport function searchParamsToPayload(schema: ListSchema, searchParams: URLSearchParams, url?: UrlConfig): UrlListPayload {\n const params = readListParams(schema, searchParams, url);\n return withClamped(buildListParams(params), params.clamped);\n}\n\n/* ------------------------- URL yozish (immutable) ------------------------- */\n/* Har biri YANGI URLSearchParams qaytaradi; filter/sort o'zgarsa `page` reset. */\n\nfunction clone(searchParams: URLSearchParams): URLSearchParams {\n return new URLSearchParams(searchParams);\n}\n\n/** Filter param'ini o'rnatadi/o'chiradi va `page`ni reset qiladi. */\nexport function setParam(searchParams: URLSearchParams, name: string, value: string | null | undefined, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n if (value === null || value === undefined || value === \"\") next.delete(name);\n else next.set(name, value);\n return next;\n}\n\n/** Sahifani o'rnatadi (`page` reset qilinmaydi). */\nexport function setPage(searchParams: URLSearchParams, page: number, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.set(cfg.pageParam, String(page));\n return next;\n}\n\n/** Sahifa o'lchamini o'rnatadi va `page`ni reset qiladi. */\nexport function setSize(searchParams: URLSearchParams, size: number, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n next.set(cfg.sizeParam, String(size));\n return next;\n}\n\n/** Sortni o'rnatadi (`[{ key, direction }, …]`) va `page`ni reset qiladi. */\nexport function setSort(searchParams: URLSearchParams, sort: SortInput, url: UrlConfig = {}): URLSearchParams {\n const cfg = { ...URL_DEFAULTS, ...url };\n const next = clone(searchParams);\n next.delete(cfg.pageParam);\n const encoded = encodeSort(sort);\n if (encoded) next.set(cfg.sortParam, encoded);\n else next.delete(cfg.sortParam);\n return next;\n}\n\n/** Barcha list param'larini tozalaydi (ixtiyoriy saqlanadigan kalitlar bilan). */\nexport function resetParams(searchParams: URLSearchParams, keep: string[] = []): URLSearchParams {\n const next = new URLSearchParams();\n for (const key of keep) {\n const value = searchParams.get(key);\n if (value !== null) next.set(key, value);\n }\n return next;\n}\n","import { createQuery, normalizeSort, type QueryConfig } from \"./query\";\nimport { createFilters, f as rawF } from \"./filters\";\nimport { mapMeta, mapInfiniteMeta, mapCursorMeta } from \"./meta\";\nimport { defineListSchema, type ListSchema } from \"./schema\";\nimport { readListParams, withClamped, type UrlConfig, type UrlLimits, type UrlListPayload } from \"./url\";\nimport type { AdapterName, WithFor } from \"./adapter\";\nimport type {\n CursorMeta,\n CursorParams,\n CursorPayload,\n FieldKey,\n Filter,\n InfiniteMeta,\n InfiniteParams,\n InfinitePayload,\n ListParams,\n ListPayload,\n Meta,\n Params,\n QueryPayload,\n RawCursorMeta,\n RawInfiniteMeta,\n RawMeta,\n Sort,\n SortDirection,\n SortInput,\n} from \"./types\";\n\n/* ---------------- resource inputs: entity-typed, adapter-aware `with` ------ */\n\nexport type ResourceListParams<T, A extends AdapterName> = Omit<ListParams<T>, \"with\"> & { with?: WithFor<A> };\nexport type ResourceInfiniteParams<T, A extends AdapterName> = Omit<InfiniteParams<T>, \"with\"> & { with?: WithFor<A> };\nexport type ResourceCursorParams<T, A extends AdapterName> = Omit<CursorParams<T>, \"with\"> & { with?: WithFor<A> };\nexport type ResourceParams<T, A extends AdapterName> = Omit<Params<T>, \"with\"> & { with?: WithFor<A> };\n\n/** `resource.search` options. */\nexport interface SearchOptions {\n /** The string operator per field (default `\"contains\"`). */\n operation?: \"contains\" | \"startsWith\" | \"endsWith\";\n}\n\n/* ---------------------------- responses / results ------------------------- */\n\ninterface RawResponse<T, M> {\n data?: T[];\n meta?: M | null;\n}\nexport interface ListResult<T> {\n data: T[];\n meta: Meta;\n}\nexport interface InfiniteResult<T> {\n data: T[];\n meta: InfiniteMeta;\n}\nexport interface CursorResult<T> {\n data: T[];\n meta: CursorMeta;\n}\n\n/* -------------------------------- query keys ------------------------------ */\n\nexport interface ResourceKeys {\n all: readonly unknown[];\n list(payload: unknown): readonly unknown[];\n infinite(payload: unknown): readonly unknown[];\n cursor(payload: unknown): readonly unknown[];\n detail(id: unknown): readonly unknown[];\n}\n\n/* -------------------------------- resource -------------------------------- */\n\nexport interface Resource<T, A extends AdapterName> {\n /** Build an offset (page) payload. */\n list(input?: ResourceListParams<T, A>): ListPayload;\n /** Build an infinite (limit/offset) payload. */\n infinite(input?: ResourceInfiniteParams<T, A>): InfinitePayload;\n /** Build a cursor (keyset) payload. */\n cursor(input?: ResourceCursorParams<T, A>): CursorPayload;\n /** Build a paginationless payload (filter/sort/columns/with). */\n params(input?: ResourceParams<T, A>): QueryPayload;\n /** Filter builder typed to `T`'s fields. */\n f: ReturnType<typeof createFilters<T>>;\n /**\n * Search preset — OR of `operation` (default `contains`) across `fields` (one input → many columns).\n * Each field must be `filterable` with that operator on the server.\n */\n search(term: string, fields: FieldKey<T>[], options?: SearchOptions): Filter<T>;\n /** Declare a URL↔filter schema (identity helper). */\n schema<S extends ListSchema>(s: S): S;\n /**\n * Build a list payload from URL search params (SSR — the non-hook `useListParams`).\n * A page or sort past the registry limits is clamped (`clamped`, non-enumerable — never sent).\n */\n fromSearchParams(searchParams: URLSearchParams, options: { schema: ListSchema; url?: UrlConfig; with?: WithFor<A> }): UrlListPayload;\n /** Stable query keys for TanStack/SWR caches. */\n keys: ResourceKeys;\n /** Map a list response's meta to camelCase (`data` typed to `T`). */\n parseList(raw?: RawResponse<T, RawMeta> | null): ListResult<T>;\n parseInfinite(raw?: RawResponse<T, RawInfiniteMeta> | null): InfiniteResult<T>;\n parseCursor(raw?: RawResponse<T, RawCursorMeta> | null): CursorResult<T>;\n}\n\n/* -------------------------------- registry -------------------------------- */\n\nexport interface RegistryDefaults {\n /** `list` page size. */\n perPage?: number;\n /** `infinite` + `cursor` page size. */\n limit?: number;\n /**\n * `perPage` upper bound (core `DEFAULT_MAX_PER_PAGE` = 200) — the same constant\n * the zod factories and both backend repositories use, so the frontend never\n * sends a request the server would reject.\n */\n maxPerPage?: number;\n /** `limit` upper bound (core `DEFAULT_MAX_LIMIT` = 200). */\n maxLimit?: number;\n /** Page depth bound (core `DEFAULT_MAX_OFFSET` = 10 000) — a deeper `list`/`infinite` request throws. */\n maxOffset?: number;\n /** Sort field count bound (core `DEFAULT_MAX_SORT_FIELDS` = 3) — more fields throw. */\n maxSortFields?: number;\n /** `list`/`infinite` sort — `[{key,direction}]` or `[\"-createdAt\", \"id\"]` shorthand. */\n sort?: SortInput;\n /** Cursor-only defaults. */\n cursor?: { order?: SortDirection };\n}\n\n/** The backend registry's `timestamps` field names, so the web default sort names the same field. */\nexport interface RegistryTimestamps {\n /** The createdAt field (default `\"createdAt\"`) — the default `list`/`infinite` sort is `[{ key: createdAt, direction: \"desc\" }]`. */\n createdAt?: string;\n}\n\nexport interface RegistryConfig<A extends AdapterName> {\n adapter: A;\n defaults?: RegistryDefaults;\n /** Same as the backend registry's `timestamps`; `defaults.sort` wins over it. */\n timestamps?: RegistryTimestamps;\n /** Drop empty filter values built from form inputs (default `true`). */\n pruneEmpty?: boolean;\n}\n\nexport interface Registry<A extends AdapterName> {\n readonly adapter: A;\n /** Entity-typed builders + filters + schema + keys + parsers. `name` = cache-key namespace (required, must be unique). */\n resource<T>(name: string): Resource<T, A>;\n /** Registry-level meta parsing (entity-agnostic — `data: unknown[]`). */\n parseList(raw?: RawResponse<unknown, RawMeta> | null): ListResult<unknown>;\n parseInfinite(raw?: RawResponse<unknown, RawInfiniteMeta> | null): InfiniteResult<unknown>;\n parseCursor(raw?: RawResponse<unknown, RawCursorMeta> | null): CursorResult<unknown>;\n}\n\n/**\n * Create a web query registry — configure defaults + backend adapter once, then\n * `registry.resource<T>()` yields entity-typed, adapter-aware query builders,\n * filters, a URL↔filter schema, cache keys and meta parsers.\n *\n * @example\n * ```ts\n * export const qk = createRegistry({ adapter: \"mongoose\", defaults: { perPage: 20, sort: [\"-createdAt\"] } });\n * const users = qk.resource<IUser>(\"users\");\n * const body = users.list({ filter: users.f.eq(\"status\", \"active\"), page });\n * ```\n */\nexport function createRegistry<A extends AdapterName>(config: RegistryConfig<A>): Registry<A> {\n const defaults = config.defaults ?? {};\n const createdAt = config.timestamps?.createdAt;\n const timestampSort: Sort = createdAt ? [{ key: createdAt, direction: \"desc\" }] : [];\n const sort: Sort = normalizeSort(defaults.sort, timestampSort); // accepts {key,direction}[] or \"-field\"[] shorthand\n const cursorOrder: SortDirection = defaults.cursor?.order ?? \"asc\";\n\n // Only set keys that are provided — createQuery merges over its own defaults,\n // and passing `undefined` would clobber them.\n const qcfg: QueryConfig = {};\n if (defaults.perPage !== undefined) qcfg.defaultPerPage = defaults.perPage;\n if (defaults.limit !== undefined) qcfg.defaultLimit = defaults.limit;\n if (defaults.maxPerPage !== undefined) qcfg.maxPerPage = defaults.maxPerPage;\n if (defaults.maxLimit !== undefined) qcfg.maxLimit = defaults.maxLimit;\n if (defaults.maxOffset !== undefined) qcfg.maxOffset = defaults.maxOffset;\n if (defaults.maxSortFields !== undefined) qcfg.maxSortFields = defaults.maxSortFields;\n if (sort.length) qcfg.defaultSort = sort; // only override when a real sort is given\n if (config.pruneEmpty !== undefined) qcfg.pruneEmpty = config.pruneEmpty;\n const q = createQuery(qcfg);\n const urlLimits: UrlLimits = {\n perPage: defaults.perPage,\n maxPerPage: defaults.maxPerPage,\n maxOffset: defaults.maxOffset,\n maxSortFields: defaults.maxSortFields,\n };\n\n const parseList = (raw?: RawResponse<unknown, RawMeta> | null): ListResult<unknown> => ({ data: raw?.data ?? [], meta: mapMeta(raw?.meta) });\n const parseInfinite = (raw?: RawResponse<unknown, RawInfiniteMeta> | null): InfiniteResult<unknown> => ({\n data: raw?.data ?? [],\n meta: mapInfiniteMeta(raw?.meta),\n });\n const parseCursor = (raw?: RawResponse<unknown, RawCursorMeta> | null): CursorResult<unknown> => ({\n data: raw?.data ?? [],\n meta: mapCursorMeta(raw?.meta),\n });\n\n function resource<T>(name: string): Resource<T, A> {\n const f = createFilters<T>();\n const keys: ResourceKeys = {\n all: [name],\n list: p => [name, \"list\", p],\n infinite: p => [name, \"infinite\", p],\n cursor: p => [name, \"cursor\", p],\n detail: id => [name, \"detail\", id],\n };\n return {\n list: input => q.list(input as unknown as ListParams) as unknown as ListPayload,\n infinite: input => q.infinite(input as unknown as InfiniteParams) as unknown as InfinitePayload,\n cursor: input => q.cursor({ ...(input as unknown as CursorParams), order: input?.order ?? cursorOrder }) as unknown as CursorPayload,\n params: input => q.params(input as unknown as Params) as unknown as QueryPayload,\n f,\n search: (term, fields, options) => rawF.or(...fields.map(field => rawF[options?.operation ?? \"contains\"](field, term))) as unknown as Filter<T>,\n schema: s => defineListSchema(s),\n fromSearchParams: (searchParams, options) => {\n const read = readListParams(options.schema, searchParams, options.url, urlLimits);\n return withClamped(q.list({ ...read, with: options.with } as unknown as ListParams) as unknown as ListPayload, read.clamped);\n },\n keys,\n parseList: raw => parseList(raw) as ListResult<T>,\n parseInfinite: raw => parseInfinite(raw) as InfiniteResult<T>,\n parseCursor: raw => parseCursor(raw) as CursorResult<T>,\n };\n }\n\n return { adapter: config.adapter, resource, parseList, parseInfinite, parseCursor };\n}\n","import type { SkipReason, SkippedCondition, SkipSite } from \"@querykitjs/core\";\n\n/**\n * The `QueryKitError.info` shape a backend may put in its 400 response body. The\n * response envelope is the project's own; web only types this part.\n */\nexport type QueryKitErrorBody = Pick<SkippedCondition, \"site\" | \"key\" | \"reason\"> & Partial<Pick<SkippedCondition, \"source\" | \"operation\">>;\n\n/* Records keyed by the core unions: a new core reason or site fails the typecheck here until it is listed. */\nconst REASONS: Record<SkipReason, true> = {\n \"unknown-key\": true,\n \"invalid-value\": true,\n \"forbidden-key\": true,\n \"forbidden-operator\": true,\n \"limit-exceeded\": true,\n \"empty-filter\": true,\n};\nconst SITES: Record<SkipSite, true> = { filter: true, sort: true, cursorKey: true, aggregate: true, page: true, mutation: true, with: true };\n\nconst isMember = <K extends string>(table: Record<K, true>, value: unknown): value is K => typeof value === \"string\" && Object.hasOwn(table, value);\n\n/**\n * Is `body` a querykit error (`reason`, `site`, `key`)? Lets the frontend tell a\n * rejected query (forbidden key, limit exceeded, …) from any other 400.\n *\n * @example\n * ```ts\n * const body = error.response?.data?.error;\n * if (isQueryKitError(body) && body.reason === \"forbidden-key\") showFieldError(body.key);\n * ```\n */\nexport function isQueryKitError(body: unknown): body is QueryKitErrorBody {\n if (typeof body !== \"object\" || body === null) return false;\n const candidate = body as Record<string, unknown>;\n return isMember(REASONS, candidate.reason) && isMember(SITES, candidate.site) && typeof candidate.key === \"string\";\n}\n","import type { AdapterName, WithFor } from \"./adapter\";\nimport type { Resource } from \"./registry\";\nimport type { ListSchema } from \"./schema\";\nimport type { ListPayload, SortInput } from \"./types\";\nimport type { UrlConfig } from \"./url\";\nimport { resetParams, setPage, setParam, setSize, setSort } from \"./url\";\n\nexport interface ListStateOptions<A extends AdapterName> {\n /** URL↔filter schema ({@link defineListSchema} / `resource.schema`). */\n schema: ListSchema;\n /** URL param names (page/size/sortType) — optional. */\n url?: UrlConfig;\n /** Fixed relations to load on every request (not URL-driven). */\n with?: WithFor<A>;\n}\n\nexport interface ListStateRead {\n /** Ready-to-send list payload (built from the URL via the resource's defaults). */\n params: ListPayload;\n /** The URL's page or sort was past the limits and was clamped (`?page=9999` → the last allowed page). */\n clamped: boolean;\n}\n\n/** URL setters: each returns the NEXT search params and never mutates the given ones. */\nexport interface ListStateActions {\n /** Set/clear a filter param (resets `page`). */\n setParam: (name: string, value: string | null | undefined) => URLSearchParams;\n setPage: (page: number) => URLSearchParams;\n /** Resets `page`. */\n setSize: (size: number) => URLSearchParams;\n /** Resets `page`; an empty sort clears the param. */\n setSort: (sort: SortInput) => URLSearchParams;\n /** Clears every param except `keep`. */\n reset: (keep?: string[]) => URLSearchParams;\n}\n\nexport interface ListState {\n read: (searchParams: URLSearchParams) => ListStateRead;\n actions: (searchParams: URLSearchParams) => ListStateActions;\n}\n\n/**\n * Framework-free list URL state — the logic behind `useListParams` in `@querykitjs/web/react`\n * and `@querykitjs/web/vue`, for any other framework (Svelte, Solid, vanilla). Pure: it reads\n * search params and returns the next ones; navigating is the caller's job.\n *\n * @example\n * ```ts\n * const list = createListState(users, { schema: usersSchema });\n * const { params, clamped } = list.read(new URLSearchParams(location.search));\n * history.pushState(null, \"\", `?${list.actions(new URLSearchParams(location.search)).setPage(2)}`);\n * ```\n */\nexport function createListState<T, A extends AdapterName>(resource: Resource<T, A>, options: ListStateOptions<A>): ListState {\n const { schema, url, with: withRel } = options;\n return {\n read(searchParams) {\n const params = resource.fromSearchParams(searchParams, { schema, url, with: withRel });\n return { params, clamped: params.clamped === true };\n },\n actions(searchParams) {\n return {\n setParam: (name, value) => setParam(searchParams, name, value, url),\n setPage: page => setPage(searchParams, page, url),\n setSize: size => setSize(searchParams, size, url),\n setSort: sort => setSort(searchParams, sort, url),\n reset: keep => resetParams(searchParams, keep),\n };\n },\n };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { b as Sort, C as CursorParams, c as CursorPayload, I as InfiniteParams, d as InfinitePayload, e as ListParams, a as ListPayload, P as Params, Q as QueryPayload, F as Filter, f as FieldCondition, g as FilterNode, S as SortInput, A as AdapterName, L as ListSchema, U as UrlConfig, W as WithFor, R as Resource } from './registry-CEq4xFui.cjs';
|
|
2
|
+
export { h as AndGroup, i as CursorMeta, j as CursorResult, D as DrizzleWith, k as FieldDescriptor, l as FieldKey, m as FilterOperator, n as FilterScalar, o as FilterValue, p as InfiniteMeta, q as InfiniteResult, r as ListResult, M as Meta, s as MongoosePopulate, N as NotGroup, O as OrGroup, t as PrismaInclude, u as RawCursorMeta, v as RawInfiniteMeta, w as RawMeta, x as Registry, y as RegistryConfig, z as RegistryDefaults, B as RegistryTimestamps, E as ResourceCursorParams, G as ResourceInfiniteParams, H as ResourceKeys, J as ResourceListParams, K as ResourceParams, T as SearchOptions, V as SortDirection, X as SortItem, Y as UrlLimits, Z as UrlListParams, _ as UrlListPayload, $ as createFilters, a0 as createRegistry, a1 as decodeSort, a2 as defineListSchema, a3 as encodeSort, a4 as readListParams, a5 as resetParams, a6 as schemaToFilter, a7 as searchParamsToPayload, a8 as setPage, a9 as setParam, aa as setSize, ab as setSort } from './registry-CEq4xFui.cjs';
|
|
3
3
|
import { SkippedCondition } from '@querykitjs/core';
|
|
4
4
|
export { f } from '@querykitjs/core';
|
|
5
5
|
|
|
@@ -122,5 +122,49 @@ type QueryKitErrorBody = Pick<SkippedCondition, "site" | "key" | "reason"> & Par
|
|
|
122
122
|
*/
|
|
123
123
|
declare function isQueryKitError(body: unknown): body is QueryKitErrorBody;
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
interface ListStateOptions<A extends AdapterName> {
|
|
126
|
+
/** URL↔filter schema ({@link defineListSchema} / `resource.schema`). */
|
|
127
|
+
schema: ListSchema;
|
|
128
|
+
/** URL param names (page/size/sortType) — optional. */
|
|
129
|
+
url?: UrlConfig;
|
|
130
|
+
/** Fixed relations to load on every request (not URL-driven). */
|
|
131
|
+
with?: WithFor<A>;
|
|
132
|
+
}
|
|
133
|
+
interface ListStateRead {
|
|
134
|
+
/** Ready-to-send list payload (built from the URL via the resource's defaults). */
|
|
135
|
+
params: ListPayload;
|
|
136
|
+
/** The URL's page or sort was past the limits and was clamped (`?page=9999` → the last allowed page). */
|
|
137
|
+
clamped: boolean;
|
|
138
|
+
}
|
|
139
|
+
/** URL setters: each returns the NEXT search params and never mutates the given ones. */
|
|
140
|
+
interface ListStateActions {
|
|
141
|
+
/** Set/clear a filter param (resets `page`). */
|
|
142
|
+
setParam: (name: string, value: string | null | undefined) => URLSearchParams;
|
|
143
|
+
setPage: (page: number) => URLSearchParams;
|
|
144
|
+
/** Resets `page`. */
|
|
145
|
+
setSize: (size: number) => URLSearchParams;
|
|
146
|
+
/** Resets `page`; an empty sort clears the param. */
|
|
147
|
+
setSort: (sort: SortInput) => URLSearchParams;
|
|
148
|
+
/** Clears every param except `keep`. */
|
|
149
|
+
reset: (keep?: string[]) => URLSearchParams;
|
|
150
|
+
}
|
|
151
|
+
interface ListState {
|
|
152
|
+
read: (searchParams: URLSearchParams) => ListStateRead;
|
|
153
|
+
actions: (searchParams: URLSearchParams) => ListStateActions;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Framework-free list URL state — the logic behind `useListParams` in `@querykitjs/web/react`
|
|
157
|
+
* and `@querykitjs/web/vue`, for any other framework (Svelte, Solid, vanilla). Pure: it reads
|
|
158
|
+
* search params and returns the next ones; navigating is the caller's job.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* const list = createListState(users, { schema: usersSchema });
|
|
163
|
+
* const { params, clamped } = list.read(new URLSearchParams(location.search));
|
|
164
|
+
* history.pushState(null, "", `?${list.actions(new URLSearchParams(location.search)).setPage(2)}`);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
declare function createListState<T, A extends AdapterName>(resource: Resource<T, A>, options: ListStateOptions<A>): ListState;
|
|
168
|
+
|
|
169
|
+
export { AdapterName, CursorParams, CursorPayload, FieldCondition, Filter, FilterNode, InfiniteParams, InfinitePayload, ListParams, ListPayload, ListSchema, Params, QueryPayload, Resource, Sort, SortInput, UrlConfig, WithFor, buildCursorParams, buildInfiniteParams, buildListParams, buildParams, createListState, createQuery, isQueryKitError, normalizeFilter, normalizeSort };
|
|
170
|
+
export type { ListState, ListStateActions, ListStateOptions, ListStateRead, QueryConfig, QueryKitErrorBody };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { b as Sort, C as CursorParams, c as CursorPayload, I as InfiniteParams, d as InfinitePayload, e as ListParams, a as ListPayload, P as Params, Q as QueryPayload, F as Filter, f as FieldCondition, g as FilterNode, S as SortInput, A as AdapterName, L as ListSchema, U as UrlConfig, W as WithFor, R as Resource } from './registry-CEq4xFui.js';
|
|
2
|
+
export { h as AndGroup, i as CursorMeta, j as CursorResult, D as DrizzleWith, k as FieldDescriptor, l as FieldKey, m as FilterOperator, n as FilterScalar, o as FilterValue, p as InfiniteMeta, q as InfiniteResult, r as ListResult, M as Meta, s as MongoosePopulate, N as NotGroup, O as OrGroup, t as PrismaInclude, u as RawCursorMeta, v as RawInfiniteMeta, w as RawMeta, x as Registry, y as RegistryConfig, z as RegistryDefaults, B as RegistryTimestamps, E as ResourceCursorParams, G as ResourceInfiniteParams, H as ResourceKeys, J as ResourceListParams, K as ResourceParams, T as SearchOptions, V as SortDirection, X as SortItem, Y as UrlLimits, Z as UrlListParams, _ as UrlListPayload, $ as createFilters, a0 as createRegistry, a1 as decodeSort, a2 as defineListSchema, a3 as encodeSort, a4 as readListParams, a5 as resetParams, a6 as schemaToFilter, a7 as searchParamsToPayload, a8 as setPage, a9 as setParam, aa as setSize, ab as setSort } from './registry-CEq4xFui.js';
|
|
3
3
|
import { SkippedCondition } from '@querykitjs/core';
|
|
4
4
|
export { f } from '@querykitjs/core';
|
|
5
5
|
|
|
@@ -122,5 +122,49 @@ type QueryKitErrorBody = Pick<SkippedCondition, "site" | "key" | "reason"> & Par
|
|
|
122
122
|
*/
|
|
123
123
|
declare function isQueryKitError(body: unknown): body is QueryKitErrorBody;
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
125
|
+
interface ListStateOptions<A extends AdapterName> {
|
|
126
|
+
/** URL↔filter schema ({@link defineListSchema} / `resource.schema`). */
|
|
127
|
+
schema: ListSchema;
|
|
128
|
+
/** URL param names (page/size/sortType) — optional. */
|
|
129
|
+
url?: UrlConfig;
|
|
130
|
+
/** Fixed relations to load on every request (not URL-driven). */
|
|
131
|
+
with?: WithFor<A>;
|
|
132
|
+
}
|
|
133
|
+
interface ListStateRead {
|
|
134
|
+
/** Ready-to-send list payload (built from the URL via the resource's defaults). */
|
|
135
|
+
params: ListPayload;
|
|
136
|
+
/** The URL's page or sort was past the limits and was clamped (`?page=9999` → the last allowed page). */
|
|
137
|
+
clamped: boolean;
|
|
138
|
+
}
|
|
139
|
+
/** URL setters: each returns the NEXT search params and never mutates the given ones. */
|
|
140
|
+
interface ListStateActions {
|
|
141
|
+
/** Set/clear a filter param (resets `page`). */
|
|
142
|
+
setParam: (name: string, value: string | null | undefined) => URLSearchParams;
|
|
143
|
+
setPage: (page: number) => URLSearchParams;
|
|
144
|
+
/** Resets `page`. */
|
|
145
|
+
setSize: (size: number) => URLSearchParams;
|
|
146
|
+
/** Resets `page`; an empty sort clears the param. */
|
|
147
|
+
setSort: (sort: SortInput) => URLSearchParams;
|
|
148
|
+
/** Clears every param except `keep`. */
|
|
149
|
+
reset: (keep?: string[]) => URLSearchParams;
|
|
150
|
+
}
|
|
151
|
+
interface ListState {
|
|
152
|
+
read: (searchParams: URLSearchParams) => ListStateRead;
|
|
153
|
+
actions: (searchParams: URLSearchParams) => ListStateActions;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Framework-free list URL state — the logic behind `useListParams` in `@querykitjs/web/react`
|
|
157
|
+
* and `@querykitjs/web/vue`, for any other framework (Svelte, Solid, vanilla). Pure: it reads
|
|
158
|
+
* search params and returns the next ones; navigating is the caller's job.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* const list = createListState(users, { schema: usersSchema });
|
|
163
|
+
* const { params, clamped } = list.read(new URLSearchParams(location.search));
|
|
164
|
+
* history.pushState(null, "", `?${list.actions(new URLSearchParams(location.search)).setPage(2)}`);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
declare function createListState<T, A extends AdapterName>(resource: Resource<T, A>, options: ListStateOptions<A>): ListState;
|
|
168
|
+
|
|
169
|
+
export { AdapterName, CursorParams, CursorPayload, FieldCondition, Filter, FilterNode, InfiniteParams, InfinitePayload, ListParams, ListPayload, ListSchema, Params, QueryPayload, Resource, Sort, SortInput, UrlConfig, WithFor, buildCursorParams, buildInfiniteParams, buildListParams, buildParams, createListState, createQuery, isQueryKitError, normalizeFilter, normalizeSort };
|
|
170
|
+
export type { ListState, ListStateActions, ListStateOptions, ListStateRead, QueryConfig, QueryKitErrorBody };
|