@crowdin/app-project-module 0.89.0 → 0.90.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/out/index.js CHANGED
@@ -98,13 +98,11 @@ exports.metadataStore = {
98
98
  },
99
99
  saveMetadata: (id, metadata, crowdinId) => __awaiter(void 0, void 0, void 0, function* () {
100
100
  if (!crowdinId) {
101
- console.warn('Warning: The crowdinId parameter in saveMetadata will be required. Please update your code to provide this parameter.');
101
+ throw new Error('The crowdinId parameter is required.');
102
102
  }
103
- else {
104
- const crowdinCredentials = yield storage.getStorage().getCrowdinCredentials(crowdinId);
105
- if (!crowdinCredentials) {
106
- console.error('Invalid crowdinId parameter: You can get your crowdinId from the JWT payload');
107
- }
103
+ const crowdinCredentials = yield storage.getStorage().getCrowdinCredentials(crowdinId);
104
+ if (!crowdinCredentials) {
105
+ throw new Error('Invalid crowdinId parameter: You can get your crowdinId from the JWT payload.');
108
106
  }
109
107
  const existing = yield storage.getStorage().getMetadata(id);
110
108
  if (existing) {
@@ -146,7 +146,7 @@ function applyIntegrationModuleDefaults(config, integration) {
146
146
  }
147
147
  const getUserSettings = integration.getConfiguration;
148
148
  integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
149
- var _m, _o;
149
+ var _m, _o, _p;
150
150
  let fields = [];
151
151
  const project = (yield crowdinClient.projectsGroupsApi.getProject(projectId));
152
152
  if (getUserSettings) {
@@ -163,42 +163,49 @@ function applyIntegrationModuleDefaults(config, integration) {
163
163
  });
164
164
  }
165
165
  if (integration.withCronSync || integration.webhooks) {
166
- defaultSettings.push({
167
- key: 'schedule',
168
- label: 'Sync schedule',
169
- helpText: `Defines how often content is synced between ${config.name} and Crowdin. Make sure Auto Sync is enabled for selected directories and files in the dual pane view.`,
170
- type: 'select',
171
- defaultValue: '0',
172
- category: types_1.DefaultCategory.SYNC,
173
- position: 0,
174
- options: [
175
- {
176
- value: '0',
177
- label: 'Disabled',
178
- },
179
- {
180
- value: '1',
181
- label: '1 hour',
182
- },
183
- {
184
- value: '3',
185
- label: '3 hours',
186
- },
187
- {
188
- value: '6',
189
- label: '6 hours',
190
- },
191
- {
192
- value: '12',
193
- label: '12 hours',
194
- },
195
- {
196
- value: '24',
197
- label: '24 hours',
198
- },
199
- ],
200
- });
201
- if ((_m = integration.syncNewElements) === null || _m === void 0 ? void 0 : _m.crowdin) {
166
+ const userSchedule = fields.find((field) => 'key' in field && field.key === 'schedule');
167
+ if (userSchedule) {
168
+ userSchedule.position = (_m = userSchedule.position) !== null && _m !== void 0 ? _m : 0;
169
+ userSchedule.category = types_1.DefaultCategory.SYNC;
170
+ }
171
+ else {
172
+ defaultSettings.push({
173
+ key: 'schedule',
174
+ label: 'Sync schedule',
175
+ helpText: `Defines how often content is synced between ${config.name} and Crowdin. Make sure Auto Sync is enabled for selected directories and files in the dual pane view.`,
176
+ type: 'select',
177
+ defaultValue: '0',
178
+ category: types_1.DefaultCategory.SYNC,
179
+ position: 0,
180
+ options: [
181
+ {
182
+ value: '0',
183
+ label: 'Disabled',
184
+ },
185
+ {
186
+ value: '1',
187
+ label: '1 hour',
188
+ },
189
+ {
190
+ value: '3',
191
+ label: '3 hours',
192
+ },
193
+ {
194
+ value: '6',
195
+ label: '6 hours',
196
+ },
197
+ {
198
+ value: '12',
199
+ label: '12 hours',
200
+ },
201
+ {
202
+ value: '24',
203
+ label: '24 hours',
204
+ },
205
+ ],
206
+ });
207
+ }
208
+ if ((_o = integration.syncNewElements) === null || _o === void 0 ? void 0 : _o.crowdin) {
202
209
  defaultSettings.push({
203
210
  key: 'new-crowdin-files',
204
211
  label: 'Automatically sync new translations from Crowdin',
@@ -208,7 +215,7 @@ function applyIntegrationModuleDefaults(config, integration) {
208
215
  position: 1,
209
216
  });
210
217
  }
211
- if ((_o = integration.syncNewElements) === null || _o === void 0 ? void 0 : _o.integration) {
218
+ if ((_p = integration.syncNewElements) === null || _p === void 0 ? void 0 : _p.integration) {
212
219
  defaultSettings.push({
213
220
  key: 'new-integration-files',
214
221
  label: `Automatically sync new content from ${config.name}`,
@@ -69,7 +69,16 @@ function webhookHandler(config, webhooks) {
69
69
  const json = JSON.parse(req.body.toString());
70
70
  for (const webhook of webhooks) {
71
71
  if (webhook.key === moduleKey) {
72
- yield webhook.callback({ events: json.events, client });
72
+ yield webhook.callback({
73
+ events: json.events,
74
+ client,
75
+ webhookContext: {
76
+ domain: credentials.domain,
77
+ organizationId: credentials.organizationId,
78
+ userId: credentials.userId,
79
+ agentId: credentials.agentId,
80
+ },
81
+ });
73
82
  }
74
83
  }
75
84
  }));
@@ -9,10 +9,17 @@ export interface Webhook extends ModuleKey {
9
9
  * handle function
10
10
  */
11
11
  callback: (data: {
12
+ webhookContext: WebhookContext;
12
13
  events: Event[];
13
14
  client: Crowdin;
14
15
  }) => Promise<void>;
15
16
  }
17
+ interface WebhookContext {
18
+ domain?: string;
19
+ organizationId?: number;
20
+ userId?: number;
21
+ agentId?: number;
22
+ }
16
23
  interface EventPayload {
17
24
  event: string;
18
25
  }
@@ -30,8 +30,8 @@ export interface Storage {
30
30
  getAllIntegrationCredentials(crowdinId: string): Promise<IntegrationCredentials[]>;
31
31
  deleteIntegrationCredentials(id: string): Promise<void>;
32
32
  deleteAllIntegrationCredentials(crowdinId: string): Promise<void>;
33
- saveMetadata(id: string, metadata: any, crowdinId?: string): Promise<void>;
34
- updateMetadata(id: string, metadata: any, crowdinId?: string): Promise<void>;
33
+ saveMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
34
+ updateMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
35
35
  getMetadata(id: string): Promise<any | undefined>;
36
36
  getAllMetadata(): Promise<any[] | undefined>;
37
37
  deleteMetadata(id: string): Promise<void>;
@@ -17,6 +17,11 @@ export declare class MySQLStorage implements Storage {
17
17
  private _rej?;
18
18
  private dbPromise;
19
19
  private config;
20
+ tableIndexes: {
21
+ [key: string]: {
22
+ [key: string]: string;
23
+ };
24
+ };
20
25
  tables: {
21
26
  crowdin_credentials: string;
22
27
  integration_credentials: string;
@@ -48,7 +53,7 @@ export declare class MySQLStorage implements Storage {
48
53
  deleteIntegrationCredentials(id: string): Promise<void>;
49
54
  deleteAllIntegrationCredentials(crowdinId: string): Promise<void>;
50
55
  saveMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
51
- updateMetadata(id: string, metadata: any, crowdinId?: string): Promise<void>;
56
+ updateMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
52
57
  getMetadata(id: string): Promise<any>;
53
58
  getAllMetadata(): Promise<any[]>;
54
59
  deleteMetadata(id: string): Promise<void>;
@@ -24,6 +24,46 @@ class MySQLStorage {
24
24
  this._res = res;
25
25
  this._rej = rej;
26
26
  });
27
+ this.tableIndexes = {
28
+ integration_credentials: {
29
+ idx_crowdin: '(crowdin_id)',
30
+ },
31
+ sync_settings: {
32
+ idx_integration_provider: '(integration_id, provider)',
33
+ idx_crowdin: '(crowdin_id)',
34
+ idx_type: '(type)',
35
+ },
36
+ files_snapshot: {
37
+ idx_integration: '(integration_id)',
38
+ idx_crowdin: '(crowdin_id)',
39
+ },
40
+ webhooks: {
41
+ idx_integration_crowdin: '(integration_id, crowdin_id)',
42
+ idx_file_provider: '(file_id, provider)',
43
+ },
44
+ user_errors: {
45
+ idx_integration_crowdin: '(integration_id, crowdin_id)',
46
+ idx_crowdin: '(crowdin_id)',
47
+ idx_created_at: '(created_at)',
48
+ },
49
+ integration_settings: {
50
+ idx_integration: '(integration_id)',
51
+ idx_crowdin: '(crowdin_id)',
52
+ },
53
+ job: {
54
+ idx_integration_crowdin: '(integration_id, crowdin_id)',
55
+ idx_finished_at: '(finished_at)',
56
+ idx_status: '(status)',
57
+ },
58
+ translation_file_cache: {
59
+ idx_integration_crowdin_file_language: '(integration_id, crowdin_id, file_id, language_id)',
60
+ idx_crowdin: '(crowdin_id)',
61
+ },
62
+ unsynced_files: {
63
+ idx_integration_crowdin: '(integration_id, crowdin_id)',
64
+ idx_crowdin: '(crowdin_id)',
65
+ },
66
+ };
27
67
  this.tables = {
28
68
  crowdin_credentials: `(
29
69
  id varchar(255) primary key,
@@ -168,6 +208,14 @@ class MySQLStorage {
168
208
  return __awaiter(this, void 0, void 0, function* () {
169
209
  for (const [tableName, tableSchema] of Object.entries(this.tables)) {
170
210
  yield connection.execute(`create table if not exists ${tableName} ${tableSchema}`);
211
+ if (this.tableIndexes[tableName]) {
212
+ for (const [indexName, indexSchema] of Object.entries(this.tableIndexes[tableName])) {
213
+ // For MySQL, we need to handle partial indexes differently since MySQL doesn't support WHERE clauses in indexes
214
+ // We'll create the basic index without the WHERE clause
215
+ const indexColumns = indexSchema.replace(/WHERE.*$/, '').trim();
216
+ yield connection.execute(`create index if not exists ${indexName} on ${tableName}${indexColumns}`);
217
+ }
218
+ }
171
219
  }
172
220
  });
173
221
  }
@@ -62,7 +62,7 @@ export declare class PostgreStorage implements Storage {
62
62
  deleteIntegrationCredentials(id: string): Promise<void>;
63
63
  deleteAllIntegrationCredentials(crowdinId: string): Promise<void>;
64
64
  saveMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
65
- updateMetadata(id: string, metadata: any, crowdinId?: string): Promise<void>;
65
+ updateMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
66
66
  getMetadata(id: string): Promise<any>;
67
67
  getAllMetadata(): Promise<any[]>;
68
68
  deleteMetadata(id: string): Promise<void>;
@@ -50,8 +50,8 @@ export declare class SQLiteStorage implements Storage {
50
50
  getAllIntegrationCredentials(crowdinId: string): Promise<IntegrationCredentials[]>;
51
51
  deleteIntegrationCredentials(id: string): Promise<void>;
52
52
  deleteAllIntegrationCredentials(crowdinId: string): Promise<void>;
53
- saveMetadata(id: string, metadata: any, crowdinId?: string): Promise<void>;
54
- updateMetadata(id: string, metadata: any, crowdinId?: string): Promise<void>;
53
+ saveMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
54
+ updateMetadata(id: string, metadata: any, crowdinId: string): Promise<void>;
55
55
  getMetadata(id: string): Promise<any>;
56
56
  getAllMetadata(): Promise<any[]>;
57
57
  deleteMetadata(id: string): Promise<void>;
package/out/types.d.ts CHANGED
@@ -394,7 +394,7 @@ export interface CrowdinAppUtilities extends CrowdinMetadataStore {
394
394
  storage: Storage;
395
395
  }
396
396
  export interface CrowdinMetadataStore {
397
- saveMetadata: (id: string, metadata: any, crowdinId?: string) => Promise<void>;
397
+ saveMetadata: (id: string, metadata: any, crowdinId: string) => Promise<void>;
398
398
  getMetadata: (id: string) => Promise<any | undefined>;
399
399
  deleteMetadata: (id: string) => Promise<void>;
400
400
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.89.0",
3
+ "version": "0.90.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",