@crowdin/app-project-module 0.39.0 → 0.40.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.
Files changed (44) hide show
  1. package/out/handlers/integration/crowdin-update.js +36 -17
  2. package/out/handlers/integration/integration-data.js +2 -0
  3. package/out/handlers/integration/integration-update.js +35 -17
  4. package/out/handlers/integration/integration-webhook.js +1 -1
  5. package/out/handlers/integration/job-cancel.d.ts +3 -0
  6. package/out/handlers/integration/job-cancel.js +28 -0
  7. package/out/handlers/integration/job-info.d.ts +3 -0
  8. package/out/handlers/integration/job-info.js +54 -0
  9. package/out/handlers/integration/main.js +6 -3
  10. package/out/handlers/integration/user-errors.d.ts +3 -0
  11. package/out/handlers/{user-errors.js → integration/user-errors.js} +5 -5
  12. package/out/index.d.ts +2 -1
  13. package/out/index.js +35 -27
  14. package/out/middlewares/crowdin-client.js +1 -0
  15. package/out/middlewares/ui-module.js +1 -0
  16. package/out/models/index.d.ts +48 -17
  17. package/out/models/index.js +1 -0
  18. package/out/models/job.d.ts +44 -0
  19. package/out/models/job.js +16 -0
  20. package/out/static/css/styles.css +1 -1
  21. package/out/static/js/form.js +17 -41
  22. package/out/static/js/main.js +1 -1
  23. package/out/storage/index.d.ts +6 -0
  24. package/out/storage/index.js +3 -0
  25. package/out/storage/mysql.d.ts +6 -0
  26. package/out/storage/mysql.js +106 -0
  27. package/out/storage/postgre.d.ts +6 -0
  28. package/out/storage/postgre.js +107 -0
  29. package/out/storage/sqlite.d.ts +6 -0
  30. package/out/storage/sqlite.js +96 -0
  31. package/out/util/cron.d.ts +1 -0
  32. package/out/util/cron.js +47 -3
  33. package/out/util/defaults.js +4 -11
  34. package/out/util/file-snapshot.js +2 -0
  35. package/out/util/files.d.ts +2 -1
  36. package/out/util/files.js +19 -1
  37. package/out/util/index.js +3 -1
  38. package/out/util/job.d.ts +12 -0
  39. package/out/util/job.js +88 -0
  40. package/out/util/logger.js +4 -0
  41. package/out/util/webhooks.js +50 -4
  42. package/out/views/main.handlebars +154 -6
  43. package/package.json +16 -15
  44. package/out/handlers/user-errors.d.ts +0 -3
@@ -1,6 +1,7 @@
1
1
  /// <reference types="node" />
2
- import { ProcessFileString } from '../models';
2
+ import { ProcessFileString, SkipIntegrationNodes, TreeItem } from '../models';
3
3
  export declare const MAX_BODY_SIZE: number;
4
4
  export declare function storeFile(fileContent: Buffer, folder: string): Promise<string>;
5
5
  export declare function getFileContent(url: string): Promise<Buffer>;
6
6
  export declare function getFileStrings(url: string): Promise<ProcessFileString[]>;
7
+ export declare function skipFilesByRegex(files: TreeItem[] | undefined, skipIntegrationNodes?: SkipIntegrationNodes): TreeItem[];
package/out/util/files.js CHANGED
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getFileStrings = exports.getFileContent = exports.storeFile = exports.MAX_BODY_SIZE = void 0;
15
+ exports.skipFilesByRegex = exports.getFileStrings = exports.getFileContent = exports.storeFile = exports.MAX_BODY_SIZE = void 0;
16
16
  const axios_1 = __importDefault(require("axios"));
17
17
  const fs_1 = __importDefault(require("fs"));
18
18
  const path_1 = __importDefault(require("path"));
@@ -45,3 +45,21 @@ function getFileStrings(url) {
45
45
  });
46
46
  }
47
47
  exports.getFileStrings = getFileStrings;
