adminforth 1.21.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,17 @@
1
- import { select, confirm, Separator } from '@inquirer/prompts';
2
- import chalk from 'chalk';
3
- import path from 'path'; // Import path
1
+ import { select, Separator, search, input } from '@inquirer/prompts';
2
+ import chalk from 'chalk';// Import path
3
+ import path from 'path';
4
4
  import { loadAdminForthConfig } from './configLoader.js'; // Helper to load config
5
- import { generateComponentFile } from './fileGenerator.js'; // Helper to create the .vue file
6
- import { updateResourceConfig } from './configUpdater.js'; // Helper to modify resource .ts file
7
- // import { openFileInIde } from './ideHelper.js'; // Helper to open file
5
+ import { generateComponentFile, generateLoginOrGlobalComponentFile, generateCrudInjectionComponent } from './fileGenerator.js'; // Helper to create the .vue file
6
+ import { updateResourceConfig, injectLoginComponent, injectGlobalComponent, updateCrudInjectionConfig } from './configUpdater.js'; // Helper to modify resource .ts file
7
+
8
+ function sanitizeLabel(input){
9
+ return input
10
+ .replace(/[^a-zA-Z0-9\s]/g, '')
11
+ .split(' ')
12
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
13
+ .join('');
14
+ }
8
15
 
