@react-querybuilder/datetime 8.17.0 → 8.19.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.
Files changed (121) hide show
  1. package/dist/cjs/getDatetimeRuleProcessorTanStackDB-CL79A1_x.js +1208 -0
  2. package/dist/cjs/getDatetimeRuleProcessorTanStackDB-CL79A1_x.js.map +1 -0
  3. package/dist/cjs/getDatetimeRuleProcessorTanStackDB-DgUg_arY.js +2 -0
  4. package/dist/cjs/getDatetimeRuleProcessorTanStackDB-DgUg_arY.js.map +1 -0
  5. package/dist/cjs/react-querybuilder_datetime.cjs.development.d.ts +214 -8
  6. package/dist/cjs/react-querybuilder_datetime.cjs.development.date-fns.d.ts +46 -2
  7. package/dist/cjs/react-querybuilder_datetime.cjs.development.date-fns.js +93 -15
  8. package/dist/cjs/react-querybuilder_datetime.cjs.development.date-fns.js.map +1 -1
  9. package/dist/cjs/react-querybuilder_datetime.cjs.development.dayjs.d.ts +46 -2
  10. package/dist/cjs/react-querybuilder_datetime.cjs.development.dayjs.js +70 -59
  11. package/dist/cjs/react-querybuilder_datetime.cjs.development.dayjs.js.map +1 -1
  12. package/dist/cjs/react-querybuilder_datetime.cjs.development.js +482 -71
  13. package/dist/cjs/react-querybuilder_datetime.cjs.development.js.map +1 -1
  14. package/dist/cjs/react-querybuilder_datetime.cjs.development.jsdate.d.ts +46 -2
  15. package/dist/cjs/react-querybuilder_datetime.cjs.development.jsdate.js +129 -15
  16. package/dist/cjs/react-querybuilder_datetime.cjs.development.jsdate.js.map +1 -1
  17. package/dist/cjs/react-querybuilder_datetime.cjs.development.luxon.d.ts +46 -2
  18. package/dist/cjs/react-querybuilder_datetime.cjs.development.luxon.js +81 -15
  19. package/dist/cjs/react-querybuilder_datetime.cjs.development.luxon.js.map +1 -1
  20. package/dist/cjs/react-querybuilder_datetime.cjs.production.d.ts +214 -8
  21. package/dist/cjs/react-querybuilder_datetime.cjs.production.date-fns.d.ts +46 -2
  22. package/dist/cjs/react-querybuilder_datetime.cjs.production.date-fns.js +1 -1
  23. package/dist/cjs/react-querybuilder_datetime.cjs.production.date-fns.js.map +1 -1
  24. package/dist/cjs/react-querybuilder_datetime.cjs.production.dayjs.d.ts +46 -2
  25. package/dist/cjs/react-querybuilder_datetime.cjs.production.dayjs.js +1 -1
  26. package/dist/cjs/react-querybuilder_datetime.cjs.production.dayjs.js.map +1 -1
  27. package/dist/cjs/react-querybuilder_datetime.cjs.production.js +1 -1
  28. package/dist/cjs/react-querybuilder_datetime.cjs.production.js.map +1 -1
  29. package/dist/cjs/react-querybuilder_datetime.cjs.production.jsdate.d.ts +46 -2
  30. package/dist/cjs/react-querybuilder_datetime.cjs.production.jsdate.js +1 -1
  31. package/dist/cjs/react-querybuilder_datetime.cjs.production.jsdate.js.map +1 -1
  32. package/dist/cjs/react-querybuilder_datetime.cjs.production.luxon.d.ts +46 -2
  33. package/dist/cjs/react-querybuilder_datetime.cjs.production.luxon.js +1 -1
  34. package/dist/cjs/react-querybuilder_datetime.cjs.production.luxon.js.map +1 -1
  35. package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-BfILPx88.js +2 -0
  36. package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-BfILPx88.js.map +1 -0
  37. package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-CzLh_zi9.js +63 -0
  38. package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-CzLh_zi9.js.map +1 -0
  39. package/dist/cjs/types-XYMw0jFT.d.ts +265 -0
  40. package/dist/datetime-layout.css +1 -0
  41. package/dist/datetime-layout.css.map +1 -0
  42. package/dist/datetime-layout.scss +3 -0
  43. package/dist/datetime.css +1 -0
  44. package/dist/datetime.css.map +1 -0
  45. package/dist/datetime.scss +1 -0
  46. package/dist/getDatetimeRuleProcessorTanStackDB-BcOC-o2A.mjs +1029 -0
  47. package/dist/getDatetimeRuleProcessorTanStackDB-BcOC-o2A.mjs.map +1 -0
  48. package/dist/getDatetimeRuleProcessorTanStackDB-Dloxv6k2.mjs +2 -0
  49. package/dist/getDatetimeRuleProcessorTanStackDB-Dloxv6k2.mjs.map +1 -0
  50. package/dist/getDatetimeRuleProcessorTanStackDB-LDwhMJg0.js +1035 -0
  51. package/dist/getDatetimeRuleProcessorTanStackDB-LDwhMJg0.js.map +1 -0
  52. package/dist/react-querybuilder_datetime.d.mts +214 -8
  53. package/dist/react-querybuilder_datetime.date-fns.d.mts +46 -2
  54. package/dist/react-querybuilder_datetime.date-fns.mjs +71 -4
  55. package/dist/react-querybuilder_datetime.date-fns.mjs.map +1 -1
  56. package/dist/react-querybuilder_datetime.dayjs.d.mts +46 -2
  57. package/dist/react-querybuilder_datetime.dayjs.mjs +47 -24
  58. package/dist/react-querybuilder_datetime.dayjs.mjs.map +1 -1
  59. package/dist/react-querybuilder_datetime.jsdate.d.mts +46 -2
  60. package/dist/react-querybuilder_datetime.jsdate.mjs +106 -3
  61. package/dist/react-querybuilder_datetime.jsdate.mjs.map +1 -1
  62. package/dist/react-querybuilder_datetime.legacy-esm.d.ts +214 -8
  63. package/dist/react-querybuilder_datetime.legacy-esm.date-fns.d.ts +46 -2
  64. package/dist/react-querybuilder_datetime.legacy-esm.date-fns.js +71 -4
  65. package/dist/react-querybuilder_datetime.legacy-esm.date-fns.js.map +1 -1
  66. package/dist/react-querybuilder_datetime.legacy-esm.dayjs.d.ts +46 -2
  67. package/dist/react-querybuilder_datetime.legacy-esm.dayjs.js +47 -24
  68. package/dist/react-querybuilder_datetime.legacy-esm.dayjs.js.map +1 -1
  69. package/dist/react-querybuilder_datetime.legacy-esm.js +425 -58
  70. package/dist/react-querybuilder_datetime.legacy-esm.js.map +1 -1
  71. package/dist/react-querybuilder_datetime.legacy-esm.jsdate.d.ts +46 -2
  72. package/dist/react-querybuilder_datetime.legacy-esm.jsdate.js +106 -3
  73. package/dist/react-querybuilder_datetime.legacy-esm.jsdate.js.map +1 -1
  74. package/dist/react-querybuilder_datetime.legacy-esm.luxon.d.ts +46 -2
  75. package/dist/react-querybuilder_datetime.legacy-esm.luxon.js +58 -3
  76. package/dist/react-querybuilder_datetime.legacy-esm.luxon.js.map +1 -1
  77. package/dist/react-querybuilder_datetime.luxon.d.mts +46 -2
  78. package/dist/react-querybuilder_datetime.luxon.mjs +58 -3
  79. package/dist/react-querybuilder_datetime.luxon.mjs.map +1 -1
  80. package/dist/react-querybuilder_datetime.mjs +443 -57
  81. package/dist/react-querybuilder_datetime.mjs.map +1 -1
  82. package/dist/react-querybuilder_datetime.production.d.mts +214 -8
  83. package/dist/react-querybuilder_datetime.production.date-fns.d.mts +46 -2
  84. package/dist/react-querybuilder_datetime.production.date-fns.mjs +1 -1
  85. package/dist/react-querybuilder_datetime.production.date-fns.mjs.map +1 -1
  86. package/dist/react-querybuilder_datetime.production.dayjs.d.mts +46 -2
  87. package/dist/react-querybuilder_datetime.production.dayjs.mjs +1 -1
  88. package/dist/react-querybuilder_datetime.production.dayjs.mjs.map +1 -1
  89. package/dist/react-querybuilder_datetime.production.jsdate.d.mts +46 -2
  90. package/dist/react-querybuilder_datetime.production.jsdate.mjs +1 -1
  91. package/dist/react-querybuilder_datetime.production.jsdate.mjs.map +1 -1
  92. package/dist/react-querybuilder_datetime.production.luxon.d.mts +46 -2
  93. package/dist/react-querybuilder_datetime.production.luxon.mjs +1 -1
  94. package/dist/react-querybuilder_datetime.production.luxon.mjs.map +1 -1
  95. package/dist/react-querybuilder_datetime.production.mjs +1 -1
  96. package/dist/react-querybuilder_datetime.production.mjs.map +1 -1
  97. package/dist/rqbDateTimeLibraryAPI.dayjs-BW7faYFD.mjs +29 -0
  98. package/dist/rqbDateTimeLibraryAPI.dayjs-BW7faYFD.mjs.map +1 -0
  99. package/dist/rqbDateTimeLibraryAPI.dayjs-BoX90aqZ.mjs +2 -0
  100. package/dist/rqbDateTimeLibraryAPI.dayjs-BoX90aqZ.mjs.map +1 -0
  101. package/dist/rqbDateTimeLibraryAPI.dayjs-DvFSxPKu.js +29 -0
  102. package/dist/rqbDateTimeLibraryAPI.dayjs-DvFSxPKu.js.map +1 -0
  103. package/dist/styles/_layout.scss +30 -0
  104. package/dist/styles/_root.scss +5 -0
  105. package/dist/styles/_variables.scss +8 -0
  106. package/dist/types-CdjHqQ0k.d.mts +265 -0
  107. package/dist/types-CdjHqQ0k.d.ts +265 -0
  108. package/package.json +30 -15
  109. package/dist/cjs/getDatetimeRuleProcessorSQL-Cca9pzSn.js +0 -2
  110. package/dist/cjs/getDatetimeRuleProcessorSQL-Cca9pzSn.js.map +0 -1
  111. package/dist/cjs/getDatetimeRuleProcessorSQL-CrA2ZrSe.js +0 -563
  112. package/dist/cjs/getDatetimeRuleProcessorSQL-CrA2ZrSe.js.map +0 -1
  113. package/dist/cjs/types-c6_k1Tpr.d.ts +0 -105
  114. package/dist/getDatetimeRuleProcessorSQL-Crw01Jo-.js +0 -482
  115. package/dist/getDatetimeRuleProcessorSQL-Crw01Jo-.js.map +0 -1
  116. package/dist/getDatetimeRuleProcessorSQL-CvGKzojM.mjs +0 -2
  117. package/dist/getDatetimeRuleProcessorSQL-CvGKzojM.mjs.map +0 -1
  118. package/dist/getDatetimeRuleProcessorSQL-Nz_XjNeY.mjs +0 -468
  119. package/dist/getDatetimeRuleProcessorSQL-Nz_XjNeY.mjs.map +0 -1
  120. package/dist/types-c6_k1Tpr.d.mts +0 -105
  121. package/dist/types-c6_k1Tpr.d.ts +0 -105
@@ -0,0 +1,1029 @@
1
+ import { defaultOperatorProcessorNL, defaultRuleProcessorCEL, defaultRuleProcessorCypher, defaultRuleProcessorDrizzle, defaultRuleProcessorElasticSearch, defaultRuleProcessorGremlin, defaultRuleProcessorJSONata, defaultRuleProcessorLDAP, defaultRuleProcessorMongoDBQuery, defaultRuleProcessorNL, defaultRuleProcessorParameterized, defaultRuleProcessorPrisma, defaultRuleProcessorSPARQL, defaultRuleProcessorSQL, defaultRuleProcessorSequelize, defaultRuleProcessorSpEL, defaultRuleProcessorTanStackDB, defaultValueProcessorByRule, getQuotedFieldName, lc, mapSQLOperator, mongoOperators, normalizeConstituentWordOrder, nullOrUndefinedOrEmpty, sparqlVar, toArray } from "react-querybuilder";
2
+ //#region src/utils.ts
3
+ const isISOStringDateOnly = (date) => typeof date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(date);
4
+ /**
5
+ * Type guard for {@link RelativeDateTimeValue}. Relative values are stored as objects
6
+ * (distinguishing them from the ISO 8601 strings used for absolute date/time values).
7
+ */
8
+ const isRelativeDateTimeValue = (value) => typeof value === "object" && value !== null && value.mode === "relative" && typeof value.anchor === "string";
9
+ const anchorRegExp = /^(start|end)Of(Day|Week|Month|Year)$/;
10
+ /**
11
+ * Resolves a {@link RelativeDateTimeValue} into a concrete `Date` using the given
12
+ * date library API. The anchor is applied relative to `base` (defaulting to now),
13
+ * then the signed offset is added.
14
+ */
15
+ const resolveRelativeDateTime = (apiFns, value, base = /* @__PURE__ */ new Date()) => {
16
+ let result = base;
17
+ if (value.anchor !== "now") {
18
+ const match = anchorRegExp.exec(value.anchor);
19
+ // v8 ignore next -- guarded by the RelativeDateTimeAnchor type
20
+ if (match) {
21
+ const unit = match[2].toLowerCase();
22
+ result = match[1] === "start" ? apiFns.startOf(result, unit) : apiFns.endOf(result, unit);
23
+ }
24
+ }
25
+ if (value.offset) result = apiFns.add(result, value.offset, value.unit);
26
+ return result;
27
+ };
28
+ /**
29
+ * Whether a `datatype` represents a date-only (no time component) type, e.g. `date`
30
+ * but not `datetime`/`datetimeoffset`/`timestamp`. Used to choose the precision when
31
+ * materializing a relative value to an ISO 8601 string.
32
+ */
33
+ const isDateOnlyDatatype = (datatype) => /^date\b/i.test(datatype);
34
+ /**
35
+ * Replaces any {@link RelativeDateTimeValue} in `value` (or in each element, if `value`
36
+ * is an array) with a concrete ISO 8601 string, resolved via
37
+ * {@link resolveRelativeDateTime}. The "now" reference can be pinned with
38
+ * `opts.context.relativeDateTimeBase` for deterministic output; precision (date-only vs
39
+ * full) follows the field's `datatype`. Non-relative values pass through unchanged.
40
+ */
41
+ const materializeRelativeValues = (apiFns, value, opts) => {
42
+ const base = opts?.context?.relativeDateTimeBase;
43
+ const dateOnly = isDateOnlyDatatype(opts?.fieldData?.datatype);
44
+ const conv = (v) => {
45
+ if (!isRelativeDateTimeValue(v)) return v;
46
+ const resolved = resolveRelativeDateTime(apiFns, v, base);
47
+ return dateOnly ? apiFns.toISOStringDateOnly(resolved) : apiFns.toISOString(resolved);
48
+ };
49
+ return Array.isArray(value) ? value.map(conv) : conv(value);
50
+ };
51
+ /**
52
+ * Resolves a rule's operator for export, applying any `context.relativeOperatorMap`
53
+ * entry. Operator-driven mode controllers (see `createOperatorModeController`) use
54
+ * dedicated operator names to signal relative mode; this maps those names to the real
55
+ * comparison operator at format time. Operators absent from the map pass through unchanged.
56
+ */
57
+ const resolveDatetimeOperator = (...[rule, opts]) => (opts?.context?.relativeOperatorMap)?.[rule.operator] ?? rule.operator;
58
+ /**
59
+ * Prepares a date/time rule for delegation to a non-symbolic default rule processor
60
+ * (e.g. "parameterized", "spel", "ldap", "gremlin", "prisma", "sequelize", "drizzle",
61
+ * "tanstack_db"). Relative values are materialized to concrete dates (these formats have
62
+ * no symbolic relative form), and `between`/`notBetween` operands are ordered
63
+ * chronologically (defaults can't reorder non-numeric date operands). When `asDate` is
64
+ * set, each valid value is converted to a `Date` (for object-based formats); otherwise
65
+ * the materialized ISO 8601 strings are passed through. The resolved `operator` (after
66
+ * any `relativeOperatorMap` mapping) is returned alongside the prepared `value`.
67
+ */
68
+ const materializeForExport = (apiFns, rule, opts, asDate = false) => {
69
+ const operator = resolveDatetimeOperator(rule, opts);
70
+ const materialized = materializeRelativeValues(apiFns, rule.value, opts);
71
+ let prepared = materialized;
72
+ if (Array.isArray(materialized) && materialized.length >= 2) {
73
+ const opLC = operator.toLowerCase();
74
+ if (opLC === "between" || opLC === "notbetween") {
75
+ const first = apiFns.toDate(materialized[0]);
76
+ const second = apiFns.toDate(materialized[1]);
77
+ if (apiFns.isValid(first) && apiFns.isValid(second) && !apiFns.isBefore(first, second)) prepared = [
78
+ materialized[1],
79
+ materialized[0],
80
+ ...materialized.slice(2)
81
+ ];
82
+ }
83
+ }
84
+ if (!asDate) return {
85
+ operator,
86
+ value: prepared
87
+ };
88
+ const toDateVal = (v) => {
89
+ const d = apiFns.toDate(v);
90
+ return apiFns.isValid(d) ? d : v;
91
+ };
92
+ return {
93
+ operator,
94
+ value: Array.isArray(prepared) ? prepared.map(toDateVal) : toDateVal(prepared)
95
+ };
96
+ };
97
+ const defaultIsDateField = (...[rule, opts]) => rule.operator !== "contains" && rule.operator !== "beginsWith" && rule.operator !== "endsWith" && rule.operator !== "doesNotContain" && rule.operator !== "doesNotBeginWith" && rule.operator !== "doesNotEndWith" && rule.operator !== "null" && rule.operator !== "notNull" && /^(?:date|datetime|datetimeoffset|timestamp)\b/i.test(opts?.fieldData?.datatype);
98
+ const processIsDateField = (isDateField, ...[rule, opts]) => {
99
+ if (typeof isDateField === "boolean") return isDateField;
100
+ if (typeof isDateField === "function") return isDateField(rule, opts);
101
+ if (Array.isArray(isDateField)) return isDateField.some((condition) => Object.entries(condition).every(([key, value]) => opts?.fieldData?.[key] === value));
102
+ if (typeof isDateField === "object") return Object.entries(isDateField).every(([key, value]) => opts?.fieldData?.[key] === value);
103
+ return defaultIsDateField(rule, opts);
104
+ };
105
+ //#endregion
106
+ //#region src/getDatetimeJsonLogicOperations.ts
107
+ /**
108
+ * Custom operations for use with JsonLogic objects generated by
109
+ * {@link datetimeRuleProcessorJsonLogic}.
110
+ */
111
+ const getDatetimeJsonLogicOperations = (apiFns) => {
112
+ const { isAfter, isBefore, isSame } = apiFns;
113
+ return {
114
+ dateAfter: (a, b) => isAfter(a, b),
115
+ dateBefore: (a, b) => isBefore(a, b),
116
+ dateBetween: (a, b, c) => isSame(b, a) || isSame(b, c) || isAfter(b, a) && isBefore(b, c) || isAfter(b, c) && isBefore(b, a),
117
+ dateNotBetween: (a, b, c) => !isSame(b, a) && !isSame(b, c) && (isBefore(a, c) && (isBefore(b, a) || isAfter(b, c)) || isAfter(a, c) && (isBefore(b, c) || isAfter(b, a))),
118
+ dateIn: (a, b) => b.some((v) => isSame(a, v)),
119
+ dateNotIn: (a, b) => b.every((v) => !isSame(a, v)),
120
+ dateNotOn: (a, b) => !isSame(a, b),
121
+ dateOn: (a, b) => isSame(a, b),
122
+ dateOnOrAfter: (a, b) => isAfter(a, b) || isSame(a, b),
123
+ dateOnOrBefore: (a, b) => isBefore(a, b) || isSame(a, b),
124
+ dateRelative: (anchor, offset, unit, dateOnly) => {
125
+ const resolved = resolveRelativeDateTime(apiFns, {
126
+ mode: "relative",
127
+ anchor,
128
+ offset,
129
+ unit
130
+ });
131
+ return dateOnly ? apiFns.toISOStringDateOnly(resolved) : apiFns.toISOString(resolved);
132
+ }
133
+ };
134
+ };
135
+ //#endregion
136
+ //#region src/getDatetimeRuleProcessorCEL.ts
137
+ const shouldNegate$3 = (op) => /^(does)?not/i.test(op);
138
+ /**
139
+ * Generates a rule processor with date/time features for use by
140
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "cel" format.
141
+ */
142
+ const getDatetimeRuleProcessorCEL = (apiFns) => (rule, options) => {
143
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
144
+ const { context = {} } = opts;
145
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorCEL(rule, opts);
146
+ const ts = (d) => `timestamp("${apiFns.toISOString(d)}")`;
147
+ const value = materializeRelativeValues(apiFns, rule.value, opts);
148
+ const operatorTL = lc(resolveDatetimeOperator(rule, opts).replace(/^=$/, "=="));
149
+ switch (operatorTL) {
150
+ case "<":
151
+ case "<=":
152
+ case "==":
153
+ case "!=":
154
+ case ">":
155
+ case ">=": return `${rule.field} ${operatorTL} ${ts(value)}`;
156
+ }
157
+ const valueAsDateArray = toArray(value, { retainEmptyStrings: false }).map((v) => apiFns.toDate(v)).filter((dateVal) => apiFns.isValid(dateVal));
158
+ switch (operatorTL) {
159
+ case "in":
160
+ case "notin": {
161
+ if (valueAsDateArray.length === 0) return "";
162
+ const [prefix, suffix] = shouldNegate$3(operatorTL) ? ["!(", ")"] : ["", ""];
163
+ return `${prefix}${rule.field} in [${valueAsDateArray.map((val) => ts(val)).join(", ")}]${suffix}`;
164
+ }
165
+ case "between":
166
+ case "notbetween": {
167
+ if (valueAsDateArray.length < 2) return "";
168
+ const [first, second] = valueAsDateArray;
169
+ const [firstDate, secondDate] = apiFns.isBefore(first, second) ? [first, second] : [second, first];
170
+ return operatorTL === "between" ? `(${rule.field} >= ${ts(firstDate)} && ${rule.field} <= ${ts(secondDate)})` : `(${rule.field} < ${ts(firstDate)} || ${rule.field} > ${ts(secondDate)})`;
171
+ }
172
+ }
173
+ return defaultRuleProcessorCEL(rule, opts);
174
+ };
175
+ //#endregion
176
+ //#region src/getDatetimeRuleProcessorCypher.ts
177
+ const shouldNegate$2 = (op) => /^(does)?not/i.test(op);
178
+ /**
179
+ * Wraps a date string in the appropriate Cypher temporal constructor.
180
+ * - Date-only strings (YYYY-MM-DD) become `date('...')`
181
+ * - Full ISO strings become `datetime('...')`
182
+ */
183
+ const cypherTemporal = (iso, dateOnly) => dateOnly ? `date('${iso}')` : `datetime('${iso}')`;
184
+ /**
185
+ * Generates a rule processor with date/time features for use by
186
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "cypher" or "gql" format.
187
+ *
188
+ * Supports:
189
+ * - Standard comparison operators (`=`, `!=`, `<`, `>`, `<=`, `>=`)
190
+ * - Range operators (between, notBetween, in, notIn)
191
+ * - Duration math via custom operators: `olderThanDuration` and `withinDuration`
192
+ * (e.g., value `"P30D"` → `datetime() - field > duration('P30D')`)
193
+ */
194
+ const getDatetimeRuleProcessorCypher = (apiFns) => (rule, options) => {
195
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
196
+ const { context = {} } = opts;
197
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorCypher(rule, opts);
198
+ const { field } = rule;
199
+ const operatorTL = lc(resolveDatetimeOperator(rule, opts));
200
+ if (operatorTL === "olderthanduration") return `datetime() - ${field} > duration('${rule.value}')`;
201
+ if (operatorTL === "withinduration") return `datetime() - ${field} <= duration('${rule.value}')`;
202
+ const valueAsDateArray = toArray(materializeRelativeValues(apiFns, rule.value, opts), { retainEmptyStrings: false }).map((v) => [v, apiFns.toDate(v)]).filter(([, d]) => apiFns.isValid(d));
203
+ const fmtDate = (originalValue) => {
204
+ const dateOnly = isISOStringDateOnly(originalValue);
205
+ return cypherTemporal(dateOnly ? apiFns.toISOStringDateOnly(originalValue) : apiFns.toISOString(originalValue), dateOnly);
206
+ };
207
+ switch (operatorTL) {
208
+ case "in":
209
+ case "notin": {
210
+ if (valueAsDateArray.length === 0) return "";
211
+ const items = valueAsDateArray.map(([orig]) => fmtDate(orig));
212
+ return `${shouldNegate$2(operatorTL) ? "NOT " : ""}${field} IN [${items.join(", ")}]`;
213
+ }
214
+ case "between":
215
+ case "notbetween": {
216
+ if (valueAsDateArray.length < 2) return "";
217
+ const [first, second] = valueAsDateArray;
218
+ const [lo, hi] = apiFns.isBefore(first[1], second[1]) ? [first, second] : [second, first];
219
+ const expr = `${fmtDate(lo[0])} <= ${field} AND ${field} <= ${fmtDate(hi[0])}`;
220
+ return operatorTL === "notbetween" ? `NOT (${expr})` : expr;
221
+ }
222
+ default: {
223
+ if (valueAsDateArray.length === 0) return "";
224
+ const [orig] = valueAsDateArray[0];
225
+ return `${field} ${operatorTL === "<>" ? "<>" : operatorTL} ${fmtDate(orig)}`;
226
+ }
227
+ }
228
+ };
229
+ //#endregion
230
+ //#region src/getDatetimeRuleProcessorDrizzle.ts
231
+ /**
232
+ * Generates a rule processor with date/time features for use by
233
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "drizzle" format.
234
+ * Relative values are materialized and all date/time values are converted to `Date`
235
+ * objects (Drizzle column operators compare against native `Date` values).
236
+ */
237
+ const getDatetimeRuleProcessorDrizzle = (apiFns) => (rule, options) => {
238
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
239
+ const { context = {} } = opts;
240
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorDrizzle(rule, opts);
241
+ const { operator, value } = materializeForExport(apiFns, rule, opts, true);
242
+ return defaultRuleProcessorDrizzle({
243
+ ...rule,
244
+ operator,
245
+ value
246
+ }, opts);
247
+ };
248
+ //#endregion
249
+ //#region src/getDatetimeRuleProcessorElasticSearch.ts
250
+ /**
251
+ * Generates a rule processor with date/time features for use by
252
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "elasticsearch" format.
253
+ * Relative values are materialized to concrete ISO 8601 strings (ElasticSearch has no
254
+ * symbolic relative form); absolute values pass through.
255
+ */
256
+ const getDatetimeRuleProcessorElasticSearch = (apiFns) => (rule, options) => {
257
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
258
+ const { context = {} } = opts;
259
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorElasticSearch(rule, opts);
260
+ const { operator, value } = materializeForExport(apiFns, rule, opts);
261
+ return defaultRuleProcessorElasticSearch({
262
+ ...rule,
263
+ operator,
264
+ value
265
+ }, opts);
266
+ };
267
+ //#endregion
268
+ //#region src/getDatetimeRuleProcessorGremlin.ts
269
+ /**
270
+ * Generates a rule processor with date/time features for use by
271
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "gremlin" format.
272
+ * Relative values are materialized to concrete ISO 8601 strings (Gremlin has no symbolic
273
+ * relative form); absolute values pass through.
274
+ */
275
+ const getDatetimeRuleProcessorGremlin = (apiFns) => (rule, options) => {
276
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
277
+ const { context = {} } = opts;
278
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorGremlin(rule, opts);
279
+ const { operator, value } = materializeForExport(apiFns, rule, opts);
280
+ return defaultRuleProcessorGremlin({
281
+ ...rule,
282
+ operator,
283
+ value
284
+ }, opts);
285
+ };
286
+ //#endregion
287
+ //#region src/getDatetimeRuleProcessorJSONata.ts
288
+ const shouldNegate$1 = (op) => /^(does)?not/i.test(op);
289
+ const negate = (clause, neg) => neg ? `$not(${clause})` : `${clause}`;
290
+ /**
291
+ * Generates a rule processor with date/time features for use by
292
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "jsonata" format.
293
+ */
294
+ const getDatetimeRuleProcessorJSONata = (apiFns) => (rule, options) => {
295
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
296
+ const { context = {} } = opts;
297
+ // v8 ignore next
298
+ const { quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "" } = opts;
299
+ const { field, valueSource } = rule;
300
+ const operator = resolveDatetimeOperator(rule, opts);
301
+ if (!processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorJSONata(rule, opts);
302
+ const valueIsField = valueSource === "field";
303
+ const value = valueIsField ? rule.value : materializeRelativeValues(apiFns, rule.value, opts);
304
+ const fldToMs = (f) => `$toMillis(${getQuotedFieldName(f, {
305
+ quoteFieldNamesWith,
306
+ fieldIdentifierSeparator
307
+ })})`;
308
+ const valToMs = (v) => `$toMillis("${apiFns.toISOString(v)}")`;
309
+ switch (operator) {
310
+ case "<":
311
+ case "<=":
312
+ case "=":
313
+ case "!=":
314
+ case ">":
315
+ case ">=": return `${fldToMs(field)} ${operator} ${valueIsField ? fldToMs(value) : valToMs(value)}`;
316
+ }
317
+ const valueAsArray = toArray(value, { retainEmptyStrings: false });
318
+ const valueAsDateArray = valueAsArray.map((v) => apiFns.toDate(v)).filter((dateVal) => apiFns.isValid(dateVal));
319
+ switch (operator) {
320
+ case "in":
321
+ case "notIn":
322
+ if (valueIsField) {
323
+ if (valueAsArray.length === 0) return "";
324
+ return negate(`${fldToMs(field)} in [${valueAsArray.map((val) => fldToMs(val)).join(", ")}]`, shouldNegate$1(operator));
325
+ }
326
+ if (valueAsDateArray.length === 0) return "";
327
+ return negate(`${fldToMs(field)} in [${valueAsDateArray.map((val) => valToMs(val)).join(", ")}]`, shouldNegate$1(operator));
328
+ case "between":
329
+ case "notBetween": {
330
+ if (valueAsArray.length < 2 || nullOrUndefinedOrEmpty(valueAsArray[0]) || nullOrUndefinedOrEmpty(valueAsArray[1]) || !valueIsField && valueAsDateArray.length < 2) return "";
331
+ if (valueIsField) {
332
+ const [firstValue, secondValue] = valueAsArray;
333
+ const expression = `${fldToMs(field)} >= ${fldToMs(firstValue)} and ${fldToMs(field)} <= ${fldToMs(secondValue)}`;
334
+ return operator === "between" ? `(${expression})` : negate(expression, true);
335
+ }
336
+ const [first, second] = valueAsDateArray;
337
+ const [firstDate, secondDate] = apiFns.isBefore(first, second) ? [first, second] : [second, first];
338
+ const expression = `${fldToMs(field)} >= ${valToMs(firstDate)} and ${fldToMs(field)} <= ${valToMs(secondDate)}`;
339
+ return operator === "between" ? `(${expression})` : negate(expression, true);
340
+ }
341
+ }
342
+ return defaultRuleProcessorJSONata(rule, opts);
343
+ };
344
+ //#endregion
345
+ //#region src/getDatetimeRuleProcessorLDAP.ts
346
+ /**
347
+ * Generates a rule processor with date/time features for use by
348
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "ldap" format.
349
+ * Relative values are materialized to concrete ISO 8601 strings (LDAP has no symbolic
350
+ * relative form); absolute values pass through.
351
+ */
352
+ const getDatetimeRuleProcessorLDAP = (apiFns) => (rule, options) => {
353
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
354
+ const { context = {} } = opts;
355
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorLDAP(rule, opts);
356
+ const { operator, value } = materializeForExport(apiFns, rule, opts);
357
+ return defaultRuleProcessorLDAP({
358
+ ...rule,
359
+ operator,
360
+ value
361
+ }, opts);
362
+ };
363
+ //#endregion
364
+ //#region src/getDatetimeRuleProcessorMongoDBQuery.ts
365
+ /**
366
+ * Generates a rule processor with date/time features for use by
367
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "mongodb_query" format.
368
+ */
369
+ const getDatetimeRuleProcessorMongoDBQuery = (apiFns) => (rule, options) => {
370
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
371
+ const { field, valueSource } = rule;
372
+ const operator = resolveDatetimeOperator(rule, opts);
373
+ if (valueSource === "field" || !processIsDateField(opts.context?.isDateField, rule, opts)) return defaultRuleProcessorMongoDBQuery(rule, opts);
374
+ const value = materializeRelativeValues(apiFns, rule.value, opts);
375
+ if (operator === "=") return { [field]: apiFns.toDate(value) };
376
+ switch (operator) {
377
+ case "<":
378
+ case "<=":
379
+ case "!=":
380
+ case ">":
381
+ case ">=": return { [field]: { [mongoOperators[operator]]: apiFns.toDate(value) } };
382
+ }
383
+ const valueAsDateArray = toArray(value, { retainEmptyStrings: false }).map((v) => apiFns.toDate(v)).filter((dateVal) => apiFns.isValid(dateVal));
384
+ switch (operator) {
385
+ case "in":
386
+ case "notIn": return { [field]: { [mongoOperators[operator]]: valueAsDateArray } };
387
+ case "between":
388
+ case "notBetween": {
389
+ if (valueAsDateArray.length < 2) return "";
390
+ const [first, second] = valueAsDateArray;
391
+ const orderedArray = apiFns.isBefore(first, second) ? [first, second] : [second, first];
392
+ return operator === "between" ? { [field]: {
393
+ $gte: orderedArray[0],
394
+ $lte: orderedArray[1]
395
+ } } : { $or: [{ [field]: { $lt: orderedArray[0] } }, { [field]: { $gt: orderedArray[1] } }] };
396
+ }
397
+ }
398
+ return defaultRuleProcessorMongoDBQuery(rule, opts);
399
+ };
400
+ //#endregion
401
+ //#region src/getDatetimeRuleProcessorMongoDB.ts
402
+ /**
403
+ * Generates a rule processor with date/time features for use by
404
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the (deprecated) "mongodb"
405
+ * format. Delegates to the "mongodb_query" date/time processor and serializes the result;
406
+ * `Date` values serialize to ISO 8601 strings.
407
+ */
408
+ const getDatetimeRuleProcessorMongoDB = (apiFns) => {
409
+ const mongoDBQueryProcessor = getDatetimeRuleProcessorMongoDBQuery(apiFns);
410
+ return (rule, options) => {
411
+ const queryObj = mongoDBQueryProcessor(rule, options);
412
+ return queryObj ? JSON.stringify(queryObj) : "";
413
+ };
414
+ };
415
+ //#endregion
416
+ //#region src/getDatetimeRuleProcessorNL.ts
417
+ const defaultDateTimeNLOperatorMap = {
418
+ "<": "is before",
419
+ ">": "is after",
420
+ "<=": "is on or before",
421
+ ">=": "is on or after",
422
+ in: ["is one of the dates", "is the same as a date in"],
423
+ notin: ["is not one of the dates", "is not the same as any date in"],
424
+ between: ["is between", "is between the dates in"],
425
+ notbetween: ["is not between", "is not between the dates in"]
426
+ };
427
+ /**
428
+ * Generates a value processor with date/time features for use by
429
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "natural_language" format.
430
+ */
431
+ const datetimeValueProcessorNL = (rule, opts) => {
432
+ if (isISOStringDateOnly(opts?.context?.originalValue)) return new Intl.DateTimeFormat(opts?.context?.locales, {
433
+ dateStyle: "full",
434
+ ...opts?.context?.dateFormat
435
+ }).format(rule.value);
436
+ return new Intl.DateTimeFormat(opts?.context?.locales, {
437
+ dateStyle: "full",
438
+ timeStyle: "long",
439
+ ...opts?.context?.dateTimeFormat
440
+ }).format(rule.value);
441
+ };
442
+ /**
443
+ * Generates a rule processor with date/time features for use by {@link @react-querybuilder/core!formatQuery formatQuery} with
444
+ * the "natural_language" format.
445
+ */
446
+ const getDatetimeRuleProcessorNL = (apiFns) => (rule, options) => {
447
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
448
+ const operator = resolveDatetimeOperator(rule, opts);
449
+ const operatorLowerCase = lc(operator);
450
+ let finalValue = "";
451
+ // v8 ignore next
452
+ const { fieldData, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", operatorProcessor = defaultOperatorProcessorNL, wordOrder = "SVO", context = {}, operatorMap = defaultDateTimeNLOperatorMap } = opts;
453
+ if (!processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorNL(rule, opts);
454
+ if (rule.valueSource === "field") return defaultRuleProcessorNL(rule, {
455
+ ...opts,
456
+ operatorMap: defaultDateTimeNLOperatorMap
457
+ });
458
+ if ((operatorLowerCase === "in" || operatorLowerCase === "notin" || operatorLowerCase === "between" || operatorLowerCase === "notbetween") && !rule.value) return "";
459
+ const valueAsDateArray = toArray(materializeRelativeValues(apiFns, rule.value, opts), { retainEmptyStrings: false }).map((v) => [v, apiFns.toDate(v)]).filter((v) => apiFns.isValid(v[1]));
460
+ switch (operatorLowerCase) {
461
+ case "in":
462
+ case "notin":
463
+ if (valueAsDateArray.length === 0) return "";
464
+ finalValue = `(${valueAsDateArray.map((value) => datetimeValueProcessorNL({
465
+ field: rule.field,
466
+ operator: "=",
467
+ value: value[1]
468
+ }, {
469
+ ...opts,
470
+ context: {
471
+ ...context,
472
+ originalValue: value[0]
473
+ }
474
+ })).join(", ")})`;
475
+ break;
476
+ case "between":
477
+ case "notbetween":
478
+ {
479
+ if (valueAsDateArray.length < 2) return "";
480
+ const [first, second] = valueAsDateArray;
481
+ finalValue = (apiFns.isBefore(first[1], second[1]) ? [first, second] : [second, first]).map(([originalValue, value]) => datetimeValueProcessorNL({
482
+ field: rule.field,
483
+ operator: "=",
484
+ value
485
+ }, {
486
+ ...opts,
487
+ context: {
488
+ ...context,
489
+ originalValue
490
+ }
491
+ })).join(` ${opts.translations?.and ?? "and"} `);
492
+ }
493
+ break;
494
+ default: {
495
+ const [originalValue, value] = valueAsDateArray[0] ?? ["", ""];
496
+ finalValue = originalValue ? datetimeValueProcessorNL({
497
+ field: rule.field,
498
+ operator: "=",
499
+ value
500
+ }, {
501
+ ...opts,
502
+ context: {
503
+ ...context,
504
+ originalValue
505
+ }
506
+ }) : "";
507
+ }
508
+ }
509
+ const wordOrderMap = {
510
+ S: getQuotedFieldName(fieldData?.label ?? rule.field, {
511
+ quoteFieldNamesWith,
512
+ fieldIdentifierSeparator
513
+ }),
514
+ V: operatorProcessor({
515
+ ...rule,
516
+ operator
517
+ }, {
518
+ ...opts,
519
+ operatorMap: {
520
+ ...defaultDateTimeNLOperatorMap,
521
+ ...operatorMap
522
+ }
523
+ }),
524
+ O: finalValue
525
+ };
526
+ return normalizeConstituentWordOrder(wordOrder).map((term) => `${wordOrderMap[term]}`).join(" ").trim();
527
+ };
528
+ //#endregion
529
+ //#region src/getDatetimeRuleProcessorParameterized.ts
530
+ /**
531
+ * Generates a rule processor with date/time features for use by
532
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "parameterized" and
533
+ * "parameterized_named" formats. Relative values are materialized to concrete ISO 8601
534
+ * strings (these formats have no symbolic relative form); absolute values pass through.
535
+ */
536
+ const getDatetimeRuleProcessorParameterized = (apiFns) => (rule, options, meta) => {
537
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
538
+ const { context = {} } = opts;
539
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorParameterized(rule, opts, meta);
540
+ const { operator, value } = materializeForExport(apiFns, rule, opts);
541
+ return defaultRuleProcessorParameterized({
542
+ ...rule,
543
+ operator,
544
+ value
545
+ }, opts, meta);
546
+ };
547
+ //#endregion
548
+ //#region src/getDatetimeRuleProcessorPrisma.ts
549
+ /**
550
+ * Generates a rule processor with date/time features for use by
551
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "prisma" format.
552
+ * Relative values are materialized and all date/time values are converted to `Date`
553
+ * objects (Prisma's `where` clauses use native `Date` values for date columns).
554
+ */
555
+ const getDatetimeRuleProcessorPrisma = (apiFns) => (rule, options) => {
556
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
557
+ const { context = {} } = opts;
558
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorPrisma(rule, opts);
559
+ const { operator, value } = materializeForExport(apiFns, rule, opts, true);
560
+ return defaultRuleProcessorPrisma({
561
+ ...rule,
562
+ operator,
563
+ value
564
+ }, opts);
565
+ };
566
+ //#endregion
567
+ //#region src/getDatetimeRuleProcessorSequelize.ts
568
+ /**
569
+ * Generates a rule processor with date/time features for use by
570
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "sequelize" format.
571
+ * Relative values are materialized and all date/time values are converted to `Date`
572
+ * objects (Sequelize `where` clauses use native `Date` values for date columns).
573
+ */
574
+ const getDatetimeRuleProcessorSequelize = (apiFns) => (rule, options) => {
575
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
576
+ const { context = {} } = opts;
577
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorSequelize(rule, opts);
578
+ const { operator, value } = materializeForExport(apiFns, rule, opts, true);
579
+ return defaultRuleProcessorSequelize({
580
+ ...rule,
581
+ operator,
582
+ value
583
+ }, opts);
584
+ };
585
+ //#endregion
586
+ //#region src/getDatetimeRuleProcessorSPARQL.ts
587
+ const shouldNegate = (op) => /^(does)?not/i.test(op);
588
+ /**
589
+ * Wraps a date string in the appropriate SPARQL typed literal.
590
+ * - Date-only strings (YYYY-MM-DD) become `"..."^^xsd:date`
591
+ * - Full ISO strings become `"..."^^xsd:dateTime`
592
+ */
593
+ const sparqlTemporal = (iso, dateOnly) => dateOnly ? `"${iso}"^^xsd:date` : `"${iso}"^^xsd:dateTime`;
594
+ /**
595
+ * Generates a rule processor with date/time features for use by
596
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "sparql" format.
597
+ *
598
+ * Supports:
599
+ * - Standard comparison operators (`=`, `!=`, `<`, `>`, `<=`, `>=`)
600
+ * - Range operators (between, notBetween, in, notIn)
601
+ * - Duration math via custom operators: `olderThanDuration` and `withinDuration`
602
+ * (e.g., value `"P30D"` → `NOW() - ?field > "P30D"^^xsd:duration`)
603
+ */
604
+ const getDatetimeRuleProcessorSPARQL = (apiFns) => (rule, options) => {
605
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
606
+ const { context = {} } = opts;
607
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorSPARQL(rule, opts);
608
+ const { field: rawField, value } = rule;
609
+ const operator = resolveDatetimeOperator(rule, opts);
610
+ const field = sparqlVar(rawField);
611
+ const operatorTL = lc(operator);
612
+ if (operatorTL === "olderthanduration") return `NOW() - ${field} > "${value}"^^xsd:duration`;
613
+ if (operatorTL === "withinduration") return `NOW() - ${field} <= "${value}"^^xsd:duration`;
614
+ const valueAsDateArray = toArray(materializeRelativeValues(apiFns, value, opts), { retainEmptyStrings: false }).map((v) => [v, apiFns.toDate(v)]).filter(([, d]) => apiFns.isValid(d));
615
+ const fmtDate = (originalValue) => {
616
+ const dateOnly = isISOStringDateOnly(originalValue);
617
+ return sparqlTemporal(dateOnly ? apiFns.toISOStringDateOnly(originalValue) : apiFns.toISOString(originalValue), dateOnly);
618
+ };
619
+ switch (operatorTL) {
620
+ case "in":
621
+ case "notin": {
622
+ if (valueAsDateArray.length === 0) return "";
623
+ const items = valueAsDateArray.map(([orig]) => fmtDate(orig));
624
+ return `${field} ${shouldNegate(operatorTL) ? "NOT " : ""}IN (${items.join(", ")})`;
625
+ }
626
+ case "between":
627
+ case "notbetween": {
628
+ if (valueAsDateArray.length < 2) return "";
629
+ const [first, second] = valueAsDateArray;
630
+ const [lo, hi] = apiFns.isBefore(first[1], second[1]) ? [first, second] : [second, first];
631
+ if (operatorTL === "notbetween") return `(${field} < ${fmtDate(lo[0])} || ${field} > ${fmtDate(hi[0])})`;
632
+ return `${field} >= ${fmtDate(lo[0])} && ${field} <= ${fmtDate(hi[0])}`;
633
+ }
634
+ default: {
635
+ if (valueAsDateArray.length === 0) return "";
636
+ const [orig] = valueAsDateArray[0];
637
+ return `${field} ${operatorTL === "<>" ? "!=" : operatorTL} ${fmtDate(orig)}`;
638
+ }
639
+ }
640
+ };
641
+ //#endregion
642
+ //#region src/getDatetimeRuleProcessorSpEL.ts
643
+ /**
644
+ * Generates a rule processor with date/time features for use by
645
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "spel" format.
646
+ * Relative values are materialized to concrete ISO 8601 strings (SpEL has no symbolic
647
+ * relative form); absolute values pass through.
648
+ */
649
+ const getDatetimeRuleProcessorSpEL = (apiFns) => (rule, options) => {
650
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
651
+ const { context = {} } = opts;
652
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorSpEL(rule, opts);
653
+ const { operator, value } = materializeForExport(apiFns, rule, opts);
654
+ return defaultRuleProcessorSpEL({
655
+ ...rule,
656
+ operator,
657
+ value
658
+ }, opts);
659
+ };
660
+ //#endregion
661
+ //#region src/getRelativeDateTimeSQL.ts
662
+ const parseAnchor = (anchor) => {
663
+ if (anchor === "now") return { bound: "now" };
664
+ const match = /^(start|end)Of(Day|Week|Month|Year)$/.exec(anchor);
665
+ return {
666
+ bound: match[1],
667
+ unit: match[2].toLowerCase()
668
+ };
669
+ };
670
+ const pluralUnit = (unit) => `${unit}s`;
671
+ const pgBuild = (value, asDate) => {
672
+ const now = asDate ? "current_date" : "current_timestamp";
673
+ const { bound, unit } = parseAnchor(value.anchor);
674
+ let expr = now;
675
+ let modified = false;
676
+ if (bound === "start" && unit) {
677
+ expr = `date_trunc('${unit}', ${now})`;
678
+ modified = true;
679
+ } else if (bound === "end" && unit) {
680
+ expr = `date_trunc('${unit}', ${now}) + interval '1 ${unit}' - ${asDate ? `interval '1 day'` : `interval '1 microsecond'`}`;
681
+ modified = true;
682
+ }
683
+ if (value.offset) {
684
+ const op = value.offset < 0 ? "-" : "+";
685
+ expr = `${expr} ${op} interval '${Math.abs(value.offset)} ${pluralUnit(value.unit)}'`;
686
+ modified = true;
687
+ }
688
+ return asDate && modified ? `cast(${expr} as date)` : expr;
689
+ };
690
+ const mysqlTrunc = (now, bound, unit) => {
691
+ if (bound === "start") switch (unit) {
692
+ case "day": return `date(${now})`;
693
+ case "week": return `date_sub(date(${now}), interval dayofweek(${now}) - 1 day)`;
694
+ case "month": return `date_format(${now}, '%Y-%m-01')`;
695
+ case "year": return `date_format(${now}, '%Y-01-01')`;
696
+ }
697
+ switch (unit) {
698
+ case "day": return `date(${now})`;
699
+ case "week": return `date_add(date(${now}), interval 7 - dayofweek(${now}) day)`;
700
+ case "month": return `last_day(${now})`;
701
+ }
702
+ return `date_format(${now}, '%Y-12-31')`;
703
+ };
704
+ const mysqlBuild = (value, asDate) => {
705
+ const now = asDate ? "curdate()" : "now()";
706
+ const { bound, unit } = parseAnchor(value.anchor);
707
+ let expr = now;
708
+ if (bound !== "now" && unit) {
709
+ expr = mysqlTrunc(now, bound, unit);
710
+ if (bound === "end" && !asDate) expr = `date_sub(date_add(${expr}, interval 1 day), interval 1 microsecond)`;
711
+ }
712
+ if (value.offset) expr = `${value.offset < 0 ? "date_sub" : "date_add"}(${expr}, interval ${Math.abs(value.offset)} ${value.unit})`;
713
+ return expr;
714
+ };
715
+ const mssqlTrunc = (now, bound, unit, asDate) => {
716
+ const start = `dateadd(${unit}, datediff(${unit}, 0, ${now}), 0)`;
717
+ if (bound === "start") return start;
718
+ const nextStart = `dateadd(${unit}, datediff(${unit}, 0, ${now}) + 1, 0)`;
719
+ return asDate ? `dateadd(day, -1, ${nextStart})` : `dateadd(nanosecond, -100, cast(${nextStart} as datetime2))`;
720
+ };
721
+ const mssqlBuild = (value, asDate) => {
722
+ const now = asDate ? "cast(getdate() as date)" : "getdate()";
723
+ const { bound, unit } = parseAnchor(value.anchor);
724
+ let expr = now;
725
+ if (bound !== "now" && unit) expr = mssqlTrunc(now, bound, unit, asDate);
726
+ if (value.offset) expr = `dateadd(${value.unit}, ${value.offset}, ${expr})`;
727
+ return expr;
728
+ };
729
+ const oracleTruncFormat = {
730
+ day: "DDD",
731
+ week: "IW",
732
+ month: "MM",
733
+ year: "YYYY"
734
+ };
735
+ const oracleBuild = (value, asDate) => {
736
+ const now = asDate ? "trunc(sysdate)" : "systimestamp";
737
+ const { bound, unit } = parseAnchor(value.anchor);
738
+ let expr = now;
739
+ let endTimestampStepBack = false;
740
+ if (bound !== "now" && unit) {
741
+ const start = `trunc(${now}, '${oracleTruncFormat[unit]}')`;
742
+ if (bound === "start") expr = start;
743
+ else {
744
+ const next = unit === "month" || unit === "year" ? `add_months(${start}, ${unit === "month" ? 1 : 12})` : `${start} + interval '1' day${unit === "week" ? " * 7" : ""}`;
745
+ if (asDate) expr = `${next} - interval '1' second`;
746
+ else {
747
+ expr = next;
748
+ endTimestampStepBack = true;
749
+ }
750
+ }
751
+ }
752
+ if (value.offset) if (value.unit === "month" || value.unit === "year") expr = `add_months(${expr}, ${value.offset * (value.unit === "year" ? 12 : 1)})`;
753
+ else {
754
+ const days = {
755
+ day: 1,
756
+ week: 7
757
+ }[value.unit];
758
+ expr = days ? `${expr} ${value.offset < 0 ? "-" : "+"} ${Math.abs(value.offset) * days}` : `${expr} + numtodsinterval(${value.offset}, '${value.unit.toUpperCase()}')`;
759
+ }
760
+ if (endTimestampStepBack) expr = `cast(${expr} as timestamp) - numtodsinterval(0.000001, 'second')`;
761
+ return expr;
762
+ };
763
+ const sqliteStartModifier = {
764
+ day: `'start of day'`,
765
+ week: `'weekday 0', '-7 days'`,
766
+ month: `'start of month'`,
767
+ year: `'start of year'`
768
+ };
769
+ const sqliteBuild = (value, asDate) => {
770
+ const fn = asDate ? "date" : "datetime";
771
+ const args = [`'now'`];
772
+ const { bound, unit } = parseAnchor(value.anchor);
773
+ if (bound !== "now" && unit) if (bound === "start") args.push(sqliteStartModifier[unit]);
774
+ else switch (unit) {
775
+ case "day":
776
+ args.push(`'start of day'`, `'+1 day'`, asDate ? `'-1 day'` : `'-1 second'`);
777
+ break;
778
+ case "week":
779
+ args.push(`'weekday 0'`, asDate ? `'-1 day'` : `'-1 second'`);
780
+ break;
781
+ case "month":
782
+ args.push(`'start of month'`, `'+1 month'`, asDate ? `'-1 day'` : `'-1 second'`);
783
+ break;
784
+ case "year":
785
+ args.push(`'start of year'`, `'+1 year'`, asDate ? `'-1 day'` : `'-1 second'`);
786
+ break;
787
+ }
788
+ if (value.offset) {
789
+ const sign = value.offset < 0 ? "-" : "+";
790
+ args.push(`'${sign}${Math.abs(value.offset)} ${pluralUnit(value.unit)}'`);
791
+ }
792
+ return `${fn}(${args.join(", ")})`;
793
+ };
794
+ const presetToRelativeBuilderMap = {
795
+ ansi: pgBuild,
796
+ mssql: mssqlBuild,
797
+ mysql: mysqlBuild,
798
+ oracle: oracleBuild,
799
+ postgresql: pgBuild,
800
+ sqlite: sqliteBuild
801
+ };
802
+ /**
803
+ * Determines whether the SQL expression for a relative date/time should be a
804
+ * date (vs. a timestamp/datetime) based on the field's declared `datatype` and
805
+ * the SQL dialect. Mirrors the per-dialect logic used for literal date values.
806
+ */
807
+ const isDateGranularity = (preset, datatype) => {
808
+ const dt = datatype;
809
+ switch (preset) {
810
+ case "mssql": return !/^(?:small)?datetime/i.test(dt);
811
+ case "mysql": return !/^(?:datetime|timestamp)/i.test(dt);
812
+ case "oracle":
813
+ case "postgresql": return !/^timestamp/i.test(dt);
814
+ default: return !/^(?:datetime|timestamp)/i.test(dt);
815
+ }
816
+ };
817
+ /**
818
+ * Builds a dialect-specific symbolic SQL expression for a {@link RelativeDateTimeValue}.
819
+ */
820
+ const getRelativeDateTimeSQL = (value, preset, datatype) => presetToRelativeBuilderMap[preset](value, isDateGranularity(preset, datatype));
821
+ //#endregion
822
+ //#region src/getDatetimeRuleProcessorSQL.ts
823
+ /**
824
+ * Generates a value processor with date/time features for use by
825
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "sql" format and "ansi" preset.
826
+ */
827
+ const getDatetimeValueProcessorANSI = ({ toISOStringDateOnly, toISOString }) => (rule, opts) => {
828
+ if (isISOStringDateOnly(opts?.context?.originalValue)) return defaultValueProcessorByRule({
829
+ ...rule,
830
+ value: toISOStringDateOnly(rule.value)
831
+ }, opts);
832
+ return defaultValueProcessorByRule({
833
+ ...rule,
834
+ value: toISOString(rule.value)
835
+ }, opts);
836
+ };
837
+ /**
838
+ * Generates a value processor with date/time features for use by {@link @react-querybuilder/core!formatQuery formatQuery} with
839
+ * the "sql" format and "mssql" preset.
840
+ */
841
+ const getDatetimeValueProcessorMSSQL = ({ toISOStringDateOnly, toISOString }) => (rule, opts) => {
842
+ const datatype = /^(?:small)?datetime/i.test(opts?.fieldData?.datatype) ? "datetimeoffset" : "date";
843
+ const value = datatype === "datetimeoffset" ? toISOString(rule.value) : toISOStringDateOnly(rule.value);
844
+ return defaultValueProcessorByRule({
845
+ ...rule,
846
+ value
847
+ }, {
848
+ ...opts,
849
+ wrapValueWith: [`cast(`, ` as ${datatype})`]
850
+ });
851
+ };
852
+ /**
853
+ * Generates a value processor with date/time features for use by {@link @react-querybuilder/core!formatQuery formatQuery} with
854
+ * the "sql" format and "mysql" preset.
855
+ */
856
+ const getDatetimeValueProcessorMySQL = ({ toISOStringDateOnly, toISOString }) => (rule, opts) => {
857
+ const datatype = /^(?:datetime|timestamp)/i.test(opts?.fieldData?.datatype) ? "datetime" : "date";
858
+ const value = datatype === "datetime" ? toISOString(rule.value) : toISOStringDateOnly(rule.value);
859
+ return defaultValueProcessorByRule({
860
+ ...rule,
861
+ value
862
+ }, {
863
+ ...opts,
864
+ wrapValueWith: [`cast(`, ` as ${datatype})`]
865
+ });
866
+ };
867
+ /**
868
+ * Generates a value processor with date/time features for use by {@link @react-querybuilder/core!formatQuery formatQuery} with
869
+ * the "sql" format and "oracle" preset.
870
+ */
871
+ const getDatetimeValueProcessorOracle = ({ toISOStringDateOnly, toISOString }) => (rule, opts) => {
872
+ const datatype = /^timestamp/i.test(opts?.fieldData?.datatype) ? "timestamp" : "date";
873
+ const value = datatype === "timestamp" ? toISOString(rule.value).replaceAll("T", " ").replace("Z", " UTC") : toISOStringDateOnly(rule.value);
874
+ return defaultValueProcessorByRule({
875
+ ...rule,
876
+ value
877
+ }, {
878
+ ...opts,
879
+ wrapValueWith: [datatype, ``]
880
+ });
881
+ };
882
+ /**
883
+ * Generates a value processor with date/time features for use by {@link @react-querybuilder/core!formatQuery formatQuery} with
884
+ * the "sql" format and "postgresql" preset.
885
+ */
886
+ const getDatetimeValueProcessorPostgreSQL = ({ toISOStringDateOnly, toISOString }) => (rule, opts) => {
887
+ const datatype = /^timestamp/i.test(opts?.fieldData?.datatype) ? "timestamp" : "date";
888
+ const value = datatype === "timestamp" ? toISOString(rule.value) : toISOStringDateOnly(rule.value);
889
+ return defaultValueProcessorByRule({
890
+ ...rule,
891
+ value
892
+ }, {
893
+ ...opts,
894
+ wrapValueWith: [datatype, ``]
895
+ });
896
+ };
897
+ const presetToValueProcessorMap = {
898
+ ansi: getDatetimeValueProcessorANSI,
899
+ mssql: getDatetimeValueProcessorMSSQL,
900
+ mysql: getDatetimeValueProcessorMySQL,
901
+ oracle: getDatetimeValueProcessorOracle,
902
+ postgresql: getDatetimeValueProcessorPostgreSQL,
903
+ sqlite: getDatetimeValueProcessorANSI
904
+ };
905
+ /**
906
+ * Generates a rule processor with date/time features for use by {@link @react-querybuilder/core!formatQuery formatQuery} with
907
+ * the "sql" format.
908
+ */
909
+ const getDatetimeRuleProcessorSQL = (apiFns) => (rule, options) => {
910
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
911
+ const operator = mapSQLOperator(resolveDatetimeOperator(rule, opts));
912
+ const operatorLowerCase = lc(operator);
913
+ // v8 ignore next
914
+ const { quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", context = {} } = opts;
915
+ let finalValue = "";
916
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorSQL(rule, opts);
917
+ const valueProcessor = presetToValueProcessorMap[opts.preset](apiFns);
918
+ const quotedField = getQuotedFieldName(rule.field, {
919
+ quoteFieldNamesWith,
920
+ fieldIdentifierSeparator
921
+ });
922
+ const ruleValue = context.materializeRelativeDateTime ? materializeRelativeValues(apiFns, rule.value, opts) : rule.value;
923
+ const rawValues = Array.isArray(ruleValue) ? ruleValue : [ruleValue];
924
+ if (rawValues.some(isRelativeDateTimeValue)) {
925
+ const exprFor = (v) => {
926
+ if (isRelativeDateTimeValue(v)) return getRelativeDateTimeSQL(v, opts.preset, opts.fieldData?.datatype);
927
+ const dateVal = apiFns.toDate(v);
928
+ if (!apiFns.isValid(dateVal)) return void 0;
929
+ return valueProcessor({
930
+ field: rule.field,
931
+ operator: "=",
932
+ value: dateVal
933
+ }, {
934
+ ...opts,
935
+ context: { originalValue: v }
936
+ });
937
+ };
938
+ switch (operatorLowerCase) {
939
+ case "in":
940
+ case "not in": {
941
+ const exprs = rawValues.map(exprFor).filter((e) => e !== void 0);
942
+ // v8 ignore next -- a relative operand always yields an expression
943
+ if (exprs.length === 0) return "";
944
+ finalValue = `(${exprs.join(", ")})`;
945
+ break;
946
+ }
947
+ case "between":
948
+ case "not between": {
949
+ const first = exprFor(rawValues[0]);
950
+ const second = exprFor(rawValues[1]);
951
+ if (first === void 0 || second === void 0) return "";
952
+ finalValue = `${first} and ${second}`;
953
+ break;
954
+ }
955
+ default: {
956
+ const expr = exprFor(rawValues[0]);
957
+ // v8 ignore next -- a single relative operand always yields an expression
958
+ if (expr === void 0) return "";
959
+ finalValue = expr;
960
+ }
961
+ }
962
+ return `${quotedField} ${operator} ${finalValue}`.trim();
963
+ }
964
+ const valueAsDateArray = toArray(ruleValue, { retainEmptyStrings: false }).map((v) => [v, apiFns.toDate(v)]).filter((v) => apiFns.isValid(v[1]));
965
+ switch (operatorLowerCase) {
966
+ case "in":
967
+ case "not in":
968
+ if (valueAsDateArray.length === 0) return "";
969
+ finalValue = `(${valueAsDateArray.map((value) => valueProcessor({
970
+ field: rule.field,
971
+ operator: "=",
972
+ value: value[1]
973
+ }, {
974
+ ...opts,
975
+ context: { originalValue: value[0] }
976
+ })).join(", ")})`;
977
+ break;
978
+ case "between":
979
+ case "not between":
980
+ {
981
+ if (valueAsDateArray.length < 2) return "";
982
+ const [first, second] = valueAsDateArray;
983
+ finalValue = (apiFns.isBefore(first[1], second[1]) ? [first, second] : [second, first]).map(([originalValue, value]) => valueProcessor({
984
+ field: rule.field,
985
+ operator: "=",
986
+ value
987
+ }, {
988
+ ...opts,
989
+ context: { originalValue }
990
+ })).join(" and ");
991
+ }
992
+ break;
993
+ default: {
994
+ const [originalValue, value] = valueAsDateArray[0] ?? ["", ""];
995
+ finalValue = valueProcessor({
996
+ field: rule.field,
997
+ operator: "=",
998
+ value
999
+ }, {
1000
+ ...opts,
1001
+ context: { originalValue }
1002
+ });
1003
+ }
1004
+ }
1005
+ return `${quotedField} ${operator} ${finalValue}`.trim();
1006
+ };
1007
+ //#endregion
1008
+ //#region src/getDatetimeRuleProcessorTanStackDB.ts
1009
+ /**
1010
+ * Generates a rule processor with date/time features for use by
1011
+ * {@link @react-querybuilder/core!formatQuery formatQuery} with the "tanstack_db" format.
1012
+ * Relative values are materialized and all date/time values are converted to `Date`
1013
+ * objects (TanStack DB collection filters compare against native `Date` values).
1014
+ */
1015
+ const getDatetimeRuleProcessorTanStackDB = (apiFns) => (rule, options) => {
1016
+ const opts = options ?? ( /* v8 ignore start -- @preserve */ {});
1017
+ const { context = {} } = opts;
1018
+ if (rule.valueSource === "field" || !processIsDateField(context.isDateField, rule, opts)) return defaultRuleProcessorTanStackDB(rule, opts);
1019
+ const { operator, value } = materializeForExport(apiFns, rule, opts, true);
1020
+ return defaultRuleProcessorTanStackDB({
1021
+ ...rule,
1022
+ operator,
1023
+ value
1024
+ }, opts);
1025
+ };
1026
+ //#endregion
1027
+ export { resolveDatetimeOperator as A, getDatetimeRuleProcessorCypher as C, isISOStringDateOnly as D, isDateOnlyDatatype as E, isRelativeDateTimeValue as O, getDatetimeRuleProcessorDrizzle as S, getDatetimeJsonLogicOperations as T, getDatetimeRuleProcessorMongoDBQuery as _, getDatetimeValueProcessorMySQL as a, getDatetimeRuleProcessorGremlin as b, getDatetimeRuleProcessorSpEL as c, getDatetimeRuleProcessorPrisma as d, getDatetimeRuleProcessorParameterized as f, getDatetimeRuleProcessorMongoDB as g, getDatetimeRuleProcessorNL as h, getDatetimeValueProcessorMSSQL as i, processIsDateField as k, getDatetimeRuleProcessorSPARQL as l, defaultDateTimeNLOperatorMap as m, getDatetimeRuleProcessorSQL as n, getDatetimeValueProcessorOracle as o, datetimeValueProcessorNL as p, getDatetimeValueProcessorANSI as r, getDatetimeValueProcessorPostgreSQL as s, getDatetimeRuleProcessorTanStackDB as t, getDatetimeRuleProcessorSequelize as u, getDatetimeRuleProcessorLDAP as v, getDatetimeRuleProcessorCEL as w, getDatetimeRuleProcessorElasticSearch as x, getDatetimeRuleProcessorJSONata as y };
1028
+
1029
+ //# sourceMappingURL=getDatetimeRuleProcessorTanStackDB-BcOC-o2A.mjs.map