@teleporthq/teleport-plugin-next-workflows 0.43.32 → 0.43.33
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/data-api-route-generator.d.ts.map +1 -1
- package/dist/cjs/data-api-route-generator.js +53 -4
- package/dist/cjs/data-api-route-generator.js.map +1 -1
- package/dist/cjs/nodes/data/data-select.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-select.js +42 -3
- package/dist/cjs/nodes/data/data-select.js.map +1 -1
- package/dist/cjs/nodes/general/general-extract-form-data.d.ts.map +1 -1
- package/dist/cjs/nodes/general/general-extract-form-data.js +37 -1
- package/dist/cjs/nodes/general/general-extract-form-data.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/data-api-route-generator.d.ts.map +1 -1
- package/dist/esm/data-api-route-generator.js +53 -4
- package/dist/esm/data-api-route-generator.js.map +1 -1
- package/dist/esm/nodes/data/data-select.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-select.js +42 -3
- package/dist/esm/nodes/data/data-select.js.map +1 -1
- package/dist/esm/nodes/general/general-extract-form-data.d.ts.map +1 -1
- package/dist/esm/nodes/general/general-extract-form-data.js +37 -1
- package/dist/esm/nodes/general/general-extract-form-data.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/data-api-route-generator.ts +53 -4
- package/src/nodes/data/data-select.ts +39 -3
- package/src/nodes/general/general-extract-form-data.ts +37 -1
|
@@ -176,9 +176,26 @@ async function safeQuery(client, sql, params, mode) {
|
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
function
|
|
179
|
+
function isSkippableFilterValue(value) {
|
|
180
|
+
if (value === undefined || value === null) return true;
|
|
181
|
+
if (typeof value === 'string' && value.trim() === '') return true;
|
|
182
|
+
if (Array.isArray(value) && value.length === 0) return true;
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isAllSentinelFilterValue(value, filter) {
|
|
187
|
+
if (typeof value !== 'string') return false;
|
|
188
|
+
var normalized = value.trim().toLowerCase();
|
|
189
|
+
if (filter && typeof filter.treatAsAll === 'string' && filter.treatAsAll.trim().toLowerCase() === normalized) {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return normalized === 'all' || normalized === 'any' || normalized === 'everything' || normalized === '__all__';
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function buildWhereClause(filters, queryParams, startIndex, options) {
|
|
180
196
|
var conditions = [];
|
|
181
197
|
var paramIndex = startIndex;
|
|
198
|
+
var skipOptionalEmpty = !!(options && options.skipOptionalEmpty);
|
|
182
199
|
|
|
183
200
|
if (!filters || !Array.isArray(filters) || filters.length === 0) {
|
|
184
201
|
return { clause: '', paramIndex: paramIndex };
|
|
@@ -194,6 +211,7 @@ function buildWhereClause(filters, queryParams, startIndex) {
|
|
|
194
211
|
var operand = f.operand || f.operator || '=';
|
|
195
212
|
|
|
196
213
|
if (value === undefined) continue;
|
|
214
|
+
if (skipOptionalEmpty && (isSkippableFilterValue(value) || isAllSentinelFilterValue(value, f))) continue;
|
|
197
215
|
|
|
198
216
|
if (Array.isArray(value)) {
|
|
199
217
|
if (value.length === 0) continue;
|
|
@@ -211,6 +229,37 @@ function buildWhereClause(filters, queryParams, startIndex) {
|
|
|
211
229
|
conditions.push(field + ' IS NOT NULL');
|
|
212
230
|
}
|
|
213
231
|
} else {
|
|
232
|
+
var normalizedOperand = String(operand || '=').toLowerCase();
|
|
233
|
+
if (normalizedOperand === 'contains' || normalizedOperand === 'not_contains' || normalizedOperand === 'not-contains') {
|
|
234
|
+
if (isSkippableFilterValue(value)) {
|
|
235
|
+
conditions.push('FALSE');
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
conditions.push(field + (normalizedOperand === 'contains' ? ' ILIKE ' : ' NOT ILIKE ') + '$' + paramIndex);
|
|
239
|
+
queryParams.push('%' + String(value) + '%');
|
|
240
|
+
paramIndex++;
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (normalizedOperand === 'startswith' || normalizedOperand === 'starts_with' || normalizedOperand === 'starts-with') {
|
|
244
|
+
if (isSkippableFilterValue(value)) {
|
|
245
|
+
conditions.push('FALSE');
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
conditions.push(field + ' ILIKE $' + paramIndex);
|
|
249
|
+
queryParams.push(String(value) + '%');
|
|
250
|
+
paramIndex++;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
if (normalizedOperand === 'endswith' || normalizedOperand === 'ends_with' || normalizedOperand === 'ends-with') {
|
|
254
|
+
if (isSkippableFilterValue(value)) {
|
|
255
|
+
conditions.push('FALSE');
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
conditions.push(field + ' ILIKE $' + paramIndex);
|
|
259
|
+
queryParams.push('%' + String(value));
|
|
260
|
+
paramIndex++;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
214
263
|
var validOps = ['=', '!=', '>', '<', '>=', '<=', 'LIKE', 'ILIKE'];
|
|
215
264
|
var sqlOp = validOps.indexOf(operand) !== -1 ? operand : '=';
|
|
216
265
|
conditions.push(field + ' ' + sqlOp + ' $' + paramIndex);
|
|
@@ -253,7 +302,7 @@ async function handleSelect(client, body) {
|
|
|
253
302
|
var cols = selectedColumns.length > 0 ? selectedColumns.join(', ') : '*';
|
|
254
303
|
var sql = 'SELECT ' + cols + ' FROM ' + tableName;
|
|
255
304
|
|
|
256
|
-
var where = buildWhereClause(filters, queryParams, 1);
|
|
305
|
+
var where = buildWhereClause(filters, queryParams, 1, { skipOptionalEmpty: true });
|
|
257
306
|
sql += where.clause;
|
|
258
307
|
|
|
259
308
|
if (sorts.length > 0) {
|
|
@@ -289,7 +338,7 @@ async function handleSelect(client, body) {
|
|
|
289
338
|
|
|
290
339
|
var countSql = 'SELECT COUNT(*) FROM ' + tableName;
|
|
291
340
|
var countParams = [];
|
|
292
|
-
var countWhere = buildWhereClause(filters, countParams, 1);
|
|
341
|
+
var countWhere = buildWhereClause(filters, countParams, 1, { skipOptionalEmpty: true });
|
|
293
342
|
countSql += countWhere.clause;
|
|
294
343
|
var countResult = await safeQuery(client, countSql, countParams, 'count');
|
|
295
344
|
var count = parseInt(countResult.rows[0].count, 10);
|
|
@@ -306,7 +355,7 @@ async function handleCount(client, body) {
|
|
|
306
355
|
|
|
307
356
|
var queryParams = [];
|
|
308
357
|
var sql = 'SELECT COUNT(*) FROM ' + tableName;
|
|
309
|
-
var where = buildWhereClause(filters, queryParams, 1);
|
|
358
|
+
var where = buildWhereClause(filters, queryParams, 1, { skipOptionalEmpty: true });
|
|
310
359
|
sql += where.clause;
|
|
311
360
|
|
|
312
361
|
var result = await safeQuery(client, sql, queryParams, 'count');
|
|
@@ -11,6 +11,42 @@ async function data_select(config: any, context: any) {
|
|
|
11
11
|
const rawQueryUserPart = config.rawQueryUserPart
|
|
12
12
|
const baseUrl = (context && context.__baseUrl) || ''
|
|
13
13
|
|
|
14
|
+
function isEmptyFilterValue(value: any) {
|
|
15
|
+
if (value === undefined || value === null) return true
|
|
16
|
+
if (typeof value === 'string' && value.trim() === '') return true
|
|
17
|
+
if (Array.isArray(value) && value.length === 0) return true
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isAllSentinel(value: any, filter: any) {
|
|
22
|
+
if (typeof value !== 'string') return false
|
|
23
|
+
const normalized = value.trim().toLowerCase()
|
|
24
|
+
const configured = filter && filter.treatAsAll
|
|
25
|
+
if (typeof configured === 'string' && configured.trim().toLowerCase() === normalized) {
|
|
26
|
+
return true
|
|
27
|
+
}
|
|
28
|
+
return (
|
|
29
|
+
normalized === 'all' ||
|
|
30
|
+
normalized === 'any' ||
|
|
31
|
+
normalized === 'everything' ||
|
|
32
|
+
normalized === '__all__'
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function shouldSkipOptionalFilter(filter: any) {
|
|
37
|
+
if (!filter) return true
|
|
38
|
+
const value = filter.destination !== undefined ? filter.destination : filter.value
|
|
39
|
+
if (isEmptyFilterValue(value)) return true
|
|
40
|
+
if (isAllSentinel(value, filter)) return true
|
|
41
|
+
if (Array.isArray(filter.skipIfValue) && filter.skipIfValue.indexOf(value) !== -1) return true
|
|
42
|
+
if (filter.skipIfEmpty === true && isEmptyFilterValue(value)) return true
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const effectiveFilters = filters.filter(function (filter: any) {
|
|
47
|
+
return !shouldSkipOptionalFilter(filter)
|
|
48
|
+
})
|
|
49
|
+
|
|
14
50
|
// A filter whose value is the unresolved route-param sentinel (see
|
|
15
51
|
// resolveTemplateTokenString in runtime-utils) — e.g. a select scoped to
|
|
16
52
|
// {{Current Page Entity.id}} that runs on a page with no such route param
|
|
@@ -19,8 +55,8 @@ async function data_select(config: any, context: any) {
|
|
|
19
55
|
// WHOLE workflow (a single unresolvable filter must never kill the note-create
|
|
20
56
|
// submit). Never fall through to an unscoped query. Observable via the warn +
|
|
21
57
|
// the __skippedUnavailableFilter marker.
|
|
22
|
-
for (let __fi = 0; __fi <
|
|
23
|
-
const __f: any =
|
|
58
|
+
for (let __fi = 0; __fi < effectiveFilters.length; __fi++) {
|
|
59
|
+
const __f: any = effectiveFilters[__fi]
|
|
24
60
|
if (
|
|
25
61
|
__f &&
|
|
26
62
|
(__f.value === '__TQ_UNRESOLVED_ROUTE_PARAM__' ||
|
|
@@ -39,7 +75,7 @@ async function data_select(config: any, context: any) {
|
|
|
39
75
|
}
|
|
40
76
|
|
|
41
77
|
try {
|
|
42
|
-
const payload: any = { tableName, filters, sorts, selectedColumns }
|
|
78
|
+
const payload: any = { tableName, filters: effectiveFilters, sorts, selectedColumns }
|
|
43
79
|
if (limit !== undefined && limit !== null) {
|
|
44
80
|
payload.limit = limit
|
|
45
81
|
}
|
|
@@ -97,11 +97,47 @@ async function general_extract_form_data(config: any, context: Record<string, un
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
const fieldKeys = Object.keys(fields)
|
|
100
|
-
const result: Record<string, any> = { fields }
|
|
100
|
+
const result: Record<string, any> = { fields, formData: fields }
|
|
101
101
|
for (let fi = 0; fi < fieldKeys.length; fi++) {
|
|
102
102
|
result[fieldKeys[fi]] = fields[fieldKeys[fi]]
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
// Workflows generated/imported from HTML often refer to a form control by
|
|
106
|
+
// its DOM id (`class-session-select`) while FormData exposes submitted
|
|
107
|
+
// values by name (`class_session_id`). Preserve the canonical name keys
|
|
108
|
+
// above, and add non-overwriting aliases for id/data-form-field-id so both
|
|
109
|
+
// conventions resolve to the same submitted value.
|
|
110
|
+
try {
|
|
111
|
+
const addAlias = (alias: string | null | undefined, name: string | undefined) => {
|
|
112
|
+
if (!alias || !name) return
|
|
113
|
+
if (fields[name] === undefined) return
|
|
114
|
+
if (result[alias] === undefined) {
|
|
115
|
+
result[alias] = fields[name]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const controls = (formEl as HTMLFormElement).querySelectorAll(
|
|
119
|
+
'input[name], select[name], textarea[name], button[name]'
|
|
120
|
+
)
|
|
121
|
+
for (let ci = 0; ci < controls.length; ci++) {
|
|
122
|
+
const control = controls[ci] as HTMLInputElement
|
|
123
|
+
addAlias(control.id, control.name)
|
|
124
|
+
addAlias(control.getAttribute('data-form-field-id'), control.name)
|
|
125
|
+
}
|
|
126
|
+
const outsideControls = document.querySelectorAll(
|
|
127
|
+
'input[name], select[name], textarea[name], button[name]'
|
|
128
|
+
)
|
|
129
|
+
for (let oi = 0; oi < outsideControls.length; oi++) {
|
|
130
|
+
const control = outsideControls[oi] as HTMLInputElement
|
|
131
|
+
if (formEl.contains(control)) continue
|
|
132
|
+
const ownerForm = control.closest('form')
|
|
133
|
+
if (ownerForm && ownerForm !== formEl) continue
|
|
134
|
+
addAlias(control.id, control.name)
|
|
135
|
+
addAlias(control.getAttribute('data-form-field-id'), control.name)
|
|
136
|
+
}
|
|
137
|
+
} catch (_aliasErr) {
|
|
138
|
+
/* aliases are best-effort; canonical name-based fields remain intact */
|
|
139
|
+
}
|
|
140
|
+
|
|
105
141
|
// Diagnostic: surface any required inputs whose value is empty at extraction
|
|
106
142
|
// time so downstream custom-JS validators have something concrete to report
|
|
107
143
|
// instead of a generic "please fill in all required fields" message.
|