@crowdin/app-project-module 0.95.3 → 0.96.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.
@@ -78,7 +78,7 @@ export declare class MySQLStorage implements Storage {
78
78
  getIntegrationConfig(integrationId: string): Promise<IntegrationConfig | undefined>;
79
79
  updateIntegrationConfig(integrationId: string, config: any): Promise<void>;
80
80
  createJob({ integrationId, crowdinId, type, title, payload }: CreateJobParams): Promise<string>;
81
- updateJob({ id, progress, status, info, data, attempt }: UpdateJobParams): Promise<void>;
81
+ updateJob({ id, progress, status, info, data, attempt, errors }: UpdateJobParams): Promise<void>;
82
82
  getJob({ id }: GetJobParams): Promise<Job | undefined>;
83
83
  getActiveJobs({ integrationId, crowdinId }: GetActiveJobsParams): Promise<Job[] | undefined>;
84
84
  deleteFinishedJobs(): Promise<void>;
@@ -139,6 +139,7 @@ class MySQLStorage {
139
139
  info text,
140
140
  data text,
141
141
  attempt int 0,
142
+ errors text,
142
143
  created_at varchar(255) not null,
143
144
  updated_at varchar(255),
144
145
  finished_at varchar(255)
@@ -605,7 +606,7 @@ class MySQLStorage {
605
606
  return id;
606
607
  });
607
608
  }
