@adminforth/upload 2.4.1 → 2.6.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.
package/build.log CHANGED
@@ -11,5 +11,5 @@ custom/preview.vue
11
11
  custom/tsconfig.json
12
12
  custom/uploader.vue
13
13
 
14
- sent 48,314 bytes received 134 bytes 96,896.00 bytes/sec
15
- total size is 47,825 speedup is 0.99
14
+ sent 49,208 bytes received 134 bytes 98,684.00 bytes/sec
15
+ total size is 48,726 speedup is 0.99
@@ -248,7 +248,6 @@ onMounted(async () => {
248
248
 
249
249
  if (resp?.files?.length) {
250
250
  attachmentFiles.value = resp.files;
251
- console.log('attachmentFiles', attachmentFiles.value);
252
251
  }
253
252
  } catch (err) {
254
253
  console.error('Failed to fetch attachment files', err);
@@ -337,7 +336,7 @@ async function generateImages() {
337
336
  let error = null;
338
337
  try {
339
338
  resp = await callAdminForthApi({
340
- path: `/plugin/${props.meta.pluginInstanceId}/generate_images`,
339
+ path: `/plugin/${props.meta.pluginInstanceId}/create-image-generation-job`,
341
340
  method: 'POST',
342
341
  body: {
343
342
  prompt: prompt.value,
@@ -346,16 +345,13 @@ async function generateImages() {
346
345
  });
347
346
  } catch (e) {
348
347
  console.error(e);
349
- } finally {
350
- clearInterval(ticker);
351
- loadingTimer.value = null;
352
- loading.value = false;
353
348
  }
349
+
354
350
  if (resp?.error) {
355
351
  error = resp.error;
356
352
  }
357
353
  if (!resp) {
358
- error = $t('Error generating images, something went wrong');
354
+ error = $t('Error creating image generation job');
359
355
  }
360
356
 
361
357
  if (error) {
@@ -371,11 +367,53 @@ async function generateImages() {
371
367
  return;
372
368
  }
373
369
 
370
+ const jobId = resp.jobId;
371
+ let jobStatus = null;
372
+ let jobResponse = null;
373
+ do {
374
+ jobResponse = await callAdminForthApi({
375
+ path: `/plugin/${props.meta.pluginInstanceId}/get-image-generation-job-status`,
376
+ method: 'POST',
377
+ body: { jobId },
378
+ });
379
+ if (jobResponse?.error) {
380
+ error = jobResponse.error;
381
+ break;
382
+ };
383
+ jobStatus = jobResponse?.job?.status;
384
+ if (jobStatus === 'failed') {
385
+ error = jobResponse?.job?.error || $t('Image generation job failed');
386
+ }
387
+ if (jobStatus === 'timeout') {
388
+ error = jobResponse?.job?.error || $t('Image generation job timeout');
389
+ }
390
+ await new Promise((resolve) => setTimeout(resolve, 2000));
391
+ } while (jobStatus === 'in_progress')
392
+
393
+ if (error) {
394
+ adminforth.alert({
395
+ message: error,
396
+ variant: 'danger',
397
+ timeout: 'unlimited',
398
+ });
399
+ clearInterval(ticker);
400
+ loadingTimer.value = null;
401
+ loading.value = false;
402
+ return;
403
+ }
404
+
405
+ const respImages = jobResponse?.job?.images || [];
406
+
374
407
  images.value = [
375
408
  ...images.value,
376
- ...resp.images,
409
+ ...respImages,
377
410
  ];
378
411
 
412
+ clearInterval(ticker);
413
+ loadingTimer.value = null;
414
+ loading.value = false;
415
+
416
+
379
417
  // images.value = [
380
418
  // 'https://via.placeholder.com/600x400?text=Image+1',
381
419
  // 'https://via.placeholder.com/600x400?text=Image+2',
@@ -386,7 +424,6 @@ async function generateImages() {
386
424
  caurosel.value = new Carousel(
387
425
  document.getElementById('gallery'),
388
426
  images.value.map((img, index) => {
389
- console.log('mapping image', img, index);
390
427
  return {
391
428
  image: img,
392
429
  el: document.getElementById('gallery').querySelector(`[data-carousel-item]:nth-child(${index + 1})`),
@@ -248,7 +248,6 @@ onMounted(async () => {
248
248
 
249
249
  if (resp?.files?.length) {
250
250
  attachmentFiles.value = resp.files;
251
- console.log('attachmentFiles', attachmentFiles.value);
252
251
  }
253
252
  } catch (err) {
254
253
  console.error('Failed to fetch attachment files', err);
@@ -337,7 +336,7 @@ async function generateImages() {
337
336
  let error = null;
338
337
  try {
339
338
  resp = await callAdminForthApi({
340
- path: `/plugin/${props.meta.pluginInstanceId}/generate_images`,
339
+ path: `/plugin/${props.meta.pluginInstanceId}/create-image-generation-job`,
341
340
  method: 'POST',
342
341
  body: {
343
342
  prompt: prompt.value,
@@ -346,16 +345,13 @@ async function generateImages() {
346
345
  });
347
346
  } catch (e) {
348
347
  console.error(e);
349
- } finally {
350
- clearInterval(ticker);
351
- loadingTimer.value = null;
352
- loading.value = false;
353
348
  }
349
+
354
350
  if (resp?.error) {
355
351
  error = resp.error;
356
352
  }
357
353
  if (!resp) {
358
- error = $t('Error generating images, something went wrong');
354
+ error = $t('Error creating image generation job');
359
355
  }
360
356
 
361
357
  if (error) {
@@ -371,11 +367,53 @@ async function generateImages() {
371
367
  return;
372
368
  }
373
369
 
370
+ const jobId = resp.jobId;
371
+ let jobStatus = null;
372
+ let jobResponse = null;
373
+ do {
374
+ jobResponse = await callAdminForthApi({
375
+ path: `/plugin/${props.meta.pluginInstanceId}/get-image-generation-job-status`,
376
+ method: 'POST',
377
+ body: { jobId },
378
+ });
379
+ if (jobResponse?.error) {
380
+ error = jobResponse.error;
381
+ break;
382
+ };
383
+ jobStatus = jobResponse?.job?.status;
384
+ if (jobStatus === 'failed') {
385
+ error = jobResponse?.job?.error || $t('Image generation job failed');
386
+ }
387
+ if (jobStatus === 'timeout') {
388
+ error = jobResponse?.job?.error || $t('Image generation job timeout');
389
+ }
390
+ await new Promise((resolve) => setTimeout(resolve, 2000));
391
+ } while (jobStatus === 'in_progress')
392
+
393
+ if (error) {
394
+ adminforth.alert({
395
+ message: error,
396
+ variant: 'danger',
397
+ timeout: 'unlimited',
398
+ });
399
+ clearInterval(ticker);
400
+ loadingTimer.value = null;
401
+ loading.value = false;
402
+ return;
403
+ }
404
+
405
+ const respImages = jobResponse?.job?.images || [];
406
+
374
407
  images.value = [
375
408
  ...images.value,
376
- ...resp.images,
409
+ ...respImages,
377
410
  ];
378
411
 
412
+ clearInterval(ticker);
413
+ loadingTimer.value = null;
414
+ loading.value = false;
415
+
416
+
379
417
  // images.value = [
380
418
  // 'https://via.placeholder.com/600x400?text=Image+1',
381
419
  // 'https://via.placeholder.com/600x400?text=Image+2',
@@ -386,7 +424,6 @@ async function generateImages() {
386
424
  caurosel.value = new Carousel(
387
425
  document.getElementById('gallery'),
388
426
  images.value.map((img, index) => {
389
- console.log('mapping image', img, index);
390
427
  return {
391
428
  image: img,
392
429
  el: document.getElementById('gallery').querySelector(`[data-carousel-item]:nth-child(${index + 1})`),
package/dist/index.js CHANGED
@@ -10,9 +10,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { AdminForthPlugin, Filters, suggestIfTypo } from "adminforth";
11
11
  import { Readable } from "stream";
12
12
  import { RateLimiter } from "adminforth";
13
+ import { randomUUID } from "crypto";
13
14
  import { interpretResource } from 'adminforth';
14
15
  import { ActionCheckSource } from 'adminforth';
15
16
  const ADMINFORTH_NOT_YET_USED_TAG = 'adminforth-candidate-for-cleanup';
17
+ const jobs = new Map();
16
18
  export default class UploadPlugin extends AdminForthPlugin {
17
19
  constructor(options) {
18
20
  var _a, _b, _c;
@@ -21,10 +23,80 @@ export default class UploadPlugin extends AdminForthPlugin {
21
23
  // for calcualting average time
22
24
  this.totalCalls = 0;
23
25
  this.totalDuration = 0;
26
+ this.getFileDownloadUrl = (path_1, ...args_1) => __awaiter(this, [path_1, ...args_1], void 0, function* (path, expiresInSeconds = 1800) {
27
+ if (!path) {
28
+ return '';
29
+ }
30
+ return this.options.storageAdapter.getDownloadUrl(path, expiresInSeconds);
31
+ });
24
32
  if ((_b = (_a = this.options.generation) === null || _a === void 0 ? void 0 : _a.rateLimit) === null || _b === void 0 ? void 0 : _b.limit) {
25
33
  this.rateLimiter = new RateLimiter((_c = this.options.generation.rateLimit) === null || _c === void 0 ? void 0 : _c.limit);
26
34
  }
27
35
  }
36
+ generateImages(jobId, prompt, recordId, adminUser, headers) {
37
+ return __awaiter(this, void 0, void 0, function* () {
38
+ var _a, _b;
39
+ if ((_a = this.options.generation.rateLimit) === null || _a === void 0 ? void 0 : _a.limit) {
40
+ // rate limit
41
+ // const { error } = RateLimiter.checkRateLimit(
42
+ // this.pluginInstanceId,
43
+ // this.options.generation.rateLimit?.limit,
44
+ // this.adminforth.auth.getClientIp(headers),
45
+ // );
46
+ if (!(yield this.rateLimiter.consume(`${this.pluginInstanceId}-${this.adminforth.auth.getClientIp(headers)}`))) {
47
+ jobs.set(jobId, { status: "failed", error: this.options.generation.rateLimit.errorMessage });
48
+ return { error: this.options.generation.rateLimit.errorMessage };
49
+ }
50
+ }
51
+ let attachmentFiles = [];
52
+ if (this.options.generation.attachFiles) {
53
+ // TODO - does it require additional allowed action to check this record id has access to get the image?
54
+ // or should we mention in docs that user should do validation in method itself
55
+ const record = yield this.adminforth.resource(this.resourceConfig.resourceId).get([Filters.EQ((_b = this.resourceConfig.columns.find(c => c.primaryKey)) === null || _b === void 0 ? void 0 : _b.name, recordId)]);
56
+ if (!record) {
57
+ return { error: `Record with id ${recordId} not found` };
58
+ }
59
+ attachmentFiles = yield this.options.generation.attachFiles({ record, adminUser });
60
+ // if files is not array, make it array
61
+ if (!Array.isArray(attachmentFiles)) {
62
+ attachmentFiles = [attachmentFiles];
63
+ }
64
+ }
65
+ let error = undefined;
66
+ const STUB_MODE = false;
67
+ const images = yield Promise.all((new Array(this.options.generation.countToGenerate)).fill(0).map(() => __awaiter(this, void 0, void 0, function* () {
68
+ if (STUB_MODE) {
69
+ yield new Promise((resolve) => setTimeout(resolve, 2000));
70
+ return `https://picsum.photos/200/300?random=${Math.floor(Math.random() * 1000)}`;
71
+ }
72
+ const start = +new Date();
73
+ let resp;
74
+ try {
75
+ resp = yield this.options.generation.adapter.generate({
76
+ prompt,
77
+ inputFiles: attachmentFiles,
78
+ n: 1,
79
+ size: this.options.generation.outputSize,
80
+ });
81
+ }
82
+ catch (e) {
83
+ error = `No response from image generation provider: ${e.message}. Please check your prompt or try again later.`;
84
+ return;
85
+ }
86
+ if (resp.error) {
87
+ console.error('Error generating image', resp.error);
88
+ error = resp.error;
89
+ return;
90
+ }
91
+ this.totalCalls++;
92
+ this.totalDuration += (+new Date() - start) / 1000;
93
+ return resp.imageURLs[0];
94
+ })));
95
+ jobs.set(jobId, { status: "completed", images, error });
96
+ return { ok: true };
97
+ });
98
+ }
99
+ ;
28
100
  instanceUniqueRepresentation(pluginOptions) {
29
101
  return `${pluginOptions.pathColumnName}`;
30
102
  }
@@ -282,66 +354,30 @@ export default class UploadPlugin extends AdminForthPlugin {
282
354
  // }'
283
355
  server.endpoint({
284
356
  method: 'POST',
285
- path: `/plugin/${this.pluginInstanceId}/generate_images`,
357
+ path: `/plugin/${this.pluginInstanceId}/create-image-generation-job`,
286
358
  handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
287
- var _b;
288
359
  const { prompt, recordId } = body;
289
- if (this.rateLimiter) {
290
- // rate limit
291
- // const { error } = RateLimiter.checkRateLimit(
292
- // this.pluginInstanceId,
293
- // this.options.generation.rateLimit?.limit,
294
- // this.adminforth.auth.getClientIp(headers),
295
- // );
296
- if (!(yield this.rateLimiter.consume(`${this.pluginInstanceId}-${this.adminforth.auth.getClientIp(headers)}`))) {
297
- return { error: this.options.generation.rateLimit.errorMessage };
298
- }
360
+ const jobId = randomUUID();
361
+ jobs.set(jobId, { status: "in_progress" });
362
+ this.generateImages(jobId, prompt, recordId, adminUser, headers);
363
+ setTimeout(() => jobs.delete(jobId), 1800000);
364
+ setTimeout(() => { jobs.set(jobId, { status: "timeout" }); }, 300000);
365
+ return { ok: true, jobId };
366
+ })
367
+ });
368
+ server.endpoint({
369
+ method: 'POST',
370
+ path: `/plugin/${this.pluginInstanceId}/get-image-generation-job-status`,
371
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
372
+ const jobId = body.jobId;
373
+ if (!jobId) {
374
+ return { error: "Can't find job id" };
299
375
  }
300
- let attachmentFiles = [];
301
- if (this.options.generation.attachFiles) {
302
- // TODO - does it require additional allowed action to check this record id has access to get the image?
303
- // or should we mention in docs that user should do validation in method itself
304
- const record = yield this.adminforth.resource(this.resourceConfig.resourceId).get([Filters.EQ((_b = this.resourceConfig.columns.find((column) => column.primaryKey)) === null || _b === void 0 ? void 0 : _b.name, recordId)]);
305
- if (!record) {
306
- return { error: `Record with id ${recordId} not found` };
307
- }
308
- attachmentFiles = yield this.options.generation.attachFiles({ record, adminUser });
309
- // if files is not array, make it array
310
- if (!Array.isArray(attachmentFiles)) {
311
- attachmentFiles = [attachmentFiles];
312
- }
376
+ const job = jobs.get(jobId);
377
+ if (!job) {
378
+ return { error: "Job not found" };
313
379
  }
314
- let error = undefined;
315
- const STUB_MODE = false;
316
- const images = yield Promise.all((new Array(this.options.generation.countToGenerate)).fill(0).map(() => __awaiter(this, void 0, void 0, function* () {
317
- if (STUB_MODE) {
318
- yield new Promise((resolve) => setTimeout(resolve, 2000));
319
- return `https://picsum.photos/200/300?random=${Math.floor(Math.random() * 1000)}`;
320
- }
321
- const start = +new Date();
322
- let resp;
323
- try {
324
- resp = yield this.options.generation.adapter.generate({
325
- prompt,
326
- inputFiles: attachmentFiles,
327
- n: 1,
328
- size: this.options.generation.outputSize,
329
- });
330
- }
331
- catch (e) {
332
- error = `No response from image generation provider: ${e.message}. Please check your prompt or try again later.`;
333
- return;
334
- }
335
- if (resp.error) {
336
- console.error('Error generating image', resp.error);
337
- error = resp.error;
338
- return;
339
- }
340
- this.totalCalls++;
341
- this.totalDuration += (+new Date() - start) / 1000;
342
- return resp.imageURLs[0];
343
- })));
344
- return { error, images };
380
+ return { ok: true, job };
345
381
  })
346
382
  });
347
383
  server.endpoint({
package/index.ts CHANGED
@@ -3,11 +3,12 @@ import { PluginOptions } from './types.js';
3
3
  import { AdminForthPlugin, AdminForthResourceColumn, AdminForthResource, Filters, IAdminForth, IHttpServer, suggestIfTypo } from "adminforth";
4
4
  import { Readable } from "stream";
5
5
  import { RateLimiter } from "adminforth";
6
+ import { randomUUID } from "crypto";
6
7
  import { interpretResource } from 'adminforth';
7
8
  import { ActionCheckSource } from 'adminforth';
8
9
 
9
10
  const ADMINFORTH_NOT_YET_USED_TAG = 'adminforth-candidate-for-cleanup';
10
-
11
+ const jobs = new Map();
11
12
  export default class UploadPlugin extends AdminForthPlugin {
12
13
  options: PluginOptions;
13
14
 
@@ -20,6 +21,8 @@ export default class UploadPlugin extends AdminForthPlugin {
20
21
 
21
22
  rateLimiter: RateLimiter;
22
23
 
24
+ getFileDownloadUrl: ((path: string) => Promise<string>);
25
+
23
26
  constructor(options: PluginOptions) {
24
27
  super(options, import.meta.url);
25
28
  this.options = options;
@@ -27,11 +30,94 @@ export default class UploadPlugin extends AdminForthPlugin {
27
30
  // for calcualting average time
28
31
  this.totalCalls = 0;
29
32
  this.totalDuration = 0;
33
+ this.getFileDownloadUrl = async (path: string, expiresInSeconds: number = 1800) : Promise<string> => {
34
+ if (!path) {
35
+ return '';
36
+ }
37
+ return this.options.storageAdapter.getDownloadUrl(path, expiresInSeconds);
38
+ }
30
39
  if (this.options.generation?.rateLimit?.limit) {
31
- this.rateLimiter = new RateLimiter(this.options.generation.rateLimit?.limit)
40
+ this.rateLimiter = new RateLimiter(this.options.generation.rateLimit?.limit)
32
41
  }
33
42
  }
34
43
 
44
+ private async generateImages(jobId: string, prompt: string, recordId: any, adminUser: any, headers: any) {
45
+ if (this.options.generation.rateLimit?.limit) {
46
+ // rate limit
47
+ // const { error } = RateLimiter.checkRateLimit(
48
+ // this.pluginInstanceId,
49
+ // this.options.generation.rateLimit?.limit,
50
+ // this.adminforth.auth.getClientIp(headers),
51
+ // );
52
+ if (!await this.rateLimiter.consume(`${this.pluginInstanceId}-${this.adminforth.auth.getClientIp(headers)}`)) {
53
+ jobs.set(jobId, { status: "failed", error: this.options.generation.rateLimit.errorMessage });
54
+ return { error: this.options.generation.rateLimit.errorMessage };
55
+ }
56
+ }
57
+ let attachmentFiles = [];
58
+ if (this.options.generation.attachFiles) {
59
+ // TODO - does it require additional allowed action to check this record id has access to get the image?
60
+ // or should we mention in docs that user should do validation in method itself
61
+ const record = await this.adminforth.resource(this.resourceConfig.resourceId).get(
62
+ [Filters.EQ(this.resourceConfig.columns.find(c => c.primaryKey)?.name, recordId)]
63
+ );
64
+
65
+
66
+ if (!record) {
67
+ return { error: `Record with id ${recordId} not found` };
68
+ }
69
+
70
+ attachmentFiles = await this.options.generation.attachFiles({ record, adminUser });
71
+ // if files is not array, make it array
72
+ if (!Array.isArray(attachmentFiles)) {
73
+ attachmentFiles = [attachmentFiles];
74
+ }
75
+
76
+ }
77
+
78
+ let error: string | undefined = undefined;
79
+
80
+ const STUB_MODE = false;
81
+
82
+ const images = await Promise.all(
83
+ (new Array(this.options.generation.countToGenerate)).fill(0).map(async () => {
84
+ if (STUB_MODE) {
85
+ await new Promise((resolve) => setTimeout(resolve, 2000));
86
+ return `https://picsum.photos/200/300?random=${Math.floor(Math.random() * 1000)}`;
87
+ }
88
+ const start = +new Date();
89
+ let resp;
90
+ try {
91
+ resp = await this.options.generation.adapter.generate(
92
+ {
93
+ prompt,
94
+ inputFiles: attachmentFiles,
95
+ n: 1,
96
+ size: this.options.generation.outputSize,
97
+ }
98
+ )
99
+ } catch (e: any) {
100
+ error = `No response from image generation provider: ${e.message}. Please check your prompt or try again later.`;
101
+ return;
102
+ }
103
+
104
+ if (resp.error) {
105
+ console.error('Error generating image', resp.error);
106
+ error = resp.error;
107
+ return;
108
+ }
109
+
110
+ this.totalCalls++;
111
+ this.totalDuration += (+new Date() - start) / 1000;
112
+
113
+ return resp.imageURLs[0]
114
+
115
+ })
116
+ );
117
+ jobs.set(jobId, { status: "completed", images, error });
118
+ return { ok: true };
119
+ };
120
+
35
121
  instanceUniqueRepresentation(pluginOptions: any) : string {
36
122
  return `${pluginOptions.pathColumnName}`;
37
123
  }
@@ -315,81 +401,34 @@ export default class UploadPlugin extends AdminForthPlugin {
315
401
 
316
402
  server.endpoint({
317
403
  method: 'POST',
318
- path: `/plugin/${this.pluginInstanceId}/generate_images`,
404
+ path: `/plugin/${this.pluginInstanceId}/create-image-generation-job`,
319
405
  handler: async ({ body, adminUser, headers }) => {
320
406
  const { prompt, recordId } = body;
321
- if (this.rateLimiter) {
322
- // rate limit
323
- // const { error } = RateLimiter.checkRateLimit(
324
- // this.pluginInstanceId,
325
- // this.options.generation.rateLimit?.limit,
326
- // this.adminforth.auth.getClientIp(headers),
327
- // );
328
- if (!await this.rateLimiter.consume(`${this.pluginInstanceId}-${this.adminforth.auth.getClientIp(headers)}`)) {
329
- return { error: this.options.generation.rateLimit.errorMessage };
330
- }
331
- }
332
- let attachmentFiles = [];
333
- if (this.options.generation.attachFiles) {
334
- // TODO - does it require additional allowed action to check this record id has access to get the image?
335
- // or should we mention in docs that user should do validation in method itself
336
- const record = await this.adminforth.resource(this.resourceConfig.resourceId).get(
337
- [Filters.EQ(this.resourceConfig.columns.find((column: any) => column.primaryKey)?.name, recordId)]
338
- );
339
-
340
- if (!record) {
341
- return { error: `Record with id ${recordId} not found` };
342
- }
343
-
344
- attachmentFiles = await this.options.generation.attachFiles({ record, adminUser });
345
- // if files is not array, make it array
346
- if (!Array.isArray(attachmentFiles)) {
347
- attachmentFiles = [attachmentFiles];
348
- }
349
-
350
- }
351
-
352
- let error: string | undefined = undefined;
353
-
354
- const STUB_MODE = false;
355
407
 
356
- const images = await Promise.all(
357
- (new Array(this.options.generation.countToGenerate)).fill(0).map(async () => {
358
- if (STUB_MODE) {
359
- await new Promise((resolve) => setTimeout(resolve, 2000));
360
- return `https://picsum.photos/200/300?random=${Math.floor(Math.random() * 1000)}`;
361
- }
362
- const start = +new Date();
363
- let resp;
364
- try {
365
- resp = await this.options.generation.adapter.generate(
366
- {
367
- prompt,
368
- inputFiles: attachmentFiles,
369
- n: 1,
370
- size: this.options.generation.outputSize,
371
- }
372
- )
373
- } catch (e: any) {
374
- error = `No response from image generation provider: ${e.message}. Please check your prompt or try again later.`;
375
- return;
376
- }
377
-
378
- if (resp.error) {
379
- console.error('Error generating image', resp.error);
380
- error = resp.error;
381
- return;
382
- }
408
+ const jobId = randomUUID();
409
+ jobs.set(jobId, { status: "in_progress" });
383
410
 
384
- this.totalCalls++;
385
- this.totalDuration += (+new Date() - start) / 1000;
386
-
387
- return resp.imageURLs[0]
411
+ this.generateImages(jobId, prompt, recordId, adminUser, headers);
412
+ setTimeout(() => jobs.delete(jobId), 1_800_000);
413
+ setTimeout(() => {jobs.set(jobId, { status: "timeout" });}, 300_000);
388
414
 
389
- })
390
- );
415
+ return { ok: true, jobId };
416
+ }
417
+ });
391
418
 
392
- return { error, images };
419
+ server.endpoint({
420
+ method: 'POST',
421
+ path: `/plugin/${this.pluginInstanceId}/get-image-generation-job-status`,
422
+ handler: async ({ body, adminUser, headers }) => {
423
+ const jobId = body.jobId;
424
+ if (!jobId) {
425
+ return { error: "Can't find job id" };
426
+ }
427
+ const job = jobs.get(jobId);
428
+ if (!job) {
429
+ return { error: "Job not found" };
430
+ }
431
+ return { ok: true, job };
393
432
  }
394
433
  });
395
434
 
@@ -451,5 +490,6 @@ export default class UploadPlugin extends AdminForthPlugin {
451
490
  });
452
491
 
453
492
  }
493
+
454
494
 
455
495
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/upload",
3
- "version": "2.4.1",
3
+ "version": "2.6.0",
4
4
  "description": "Plugin for uploading files for adminforth",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",