48
+ function skipFilesByRegex(files, skipIntegrationNodes) {
49
+ if (!Array.isArray(files)) {
50
+ return [];
51
+ }
52
+ if (skipIntegrationNodes) {
53
+ files = files.filter((file) => file);
54
+ if (skipIntegrationNodes.fileNamePattern) {
55
+ const regex = new RegExp(skipIntegrationNodes.fileNamePattern);
56
+ files = files.filter((file) => !('type' in file) || !regex.test(file.name));
57
+ }
58
+ if (skipIntegrationNodes.folderNamePattern) {
59
+ const regex = new RegExp(skipIntegrationNodes.folderNamePattern);
60
+ files = files.filter((file) => 'type' in file || !regex.test(file.name));
61
+ }
62
+ }
63
+ return files;
64
+ }
65
+ exports.skipFilesByRegex = skipFilesByRegex;
package/out/util/index.js CHANGED
@@ -56,7 +56,9 @@ function handleError(err, req, res) {
56
56
  res.redirect('/');
57
57
  return;
58
58
  }
59
- res.status(code).send({ message: (0, logger_1.getErrorMessage)(err), code });
59
+ if (!res.headersSent) {
60
+ res.status(code).send({ message: (0, logger_1.getErrorMessage)(err), code });
61
+ }
60
62
  });
61
63
  }
