n8n-nodes-lifespace 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -128,8 +128,8 @@ Ordinary Record CRUD/Action routes remain model-contract surfaces derived from p
128
128
  New Workflow and Agent configurations expose one query model:
129
129
 
130
130
  - **Search** is a top-level retrieval facet when the selected Record Type publishes searchable fields.
131
- - **Filters** use a grouped human builder over `query.canonical.filter.targets`. Ordinary conditions render inline as separate **Field**, **Operator**, and string/expression **Value** controls. Field choices come from Discovery; Operator choices reload from Discovery for the selected field using n8n's row-relative dynamic-option dependency. The adapter parses number/integer/boolean values and canonical JSON operands back into the typed Canonical Filter AST.
132
- - **Match** supports top-level All/Any composition, with one level of nested Condition Groups that each have their own All/Any rule.
131
+ - **Filters** expose only Filter Groups. Each group has its own **Match: All / Any** and vertically stacked **Field**, **Operator**, and string/expression **Value** controls; multiple groups compose with AND. Field choices come from Discovery, and Operator choices reload from the selected field using n8n's row-relative dynamic-option dependency.
132
+ - Temporal range **Overlaps** is projected for human workflows as paired **Overlaps Start** + **Overlaps End** conditions in the same group. The adapter validates the pair and lowers it to one canonical `overlaps` range predicate. Date pairs use the current n8n workflow timezone unless **Options → Viewing Timezone** overrides it.
133
133
  - **Sorts** come from `query.canonical.sort.fields` and preserve user priority.
134
134
  - **Return All**, **Limit**, and the optional opaque **Cursor** use canonical cursor pagination.
135
135
 
@@ -157,7 +157,9 @@ Two boundaries are intentional:
157
157
  - **Resource** and **Operation** are structural node controls and do not accept expressions because they determine which parameter schema and execution path the node has.
158
158
  - **Fields** and **Action Input** remain generated from Runtime Discovery. **Filters** use Discovery-backed field/operator selectors plus string/expression values so Boolean grouping does not depend on dynamically changing n8n value-control types.
159
159
 
160
- For List / Query, **Filters** is a Discovery-driven grouped condition builder. Ordinary conditions render inline in the wide parameter pane instead of as expandable fixed-collection cards. Each row has separate **Field**, **Operator**, and **Value** controls; changing Field reloads only the operators published for that field. Value remains text or an n8n expression. The adapter deterministically converts that text back to the canonical typed value before the request. Structured Range/TemporalRange/`within` operands use canonical JSON text in this first builder version. Condition Groups remain explicit containers because they represent nested Boolean structure; their member conditions use the same inline row layout. **Sorts** remains an ordered structural list because sort priority is part of workflow structure rather than per-item data.
160
+ For List / Query, **Filters** is a Discovery-driven group builder. There are no separate top-level Match or Conditions surfaces: every condition belongs to a Filter Group, each group chooses All/Any, and groups are ANDed together. Conditions use the same vertical layout as n8n's Data Table filters: **Field**, then **Operator**, then **Value**. Changing Field reloads only the operators published for that field. Scalar values remain text or n8n expressions and are deterministically converted back to canonical typed values before the request.
161
+
162
+ For TemporalRange fields, the human projection does not ask for JSON. Canonical `overlaps` is split into **Overlaps Start** and **Overlaps End** inputs; they must appear once each in the same Filter Group and are lowered back to one canonical `overlaps` predicate. Human date End values are inclusive, so the adapter converts them to Core's exclusive end boundary. `before` and `after` accept a single date or absolute RFC3339 date-time string. `contains` remains executable for stored workflows but is not offered in the new Human UI until it has an equally simple structured projection. **Options → Viewing Timezone** is optional; TemporalRange date interpretation and sorting fall back to the effective n8n workflow timezone when it is omitted. **Sorts** remains an ordered structural list because sort priority is part of workflow structure rather than per-item data.
161
163
 
162
164
  If **Record Type** itself varies per input item and those Record Types have different schemas, one discovery-generated mapper cannot safely represent every possible schema at design time. In that case, branch to separate LifeSpace nodes per schema or use **API Request** for a deliberately fully dynamic request.
163
165
 
