@adminforth/bulk-ai-flow 1.14.4 → 1.14.6

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/build.log CHANGED
@@ -13,5 +13,5 @@ custom/package-lock.json
13
13
  custom/package.json
14
14
  custom/tsconfig.json
15
15
 
16
- sent 74,113 bytes received 172 bytes 148,570.00 bytes/sec
17
- total size is 73,472 speedup is 0.99
16
+ sent 74,310 bytes received 172 bytes 148,964.00 bytes/sec
17
+ total size is 73,669 speedup is 0.99
@@ -10,12 +10,12 @@
10
10
  <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
11
11
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
12
12
  </svg>
13
- <span class="sr-only">Close modal</span>
13
+ <span class="sr-only">{{ $t('Close modal') }}</span>
14
14
  </button>
15
15
  </div>
16
16
  <div class="flex gap-4 items-start justify-between">
17
- <h3 class="text-sm font-medium text-gray-700 mb-2">Old Image</h3>
18
- <h3 class="text-sm font-medium text-gray-700 mb-2">New Image</h3>
17
+ <h3 class="text-sm font-medium text-gray-700 mb-2">{{ $t('Old Image') }}</h3>
18
+ <h3 class="text-sm font-medium text-gray-700 mb-2">{{ $t('New Image') }}</h3>
19
19
  </div>
20
20
  <div class="flex gap-4 items-center">
21
21
  <!-- Old Image -->
@@ -29,7 +29,7 @@
29
29
  class="w-full max-w-sm h-auto object-cover rounded-lg cursor-pointer border hover:border-blue-500 transition-colors duration-200"
30
30
  />
31
31
  <div v-else class="w-full max-w-sm h-48 bg-gray-100 rounded-lg flex items-center justify-center">
32
- <p class="text-gray-500">No old image</p>
32
+ <p class="text-gray-500">{{ $t('No old image') }}</p>
33
33
  </div>
34
34
  </div>
35
35
  </div>
@@ -54,7 +54,7 @@
54
54
  class="w-full max-w-sm h-auto object-cover rounded-lg cursor-pointer border hover:border-blue-500 transition-colors duration-200"
55
55
  />
56
56
  <div v-else class="w-full max-w-sm h-48 bg-gray-100 rounded-lg flex items-center justify-center">
57
- <p class="text-gray-500">No new image</p>
57
+ <p class="text-gray-500">{{ $t('No new image') }}</p>
58
58
  </div>
59
59
  </div>
60
60
  </div>
@@ -302,7 +302,7 @@ async function getRecords() {
302
302
  } catch (error) {
303
303
  console.error('Failed to get records:', error);
304
304
  isError.value = true;
305
- errorMessage.value = `Failed to fetch records. Please, try to re-run the action.`;
305
+ errorMessage.value = t(`Failed to fetch records. Please, try to re-run the action.`);
306
306
  }
307
307
  }
308
308
 
@@ -319,7 +319,7 @@ async function getImages() {
319
319
  } catch (error) {
320
320
  console.error('Failed to get images:', error);
321
321
  isError.value = true;
322
- errorMessage.value = `Failed to fetch images. Please, try to re-run the action.`;
322
+ errorMessage.value = t(`Failed to fetch images. Please, try to re-run the action.`);
323
323
  }
324
324
  }
325
325
 
