@querykitjs/core 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,75 +1,5 @@
1
- /**
2
- * Filter operatorlari — yagona runtime manba. `FilterOperator` tipi (`types.ts`)
3
- * shundan chiqadi; `@querykitjs/zod` shu massivdan zod enum quradi.
4
- */
5
- declare const FILTER_OPERATORS: readonly ["=", "!=", ">", ">=", "<", "<=", "eq", "ne", "gt", "gte", "lt", "lte", "like", "ilike", "notLike", "contains", "startsWith", "endsWith", "%_%", "%_", "_%", "in", "notIn", "between", "notBetween", "isNull", "isNotNull"];
6
-
7
- /**
8
- * `@querykitjs/core` — ORM-agnostik query DSL tiplari. Backend adapterlar
9
- * (`@querykitjs/drizzle-pg`) va frontend (`@querykitjs/web`) shu bir xil kontraktga
10
- * tayanadi. Tiplar ustun-kaliti (`TKey`) bo'yicha generic; adapterlar uni o'z
11
- * kalit tipiga (Drizzle jadval ustuni yoki entity maydoni) ixtisoslashtiradi.
12
- */
13
-
14
- /** Qo'llab-quvvatlanadigan filter operatorlari (token va nom aliaslari). */
15
- type FilterOperator = (typeof FILTER_OPERATORS)[number];
16
- type FilterScalar = string | number | boolean | Date | null;
17
- type FilterValue = FilterScalar | FilterScalar[];
18
- /** Bitta maydon sharti (`operation` default `"="`). */
19
- interface FieldCondition<TKey extends string = string> {
20
- key: TKey;
21
- operation?: FilterOperator;
22
- value?: FilterValue;
23
- }
24
- interface AndGroup<TKey extends string = string, TRaw = never> {
25
- and: FilterNode<TKey, TRaw>[];
26
- }
27
- interface OrGroup<TKey extends string = string, TRaw = never> {
28
- or: FilterNode<TKey, TRaw>[];
29
- }
30
- interface NotGroup<TKey extends string = string, TRaw = never> {
31
- not: FilterNode<TKey, TRaw>;
32
- }
33
- /**
34
- * Filter daraxti tuguni: maydon sharti, mantiqiy guruh, yoki adapter qo'shadigan
35
- * raw escape-hatch (`TRaw`, masalan Drizzle `SQL`; default `never`).
36
- */
37
- type FilterNode<TKey extends string = string, TRaw = never> = FieldCondition<TKey> | AndGroup<TKey, TRaw> | OrGroup<TKey, TRaw> | NotGroup<TKey, TRaw> | TRaw;
38
- /** Public filter: daraxt/tugun yoki flat massiv (implicit AND). */
39
- type Filter<TKey extends string = string, TRaw = never> = FilterNode<TKey, TRaw> | FieldCondition<TKey>[];
40
- type SortDirection = "asc" | "desc";
41
- /** One sort field — `{ key, direction }`. */
42
- interface SortItem<TKey extends string = string> {
43
- key: TKey;
44
- direction?: SortDirection;
45
- }
46
- /** Sort is **always an array** of {@link SortItem} (multi-field capable). */
47
- type Sort<TKey extends string = string> = SortItem<TKey>[];
48
- /** Offset (sahifali) paginatsiya meta'si. */
49
- interface OffsetMeta {
50
- total_items: number;
51
- total_pages: number;
52
- current_page: number;
53
- per_page: number;
54
- has_next: boolean;
55
- has_prev: boolean;
56
- }
57
- /** Infinite-scroll paginatsiya meta'si. */
58
- interface InfiniteMeta {
59
- limit: number;
60
- offset: number;
61
- count: number;
62
- has_more: boolean;
63
- next_offset: number | null;
64
- }
65
- /** Cursor (keyset) paginatsiya meta'si. */
66
- interface CursorMeta {
67
- limit: number;
68
- has_next: boolean;
69
- has_prev: boolean;
70
- next_cursor: string | null;
71
- prev_cursor: string | null;
72
- }
1
+ import { F as FilterValue, a as FieldCondition, b as FilterScalar, c as FilterNode, A as AndGroup, O as OrGroup, N as NotGroup, S as SkippedCondition } from './raw-Bx8c-TrC.js';
2
+ export { d as AggregateSpec, e as AllRows, C as CursorMeta, D as DEFAULT_LIMIT, f as DEFAULT_MAX_CONDITIONS, g as DEFAULT_MAX_FILTER_DEPTH, h as DEFAULT_MAX_IN_ITEMS, i as DEFAULT_MAX_LIKE_WILDCARDS, j as DEFAULT_MAX_LIMIT, k as DEFAULT_MAX_OFFSET, l as DEFAULT_MAX_PER_PAGE, m as DEFAULT_MAX_SORT_FIELDS, n as DEFAULT_MAX_STRING_LENGTH, o as DEFAULT_PER_PAGE, p as DEFAULT_QUERY_LIMITS, q as FILTER_OPERATORS, r as Filter, s as FilterOperator, t as Filterable, I as InfiniteMeta, L as LooseKey, M as MutationCount, u as MutationOptions, v as MutationRows, w as OffsetMeta, Q as QueryLimits, R as RelationRule, x as Relations, y as Scope, z as ScopeIn, B as SkipReason, E as SkipSite, G as Sort, H as SortDirection, J as SortItem, T as TEXT_FILTER_OPERATORS, U as UpsertOptions, W as WireBaseParams, K as WireCursorParams, P as WireInfiniteParams, V as WireOffsetParams, X as raw, Y as resolveLimits } from './raw-Bx8c-TrC.js';
73
3
 
74
4
  /**
75
5
  * Filter shartlarini tipli, ergonomik quruvchilar to'plamini qaytaradi. Kalit
@@ -100,6 +30,7 @@ declare function createFilters<TKey extends string = string, TRaw = never>(): {
100
30
  in: (key: TKey, value: Array<string | number>) => FieldCondition<TKey>;
101
31
  notIn: (key: TKey, value: Array<string | number>) => FieldCondition<TKey>;
102
32
  between: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => FieldCondition<TKey>;
33
+ notBetween: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => FieldCondition<TKey>;
103
34
  /** Diapazon — ikkita shart (`>=` va `<=`) massivi (flat filterga spread qilinadi). */
104
35
  range: (key: TKey, from: FilterScalar | Date, to: FilterScalar | Date) => FieldCondition<TKey>[];
105
36
  isNull: (key: TKey) => FieldCondition<TKey>;
@@ -125,6 +56,7 @@ declare const f: {
125
56
  in: (key: string, value: Array<string | number>) => FieldCondition<string>;
126
57
  notIn: (key: string, value: Array<string | number>) => FieldCondition<string>;
127
58
  between: (key: string, min: FilterScalar | Date, max: FilterScalar | Date) => FieldCondition<string>;
59
+ notBetween: (key: string, min: FilterScalar | Date, max: FilterScalar | Date) => FieldCondition<string>;
128
60
  /** Diapazon — ikkita shart (`>=` va `<=`) massivi (flat filterga spread qilinadi). */
129
61
  range: (key: string, from: FilterScalar | Date, to: FilterScalar | Date) => FieldCondition<string>[];
130
62
  isNull: (key: string) => FieldCondition<string>;
@@ -135,13 +67,50 @@ declare const f: {
135
67
  };
136
68
 
137
69
  /**
138
- * Umumiy pagination default'lari — yagona manba. Backend adapter (`createRegistry`
139
- * options) va frontend (`createQuery` config) shu qiymatlarni fallback sifatida
140
- * ishlatadi, shuning uchun ular hech qachon bir-biridan farq qilmaydi.
70
+ * querykit xatolari. Backend adapterlari (`drizzle-pg`, `mongoose`) `strict`
71
+ * rejimda shu bitta klassni tashlaydi — ya'ni ikkala backend uchun xatoni
72
+ * ushlash usuli bir xil.
141
73
  */
142
- /** Offset (list) sahifa o'lchami default'i. */
143
- declare const DEFAULT_PER_PAGE = 20;
144
- /** Infinite/cursor `limit` default'i. */
145
- declare const DEFAULT_LIMIT = 20;
146
74
 
147
- export { type AndGroup, type CursorMeta, DEFAULT_LIMIT, DEFAULT_PER_PAGE, FILTER_OPERATORS, type FieldCondition, type Filter, type FilterNode, type FilterOperator, type FilterScalar, type FilterValue, type InfiniteMeta, type NotGroup, type OffsetMeta, type OrGroup, type Sort, type SortDirection, type SortItem, createFilters, f };
75
+ /**
76
+ * `strict` rejimda noto'g'ri so'rov shartida tashlanadi (noma'lum kalit yoki
77
+ * operatorga mos kelmagan qiymat). Backend'da 400 qilib qaytarish uchun:
78
+ *
79
+ * ```ts
80
+ * try {
81
+ * return await usersRepository.findList(params);
82
+ * } catch (err) {
83
+ * if (err instanceof QueryKitError) return c.json({ error: err.message }, 400);
84
+ * throw err;
85
+ * }
86
+ * ```
87
+ */
88
+ declare class QueryKitError extends Error {
89
+ /** Barqaror kod — `instanceof` ishlamaydigan chegaralarda (RPC, worker) tekshirish uchun. */
90
+ readonly code = "QUERYKIT_INVALID_CONDITION";
91
+ /** Tashlab yuborilgan shart haqida to'liq ma'lumot (hook argumenti bilan bir xil shakl). */
92
+ readonly info: SkippedCondition;
93
+ constructor(info: SkippedCondition);
94
+ }
95
+ /**
96
+ * A read ran past its time limit (`maxTimeMS` on MongoDB). Kept apart from
97
+ * {@link QueryKitError}: the request was valid, the database was slow — map it to
98
+ * 503 / 504, not 400.
99
+ */
100
+ declare class QueryKitTimeoutError extends Error {
101
+ /** Collection / model name. */
102
+ readonly source: string;
103
+ /** The limit that was hit, in milliseconds. */
104
+ readonly maxTimeMS: number;
105
+ /** Stable code for boundaries where `instanceof` does not work. */
106
+ readonly code = "QUERYKIT_TIMEOUT";
107
+ constructor(
108
+ /** Collection / model name. */
109
+ source: string,
110
+ /** The limit that was hit, in milliseconds. */
111
+ maxTimeMS: number, options?: {
112
+ cause?: unknown;
113
+ });
114
+ }
115
+
116
+ export { AndGroup, FieldCondition, FilterNode, FilterScalar, FilterValue, NotGroup, OrGroup, QueryKitError, QueryKitTimeoutError, SkippedCondition, createFilters, f };
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ export { DEFAULT_LIMIT, DEFAULT_MAX_CONDITIONS, DEFAULT_MAX_FILTER_DEPTH, DEFAULT_MAX_IN_ITEMS, DEFAULT_MAX_LIKE_WILDCARDS, DEFAULT_MAX_LIMIT, DEFAULT_MAX_OFFSET, DEFAULT_MAX_PER_PAGE, DEFAULT_MAX_SORT_FIELDS, DEFAULT_MAX_STRING_LENGTH, DEFAULT_PER_PAGE, DEFAULT_QUERY_LIMITS, QueryKitError, QueryKitTimeoutError, raw, resolveLimits } from './chunk-NHNDPIPM.js';
2
+
1
3
  // src/filters.ts
2
4
  function field(key, operation, value) {
3
5
  return { key, operation, value };
@@ -19,6 +21,7 @@ function createFilters() {
19
21
  in: (key, value) => field(key, "in", value),
20
22
  notIn: (key, value) => field(key, "notIn", value),
21
23
  between: (key, min, max) => field(key, "between", [min, max]),
24
+ notBetween: (key, min, max) => field(key, "notBetween", [min, max]),
22
25
  /** Diapazon — ikkita shart (`>=` va `<=`) massivi (flat filterga spread qilinadi). */
23
26
  range: (key, from, to) => [
24
27
  field(key, ">=", from),
@@ -31,11 +34,7 @@ function createFilters() {
31
34
  not: (node) => ({ not: node })
32
35
  };
33
36
  }
34
- var f = createFilters();
35
-
36
- // src/defaults.ts
37
- var DEFAULT_PER_PAGE = 20;
38
- var DEFAULT_LIMIT = 20;
37
+ var f = /* @__PURE__ */ createFilters();
39
38
 
40
39
  // src/operators.ts
41
40
  var FILTER_OPERATORS = [
@@ -69,8 +68,18 @@ var FILTER_OPERATORS = [
69
68
  "notBetween",
70
69
  "isNull",
71
70
  "isNotNull"
71
+ ], TEXT_FILTER_OPERATORS = [
72
+ "like",
73
+ "ilike",
74
+ "notLike",
75
+ "contains",
76
+ "startsWith",
77
+ "endsWith",
78
+ "%_%",
79
+ "%_",
80
+ "_%"
72
81
  ];
73
82
 
74
- export { DEFAULT_LIMIT, DEFAULT_PER_PAGE, FILTER_OPERATORS, createFilters, f };
83
+ export { FILTER_OPERATORS, TEXT_FILTER_OPERATORS, createFilters, f };
75
84
  //# sourceMappingURL=index.js.map
76
85
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/filters.ts","../src/defaults.ts","../src/operators.ts"],"names":[],"mappings":";AAEA,SAAS,KAAA,CAA2B,GAAA,EAAW,SAAA,EAA2B,KAAA,EAA2C;AACnH,EAAA,OAAO,EAAE,GAAA,EAAK,SAAA,EAAW,KAAA,EAAM;AACjC;AAeO,SAAS,aAAA,GAA4D;AAG1E,EAAA,OAAO;AAAA,IACL,IAAI,CAAC,GAAA,EAAW,UAAuB,KAAA,CAAM,GAAA,EAAK,KAAK,KAAK,CAAA;AAAA,IAC5D,IAAI,CAAC,GAAA,EAAW,UAAuB,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IAC7D,IAAI,CAAC,GAAA,EAAW,UAAuB,KAAA,CAAM,GAAA,EAAK,KAAK,KAAK,CAAA;AAAA,IAC5D,KAAK,CAAC,GAAA,EAAW,UAAuB,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IAC9D,IAAI,CAAC,GAAA,EAAW,UAAuB,KAAA,CAAM,GAAA,EAAK,KAAK,KAAK,CAAA;AAAA,IAC5D,KAAK,CAAC,GAAA,EAAW,UAAuB,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IAE9D,UAAU,CAAC,GAAA,EAAW,UAAkB,KAAA,CAAM,GAAA,EAAK,OAAO,KAAK,CAAA;AAAA,IAC/D,YAAY,CAAC,GAAA,EAAW,UAAkB,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IAChE,UAAU,CAAC,GAAA,EAAW,UAAkB,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IAC9D,MAAM,CAAC,GAAA,EAAW,UAAkB,KAAA,CAAM,GAAA,EAAK,QAAQ,KAAK,CAAA;AAAA,IAC5D,OAAO,CAAC,GAAA,EAAW,UAAkB,KAAA,CAAM,GAAA,EAAK,SAAS,KAAK,CAAA;AAAA,IAC9D,SAAS,CAAC,GAAA,EAAW,UAAkB,KAAA,CAAM,GAAA,EAAK,WAAW,KAAK,CAAA;AAAA,IAElE,IAAI,CAAC,GAAA,EAAW,UAAkC,KAAA,CAAM,GAAA,EAAK,MAAM,KAAK,CAAA;AAAA,IACxE,OAAO,CAAC,GAAA,EAAW,UAAkC,KAAA,CAAM,GAAA,EAAK,SAAS,KAAK,CAAA;AAAA,IAC9E,OAAA,EAAS,CAAC,GAAA,EAAW,GAAA,EAA0B,GAAA,KAA6B,KAAA,CAAM,GAAA,EAAK,SAAA,EAAW,CAAC,GAAA,EAAK,GAAG,CAAgB,CAAA;AAAA;AAAA,IAE3H,KAAA,EAAO,CAAC,GAAA,EAAW,IAAA,EAA2B,EAAA,KAAoD;AAAA,MAChG,KAAA,CAAM,GAAA,EAAK,IAAA,EAAM,IAAmB,CAAA;AAAA,MACpC,KAAA,CAAM,GAAA,EAAK,IAAA,EAAM,EAAiB;AAAA,KACpC;AAAA,IAEA,MAAA,EAAQ,CAAC,GAAA,KAAc,KAAA,CAAM,KAAK,QAAQ,CAAA;AAAA,IAC1C,SAAA,EAAW,CAAC,GAAA,KAAc,KAAA,CAAM,KAAK,WAAW,CAAA;AAAA,IAEhD,GAAA,EAAK,CAAA,GAAI,KAAA,MAAyC,EAAE,KAAK,KAAA,EAAM,CAAA;AAAA,IAC/D,EAAA,EAAI,CAAA,GAAI,KAAA,MAAwC,EAAE,IAAI,KAAA,EAAM,CAAA;AAAA,IAC5D,GAAA,EAAK,CAAC,IAAA,MAAsC,EAAE,KAAK,IAAA,EAAK;AAAA,GAC1D;AACF;AAGO,IAAM,IAAI,aAAA;;;ACjDV,IAAM,gBAAA,GAAmB;AAGzB,IAAM,aAAA,GAAgB;;;ACNtB,IAAM,gBAAA,GAAmB;AAAA,EAC9B,GAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA;AAAA,EACA,IAAA;AAAA;AAAA,EACA,IAAA;AAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF","file":"index.js","sourcesContent":["import type { AndGroup, FieldCondition, FilterNode, FilterOperator, FilterScalar, FilterValue, NotGroup, OrGroup } from \"./types\";\n\nfunction field<TKey extends string>(key: TKey, operation: FilterOperator, value?: FilterValue): FieldCondition<TKey> {\n return { key, operation, value };\n}\n\n/**\n * Filter shartlarini tipli, ergonomik quruvchilar to'plamini qaytaradi. Kalit\n * tipiga (`TKey`) bog'lanadi; adapterlar uni o'z ustun/maydon kaliti bilan\n * chaqiradi. `TRaw` — guruhlarga (`and/or/not`) qo'shsa bo'ladigan raw tugun tipi.\n *\n * @typeParam TKey - ustun/maydon kaliti (string union).\n * @typeParam TRaw - raw escape-hatch tugun tipi (masalan Drizzle `SQL`).\n * @example\n * ```ts\n * const f = createFilters<\"status\" | \"age\">();\n * f.and(f.eq(\"status\", \"active\"), f.gte(\"age\", 18));\n * ```\n */\nexport function createFilters<TKey extends string = string, TRaw = never>() {\n type Node = FilterNode<TKey, TRaw>;\n\n return {\n eq: (key: TKey, value: FilterValue) => field(key, \"=\", value),\n ne: (key: TKey, value: FilterValue) => field(key, \"!=\", value),\n gt: (key: TKey, value: FilterValue) => field(key, \">\", value),\n gte: (key: TKey, value: FilterValue) => field(key, \">=\", value),\n lt: (key: TKey, value: FilterValue) => field(key, \"<\", value),\n lte: (key: TKey, value: FilterValue) => field(key, \"<=\", value),\n\n contains: (key: TKey, value: string) => field(key, \"%_%\", value),\n startsWith: (key: TKey, value: string) => field(key, \"%_\", value),\n endsWith: (key: TKey, value: string) => field(key, \"_%\", value),\n like: (key: TKey, value: string) => field(key, \"like\", value),\n ilike: (key: TKey, value: string) => field(key, \"ilike\", value),\n notLike: (key: TKey, value: string) => field(key, \"notLike\", value),\n\n in: (key: TKey, value: Array<string | number>) => field(key, \"in\", value),\n notIn: (key: TKey, value: Array<string | number>) => field(key, \"notIn\", value),\n between: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => field(key, \"between\", [min, max] as FilterValue),\n /** Diapazon — ikkita shart (`>=` va `<=`) massivi (flat filterga spread qilinadi). */\n range: (key: TKey, from: FilterScalar | Date, to: FilterScalar | Date): FieldCondition<TKey>[] => [\n field(key, \">=\", from as FilterValue),\n field(key, \"<=\", to as FilterValue),\n ],\n\n isNull: (key: TKey) => field(key, \"isNull\"),\n isNotNull: (key: TKey) => field(key, \"isNotNull\"),\n\n and: (...nodes: Node[]): AndGroup<TKey, TRaw> => ({ and: nodes }),\n or: (...nodes: Node[]): OrGroup<TKey, TRaw> => ({ or: nodes }),\n not: (node: Node): NotGroup<TKey, TRaw> => ({ not: node }),\n };\n}\n\n/** Tipsiz (kalitga bog'lanmagan) filter quruvchilar — tez foydalanish uchun. */\nexport const f = createFilters();\n","/**\n * Umumiy pagination default'lari — yagona manba. Backend adapter (`createRegistry`\n * options) va frontend (`createQuery` config) shu qiymatlarni fallback sifatida\n * ishlatadi, shuning uchun ular hech qachon bir-biridan farq qilmaydi.\n */\n\n/** Offset (list) sahifa o'lchami default'i. */\nexport const DEFAULT_PER_PAGE = 20;\n\n/** Infinite/cursor `limit` default'i. */\nexport const DEFAULT_LIMIT = 20;\n","/**\n * Filter operatorlari — yagona runtime manba. `FilterOperator` tipi (`types.ts`)\n * shundan chiqadi; `@querykitjs/zod` shu massivdan zod enum quradi.\n */\nexport const FILTER_OPERATORS = [\n \"=\",\n \"!=\",\n \">\",\n \">=\",\n \"<\",\n \"<=\",\n \"eq\",\n \"ne\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"like\",\n \"ilike\",\n \"notLike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"%_%\", // contains\n \"%_\", // startsWith\n \"_%\", // endsWith\n \"in\",\n \"notIn\",\n \"between\",\n \"notBetween\",\n \"isNull\",\n \"isNotNull\",\n] as const;\n"]}
1
+ {"version":3,"sources":["../src/filters.ts","../src/operators.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { AndGroup, FieldCondition, FilterNode, FilterOperator, FilterScalar, FilterValue, NotGroup, OrGroup } from \"./types\";\n\nfunction field<TKey extends string>(key: TKey, operation: FilterOperator, value?: FilterValue): FieldCondition<TKey> {\n return { key, operation, value };\n}\n\n/**\n * Filter shartlarini tipli, ergonomik quruvchilar to'plamini qaytaradi. Kalit\n * tipiga (`TKey`) bog'lanadi; adapterlar uni o'z ustun/maydon kaliti bilan\n * chaqiradi. `TRaw` — guruhlarga (`and/or/not`) qo'shsa bo'ladigan raw tugun tipi.\n *\n * @typeParam TKey - ustun/maydon kaliti (string union).\n * @typeParam TRaw - raw escape-hatch tugun tipi (masalan Drizzle `SQL`).\n * @example\n * ```ts\n * const f = createFilters<\"status\" | \"age\">();\n * f.and(f.eq(\"status\", \"active\"), f.gte(\"age\", 18));\n * ```\n */\nexport function createFilters<TKey extends string = string, TRaw = never>() {\n type Node = FilterNode<TKey, TRaw>;\n\n return {\n eq: (key: TKey, value: FilterValue) => field(key, \"=\", value),\n ne: (key: TKey, value: FilterValue) => field(key, \"!=\", value),\n gt: (key: TKey, value: FilterValue) => field(key, \">\", value),\n gte: (key: TKey, value: FilterValue) => field(key, \">=\", value),\n lt: (key: TKey, value: FilterValue) => field(key, \"<\", value),\n lte: (key: TKey, value: FilterValue) => field(key, \"<=\", value),\n\n contains: (key: TKey, value: string) => field(key, \"%_%\", value),\n startsWith: (key: TKey, value: string) => field(key, \"%_\", value),\n endsWith: (key: TKey, value: string) => field(key, \"_%\", value),\n like: (key: TKey, value: string) => field(key, \"like\", value),\n ilike: (key: TKey, value: string) => field(key, \"ilike\", value),\n notLike: (key: TKey, value: string) => field(key, \"notLike\", value),\n\n in: (key: TKey, value: Array<string | number>) => field(key, \"in\", value),\n notIn: (key: TKey, value: Array<string | number>) => field(key, \"notIn\", value),\n between: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => field(key, \"between\", [min, max] as FilterValue),\n notBetween: (key: TKey, min: FilterScalar | Date, max: FilterScalar | Date) => field(key, \"notBetween\", [min, max] as FilterValue),\n /** Diapazon — ikkita shart (`>=` va `<=`) massivi (flat filterga spread qilinadi). */\n range: (key: TKey, from: FilterScalar | Date, to: FilterScalar | Date): FieldCondition<TKey>[] => [\n field(key, \">=\", from as FilterValue),\n field(key, \"<=\", to as FilterValue),\n ],\n\n isNull: (key: TKey) => field(key, \"isNull\"),\n isNotNull: (key: TKey) => field(key, \"isNotNull\"),\n\n and: (...nodes: Node[]): AndGroup<TKey, TRaw> => ({ and: nodes }),\n or: (...nodes: Node[]): OrGroup<TKey, TRaw> => ({ or: nodes }),\n not: (node: Node): NotGroup<TKey, TRaw> => ({ not: node }),\n };\n}\n\n/** Tipsiz (kalitga bog'lanmagan) filter quruvchilar — tez foydalanish uchun. */\nexport const f = /* @__PURE__ */ createFilters();\n","/**\n * Filter operatorlari — yagona runtime manba. `FilterOperator` tipi (`types.ts`)\n * shundan chiqadi; `@querykitjs/zod` shu massivdan zod enum quradi.\n */\nexport const FILTER_OPERATORS = [\n \"=\",\n \"!=\",\n \">\",\n \">=\",\n \"<\",\n \"<=\",\n \"eq\",\n \"ne\",\n \"gt\",\n \"gte\",\n \"lt\",\n \"lte\",\n \"like\",\n \"ilike\",\n \"notLike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"%_%\", // contains\n \"%_\", // startsWith\n \"_%\", // endsWith\n \"in\",\n \"notIn\",\n \"between\",\n \"notBetween\",\n \"isNull\",\n \"isNotNull\",\n] as const;\n\n/**\n * Qiymati **text pattern** bo'lgan operatorlar. Backend adapterlari wire qiymatni\n * ustun/path tipiga cast qilishda shularni chetlab o'tadi — aks holda\n * `ilike(dateColumn, \"%2026%\")` ISO string o'rniga `String(Date)` olardi\n * (`\"Mon Jul 28 2026 …\"`). Ro'yxat ikki adapterda divergent bo'lmasligi uchun\n * shu yerda — yagona manba.\n */\nexport const TEXT_FILTER_OPERATORS = [\n \"like\",\n \"ilike\",\n \"notLike\",\n \"contains\",\n \"startsWith\",\n \"endsWith\",\n \"%_%\",\n \"%_\",\n \"_%\",\n] as const satisfies readonly (typeof FILTER_OPERATORS)[number][];\n"]}
@@ -0,0 +1,357 @@
1
+ 'use strict';
2
+
3
+ var chunkVD7XT52J_cjs = require('./chunk-VD7XT52J.cjs');
4
+
5
+ // src/internal/cursor.ts
6
+ function encodeCursor(value) {
7
+ let normalized = value instanceof Date ? value.toISOString() : value, json = JSON.stringify({ v: normalized });
8
+ return Buffer.from(json, "utf8").toString("base64url");
9
+ }
10
+ function decodeCursor(cursor) {
11
+ if (cursor)
12
+ try {
13
+ let json = Buffer.from(cursor, "base64url").toString("utf8");
14
+ return JSON.parse(json).v;
15
+ } catch {
16
+ return;
17
+ }
18
+ }
19
+ var isScalar = (value) => typeof value == "string" || typeof value == "boolean" || typeof value == "number" && Number.isFinite(value), scalarOf = (value) => {
20
+ let normalized = value instanceof Date ? value.toISOString() : typeof value == "object" && value !== null && typeof value.toJSON == "function" ? value.toJSON() : value;
21
+ return isScalar(normalized) ? normalized : void 0;
22
+ };
23
+ async function sign(body, secret) {
24
+ let encoder = new TextEncoder(), key = await crypto.subtle.importKey("raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]), signature = await crypto.subtle.sign("HMAC", key, encoder.encode(body));
25
+ return Buffer.from(signature).toString("base64url");
26
+ }
27
+ function sameSignature(a, b) {
28
+ if (a.length !== b.length) return false;
29
+ let diff = 0;
30
+ for (let index = 0; index < a.length; index++) diff |= a.charCodeAt(index) ^ b.charCodeAt(index);
31
+ return diff === 0;
32
+ }
33
+ async function encodeCursorToken(payload, secret) {
34
+ let body = JSON.stringify({ v: 2, k: scalarOf(payload.k) ?? null, id: scalarOf(payload.id) ?? null }), signed = secret ? JSON.stringify({ ...JSON.parse(body), s: await sign(body, secret) }) : body;
35
+ return Buffer.from(signed, "utf8").toString("base64url");
36
+ }
37
+ async function decodeCursorToken(token, options) {
38
+ if (!token) return;
39
+ let refuse = () => {
40
+ throw new chunkVD7XT52J_cjs.QueryKitError({ source: options.source, site: "cursorKey", key: options.key ?? "cursor", reason: "invalid-value" });
41
+ }, payload;
42
+ try {
43
+ payload = JSON.parse(Buffer.from(token, "base64url").toString("utf8"));
44
+ } catch {
45
+ return refuse();
46
+ }
47
+ if (typeof payload != "object" || payload === null || payload.v !== 2 || !isScalar(payload.k) || !isScalar(payload.id)) return refuse();
48
+ if (options.secret) {
49
+ let body = JSON.stringify({ v: 2, k: payload.k, id: payload.id });
50
+ if (typeof payload.s != "string" || !sameSignature(payload.s, await sign(body, options.secret))) return refuse();
51
+ }
52
+ return { k: payload.k, id: payload.id };
53
+ }
54
+
55
+ // src/internal/diagnostics.ts
56
+ function reportSkip(diag, info) {
57
+ if (!diag) return;
58
+ let full = { ...info, source: diag.source };
59
+ if (diag.strict) throw new chunkVD7XT52J_cjs.QueryKitError(full);
60
+ diag.onSkipped?.(full);
61
+ }
62
+
63
+ // src/internal/context.ts
64
+ function loadAsyncLocalStorage() {
65
+ let asyncHooks = typeof process < "u" && typeof process.getBuiltinModule == "function" ? process.getBuiltinModule("node:async_hooks") : void 0;
66
+ if (!asyncHooks?.AsyncLocalStorage)
67
+ throw new Error("querykit: the repository context needs node:async_hooks (Node >= 22.12 or Bun) \u2014 a querykit adapter cannot run in this runtime");
68
+ return asyncHooks.AsyncLocalStorage;
69
+ }
70
+ function createContextStore() {
71
+ let AsyncLocalStorage = loadAsyncLocalStorage(), als = new AsyncLocalStorage();
72
+ return {
73
+ get: () => als.getStore(),
74
+ run: (patch, fn) => als.run({ ...als.getStore(), ...patch }, fn)
75
+ };
76
+ }
77
+
78
+ // src/internal/sort.ts
79
+ function normalizeSort(sort, diag) {
80
+ if (!sort) return [];
81
+ let items = [];
82
+ for (let item of sort)
83
+ item && typeof item.key == "string" && item.key ? items.push({ key: item.key, direction: item.direction ?? "asc" }) : reportSkip(diag, { site: "sort", key: "", reason: "invalid-value" });
84
+ return items;
85
+ }
86
+
87
+ // src/internal/pagination.ts
88
+ function clampPageSize(requested, fallback, max) {
89
+ return Math.min(max, Math.max(1, Math.trunc(requested ?? fallback)));
90
+ }
91
+ function clampPage(requested) {
92
+ return Math.max(1, Math.trunc(requested ?? 1));
93
+ }
94
+ function clampOffset(requested) {
95
+ return Math.max(0, Math.trunc(requested ?? 0));
96
+ }
97
+ function offsetMeta(page, perPage, totalItems) {
98
+ let totalPages = Math.ceil(totalItems / perPage);
99
+ return {
100
+ total_items: totalItems,
101
+ total_pages: totalPages,
102
+ current_page: page,
103
+ per_page: perPage,
104
+ has_next: page < totalPages,
105
+ has_prev: page > 1
106
+ };
107
+ }
108
+ function offsetPageWithoutTotal(rows, page, perPage) {
109
+ let hasNext = rows.length > perPage;
110
+ return {
111
+ data: hasNext ? rows.slice(0, perPage) : [...rows],
112
+ meta: { total_items: null, total_pages: null, current_page: page, per_page: perPage, has_next: hasNext, has_prev: page > 1 }
113
+ };
114
+ }
115
+ function infinitePage(rows, limit, offset) {
116
+ let hasMore = rows.length > limit, data = hasMore ? rows.slice(0, limit) : [...rows];
117
+ return {
118
+ data,
119
+ meta: { limit, offset, count: data.length, has_more: hasMore, next_offset: hasMore ? offset + limit : null }
120
+ };
121
+ }
122
+ async function cursorPage(rows, options) {
123
+ let { limit, direction, hasCursor, cursorField, idField, secret } = options, hasExtra = rows.length > limit, data = hasExtra ? rows.slice(0, limit) : [...rows];
124
+ direction === "backward" && (data = data.reverse());
125
+ let first = data[0], last = data[data.length - 1], hasNext = direction === "forward" ? hasExtra : hasCursor, hasPrev = direction === "forward" ? hasCursor : hasExtra;
126
+ return {
127
+ data,
128
+ meta: {
129
+ limit,
130
+ has_next: hasNext,
131
+ has_prev: hasPrev,
132
+ next_cursor: hasNext && last ? await encodeCursorToken({ k: last[cursorField], id: last[idField] }, secret) : null,
133
+ prev_cursor: hasPrev && first ? await encodeCursorToken({ k: first[cursorField], id: first[idField] }, secret) : null
134
+ }
135
+ };
136
+ }
137
+
138
+ // src/internal/mutation.ts
139
+ var isPlainObject = (value) => typeof value == "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
140
+ function isAllRows(filter) {
141
+ return isPlainObject(filter) && filter.all === true && Object.keys(filter).length === 1;
142
+ }
143
+ function isEmptyFilter(filter) {
144
+ return filter == null || Array.isArray(filter) && filter.length === 0 || isPlainObject(filter) && Object.keys(filter).length === 0;
145
+ }
146
+ function refuseEmptyFilter(source, method) {
147
+ throw new chunkVD7XT52J_cjs.QueryKitError({ source, site: "mutation", key: method, reason: "empty-filter" });
148
+ }
149
+
150
+ // src/internal/scope.ts
151
+ var isPlainObject2 = (value) => typeof value == "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype, isInScope = (value) => isPlainObject2(value) && Object.keys(value).length === 1 && Array.isArray(value.in);
152
+ function scopeConditions(scope) {
153
+ return Object.entries(scope ?? {}).map(
154
+ ([key, value]) => isInScope(value) ? { key, operation: "in", value: [...value.in] } : { key, operation: "=", value }
155
+ );
156
+ }
157
+ function scopeDefaults(scope) {
158
+ return Object.fromEntries(Object.entries(scope ?? {}).filter(([, value]) => !isInScope(value)));
159
+ }
160
+
161
+ // src/internal/with.ts
162
+ var isPlainObject3 = (value) => typeof value == "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype, ruleOf = (relations, name) => {
163
+ let rule = relations && Object.prototype.hasOwnProperty.call(relations, name) ? relations[name] : void 0;
164
+ return isPlainObject3(rule) && (rule.columns === "*" || Array.isArray(rule.columns)) ? rule : void 0;
165
+ }, selectedKeys = (selection) => {
166
+ if (typeof selection == "string") return selection.split(/\s+/).filter(Boolean);
167
+ if (isPlainObject3(selection)) return Object.keys(selection).filter((key) => !!selection[key]);
168
+ };
169
+ function checkWith(withValue, relations, dialect, source, path = "") {
170
+ if (withValue == null) return;
171
+ let refuse = (key) => {
172
+ throw new chunkVD7XT52J_cjs.QueryKitError({ source, site: "with", key: path + key, reason: "forbidden-key" });
173
+ };
174
+ if (!isPlainObject3(withValue)) return refuse("with");
175
+ let checked = {};
176
+ for (let [name, value] of Object.entries(withValue)) {
177
+ if (value === false || value === void 0) continue;
178
+ let rule = ruleOf(relations, name) ?? refuse(name), listed = rule.columns === "*" ? void 0 : new Set(rule.columns), selectListed = () => Object.fromEntries([...listed].map((column) => [column, true]));
179
+ if (value === true) {
180
+ checked[name] = listed ? { [dialect.columns]: selectListed() } : true;
181
+ continue;
182
+ }
183
+ isPlainObject3(value) || refuse(name);
184
+ let options = value, out = {};
185
+ for (let [key, option] of Object.entries(options)) {
186
+ let at = `${name}.${key}`;
187
+ if (key === dialect.columns) {
188
+ let keys = selectedKeys(option) ?? refuse(at);
189
+ for (let column of keys) listed && (column.startsWith("-") || !listed.has(column)) && refuse(`${name}.${column}`);
190
+ out[key] = option;
191
+ } else if (key === dialect.nested)
192
+ out[key] = checkWith(option, rule.nested, dialect, source, `${name}.`);
193
+ else if (dialect.filters.includes(key))
194
+ checkFilterFields(option, rule, dialect, (field) => refuse(`${name}.${field}`)), out[key] = option;
195
+ else if (dialect.paging.includes(key))
196
+ out[key] = option;
197
+ else if (key === dialect.orderBy) {
198
+ for (let item of Array.isArray(option) ? option : [option])
199
+ for (let column of selectedKeys(item) ?? refuse(at)) listed && !listed.has(column) && refuse(`${name}.${column}`);
200
+ out[key] = option;
201
+ } else if (key === dialect.options) {
202
+ for (let sub of Object.keys(isPlainObject3(option) ? option : refuse(at))) dialect.paging.includes(sub) || refuse(`${at}.${sub}`);
203
+ out[key] = option;
204
+ } else
205
+ refuse(at);
206
+ }
207
+ listed && out[dialect.columns] === void 0 && (out[dialect.columns] = selectListed()), checked[name] = out;
208
+ }
209
+ return checked;
210
+ }
211
+ function checkFilterFields(filter, rule, dialect, refuse) {
212
+ isPlainObject3(filter) || refuse("filter");
213
+ for (let [key, value] of Object.entries(filter))
214
+ if (dialect.logical.includes(key))
215
+ for (let part of Array.isArray(value) ? value : [value]) checkFilterFields(part, rule, dialect, refuse);
216
+ else (key.startsWith("$") || !rule.filterable || rule.filterable[key] === void 0) && refuse(key);
217
+ }
218
+
219
+ // src/internal/limits.ts
220
+ var isRecord = (value) => typeof value == "object" && value !== null && !Array.isArray(value), formatLimit = (limit, max) => `${limit} (${max})`;
221
+ function findFilterLimitViolation(filter, limits) {
222
+ let hit = (limit, path) => ({ limit, max: limits[limit], path }), pending = [], push = (children, depth, path) => {
223
+ for (let index = children.length - 1; index >= 0; index--) pending.push([children[index], depth, [...path, index]]);
224
+ };
225
+ Array.isArray(filter) ? push(filter, 1, []) : filter !== void 0 && pending.push([filter, 1, []]);
226
+ let conditions = 0;
227
+ for (let next = pending.pop(); next; next = pending.pop()) {
228
+ let [node, depth, path] = next;
229
+ if (depth > limits.maxDepth) return hit("maxDepth", path);
230
+ if (!isRecord(node)) continue;
231
+ if ("key" in node) {
232
+ if (++conditions > limits.maxConditions) return hit("maxConditions", path);
233
+ let { value } = node, valuePath = [...path, "value"];
234
+ if (Array.isArray(value) && value.length > limits.maxInItems) return hit("maxInItems", valuePath);
235
+ let tooLong = (Array.isArray(value) ? value : [value]).findIndex((item) => typeof item == "string" && item.length > limits.maxStringLength);
236
+ if (tooLong >= 0) return hit("maxStringLength", Array.isArray(value) ? [...valuePath, tooLong] : valuePath);
237
+ continue;
238
+ }
239
+ let group = "and" in node ? "and" : "or" in node ? "or" : void 0;
240
+ if (group) {
241
+ let children = node[group];
242
+ Array.isArray(children) && push(children, depth + 1, [...path, group]);
243
+ } else "not" in node && pending.push([node.not, depth + 1, [...path, "not"]]);
244
+ }
245
+ }
246
+ var LIKE_OPERATORS = /* @__PURE__ */ new Set(["like", "ilike", "notLike"]), isLikeOperator = (operation) => LIKE_OPERATORS.has(operation);
247
+ function likeWildcards(pattern) {
248
+ let count = 0, previous = "";
249
+ for (let index = 0; index < pattern.length; index++) {
250
+ let char = pattern[index];
251
+ if (char === "\\") {
252
+ index++, previous = "";
253
+ continue;
254
+ }
255
+ (char === "_" || char === "%" && previous !== "%") && count++, previous = char;
256
+ }
257
+ return count;
258
+ }
259
+ var offsetOf = (page, perPage) => ((page ?? 1) - 1) * (perPage ?? 20);
260
+
261
+ // src/internal/policy.ts
262
+ var DEFAULT_OPERATORS = ["=", "in"], OPERATOR_TOKEN = {
263
+ eq: "=",
264
+ ne: "!=",
265
+ gt: ">",
266
+ gte: ">=",
267
+ lt: "<",
268
+ lte: "<=",
269
+ contains: "%_%",
270
+ startsWith: "%_",
271
+ endsWith: "_%"
272
+ }, tokenOf = (operation) => OPERATOR_TOKEN[operation] ?? operation, isRecord2 = (value) => typeof value == "object" && value !== null && !Array.isArray(value);
273
+ function filterRules(options, canonical) {
274
+ let rules = /* @__PURE__ */ new Map();
275
+ if (options.filterable) {
276
+ for (let [key, operators] of Object.entries(options.filterable))
277
+ operators && rules.set(canonical(key), operators === "*" ? "*" : new Set(operators.map(tokenOf)));
278
+ return rules;
279
+ }
280
+ let fields = options.allowedColumns ?? (options.forcedColumns ? Object.keys(options.forcedColumns).filter((key) => options.forcedColumns[key]) : [options.primaryKey]), equality = new Set(DEFAULT_OPERATORS);
281
+ for (let field of fields) rules.set(canonical(field), equality);
282
+ return rules;
283
+ }
284
+ function resolvePolicy(options) {
285
+ let limits = chunkVD7XT52J_cjs.resolveLimits(options.limits), canonical = (key) => options.fieldOf(key) ?? key, rules = filterRules(options, canonical), sortable = new Set((options.sortable ?? [options.primaryKey, ...options.createdAt ? [options.createdAt] : []]).map(canonical)), refuse = (site, key, reason, operation) => {
286
+ throw new chunkVD7XT52J_cjs.QueryKitError({ source: options.source, site, key, reason, ...operation ? { operation } : {} });
287
+ }, checkCondition = (node) => {
288
+ let key = String(node.key), field = options.fieldOf(key);
289
+ if (field === void 0) return;
290
+ let operation = typeof node.operation == "string" ? node.operation : "=", rule = rules.get(field);
291
+ rule || refuse("filter", key, "forbidden-key", operation), rule !== "*" && !rule.has(tokenOf(operation)) && refuse("filter", key, "forbidden-operator", operation), isLikeOperator(operation) && typeof node.value == "string" && likeWildcards(node.value) > limits.maxLikeWildcards && refuse("filter", "maxLikeWildcards", "limit-exceeded", operation);
292
+ }, checkSortKey = (site, key) => {
293
+ let field = options.fieldOf(key);
294
+ field !== void 0 && !sortable.has(field) && refuse(site, key, "forbidden-key");
295
+ };
296
+ return {
297
+ limits,
298
+ checkFilter(filter) {
299
+ let violation = findFilterLimitViolation(filter, limits);
300
+ violation && refuse("filter", violation.limit, "limit-exceeded");
301
+ let pending = Array.isArray(filter) ? [...filter] : [filter];
302
+ for (; pending.length > 0; ) {
303
+ let node = pending.pop();
304
+ isRecord2(node) && ("key" in node ? checkCondition(node) : Array.isArray(node.and) ? pending.push(...node.and) : Array.isArray(node.or) ? pending.push(...node.or) : "not" in node ? pending.push(node.not) : !chunkVD7XT52J_cjs.isRaw(node) && !options.isNative?.(node) && refuse("filter", Object.keys(node)[0] ?? "", "forbidden-key"));
305
+ }
306
+ },
307
+ checkSort(sort) {
308
+ if (sort) {
309
+ sort.length > limits.maxSortFields && refuse("sort", "maxSortFields", "limit-exceeded");
310
+ for (let item of sort) item && typeof item.key == "string" && item.key && checkSortKey("sort", item.key);
311
+ }
312
+ },
313
+ checkCursorKey(key) {
314
+ checkSortKey("cursorKey", key);
315
+ },
316
+ checkPage(page) {
317
+ ("offset" in page ? page.offset : offsetOf(page.page, page.perPage)) > limits.maxOffset && refuse("page", "maxOffset", "limit-exceeded");
318
+ },
319
+ checkAggregateKey(key) {
320
+ let field = options.fieldOf(key);
321
+ field !== void 0 && !rules.has(field) && refuse("aggregate", key, "forbidden-key");
322
+ }
323
+ };
324
+ }
325
+
326
+ Object.defineProperty(exports, "isRaw", {
327
+ enumerable: true,
328
+ get: function () { return chunkVD7XT52J_cjs.isRaw; }
329
+ });
330
+ exports.checkWith = checkWith;
331
+ exports.clampOffset = clampOffset;
332
+ exports.clampPage = clampPage;
333
+ exports.clampPageSize = clampPageSize;
334
+ exports.createContextStore = createContextStore;
335
+ exports.cursorPage = cursorPage;
336
+ exports.decodeCursor = decodeCursor;
337
+ exports.decodeCursorToken = decodeCursorToken;
338
+ exports.encodeCursor = encodeCursor;
339
+ exports.encodeCursorToken = encodeCursorToken;
340
+ exports.findFilterLimitViolation = findFilterLimitViolation;
341
+ exports.formatLimit = formatLimit;
342
+ exports.infinitePage = infinitePage;
343
+ exports.isAllRows = isAllRows;
344
+ exports.isEmptyFilter = isEmptyFilter;
345
+ exports.isLikeOperator = isLikeOperator;
346
+ exports.likeWildcards = likeWildcards;
347
+ exports.normalizeSort = normalizeSort;
348
+ exports.offsetMeta = offsetMeta;
349
+ exports.offsetOf = offsetOf;
350
+ exports.offsetPageWithoutTotal = offsetPageWithoutTotal;
351
+ exports.refuseEmptyFilter = refuseEmptyFilter;
352
+ exports.reportSkip = reportSkip;
353
+ exports.resolvePolicy = resolvePolicy;
354
+ exports.scopeConditions = scopeConditions;
355
+ exports.scopeDefaults = scopeDefaults;
356
+ //# sourceMappingURL=internal.cjs.map
357
+ //# sourceMappingURL=internal.cjs.map