9
16
  export default async function createComponent(args) {
10
17
  console.log('This command will help you to generate boilerplate for component.\n');
@@ -64,13 +71,23 @@ async function handleFieldComponentCreation(config, resources) {
64
71
  const selectedResource = resources.find(r => r.resourceId === resourceId);
65
72
  console.log(chalk.grey(`Selected ❯ 🔤 Custom fields ❯ ${fieldType} ❯ ${selectedResource.label}`));
66
73
 
67
- const columnName = await select({
68
- message: 'Select column for which you want to create component:',
69
- choices: [
70
- ...selectedResource.columns.map(c => ({ name: `${c.label} ${chalk.grey(`${c.name}`)}`, value: c.name })),
71
- new Separator(),
72
- { name: '🔙 BACK', value: '__BACK__' },
73
- ]
74
+ const columnName = await search({
75
+ message: 'Select column for which you want to create component:',
76
+ source: async (input) => {
77
+ const searchTerm = input ? input.toLowerCase() : '';
78
+
79
+ const filteredColumns = selectedResource.columns.filter(c => {
80
+ const label = c.label || '';
81
+ const name = c.name || '';
82
+ return label.toLowerCase().includes(searchTerm) || name.toLowerCase().includes(searchTerm);
83
+ });
84
+
85
+ return [
86
+ ...filteredColumns.map(c => ({ name: `${c.label} ${chalk.grey(`${c.name}`)}`, value: c.name })),
87
+ new Separator(),
88
+ { name: '🔙 BACK', value: '__BACK__' },
89
+ ];
90
+ },
74
91
  });
75
92
  if (columnName === '__BACK__') return handleFieldComponentCreation(config, resources); // Pass config back
76
93
 
@@ -79,60 +96,226 @@ async function handleFieldComponentCreation(config, resources) {
79
96
  console.log(chalk.dim(`One-line alternative: |adminforth component fields.${fieldType}.${resourceId}.${columnName}|`));
80
97
 
81
98
 
82
- const existingComponentPath = null;
83
-
84
- if (existingComponentPath) {
85
- const action = await select({
86
- message: 'You already have a component for this field, open it in editor?',
87
- choices: [
88
- { name: '✏️ Open in IDE', value: 'open' },
89
- { name: '🔙 BACK', value: '__BACK__' },
90
- { name: '🚪 Exit', value: '__EXIT__' },
91
- ]
92
- });
93
- if (action === 'open') {
94
- // await openFileInIde(existingComponentPath); // Needs absolute path
95
- console.log(`Opening ${existingComponentPath}... (Implementation needed)`);
96
- } else if (action === '__BACK__') {
97
- return handleFieldComponentCreation(config, resources); // Pass config back
98
- } else {
99
- process.exit(0);
99
+ const safeResourceLabel = sanitizeLabel(selectedResource.label)
100
+ const safeColumnLabel = sanitizeLabel(selectedColumn.label)
101
+ const componentFileName = `${safeResourceLabel}${safeColumnLabel}${fieldType.charAt(0).toUpperCase() + fieldType.slice(1)}.vue`; // e.g., UserEmailShow.vue
102
+ const componentPathForConfig = `@@/${componentFileName}`; // Path relative to custom dir for config
103
+
104
+
105
+ try {
106
+ const { alreadyExists, path: absoluteComponentPath } = await generateComponentFile(
107
+ componentFileName,
108
+ fieldType,
109
+ { resource: selectedResource, column: selectedColumn },
110
+ config
111
+ );
112
+ if (!alreadyExists) {
113
+ console.log(chalk.dim(`Component generation successful: ${absoluteComponentPath}`));
114
+
115
+ await updateResourceConfig(selectedResource.resourceId, columnName, fieldType, componentPathForConfig);
116
+ console.log(
117
+ chalk.bold.greenBright('You can now open the component in your IDE:'),
118
+ chalk.underline.cyanBright(absoluteComponentPath)
119
+ );
120
+ }
121
+ process.exit(0);
122
+ }catch (error) {
123
+ console.error(error);
124
+ console.error(chalk.red('\n❌ Component creation failed. Please check the errors above.'));
125
+ process.exit(1);
126
+ }
127
+ }
128
+
129
+ async function handleCrudPageInjectionCreation(config, resources) {
130
+ console.log(chalk.grey('Selected ❯ 📄 CRUD Page Injection'));
131
+
132
+ const crudType = await select({
133
+ message: 'What view do you want to inject a custom component into?',
134
+ choices: [
135
+ { name: '🔸 list', value: 'list' },
136
+ { name: '📃 show', value: 'show' },
137
+ { name: '✏️ edit', value: 'edit' },
138
+ { name: '➕ create', value: 'create' },
139
+ new Separator(),
140
+ { name: '🔙 BACK', value: '__BACK__' },
141
+ ],
142
+ });
143
+ if (crudType === '__BACK__') return createComponent([]);
144
+
145
+ console.log(chalk.grey(`Selected ❯ 📄 CRUD Page Injection ❯ ${crudType}`));
146
+
147
+ const resourceId = await select({
148
+ message: 'Select resource for which you want to inject the component:',
149
+ choices: [
150
+ ...resources.map(r => ({ name: `${r.label} ${chalk.grey(`${r.resourceId}`)}`, value: r.resourceId })),
151
+ new Separator(),
152
+ { name: '🔙 BACK', value: '__BACK__' },
153
+ ],
154
+ });
155
+ if (resourceId === '__BACK__') return handleCrudPageInjectionCreation(config, resources);
156
+
157
+ const selectedResource = resources.find(r => r.resourceId === resourceId);
158
+ console.log(chalk.grey(`Selected ❯ 📄 CRUD Page Injection ❯ ${crudType} ❯ ${selectedResource.label}`));
159
+
160
+ const injectionPosition = await select({
161
+ message: 'Where exactly do you want to inject the component?',
162
+ choices: [
163
+ { name: '⬆️ Before Breadcrumbs', value: 'beforeBreadcrumbs' },
164
+ { name: '⬇️ After Breadcrumbs', value: 'afterBreadcrumbs' },
165
+ { name: '📄 After Page', value: 'bottom' },
166
+ { name: '⋯ threeDotsDropdownItems', value: 'threeDotsDropdownItems' },
167
+ new Separator(),
168
+ { name: '🔙 BACK', value: '__BACK__' },
169
+ ],
170
+ });
171
+ if (injectionPosition === '__BACK__') return handleCrudPageInjectionCreation(config, resources);
172
+
173
+ const isThin = await select({
174
+ message: 'Will this component be thin enough to fit on the same page with list (so list will still shrink)?',
175
+ choices: [
176
+ { name: 'Yes', value: true },
177
+ { name: 'No', value: false },
178
+ ],
179
+ });
180
+
181
+ const safeResourceLabel = sanitizeLabel(selectedResource.label)
182
+ const componentFileName = `${safeResourceLabel}${crudType.charAt(0).toUpperCase() + crudType.slice(1)}${injectionPosition.charAt(0).toUpperCase() + injectionPosition.slice(1)}.vue`;
183
+ const componentPathForConfig = `@@/${componentFileName}`;
184
+
185
+ try {
186
+ const { alreadyExists, path: absoluteComponentPath } = await generateCrudInjectionComponent(
187
+ componentFileName,
188
+ injectionPosition,
189
+ { resource: selectedResource },
190
+ config
191
+ );
192
+
193
+ if (!alreadyExists) {
194
+ console.log(chalk.dim(`Component generation successful: ${absoluteComponentPath}`));
195
+
196
+ await updateCrudInjectionConfig(
197
+ selectedResource.resourceId,
198
+ crudType,
199
+ injectionPosition,
200
+ componentPathForConfig,
201
+ isThin
202
+ );
203
+ console.log(
204
+ chalk.bold.greenBright('You can now open the component in your IDE:'),
205
+ chalk.underline.cyanBright(absoluteComponentPath)
206
+ );
100
207
  }
101
- } else {
102
- const safeResourceLabel = selectedResource.label.replace(/[^a-zA-Z0-9]/g, '');
103
- const safeColumnLabel = selectedColumn.label.replace(/[^a-zA-Z0-9]/g, '');
104
- const componentFileName = `${safeResourceLabel}${safeColumnLabel}${fieldType.charAt(0).toUpperCase() + fieldType.slice(1)}.vue`; // e.g., UserEmailShow.vue
105
- const componentPathForConfig = `@@/${componentFileName}`; // Path relative to custom dir for config
106
-
107
- let absoluteComponentPath;
108
- try {
109
- absoluteComponentPath = await generateComponentFile(
110
- componentFileName,
111
- fieldType,
112
- { resource: selectedResource, column: selectedColumn },
113
- config
114
- );
115
- console.log(chalk.dim(`Component generation successful: ${absoluteComponentPath}`));
116
-
117
- await updateResourceConfig(selectedResource.resourceId, columnName, fieldType, componentPathForConfig);
118
- console.log(chalk.green(`\n✅ Successfully created component ${componentPathForConfig} and updated configuration.`));
119
-
120
- const openNow = await confirm({
121
- message: 'Open the new component file in your IDE?',
122
- default: true
123
- });
124
- if (openNow) { // await openFileInIde(absoluteComponentPath); // Use the absolute path here
125
- console.log(`Opening ${absoluteComponentPath}... (Implementation needed)`);
126
- }
127
-
128
- } catch (error) {
129
- console.error(chalk.red('\n❌ Component creation failed. Please check the errors above.'));
130
- process.exit(1);
208
+ process.exit(0);
209
+ } catch (error) {
210
+ console.error(error);
211
+ console.error(chalk.red('\n❌ Component creation failed. Please check the errors above.'));
212
+ process.exit(1);
213
+ }
214
+ }
215
+
216
+
217
+ async function handleLoginPageInjectionCreation(config) {
218
+ console.log('Selected ❯ 🔐 Login page injections');
219
+ const injectionType = await select({
220
+ message: 'Select injection type:',
221
+ choices: [
222
+ { name: 'After Login and password inputs', value: 'afterLogin' },
223
+ { name: '🔙 BACK', value: '__BACK__' },
224
+ ],
225
+ });
226
+ if (injectionType === '__BACK__') return createComponent([]);
227
+
228
+ console.log(chalk.grey(`Selected 🔐 Login page injections ${injectionType}`));
229
+
230
+ const reason = await input({
231
+ message: 'What will you need component for? (enter name)',
232
+ });
233
+
234
+ console.log(chalk.grey(`Selected ❯ 🔐 Login page injections ❯ ${injectionType} ❯ ${reason}`));
235
+
236
+
237
+ try {
238
+ const safeName = sanitizeLabel(reason)
239
+ const componentFileName = `CustomLogin${safeName}.vue`;
240
+
241
+ const context = { reason };
242
+
243
+ const { alreadyExists, path: absoluteComponentPath } = await generateLoginOrGlobalComponentFile(
244
+ componentFileName,
245
+ injectionType,
246
+ context
247
+ );
248
+ if (!alreadyExists) {
249
+ console.log(chalk.dim(`Component generation successful: ${absoluteComponentPath}`));
250
+ const configFilePath = path.resolve(process.cwd(), 'index.ts');
251
+ console.log(chalk.dim(`Injecting component: ${configFilePath}, ${componentFileName}`));
252
+ await injectLoginComponent(configFilePath, `@@/${componentFileName}`);
253
+
254
+ console.log(
255
+ chalk.bold.greenBright('You can now open the component in your IDE:'),
256
+ chalk.underline.cyanBright(absoluteComponentPath)
257
+ );
131
258
  }
259
+ process.exit(0);
260
+ }catch (error) {
261
+ console.error(error);
262
+ console.error(chalk.red('\n❌ Component creation failed. Please check the errors above.'));
263
+ process.exit(1);
132
264
  }
265
+
133
266
  }
134
267
 
135
- // --- TODO: Implement similar handlers for other component types (pass config) ---
136
- async function handleCrudPageInjectionCreation(config, resources) { console.log('CRUD Page Injection creation not implemented yet.'); }
137
- async function handleLoginPageInjectionCreation(config) { console.log('Login Page Injection creation not implemented yet.'); }
138
- async function handleGlobalInjectionCreation(config) { console.log('Global Injection creation not implemented yet.'); }
268
+ async function handleGlobalInjectionCreation(config) {
269
+ console.log('Selected 🌍 Global page injections');
270
+
271
+ const injectionType = await select({
272
+ message: 'Select global injection type:',
273
+ choices: [
274
+ { name: 'User Menu', value: 'userMenu' },
275
+ { name: 'Header', value: 'header' },
276
+ { name: 'Sidebar', value: 'sidebar' },
277
+ { name: 'Every Page Bottom', value: 'everyPageBottom' },
278
+ { name: '🔙 BACK', value: '__BACK__' },
279
+ ],
280
+ });
281
+
282
+ if (injectionType === '__BACK__') return createComponent([]);
283
+
284
+ console.log(chalk.grey(`Selected ❯ 🌍 Global page injections ❯ ${injectionType}`));
285
+
286
+ const reason = await input({
287
+ message: 'What will you need the component for? (enter name)',
288
+ });
289
+
290
+ console.log(chalk.grey(`Selected ❯ 🌍 Global page injections ❯ ${injectionType} ❯ ${reason}`));
291
+
292
+ try {
293
+ const safeName = sanitizeLabel(reason)
294
+ const componentFileName = `CustomGlobal${safeName}.vue`;
295
+
296
+ const context = { reason };
297
+
298
+ const { alreadyExists, path: absoluteComponentPath } = await generateLoginOrGlobalComponentFile(
299
+ componentFileName,
300
+ injectionType,
301
+ context
302
+ );
303
+ if (!alreadyExists) {
304
+ console.log(chalk.dim(`Component generation successful: ${absoluteComponentPath}`));
305
+
306
+ const configFilePath = path.resolve(process.cwd(), 'index.ts');
307
+
308
+ await injectGlobalComponent(configFilePath, injectionType, `@@/${componentFileName}`);
309
+
310
+ console.log(
311
+ chalk.bold.greenBright('You can now open the component in your IDE:'),
312
+ chalk.underline.cyanBright(absoluteComponentPath)
313
+ );
314
+ }
315
+ process.exit(0);
316
+ } catch (error) {
317
+ console.error(error);
318
+ console.error(chalk.red('\n❌ Component creation failed. Please check the errors above.'));
319
+ process.exit(1);
320
+ }
321
+ }
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
3
+ <button
4
+ type="button"
5
+ @click="handleClick"
6
+ class="text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-500 dark:hover:bg-blue-600 dark:focus:ring-blue-800"
7
+ >
8
+ Example
9
+ </button>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { onMounted } from 'vue';
15
+ import { useI18n } from 'vue-i18n';
16
+ import adminforth from '@/adminforth';
17
+
18
+ const { t } = useI18n();
19
+
20
+ onMounted(() => {
21
+ // Logic on mount if needed
22
+ });
23
+
24
+ function handleClick() {
25
+ adminforth.alert({
26
+ message: t('Confirmed'),
27
+ variant: 'success',
28
+ });
29
+ }
30
+ </script>
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
3
+ <button
4
+ type="button"
5
+ @click="handleClick"
6
+ class="text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-500 dark:hover:bg-blue-600 dark:focus:ring-blue-800"
7
+ >
8
+ Example
9
+ </button>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { onMounted } from 'vue';
15
+ import { useI18n } from 'vue-i18n';
16
+ import adminforth from '@/adminforth';
17
+
18
+ const { t } = useI18n();
19
+
20
+ onMounted(() => {
21
+ // Logic on mount if needed
22
+ });
23
+
24
+ function handleClick() {
25
+ adminforth.alert({
26
+ message: t('Confirmed'),
27
+ variant: 'success',
28
+ });
29
+ }
30
+ </script>
@@ -0,0 +1,61 @@
1
+ <template>
2
+ <div class="overflow-auto p-4">
3
+ <table class="min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
4
+ <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
5
+ <tr>
6
+ <th scope="col" class="px-6 py-3" v-for="header in headers" :key="header">
7
+ {{ header }}
8
+ </th>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <tr
13
+ v-for="row in rows"
14
+ :key="row.id"
15
+ class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600"
16
+ >
17
+ <td class="px-6 py-4" v-for="cell in row.cells" :key="cell">
18
+ {{ cell }}
19
+ </td>
20
+ </tr>
21
+ </tbody>
22
+ </table>
23
+ </div>
24
+ </template>
25
+
26
+ <script setup lang="ts">
27
+ import { onMounted, ref } from 'vue';
28
+
29
+ const headers = [
30
+ 'ID',
31
+ 'Name',
32
+ 'Email',
33
+ 'Phone',
34
+ 'Address',
35
+ 'City',
36
+ 'Country',
37
+ 'Company',
38
+ 'Position',
39
+ 'Status',
40
+ ];
41
+
42
+ const rows = Array.from({ length: 50 }, (_, i) => ({
43
+ id: i + 1,
44
+ cells: [
45
+ i + 1,
46
+ `Name ${i + 1}`,
47
+ `user${i + 1}@example.com`,
48
+ `+1-555-010${i.toString().padStart(2, '0')}`,
49
+ `Address ${i + 1}`,
50
+ `City ${i + 1}`,
51
+ `Country ${i + 1}`,
52
+ `Company ${i + 1}`,
53
+ `Position ${i + 1}`,
54
+ i % 2 === 0 ? 'Active' : 'Inactive',
55
+ ],
56
+ }));
57
+
58
+ onMounted(() => {
59
+ console.log('Table mounted. Rows:', rows.length);
60
+ });
61
+ </script>
@@ -0,0 +1,55 @@
1
+ <template>
2
+ <div class="flex flex-col p-4 space-y-2">
3
+ <button
4
+ v-for="item in menuItems"
5
+ :key="item.label"
6
+ @click="item.action"
7
+ class="w-full text-left text-sm px-4 py-2 rounded hover:bg-gray-100 dark:hover:bg-gray-700 dark:text-white"
8
+ >
9
+ {{ t(item.label) }}
10
+ </button>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup lang="ts">
15
+ import { useI18n } from 'vue-i18n';
16
+ import adminforth from '@/adminforth';
17
+ import { onMounted } from 'vue';
18
+
19
+ const { t } = useI18n();
20
+
21
+ const menuItems = [
22
+ {
23
+ label: 'Show Success Alert',
24
+ action: () => {
25
+ adminforth.alert({
26
+ message: t('Success Alert'),
27
+ variant: 'success',
28
+ });
29
+ },
30
+ },
31
+ {
32
+ label: 'Show Warning Alert',
33
+ action: () => {
34
+ adminforth.alert({
35
+ message: t('Warning Alert'),
36
+ variant: 'warning',
37
+ });
38
+ },
39
+ },
40
+ {
41
+ label: 'Show Error Alert',
42
+ action: () => {
43
+ adminforth.alert({
44
+ message: t('Error Alert'),
45
+ variant: 'danger',
46
+ });
47
+ },
48
+ },
49
+ ];
50
+
51
+ onMounted(() => {
52
+ // Logic on mount if needed
53
+ });
54
+
55
+ </script>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <div class="flex items-center justify-center text-gray-900 dark:text-gray-400 p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
3
+ {{reason}}
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ defineProps({
9
+ reason: String
10
+ });
11
+ </script>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <div class="text-center text-gray-500 text-sm mt-4">
3
+ {{reason}}
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ defineProps({
9
+ reason: String
10
+ });
11
+ </script>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <div class="display-flex justify-center text-lightSidebarIcons text-center dark:text-darkSidebarIcons">
3
+ {{reason}}
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ defineProps({
9
+ reason: String
10
+ });
11
+ </script>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <div class="text-center text-gray-500 text-sm mt-4">
3
+ {{reason}}
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ defineProps({
9
+ reason: String
10
+ });
11
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <div class="text-center text-gray-500 text-sm mt-4">
3
+ {{reason}}
4
+ </div>
5
+ </template>
6
+
7
+ <script setup>
8
+ defineProps({
9
+ reason: String
10
+ });
11
+ </script>
12
+
@@ -1 +1 @@
1
- {"version":3,"file":"baseConnector.d.ts","sourceRoot":"","sources":["../../dataConnectors/baseConnector.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"baseConnector.d.ts","sourceRoot":"","sources":["../../dataConnectors/baseConnector.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { suggestIfTypo } from "../modules/utils.js";
2
- import { AdminForthFilterOperators } from "../types/Common.js";
2
+ import { AdminForthDataTypes, AdminForthFilterOperators } from "../types/Common.js";
3
+ import { randomUUID } from "crypto";
3
4
  export default class AdminForthBaseConnector {
4
5
  get db() {
5
6
  console.warn('.db is deprecated, use .client instead');
@@ -45,6 +46,7 @@ export default class AdminForthBaseConnector {
45
46
  return { operator: AdminForthFilterOperators.AND, subFilters: [filter] };
46
47
  }
47
48
  validateAndNormalizeFilters(filters, resource) {
49
+ var _a;
48
50
  if (Array.isArray(filters)) {
49
51
  // go through all filters in array and call validation+normalization for each
50
52
  // as soon as error is encountered, there is no point in calling validation for other filters
@@ -99,8 +101,15 @@ export default class AdminForthBaseConnector {
99
101
  return { ok: false, error: `Value for operator '${filters.operator}' should be an array, in filter object: ${JSON.stringify(filters)}` };
100
102
  }
101
103
  if (filters.value.length === 0) {
102
- // nonsense
103
- return { ok: false, error: `Filter has IN operator but empty value: ${JSON.stringify(filters)}` };
104
+ // nonsense, and some databases might not accept IN []
105
+ const colType = (_a = resource.dataSourceColumns.find((col) => col.name == filters.field)) === null || _a === void 0 ? void 0 : _a.type;
106
+ if (colType === AdminForthDataTypes.STRING || colType === AdminForthDataTypes.TEXT) {
107
+ filters.value = [randomUUID()];
108
+ return { ok: true, error: `` };
109
+ }
110
+ else {
111
+ return { ok: false, error: `Value for operator '${filters.operator}' should not be empty array, in filter object: ${JSON.stringify(filters)}` };
112
+ }
104
113
  }
105
114
  filters.value = filters.value.map((val) => this.setFieldValue(fieldObj, val));
106
115
  }