@@ -375,7 +375,7 @@ async function convertImages(fieldName, img) {
375
375
 
376
376
  async function saveData() {
377
377
  if (!selected.value?.length) {
378
- adminforth.alert({ message: 'No items selected', variant: 'warning' });
378
+ adminforth.alert({ message: t('No items selected'), variant: 'warning' });
379
379
  return;
380
380
  }
381
381
  try {
@@ -420,16 +420,16 @@ async function saveData() {
420
420
  timeout: 'unlimited',
421
421
  });
422
422
  isError.value = true;
423
- errorMessage.value = `Failed to save data. You are not allowed to save.`;
423
+ errorMessage.value = t(`Failed to save data. You are not allowed to save.`);
424
424
  } else {
425
425
  console.error('Error saving data:', res);
426
426
  isError.value = true;
427
- errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
427
+ errorMessage.value = t(`Failed to save data. Please, try to re-run the action.`);
428
428
  }
429
429
  } catch (error) {
430
430
  console.error('Error saving data:', error);
431
431
  isError.value = true;
432
- errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
432
+ errorMessage.value = t(`Failed to save data. Please, try to re-run the action.`);
433
433
  } finally {
434
434
  isLoading.value = false;
435
435
  }
@@ -474,7 +474,7 @@ async function runAiAction({
474
474
  if (rateLimitRes?.error) {
475
475
  isRateLimitExceeded = true;
476
476
  adminforth.alert({
477
- message: `Rate limit exceeded for "${actionType.replace('_', ' ')}" action. Please try again later.`,
477
+ message: t(`Rate limit exceeded for "${actionType.replace('_', ' ')}" action. Please try again later.`),
478
478
  variant: 'danger',
479
479
  timeout: 'unlimited',
480
480
  });
@@ -482,7 +482,7 @@ async function runAiAction({
482
482
  }
483
483
  } catch (e) {
484
484
  adminforth.alert({
485
- message: `Error checking rate limit for "${actionType.replace('_', ' ')}" action.`,
485
+ message: t(`Error checking rate limit for "${actionType.replace('_', ' ')}" action.`),
486
486
  variant: 'danger',
487
487
  timeout: 'unlimited',
488
488
  });
@@ -516,7 +516,7 @@ async function runAiAction({
516
516
  } catch (e) {
517
517
  console.error(`Error during ${actionType} for item ${i}:`, e);
518
518
  hasError = true;
519
- errorMessage = `Failed to ${actionType.replace('_', ' ')}. Please, try to re-run the action.`;
519
+ errorMessage = t(`Failed to ${actionType.replace('_', ' ')}. Please, try to re-run the action.`);
520
520
  return { success: false, index: i, error: e };
521
521
  }
522
522
  });
@@ -591,7 +591,7 @@ async function runAiAction({
591
591
  }
592
592
  isAtLeastOneInProgress = true;
593
593
  adminforth.alert({
594
- message: `Generation action "${actionType.replace('_', ' ')}" failed for record: ${recordId}. Error: ${jobResponse.job?.error || 'Unknown error'}`,
594
+ message: t(`Generation action "${actionType.replace('_', ' ')}" failed for record: ${recordId}. Error: ${jobResponse.job?.error || 'Unknown error'}`),
595
595
  variant: 'danger',
596
596
  timeout: 'unlimited',
597
597
  });
@@ -6,7 +6,7 @@
6
6
  >
7
7
  <!-- HEADER TEMPLATE -->
8
8
  <template #header:checkboxes="{ item }">
9
- MARK FOR SAVE
9
+ {{ $t('MARK FOR SAVE') }}
10
10
  </template>
11
11
  <!-- CHECKBOX CELL TEMPLATE -->
12
12
  <template #cell:checkboxes="{ item }">
@@ -28,12 +28,12 @@
28
28
  @click="zoomImage(image)"
29
29
  />
30
30
  <div v-else class="w-20 h-20">
31
- <p>Invalid source image</p>
31
+ <p>{{ $t('Invalid source image') }}</p>
32
32
  </div>
33
33
  </div>
34
34
  </div>
35
35
  <div class="flex items-center justify-center text-center w-20 h-20" v-else>
36
- <p>No images found</p>
36
+ <p>{{ $t('No images found') }}</p>
37
37
  </div>
38
38
  <transition name="fade">
39
39
  <div
@@ -66,7 +66,7 @@
66
66
  </Select>
67
67
  <Tooltip>
68
68
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
69
- <p class="text-sm ">old value</p>
69
+ <p class="text-sm ">{{ $t('old value') }}</p>
70
70
  </div>
71
71
  <template #tooltip>
72
72
  {{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}
@@ -82,7 +82,7 @@
82
82
  </Textarea>
83
83
  <Tooltip>
84
84
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
85
- <p class="text-sm ">old value</p>
85
+ <p class="text-sm ">{{ $t('old value') }}</p>
86
86
  </div>
87
87
  <template #tooltip>
88
88
  <p class="max-w-[200px]">{{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}</p>
@@ -97,7 +97,7 @@
97
97
  </Toggle>
98
98
  <Tooltip>
99
99
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
100
- <p class="text-sm ">old value</p>
100
+ <p class="text-sm ">{{ $t('old value') }}</p>
101
101
  </div>
102
102
  <template #tooltip>
103
103
  {{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}
@@ -113,7 +113,7 @@
113
113
  />
114
114
  <Tooltip>
115
115
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
116
- <p class="text-sm ">old value</p>
116
+ <p class="text-sm ">{{ $t('old value') }}</p>
117
117
  </div>
118
118
  <template #tooltip>
119
119
  {{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}
@@ -137,14 +137,14 @@
137
137
  :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }"
138
138
  @click="() => {openImageCompare[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] = true}"
139
139
  >
140
- old image
140
+ {{ $t('old image') }}
141
141
  </p>
142
142
  </div>
143
143
  <div v-else class="flex items-center justify-center text-center w-20 h-20">
144
144
  <Tooltip v-if="imageGenerationErrorMessage[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])] === 'No source images found'">
145
145
  <p
146
146
  >
147
- Can't generate image.
147
+ {{ $t("Can't generate image.") }}
148
148
  </p>
149
149
  <template #tooltip>
150
150
  {{ imageGenerationErrorMessage[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])] }}
@@ -10,12 +10,12 @@
10
10
  <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
11
11
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
12
12
  </svg>
13
- <span class="sr-only">Close modal</span>
13
+ <span class="sr-only">{{ $t('Close modal') }}</span>
14
14
  </button>
15
15
  </div>
16
16
  <div class="flex gap-4 items-start justify-between">
17
- <h3 class="text-sm font-medium text-gray-700 mb-2">Old Image</h3>
18
- <h3 class="text-sm font-medium text-gray-700 mb-2">New Image</h3>
17
+ <h3 class="text-sm font-medium text-gray-700 mb-2">{{ $t('Old Image') }}</h3>
18
+ <h3 class="text-sm font-medium text-gray-700 mb-2">{{ $t('New Image') }}</h3>
19
19
  </div>
20
20
  <div class="flex gap-4 items-center">
21
21
  <!-- Old Image -->
@@ -29,7 +29,7 @@
29
29
  class="w-full max-w-sm h-auto object-cover rounded-lg cursor-pointer border hover:border-blue-500 transition-colors duration-200"
30
30
  />
31
31
  <div v-else class="w-full max-w-sm h-48 bg-gray-100 rounded-lg flex items-center justify-center">
32
- <p class="text-gray-500">No old image</p>
32
+ <p class="text-gray-500">{{ $t('No old image') }}</p>
33
33
  </div>
34
34
  </div>
35
35
  </div>
@@ -54,7 +54,7 @@
54
54
  class="w-full max-w-sm h-auto object-cover rounded-lg cursor-pointer border hover:border-blue-500 transition-colors duration-200"
55
55
  />
56
56
  <div v-else class="w-full max-w-sm h-48 bg-gray-100 rounded-lg flex items-center justify-center">
57
- <p class="text-gray-500">No new image</p>
57
+ <p class="text-gray-500">{{ $t('No new image') }}</p>
58
58
  </div>
59
59
  </div>
60
60
  </div>
@@ -302,7 +302,7 @@ async function getRecords() {
302
302
  } catch (error) {
303
303
  console.error('Failed to get records:', error);
304
304
  isError.value = true;
305
- errorMessage.value = `Failed to fetch records. Please, try to re-run the action.`;
305
+ errorMessage.value = t(`Failed to fetch records. Please, try to re-run the action.`);
306
306
  }
307
307
  }
308
308
 
@@ -319,7 +319,7 @@ async function getImages() {
319
319
  } catch (error) {
320
320
  console.error('Failed to get images:', error);
321
321
  isError.value = true;
322
- errorMessage.value = `Failed to fetch images. Please, try to re-run the action.`;
322
+ errorMessage.value = t(`Failed to fetch images. Please, try to re-run the action.`);
323
323
  }
324
324
  }
325
325
 
@@ -375,7 +375,7 @@ async function convertImages(fieldName, img) {
375
375
 
376
376
  async function saveData() {
377
377
  if (!selected.value?.length) {
378
- adminforth.alert({ message: 'No items selected', variant: 'warning' });
378
+ adminforth.alert({ message: t('No items selected'), variant: 'warning' });
379
379
  return;
380
380
  }
381
381
  try {
@@ -420,16 +420,16 @@ async function saveData() {
420
420
  timeout: 'unlimited',
421
421
  });
422
422
  isError.value = true;
423
- errorMessage.value = `Failed to save data. You are not allowed to save.`;
423
+ errorMessage.value = t(`Failed to save data. You are not allowed to save.`);
424
424
  } else {
425
425
  console.error('Error saving data:', res);
426
426
  isError.value = true;
427
- errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
427
+ errorMessage.value = t(`Failed to save data. Please, try to re-run the action.`);
428
428
  }
429
429
  } catch (error) {
430
430
  console.error('Error saving data:', error);
431
431
  isError.value = true;
432
- errorMessage.value = `Failed to save data. Please, try to re-run the action.`;
432
+ errorMessage.value = t(`Failed to save data. Please, try to re-run the action.`);
433
433
  } finally {
434
434
  isLoading.value = false;
435
435
  }
@@ -474,7 +474,7 @@ async function runAiAction({
474
474
  if (rateLimitRes?.error) {
475
475
  isRateLimitExceeded = true;
476
476
  adminforth.alert({
477
- message: `Rate limit exceeded for "${actionType.replace('_', ' ')}" action. Please try again later.`,
477
+ message: t(`Rate limit exceeded for "${actionType.replace('_', ' ')}" action. Please try again later.`),
478
478
  variant: 'danger',
479
479
  timeout: 'unlimited',
480
480
  });
@@ -482,7 +482,7 @@ async function runAiAction({
482
482
  }
483
483
  } catch (e) {
484
484
  adminforth.alert({
485
- message: `Error checking rate limit for "${actionType.replace('_', ' ')}" action.`,
485
+ message: t(`Error checking rate limit for "${actionType.replace('_', ' ')}" action.`),
486
486
  variant: 'danger',
487
487
  timeout: 'unlimited',
488
488
  });
@@ -516,7 +516,7 @@ async function runAiAction({
516
516
  } catch (e) {
517
517
  console.error(`Error during ${actionType} for item ${i}:`, e);
518
518
  hasError = true;
519
- errorMessage = `Failed to ${actionType.replace('_', ' ')}. Please, try to re-run the action.`;
519
+ errorMessage = t(`Failed to ${actionType.replace('_', ' ')}. Please, try to re-run the action.`);
520
520
  return { success: false, index: i, error: e };
521
521
  }
522
522
  });
@@ -591,7 +591,7 @@ async function runAiAction({
591
591
  }
592
592
  isAtLeastOneInProgress = true;
593
593
  adminforth.alert({
594
- message: `Generation action "${actionType.replace('_', ' ')}" failed for record: ${recordId}. Error: ${jobResponse.job?.error || 'Unknown error'}`,
594
+ message: t(`Generation action "${actionType.replace('_', ' ')}" failed for record: ${recordId}. Error: ${jobResponse.job?.error || 'Unknown error'}`),
595
595
  variant: 'danger',
596
596
  timeout: 'unlimited',
597
597
  });
@@ -6,7 +6,7 @@
6
6
  >
7
7
  <!-- HEADER TEMPLATE -->
8
8
  <template #header:checkboxes="{ item }">
9
- MARK FOR SAVE
9
+ {{ $t('MARK FOR SAVE') }}
10
10
  </template>
11
11
  <!-- CHECKBOX CELL TEMPLATE -->
12
12
  <template #cell:checkboxes="{ item }">
@@ -28,12 +28,12 @@
28
28
  @click="zoomImage(image)"
29
29
  />
30
30
  <div v-else class="w-20 h-20">
31
- <p>Invalid source image</p>
31
+ <p>{{ $t('Invalid source image') }}</p>
32
32
  </div>
33
33
  </div>
34
34
  </div>
35
35
  <div class="flex items-center justify-center text-center w-20 h-20" v-else>
36
- <p>No images found</p>
36
+ <p>{{ $t('No images found') }}</p>
37
37
  </div>
38
38
  <transition name="fade">
39
39
  <div
@@ -66,7 +66,7 @@
66
66
  </Select>
67
67
  <Tooltip>
68
68
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
69
- <p class="text-sm ">old value</p>
69
+ <p class="text-sm ">{{ $t('old value') }}</p>
70
70
  </div>
71
71
  <template #tooltip>
72
72
  {{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}
@@ -82,7 +82,7 @@
82
82
  </Textarea>
83
83
  <Tooltip>
84
84
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
85
- <p class="text-sm ">old value</p>
85
+ <p class="text-sm ">{{ $t('old value') }}</p>
86
86
  </div>
87
87
  <template #tooltip>
88
88
  <p class="max-w-[200px]">{{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}</p>
@@ -97,7 +97,7 @@
97
97
  </Toggle>
98
98
  <Tooltip>
99
99
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
100
- <p class="text-sm ">old value</p>
100
+ <p class="text-sm ">{{ $t('old value') }}</p>
101
101
  </div>
102
102
  <template #tooltip>
103
103
  {{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}
@@ -113,7 +113,7 @@
113
113
  />
114
114
  <Tooltip>
115
115
  <div class="mt-2 flex items-center justify-start gap-1 hover:text-blue-500" :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }">
116
- <p class="text-sm ">old value</p>
116
+ <p class="text-sm ">{{ $t('old value') }}</p>
117
117
  </div>
118
118
  <template #tooltip>
119
119
  {{ oldData[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }}
@@ -137,14 +137,14 @@
137
137
  :class="{ 'opacity-0': !hovers[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] }"
138
138
  @click="() => {openImageCompare[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])][n] = true}"
139
139
  >
140
- old image
140
+ {{ $t('old image') }}
141
141
  </p>
142
142
  </div>
143
143
  <div v-else class="flex items-center justify-center text-center w-20 h-20">
144
144
  <Tooltip v-if="imageGenerationErrorMessage[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])] === 'No source images found'">
145
145
  <p
146
146
  >
147
- Can't generate image.
147
+ {{ $t("Can't generate image.") }}
148
148
  </p>
149
149
  <template #tooltip>
150
150
  {{ imageGenerationErrorMessage[tableColumnsIndexes.findIndex(el => el[primaryKey] === item[primaryKey])] }}
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ const jobs = new Map();
17
17
  export default class BulkAiFlowPlugin extends AdminForthPlugin {
18
18
  constructor(options) {
19
19
  super(options, import.meta.url);
20
+ this.rateLimiters = {};
20
21
  this.options = options;
21
22
  // for calculating average time
22
23
  this.totalCalls = 0;
@@ -47,18 +48,22 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
47
48
  return this.compileTemplates(this.options.generateImages, record, v => String(v.prompt));
48
49
  }
49
50
  checkRateLimit(field, fieldNameRateLimit, headers) {
50
- if (fieldNameRateLimit) {
51
- // rate limit
52
- // const { error } = RateLimiter.checkRateLimit(
53
- // field,
54
- // fieldNameRateLimit,
55
- // this.adminforth.auth.getClientIp(headers),
56
- // );
57
- const rateLimiter = new RateLimiter(fieldNameRateLimit);
58
- if (!rateLimiter.consume(`${field}-${this.adminforth.auth.getClientIp(headers)}`)) {
59
- return { error: "Rate limit exceeded" };
51
+ return __awaiter(this, void 0, void 0, function* () {
52
+ if (fieldNameRateLimit) {
53
+ // rate limit
54
+ // const { error } = RateLimiter.checkRateLimit(
55
+ // field,
56
+ // fieldNameRateLimit,
57
+ // this.adminforth.auth.getClientIp(headers),
58
+ // );
59
+ if (!this.rateLimiters[field]) {
60
+ this.rateLimiters[field] = new RateLimiter(fieldNameRateLimit);
61
+ }
62
+ if (!(yield this.rateLimiters[field].consume(`${field}-${this.adminforth.auth.getClientIp(headers)}`))) {
63
+ return { error: "Rate limit exceeded" };
64
+ }
60
65
  }
61
- }
66
+ });
62
67
  }
63
68
  analyze_image(jobId, recordId, adminUser, headers) {
64
69
  return __awaiter(this, void 0, void 0, function* () {
@@ -274,7 +279,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
274
279
  var _a;
275
280
  const Id = recordId;
276
281
  let isError = false;
277
- if (this.checkRateLimit(fieldName, this.options.generateImages[fieldName].rateLimit, headers)) {
282
+ if (yield this.checkRateLimit(fieldName, this.options.generateImages[fieldName].rateLimit, headers)) {
278
283
  jobs.set(jobId, { status: 'failed', error: "Rate limit exceeded" });
279
284
  return { error: "Rate limit exceeded" };
280
285
  }
@@ -707,17 +712,17 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
707
712
  var _b, _c, _d;
708
713
  const actionType = body.actionType;
709
714
  if (actionType === 'analyze' && ((_b = this.options.rateLimits) === null || _b === void 0 ? void 0 : _b.fillFieldsFromImages)) {
710
- if (this.checkRateLimit("fillFieldsFromImages", this.options.rateLimits.fillFieldsFromImages, headers)) {
715
+ if (yield this.checkRateLimit("fillFieldsFromImages", this.options.rateLimits.fillFieldsFromImages, headers)) {
711
716
  return { ok: false, error: "Rate limit exceeded for image analyze" };
712
717
  }
713
718
  }
714
719
  if (actionType === 'analyze_no_images' && ((_c = this.options.rateLimits) === null || _c === void 0 ? void 0 : _c.fillPlainFields)) {
715
- if (this.checkRateLimit("fillPlainFields", this.options.rateLimits.fillPlainFields, headers)) {
720
+ if (yield this.checkRateLimit("fillPlainFields", this.options.rateLimits.fillPlainFields, headers)) {
716
721
  return { ok: false, error: "Rate limit exceeded for plain field analyze" };
717
722
  }
718
723
  }
719
724
  if (actionType === 'generate_images' && ((_d = this.options.rateLimits) === null || _d === void 0 ? void 0 : _d.generateImages)) {
720
- if (this.checkRateLimit("generateImages", this.options.rateLimits.generateImages, headers)) {
725
+ if (yield this.checkRateLimit("generateImages", this.options.rateLimits.generateImages, headers)) {
721
726
  return { ok: false, error: "Rate limit exceeded for image generation" };
722
727
  }
723
728
  }
package/index.ts CHANGED
@@ -13,6 +13,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
13
13
  uploadPlugin: AdminForthPlugin;
14
14
  totalCalls: number;
15
15
  totalDuration: number;
16
+ rateLimiters: Record<string, RateLimiter> = {};
16
17
 
17
18
  constructor(options: PluginOptions) {
18
19
  super(options, import.meta.url);
@@ -54,7 +55,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
54
55
  return this.compileTemplates(this.options.generateImages, record, v => String(v.prompt));
55
56
  }
56
57
 
57
- private checkRateLimit(field: string,fieldNameRateLimit: string | undefined, headers: Record<string, string | string[] | undefined>): { error?: string } | void {
58
+ private async checkRateLimit(field: string, fieldNameRateLimit: string | undefined, headers: Record<string, string | string[] | undefined>): Promise<void | { error?: string; }> {
58
59
  if (fieldNameRateLimit) {
59
60
  // rate limit
60
61
  // const { error } = RateLimiter.checkRateLimit(
@@ -62,8 +63,10 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
62
63
  // fieldNameRateLimit,
63
64
  // this.adminforth.auth.getClientIp(headers),
64
65
  // );
65
- const rateLimiter = new RateLimiter(fieldNameRateLimit);
66
- if (!rateLimiter.consume(`${field}-${this.adminforth.auth.getClientIp(headers)}`)) {
66
+ if (!this.rateLimiters[field]) {
67
+ this.rateLimiters[field] = new RateLimiter(fieldNameRateLimit);
68
+ }
69
+ if (!await this.rateLimiters[field].consume(`${field}-${this.adminforth.auth.getClientIp(headers)}`)) {
67
70
  return { error: "Rate limit exceeded" };
68
71
  }
69
72
  }
@@ -271,7 +274,7 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
271
274
  private async regenerateImage(jobId: string, recordId: string, fieldName: string, prompt: string, adminUser: any, headers: Record<string, string | string[] | undefined>) {
272
275
  const Id = recordId;
273
276
  let isError = false;
274
- if (this.checkRateLimit(fieldName, this.options.generateImages[fieldName].rateLimit, headers)) {
277
+ if (await this.checkRateLimit(fieldName, this.options.generateImages[fieldName].rateLimit, headers)) {
275
278
  jobs.set(jobId, { status: 'failed', error: "Rate limit exceeded" });
276
279
  return { error: "Rate limit exceeded" };
277
280
  }
@@ -739,17 +742,17 @@ export default class BulkAiFlowPlugin extends AdminForthPlugin {
739
742
  handler: async ({ body, adminUser, headers }) => {
740
743
  const actionType = body.actionType;
741
744
  if (actionType === 'analyze' && this.options.rateLimits?.fillFieldsFromImages) {
742
- if (this.checkRateLimit("fillFieldsFromImages" ,this.options.rateLimits.fillFieldsFromImages, headers)) {
745
+ if (await this.checkRateLimit("fillFieldsFromImages" ,this.options.rateLimits.fillFieldsFromImages, headers)) {
743
746
  return {ok: false, error: "Rate limit exceeded for image analyze" };
744
747
  }
745
748
  }
746
749
  if (actionType === 'analyze_no_images' && this.options.rateLimits?.fillPlainFields) {
747
- if (this.checkRateLimit("fillPlainFields" ,this.options.rateLimits.fillPlainFields, headers)) {
750
+ if (await this.checkRateLimit("fillPlainFields" ,this.options.rateLimits.fillPlainFields, headers)) {
748
751
  return {ok: false, error: "Rate limit exceeded for plain field analyze" };
749
752
  }
750
753
  }
751
754
  if (actionType === 'generate_images' && this.options.rateLimits?.generateImages) {
752
- if (this.checkRateLimit("generateImages" ,this.options.rateLimits.generateImages, headers)) {
755
+ if (await this.checkRateLimit("generateImages" ,this.options.rateLimits.generateImages, headers)) {
753
756
  return {ok: false, error: "Rate limit exceeded for image generation" };
754
757
  }
755
758
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/bulk-ai-flow",
3
- "version": "1.14.4",
3
+ "version": "1.14.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },