@react-querybuilder/datetime 8.18.0 → 8.19.1
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/cjs/getDatetimeRuleProcessorTanStackDB-CL79A1_x.js +1208 -0
- package/dist/cjs/getDatetimeRuleProcessorTanStackDB-CL79A1_x.js.map +1 -0
- package/dist/cjs/getDatetimeRuleProcessorTanStackDB-DgUg_arY.js +2 -0
- package/dist/cjs/getDatetimeRuleProcessorTanStackDB-DgUg_arY.js.map +1 -0
- package/dist/cjs/react-querybuilder_datetime.cjs.development.d.ts +214 -8
- package/dist/cjs/react-querybuilder_datetime.cjs.development.date-fns.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.development.date-fns.js +93 -15
- package/dist/cjs/react-querybuilder_datetime.cjs.development.date-fns.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.development.dayjs.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.development.dayjs.js +70 -59
- package/dist/cjs/react-querybuilder_datetime.cjs.development.dayjs.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.development.js +482 -71
- package/dist/cjs/react-querybuilder_datetime.cjs.development.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.development.jsdate.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.development.jsdate.js +129 -15
- package/dist/cjs/react-querybuilder_datetime.cjs.development.jsdate.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.development.luxon.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.development.luxon.js +81 -15
- package/dist/cjs/react-querybuilder_datetime.cjs.development.luxon.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.d.ts +214 -8
- package/dist/cjs/react-querybuilder_datetime.cjs.production.date-fns.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.production.date-fns.js +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.date-fns.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.dayjs.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.production.dayjs.js +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.dayjs.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.js +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.jsdate.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.production.jsdate.js +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.jsdate.js.map +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.luxon.d.ts +46 -2
- package/dist/cjs/react-querybuilder_datetime.cjs.production.luxon.js +1 -1
- package/dist/cjs/react-querybuilder_datetime.cjs.production.luxon.js.map +1 -1
- package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-BfILPx88.js +2 -0
- package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-BfILPx88.js.map +1 -0
- package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-CzLh_zi9.js +63 -0
- package/dist/cjs/rqbDateTimeLibraryAPI.dayjs-CzLh_zi9.js.map +1 -0
- package/dist/cjs/types-XYMw0jFT.d.ts +265 -0
- package/dist/datetime-layout.css +1 -0
- package/dist/datetime-layout.css.map +1 -0
- package/dist/datetime-layout.scss +3 -0
- package/dist/datetime.css +1 -0
- package/dist/datetime.css.map +1 -0
- package/dist/datetime.scss +1 -0
- package/dist/getDatetimeRuleProcessorTanStackDB-BcOC-o2A.mjs +1029 -0
- package/dist/getDatetimeRuleProcessorTanStackDB-BcOC-o2A.mjs.map +1 -0
- package/dist/getDatetimeRuleProcessorTanStackDB-Dloxv6k2.mjs +2 -0
- package/dist/getDatetimeRuleProcessorTanStackDB-Dloxv6k2.mjs.map +1 -0
- package/dist/getDatetimeRuleProcessorTanStackDB-LDwhMJg0.js +1035 -0
- package/dist/getDatetimeRuleProcessorTanStackDB-LDwhMJg0.js.map +1 -0
- package/dist/react-querybuilder_datetime.d.mts +214 -8
- package/dist/react-querybuilder_datetime.date-fns.d.mts +46 -2
- package/dist/react-querybuilder_datetime.date-fns.mjs +71 -4
- package/dist/react-querybuilder_datetime.date-fns.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.dayjs.d.mts +46 -2
- package/dist/react-querybuilder_datetime.dayjs.mjs +47 -24
- package/dist/react-querybuilder_datetime.dayjs.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.jsdate.d.mts +46 -2
- package/dist/react-querybuilder_datetime.jsdate.mjs +106 -3
- package/dist/react-querybuilder_datetime.jsdate.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.legacy-esm.d.ts +214 -8
- package/dist/react-querybuilder_datetime.legacy-esm.date-fns.d.ts +46 -2
- package/dist/react-querybuilder_datetime.legacy-esm.date-fns.js +71 -4
- package/dist/react-querybuilder_datetime.legacy-esm.date-fns.js.map +1 -1
- package/dist/react-querybuilder_datetime.legacy-esm.dayjs.d.ts +46 -2
- package/dist/react-querybuilder_datetime.legacy-esm.dayjs.js +47 -24
- package/dist/react-querybuilder_datetime.legacy-esm.dayjs.js.map +1 -1
- package/dist/react-querybuilder_datetime.legacy-esm.js +425 -58
- package/dist/react-querybuilder_datetime.legacy-esm.js.map +1 -1
- package/dist/react-querybuilder_datetime.legacy-esm.jsdate.d.ts +46 -2
- package/dist/react-querybuilder_datetime.legacy-esm.jsdate.js +106 -3
- package/dist/react-querybuilder_datetime.legacy-esm.jsdate.js.map +1 -1
- package/dist/react-querybuilder_datetime.legacy-esm.luxon.d.ts +46 -2
- package/dist/react-querybuilder_datetime.legacy-esm.luxon.js +58 -3
- package/dist/react-querybuilder_datetime.legacy-esm.luxon.js.map +1 -1
- package/dist/react-querybuilder_datetime.luxon.d.mts +46 -2
- package/dist/react-querybuilder_datetime.luxon.mjs +58 -3
- package/dist/react-querybuilder_datetime.luxon.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.mjs +443 -57
- package/dist/react-querybuilder_datetime.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.production.d.mts +214 -8
- package/dist/react-querybuilder_datetime.production.date-fns.d.mts +46 -2
- package/dist/react-querybuilder_datetime.production.date-fns.mjs +1 -1
- package/dist/react-querybuilder_datetime.production.date-fns.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.production.dayjs.d.mts +46 -2
- package/dist/react-querybuilder_datetime.production.dayjs.mjs +1 -1
- package/dist/react-querybuilder_datetime.production.dayjs.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.production.jsdate.d.mts +46 -2
- package/dist/react-querybuilder_datetime.production.jsdate.mjs +1 -1
- package/dist/react-querybuilder_datetime.production.jsdate.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.production.luxon.d.mts +46 -2
- package/dist/react-querybuilder_datetime.production.luxon.mjs +1 -1
- package/dist/react-querybuilder_datetime.production.luxon.mjs.map +1 -1
- package/dist/react-querybuilder_datetime.production.mjs +1 -1
- package/dist/react-querybuilder_datetime.production.mjs.map +1 -1
- package/dist/rqbDateTimeLibraryAPI.dayjs-BW7faYFD.mjs +29 -0
- package/dist/rqbDateTimeLibraryAPI.dayjs-BW7faYFD.mjs.map +1 -0
- package/dist/rqbDateTimeLibraryAPI.dayjs-BoX90aqZ.mjs +2 -0
- package/dist/rqbDateTimeLibraryAPI.dayjs-BoX90aqZ.mjs.map +1 -0
- package/dist/rqbDateTimeLibraryAPI.dayjs-DvFSxPKu.js +29 -0
- package/dist/rqbDateTimeLibraryAPI.dayjs-DvFSxPKu.js.map +1 -0
- package/dist/styles/_layout.scss +30 -0
- package/dist/styles/_root.scss +5 -0
- package/dist/styles/_variables.scss +8 -0
- package/dist/types-CdjHqQ0k.d.mts +265 -0
- package/dist/types-CdjHqQ0k.d.ts +265 -0
- package/package.json +28 -13
- package/dist/cjs/getDatetimeRuleProcessorSQL-Cca9pzSn.js +0 -2
- package/dist/cjs/getDatetimeRuleProcessorSQL-Cca9pzSn.js.map +0 -1
- package/dist/cjs/getDatetimeRuleProcessorSQL-CrA2ZrSe.js +0 -563
- package/dist/cjs/getDatetimeRuleProcessorSQL-CrA2ZrSe.js.map +0 -1
- package/dist/cjs/types-c6_k1Tpr.d.ts +0 -105
- package/dist/getDatetimeRuleProcessorSQL-Crw01Jo-.js +0 -482
- package/dist/getDatetimeRuleProcessorSQL-Crw01Jo-.js.map +0 -1
- package/dist/getDatetimeRuleProcessorSQL-CvGKzojM.mjs +0 -2
- package/dist/getDatetimeRuleProcessorSQL-CvGKzojM.mjs.map +0 -1
- package/dist/getDatetimeRuleProcessorSQL-Nz_XjNeY.mjs +0 -468
- package/dist/getDatetimeRuleProcessorSQL-Nz_XjNeY.mjs.map +0 -1
- package/dist/types-c6_k1Tpr.d.mts +0 -105
- package/dist/types-c6_k1Tpr.d.ts +0 -105
|
@@ -0,0 +1,1208 @@
|
|
|
1
|
+
let react_querybuilder = require("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 (0, react_querybuilder.defaultRuleProcessorCEL)(rule, opts);
|
|
146
|
+
const ts = (d) => `timestamp("${apiFns.toISOString(d)}")`;
|
|
147
|
+
const value = materializeRelativeValues(apiFns, rule.value, opts);
|
|
148
|
+
const operatorTL = (0, react_querybuilder.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 = (0, react_querybuilder.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 (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorCypher)(rule, opts);
|
|
198
|
+
const { field } = rule;
|
|
199
|
+
const operatorTL = (0, react_querybuilder.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 = (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorDrizzle)(rule, opts);
|
|
241
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts, true);
|
|
242
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorElasticSearch)(rule, opts);
|
|
260
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts);
|
|
261
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorGremlin)(rule, opts);
|
|
279
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts);
|
|
280
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorJSONata)(rule, opts);
|
|
302
|
+
const valueIsField = valueSource === "field";
|
|
303
|
+
const value = valueIsField ? rule.value : materializeRelativeValues(apiFns, rule.value, opts);
|
|
304
|
+
const fldToMs = (f) => `$toMillis(${(0, react_querybuilder.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 = (0, react_querybuilder.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 || (0, react_querybuilder.nullOrUndefinedOrEmpty)(valueAsArray[0]) || (0, react_querybuilder.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 (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorLDAP)(rule, opts);
|
|
356
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts);
|
|
357
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.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]: { [react_querybuilder.mongoOperators[operator]]: apiFns.toDate(value) } };
|
|
382
|
+
}
|
|
383
|
+
const valueAsDateArray = (0, react_querybuilder.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]: { [react_querybuilder.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 (0, react_querybuilder.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 = (0, react_querybuilder.lc)(operator);
|
|
450
|
+
let finalValue = "";
|
|
451
|
+
// v8 ignore next
|
|
452
|
+
const { fieldData, quoteFieldNamesWith = ["", ""], fieldIdentifierSeparator = "", operatorProcessor = react_querybuilder.defaultOperatorProcessorNL, wordOrder = "SVO", context = {}, operatorMap = defaultDateTimeNLOperatorMap } = opts;
|
|
453
|
+
if (!processIsDateField(context.isDateField, rule, opts)) return (0, react_querybuilder.defaultRuleProcessorNL)(rule, opts);
|
|
454
|
+
if (rule.valueSource === "field") return (0, react_querybuilder.defaultRuleProcessorNL)(rule, {
|
|
455
|
+
...opts,
|
|
456
|
+
operatorMap: defaultDateTimeNLOperatorMap
|
|
457
|
+
});
|
|
458
|
+
if ((operatorLowerCase === "in" || operatorLowerCase === "notin" || operatorLowerCase === "between" || operatorLowerCase === "notbetween") && !rule.value) return "";
|
|
459
|
+
const valueAsDateArray = (0, react_querybuilder.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: (0, react_querybuilder.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 (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorParameterized)(rule, opts, meta);
|
|
540
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts);
|
|
541
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorPrisma)(rule, opts);
|
|
559
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts, true);
|
|
560
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorSequelize)(rule, opts);
|
|
578
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts, true);
|
|
579
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorSPARQL)(rule, opts);
|
|
608
|
+
const { field: rawField, value } = rule;
|
|
609
|
+
const operator = resolveDatetimeOperator(rule, opts);
|
|
610
|
+
const field = (0, react_querybuilder.sparqlVar)(rawField);
|
|
611
|
+
const operatorTL = (0, react_querybuilder.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 = (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorSpEL)(rule, opts);
|
|
653
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts);
|
|
654
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.defaultValueProcessorByRule)({
|
|
829
|
+
...rule,
|
|
830
|
+
value: toISOStringDateOnly(rule.value)
|
|
831
|
+
}, opts);
|
|
832
|
+
return (0, react_querybuilder.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 (0, react_querybuilder.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 (0, react_querybuilder.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 (0, react_querybuilder.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 (0, react_querybuilder.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 = (0, react_querybuilder.mapSQLOperator)(resolveDatetimeOperator(rule, opts));
|
|
912
|
+
const operatorLowerCase = (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorSQL)(rule, opts);
|
|
917
|
+
const valueProcessor = presetToValueProcessorMap[opts.preset](apiFns);
|
|
918
|
+
const quotedField = (0, react_querybuilder.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 = (0, react_querybuilder.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 (0, react_querybuilder.defaultRuleProcessorTanStackDB)(rule, opts);
|
|
1019
|
+
const { operator, value } = materializeForExport(apiFns, rule, opts, true);
|
|
1020
|
+
return (0, react_querybuilder.defaultRuleProcessorTanStackDB)({
|
|
1021
|
+
...rule,
|
|
1022
|
+
operator,
|
|
1023
|
+
value
|
|
1024
|
+
}, opts);
|
|
1025
|
+
};
|
|
1026
|
+
//#endregion
|
|
1027
|
+
Object.defineProperty(exports, "datetimeValueProcessorNL", {
|
|
1028
|
+
enumerable: true,
|
|
1029
|
+
get: function() {
|
|
1030
|
+
return datetimeValueProcessorNL;
|
|
1031
|
+
}
|
|
1032
|
+
});
|
|
1033
|
+
Object.defineProperty(exports, "defaultDateTimeNLOperatorMap", {
|
|
1034
|
+
enumerable: true,
|
|
1035
|
+
get: function() {
|
|
1036
|
+
return defaultDateTimeNLOperatorMap;
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
Object.defineProperty(exports, "getDatetimeJsonLogicOperations", {
|
|
1040
|
+
enumerable: true,
|
|
1041
|
+
get: function() {
|
|
1042
|
+
return getDatetimeJsonLogicOperations;
|
|
1043
|
+
}
|
|
1044
|
+
});
|
|
1045
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorCEL", {
|
|
1046
|
+
enumerable: true,
|
|
1047
|
+
get: function() {
|
|
1048
|
+
return getDatetimeRuleProcessorCEL;
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
1051
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorCypher", {
|
|
1052
|
+
enumerable: true,
|
|
1053
|
+
get: function() {
|
|
1054
|
+
return getDatetimeRuleProcessorCypher;
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorDrizzle", {
|
|
1058
|
+
enumerable: true,
|
|
1059
|
+
get: function() {
|
|
1060
|
+
return getDatetimeRuleProcessorDrizzle;
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorElasticSearch", {
|
|
1064
|
+
enumerable: true,
|
|
1065
|
+
get: function() {
|
|
1066
|
+
return getDatetimeRuleProcessorElasticSearch;
|
|
1067
|
+
}
|
|
1068
|
+
});
|
|
1069
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorGremlin", {
|
|
1070
|
+
enumerable: true,
|
|
1071
|
+
get: function() {
|
|
1072
|
+
return getDatetimeRuleProcessorGremlin;
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
1075
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorJSONata", {
|
|
1076
|
+
enumerable: true,
|
|
1077
|
+
get: function() {
|
|
1078
|
+
return getDatetimeRuleProcessorJSONata;
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorLDAP", {
|
|
1082
|
+
enumerable: true,
|
|
1083
|
+
get: function() {
|
|
1084
|
+
return getDatetimeRuleProcessorLDAP;
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorMongoDB", {
|
|
1088
|
+
enumerable: true,
|
|
1089
|
+
get: function() {
|
|
1090
|
+
return getDatetimeRuleProcessorMongoDB;
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorMongoDBQuery", {
|
|
1094
|
+
enumerable: true,
|
|
1095
|
+
get: function() {
|
|
1096
|
+
return getDatetimeRuleProcessorMongoDBQuery;
|
|
1097
|
+
}
|
|
1098
|
+
});
|
|
1099
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorNL", {
|
|
1100
|
+
enumerable: true,
|
|
1101
|
+
get: function() {
|
|
1102
|
+
return getDatetimeRuleProcessorNL;
|
|
1103
|
+
}
|
|
1104
|
+
});
|
|
1105
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorParameterized", {
|
|
1106
|
+
enumerable: true,
|
|
1107
|
+
get: function() {
|
|
1108
|
+
return getDatetimeRuleProcessorParameterized;
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorPrisma", {
|
|
1112
|
+
enumerable: true,
|
|
1113
|
+
get: function() {
|
|
1114
|
+
return getDatetimeRuleProcessorPrisma;
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorSPARQL", {
|
|
1118
|
+
enumerable: true,
|
|
1119
|
+
get: function() {
|
|
1120
|
+
return getDatetimeRuleProcessorSPARQL;
|
|
1121
|
+
}
|
|
1122
|
+
});
|
|
1123
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorSQL", {
|
|
1124
|
+
enumerable: true,
|
|
1125
|
+
get: function() {
|
|
1126
|
+
return getDatetimeRuleProcessorSQL;
|
|
1127
|
+
}
|
|
1128
|
+
});
|
|
1129
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorSequelize", {
|
|
1130
|
+
enumerable: true,
|
|
1131
|
+
get: function() {
|
|
1132
|
+
return getDatetimeRuleProcessorSequelize;
|
|
1133
|
+
}
|
|
1134
|
+
});
|
|
1135
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorSpEL", {
|
|
1136
|
+
enumerable: true,
|
|
1137
|
+
get: function() {
|
|
1138
|
+
return getDatetimeRuleProcessorSpEL;
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
Object.defineProperty(exports, "getDatetimeRuleProcessorTanStackDB", {
|
|
1142
|
+
enumerable: true,
|
|
1143
|
+
get: function() {
|
|
1144
|
+
return getDatetimeRuleProcessorTanStackDB;
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
Object.defineProperty(exports, "getDatetimeValueProcessorANSI", {
|
|
1148
|
+
enumerable: true,
|
|
1149
|
+
get: function() {
|
|
1150
|
+
return getDatetimeValueProcessorANSI;
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
Object.defineProperty(exports, "getDatetimeValueProcessorMSSQL", {
|
|
1154
|
+
enumerable: true,
|
|
1155
|
+
get: function() {
|
|
1156
|
+
return getDatetimeValueProcessorMSSQL;
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
1159
|
+
Object.defineProperty(exports, "getDatetimeValueProcessorMySQL", {
|
|
1160
|
+
enumerable: true,
|
|
1161
|
+
get: function() {
|
|
1162
|
+
return getDatetimeValueProcessorMySQL;
|
|
1163
|
+
}
|
|
1164
|
+
});
|
|
1165
|
+
Object.defineProperty(exports, "getDatetimeValueProcessorOracle", {
|
|
1166
|
+
enumerable: true,
|
|
1167
|
+
get: function() {
|
|
1168
|
+
return getDatetimeValueProcessorOracle;
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
Object.defineProperty(exports, "getDatetimeValueProcessorPostgreSQL", {
|
|
1172
|
+
enumerable: true,
|
|
1173
|
+
get: function() {
|
|
1174
|
+
return getDatetimeValueProcessorPostgreSQL;
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1177
|
+
Object.defineProperty(exports, "isDateOnlyDatatype", {
|
|
1178
|
+
enumerable: true,
|
|
1179
|
+
get: function() {
|
|
1180
|
+
return isDateOnlyDatatype;
|
|
1181
|
+
}
|
|
1182
|
+
});
|
|
1183
|
+
Object.defineProperty(exports, "isISOStringDateOnly", {
|
|
1184
|
+
enumerable: true,
|
|
1185
|
+
get: function() {
|
|
1186
|
+
return isISOStringDateOnly;
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1189
|
+
Object.defineProperty(exports, "isRelativeDateTimeValue", {
|
|
1190
|
+
enumerable: true,
|
|
1191
|
+
get: function() {
|
|
1192
|
+
return isRelativeDateTimeValue;
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
Object.defineProperty(exports, "processIsDateField", {
|
|
1196
|
+
enumerable: true,
|
|
1197
|
+
get: function() {
|
|
1198
|
+
return processIsDateField;
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
Object.defineProperty(exports, "resolveDatetimeOperator", {
|
|
1202
|
+
enumerable: true,
|
|
1203
|
+
get: function() {
|
|
1204
|
+
return resolveDatetimeOperator;
|
|
1205
|
+
}
|
|
1206
|
+
});
|
|
1207
|
+
|
|
1208
|
+
//# sourceMappingURL=getDatetimeRuleProcessorTanStackDB-CL79A1_x.js.map
|