@crowdin/app-project-module 0.98.0 → 0.100.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 +1 -0
- package/out/modules/api/api.js +87 -2
- package/out/modules/file-processing/handlers/translations-alignment.d.ts +5 -0
- package/out/modules/file-processing/handlers/translations-alignment.js +72 -0
- package/out/modules/file-processing/index.d.ts +4 -0
- package/out/modules/file-processing/index.js +16 -1
- package/out/modules/file-processing/types.d.ts +36 -1
- package/out/modules/file-processing/types.js +1 -0
- package/out/modules/integration/handlers/crowdin-update.js +1 -1
- package/out/modules/integration/handlers/job-info-deprecated.d.ts +4 -0
- package/out/modules/integration/handlers/job-info-deprecated.js +138 -0
- package/out/modules/integration/handlers/job-info.d.ts +1 -2
- package/out/modules/integration/handlers/job-info.js +20 -75
- package/out/modules/integration/handlers/job-list.d.ts +3 -0
- package/out/modules/integration/handlers/job-list.js +46 -0
- package/out/modules/integration/index.js +15 -1
- package/out/modules/integration/util/types.d.ts +6 -0
- package/out/modules/manifest.js +11 -0
- package/out/storage/index.d.ts +2 -1
- package/out/storage/mysql.d.ts +2 -1
- package/out/storage/mysql.js +33 -0
- package/out/storage/postgre.d.ts +2 -1
- package/out/storage/postgre.js +32 -0
- package/out/storage/sqlite.d.ts +2 -1
- package/out/storage/sqlite.js +28 -0
- package/out/types.d.ts +2 -1
- package/package.json +1 -1
package/out/index.js
CHANGED
|
@@ -210,6 +210,7 @@ function addCrowdinEndpoints(app, clientConfig) {
|
|
|
210
210
|
fileProcessingApps.registerFilePostImport({ config, app });
|
|
211
211
|
fileProcessingApps.registerFilePreExport({ config, app });
|
|
212
212
|
fileProcessingApps.registerFilePostExport({ config, app });
|
|
213
|
+
fileProcessingApps.registerFileTranslationsAlignmentExport({ config, app });
|
|
213
214
|
apiApp.register({ config, app });
|
|
214
215
|
aiProvider.register({ config, app });
|
|
215
216
|
aiPromptProvider.register({ config, app });
|
package/out/modules/api/api.js
CHANGED
|
@@ -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
|
|
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,
|
|
425
|
+
}), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, job_info_deprecated_1.default)(config));
|
|
341
426
|
/**
|
|
342
427
|
* @openapi
|
|
343
428
|
* /jobs:
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { Config, CrowdinClientRequest } from '../../../types';
|
|
4
|
+
import { TranslationsAlignmentLogic } from '../types';
|
|
5
|
+
export default function handle(baseConfig: Config, config: TranslationsAlignmentLogic, folderName: string): (req: 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,72 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const util_1 = require("../../../util");
|
|
18
|
+
const files_1 = require("../util/files");
|
|
19
|
+
function handle(baseConfig, config, folderName) {
|
|
20
|
+
const folderPath = config.filesFolder || baseConfig.dbFolder;
|
|
21
|
+
if (!fs_1.default.existsSync(path_1.default.join(folderPath, folderName))) {
|
|
22
|
+
fs_1.default.mkdirSync(path_1.default.join(folderPath, folderName), { recursive: true });
|
|
23
|
+
}
|
|
24
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
var _a;
|
|
26
|
+
const response = {};
|
|
27
|
+
const baseFilesUrl = `${baseConfig.baseUrl}/file/download/${folderName}`;
|
|
28
|
+
const body = req.body;
|
|
29
|
+
// Skip assets (e.g., images, videos, or other media files) as they typically don't need to be processed
|
|
30
|
+
if (((_a = body === null || body === void 0 ? void 0 : body.file) === null || _a === void 0 ? void 0 : _a.type) === 'assets' && !('processAssets' in config && config.processAssets)) {
|
|
31
|
+
res.sendStatus(415);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const fileSourceStringsContent = body.sourceStringsUrl
|
|
35
|
+
? (yield (0, files_1.getFileStrings)(body.sourceStringsUrl))
|
|
36
|
+
: body.sourceStrings;
|
|
37
|
+
const fileTranslationsContent = body.translationStringsUrl
|
|
38
|
+
? (yield (0, files_1.getFileStrings)(body.translationStringsUrl))
|
|
39
|
+
: body.translationStrings;
|
|
40
|
+
const fileProcessResult = yield config.fileProcess(body, {
|
|
41
|
+
sourceStrings: fileSourceStringsContent,
|
|
42
|
+
translations: fileTranslationsContent,
|
|
43
|
+
}, req.crowdinApiClient, req.crowdinContext, req.crowdinContext.jwtPayload.context.project_id);
|
|
44
|
+
const { strings, error: processingErrorMessage } = fileProcessResult;
|
|
45
|
+
if (!strings) {
|
|
46
|
+
response.translations = [];
|
|
47
|
+
res.send({
|
|
48
|
+
data: response,
|
|
49
|
+
error: processingErrorMessage ? { message: processingErrorMessage } : undefined,
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const stringsNDJson = strings.map((s) => JSON.stringify(s)).join('\n\r');
|
|
54
|
+
const bufferData = Buffer.from(stringsNDJson, 'utf-8');
|
|
55
|
+
if (Buffer.byteLength(bufferData) < files_1.MAX_BODY_SIZE) {
|
|
56
|
+
response.translations = strings;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
let url;
|
|
60
|
+
if (config.storeFile) {
|
|
61
|
+
url = yield config.storeFile(bufferData);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
const storedFile = yield (0, files_1.storeFile)(bufferData, path_1.default.join(folderPath, folderName));
|
|
65
|
+
url = `${baseFilesUrl}?file=${storedFile}`;
|
|
66
|
+
}
|
|
67
|
+
response.translationsUrl = url;
|
|
68
|
+
}
|
|
69
|
+
res.send({ data: response, error: processingErrorMessage ? { message: processingErrorMessage } : undefined });
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
exports.default = handle;
|
|
@@ -3,11 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.registerFilePostExport = exports.registerFilePreExport = exports.registerFilePostImport = exports.registerFilePreImport = exports.registerCustomFileFormat = void 0;
|
|
6
|
+
exports.registerFileTranslationsAlignmentExport = exports.registerFilePostExport = exports.registerFilePreExport = exports.registerFilePostImport = exports.registerFilePreImport = exports.registerCustomFileFormat = void 0;
|
|
7
7
|
const crowdin_client_1 = __importDefault(require("../../middlewares/crowdin-client"));
|
|
8
8
|
const custom_file_format_1 = __importDefault(require("./handlers/custom-file-format"));
|
|
9
9
|
const file_download_1 = __importDefault(require("./handlers/file-download"));
|
|
10
10
|
const pre_post_process_1 = __importDefault(require("./handlers/pre-post-process"));
|
|
11
|
+
const translations_alignment_1 = __importDefault(require("./handlers/translations-alignment"));
|
|
11
12
|
const types_1 = require("./types");
|
|
12
13
|
const defaults_1 = require("./util/defaults");
|
|
13
14
|
function registerCustomFileFormat({ config, app }) {
|
|
@@ -87,3 +88,17 @@ function registerFilePostExport({ config, app }) {
|
|
|
87
88
|
app.get(`/file/download/${types_1.ProcessFileJobType.POST_EXPORT}`, (0, file_download_1.default)(config, config.filePostExport, types_1.ProcessFileJobType.POST_EXPORT));
|
|
88
89
|
}
|
|
89
90
|
exports.registerFilePostExport = registerFilePostExport;
|
|
91
|
+
function registerFileTranslationsAlignmentExport({ config, app }) {
|
|
92
|
+
if (!config.fileTranslationsAlignmentExport) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
(0, defaults_1.applyFileProcessorsModuleDefaults)(config, config.fileTranslationsAlignmentExport);
|
|
96
|
+
app.post('/translations-alignment', (0, crowdin_client_1.default)({
|
|
97
|
+
config,
|
|
98
|
+
optional: false,
|
|
99
|
+
checkSubscriptionExpiration: true,
|
|
100
|
+
moduleKey: config.fileTranslationsAlignmentExport.key,
|
|
101
|
+
}), (0, translations_alignment_1.default)(config, config.fileTranslationsAlignmentExport, types_1.ProcessFileJobType.TRANSLATIONS_ALIGNMENT));
|
|
102
|
+
app.get(`/file/download/${types_1.ProcessFileJobType.POST_EXPORT}`, (0, file_download_1.default)(config, config.fileTranslationsAlignmentExport, types_1.ProcessFileJobType.TRANSLATIONS_ALIGNMENT));
|
|
103
|
+
}
|
|
104
|
+
exports.registerFileTranslationsAlignmentExport = registerFileTranslationsAlignmentExport;
|
|
@@ -60,9 +60,17 @@ export interface CustomFileFormatLogic extends FileProcessLogic {
|
|
|
60
60
|
}
|
|
61
61
|
export type FileImportExportLogic = FilePreImportLogic | FilePostImportLogic | FilePreExportLogic | FilePostExportLogic;
|
|
62
62
|
export type FileImportExportContent = ProcessFileString[] | Buffer | undefined;
|
|
63
|
+
export type TranslationAlignmentContent = TranslationAlignmentString[] | Buffer | undefined;
|
|
64
|
+
export interface FileTranslationAlignmentContent {
|
|
65
|
+
sourceStrings: TranslationAlignmentContent;
|
|
66
|
+
translations: TranslationAlignmentContent;
|
|
67
|
+
}
|
|
63
68
|
export interface BaseFileProcessLogic<T> {
|
|
64
69
|
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<T>;
|
|
65
70
|
}
|
|
71
|
+
export interface TranslationAlignmentProcessLogin<T> {
|
|
72
|
+
fileProcess: (req: ProcessTranslationAlignmentRequest, content: FileTranslationAlignmentContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<T>;
|
|
73
|
+
}
|
|
66
74
|
export interface FilePreImportLogic extends FileProcessLogic, BaseFileProcessLogic<ContentFileResponse> {
|
|
67
75
|
/**
|
|
68
76
|
* Set to `true` to enable asset processing in the application.
|
|
@@ -79,6 +87,19 @@ export interface FilePostExportLogic extends FileProcessLogic, BaseFileProcessLo
|
|
|
79
87
|
*/
|
|
80
88
|
processAssets?: boolean;
|
|
81
89
|
}
|
|
90
|
+
export interface TranslationsAlignmentLogic extends FileProcessLogic, TranslationAlignmentProcessLogin<TranslationAlignmentResponse> {
|
|
91
|
+
}
|
|
92
|
+
export interface ProcessTranslationAlignmentRequest {
|
|
93
|
+
jobType: ProcessFileJobType;
|
|
94
|
+
file: ProcessFileRecord;
|
|
95
|
+
sourceLanguage: LanguagesModel.Language;
|
|
96
|
+
targetLanguages: LanguagesModel.Language[];
|
|
97
|
+
sourceStrings: TranslationAlignmentString[];
|
|
98
|
+
sourceStringsUrl: string;
|
|
99
|
+
translationStrings: TranslationAlignmentString[];
|
|
100
|
+
translationStringsUrl: string;
|
|
101
|
+
getRawContent?: (encoding: BufferEncoding) => Promise<string | Buffer>;
|
|
102
|
+
}
|
|
82
103
|
export interface ProcessFileRequest {
|
|
83
104
|
jobType: ProcessFileJobType;
|
|
84
105
|
file: ProcessFileRecord;
|
|
@@ -102,7 +123,8 @@ export declare enum ProcessFileJobType {
|
|
|
102
123
|
PRE_IMPORT = "pre-import-file",
|
|
103
124
|
POST_IMPORT = "post-import-file",
|
|
104
125
|
PRE_EXPORT = "pre-export-file",
|
|
105
|
-
POST_EXPORT = "post-export-file"
|
|
126
|
+
POST_EXPORT = "post-export-file",
|
|
127
|
+
TRANSLATIONS_ALIGNMENT = "translations-alignment-file"
|
|
106
128
|
}
|
|
107
129
|
export interface ParseFileResponse {
|
|
108
130
|
previewFile?: Buffer;
|
|
@@ -121,6 +143,14 @@ export interface StringsFileResponse extends ParseFileResponse {
|
|
|
121
143
|
export interface ContentFileResponse extends BuildFileResponse {
|
|
122
144
|
notModified?: boolean;
|
|
123
145
|
}
|
|
146
|
+
export interface TranslationAlignmentResponse {
|
|
147
|
+
strings?: TranslationAlignmentResult[];
|
|
148
|
+
error?: string;
|
|
149
|
+
}
|
|
150
|
+
export interface TranslationAlignmentResult {
|
|
151
|
+
sourceStringId: number;
|
|
152
|
+
text: string | SourceStringsModel.PluralText;
|
|
153
|
+
}
|
|
124
154
|
export interface ProcessFileString {
|
|
125
155
|
previewId?: number;
|
|
126
156
|
id: number;
|
|
@@ -135,6 +165,11 @@ export interface ProcessFileString {
|
|
|
135
165
|
translations?: StringTranslations;
|
|
136
166
|
uniqId?: string;
|
|
137
167
|
}
|
|
168
|
+
export interface TranslationAlignmentString {
|
|
169
|
+
id: number | null;
|
|
170
|
+
text: string | SourceStringsModel.PluralText;
|
|
171
|
+
context: string;
|
|
172
|
+
}
|
|
138
173
|
export interface StringTranslations {
|
|
139
174
|
[language: string]: {
|
|
140
175
|
text: string | SourceStringsModel.PluralText;
|
|
@@ -9,4 +9,5 @@ var ProcessFileJobType;
|
|
|
9
9
|
ProcessFileJobType["POST_IMPORT"] = "post-import-file";
|
|
10
10
|
ProcessFileJobType["PRE_EXPORT"] = "pre-export-file";
|
|
11
11
|
ProcessFileJobType["POST_EXPORT"] = "post-export-file";
|
|
12
|
+
ProcessFileJobType["TRANSLATIONS_ALIGNMENT"] = "translations-alignment-file";
|
|
12
13
|
})(ProcessFileJobType = exports.ProcessFileJobType || (exports.ProcessFileJobType = {}));
|
|
@@ -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
|
-
|
|
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(
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
83
|
-
res.send(
|
|
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,
|
|
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,
|
package/out/modules/manifest.js
CHANGED
|
@@ -86,6 +86,17 @@ function handle(config) {
|
|
|
86
86
|
},
|
|
87
87
|
];
|
|
88
88
|
}
|
|
89
|
+
if (config.fileTranslationsAlignmentExport) {
|
|
90
|
+
// prevent possible overrides of the other modules
|
|
91
|
+
config.fileTranslationsAlignmentExport = Object.assign(Object.assign({}, config.fileTranslationsAlignmentExport), { key: config.identifier + '-ftae' });
|
|
92
|
+
modules['file-translations-alignment'] = [
|
|
93
|
+
{
|
|
94
|
+
key: config.fileTranslationsAlignmentExport.key,
|
|
95
|
+
signaturePatterns: config.fileTranslationsAlignmentExport.signaturePatterns,
|
|
96
|
+
url: '/translations-alignment',
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
}
|
|
89
100
|
if (config.customMT) {
|
|
90
101
|
// prevent possible overrides of the other modules
|
|
91
102
|
config.customMT = Object.assign(Object.assign({}, config.customMT), { key: config.identifier + '-mt' });
|
package/out/storage/index.d.ts
CHANGED
|
@@ -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>;
|
package/out/storage/mysql.d.ts
CHANGED
|
@@ -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>;
|
package/out/storage/mysql.js
CHANGED
|
@@ -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;
|
package/out/storage/postgre.d.ts
CHANGED
|
@@ -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>;
|
package/out/storage/postgre.js
CHANGED
|
@@ -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;
|
package/out/storage/sqlite.d.ts
CHANGED
|
@@ -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>;
|
package/out/storage/sqlite.js
CHANGED
|
@@ -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/out/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { ContextContent } from './modules/context-menu/types';
|
|
|
5
5
|
import { CustomMTLogic } from './modules/custom-mt/types';
|
|
6
6
|
import { CustomSpellcheckerModule } from './modules/custom-spell-check/types';
|
|
7
7
|
import { EditorPanels } from './modules/editor-right-panel/types';
|
|
8
|
-
import { CustomFileFormatLogic, FilePostExportLogic, FilePostImportLogic, FilePreExportLogic, FilePreImportLogic } from './modules/file-processing/types';
|
|
8
|
+
import { CustomFileFormatLogic, FilePostExportLogic, FilePostImportLogic, FilePreExportLogic, FilePreImportLogic, TranslationsAlignmentLogic } from './modules/file-processing/types';
|
|
9
9
|
import { IntegrationLogic } from './modules/integration/types';
|
|
10
10
|
import { Storage } from './storage';
|
|
11
11
|
import { MySQLStorageConfig } from './storage/mysql';
|
|
@@ -203,6 +203,7 @@ export interface ClientConfig extends ImagePath {
|
|
|
203
203
|
filePostImport?: FilePostImportLogic;
|
|
204
204
|
filePreExport?: FilePreExportLogic;
|
|
205
205
|
filePostExport?: FilePostExportLogic;
|
|
206
|
+
fileTranslationsAlignmentExport?: TranslationsAlignmentLogic;
|
|
206
207
|
/**
|
|
207
208
|
* Disable formatting logs
|
|
208
209
|
*/
|
package/package.json
CHANGED