@crowdin/app-project-module 0.85.0 → 0.86.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/modules/integration/handlers/crowdin-update.js +13 -6
- package/out/modules/integration/handlers/integration-data.js +50 -6
- package/out/modules/integration/handlers/main.js +3 -3
- package/out/modules/integration/types.d.ts +35 -1
- package/out/modules/integration/util/cron.js +7 -0
- package/out/modules/integration/util/defaults.js +68 -4
- package/out/modules/integration/util/files.d.ts +7 -1
- package/out/modules/integration/util/files.js +79 -3
- package/out/modules/integration/util/types.d.ts +8 -0
- package/out/static/js/form.js +1 -1
- package/out/storage/index.d.ts +4 -1
- package/out/storage/mysql.d.ts +5 -1
- package/out/storage/mysql.js +29 -0
- package/out/storage/postgre.d.ts +5 -1
- package/out/storage/postgre.js +29 -0
- package/out/storage/sqlite.d.ts +5 -1
- package/out/storage/sqlite.js +22 -0
- package/out/views/main.handlebars +50 -40
- package/package.json +4 -2
|
@@ -19,6 +19,7 @@ const defaults_1 = require("../util/defaults");
|
|
|
19
19
|
const logger_1 = require("../../../util/logger");
|
|
20
20
|
const job_1 = require("../util/job");
|
|
21
21
|
const files_1 = require("../util/files");
|
|
22
|
+
const types_2 = require("../types");
|
|
22
23
|
function handle(config, integration) {
|
|
23
24
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
24
25
|
var _a, _b, _c;
|
|
@@ -33,6 +34,7 @@ function handle(config, integration) {
|
|
|
33
34
|
if (((_b = config.api) === null || _b === void 0 ? void 0 : _b.default) && req.body.files) {
|
|
34
35
|
req.body = req.body.files;
|
|
35
36
|
}
|
|
37
|
+
let payload = req.body;
|
|
36
38
|
const excludedTargetLanguages = yield (0, files_1.getExcludedTargetLanguages)({
|
|
37
39
|
client: req.crowdinApiClient,
|
|
38
40
|
projectId,
|
|
@@ -43,29 +45,34 @@ function handle(config, integration) {
|
|
|
43
45
|
crowdinId: req.crowdinContext.crowdinId,
|
|
44
46
|
type: types_1.JobType.UPDATE_TO_CROWDIN,
|
|
45
47
|
title: 'Sync files to Crowdin',
|
|
46
|
-
payload
|
|
48
|
+
payload,
|
|
47
49
|
res,
|
|
48
50
|
projectId,
|
|
49
51
|
client: req.crowdinApiClient,
|
|
50
52
|
jobType: types_1.JobClientType.MANUAL,
|
|
51
53
|
jobStoreType: integration.jobStoreType,
|
|
52
54
|
jobCallback: (job) => __awaiter(this, void 0, void 0, function* () {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
req.body = (0, lodash_uniqby_1.default)(req.body, 'id');
|
|
55
|
+
if (payload && (payload === null || payload === void 0 ? void 0 : payload.length)) {
|
|
56
|
+
payload = yield (0, files_1.expandFilesTree)(payload, req, integration, job);
|
|
57
|
+
payload = (0, lodash_uniqby_1.default)(payload, 'id');
|
|
57
58
|
}
|
|
58
59
|
const result = yield integration.updateCrowdin({
|
|
59
60
|
projectId,
|
|
60
61
|
client: req.crowdinApiClient,
|
|
61
62
|
credentials: req.integrationCredentials,
|
|
62
|
-
request:
|
|
63
|
+
request: payload,
|
|
63
64
|
rootFolder,
|
|
64
65
|
appSettings: req.integrationSettings,
|
|
65
66
|
uploadTranslations,
|
|
66
67
|
job,
|
|
67
68
|
excludedTargetLanguages: req.query.languages ? excludedTargetLanguages : undefined,
|
|
68
69
|
});
|
|
70
|
+
try {
|
|
71
|
+
yield (0, files_1.updateSyncedData)(req.crowdinContext.clientId, req.crowdinContext.crowdinId, payload, types_2.Provider.INTEGRATION);
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
(0, logger_1.logError)(e, req.crowdinContext);
|
|
75
|
+
}
|
|
69
76
|
let message;
|
|
70
77
|
if ((0, files_1.isExtendedResultType)(result)) {
|
|
71
78
|
message = result.message;
|
|
@@ -12,31 +12,75 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
const util_1 = require("../../../util");
|
|
13
13
|
const logger_1 = require("../../../util/logger");
|
|
14
14
|
const files_1 = require("../util/files");
|
|
15
|
+
const types_1 = require("../types");
|
|
16
|
+
const storage_1 = require("../../../storage");
|
|
15
17
|
function handle(integration) {
|
|
16
18
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
17
20
|
const { parent_id: parentId, search, page } = req.query;
|
|
18
21
|
req.logInfo('Received request to get integration data');
|
|
19
22
|
let message;
|
|
20
23
|
let stopPagination;
|
|
21
|
-
let files;
|
|
24
|
+
let files = [];
|
|
25
|
+
const { crowdinId, clientId } = req.crowdinContext;
|
|
22
26
|
try {
|
|
23
|
-
const
|
|
27
|
+
const appSettings = req.integrationSettings;
|
|
28
|
+
const result = yield integration.getIntegrationFiles(req.integrationCredentials, appSettings, parentId, search, page);
|
|
24
29
|
if ((0, files_1.isExtendedResultType)(result)) {
|
|
25
|
-
files = result.data;
|
|
30
|
+
files = result.data || [];
|
|
26
31
|
message = result.message;
|
|
27
32
|
stopPagination = result.stopPagination;
|
|
28
33
|
}
|
|
29
34
|
else {
|
|
30
|
-
files = result;
|
|
35
|
+
files = result || [];
|
|
31
36
|
}
|
|
32
37
|
files = (0, files_1.skipFilesByRegex)(files, integration.skipIntegrationNodes);
|
|
38
|
+
if (integration.filterByPathIntegrationFiles) {
|
|
39
|
+
const includePatterns = (_a = appSettings === null || appSettings === void 0 ? void 0 : appSettings.includeByFilePath) === null || _a === void 0 ? void 0 : _a.split('\n').filter(Boolean);
|
|
40
|
+
const excludePatterns = (_b = appSettings === null || appSettings === void 0 ? void 0 : appSettings.excludeByFilePath) === null || _b === void 0 ? void 0 : _b.split('\n').filter(Boolean);
|
|
41
|
+
files = (0, files_1.filterFilesByPath)(files, includePatterns, excludePatterns);
|
|
42
|
+
}
|
|
43
|
+
if (((_d = (_c = integration.filtering) === null || _c === void 0 ? void 0 : _c.integrationFileStatus) === null || _d === void 0 ? void 0 : _d.isNew) ||
|
|
44
|
+
((_f = (_e = integration.filtering) === null || _e === void 0 ? void 0 : _e.integrationFileStatus) === null || _f === void 0 ? void 0 : _f.isUpdated) ||
|
|
45
|
+
((_h = (_g = integration.filtering) === null || _g === void 0 ? void 0 : _g.integrationFileStatus) === null || _h === void 0 ? void 0 : _h.notSynced)) {
|
|
46
|
+
const syncedData = yield (0, storage_1.getStorage)().getSyncedData(clientId, crowdinId, types_1.Provider.INTEGRATION);
|
|
47
|
+
const syncedFiles = (syncedData === null || syncedData === void 0 ? void 0 : syncedData.files) ? JSON.parse(syncedData.files) : [];
|
|
48
|
+
const lastSyncTimestamp = (syncedData === null || syncedData === void 0 ? void 0 : syncedData.updatedAt) ? Number(syncedData.updatedAt) : null;
|
|
49
|
+
files = files.map((file) => {
|
|
50
|
+
var _a, _b, _c, _d, _e, _f;
|
|
51
|
+
if (!file.type) {
|
|
52
|
+
return file;
|
|
53
|
+
}
|
|
54
|
+
const notSynced = ((_b = (_a = integration.filtering) === null || _a === void 0 ? void 0 : _a.integrationFileStatus) === null || _b === void 0 ? void 0 : _b.notSynced) === true
|
|
55
|
+
? !syncedFiles.some((syncedItem) => syncedItem.id === file.id)
|
|
56
|
+
: false;
|
|
57
|
+
const isNew = ((_d = (_c = integration.filtering) === null || _c === void 0 ? void 0 : _c.integrationFileStatus) === null || _d === void 0 ? void 0 : _d.isNew) === true
|
|
58
|
+
? !syncedFiles.some((syncedItem) => syncedItem.id === file.id) &&
|
|
59
|
+
lastSyncTimestamp &&
|
|
60
|
+
file.createdAt &&
|
|
61
|
+
(typeof file.createdAt === 'string'
|
|
62
|
+
? new Date(file.createdAt).getTime()
|
|
63
|
+
: file.createdAt) > Number(lastSyncTimestamp)
|
|
64
|
+
: false;
|
|
65
|
+
const isUpdated = ((_f = (_e = integration.filtering) === null || _e === void 0 ? void 0 : _e.integrationFileStatus) === null || _f === void 0 ? void 0 : _f.isUpdated) === true
|
|
66
|
+
? lastSyncTimestamp &&
|
|
67
|
+
file.updatedAt &&
|
|
68
|
+
(typeof file.updatedAt === 'string'
|
|
69
|
+
? new Date(file.updatedAt).getTime()
|
|
70
|
+
: file.updatedAt) > Number(lastSyncTimestamp)
|
|
71
|
+
: false;
|
|
72
|
+
return Object.assign(Object.assign({}, file), { isNew,
|
|
73
|
+
notSynced,
|
|
74
|
+
isUpdated });
|
|
75
|
+
});
|
|
76
|
+
}
|
|
33
77
|
}
|
|
34
78
|
catch (e) {
|
|
35
79
|
yield (0, logger_1.handleUserError)({
|
|
36
80
|
action: 'Get External Service data',
|
|
37
81
|
error: e,
|
|
38
|
-
crowdinId
|
|
39
|
-
clientId
|
|
82
|
+
crowdinId,
|
|
83
|
+
clientId,
|
|
40
84
|
});
|
|
41
85
|
res.send({ data: [], message: (e === null || e === void 0 ? void 0 : e.message) || e });
|
|
42
86
|
throw e;
|
|
@@ -39,7 +39,7 @@ const defaults_1 = require("../util/defaults");
|
|
|
39
39
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
40
40
|
function handle(config, integration) {
|
|
41
41
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
42
|
-
var _a, _b, _c;
|
|
42
|
+
var _a, _b, _c, _d;
|
|
43
43
|
const logger = req.logInfo || logger_1.log;
|
|
44
44
|
const installed = !!req.crowdinApiClient;
|
|
45
45
|
const loggedIn = !!req.integrationCredentials;
|
|
@@ -82,7 +82,7 @@ function handle(config, integration) {
|
|
|
82
82
|
}
|
|
83
83
|
options.infoModal = integration.infoModal;
|
|
84
84
|
options.syncNewElements = integration.syncNewElements;
|
|
85
|
-
options.filtering = integration.filtering;
|
|
85
|
+
options.filtering = Object.assign(Object.assign({}, integration.filtering), { integrationFilterConfig: JSON.stringify(((_c = integration.filtering) === null || _c === void 0 ? void 0 : _c.integrationFilterConfig) || []) });
|
|
86
86
|
options.withCronSync = integration.withCronSync;
|
|
87
87
|
options.webhooks = integration.webhooks
|
|
88
88
|
? {
|
|
@@ -103,7 +103,7 @@ function handle(config, integration) {
|
|
|
103
103
|
: null;
|
|
104
104
|
options.notice = integration.notice;
|
|
105
105
|
options.asyncProgress = {
|
|
106
|
-
checkInterval: ((
|
|
106
|
+
checkInterval: ((_d = integration.asyncProgress) === null || _d === void 0 ? void 0 : _d.checkInterval) || 1000,
|
|
107
107
|
};
|
|
108
108
|
logger(`Routing user to ${view} view`);
|
|
109
109
|
return res.render(view, options);
|
|
@@ -107,8 +107,36 @@ export interface IntegrationLogic extends ModuleKey {
|
|
|
107
107
|
crowdin: boolean;
|
|
108
108
|
integration: boolean;
|
|
109
109
|
};
|
|
110
|
+
/**
|
|
111
|
+
* Enable file filtering
|
|
112
|
+
*/
|
|
110
113
|
filtering?: {
|
|
111
|
-
crowdinLanguages
|
|
114
|
+
crowdinLanguages?: boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Configuration for integration file filtering
|
|
117
|
+
*/
|
|
118
|
+
integrationFilterConfig?: any;
|
|
119
|
+
/**
|
|
120
|
+
* Enable file status filtering
|
|
121
|
+
*/
|
|
122
|
+
integrationFileStatus?: {
|
|
123
|
+
/**
|
|
124
|
+
* Enable file filtering by "isNew" status
|
|
125
|
+
*/
|
|
126
|
+
isNew?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Enable file filtering by "isUpdated" status
|
|
129
|
+
*/
|
|
130
|
+
isUpdated?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Enable file filtering by "failed" status
|
|
133
|
+
*/
|
|
134
|
+
failed?: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Enable file filtering by "notSynced" status
|
|
137
|
+
*/
|
|
138
|
+
notSynced?: boolean;
|
|
139
|
+
};
|
|
112
140
|
};
|
|
113
141
|
/**
|
|
114
142
|
* Enable integration folder open event
|
|
@@ -130,6 +158,10 @@ export interface IntegrationLogic extends ModuleKey {
|
|
|
130
158
|
* Enable the option to upload file for translation into selected languages.
|
|
131
159
|
*/
|
|
132
160
|
excludedTargetLanguages?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Enable the option to add 'Exclude paths' and 'Include paths' text fields to integration settings
|
|
163
|
+
*/
|
|
164
|
+
filterByPathIntegrationFiles?: boolean;
|
|
133
165
|
/**
|
|
134
166
|
* function to get crowdin file translation progress
|
|
135
167
|
*/
|
|
@@ -305,6 +337,7 @@ export interface File {
|
|
|
305
337
|
labels?: LabelTreeElement[];
|
|
306
338
|
failed?: boolean;
|
|
307
339
|
excludedTargetLanguages?: string[];
|
|
340
|
+
path?: string;
|
|
308
341
|
}
|
|
309
342
|
export interface Folder {
|
|
310
343
|
id: string;
|
|
@@ -313,6 +346,7 @@ export interface Folder {
|
|
|
313
346
|
nodeType?: IntegrationTreeElementType;
|
|
314
347
|
customContent?: string;
|
|
315
348
|
labels?: LabelTreeElement[];
|
|
349
|
+
path?: string;
|
|
316
350
|
}
|
|
317
351
|
export type TreeItem = File | Folder;
|
|
318
352
|
/**
|
|
@@ -43,6 +43,7 @@ const types_1 = require("../types");
|
|
|
43
43
|
const job_1 = require("./job");
|
|
44
44
|
const types_2 = require("./types");
|
|
45
45
|
const subscription_1 = require("../../../util/subscription");
|
|
46
|
+
const files_1 = require("./files");
|
|
46
47
|
function runJob({ config, integration, job, }) {
|
|
47
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
48
49
|
(0, logger_1.log)(`Starting cron job with expression [${job.expression}]`);
|
|
@@ -106,6 +107,12 @@ function runUpdateProviderJob({ integrationId, crowdinId, type, title, payload,
|
|
|
106
107
|
};
|
|
107
108
|
if (type === types_2.JobType.UPDATE_TO_CROWDIN) {
|
|
108
109
|
yield integration.updateCrowdin(updateParams);
|
|
110
|
+
try {
|
|
111
|
+
yield (0, files_1.updateSyncedData)(integrationId, crowdinId, payload, types_1.Provider.INTEGRATION);
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
(0, logger_1.logError)(e, context);
|
|
115
|
+
}
|
|
109
116
|
}
|
|
110
117
|
else if (type === types_2.JobType.UPDATE_TO_INTEGRATION) {
|
|
111
118
|
yield integration.updateIntegration(updateParams);
|
|
@@ -57,7 +57,7 @@ function getOauthRoute(integration) {
|
|
|
57
57
|
}
|
|
58
58
|
exports.getOauthRoute = getOauthRoute;
|
|
59
59
|
function applyIntegrationModuleDefaults(config, integration) {
|
|
60
|
-
var _a, _b;
|
|
60
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
61
61
|
if (!integration.getCrowdinFiles) {
|
|
62
62
|
integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
|
|
63
63
|
const allBranches = (yield client.sourceFilesApi.withFetchAll().listProjectBranches(projectId)).data.map((d) => d.data);
|
|
@@ -139,9 +139,13 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
139
139
|
],
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
|
+
if ((integration.filterByPathIntegrationFiles === undefined || integration.filterByPathIntegrationFiles) &&
|
|
143
|
+
!integration.integrationOneLevelFetching) {
|
|
144
|
+
integration.filterByPathIntegrationFiles = true;
|
|
145
|
+
}
|
|
142
146
|
const getUserSettings = integration.getConfiguration;
|
|
143
147
|
integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
144
|
-
var
|
|
148
|
+
var _m, _o;
|
|
145
149
|
let fields = [];
|
|
146
150
|
const project = (yield crowdinClient.projectsGroupsApi.getProject(projectId));
|
|
147
151
|
if (getUserSettings) {
|
|
@@ -190,7 +194,7 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
190
194
|
},
|
|
191
195
|
],
|
|
192
196
|
});
|
|
193
|
-
if ((
|
|
197
|
+
if ((_m = integration.syncNewElements) === null || _m === void 0 ? void 0 : _m.crowdin) {
|
|
194
198
|
defaultSettings.push({
|
|
195
199
|
key: 'new-crowdin-files',
|
|
196
200
|
label: 'Automatically sync new translations from Crowdin',
|
|
@@ -198,7 +202,7 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
198
202
|
dependencySettings: JSON.stringify([{ '#schedule-settings': { type: '!equal', value: ['0'] } }]),
|
|
199
203
|
});
|
|
200
204
|
}
|
|
201
|
-
if ((
|
|
205
|
+
if ((_o = integration.syncNewElements) === null || _o === void 0 ? void 0 : _o.integration) {
|
|
202
206
|
defaultSettings.push({
|
|
203
207
|
key: 'new-integration-files',
|
|
204
208
|
label: `Automatically sync new content from ${config.name}`,
|
|
@@ -245,6 +249,21 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
245
249
|
],
|
|
246
250
|
});
|
|
247
251
|
}
|
|
252
|
+
if (integration.filterByPathIntegrationFiles) {
|
|
253
|
+
defaultSettings.push({
|
|
254
|
+
label: 'File Filters',
|
|
255
|
+
}, {
|
|
256
|
+
key: 'includeByFilePath',
|
|
257
|
+
label: 'Source files path',
|
|
258
|
+
type: 'textarea',
|
|
259
|
+
helpText: 'Enter the file path patterns to include files for synchronization. Use wildcard selectors like `*` and `**` to match multiple files. Example: `/pages/**',
|
|
260
|
+
}, {
|
|
261
|
+
key: 'excludeByFilePath',
|
|
262
|
+
label: 'Ignore files or folders',
|
|
263
|
+
type: 'textarea',
|
|
264
|
+
helpText: 'Enter the path patterns for files or folders to exclude. Use wildcard selectors like `*` and `**` to match multiple files. Example: `/drafts/**`',
|
|
265
|
+
});
|
|
266
|
+
}
|
|
248
267
|
return [...defaultSettings, ...fields];
|
|
249
268
|
});
|
|
250
269
|
if (!integration.checkConnection) {
|
|
@@ -258,6 +277,51 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
258
277
|
if (!((_b = integration.filtering) === null || _b === void 0 ? void 0 : _b.hasOwnProperty('crowdinLanguages'))) {
|
|
259
278
|
integration.filtering = Object.assign(Object.assign({}, (integration.filtering || {})), { crowdinLanguages: true });
|
|
260
279
|
}
|
|
280
|
+
integration.filtering.integrationFileStatus = Object.assign({ notSynced: true }, integration.filtering.integrationFileStatus);
|
|
281
|
+
if (!((_c = integration.filtering) === null || _c === void 0 ? void 0 : _c.hasOwnProperty('integrationFilterConfig'))) {
|
|
282
|
+
const filterItems = [
|
|
283
|
+
{
|
|
284
|
+
value: 'all',
|
|
285
|
+
label: 'All',
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
if ((_e = (_d = integration.filtering) === null || _d === void 0 ? void 0 : _d.integrationFileStatus) === null || _e === void 0 ? void 0 : _e.isNew) {
|
|
289
|
+
filterItems.push({
|
|
290
|
+
value: 'isNew',
|
|
291
|
+
label: 'New',
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
if ((_g = (_f = integration.filtering) === null || _f === void 0 ? void 0 : _f.integrationFileStatus) === null || _g === void 0 ? void 0 : _g.isUpdated) {
|
|
295
|
+
filterItems.push({
|
|
296
|
+
value: 'isUpdated',
|
|
297
|
+
label: 'Modified',
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
if ((_j = (_h = integration.filtering) === null || _h === void 0 ? void 0 : _h.integrationFileStatus) === null || _j === void 0 ? void 0 : _j.failed) {
|
|
301
|
+
filterItems.push({
|
|
302
|
+
value: 'failed',
|
|
303
|
+
label: 'Sync Error',
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
if ((_l = (_k = integration.filtering) === null || _k === void 0 ? void 0 : _k.integrationFileStatus) === null || _l === void 0 ? void 0 : _l.notSynced) {
|
|
307
|
+
filterItems.push({
|
|
308
|
+
value: 'notSynced',
|
|
309
|
+
label: 'Never Synced',
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
integration.filtering = Object.assign(Object.assign({}, (integration.filtering || {})), { integrationFilterConfig: filterItems.length > 1
|
|
313
|
+
? [
|
|
314
|
+
{
|
|
315
|
+
key: 'file',
|
|
316
|
+
type: 'list_single',
|
|
317
|
+
label: 'File',
|
|
318
|
+
items: filterItems,
|
|
319
|
+
defaultValue: 'all',
|
|
320
|
+
defaultLabel: 'All',
|
|
321
|
+
},
|
|
322
|
+
]
|
|
323
|
+
: [] });
|
|
324
|
+
}
|
|
261
325
|
if (!integration.userErrorLifetimeDays) {
|
|
262
326
|
integration.userErrorLifetimeDays = 30;
|
|
263
327
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExtendedResult, IntegrationFile, IntegrationLogic, IntegrationRequest, SkipIntegrationNodes, TreeItem, UpdateIntegrationRequest } from '../types';
|
|
1
|
+
import { ExtendedResult, IntegrationFile, IntegrationLogic, IntegrationRequest, SkipIntegrationNodes, TreeItem, UpdateIntegrationRequest, Provider } from '../types';
|
|
2
2
|
import { JobClient } from './types';
|
|
3
3
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
4
4
|
import { SourceFilesModel } from '@crowdin/crowdin-api-client';
|
|
@@ -17,3 +17,9 @@ export declare function getExcludedTargetLanguages({ client, projectId, language
|
|
|
17
17
|
languages: string[];
|
|
18
18
|
}): Promise<string[]>;
|
|
19
19
|
export declare function filterLanguages(request: UpdateIntegrationRequest, files: SourceFilesModel.File[]): UpdateIntegrationRequest;
|
|
20
|
+
export declare function buildPath(file: TreeItem, files: TreeItem[]): string;
|
|
21
|
+
export declare function getParentPaths(filePath: string): Set<string>;
|
|
22
|
+
export declare function getParentFiles(allFiles: TreeItem[], fileCollection: TreeItem[]): TreeItem[];
|
|
23
|
+
export declare function filterFilesByPatterns(files: TreeItem[], patterns: string[]): TreeItem[];
|
|
24
|
+
export declare function filterFilesByPath(files: TreeItem[], includePatterns?: string[], excludePatterns?: string[]): TreeItem[];
|
|
25
|
+
export declare function updateSyncedData(clientId: string, crowdinId: string, payload: any[], provider?: Provider): Promise<void>;
|
|
@@ -8,11 +8,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.filterLanguages = exports.getExcludedTargetLanguages = exports.markUnsyncedFiles = exports.isExtendedResultType = exports.expandFilesTree = exports.skipFilesByRegex = void 0;
|
|
13
|
-
const types_1 = require("
|
|
15
|
+
exports.updateSyncedData = exports.filterFilesByPath = exports.filterFilesByPatterns = exports.getParentFiles = exports.getParentPaths = exports.buildPath = exports.filterLanguages = exports.getExcludedTargetLanguages = exports.markUnsyncedFiles = exports.isExtendedResultType = exports.expandFilesTree = exports.skipFilesByRegex = void 0;
|
|
16
|
+
const types_1 = require("../types");
|
|
17
|
+
const types_2 = require("./types");
|
|
14
18
|
const storage_1 = require("../../../storage");
|
|
15
19
|
const util_1 = require("../../../util");
|
|
20
|
+
const minimatch_1 = require("minimatch");
|
|
21
|
+
const lodash_uniqby_1 = __importDefault(require("lodash.uniqby"));
|
|
16
22
|
function skipFilesByRegex(files, skipIntegrationNodes) {
|
|
17
23
|
if (!Array.isArray(files)) {
|
|
18
24
|
return [];
|
|
@@ -34,7 +40,7 @@ exports.skipFilesByRegex = skipFilesByRegex;
|
|
|
34
40
|
function expandFilesTree(nodes, req, integration, job) {
|
|
35
41
|
var _a;
|
|
36
42
|
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
-
if (job &&
|
|
43
|
+
if (job && types_2.JobStatus.CANCELED === ((_a = (yield job.get())) === null || _a === void 0 ? void 0 : _a.status)) {
|
|
38
44
|
throw new Error('Job canceled');
|
|
39
45
|
}
|
|
40
46
|
const files = nodes.filter((file) => file.nodeType === undefined || file.nodeType === '1');
|
|
@@ -121,3 +127,73 @@ function filterLanguages(request, files) {
|
|
|
121
127
|
return result;
|
|
122
128
|
}
|
|
123
129
|
exports.filterLanguages = filterLanguages;
|
|
130
|
+
function buildPath(file, files) {
|
|
131
|
+
const filePath = `/${file.name}`;
|
|
132
|
+
if (!file.parentId) {
|
|
133
|
+
return filePath;
|
|
134
|
+
}
|
|
135
|
+
const parent = files.find((f) => f.id === file.parentId);
|
|
136
|
+
if (!parent) {
|
|
137
|
+
return filePath;
|
|
138
|
+
}
|
|
139
|
+
const parentPath = buildPath(parent, files);
|
|
140
|
+
return `${parentPath}${filePath}`;
|
|
141
|
+
}
|
|
142
|
+
exports.buildPath = buildPath;
|
|
143
|
+
function getParentPaths(filePath) {
|
|
144
|
+
const parentPaths = new Set();
|
|
145
|
+
const parts = filePath.split('/');
|
|
146
|
+
let currentPath = '';
|
|
147
|
+
for (let i = 1; i < parts.length - 1; i++) {
|
|
148
|
+
currentPath += '/' + parts[i];
|
|
149
|
+
parentPaths.add(currentPath);
|
|
150
|
+
}
|
|
151
|
+
return parentPaths;
|
|
152
|
+
}
|
|
153
|
+
exports.getParentPaths = getParentPaths;
|
|
154
|
+
function getParentFiles(allFiles, fileCollection) {
|
|
155
|
+
const parentPaths = new Set();
|
|
156
|
+
fileCollection
|
|
157
|
+
.filter((file) => !!file.path)
|
|
158
|
+
.forEach((file) => {
|
|
159
|
+
const paths = getParentPaths(file.path);
|
|
160
|
+
paths.forEach((path) => parentPaths.add(path));
|
|
161
|
+
});
|
|
162
|
+
return allFiles.filter((file) => file.path && parentPaths.has(file.path));
|
|
163
|
+
}
|
|
164
|
+
exports.getParentFiles = getParentFiles;
|
|
165
|
+
function filterFilesByPatterns(files, patterns) {
|
|
166
|
+
return files.filter((file) => patterns.some((pattern) => (0, minimatch_1.minimatch)(file.path || '', pattern.trim())));
|
|
167
|
+
}
|
|
168
|
+
exports.filterFilesByPatterns = filterFilesByPatterns;
|
|
169
|
+
function filterFilesByPath(files, includePatterns, excludePatterns) {
|
|
170
|
+
const filesWithPaths = files.map((file) => (Object.assign(Object.assign({}, file), { path: buildPath(file, files) })));
|
|
171
|
+
let filteredFiles = [...filesWithPaths];
|
|
172
|
+
if (includePatterns === null || includePatterns === void 0 ? void 0 : includePatterns.length) {
|
|
173
|
+
const includedFiles = filterFilesByPatterns(filteredFiles, includePatterns);
|
|
174
|
+
const parentFiles = getParentFiles(filesWithPaths, includedFiles);
|
|
175
|
+
filteredFiles = [...new Set([...includedFiles, ...parentFiles])];
|
|
176
|
+
}
|
|
177
|
+
if (excludePatterns === null || excludePatterns === void 0 ? void 0 : excludePatterns.length) {
|
|
178
|
+
const excludedFiles = filterFilesByPatterns(filteredFiles, excludePatterns);
|
|
179
|
+
const remainingFiles = filteredFiles.filter((file) => !excludedFiles.includes(file));
|
|
180
|
+
const parentFiles = getParentFiles(filesWithPaths, remainingFiles);
|
|
181
|
+
filteredFiles = [...new Set([...remainingFiles, ...parentFiles])];
|
|
182
|
+
}
|
|
183
|
+
return filteredFiles;
|
|
184
|
+
}
|
|
185
|
+
exports.filterFilesByPath = filterFilesByPath;
|
|
186
|
+
function updateSyncedData(clientId, crowdinId, payload, provider = types_1.Provider.INTEGRATION) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const existingSyncedData = yield (0, storage_1.getStorage)().getSyncedData(clientId, crowdinId, provider);
|
|
189
|
+
if (existingSyncedData) {
|
|
190
|
+
const existingFiles = JSON.parse(existingSyncedData.files);
|
|
191
|
+
const mergedFiles = (0, lodash_uniqby_1.default)([...existingFiles, ...payload], 'id');
|
|
192
|
+
yield (0, storage_1.getStorage)().updateSyncedData(JSON.stringify(mergedFiles), clientId, crowdinId, provider);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
yield (0, storage_1.getStorage)().saveSyncedData(JSON.stringify(payload), clientId, crowdinId, provider);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
exports.updateSyncedData = updateSyncedData;
|
|
@@ -113,3 +113,11 @@ export interface UnsyncedFiles {
|
|
|
113
113
|
files: string;
|
|
114
114
|
}
|
|
115
115
|
export type GetUnsyncedFiles = Pick<UnsyncedFiles, 'integrationId' | 'crowdinId'>;
|
|
116
|
+
export interface IntegrationSyncedData {
|
|
117
|
+
id: number;
|
|
118
|
+
integrationId: string;
|
|
119
|
+
crowdinId: string;
|
|
120
|
+
type: string;
|
|
121
|
+
updatedAt: string;
|
|
122
|
+
files?: any;
|
|
123
|
+
}
|