@crowdin/app-project-module 0.35.1 → 0.37.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,3 +1,4 @@
1
+ import { AxiosError } from 'axios';
1
2
  import { Config, CrowdinContextInfo } from '../models';
2
3
  export type LogFunction = (message: string) => void;
3
4
  export type LogErrorFunction = (error: any) => void;
@@ -7,9 +8,23 @@ export type LogContext = {
7
8
  projectId: number;
8
9
  };
9
10
  export declare function initialize(config: Config): void;
10
- export declare function preprareContext(context: CrowdinContextInfo): LogContext;
11
+ export declare function prepareContext(context: CrowdinContextInfo): LogContext;
11
12
  export declare function withContext(context: CrowdinContextInfo): LogFunction;
12
13
  export declare function withContextError(context: CrowdinContextInfo): LogFunction;
13
14
  export declare function log(message: string, context?: CrowdinContextInfo): void;
14
15
  export declare function logError(e: any, context?: CrowdinContextInfo): void;
16
+ export declare function isAxiosError(e: any): e is CustomAxiosError;
15
17
  export declare function getErrorMessage(err: any): any;
18
+ interface CustomAxiosError extends AxiosError {
19
+ data?: any;
20
+ }
21
+ export declare class AppModuleError extends Error {
22
+ data: any;
23
+ isAxiosError: boolean;
24
+ constructor(error: CustomAxiosError | Error | string, data?: any);
25
+ }
26
+ export declare class AppModuleAggregateError extends Error {
27
+ errors: Error[] | AppModuleError[];
28
+ constructor(errors: Error[] | AppModuleError[], message: string);
29
+ }
30
+ export {};
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.getErrorMessage = exports.logError = exports.log = exports.withContextError = exports.withContext = exports.preprareContext = exports.initialize = void 0;
26
+ exports.AppModuleAggregateError = exports.AppModuleError = exports.getErrorMessage = exports.isAxiosError = exports.logError = exports.log = exports.withContextError = exports.withContext = exports.prepareContext = exports.initialize = void 0;
27
27
  const logsFormatter = __importStar(require("@crowdin/logs-formatter"));
28
28
  let logConfig;
29
29
  let onError;
@@ -32,14 +32,14 @@ function initialize(config) {
32
32
  onError = config.onError;
33
33
  }
34
34
  exports.initialize = initialize;
35
- function preprareContext(context) {
35
+ function prepareContext(context) {
36
36
  return {
37
37
  orgId: context.crowdinId,
38
38
  userId: context.clientId,
39
39
  projectId: context.jwtPayload.context.project_id,
40
40
  };
41
41
  }
42
- exports.preprareContext = preprareContext;
42
+ exports.prepareContext = prepareContext;
43
43
  function withContext(context) {
44
44
  return (message) => log(message, context);
45
45
  }
@@ -65,7 +65,7 @@ function log(message, context) {
65
65
  user_id: context.jwtPayload.context.user_id,
66
66
  },
67
67
  });
68
- prefix += ` Context [${JSON.stringify(preprareContext(context))}]`;
68
+ prefix += ` Context [${JSON.stringify(prepareContext(context))}]`;
69
69
  }
70
70
  // eslint-disable-next-line no-console
71
71
  console.log(`${prefix} ${message}`);
@@ -78,7 +78,6 @@ function logError(e, context) {
78
78
  onError(e, context);
79
79
  }