608
- updateJob({ id, progress, status, info, data, attempt }) {
609
+ updateJob({ id, progress, status, info, data, attempt, errors }) {
609
610
  return __awaiter(this, void 0, void 0, function* () {
610
611
  const updateFields = ['updated_at'];
611
612
  const updateParams = [Date.now().toString()];
@@ -637,6 +638,10 @@ class MySQLStorage {
637
638
  updateFields.push('attempt = ?');
638
639
  updateParams.push(attempt);
639
640
  }
641
+ if (errors) {
642
+ updateFields.push('errors = ?');
643
+ updateParams.push(JSON.stringify(errors));
644
+ }
640
645
  updateParams.push(id);
641
646
  yield this.dbPromise;
642
647
  yield this.executeQuery((connection) => connection.execute(`
@@ -662,6 +667,7 @@ class MySQLStorage {
662
667
  info,
663
668
  data,
664
669
  attempt,
670
+ errors,
665
671
  created_at as "createdAt",
666
672
  updated_at as "updatedAt",
667
673
  finished_at as "finishedAt"
@@ -688,6 +694,7 @@ class MySQLStorage {
688
694
  info,
689
695
  data,
690
696
  attempt,
697
+ errors,
691
698
  created_at as "createdAt",
692
699
  updated_at as "updatedAt",
693
700
  finished_at as "finishedAt"
@@ -722,6 +729,7 @@ class MySQLStorage {
722
729
  info,
723
730
  data,
724
731
  attempt,
732
+ errors,
725
733
  created_at as "createdAt",
726
734
  updated_at as "updatedAt",
727
735
  finished_at as "finishedAt"
@@ -88,7 +88,7 @@ export declare class PostgreStorage implements Storage {
88
88
  getIntegrationConfig(integrationId: string): Promise<IntegrationConfig | undefined>;
89
89
  updateIntegrationConfig(integrationId: string, config: any): Promise<void>;
90
90
  createJob({ integrationId, crowdinId, type, payload, title }: CreateJobParams): Promise<string>;
91
- updateJob({ id, progress, status, info, data, attempt }: UpdateJobParams): Promise<void>;
91
+ updateJob({ id, progress, status, info, data, attempt, errors }: UpdateJobParams): Promise<void>;
92
92
  getJob({ id }: GetJobParams): Promise<Job | undefined>;
93
93
  getActiveJobs({ integrationId, crowdinId }: GetActiveJobsParams): Promise<Job[] | undefined>;
94
94
  deleteFinishedJobs(): Promise<void>;
@@ -102,6 +102,7 @@ class PostgreStorage {
102
102
  info varchar null,
103
103
  data varchar null,
104
104
  attempt int default 0,
105
+ errors varchar null,
105
106
  created_at varchar not null,
106
107
  updated_at varchar null,
107
108
  finished_at varchar null
@@ -224,6 +225,7 @@ class PostgreStorage {
224
225
  yield this.addColumns(client, ['crowdin_id'], 'app_metadata');
225
226
  yield this.addColumns(client, ['agent_id'], 'crowdin_credentials');
226
227
  yield this.addColumn(client, 'attempt', 'job', 'int default 0');
228
+ yield this.addColumn(client, 'errors', 'job', 'varchar NULL');
227
229
  yield this.addColumn(client, 'managers', 'integration_credentials', 'varchar NULL');
228
230
  });
229
231
  }
@@ -642,7 +644,7 @@ class PostgreStorage {
642
644
  return id;
643
645
  });
644
646
  }
645
- updateJob({ id, progress, status, info, data, attempt }) {
647
+ updateJob({ id, progress, status, info, data, attempt, errors }) {
646
648
  return __awaiter(this, void 0, void 0, function* () {
647
649
  let parametersPointer = 1;
648
650
  const updateFields = [`updated_at = $${parametersPointer}`];
@@ -682,6 +684,11 @@ class PostgreStorage {
682
684
  updateFields.push('attempt = $' + parametersPointer);
683
685
  updateParams.push(attempt);
684
686
  }
687
+ if (errors) {
688
+ parametersPointer++;
689
+ updateFields.push('errors = $' + parametersPointer);
690
+ updateParams.push(JSON.stringify(errors));
691
+ }
685
692
  parametersPointer++;
686
693
  updateParams.push(id);
687
694
  yield this.dbPromise;
@@ -698,7 +705,7 @@ class PostgreStorage {
698
705
  return this.executeQuery((client) => __awaiter(this, void 0, void 0, function* () {
699
706
  const res = yield client.query(`
700
707
  SELECT id, integration_id as "integrationId", crowdin_id as "crowdinId", type, payload, progress, status,
701
- title, info, data, attempt, created_at as "createdAt", updated_at as "updatedAt", finished_at as "finishedAt"
708
+ title, info, data, attempt, errors, created_at as "createdAt", updated_at as "updatedAt", finished_at as "finishedAt"
702
709
  FROM job
703
710
  WHERE id = $1
704
711
  `, [id]);
@@ -712,7 +719,7 @@ class PostgreStorage {
712
719
  return this.executeQuery((client) => __awaiter(this, void 0, void 0, function* () {
713
720
  const res = yield client.query(`
714
721
  SELECT id, integration_id as "integrationId", crowdin_id as "crowdinId", type, payload, progress, status,
715
- title, info, data, attempt, created_at as "createdAt", updated_at as "updatedAt", finished_at as "finishedAt"
722
+ title, info, data, attempt, errors, created_at as "createdAt", updated_at as "updatedAt", finished_at as "finishedAt"
716
723
  FROM job
717
724
  WHERE integration_id = $1 AND crowdin_id = $2 AND finished_at is NULL
718
725
  `, [integrationId, crowdinId]);
@@ -732,7 +739,7 @@ class PostgreStorage {
732
739
  return this.executeQuery((client) => __awaiter(this, void 0, void 0, function* () {
733
740
  const res = yield client.query(`
734
741
  SELECT id, integration_id as "integrationId", crowdin_id as "crowdinId", type, payload, progress, status,
735
- title, info, data, attempt, created_at as "createdAt", updated_at as "updatedAt", finished_at as "finishedAt"
742
+ title, info, data, attempt, errors, created_at as "createdAt", updated_at as "updatedAt", finished_at as "finishedAt"
736
743
  FROM job
737
744
  WHERE status IN ($1, $2) AND finished_at is NULL
738
745
  `, [types_2.JobStatus.IN_PROGRESS, types_2.JobStatus.CREATED]);
@@ -76,7 +76,7 @@ export declare class SQLiteStorage implements Storage {
76
76
  getIntegrationConfig(integrationId: string): Promise<IntegrationConfig | undefined>;
77
77
  updateIntegrationConfig(integrationId: string, config: any): Promise<void>;
78
78
  createJob({ integrationId, crowdinId, type, title, payload }: CreateJobParams): Promise<string>;
79
- updateJob({ id, progress, status, info, data, attempt }: UpdateJobParams): Promise<void>;
79
+ updateJob({ id, progress, status, info, data, attempt, errors }: UpdateJobParams): Promise<void>;
80
80
  getJob({ id }: GetJobParams): Promise<Job | undefined>;
81
81
  getActiveJobs({ integrationId, crowdinId }: GetActiveJobsParams): Promise<Job[] | undefined>;
82
82
  deleteFinishedJobs(): Promise<void>;
@@ -98,6 +98,7 @@ class SQLiteStorage {
98
98
  info varchar null,
99
99
  data varchar null,
100
100
  attempt varchar DEFAULT 0,
101
+ errors varchar null,
101
102
  created_at varchar not null,
102
103
  updated_at varchar null,
103
104
  finished_at varchar null
@@ -234,6 +235,7 @@ class SQLiteStorage {
234
235
  yield this.addColumns(['app_secret', 'domain', 'user_id', 'agent_id', 'organization_id', 'base_url'], 'crowdin_credentials');
235
236
  yield this.addColumns(['crowdin_id'], 'app_metadata');
236
237
  yield this.addColumn('job', 'attempt', 'DEFAULT 0');
238
+ yield this.addColumn('job', 'errors', 'null');
237
239
  yield this.addColumn('integration_credentials', 'managers', 'null');
238
240
  });
239
241
  }
@@ -575,7 +577,7 @@ class SQLiteStorage {
575
577
  return id;
576
578
  });
577
579
  }
578
- updateJob({ id, progress, status, info, data, attempt }) {
580
+ updateJob({ id, progress, status, info, data, attempt, errors }) {
579
581
  const updateFields = ['updated_at = ?'];
580
582
  const updateParams = [Date.now().toString()];
581
583
  if (progress) {
@@ -606,6 +608,10 @@ class SQLiteStorage {
606
608
  updateFields.push('attempt = ?');
607
609
  updateParams.push(attempt);
608
610
  }
611
+ if (errors) {
612
+ updateFields.push('errors = ?');
613
+ updateParams.push(JSON.stringify(errors));
614
+ }
609
615
  updateParams.push(id);
610
616
  const query = `
611
617
  UPDATE job
@@ -618,7 +624,7 @@ class SQLiteStorage {
618
624
  return __awaiter(this, void 0, void 0, function* () {
619
625
  const row = yield this.get(`
620
626
  SELECT id, integration_id as integrationId, crowdin_id as crowdinId, type, payload, progress, status,
621
- title, info, data, attempt, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
627
+ title, info, data, attempt, errors, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
622
628
  FROM job
623
629
  WHERE id = ?
624
630
  `, [id]);
@@ -630,7 +636,7 @@ class SQLiteStorage {
630
636
  getActiveJobs({ integrationId, crowdinId }) {
631
637
  return __awaiter(this, void 0, void 0, function* () {
632
638
  return this.each(`
633
- SELECT id, integration_id as integrationId, crowdin_id as crowdinId, type, payload, progress, status, title, info, data, attempt, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
639
+ SELECT id, integration_id as integrationId, crowdin_id as crowdinId, type, payload, progress, status, title, info, data, attempt, errors, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
634
640
  FROM job
635
641
  WHERE integration_id = ? AND crowdin_id = ? AND finished_at is NULL
636
642
  `, [integrationId, crowdinId]);
@@ -644,7 +650,7 @@ class SQLiteStorage {
644
650
  getAllInProgressJobs() {
645
651
  return __awaiter(this, void 0, void 0, function* () {
646
652
  return this.each(`
647
- SELECT id, integration_id as integrationId, crowdin_id as crowdinId, type, payload, progress, status, title, info, data, attempt, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
653
+ SELECT id, integration_id as integrationId, crowdin_id as crowdinId, type, payload, progress, status, title, info, data, attempt, errors, created_at as createdAt, updated_at as updatedAt, finished_at as finishedAt
648
654
  FROM job
649
655
  WHERE status IN (?,?) AND finished_at is NULL
650
656
  `, [types_2.JobStatus.IN_PROGRESS, types_2.JobStatus.CREATED]);
@@ -218,50 +218,64 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, context,
218
218
  }
219
219
  exports.prepareCrowdinClient = prepareCrowdinClient;
220
220
  function prepareIntegrationCredentials(config, integration, integrationCredentials) {
221
- var _a, _b, _c, _d, _e, _f, _g;
222
221
  return __awaiter(this, void 0, void 0, function* () {
223
222
  const credentials = JSON.parse((0, _1.decryptData)(config, integrationCredentials.credentials));
224
223
  credentials.ownerId = crowdinAppFunctions.parseCrowdinId(integrationCredentials.id).userId;
225
224
  const oauthLogin = integration.oauthLogin;
226
225
  const integrationLogin = integration.loginForm;
226
+ // Add tokenProvider function to credentials for dynamic token refresh
227
227
  if ((oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.refresh) || (integrationLogin === null || integrationLogin === void 0 ? void 0 : integrationLogin.refresh)) {
228
- (0, logger_1.log)('Checking if integration credentials need to be refreshed');
229
- const { expireIn } = credentials;
230
- //2 min as an extra buffer
231
- const isExpired = !expireIn || expireIn - 120 < Date.now() / 1000;
232
228
  const performRefreshTokenRequest = (oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.performRefreshTokenRequest) || (integrationLogin === null || integrationLogin === void 0 ? void 0 : integrationLogin.performRefreshTokenRequest);
233
- if (isExpired) {
234
- (0, logger_1.log)('Integration credentials have expired. Requesting a new credentials');
235
- let newCredentials;
236
- if (performRefreshTokenRequest) {
237
- const loginForm = yield (0, storage_1.getStorage)().getMetadata((0, defaults_1.getOAuthLoginFormId)(integrationCredentials.id));
238
- newCredentials = yield performRefreshTokenRequest(credentials, loginForm);
239
- }
240
- else if (oauthLogin) {
241
- const url = oauthLogin.refreshTokenUrl || oauthLogin.accessTokenUrl;
242
- const request = {};
243
- request[((_a = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _a === void 0 ? void 0 : _a.clientId) || 'client_id'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientId;
244
- request[((_b = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _b === void 0 ? void 0 : _b.clientSecret) || 'client_secret'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientSecret;
245
- request[((_c = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _c === void 0 ? void 0 : _c.refreshToken) || 'refresh_token'] = credentials.refreshToken;
246
- if (oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraRefreshTokenParameters) {
247
- Object.entries(oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraRefreshTokenParameters).forEach(([key, value]) => (request[key] = value));
229
+ credentials.tokenProvider = {
230
+ getToken: (force = false) => __awaiter(this, void 0, void 0, function* () {
231
+ var _a, _b, _c, _d, _e, _f, _g;
232
+ const { expireIn } = credentials;
233
+ //2 min as an extra buffer
234
+ const isExpired = !expireIn || expireIn - 120 < Date.now() / 1000;
235
+ if (!force && !isExpired) {
236
+ return credentials.accessToken;
248
237
  }
249
- newCredentials = (yield axios_1.default.post(url || '', request, {
250
- headers: { Accept: 'application/json' },
251
- })).data;
252
- }
253
- else {
254
- return credentials;
255
- }
256
- credentials.accessToken = newCredentials[((_d = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _d === void 0 ? void 0 : _d.accessToken) || 'access_token'];
257
- credentials.expireIn =
258
- Number(newCredentials[((_e = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _e === void 0 ? void 0 : _e.expiresIn) || 'expires_in']) + Date.now() / 1000;
259
- if (newCredentials[((_f = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _f === void 0 ? void 0 : _f.refreshToken) || 'refresh_token']) {
260
- credentials.refreshToken = newCredentials[((_g = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _g === void 0 ? void 0 : _g.refreshToken) || 'refresh_token'];
261
- }
262
- (0, logger_1.log)('Saving updated integration credentials in the database');
263
- yield (0, storage_1.getStorage)().updateIntegrationCredentials(integrationCredentials.id, (0, _1.encryptData)(config, JSON.stringify(credentials)));
264
- }
238
+ (0, logger_1.log)(force
239
+ ? 'Force refreshing integration credentials'
240
+ : 'Integration credentials have expired during operation. Requesting a new credentials');
241
+ let newCredentials;
242
+ if (performRefreshTokenRequest) {
243
+ const loginForm = yield (0, storage_1.getStorage)().getMetadata((0, defaults_1.getOAuthLoginFormId)(integrationCredentials.id));
244
+ newCredentials = yield performRefreshTokenRequest(credentials, loginForm);
245
+ }
246
+ else if (oauthLogin) {
247
+ const url = oauthLogin.refreshTokenUrl || oauthLogin.accessTokenUrl;
248
+ const request = {};
249
+ request[((_a = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _a === void 0 ? void 0 : _a.clientId) || 'client_id'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientId;
250
+ request[((_b = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _b === void 0 ? void 0 : _b.clientSecret) || 'client_secret'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientSecret;
251
+ request[((_c = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _c === void 0 ? void 0 : _c.refreshToken) || 'refresh_token'] = credentials.refreshToken;
252
+ if (oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraRefreshTokenParameters) {
253
+ Object.entries(oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraRefreshTokenParameters).forEach(([key, value]) => (request[key] = value));
254
+ }
255
+ newCredentials = (yield axios_1.default.post(url || '', request, {
256
+ headers: { Accept: 'application/json' },
257
+ })).data;
258
+ }
259
+ else {
260
+ return credentials.accessToken;
261
+ }
262
+ credentials.accessToken = newCredentials[((_d = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _d === void 0 ? void 0 : _d.accessToken) || 'access_token'];
263
+ credentials.expireIn =
264
+ Number(newCredentials[((_e = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _e === void 0 ? void 0 : _e.expiresIn) || 'expires_in']) + Date.now() / 1000;
265
+ if (newCredentials[((_f = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _f === void 0 ? void 0 : _f.refreshToken) || 'refresh_token']) {
266
+ credentials.refreshToken =
267
+ newCredentials[((_g = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _g === void 0 ? void 0 : _g.refreshToken) || 'refresh_token'];
268
+ }
269
+ (0, logger_1.log)('Saving updated integration credentials in the database');
270
+ yield (0, storage_1.getStorage)().updateIntegrationCredentials(integrationCredentials.id, (0, _1.encryptData)(config, JSON.stringify(credentials)));
271
+ return credentials.accessToken;
272
+ }),
273
+ refreshToken: () => {
274
+ return credentials.tokenProvider.getToken(true);
275
+ },
276
+ };
277
+ (0, logger_1.log)('Checking if integration credentials need to be refreshed');
278
+ yield credentials.tokenProvider.getToken();
265
279
  }
266
280
  return credentials;
267
281
  });
package/out/util/index.js CHANGED
@@ -64,7 +64,7 @@ function handleError(err, req, res) {
64
64
  res.render('error', errorMessage);
65
65
  }
66
66
  else {
67
- res.status(code).send(errorMessage);
67
+ res.status(code).send({ error: errorMessage });
68
68
  }
69
69
  }
70
70
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.95.3",
3
+ "version": "0.96.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",