@@ -37,56 +37,26 @@ function filterConditionValues() {
37
37
  name: 'value',
38
38
  type: 'string',
39
39
  default: '',
40
- description: 'Enter a scalar value as text. Number, integer and boolean values are parsed by the adapter. For Range, TemporalRange and Within operands, enter the canonical JSON object. Is Empty and Is Not Empty ignore this value.',
40
+ displayOptions: {
41
+ hide: {
42
+ operator: [{ _cnd: { regex: '^lsqh1:(?:isNull|isNotNull)\\.' } }],
43
+ },
44
+ },
45
+ description: 'Enter a string or n8n expression. Number and boolean values are parsed by the adapter. Temporal range Overlaps uses paired Overlaps Start and Overlaps End conditions; Before and After accept a date or absolute date-time string.',
41
46
  },
42
47
  ];
43
48
  }
44
- function filterConditionsProperty() {
45
- return {
46
- displayName: 'Conditions',
47
- name: 'queryFilterConditions',
48
- type: 'fixedCollection',
49
- default: {},
50
- placeholder: 'Add Condition',
51
- typeOptions: {
52
- multipleValues: true,
53
- multipleValueButtonText: 'Add Condition',
54
- fixedCollection: { layout: 'inline' },
55
- },
56
- displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
57
- options: [{
58
- displayName: 'Condition',
59
- name: 'condition',
60
- values: filterConditionValues(),
61
- }],
62
- description: 'Top-level filter conditions. The Match setting determines whether all or any top-level conditions and groups must match.',
63
- };
64
- }
65
- function filterMatchProperty() {
66
- return {
67
- displayName: 'Match',
68
- name: 'queryFilterMatch',
69
- type: 'options',
70
- options: [
71
- { name: 'All Conditions and Groups', value: 'all' },
72
- { name: 'Any Condition or Group', value: 'any' },
73
- ],
74
- default: 'all',
75
- displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
76
- description: 'How top-level Conditions and Groups are combined',
77
- };
78
- }
79
49
  function filterGroupsProperty() {
80
50
  return {
81
- displayName: 'Condition Groups',
51
+ displayName: 'Filters',
82
52
  name: 'queryFilterGroups',
83
53
  type: 'fixedCollection',
84
54
  default: {},
85
- placeholder: 'Add Condition Group',
55
+ placeholder: 'Add Filter Group',
86
56
  typeOptions: { multipleValues: true },
87
57
  displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
88
58
  options: [{
89
- displayName: 'Condition Group',
59
+ displayName: 'Filter Group',
90
60
  name: 'group',
91
61
  values: [
92
62
  {
@@ -108,7 +78,6 @@ function filterGroupsProperty() {
108
78
  typeOptions: {
109
79
  multipleValues: true,
110
80
  multipleValueButtonText: 'Add Condition',
111
- fixedCollection: { layout: 'inline' },
112
81
  },
113
82
  options: [{
114
83
  displayName: 'Condition',
@@ -118,21 +87,21 @@ function filterGroupsProperty() {
118
87
  },
119
88
  ],
120
89
  }],
121
- description: 'Add one level of nested Boolean groups. Each group has its own All/Any match rule and participates in the top-level Match rule.',
90
+ description: 'Add Filter Groups. Conditions inside a group use All or Any; multiple Filter Groups are combined with AND.',
122
91
  };
123
92
  }
124
- function queryViewingTimezoneProperty() {
93
+ function queryViewingTimezoneOption() {
125
94
  return {
126
95
  displayName: 'Viewing Timezone',
127
- name: 'queryViewingTimezone',
96
+ name: 'viewingTimezone',
128
97
  type: 'string',
129
98
  default: '',
130
99
  placeholder: 'Asia/Shanghai',
131
- displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } },
132
- description: 'IANA timezone used only when a TemporalRange field is sorted. LifeSpace requires this context to compare date and instant variants deterministically.',
100
+ description: 'Optional IANA timezone override for temporal range date interpretation and sorting. If omitted, the current n8n workflow timezone is used.',
133
101
  };
134
102
  }
135
103
  function humanProperties(properties) {
104
+ var _a;
136
105
  const result = [];
137
106
  for (const property of properties) {
138
107
  if ([
@@ -172,11 +141,18 @@ function humanProperties(properties) {
172
141
  continue;
173
142
  }
174
143
  if (property.name === 'search') {
175
- result.push({ ...property, displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } } }, filterMatchProperty(), filterConditionsProperty(), filterGroupsProperty());
144
+ result.push({ ...property, displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } } }, filterGroupsProperty());
176
145
  continue;
177
146
  }
178
147
  if (property.name === 'sorts') {
179
- result.push({ ...property, displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } } }, queryViewingTimezoneProperty());
148
+ result.push({ ...property, displayOptions: { show: { resource: ['modelRecord'], operation: ['list'] } } });
149
+ continue;
150
+ }
151
+ if (property.name === 'options') {
152
+ result.push({
153
+ ...property,
154
+ options: [...((_a = property.options) !== null && _a !== void 0 ? _a : []), queryViewingTimezoneOption()],
155
+ });
180
156
  continue;
181
157
  }
182
158
  result.push(property);
@@ -214,7 +190,6 @@ class LifeSpaceWorkflow extends LifeSpace_node_1.LifeSpace {
214
190
  dark: 'file:lifespace.dark.svg',
215
191
  },
216
192
  description: 'Use LifeSpace in human-authored n8n workflows',
217
- parameterPane: 'wide',
218
193
  properties: humanProperties(description.properties),
219
194
  };
