@crowdin/app-project-module 0.98.0 → 0.99.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.
@@ -15,7 +15,9 @@ const crowdin_file_progress_1 = __importDefault(require("../integration/handlers
15
15
  const crowdin_files_1 = __importDefault(require("../integration/handlers/crowdin-files"));
16
16
  const crowdin_update_1 = __importDefault(require("../integration/handlers/crowdin-update"));
17
17
  const integration_data_1 = __importDefault(require("../integration/handlers/integration-data"));
18
+ const job_info_deprecated_1 = __importDefault(require("../integration/handlers/job-info-deprecated"));
18
19
  const job_info_1 = __importDefault(require("../integration/handlers/job-info"));
20
+ const job_list_1 = __importDefault(require("../integration/handlers/job-list"));
19
21
  const job_cancel_1 = __importDefault(require("../integration/handlers/job-cancel"));
20
22
  const integration_login_1 = __importDefault(require("../integration/handlers/integration-login"));
21
23
  const integration_update_1 = __importDefault(require("../integration/handlers/integration-update"));
@@ -85,6 +87,20 @@ function getDefaultApiEndpointsManifest(config) {
85
87
  method: types_1.RequestMethods.POST,
86
88
  description: 'Update integration data',
87
89
  documentationUrl: '/api-docs#tag/Files/operation/integration.update',
90
+ }, {
91
+ key: 'job-list-api',
92
+ name: 'Job List',
93
+ url: '/all-jobs',
94
+ method: types_1.RequestMethods.GET,
95
+ description: 'Get All Jobs',
96
+ documentationUrl: '/api-docs#tag/Jobs/operation/job.list',
97
+ }, {
98
+ key: 'job-info-api',
99
+ name: 'Job Info',
100
+ url: '/job-info',
101
+ method: types_1.RequestMethods.GET,
102
+ description: 'Get Job Info',
103
+ documentationUrl: '/api-docs#tag/Jobs/operation/job.info',
88
104
  }, {
89
105
  key: 'job-get-api',
90
106
  name: 'Job Status',
@@ -94,7 +110,7 @@ function getDefaultApiEndpointsManifest(config) {
94
110
  documentationUrl: '/api-docs#tag/Jobs/operation/job.get',
95
111
  }, {
96
112
  key: 'job-cancel-api',
97
- name: 'Job Status',
113
+ name: 'Cancel Job',
98
114
  url: '/jobs',
99
115
  method: types_1.RequestMethods.DELETE,
100
116
  description: 'Cancel Job',
@@ -308,6 +324,74 @@ function addDefaultApiEndpoints(app, config) {
308
324
  checkSubscriptionExpiration: true,
309
325
  moduleKey: 'integration-update-api',
310
326
  }), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_update_1.default)(config, config.projectIntegration));
327
+ /**
328
+ * @openapi
329
+ * /all-jobs:
330
+ * get:
331
+ * tags:
332
+ * - 'Jobs'
333
+ * summary: 'List Jobs'
334
+ * operationId: job.list
335
+ * parameters:
336
+ * - $ref: '#/components/parameters/ProjectId'
337
+ * - name: limit
338
+ * in: query
339
+ * required: false
340
+ * description: 'Number of jobs to return'
341
+ * schema:
342
+ * type: integer
343
+ * example: 25
344
+ * - name: offset
345
+ * in: query
346
+ * required: false
347
+ * description: 'Number of jobs to skip'
348
+ * schema:
349
+ * type: integer
350
+ * example: 0
351
+ * responses:
352
+ * 200:
353
+ * description: 'Job information retrieved successfully'
354
+ * content:
355
+ * application/json:
356
+ * schema:
357
+ * $ref: '#/components/schemas/JobResponse'
358
+ */
359
+ app.get('/all-jobs', api_call_1.default, json_response_1.default, (0, crowdin_client_1.default)({
360
+ config,
361
+ optional: false,
362
+ checkSubscriptionExpiration: true,
363
+ moduleKey: 'job-list-api',
364
+ }), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_list_1.default)());
365
+ /**
366
+ * @openapi
367
+ * /job-info:
368
+ * get:
369
+ * tags:
370
+ * - 'Jobs'
371
+ * summary: 'Get Job Info'
372
+ * operationId: job.info
373
+ * parameters:
374
+ * - $ref: '#/components/parameters/ProjectId'
375
+ * - name: jobId
376
+ * in: query
377
+ * required: true
378
+ * schema:
379
+ * type: string
380
+ * example: 067da473-fc0b-43e3-b0a2-09d26af130c1
381
+ * responses:
382
+ * 200:
383
+ * description: 'Job information retrieved successfully'
384
+ * content:
385
+ * application/json:
386
+ * schema:
387
+ * $ref: '#/components/schemas/JobResponse'
388
+ */
389
+ app.get('/job-info', api_call_1.default, json_response_1.default, (0, crowdin_client_1.default)({
390
+ config,
391
+ optional: false,
392
+ checkSubscriptionExpiration: true,
393
+ moduleKey: 'job-info-api',
394
+ }), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_info_1.default)());
311
395
  /**
312
396
  * @openapi
313
397
  * /jobs:
@@ -316,6 +400,7 @@ function addDefaultApiEndpoints(app, config) {
316
400
  * - 'Jobs'
317
401
  * summary: 'Get Job Info'
318
402
  * operationId: job.get
403
+ * deprecated: true
319
404
  * parameters:
320
405
  * - $ref: '#/components/parameters/ProjectId'
321
406
  * - name: jobId
@@ -337,7 +422,7 @@ function addDefaultApiEndpoints(app, config) {
337
422
  optional: false,
338
423
  checkSubscriptionExpiration: true,
339
424
  moduleKey: 'job-get-api',
340
- }), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_info_1.default)(config));
425
+ }), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_info_deprecated_1.default)(config));
341
426
  /**
342
427
  * @openapi
343
428
  * /jobs:
@@ -64,7 +64,7 @@ function handle(config, integration) {
64
64
  payload = yield (0, files_1.expandFilesTree)(payload, req, integration, job);
65
65
  payload = (0, lodash_uniqby_1.default)(payload, 'id');
66
66
  }
67
- if (!forcePushSources && (payload === null || payload === void 0 ? void 0 : payload.length)) {
67
+ if (integration.forcePushSources === true && !forcePushSources && (payload === null || payload === void 0 ? void 0 : payload.length)) {
68
68
  payload = yield (0, files_1.filterSyncedData)(payload);
69
69
  }
70
70
  const result = yield integration.updateCrowdin({
@@ -0,0 +1,4 @@
1
+ /// <reference types="qs" />
2
+ import { Response } from 'express';
3
+ import { Config } from '../../../types';
4
+ export default function handle(config: Config): (req: import("../../../types").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;
@@ -0,0 +1,138 @@
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
+ const types_1 = require("../util/types");
13
+ const util_1 = require("../../../util");
14
+ const storage_1 = require("../../../storage");
15
+ const cron_1 = require("../util/cron");
16
+ const defaults_1 = require("../util/defaults");
17
+ const connection_1 = require("../../../util/connection");
18
+ const logger_1 = require("../../../util/logger");
19
+ const MINUTES = 60;
20
+ function getHumanETA(ms) {
21
+ const seconds = Math.floor(ms / 1000);
22
+ let minutes = Math.floor(seconds / 60);
23
+ const hours = Math.floor(minutes / 60);
24
+ if (seconds < 60) {
25
+ return 'Less than a minute remaining';
26
+ }
27
+ minutes = minutes % 60;
28
+ const timeParts = [];
29
+ if (hours) {
30
+ timeParts.push(`${hours} ${hours > 1 ? 'hours' : 'hour'}`);
31
+ }
32
+ if (minutes) {
33
+ timeParts.push(`${minutes} ${minutes > 1 ? 'minutes' : 'minute'}`);
34
+ }
35
+ return `About ${timeParts.join(' and ')} remaining`;
36
+ }
37
+ function handle(config) {
38
+ return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
39
+ const isApi = req.isApiCall;
40
+ const id = req.query.jobId || req.body.jobId;
41
+ if (!id) {
42
+ req.logInfo('Get active jobs');
43
+ const jobs = yield (0, storage_1.getStorage)().getActiveJobs({
44
+ integrationId: req.crowdinContext.clientId,
45
+ crowdinId: req.crowdinContext.crowdinId,
46
+ });
47
+ if (isApi && jobs) {
48
+ const filteredJobs = jobs.map((job) => ({
49
+ id: job.id,
50
+ progress: job.progress,
51
+ status: job.status,
52
+ title: job.title,
53
+ }));
54
+ req.logInfo(`Returning active filtered jobs info ${JSON.stringify(filteredJobs, null, 2)}`);
55
+ res.send(filteredJobs);
56
+ return;
57
+ }
58
+ req.logInfo(`Returning active jobs info ${JSON.stringify(jobs, null, 2)}`);
59
+ res.send(jobs);
60
+ return;
61
+ }
62
+ req.logInfo(`Get job info for id ${id}`);
63
+ const job = yield (0, storage_1.getStorage)().getJob({ id });
64
+ if (isApi && !job) {
65
+ return res.status(404).json({
66
+ error: {
67
+ message: `Job with ID ${id} not found`,
68
+ },
69
+ });
70
+ }
71
+ if (job && job.status === types_1.JobStatus.IN_PROGRESS && job.progress > 5 && job.updatedAt) {
72
+ job.eta = ((Date.now() - job.createdAt) / job.progress) * (100 - job.progress);
73
+ job.info = getHumanETA(job.eta) + (job.info ? `\n${job.info}` : '');
74
+ }
75
+ if (isApi && job) {
76
+ const filteredJob = {
77
+ id: job.id,
78
+ progress: job.progress,
79
+ status: job.status,
80
+ title: job.title,
81
+ };
82
+ req.logInfo(`Returning filtered job info ${JSON.stringify(filteredJob, null, 2)}`);
83
+ res.send([filteredJob]);
84
+ return;
85
+ }
86
+ if (job && (job === null || job === void 0 ? void 0 : job.updatedAt) && Date.now() - job.updatedAt >= MINUTES * 60 * 1000) {
87
+ const context = req.crowdinContext;
88
+ const projectId = context.jwtPayload.context.project_id;
89
+ const integration = config.projectIntegration;
90
+ const crowdinId = req.crowdinContext.crowdinId;
91
+ const integrationId = req.crowdinContext.clientId;
92
+ try {
93
+ const integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(integrationId);
94
+ const credentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
95
+ const integrationConfig = yield (0, storage_1.getStorage)().getIntegrationConfig(integrationId);
96
+ const intConfig = (integrationConfig === null || integrationConfig === void 0 ? void 0 : integrationConfig.config)
97
+ ? JSON.parse(integrationConfig.config)
98
+ : { schedule: '0', condition: '0' };
99
+ const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, req.crowdinApiClient, projectId);
100
+ req.logInfo(`Restarting the job after no updates for more than ${MINUTES} minutes.`);
101
+ return (0, cron_1.runUpdateProviderJob)({
102
+ integrationId,
103
+ crowdinId,
104
+ type: job.type,
105
+ title: job.title,
106
+ payload: JSON.parse(job.payload),
107
+ jobType: types_1.JobClientType.RERUN,
108
+ projectId,
109
+ client: req.crowdinApiClient,
110
+ integration,
111
+ context,
112
+ credentials,
113
+ rootFolder,
114
+ appSettings: intConfig,
115
+ reRunJobId: id,
116
+ });
117
+ }
118
+ catch (e) {
119
+ (0, logger_1.logError)(e);
120
+ yield (0, storage_1.getStorage)().updateJob({
121
+ id: job.id,
122
+ status: types_1.JobStatus.FAILED,
123
+ info: (0, logger_1.getErrorMessage)(e),
124
+ });
125
+ return res.status(500).json({
126
+ error: {
127
+ message: `Job was failed after attempt to restart it due to inactivity (no updates for ${MINUTES} minutes). Please try to restart the job manually.`,
128
+ jobId: job.id,
129
+ status: types_1.JobStatus.FAILED,
130
+ },
131
+ });
132
+ }
133
+ }
134
+ req.logInfo(`Returning job info ${JSON.stringify(job, null, 2)}`);
135
+ res.send(job);
136
+ }));
137
+ }
138
+ exports.default = handle;
@@ -1,4 +1,3 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- import { Config } from '../../../types';
4
- export default function handle(config: Config): (req: import("../../../types").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;
3
+ export default function handle(): (req: import("../../../types").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;
@@ -12,11 +12,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const types_1 = require("../util/types");
13
13
  const util_1 = require("../../../util");
14
14
  const storage_1 = require("../../../storage");
15
- const cron_1 = require("../util/cron");
16
- const defaults_1 = require("../util/defaults");
17
- const connection_1 = require("../../../util/connection");
18
- const logger_1 = require("../../../util/logger");
19
- const MINUTES = 60;
20
15
  function getHumanETA(ms) {
21
16
  const seconds = Math.floor(ms / 1000);
22
17
  let minutes = Math.floor(seconds / 60);
@@ -34,30 +29,19 @@ function getHumanETA(ms) {
34
29
  }
35
30
  return `About ${timeParts.join(' and ')} remaining`;
36
31
  }
37
- function handle(config) {
32
+ function handle() {
38
33
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
39
34
  const isApi = req.isApiCall;
40
35
  const id = req.query.jobId || req.body.jobId;
41
36
  if (!id) {
42
- req.logInfo('Get active jobs');
43
- const jobs = yield (0, storage_1.getStorage)().getActiveJobs({
44
- integrationId: req.crowdinContext.clientId,
45
- crowdinId: req.crowdinContext.crowdinId,
46
- });
47
- if (isApi && jobs) {
48
- const filteredJobs = jobs.map((job) => ({
49
- id: job.id,
50
- progress: job.progress,
51
- status: job.status,
52
- title: job.title,
53
- }));
54
- req.logInfo(`Returning active filtered jobs info ${JSON.stringify(filteredJobs, null, 2)}`);
55
- res.send(filteredJobs);
56
- return;
37
+ if (isApi) {
38
+ return res.status(400).json({
39
+ error: {
40
+ message: 'jobId is required',
41
+ },
42
+ });
57
43
  }
58
- req.logInfo(`Returning active jobs info ${JSON.stringify(jobs, null, 2)}`);
59
- res.send(jobs);
60
- return;
44
+ return res.status(400).send('jobId is required');
61
45
  }
62
46
  req.logInfo(`Get job info for id ${id}`);
63
47
  const job = yield (0, storage_1.getStorage)().getJob({ id });
@@ -73,64 +57,25 @@ function handle(config) {
73
57
  job.info = getHumanETA(job.eta) + (job.info ? `\n${job.info}` : '');
74
58
  }
75
59
  if (isApi && job) {
76
- const filteredJob = {
60
+ const baseJob = {
77
61
  id: job.id,
62
+ info: job.info,
63
+ data: job.data,
64
+ attempt: job.attempt,
65
+ payload: job.payload,
66
+ eta: job.eta,
78
67
  progress: job.progress,
79
68
  status: job.status,
80
69
  title: job.title,
70
+ type: job.type,
71
+ createdAt: new Date(+job.createdAt).toISOString(),
72
+ updatedAt: job.updatedAt ? new Date(+job.updatedAt).toISOString() : null,
73
+ finishedAt: job.finishedAt ? new Date(+job.finishedAt).toISOString() : null,
81
74
  };
82
- req.logInfo(`Returning filtered job info ${JSON.stringify(filteredJob, null, 2)}`);
83
- res.send([filteredJob]);
75
+ req.logInfo(`Returning filtered job info ${JSON.stringify(baseJob, null, 2)}`);
76
+ res.send(baseJob);
84
77
  return;
85
78
  }
86
- if (job && (job === null || job === void 0 ? void 0 : job.updatedAt) && Date.now() - job.updatedAt >= MINUTES * 60 * 1000) {
87
- const context = req.crowdinContext;
88
- const projectId = context.jwtPayload.context.project_id;
89
- const integration = config.projectIntegration;
90
- const crowdinId = req.crowdinContext.crowdinId;
91
- const integrationId = req.crowdinContext.clientId;
92
- try {
93
- const integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(integrationId);
94
- const credentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
95
- const integrationConfig = yield (0, storage_1.getStorage)().getIntegrationConfig(integrationId);
96
- const intConfig = (integrationConfig === null || integrationConfig === void 0 ? void 0 : integrationConfig.config)
97
- ? JSON.parse(integrationConfig.config)
98
- : { schedule: '0', condition: '0' };
99
- const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, req.crowdinApiClient, projectId);
100
- req.logInfo(`Restarting the job after no updates for more than ${MINUTES} minutes.`);
101
- return (0, cron_1.runUpdateProviderJob)({
102
- integrationId,
103
- crowdinId,
104
- type: job.type,
105
- title: job.title,
106
- payload: JSON.parse(job.payload),
107
- jobType: types_1.JobClientType.RERUN,
108
- projectId,
109
- client: req.crowdinApiClient,
110
- integration,
111
- context,
112
- credentials,
113
- rootFolder,
114
- appSettings: intConfig,
115
- reRunJobId: id,
116
- });
117
- }
118
- catch (e) {
119
- (0, logger_1.logError)(e);
120
- yield (0, storage_1.getStorage)().updateJob({
121
- id: job.id,
122
- status: types_1.JobStatus.FAILED,
123
- info: (0, logger_1.getErrorMessage)(e),
124
- });
125
- return res.status(500).json({
126
- error: {
127
- message: `Job was failed after attempt to restart it due to inactivity (no updates for ${MINUTES} minutes). Please try to restart the job manually.`,
128
- jobId: job.id,
129
- status: types_1.JobStatus.FAILED,
130
- },
131
- });
132
- }
133
- }
134
79
  req.logInfo(`Returning job info ${JSON.stringify(job, null, 2)}`);
135
80
  res.send(job);
136
81
  }));
@@ -0,0 +1,3 @@
1
+ /// <reference types="qs" />
2
+ import { Response } from 'express';
3
+ export default function handle(): (req: import("../../../types").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;
@@ -0,0 +1,46 @@
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
+ const util_1 = require("../../../util");
13
+ const storage_1 = require("../../../storage");
14
+ function handle() {
15
+ return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
16
+ const limit = req.query.limit ? parseInt(req.query.limit, 10) : 25;
17
+ const offset = req.query.offset ? parseInt(req.query.offset, 10) : 0;
18
+ req.logInfo('Get all jobs');
19
+ const jobs = yield (0, storage_1.getStorage)().getAllJobs({
20
+ integrationId: req.crowdinContext.clientId,
21
+ crowdinId: req.crowdinContext.crowdinId,
22
+ limit,
23
+ offset,
24
+ });
25
+ if (!jobs) {
26
+ req.logInfo('No jobs found');
27
+ res.send([]);
28
+ return;
29
+ }
30
+ const filteredJobs = jobs.map((job) => {
31
+ const baseJob = {
32
+ id: job.id,
33
+ progress: job.progress,
34
+ status: job.status,
35
+ title: job.title,
36
+ type: job.type,
37
+ createdAt: new Date(+job.createdAt).toISOString(),
38
+ finishedAt: job.finishedAt ? new Date(+job.finishedAt).toISOString() : null,
39
+ };
40
+ return baseJob;
41
+ });
42
+ req.logInfo(`Returning ${filteredJobs.length} jobs`);
43
+ res.send(filteredJobs);
44
+ }));
45
+ }
46
+ exports.default = handle;
@@ -54,7 +54,9 @@ const integration_logout_1 = __importDefault(require("./handlers/integration-log
54
54
  const integration_update_1 = __importDefault(require("./handlers/integration-update"));
55
55
  const integration_webhook_1 = __importDefault(require("./handlers/integration-webhook"));
56
56
  const job_cancel_1 = __importDefault(require("./handlers/job-cancel"));
57
+ const job_info_deprecated_1 = __importDefault(require("./handlers/job-info-deprecated"));
57
58
  const job_info_1 = __importDefault(require("./handlers/job-info"));
59
+ const job_list_1 = __importDefault(require("./handlers/job-list"));
58
60
  const main_1 = __importDefault(require("./handlers/main"));
59
61
  const oauth_login_1 = __importDefault(require("./handlers/oauth-login"));
60
62
  const oauth_url_1 = __importDefault(require("./handlers/oauth-url"));
@@ -88,12 +90,24 @@ function register({ config, app }) {
88
90
  checkSubscriptionExpiration: true,
89
91
  moduleKey: integrationLogic.key,
90
92
  }), (0, subscription_info_1.default)(config));
93
+ app.get('/api/all-jobs', json_response_1.default, (0, crowdin_client_1.default)({
94
+ config,
95
+ optional: false,
96
+ checkSubscriptionExpiration: true,
97
+ moduleKey: integrationLogic.key,
98
+ }), (0, job_list_1.default)());
99
+ app.get('/api/job-info', json_response_1.default, (0, crowdin_client_1.default)({
100
+ config,
101
+ optional: false,
102
+ checkSubscriptionExpiration: true,
103
+ moduleKey: integrationLogic.key,
104
+ }), (0, job_info_1.default)());
91
105
  app.get('/api/jobs', json_response_1.default, (0, crowdin_client_1.default)({
92
106
  config,
93
107
  optional: false,
94
108
  checkSubscriptionExpiration: true,
95
109
  moduleKey: integrationLogic.key,
96
- }), (0, job_info_1.default)(config));
110
+ }), (0, job_info_deprecated_1.default)(config));
97
111
  app.delete('/api/jobs', json_response_1.default, (0, crowdin_client_1.default)({
98
112
  config,
99
113
  optional: false,
@@ -126,3 +126,9 @@ export interface IntegrationSyncedData {
126
126
  updatedAt: string;
127
127
  files?: any;
128
128
  }
129
+ export type GetAllJobsParams = {
130
+ integrationId: string;
131
+ crowdinId: string;
132
+ limit: number;
133
+ offset: number;
134
+ };
@@ -1,6 +1,6 @@
1
1
  import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks, Provider } from '../modules/integration/types';
2
2
  import { Config, CrowdinCredentials, UnauthorizedConfig } from '../types';
3
- import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData } from '../modules/integration/util/types';
3
+ import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData, GetAllJobsParams } from '../modules/integration/util/types';
4
4
  import { UserErrors } from './types';
5
5
  export declare const TABLES: {
6
6
  crowdin_credentials: string;
@@ -62,6 +62,7 @@ export interface Storage {
62
62
  getActiveJobs(params: GetActiveJobsParams): Promise<Job[] | undefined>;
63
63
  deleteFinishedJobs(): Promise<void>;
64
64
  getAllInProgressJobs(): Promise<Job[] | undefined>;
65
+ getAllJobs(params: GetAllJobsParams): Promise<Job[] | undefined>;
65
66
  saveTranslationCache(params: TranslationCache): Promise<void>;
66
67
  getFileTranslationCache(params: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
67
68
  getFileTranslationCacheByLanguage(params: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
@@ -1,6 +1,6 @@
1
1
  import { Storage } from '.';
2
2
  import { CrowdinCredentials } from '../types';
3
- import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData } from '../modules/integration/util/types';
3
+ import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData, GetAllJobsParams } from '../modules/integration/util/types';
4
4
  import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks } from '../modules/integration/types';
5
5
  import { UserErrors } from './types';
6
6
  export interface MySQLStorageConfig {
@@ -83,6 +83,7 @@ export declare class MySQLStorage implements Storage {
83
83
  getActiveJobs({ integrationId, crowdinId }: GetActiveJobsParams): Promise<Job[] | undefined>;
84
84
  deleteFinishedJobs(): Promise<void>;
85
85
  getAllInProgressJobs(): Promise<Job[] | undefined>;
86
+ getAllJobs({ integrationId, crowdinId, limit, offset }: GetAllJobsParams): Promise<Job[] | undefined>;
86
87
  saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }: TranslationCache): Promise<void>;
87
88
  getFileTranslationCache({ integrationId, crowdinId, fileId, }: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
88
89
  getFileTranslationCacheByLanguage({ integrationId, crowdinId, fileId, languageId, }: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
@@ -289,6 +289,7 @@ class MySQLStorage {
289
289
  yield connection.execute('DELETE FROM job WHERE crowdin_id = ?', [id]);
290
290
  yield connection.execute('DELETE FROM translation_file_cache WHERE crowdin_id = ?', [id]);
291
291
  yield connection.execute('DELETE FROM unsynced_files WHERE crowdin_id = ?', [id]);
292
+ yield connection.execute('DELETE FROM synced_data WHERE crowdin_id = ?', [id]);
292
293
  }));
293
294
  });
294
295
  }
@@ -342,6 +343,7 @@ class MySQLStorage {
342
343
  yield connection.execute('DELETE FROM webhooks where integration_id = ?', [id]);
343
344
  yield connection.execute('DELETE FROM job where integration_id = ?', [id]);
344
345
  yield connection.execute('DELETE FROM unsynced_files where integration_id = ?', [id]);
346
+ yield connection.execute('DELETE FROM synced_data where integration_id = ?', [id]);
345
347
  }));
346
348
  });
347
349
  }
@@ -356,6 +358,7 @@ class MySQLStorage {
356
358
  yield connection.execute('DELETE FROM user_errors where crowdin_id = ?', [crowdinId]);
357
359
  yield connection.execute('DELETE FROM job where crowdin_id = ?', [crowdinId]);
358
360
  yield connection.execute('DELETE FROM unsynced_files where crowdin_id = ?', [crowdinId]);
361
+ yield connection.execute('DELETE FROM synced_data where crowdin_id = ?', [crowdinId]);
359
362
  }));
360
363
  });
361
364
  }
@@ -749,6 +752,36 @@ class MySQLStorage {
749
752
  }));
750
753
  });
751
754
  }
755
+ getAllJobs({ integrationId, crowdinId, limit, offset }) {
756
+ return __awaiter(this, void 0, void 0, function* () {
757
+ yield this.dbPromise;
758
+ return this.executeQuery((connection) => __awaiter(this, void 0, void 0, function* () {
759
+ const [rows] = yield connection.execute(`
760
+ SELECT
761
+ id,
762
+ integration_id as "integrationId",
763
+ crowdin_id as "crowdinId",
764
+ type,
765
+ payload,
766
+ progress,
767
+ status,
768
+ title,
769
+ info,
770
+ data,
771
+ attempt,
772
+ created_at as "createdAt",
773
+ updated_at as "updatedAt",
774
+ finished_at as "finishedAt"
775
+ FROM job
776
+ WHERE integration_id = ?
777
+ AND crowdin_id = ?
778
+ ORDER BY created_at DESC
779
+ LIMIT ? OFFSET ?
780
+ `, [integrationId, crowdinId, limit, offset]);
781
+ return rows || [];
782
+ }));
783
+ });
784
+ }
752
785
  saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }) {
753
786
  return __awaiter(this, void 0, void 0, function* () {
754
787
  yield this.dbPromise;
@@ -2,7 +2,7 @@ import { Client } from 'pg';
2
2
  import { Storage } from '.';
3
3
  import { CrowdinCredentials } from '../types';
4
4
  import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks } from '../modules/integration/types';
5
- import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData } from '../modules/integration/util/types';
5
+ import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData, GetAllJobsParams } from '../modules/integration/util/types';
6
6
  import { UserErrors } from './types';
7
7
  export interface PostgreStorageConfig {
8
8
  host?: string;
@@ -93,6 +93,7 @@ export declare class PostgreStorage implements Storage {
93
93
  getActiveJobs({ integrationId, crowdinId }: GetActiveJobsParams): Promise<Job[] | undefined>;
94
94
  deleteFinishedJobs(): Promise<void>;
95
95
  getAllInProgressJobs(): Promise<Job[] | undefined>;
96
+ getAllJobs({ integrationId, crowdinId, limit, offset }: GetAllJobsParams): Promise<Job[] | undefined>;
96
97
  saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }: TranslationCache): Promise<void>;
97
98
  getFileTranslationCache({ integrationId, crowdinId, fileId, }: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
98
99
  getFileTranslationCacheByLanguage({ integrationId, crowdinId, fileId, languageId, }: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
@@ -334,6 +334,7 @@ class PostgreStorage {
334
334
  yield client.query('DELETE FROM job WHERE crowdin_id = $1', [id]);
335
335
  yield client.query('DELETE FROM translation_file_cache WHERE crowdin_id = $1', [id]);
336
336
  yield client.query('DELETE FROM unsynced_files WHERE crowdin_id = $1', [id]);
337
+ yield client.query('DELETE FROM synced_data WHERE crowdin_id = $1', [id]);
337
338
  }));
338
339
  });
339
340
  }
@@ -387,6 +388,7 @@ class PostgreStorage {
387
388
  yield client.query('DELETE FROM webhooks where integration_id = $1', [id]);
388
389
  yield client.query('DELETE FROM job where integration_id = $1', [id]);
389
390
  yield client.query('DELETE FROM unsynced_files where integration_id = $1', [id]);
391
+ yield client.query('DELETE FROM synced_data where integration_id = $1', [id]);
390
392
  }));
391
393
  });
392
394
  }
@@ -401,6 +403,7 @@ class PostgreStorage {
401
403
  yield client.query('DELETE FROM user_errors where crowdin_id = $1', [crowdinId]);
402
404
  yield client.query('DELETE FROM job where crowdin_id = $1', [crowdinId]);
403
405
  yield client.query('DELETE FROM unsynced_files where crowdin_id = $1', [crowdinId]);
406
+ yield client.query('DELETE FROM synced_data where crowdin_id = $1', [crowdinId]);
404
407
  }));
405
408
  });
406
409
  }
@@ -754,6 +757,35 @@ class PostgreStorage {
754
757
  }));
755
758
  });
756
759
  }
760
+ getAllJobs({ integrationId, crowdinId, limit, offset }) {
761
+ return __awaiter(this, void 0, void 0, function* () {
762
+ yield this.dbPromise;
763
+ return this.executeQuery((client) => __awaiter(this, void 0, void 0, function* () {
764
+ const res = yield client.query(`
765
+ SELECT
766
+ id,
767
+ integration_id as "integrationId",
768
+ crowdin_id as "crowdinId",
769
+ type,
770
+ payload,
771
+ progress,
772
+ status,
773
+ title,
774
+ info,
775
+ data,
776
+ attempt,
777
+ created_at as "createdAt",
778
+ updated_at as "updatedAt",
779
+ finished_at as "finishedAt"
780
+ FROM job
781
+ WHERE integration_id = $1 AND crowdin_id = $2
782
+ ORDER BY created_at DESC
783
+ LIMIT $3 OFFSET $4
784
+ `, [integrationId, crowdinId, limit, offset]);
785
+ return (res === null || res === void 0 ? void 0 : res.rows) || [];
786
+ }));
787
+ });
788
+ }
757
789
  saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag, }) {
758
790
  return __awaiter(this, void 0, void 0, function* () {
759
791
  yield this.dbPromise;
@@ -1,7 +1,7 @@
1
1
  import { Storage } from '.';
2
2
  import { CrowdinCredentials } from '../types';
3
3
  import { IntegrationConfig, IntegrationCredentials, IntegrationFilesSnapshot, IntegrationSyncSettings, IntegrationWebhooks } from '../modules/integration/types';
4
- import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData } from '../modules/integration/util/types';
4
+ import { CreateJobParams, GetActiveJobsParams, GetJobParams, GetFileTranslationCacheByLanguageParams, Job, TranslationCache, UpdateJobParams, UpdateTranslationCacheParams, GetFileTranslationCache, UnsyncedFiles, GetUnsyncedFiles, IntegrationSyncedData, GetAllJobsParams } from '../modules/integration/util/types';
5
5
  import { UserErrors } from './types';
6
6
  export interface SQLiteStorageConfig {
7
7
  dbFolder: string;
@@ -81,6 +81,7 @@ export declare class SQLiteStorage implements Storage {
81
81
  getActiveJobs({ integrationId, crowdinId }: GetActiveJobsParams): Promise<Job[] | undefined>;
82
82
  deleteFinishedJobs(): Promise<void>;
83
83
  getAllInProgressJobs(): Promise<Job[] | undefined>;
84
+ getAllJobs({ integrationId, crowdinId, limit, offset }: GetAllJobsParams): Promise<Job[] | undefined>;
84
85
  saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag }: TranslationCache): Promise<void>;
85
86
  getFileTranslationCache({ integrationId, crowdinId, fileId, }: GetFileTranslationCache): Promise<TranslationCache[] | undefined>;
86
87
  getFileTranslationCacheByLanguage({ integrationId, crowdinId, fileId, languageId, }: GetFileTranslationCacheByLanguageParams): Promise<TranslationCache | undefined>;
@@ -359,6 +359,7 @@ class SQLiteStorage {
359
359
  yield this.run('DELETE FROM job WHERE crowdin_id = ?', [id]);
360
360
  yield this.run('DELETE FROM translation_file_cache WHERE crowdin_id = ?', [id]);
361
361
  yield this.run('DELETE FROM unsynced_files WHERE crowdin_id = ?', [id]);
362
+ yield this.run('DELETE FROM synced_data WHERE crowdin_id = ?', [id]);
362
363
  });
363
364
  }
364
365
  saveIntegrationCredentials(id, credentials, crowdinId) {
@@ -393,6 +394,7 @@ class SQLiteStorage {
393
394
  yield this.run('DELETE FROM webhooks where integration_id = ?', [id]);
394
395
  yield this.run('DELETE FROM job where integration_id = ?', [id]);
395
396
  yield this.run('DELETE FROM unsynced_files where integration_id = ?', [id]);
397
+ yield this.run('DELETE FROM synced_data where integration_id = ?', [id]);
396
398
  });
397
399
  }
398
400
  deleteAllIntegrationCredentials(crowdinId) {
@@ -404,6 +406,7 @@ class SQLiteStorage {
404
406
  yield this.run('DELETE FROM user_errors where crowdin_id = ?', [crowdinId]);
405
407
  yield this.run('DELETE FROM job where crowdin_id = ?', [crowdinId]);
406
408
  yield this.run('DELETE FROM unsynced_files where crowdin_id = ?', [crowdinId]);
409
+ yield this.run('DELETE FROM synced_data where crowdin_id = ?', [crowdinId]);
407
410
  });
408
411
  }
409
412
  saveMetadata(id, metadata, crowdinId) {
@@ -662,6 +665,31 @@ class SQLiteStorage {
662
665
  `, [types_2.JobStatus.IN_PROGRESS, types_2.JobStatus.CREATED]);
663
666
  });
664
667
  }
668
+ getAllJobs({ integrationId, crowdinId, limit, offset }) {
669
+ return __awaiter(this, void 0, void 0, function* () {
670
+ return this.each(`
671
+ SELECT
672
+ id,
673
+ integration_id as integrationId,
674
+ crowdin_id as crowdinId,
675
+ type,
676
+ payload,
677
+ progress,
678
+ status,
679
+ title,
680
+ info,
681
+ data,
682
+ attempt,
683
+ created_at as createdAt,
684
+ updated_at as updatedAt,
685
+ finished_at as finishedAt
686
+ FROM job
687
+ WHERE integration_id = ? AND crowdin_id = ?
688
+ ORDER BY created_at DESC
689
+ LIMIT ? OFFSET ?
690
+ `, [integrationId, crowdinId, limit, offset]);
691
+ });
692
+ }
665
693
  saveTranslationCache({ integrationId, crowdinId, fileId, languageId, etag }) {
666
694
  return this.run(`
667
695
  INSERT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.98.0",
3
+ "version": "0.99.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",