62
64
  function runAsyncWrapper(callback) {
@@ -0,0 +1,12 @@
1
+ import { JobClient, JobType } from '../models/job';
2
+ import { Response } from 'express';
3
+ export declare function runAsJob({ integrationId, crowdinId, type, title, payload, res, jobCallback, onError, }: {
4
+ integrationId: string;
5
+ crowdinId: string;
6
+ type: JobType;
7
+ title?: string;
8
+ payload?: any;
9
+ res?: Response;
10
+ jobCallback: (arg1: JobClient) => Promise<any>;
11
+ onError?: (e: any) => Promise<void>;
12
+ }): Promise<void>;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.runAsJob = void 0;
13
+ const job_1 = require("../models/job");
14
+ const storage_1 = require("../storage");
15
+ const logger_1 = require("./logger");
16
+ const blockingJobs = {
17
+ [job_1.JobType.UPDATE_TO_CROWDIN]: [job_1.JobType.UPDATE_TO_CROWDIN, job_1.JobType.UPDATE_TO_INTEGRATION],
18
+ [job_1.JobType.UPDATE_TO_INTEGRATION]: [job_1.JobType.UPDATE_TO_CROWDIN, job_1.JobType.UPDATE_TO_INTEGRATION],
19
+ };
20
+ function runAsJob({ integrationId, crowdinId, type, title, payload, res, jobCallback, onError, }) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const storage = (0, storage_1.getStorage)();
23
+ const activeJobs = yield storage.getActiveJobs({ integrationId, crowdinId });
24
+ if (activeJobs === null || activeJobs === void 0 ? void 0 : activeJobs.length) {
25
+ const existingJob = activeJobs.find((job) => blockingJobs[type].includes(job.type));
26
+ if (existingJob === null || existingJob === void 0 ? void 0 : existingJob.id) {
27
+ if (res) {
28
+ res.status(202).send({ jobId: existingJob.id, message: 'Job is already running' });
29
+ }
30
+ return;
31
+ }
32
+ }
33
+ const jobId = yield storage.createJob({
34
+ integrationId,
35
+ crowdinId,
36
+ type,
37
+ title: title || '',
38
+ payload: JSON.stringify(payload),
39
+ });
40
+ if (res) {
41
+ res.status(202).send({ jobId });
42
+ }
43
+ const job = {
44
+ get: function getJob() {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ return yield storage.getJob({ id: jobId });
47
+ });
48
+ },
49
+ update: function updateProgress({ progress, status, info, data }) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ const prevData = yield this.get();
52
+ if ((prevData === null || prevData === void 0 ? void 0 : prevData.status) === job_1.JobStatus.CANCELED) {
53
+ return { isCanceled: true };
54
+ }
55
+ yield storage.updateJob({
56
+ id: jobId,
57
+ progress,
58
+ status: status || job_1.JobStatus.IN_PROGRESS,
59
+ info,
60
+ data: JSON.stringify(data),
61
+ });
62
+ return { isCanceled: false };
63
+ });
64
+ },
65
+ };
66
+ try {
67
+ const data = yield jobCallback(job);
68
+ yield job.update({
69
+ progress: 100,
70
+ status: job_1.JobStatus.FINISHED,
71
+ data,
72
+ });
73
+ }
74
+ catch (e) {
75
+ yield job.update({
76
+ status: job_1.JobStatus.FAILED,
77
+ info: (0, logger_1.getErrorMessage)(e),
78
+ });
79
+ if (onError) {
80
+ yield onError(e);
81
+ }
82
+ else {
83
+ throw e;
84
+ }
85
+ }
86
+ });
87
+ }
88
+ exports.runAsJob = runAsJob;
@@ -67,7 +67,9 @@ function log(message, context) {
67
67
  else {
68
68
  let prefix = `[${new Date().toISOString()}]`;
69
69
  if (context) {
70
+ logsFormatter.resetContext();
70
71
  logsFormatter.setContext({
72
+ appIdentifier: context.appIdentifier || '',
71
73
  project: {
72
74
  id: context.jwtPayload.context.project_id,
73
75
  identifier: (_a = context.jwtPayload.context.project_identifier) !== null && _a !== void 0 ? _a : '',
@@ -100,7 +102,9 @@ function logError(e, context) {
100
102
  }
101
103
  else {
102
104
  if (context) {
105
+ logsFormatter.resetContext();
103
106
  logsFormatter.setContext({
107
+ appIdentifier: context.appIdentifier || '',
104
108
  project: {
105
109
  id: context.jwtPayload.context.project_id,
106
110
  identifier: (_a = context.jwtPayload.context.project_identifier) !== null && _a !== void 0 ? _a : '',
@@ -44,6 +44,8 @@ const connection_1 = require("./connection");
44
44
  const defaults_1 = require("./defaults");
45
45
  const index_1 = require("./index");
46
46
  const logger_1 = require("./logger");
47
+ const prefetchCount = 20;
48
+ const forceProcessDelay = 5000;
47
49
  exports.HookEvents = {
48
50
  fileAdded: 'file.added',
49
51
  fileDeleted: 'file.deleted',
@@ -308,7 +310,7 @@ function listenQueueMessage(config, integration, queueUrl, queueName) {
308
310
  const channel = yield connection.createChannel();
309
311
  if (channel) {
310
312
  yield channel.assertQueue(queueName, { durable: true });
311
- yield channel.prefetch(1);
313
+ yield channel.prefetch(prefetchCount);
312
314
  yield channel.consume(queueName, consumer(channel, config, integration), { noAck: false });
313
315
  }
314
316
  }
@@ -321,23 +323,67 @@ function listenQueueMessage(config, integration, queueUrl, queueName) {
321
323
  }
322
324
  exports.listenQueueMessage = listenQueueMessage;
323
325
  function consumer(channel, config, integration) {
326
+ let messagesCounter = 0;
327
+ let webhooksInfo = {};
328
+ let webhooksData = [];
329
+ let timeoutId;
330
+ const resetStateVariables = () => {
331
+ messagesCounter = 0;
332
+ webhooksInfo = {};
333
+ webhooksData = [];
334
+ };
324
335
  return function (msg) {
325
336
  var _a;
326
337
  return __awaiter(this, void 0, void 0, function* () {
338
+ messagesCounter++;
327
339
  if (!msg) {
328
340
  return;
329
341
  }
342
+ clearTimeout(timeoutId);
330
343
  try {
331
344
  const data = JSON.parse(msg.content.toString());
332
345
  const urlParam = (_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.urlParam;
333
346
  const webhookUrlParam = data.query[urlParam];
334
- const webhookData = yield prepareWebhookData(config, integration, webhookUrlParam, models_1.Provider.INTEGRATION);
335
- yield updateCrowdinFromWebhookRequest({ integration, webhookData, req: data });
347
+ const { clientId } = decodedUrlParam(config, webhookUrlParam);
348
+ if (!webhooksInfo[clientId]) {
349
+ webhooksInfo[clientId] = {};
350
+ webhooksInfo[clientId].data = [data];
351
+ webhooksInfo[clientId].integration = integration;
352
+ webhooksData.push(prepareWebhookData(config, integration, webhookUrlParam, models_1.Provider.INTEGRATION).then((res) => {
353
+ webhooksInfo[clientId].webhookData = res;
354
+ }));
355
+ }
356
+ else {
357
+ webhooksInfo[clientId].data.push(data);
358
+ }
359
+ if (messagesCounter < prefetchCount) {
360
+ // if all messages are not received, wait 5 seconds to force process messages
361
+ timeoutId = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
362
+ yield processMessages(webhooksData, webhooksInfo, channel, msg);
363
+ resetStateVariables();
364
+ }), forceProcessDelay);
365
+ return;
366
+ }
367
+ clearTimeout(timeoutId);
368
+ yield processMessages(webhooksData, webhooksInfo, channel, msg);
369
+ resetStateVariables();
336
370
  }
337
371
  catch (e) {
338
372
  (0, logger_1.logError)(e);
339
373
  }
340
- channel.ack(msg);
341
374
  });
342
375
  };
343
376
  }
377
+ function processMessages(webhooksData, webhooksInfo, channel, msg) {
378
+ return __awaiter(this, void 0, void 0, function* () {
379
+ yield Promise.all(webhooksData);
380
+ for (const { data, integration, webhookData } of Object.values(webhooksInfo)) {
381
+ yield updateCrowdinFromWebhookRequest({
382
+ integration: integration,
383
+ webhookData: webhookData,
384
+ req: data,
385
+ });
386
+ }
387
+ channel.ack(msg, true);
388
+ });
389
+ }
@@ -58,6 +58,7 @@
58
58
  {{/if}}
59
59
  </div>
60
60
  <crowdin-simple-integration
61
+ async-progress
61
62
  {{#if syncNewElements.crowdin}}
62
63
  skip-crowdin-auto-schedule
63
64
  {{/if}}
@@ -90,7 +91,6 @@
90
91
  >
91
92
  </crowdin-simple-integration>
92
93
  <div id="user-errors" class="hidden">
93
- <crowdin-alert title="Error Logs">This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted.</crowdin-alert>
94
94
  <crowdin-show-as-table
95
95
  is-loading
96
96
  id="user-errors-table"
@@ -98,9 +98,13 @@
98
98
  total-records="25"
99
99
  search-placeholder="Search something"
100
100
  ></crowdin-show-as-table>
101
+ <crowdin-alert>This table displays the most recent error logs from the past month. Logs older than one month will be automatically deleted.</crowdin-alert>
101
102
  </div>
102
103
  </div>
103
104
  <crowdin-toasts></crowdin-toasts>
105
+ <crowdin-async-progress
106
+ cancelAsyncAction=""
107
+ ></crowdin-async-progress>
104
108
  <crowdin-modal id="subscription-modal" modal-width="50" close-button="false">
105
109
  <div>
106
110
  <crowdin-alert type="warning">Subscribe to continue using the {{name}} app.</crowdin-alert>
@@ -296,6 +300,9 @@
296
300
  });
297
301
  document.body.addEventListener('uploadFilesToCrowdin', uploadFilesToCrowdin);
298
302
  document.body.addEventListener('uploadFilesToIntegration', uploadFilesToIntegration);
303
+ document.body.addEventListener('cancelAsyncAction', (e) => {
304
+ cancelJob(e.detail);
305
+ });
299
306
  {{#if integrationSearchListener}}
300
307
  document.body.addEventListener("integrationFilterChange", (event) => {
301
308
  getIntegrationData(false, 0, event.detail);
@@ -308,11 +315,27 @@
308
315
  const fileType = '1';
309
316
  const branchType = '2';
310
317
 
318
+ const JOB_TYPE = {
319
+ updateCrowdin: 'updateCrowdin',
320
+ updateIntegration: 'updateIntegration',
321
+ };
322
+
323
+ const JOB_STATUS = {
324
+ created: 'created',
325
+ inProgress: 'inProgress',
326
+ failed: 'failed',
327
+ canceled: 'canceled',
328
+ finished: 'finished',
329
+ };
330
+
331
+ const asyncJobs = {};
332
+
311
333
  let project = {};
312
334
  let crowdinData = [];
313
335
 
314
336
  getCrowdinData();
315
337
  getIntegrationData();
338
+ getActiveJobs();
316
339
 
317
340
  function integrationLogout() {
318
341
  checkOrigin()
@@ -481,10 +504,131 @@
481
504
  body: JSON.stringify(req)
482
505
  }))
483
506
  .then(checkResponse)
484
- .then(() => showToast(`File${event.detail.length > 1 ? 's' : ''} imported successfully`))
485
- .then(getCrowdinData)
507
+ .then((res) => {
508
+ checkJob({
509
+ jobId: res?.jobId,
510
+ jobType: JOB_TYPE.updateCrowdin,
511
+ })
512
+ })
486
513
  .catch(e => catchRejection(e, 'Can\'t upload templates to Crowdin'))
487
- .finally(() => (appComponent.setAttribute('is-to-crowdin-process', false)));
514
+ }
515
+
516
+ function getActiveJobs() {
517
+ checkOrigin()
518
+ .then(restParams => fetch(`api/jobs${restParams}`))
519
+ .then(checkResponse)
520
+ .then((jobs) => {
521
+ if (!Array.isArray(jobs)) {
522
+ return;
523
+ }
524
+
525
+ jobs.forEach((job) => {
526
+ switch (job.type) {
527
+ case JOB_TYPE.updateCrowdin:
528
+ appComponent.setAttribute('is-to-crowdin-process', true);
529
+ break;
530
+ case JOB_TYPE.updateIntegration:
531
+ appComponent.setAttribute('is-to-integration-process', true);
532
+ break;
533
+ default:
534
+ }
535
+
536
+ checkJob({
537
+ jobId: job.id,
538
+ jobType: job.type,
539
+ })
540
+ })
541
+ })
542
+ .catch(e => catchRejection(e, 'Sync status check failed'))
543
+ }
544
+
545
+ function cancelJob(jobId) {
546
+ if (asyncJobs[jobId]?.isFailed) {
547
+ return;
548
+ }
549
+
550
+ checkOrigin()
551
+ .then(restParams => fetch('api/jobs' + restParams + '&job_id=' + jobId, {
552
+ method: 'DELETE',
553
+ headers: { 'Content-Type': 'application/json' },
554
+ }))
555
+ .then(checkResponse)
556
+ .then(() => showToast('Cancellation…'))
557
+ .catch(e => catchRejection(e, 'Sync cancellation failed'));
558
+ }
559
+
560
+ function checkJob({jobId, jobType, onSuccess, onError, onFinally}) {
561
+ switch (jobType) {
562
+ case JOB_TYPE.updateCrowdin:
563
+ if (!onSuccess) {
564
+ onSuccess = ((job) => {
565
+ getCrowdinData();
566
+ });
567
+ }
568
+
569
+ if (!onFinally) {
570
+ onFinally = (() => appComponent.setAttribute('is-to-crowdin-process', false));
571
+ }
572
+ break;
573
+ case JOB_TYPE.updateIntegration:
574
+ if (!onFinally) {
575
+ onFinally = (() => appComponent.setAttribute('is-to-integration-process', false));
576
+ }
577
+ break;
578
+ default:
579
+ }
580
+
581
+ checkOrigin()
582
+ .then(restParams => fetch('api/jobs' + restParams + '&job_id=' + jobId))
583
+ .then(checkResponse)
584
+ .then((job) => {
585
+ const isFailed = [JOB_STATUS.failed, JOB_STATUS.canceled].includes(job.status);
586
+ const progress = isFailed || JOB_STATUS.finished === job.status ? 100 : job.progress;
587
+ const info = JOB_STATUS.canceled === job.status ? `Cancelled\n${job.info || ''}` : job.info;
588
+
589
+ pushJobs([ {
590
+ id: job.id,
591
+ title: job.title,
592
+ progress,
593
+ info,
594
+ isFailed,
595
+ } ]);
596
+
597
+ if (isFailed) {
598
+ onError && onError();
599
+ } else if ([JOB_STATUS.created, JOB_STATUS.inProgress].includes(job.status) && job.progress < 100) {
600
+ setTimeout(() => {
601
+ checkJob({jobId, jobType, onSuccess, onError, onFinally});
602
+ }, {{asyncProgress.checkInterval}});
603
+ return;
604
+ } else {
605
+ onSuccess && onSuccess(job);
606
+ }
607
+
608
+ onFinally && onFinally(job);
609
+ })
610
+ .catch((e) => {
611
+ onFinally && onFinally();
612
+
613
+ pushJobs([ {
614
+ id: jobId,
615
+ isFailed: true,
616
+ } ]);
617
+
618
+ showToast('Sync status check failed');
619
+ });
620
+ }
621
+
622
+ function pushJobs(jobs) {
623
+ const el = document.querySelector('crowdin-async-progress');
624
+ if (el && el.pushJobs) {
625
+ el.pushJobs(jobs);
626
+ jobs.forEach((job) => (asyncJobs[job.id] = job));
627
+ } else {
628
+ setTimeout(() => {
629
+ pushJobs(jobs);
630
+ }, 300);
631
+ }
488
632
  }
489
633
 
490
634
  function uploadFilesToIntegration(e) {
@@ -504,9 +648,13 @@
504
648
  body: JSON.stringify(req)
505
649
  }))
506
650
  .then(checkResponse)
507
- .then(() => showToast(`File${Object.keys(e.detail).length > 1 ? 's' : ''} exported successfully`))
651
+ .then((res) => {
652
+ checkJob({
653
+ jobId: res?.jobId,
654
+ jobType: JOB_TYPE.updateIntegration,
655
+ })
656
+ })
508
657
  .catch(e => catchRejection(e, 'Can\'t upload files to {{name}}'))
509
- .finally(() => (appComponent.setAttribute('is-to-integration-process', false)));
510
658
  }
511
659
 
512
660
  {{#if configurationFields}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.39.0",
3
+ "version": "0.40.0",
4
4
  "description": "Module that generates for you all common endpoints for serving standalone Crowdin App",
5
5
  "main": "out/index.js",
6
6
  "types": "out/index.d.ts",
@@ -15,11 +15,10 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@aws-sdk/client-s3": "^3.423.0",
18
- "@aws-sdk/s3-request-presigner": "^3.423.0",
18
+ "@aws-sdk/s3-request-presigner": "^3.484.0",
19
19
  "@crowdin/crowdin-apps-functions": "0.6.0",
20
- "@crowdin/logs-formatter": "^2.0.6",
20
+ "@crowdin/logs-formatter": "^2.1.1",
21
21
  "@godaddy/terminus": "^4.12.1",
22
- "@types/pg": "^8.10.3",
23
22
  "amqplib": "^0.10.3",
24
23
  "crypto-js": "^4.2.0",
25
24
  "express": "4.18.2",
@@ -33,29 +32,31 @@
33
32
  "uuid": "^8.3.2"
34
33
  },
35
34
  "devDependencies": {
36
- "@babel/preset-react": "^7.22.15",
35
+ "@babel/preset-react": "^7.23.3",
37
36
  "@emotion/react": "^11.11.1",
38
37
  "@emotion/styled": "^11.11.0",
39
- "@mui/icons-material": "^5.14.16",
40
- "@mui/material": "^5.14.16",
41
- "@rjsf/core": "^5.13.3",
42
- "@rjsf/mui": "^5.13.3",
43
- "@rjsf/utils": "^5.13.3",
44
- "@rjsf/validator-ajv8": "^5.13.3",
38
+ "@mui/icons-material": "^5.15.2",
39
+ "@mui/material": "^5.15.2",
40
+ "@rjsf/core": "^5.15.1",
41
+ "@rjsf/mui": "^5.15.1",
42
+ "@rjsf/utils": "^5.15.1",
43
+ "@rjsf/validator-ajv8": "^5.15.1",
45
44
  "@rollup/plugin-babel": "^6.0.4",
46
- "@rollup/plugin-commonjs": "^24.0.1",
45
+ "@rollup/plugin-commonjs": "^24.1.0",
47
46
  "@rollup/plugin-json": "^6.0.0",
48
47
  "@rollup/plugin-node-resolve": "^15.2.1",
49
- "@rollup/plugin-replace": "^5.0.2",
48
+ "@rollup/plugin-replace": "^5.0.5",
50
49
  "@rollup/plugin-terser": "^0.4.3",
51
- "@types/amqplib": "^0.10.2",
50
+ "@types/amqplib": "^0.10.4",
52
51
  "@types/crypto-js": "^4.1.3",
53
52
  "@types/express": "4.17.18",
54
53
  "@types/express-handlebars": "^5.3.1",
55
54
  "@types/jest": "^29.5.5",
56
- "@types/node": "^16.18.60",
55
+ "@types/node": "^16.18.69",
57
56
  "@types/node-cron": "^3.0.9",
57
+ "@types/pg": "^8.10.3",
58
58
  "@types/swagger-jsdoc": "^6.0.1",
59
+ "@types/uuid": "^9.0.7",
59
60
  "@typescript-eslint/eslint-plugin": "^2.3.1",
60
61
  "@typescript-eslint/parser": "^2.3.1",
61
62
  "eslint": "^6.4.0",
@@ -1,3 +0,0 @@
1
- /// <reference types="qs" />
2
- import { Response } from 'express';
3
- export default function handle(): (req: import("../models").CrowdinClientRequest | import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;