220
195
  const node = this;
@@ -226,6 +201,7 @@ class LifeSpaceWorkflow extends LifeSpace_node_1.LifeSpace {
226
201
  getCanonicalFilterOperators: humanProjection_1.getCanonicalFilterOperators,
227
202
  getCanonicalFilterOptions: humanProjection_1.getCanonicalFilterOptions,
228
203
  getCanonicalTimeWindowFields: humanProjection_1.getCanonicalTimeWindowFields,
204
+ getSortableFields: humanProjection_1.getHumanSortableFields,
229
205
  },
230
206
  resourceMapping: {
231
207
  ...((_e = (_d = node.methods) === null || _d === void 0 ? void 0 : _d.resourceMapping) !== null && _e !== void 0 ? _e : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"LifeSpaceWorkflow.node.js","sourceRoot":"","sources":["../../../nodes/LifeSpaceWorkflow/LifeSpaceWorkflow.node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LifeSpaceWorkflow.node.js","sourceRoot":"","sources":["../../../nodes/LifeSpaceWorkflow/LifeSpaceWorkflow.node.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,11 @@
1
1
  import type { IDataObject, IExecuteFunctions, ILoadOptionsFunctions, INodePropertyOptions, ResourceMapperField, ResourceMapperFields } from 'n8n-workflow';
2
+ import { type QueryPredicate } from '../shared/lifeSpaceQuerySemantics';
2
3
  export declare function getHumanRecordFields(this: ILoadOptionsFunctions): Promise<ResourceMapperFields>;
3
4
  export declare function getHumanActionInputFields(this: ILoadOptionsFunctions): Promise<ResourceMapperFields>;
4
5
  export declare function getCanonicalFilterFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
6
+ export declare function humanFilterOperatorSelector(predicate: QueryPredicate, role?: string): string;
7
+ export declare function temporalSortFieldSelector(field: string): string;
8
+ export declare function getHumanSortableFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
5
9
  export declare function getCanonicalFilterOperators(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
6
10
  export declare function getCanonicalFilterOptions(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
11
  export declare function getHumanQueryFilterFields(this: ILoadOptionsFunctions): Promise<ResourceMapperFields>;
@@ -15,7 +19,7 @@ export type CanonicalFilter = {
15
19
  } | {
16
20
  or: CanonicalFilter[];
17
21
  };
18
- export declare function projectHumanFilterBuilder(context: Pick<IExecuteFunctions, 'getNode'>, match: unknown, conditions: unknown, groups: unknown): CanonicalFilter[];
22
+ export declare function projectHumanFilterBuilder(context: Pick<IExecuteFunctions, 'getNode'>, match: unknown, conditions: unknown, groups: unknown, timezone?: string): CanonicalFilter[];
19
23
  export declare function projectQueryFilters(value: unknown): CanonicalFilter[];
20
24
  export declare function canonicalTimeWindowSelector(field: string, operator: string): string;
21
25
  export declare function getCanonicalTimeWindowFields(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getHumanRecordFields = getHumanRecordFields;
4
4
  exports.getHumanActionInputFields = getHumanActionInputFields;
5
5
  exports.getCanonicalFilterFields = getCanonicalFilterFields;
6
+ exports.humanFilterOperatorSelector = humanFilterOperatorSelector;
7
+ exports.temporalSortFieldSelector = temporalSortFieldSelector;
8
+ exports.getHumanSortableFields = getHumanSortableFields;
6
9
  exports.getCanonicalFilterOperators = getCanonicalFilterOperators;
7
10
  exports.getCanonicalFilterOptions = getCanonicalFilterOptions;
8
11
  exports.getHumanQueryFilterFields = getHumanQueryFilterFields;
@@ -131,6 +134,84 @@ async function getCanonicalFilterFields() {
131
134
  }
132
135
  return [...fields.entries()].map(([value, name]) => ({ name, value }));
133
136
  }
137
+ const HUMAN_OPERATOR_SELECTOR_PREFIX = 'lsqh1:';
138
+ const TEMPORAL_SORT_SELECTOR_PREFIX = 'lsqts1.';
139
+ function rangeLikeValueType(valueType) {
140
+ return [
141
+ 'range<date>',
142
+ 'range<instant>',
143
+ 'temporal_range',
144
+ 'date-range',
145
+ 'instant-range',
146
+ 'temporal-range',
147
+ ].includes(String(valueType));
148
+ }
149
+ function humanFilterOperatorSelector(predicate, role = predicate.operator) {
150
+ const payload = Buffer.from((0, lifeSpaceQuerySemantics_1.queryPredicateSelector)(predicate)).toString('base64url');
151
+ return `${HUMAN_OPERATOR_SELECTOR_PREFIX}${role}.${payload}`;
152
+ }
153
+ function parseHumanFilterOperatorSelector(value) {
154
+ const raw = String(value !== null && value !== void 0 ? value : '');
155
+ if (!raw.startsWith(HUMAN_OPERATOR_SELECTOR_PREFIX)) {
156
+ const predicate = (0, lifeSpaceQuerySemantics_1.parseQueryPredicateSelector)(raw);
157
+ return predicate ? { predicate } : null;
158
+ }
159
+ const rest = raw.slice(HUMAN_OPERATOR_SELECTOR_PREFIX.length);
160
+ const separator = rest.indexOf('.');
161
+ if (separator < 1)
162
+ return null;
163
+ const role = rest.slice(0, separator);
164
+ try {
165
+ const selector = Buffer.from(rest.slice(separator + 1), 'base64url').toString('utf8');
166
+ const predicate = (0, lifeSpaceQuerySemantics_1.parseQueryPredicateSelector)(selector);
167
+ if (!predicate)
168
+ return null;
169
+ if (role === 'overlapsStart')
170
+ return { predicate, overlapBoundary: 'start' };
171
+ if (role === 'overlapsEnd')
172
+ return { predicate, overlapBoundary: 'end' };
173
+ return role === predicate.operator ? { predicate } : null;
174
+ }
175
+ catch {
176
+ return null;
177
+ }
178
+ }
179
+ function temporalSortFieldSelector(field) {
180
+ return TEMPORAL_SORT_SELECTOR_PREFIX + Buffer.from(field).toString('base64url');
181
+ }
182
+ function parseTemporalSortFieldSelector(value) {
183
+ const raw = String(value !== null && value !== void 0 ? value : '').trim();
184
+ if (!raw.startsWith(TEMPORAL_SORT_SELECTOR_PREFIX))
185
+ return { field: raw, temporalRange: false };
186
+ try {
187
+ const field = Buffer.from(raw.slice(TEMPORAL_SORT_SELECTOR_PREFIX.length), 'base64url').toString('utf8').trim();
188
+ return { field, temporalRange: Boolean(field) };
189
+ }
190
+ catch {
191
+ return { field: raw, temporalRange: false };
192
+ }
193
+ }
194
+ async function getHumanSortableFields() {
195
+ var _a, _b, _c;
196
+ const selected = await selectedModel(this);
197
+ if (!selected)
198
+ return [];
199
+ const canonicalFields = (_a = selected.model.query.canonical) === null || _a === void 0 ? void 0 : _a.sort.fields;
200
+ const fields = (canonicalFields === null || canonicalFields === void 0 ? void 0 : canonicalFields.length)
201
+ ? canonicalFields
202
+ : [...selected.model.query.sort.envelopeFields, ...selected.model.query.sortable];
203
+ const temporalFields = new Set(((_c = (_b = selected.model.query.canonical) === null || _b === void 0 ? void 0 : _b.filter.targets) !== null && _c !== void 0 ? _c : [])
204
+ .filter((target) => ['temporal_range', 'temporal-range'].includes(String(target.valueType)))
205
+ .map((target) => target.field));
206
+ return [...new Set(fields)].map((fieldKey) => {
207
+ var _a;
208
+ const field = selected.model.fields.find((entry) => entry.key === fieldKey);
209
+ return {
210
+ name: ((_a = field === null || field === void 0 ? void 0 : field.title) === null || _a === void 0 ? void 0 : _a.trim()) || fieldKey,
211
+ value: temporalFields.has(fieldKey) ? temporalSortFieldSelector(fieldKey) : fieldKey,
212
+ };
213
+ });
214
+ }
134
215
  async function getCanonicalFilterOperators() {
135
216
  var _a;
136
217
  const selected = await selectedModel(this);
@@ -138,10 +219,20 @@ async function getCanonicalFilterOperators() {
138
219
  return [];
139
220
  const field = String((_a = this.getCurrentNodeParameter('&field')) !== null && _a !== void 0 ? _a : '').trim();
140
221
  const predicates = (0, lifeSpaceQuerySemantics_1.queryPredicates)(selected.model).filter((predicate) => !field || predicate.field === field);
141
- return predicates.map((predicate) => ({
142
- name: predicate.operatorLabel,
143
- value: (0, lifeSpaceQuerySemantics_1.queryPredicateSelector)(predicate),
144
- }));
222
+ const result = [];
223
+ for (const predicate of predicates) {
224
+ if (rangeLikeValueType(predicate.valueType) && predicate.operator === 'overlaps') {
225
+ result.push({ name: 'Overlaps Start', value: humanFilterOperatorSelector(predicate, 'overlapsStart') }, { name: 'Overlaps End', value: humanFilterOperatorSelector(predicate, 'overlapsEnd') });
226
+ continue;
227
+ }
228
+ if (rangeLikeValueType(predicate.valueType) && predicate.operator === 'contains')
229
+ continue;
230
+ result.push({
231
+ name: predicate.operatorLabel,
232
+ value: humanFilterOperatorSelector(predicate),
233
+ });
234
+ }
235
+ return result;
145
236
  }
146
237
  async function getCanonicalFilterOptions() {
147
238
  const selected = await selectedModel(this);
@@ -269,20 +360,93 @@ function structuredQueryValue(predicate) {
269
360
  return true;
270
361
  if (predicate.operator === 'kindIs')
271
362
  return false;
272
- return [
273
- 'range<date>',
274
- 'range<instant>',
275
- 'temporal_range',
276
- 'date-range',
277
- 'instant-range',
278
- 'temporal-range',
279
- ].includes(String(predicate.valueType));
363
+ return rangeLikeValueType(predicate.valueType);
364
+ }
365
+ function exactHumanDate(raw) {
366
+ if (!/^\d{4}-\d{2}-\d{2}$/u.test(raw))
367
+ return null;
368
+ const [year, month, day] = raw.split('-').map(Number);
369
+ const parsed = new Date(Date.UTC(year, month - 1, day));
370
+ if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() + 1 !== month || parsed.getUTCDate() !== day)
371
+ return null;
372
+ return raw;
373
+ }
374
+ function nextHumanDate(date) {
375
+ const [year, month, day] = date.split('-').map(Number);
376
+ const next = new Date(Date.UTC(year, month - 1, day + 1));
377
+ return next.toISOString().slice(0, 10);
378
+ }
379
+ function absoluteHumanInstant(raw) {
380
+ if (!/^\d{4}-\d{2}-\d{2}T.+(?:Z|[+-]\d{2}:\d{2})$/u.test(raw))
381
+ return null;
382
+ const time = Date.parse(raw);
383
+ return Number.isFinite(time) ? new Date(time).toISOString() : null;
384
+ }
385
+ function overlapWindowValue(context, field, startValue, endValue, timezone) {
386
+ const startRaw = String(startValue !== null && startValue !== void 0 ? startValue : '').trim();
387
+ const endRaw = String(endValue !== null && endValue !== void 0 ? endValue : '').trim();
388
+ const startDate = exactHumanDate(startRaw);
389
+ const endDate = exactHumanDate(endRaw);
390
+ if (startDate && endDate) {
391
+ if (endDate < startDate) {
392
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${field} Overlaps End must not be earlier than Overlaps Start`);
393
+ }
394
+ return {
395
+ kind: 'local_date_window',
396
+ startDate,
397
+ endDateExclusive: nextHumanDate(endDate),
398
+ timezone,
399
+ };
400
+ }
401
+ const startInstant = absoluteHumanInstant(startRaw);
402
+ const endInstant = absoluteHumanInstant(endRaw);
403
+ if (startInstant && endInstant) {
404
+ if (Date.parse(endInstant) <= Date.parse(startInstant)) {
405
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${field} Overlaps End must be later than Overlaps Start`);
406
+ }
407
+ return { kind: 'instant', start: startInstant, endExclusive: endInstant };
408
+ }
409
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${field} Overlaps Start and End must both be YYYY-MM-DD dates or both be absolute RFC3339 date-times`);
410
+ }
411
+ function singleRangeBoundaryValue(context, predicate, value, timezone) {
412
+ const raw = String(value !== null && value !== void 0 ? value : '').trim();
413
+ const date = exactHumanDate(raw);
414
+ if (date) {
415
+ return {
416
+ kind: 'local_date_window',
417
+ startDate: date,
418
+ endDateExclusive: nextHumanDate(date),
419
+ timezone,
420
+ };
421
+ }
422
+ const instant = absoluteHumanInstant(raw);
423
+ if (instant) {
424
+ const time = Date.parse(instant);
425
+ if (predicate.operator === 'before') {
426
+ return {
427
+ kind: 'instant',
428
+ start: instant,
429
+ endExclusive: new Date(time + 1).toISOString(),
430
+ };
431
+ }
432
+ if (predicate.operator === 'after') {
433
+ return {
434
+ kind: 'instant',
435
+ start: new Date(time - 1).toISOString(),
436
+ endExclusive: instant,
437
+ };
438
+ }
439
+ }
440
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${predicate.field} — ${predicate.operatorLabel} requires YYYY-MM-DD or an absolute RFC3339 date-time`);
280
441
  }
281
- function parseHumanFilterValue(context, predicate, value) {
442
+ function parseHumanFilterValue(context, predicate, value, timezone) {
282
443
  const raw = String(value !== null && value !== void 0 ? value : '').trim();
283
444
  if (!raw) {
284
445
  throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${predicate.field} — ${predicate.operatorLabel} requires a value`);
285
446
  }
447
+ if (rangeLikeValueType(predicate.valueType) && ['before', 'after'].includes(predicate.operator)) {
448
+ return singleRangeBoundaryValue(context, predicate, raw, timezone);
449
+ }
286
450
  if (structuredQueryValue(predicate)) {
287
451
  let parsed;
288
452
  try {
@@ -321,21 +485,21 @@ function parseHumanFilterValue(context, predicate, value) {
321
485
  return dateOnly(raw);
322
486
  return raw;
323
487
  }
324
- function projectHumanFilterCondition(context, row) {
325
- var _a, _b, _c;
326
- const selector = (_a = row.operator) !== null && _a !== void 0 ? _a : row.predicate;
327
- const predicate = (0, lifeSpaceQuerySemantics_1.parseQueryPredicateSelector)(selector);
328
- if (!predicate)
329
- return null;
330
- const field = String((_b = row.field) !== null && _b !== void 0 ? _b : '').trim();
488
+ function validateConditionField(context, row, predicate) {
489
+ var _a;
490
+ const field = String((_a = row.field) !== null && _a !== void 0 ? _a : '').trim();
331
491
  if (field && field !== predicate.field) {
332
492
  throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter operator "${predicate.operatorLabel}" does not belong to field "${field}"`);
333
493
  }
494
+ }
495
+ function projectHumanFilterCondition(context, row, predicate, timezone) {
496
+ var _a;
497
+ validateConditionField(context, row, predicate);
334
498
  if (predicate.operator === 'isNull' || predicate.operator === 'isNotNull') {
335
499
  return { field: predicate.field, op: predicate.operator };
336
500
  }
337
501
  if (predicate.operator === 'in') {
338
- const values = String((_c = row.value) !== null && _c !== void 0 ? _c : '')
502
+ const values = String((_a = row.value) !== null && _a !== void 0 ? _a : '')
339
503
  .split(',')
340
504
  .map((value) => value.trim())
341
505
  .filter(Boolean);
@@ -352,7 +516,7 @@ function projectHumanFilterCondition(context, row) {
352
516
  return {
353
517
  field: predicate.field,
354
518
  op: predicate.operator,
355
- value: parseHumanFilterValue(context, predicate, row.value),
519
+ value: parseHumanFilterValue(context, predicate, row.value, timezone),
356
520
  };
357
521
  }
358
522
  function combineHumanFilters(match, filters) {
@@ -362,24 +526,57 @@ function combineHumanFilters(match, filters) {
362
526
  return filters[0];
363
527
  return String(match !== null && match !== void 0 ? match : 'all') === 'any' ? { or: filters } : { and: filters };
364
528
  }
365
- function projectHumanFilterBuilder(context, match, conditions, groups) {
366
- const children = humanFilterConditions(conditions)
367
- .map((row) => projectHumanFilterCondition(context, row))
368
- .filter((entry) => entry !== null);
529
+ function projectHumanFilterRows(context, match, rows, timezone) {
530
+ var _a, _b;
531
+ const filters = [];
532
+ const overlapBounds = new Map();
533
+ for (const row of rows) {
534
+ const selection = parseHumanFilterOperatorSelector((_a = row.operator) !== null && _a !== void 0 ? _a : row.predicate);
535
+ if (!selection)
536
+ continue;
537
+ validateConditionField(context, row, selection.predicate);
538
+ if (selection.overlapBoundary) {
539
+ const current = (_b = overlapBounds.get(selection.predicate.field)) !== null && _b !== void 0 ? _b : { predicate: selection.predicate };
540
+ if (current[selection.overlapBoundary] !== undefined) {
541
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${selection.predicate.field} may contain only one Overlaps ${selection.overlapBoundary === 'start' ? 'Start' : 'End'} in a Filter Group`);
542
+ }
543
+ current[selection.overlapBoundary] = row.value;
544
+ overlapBounds.set(selection.predicate.field, current);
545
+ continue;
546
+ }
547
+ const filter = projectHumanFilterCondition(context, row, selection.predicate, timezone);
548
+ if (filter)
549
+ filters.push(filter);
550
+ }
551
+ for (const [field, pair] of overlapBounds) {
552
+ if (pair.start === undefined || pair.end === undefined) {
553
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Filter ${field} requires Overlaps Start and Overlaps End in the same Filter Group`);
554
+ }
555
+ filters.push({
556
+ field,
557
+ op: 'overlaps',
558
+ value: overlapWindowValue(context, field, pair.start, pair.end, timezone),
559
+ });
560
+ }
561
+ return combineHumanFilters(match, filters);
562
+ }
563
+ function projectHumanFilterBuilder(context, match, conditions, groups, timezone = 'UTC') {
564
+ const legacyRows = humanFilterConditions(conditions);
369
565
  const groupRows = Array.isArray(groups)
370
566
  ? groups
371
567
  : groups && typeof groups === 'object' && Array.isArray(groups.group)
372
568
  ? groups.group
373
569
  : [];
374
- for (const group of groupRows) {
375
- const nested = humanFilterConditions(group.conditions)
376
- .map((row) => projectHumanFilterCondition(context, row))
377
- .filter((entry) => entry !== null);
378
- const combined = combineHumanFilters(group.match, nested);
379
- if (combined)
380
- children.push(combined);
381
- }
382
- const combined = combineHumanFilters(match, children);
570
+ const projectedGroups = groupRows
571
+ .map((group) => projectHumanFilterRows(context, group.match, humanFilterConditions(group.conditions), timezone))
572
+ .filter((entry) => entry !== null);
573
+ if (legacyRows.length) {
574
+ const legacy = projectHumanFilterRows(context, match, legacyRows, timezone);
575
+ const children = [...(legacy ? [legacy] : []), ...projectedGroups];
576
+ const combined = combineHumanFilters(match, children);
577
+ return combined ? [combined] : [];
578
+ }
579
+ const combined = combineHumanFilters('all', projectedGroups);
383
580
  return combined ? [combined] : [];
384
581
  }
385
582
  function projectQueryFilters(value) {
@@ -472,6 +669,23 @@ function projectCanonicalTimeWindows(value) {
472
669
  }
473
670
  return result;
474
671
  }
672
+ function queryTimezone(context, itemIndex) {
673
+ var _a, _b;
674
+ const configured = context.getNodeParameter('options', itemIndex, {});
675
+ const explicit = String((_a = configured.viewingTimezone) !== null && _a !== void 0 ? _a : '').trim();
676
+ if (explicit)
677
+ return explicit;
678
+ const legacy = String((_b = context.getNodeParameter('queryViewingTimezone', itemIndex, '')) !== null && _b !== void 0 ? _b : '').trim();
679
+ return legacy || context.getTimezone();
680
+ }
681
+ function rawSortRows(context, itemIndex, options) {
682
+ const rows = context.getNodeParameter('sorts.sort', itemIndex, [], options);
683
+ return Array.isArray(rows) ? rows : [];
684
+ }
685
+ function hasTemporalRangeSort(context, itemIndex, options) {
686
+ return rawSortRows(context, itemIndex, options)
687
+ .some((row) => parseTemporalSortFieldSelector(row.field).temporalRange);
688
+ }
475
689
  function errorAwareHelpers(context) {
476
690
  return new Proxy(context.helpers, {
477
691
  get(target, property, receiver) {
@@ -497,7 +711,7 @@ function humanExecutionContext(context) {
497
711
  if (property !== 'getNodeParameter')
498
712
  return Reflect.get(target, property, receiver);
499
713
  return (name, itemIndex, fallback, options) => {
500
- var _a, _b, _c, _d;
714
+ var _a, _b, _c;
501
715
  if (name === 'queryMode') {
502
716
  const operation = String((_a = target.getNodeParameter('operation', itemIndex, '')) !== null && _a !== void 0 ? _a : '');
503
717
  if (operation === 'list') {
@@ -505,15 +719,24 @@ function humanExecutionContext(context) {
505
719
  return stored === 'capability' ? 'capability' : 'canonical';
506
720
  }
507
721
  }
722
+ if (name === 'sorts.sort') {
723
+ return rawSortRows(target, itemIndex, options).map((row) => ({
724
+ ...row,
725
+ field: parseTemporalSortFieldSelector(row.field).field,
726
+ }));
727
+ }
508
728
  if (name === 'options') {
509
729
  const base = target.getNodeParameter(name, itemIndex, fallback, options);
730
+ const value = base && typeof base === 'object' && !Array.isArray(base)
731
+ ? { ...base }
732
+ : {};
510
733
  const operation = String((_c = target.getNodeParameter('operation', itemIndex, '')) !== null && _c !== void 0 ? _c : '');
511
- const timezone = operation === 'list'
512
- ? String((_d = target.getNodeParameter('queryViewingTimezone', itemIndex, '')) !== null && _d !== void 0 ? _d : '').trim()
513
- : '';
514
- if (!timezone || !base || typeof base !== 'object' || Array.isArray(base))
515
- return base;
516
- return { ...base, viewingTimezone: timezone };
734
+ if (operation !== 'list' || !hasTemporalRangeSort(target, itemIndex, options)) {
735
+ delete value.viewingTimezone;
736
+ return value;
737
+ }
738
+ value.viewingTimezone = queryTimezone(target, itemIndex);
739
+ return value;
517
740
  }
518
741
  if (name === 'canonicalFilters') {
519
742
  const conditions = target.getNodeParameter('queryFilterConditions.condition', itemIndex, [], options);
@@ -522,7 +745,7 @@ function humanExecutionContext(context) {
522
745
  || (Array.isArray(groups) && groups.length > 0);
523
746
  if (hasBuilder) {
524
747
  const match = target.getNodeParameter('queryFilterMatch', itemIndex, 'all', options);
525
- return projectHumanFilterBuilder(target, match, conditions, groups);
748
+ return projectHumanFilterBuilder(target, match, conditions, groups, queryTimezone(target, itemIndex));
526
749
  }
527
750
  const mapped = target.getNodeParameter('queryFilters.value', itemIndex, {}, options);
528
751
  return projectQueryFilters(mapped);