80
80
  else {
81
- let message = `[${new Date().toISOString()}] Error.`;
82
81
  if (context) {
83
82
  logsFormatter.setContext({
84
83
  project: {
@@ -89,22 +88,47 @@ function logError(e, context) {
89
88
  user_id: context.jwtPayload.context.user_id,
90
89
  },
91
90
  });
92
- message += ` Context ${JSON.stringify(preprareContext(context))}`;
93
91
  }
94
- if (isAxiosError(e)) {
95
- const request = e.config ? { url: e.config.url, method: e.config.method, data: e.config.data } : {};
96
- const response = e.response ? { data: e.response.data, status: e.response.status } : {};
97
- console.error(`${message} Axios error. Request ${JSON.stringify(request)}. Response ${JSON.stringify(response)}. Message ${e.message}`);
92
+ if (e instanceof AppModuleAggregateError) {
93
+ if (e.errors && e.errors.length > 0) {
94
+ for (const error of e.errors) {
95
+ errorOutputByType(error);
96
+ }
97
+ }
98
98
  }
99
99
  else {
100
- console.error(message, e);
100
+ errorOutputByType(e);
101
101
  }
102
102
  }
103
103
  }
104
104
  exports.logError = logError;
105
+ function errorOutputByType(error) {
106
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
107
+ const message = error.message || error;
108
+ if (isAxiosError(error)) {
109
+ const request = error.config || error.data.config
110
+ ? {
111
+ url: ((_a = error.config) === null || _a === void 0 ? void 0 : _a.url) || ((_b = error.data) === null || _b === void 0 ? void 0 : _b.config.url),
112
+ method: ((_c = error.config) === null || _c === void 0 ? void 0 : _c.method) || ((_d = error.data) === null || _d === void 0 ? void 0 : _d.config.method),
113
+ data: ((_e = error.config) === null || _e === void 0 ? void 0 : _e.data) || ((_f = error.data) === null || _f === void 0 ? void 0 : _f.config.data),
114
+ }
115
+ : {};
116
+ const response = error.response || error.data.response
117
+ ? {
118
+ data: ((_g = error.response) === null || _g === void 0 ? void 0 : _g.data) || ((_h = error.data) === null || _h === void 0 ? void 0 : _h.response.data),
119
+ status: ((_j = error.response) === null || _j === void 0 ? void 0 : _j.status) || ((_k = error.data) === null || _k === void 0 ? void 0 : _k.response.status),
120
+ }
121
+ : {};
122
+ console.error(message, { attributes: { request, response } }, { backtrace: error.stack });
123
+ }
124
+ else {
125
+ console.error(message, error.data ? { attributes: error.data } : '', error.stack ? { backtrace: error.stack } : '');
126
+ }
127
+ }
105
128
  function isAxiosError(e) {
106
129
  return !!e.isAxiosError;
107
130
  }
131
+ exports.isAxiosError = isAxiosError;
108
132
  function getErrorMessage(err) {
109
133
  let message;
110
134
  if (typeof err === 'string') {
@@ -119,3 +143,24 @@ function getErrorMessage(err) {
119
143
  return message;
120
144
  }
121
145
  exports.getErrorMessage = getErrorMessage;
146
+ class AppModuleError extends Error {
147
+ constructor(error, data) {
148
+ super(typeof error === 'string' ? error : error.message);
149
+ this.isAxiosError = false;
150
+ this.name = 'AppModuleError';
151
+ this.data = typeof error === 'string' ? Object.assign({}, data) : Object.assign(Object.assign({}, error), data);
152
+ this.stack = typeof error === 'string' ? this.stack : error.stack;
153
+ if (isAxiosError(error)) {
154
+ this.isAxiosError = true;
155
+ }
156
+ }
157
+ }
158
+ exports.AppModuleError = AppModuleError;
159
+ class AppModuleAggregateError extends Error {
160
+ constructor(errors, message) {
161
+ super(message);
162
+ this.name = 'AppModuleAggregateError';
163
+ this.errors = errors;
164
+ }
165
+ }
166
+ exports.AppModuleAggregateError = AppModuleAggregateError;
@@ -1,18 +1,18 @@
1
1
  import Crowdin from '@crowdin/crowdin-api-client';
2
2
  import { WebhooksModel } from '@crowdin/crowdin-api-client/out/webhooks';
3
- import { Config, CrowdinContextInfo, IntegrationLogic, IntegrationSyncSettings, Payload, Provider, TreeItem, UpdateCrowdinWebhookPayloadsArgs, UpdateIntegrationRequest, WebhookUrlParams } from '../models';
3
+ import { AppSettings, Config, CrowdinContextInfo, IntegrationLogic, IntegrationSyncSettings, Provider, UpdateCrowdinWebhookPayloadsArgs, WebhookUrlParams } from '../models';
4
+ export declare const HookEvents: any;
4
5
  export declare function encodedUrlParam(config: Config, integration: IntegrationLogic, crowdinContext: CrowdinContextInfo): string;
5
6
  export declare function decodedUrlParam(config: Config, data: string): WebhookUrlParams;
6
7
  export declare function makeCrowdinWebhookUrl(config: Config, integration: IntegrationLogic, crowdinContext: CrowdinContextInfo): string;
7
- export declare function registerWebhooks(config: Config, integration: IntegrationLogic, client: Crowdin, crowdinContext: CrowdinContextInfo, apiCredentials: any, appSettings: any): Promise<void>;
8
- export declare function unregisterWebhooks(config: Config, integration: IntegrationLogic, client: Crowdin, crowdinContext: CrowdinContextInfo, apiCredentials: any, appSettings: any): Promise<void>;
8
+ export declare function registerWebhooks(config: Config, integration: IntegrationLogic, client: Crowdin, crowdinContext: CrowdinContextInfo, apiCredentials: any, appSettings: AppSettings): Promise<void>;
9
+ export declare function unregisterWebhooks(config: Config, integration: IntegrationLogic, client: Crowdin, crowdinContext: CrowdinContextInfo, apiCredentials: any, appSettings: AppSettings): Promise<void>;
9
10
  export declare function getCrowdinProjectWebhook(config: Config, client: Crowdin, projectId: number, name: string): Promise<WebhooksModel.Webhook | undefined>;
10
11
  export declare function getAllCrowdinProjectWebhooks(config: Config, client: Crowdin, projectId: number): Promise<WebhooksModel.Webhook[]>;
11
12
  export declare function registerCrowdinWebhook(config: Config, url: string, client: Crowdin, crowdinContext: CrowdinContextInfo, events: WebhooksModel.Event[]): Promise<void>;
12
13
  export declare function updateCrowdinWebhooks(config: Config, client: Crowdin, projectId: number, webhook: WebhooksModel.Webhook, events: WebhooksModel.Event[], url: string): Promise<void>;
13
14
  export declare function unregisterCrowdinWebhooks(config: Config, client: Crowdin, projectId: number, webhook: WebhooksModel.Webhook): Promise<void>;
14
15
  export declare function unregisterAllCrowdinWebhooks(config: Config, integration: IntegrationLogic, crowdinId: string): Promise<void>;
15
- export declare function filterSyncFiles(events: Payload[], syncFileSettings: UpdateIntegrationRequest): UpdateIntegrationRequest;
16
16
  export declare function prepareWebhookData(config: Config, integration: IntegrationLogic, webhookUrlParam: string, provider: Provider): Promise<{
17
17
  projectId: number;
18
18
  crowdinClient: {
@@ -21,9 +21,8 @@ export declare function prepareWebhookData(config: Config, integration: Integrat
21
21
  };
22
22
  preparedIntegrationCredentials: any;
23
23
  rootFolder: import("@crowdin/crowdin-api-client").SourceFilesModel.Directory | undefined;
24
- appSettings: any;
24
+ appSettings: AppSettings;
25
25
  syncSettings: IntegrationSyncSettings | null;
26
- newFiles: TreeItem[] | UpdateIntegrationRequest;
27
26
  }>;
28
- export declare function updateCrowdinFromWebhookRequest(args: UpdateCrowdinWebhookPayloadsArgs): Promise<void | import("../models").ExtendedResult<void>>;
27
+ export declare function updateCrowdinFromWebhookRequest(args: UpdateCrowdinWebhookPayloadsArgs): Promise<void>;
29
28
  export declare function listenQueueMessage(config: Config, integration: IntegrationLogic, queueUrl: string, queueName: string): Promise<void>;
@@ -35,20 +35,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
35
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.listenQueueMessage = exports.updateCrowdinFromWebhookRequest = exports.prepareWebhookData = exports.filterSyncFiles = exports.unregisterAllCrowdinWebhooks = exports.unregisterCrowdinWebhooks = exports.updateCrowdinWebhooks = exports.registerCrowdinWebhook = exports.getAllCrowdinProjectWebhooks = exports.getCrowdinProjectWebhook = exports.unregisterWebhooks = exports.registerWebhooks = exports.makeCrowdinWebhookUrl = exports.decodedUrlParam = exports.encodedUrlParam = void 0;
38
+ exports.listenQueueMessage = exports.updateCrowdinFromWebhookRequest = exports.prepareWebhookData = exports.unregisterAllCrowdinWebhooks = exports.unregisterCrowdinWebhooks = exports.updateCrowdinWebhooks = exports.registerCrowdinWebhook = exports.getAllCrowdinProjectWebhooks = exports.getCrowdinProjectWebhook = exports.unregisterWebhooks = exports.registerWebhooks = exports.makeCrowdinWebhookUrl = exports.decodedUrlParam = exports.encodedUrlParam = exports.HookEvents = void 0;
39
39
  const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
40
40
  const amqplib_1 = __importDefault(require("amqplib"));
41
41
  const models_1 = require("../models");
42
42
  const storage_1 = require("../storage");
43
43
  const connection_1 = require("./connection");
44
44
  const defaults_1 = require("./defaults");
45
- const file_snapshot_1 = require("./file-snapshot");
46
45
  const index_1 = require("./index");
47
46
  const logger_1 = require("./logger");
48
- const HookEvents = {
49
- ALL: ['file.translated', 'file.approved'],
50
- TRANSLATED: ['file.translated'],
51
- APPROVED: ['file.approved'],
47
+ exports.HookEvents = {
48
+ fileAdded: 'file.added',
49
+ fileDeleted: 'file.deleted',
50
+ fileApproved: 'file.approved',
51
+ fileTranslated: 'file.translated',
52
+ translationUpdated: 'translation.updated',
53
+ };
54
+ const HookConditionEvents = {
55
+ ALL: [exports.HookEvents.translationUpdated, exports.HookEvents.fileDeleted],
56
+ TRANSLATED: [exports.HookEvents.fileTranslated, exports.HookEvents.fileDeleted],
57
+ APPROVED: [exports.HookEvents.fileApproved, exports.HookEvents.fileDeleted],
52
58
  };
53
59
  function encodedUrlParam(config, integration, crowdinContext) {
54
60
  var _a;
@@ -75,7 +81,7 @@ exports.makeCrowdinWebhookUrl = makeCrowdinWebhookUrl;
75
81
  function registerWebhooks(config, integration, client, crowdinContext, apiCredentials, appSettings) {
76
82
  var _a, _b;
77
83
  return __awaiter(this, void 0, void 0, function* () {
78
- const isWebhookSync = +appSettings.syncType === models_1.SyncType.WEBHOOKS;
84
+ const isWebhookSync = Number(appSettings.schedule) !== models_1.SyncSchedule.DISABLED;
79
85
  const projectId = crowdinContext.jwtPayload.context.project_id;
80
86
  const urlParam = encodedUrlParam(config, integration, crowdinContext);
81
87
  if ((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.crowdinWebhooks) {
@@ -84,9 +90,12 @@ function registerWebhooks(config, integration, client, crowdinContext, apiCreden
84
90
  else {
85
91
  const webhookName = `${config.name} application hook ${crowdinContext.jwtPayload.sub}`;
86
92
  const webhookUrl = makeCrowdinWebhookUrl(config, integration, crowdinContext);
87
- const syncCondition = models_1.SyncCondition[+appSettings.condition];
88
- const events = HookEvents[syncCondition];
93
+ const syncCondition = models_1.SyncCondition[Number(appSettings.condition)];
94
+ const events = [...HookConditionEvents[syncCondition]];
89
95
  const webhook = yield getCrowdinProjectWebhook(config, client, projectId, webhookName);
96
+ if (appSettings['new-crowdin-files']) {
97
+ events.push(exports.HookEvents.fileAdded);
98
+ }
90
99
  if (isWebhookSync && webhook) {
91
100
  yield updateCrowdinWebhooks(config, client, projectId, webhook, events, webhookUrl);
92
101
  }
@@ -210,54 +219,38 @@ function unregisterAllCrowdinWebhooks(config, integration, crowdinId) {
210
219
  });
211
220
  }
212
221
  exports.unregisterAllCrowdinWebhooks = unregisterAllCrowdinWebhooks;
213
- function filterSyncFiles(events, syncFileSettings) {
214
- const files = {};
215
- events.forEach((event) => {
216
- const fileId = event.fileId;
217
- const language = event.language;
218
- if (syncFileSettings[fileId] && syncFileSettings[fileId].includes(language)) {
219
- if (files[fileId]) {
220
- files[fileId] = [...files[fileId], event.language];
221
- }
222
- else {
223
- files[fileId] = [event.language];
224
- }
225
- }
226
- });
227
- return files;
228
- }
229
- exports.filterSyncFiles = filterSyncFiles;
230
222
  function prepareWebhookData(config, integration, webhookUrlParam, provider) {
231
- var _a;
232
223
  return __awaiter(this, void 0, void 0, function* () {
233
224
  let rootFolder = undefined;
234
- let appSettings = null;
235
225
  let syncSettings = null;
236
- let newFiles = [];
226
+ let appSettings = {};
237
227
  const { projectId, crowdinId, clientId } = decodedUrlParam(config, webhookUrlParam);
238
228
  const crowdinCredentials = yield (0, storage_1.getStorage)().getCrowdinCredentials(crowdinId);
239
- const crowdinClient = yield (0, connection_1.prepareCrowdinClient)({ config, credentials: crowdinCredentials });
240
229
  const integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(clientId);
230
+ const context = {
231
+ jwtPayload: {
232
+ context: {
233
+ // eslint-disable-next-line @typescript-eslint/camelcase
234
+ project_id: projectId,
235
+ // eslint-disable-next-line @typescript-eslint/camelcase
236
+ organization_id: crowdinCredentials === null || crowdinCredentials === void 0 ? void 0 : crowdinCredentials.organizationId,
237
+ // eslint-disable-next-line @typescript-eslint/camelcase
238
+ user_id: crowdinCredentials === null || crowdinCredentials === void 0 ? void 0 : crowdinCredentials.userId,
239
+ },
240
+ },
241
+ };
242
+ const crowdinClient = yield (0, connection_1.prepareCrowdinClient)({
243
+ config,
244
+ credentials: crowdinCredentials,
245
+ context,
246
+ });
241
247
  const preparedIntegrationCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
242
248
  if (integrationCredentials === null || integrationCredentials === void 0 ? void 0 : integrationCredentials.config) {
243
249
  appSettings = JSON.parse(integrationCredentials.config);
244
- const isWebhookSync = +appSettings.syncType === models_1.SyncType.WEBHOOKS;
250
+ const isWebhookSync = Number(appSettings.schedule) !== models_1.SyncSchedule.DISABLED;
245
251
  if (isWebhookSync) {
246
252
  syncSettings = (yield (0, storage_1.getStorage)().getSyncSettings(clientId, crowdinId, 'schedule', provider));
247
253
  rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient.client, projectId);
248
- if (((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) && appSettings[`new-${provider}-files`]) {
249
- newFiles = yield (0, file_snapshot_1.getAllNewFiles)({
250
- config,
251
- integration,
252
- crowdinApiClient: crowdinClient.client,
253
- crowdinId,
254
- integrationCredentials: preparedIntegrationCredentials,
255
- integrationId: clientId,
256
- projectId,
257
- integrationSettings: appSettings,
258
- syncSettings,
259
- });
260
- }
261
254
  }
262
255
  }
263
256
  return {
@@ -267,7 +260,6 @@ function prepareWebhookData(config, integration, webhookUrlParam, provider) {
267
260
  rootFolder,
268
261
  appSettings,
269
262
  syncSettings,
270
- newFiles,
271
263
  };
272
264
  });
273
265
  }
@@ -277,24 +269,29 @@ function updateCrowdinFromWebhookRequest(args) {
277
269
  return __awaiter(this, void 0, void 0, function* () {
278
270
  const { integration, webhookData, req } = args;
279
271
  let filesToSync = [];
280
- const { projectId, crowdinClient, preparedIntegrationCredentials, rootFolder, appSettings, syncSettings, newFiles, } = webhookData;
272
+ const { projectId, crowdinClient, preparedIntegrationCredentials, rootFolder, appSettings, syncSettings } = webhookData;
281
273
  const syncFiles = (syncSettings === null || syncSettings === void 0 ? void 0 : syncSettings.files) ? JSON.parse(syncSettings.files) : [];
282
274
  if ((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.integrationWebhookInterceptor) {
283
275
  filesToSync = yield ((_b = integration.webhooks) === null || _b === void 0 ? void 0 : _b.integrationWebhookInterceptor(projectId, crowdinClient.client, preparedIntegrationCredentials, rootFolder, appSettings, syncSettings, req));
284
276
  }
285
- const allIntFiles = [...filesToSync, ...newFiles].map((file) => (Object.assign({ id: file.id, name: file.name, parentId: file.parent_id || file.parentId,
286
- // eslint-disable-next-line @typescript-eslint/camelcase
287
- parent_id: file.parent_id || file.parentId, nodeType: file.nodeType || file.node_type || '1',
288
- // eslint-disable-next-line @typescript-eslint/camelcase
289
- node_type: file.nodeType || file.node_type || '1' }, (file.type ? { type: file.type } : {}))));
290
- const intFiles = allIntFiles.filter((file) => file.nodeType === '1');
291
- const newSyncSettingsFiels = [...syncFiles, ...newFiles].map((file) => (Object.assign(Object.assign({}, file), { schedule: true, sync: false })));
292
- if (Object.keys(newFiles).length) {
293
- yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(newSyncSettingsFiels), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
294
- const currentFileSnapshot = yield (0, file_snapshot_1.getIntegrationSnapshot)(integration, preparedIntegrationCredentials, appSettings);
295
- yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(currentFileSnapshot), syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
277
+ for (const file of filesToSync) {
278
+ const fileNodeType = file.nodeType || file.node_type || '1';
279
+ if (fileNodeType !== '1') {
280
+ continue;
281
+ }
282
+ const initFile = Object.assign({ id: file.id, name: file.name, sync: false, schedule: true,
283
+ // eslint-disable-next-line @typescript-eslint/camelcase
284
+ parent_id: file.parent_id || file.parentId,
285
+ // eslint-disable-next-line @typescript-eslint/camelcase
286
+ node_type: file.nodeType || file.node_type || '1' }, (file.type ? { type: file.type } : {}));
287
+ if (!syncFiles.find((obj) => obj.id === initFile.id)) {
288
+ yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify([...syncFiles, initFile]), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
289
+ }
290
+ const webhook = yield (0, storage_1.getStorage)().getWebhooks(initFile.id, syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
291
+ if (!webhook) {
292
+ yield (0, storage_1.getStorage)().saveWebhooks(initFile.id, syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
293
+ }
296
294
  }
297
- return yield integration.updateCrowdin(projectId, crowdinClient.client, preparedIntegrationCredentials, intFiles, rootFolder, appSettings);
298
295
  });
299
296
  }
300
297
  exports.updateCrowdinFromWebhookRequest = updateCrowdinFromWebhookRequest;
@@ -334,7 +334,8 @@
334
334
  .then(checkResponse)
335
335
  .then((res) => {
336
336
  project = res;
337
- appComponent.setCrowdinLanguagesData(project.targetLanguages)
337
+ const languagesSorted = project.targetLanguages.sort((a, b) => a.name.localeCompare(b.name));
338
+ appComponent.setCrowdinLanguagesData(languagesSorted)
338
339
  })
339
340
  {{#or withCronSync webhooks}}
340
341
  .then(() => getSyncSettings('crowdin'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.35.1",
3
+ "version": "0.37.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",
@@ -17,11 +17,11 @@
17
17
  "@aws-sdk/client-s3": "^3.423.0",
18
18
  "@aws-sdk/s3-request-presigner": "^3.423.0",
19
19
  "@crowdin/crowdin-apps-functions": "0.5.1",
20
- "@crowdin/logs-formatter": "^2.0.3",
20
+ "@crowdin/logs-formatter": "^2.0.4",
21
21
  "@godaddy/terminus": "^4.12.1",
22
22
  "@types/pg": "^8.10.3",
23
23
  "amqplib": "^0.10.3",
24
- "crypto-js": "^4.1.1",
24
+ "crypto-js": "^4.2.0",
25
25
  "express": "4.18.2",
26
26
  "express-handlebars": "^5.3.5",
27
27
  "mysql2": "^2.3.3",
@@ -36,24 +36,24 @@
36
36
  "@babel/preset-react": "^7.22.15",
37
37
  "@emotion/react": "^11.11.1",
38
38
  "@emotion/styled": "^11.11.0",
39
- "@mui/icons-material": "^5.14.12",
40
- "@mui/material": "^5.14.12",
41
- "@rjsf/core": "^5.13.0",
42
- "@rjsf/mui": "^5.13.0",
43
- "@rjsf/utils": "^5.13.0",
44
- "@rjsf/validator-ajv8": "^5.13.0",
45
- "@rollup/plugin-babel": "^6.0.3",
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",
45
+ "@rollup/plugin-babel": "^6.0.4",
46
46
  "@rollup/plugin-commonjs": "^24.0.1",
47
47
  "@rollup/plugin-json": "^6.0.0",
48
48
  "@rollup/plugin-node-resolve": "^15.2.1",
49
49
  "@rollup/plugin-replace": "^5.0.2",
50
50
  "@rollup/plugin-terser": "^0.4.3",
51
51
  "@types/amqplib": "^0.10.2",
52
- "@types/crypto-js": "^4.1.2",
52
+ "@types/crypto-js": "^4.1.3",
53
53
  "@types/express": "4.17.18",
54
54
  "@types/express-handlebars": "^5.3.1",
55
55
  "@types/jest": "^29.5.5",
56
- "@types/node": "^16.18.57",
56
+ "@types/node": "^16.18.60",
57
57
  "@types/node-cron": "^3.0.9",
58
58
  "@types/swagger-jsdoc": "^6.0.1",
59
59
  "@typescript-eslint/eslint-plugin": "^2.3.1",