@crowdin/app-project-module 0.34.2 → 0.35.1
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/handlers/file-processing/custom-file-format.js +8 -9
- package/out/handlers/file-processing/pre-post-process.js +13 -10
- package/out/handlers/integration/crowdin-webhook.js +1 -1
- package/out/handlers/integration/main.js +1 -0
- package/out/handlers/integration/sync-settings-save.js +2 -1
- package/out/index.js +5 -0
- package/out/models/index.d.ts +39 -11
- package/out/static/js/form.js +36 -15
- package/out/util/cron.js +3 -2
- package/out/util/defaults.d.ts +2 -1
- package/out/util/defaults.js +24 -2
- package/out/util/files.d.ts +5 -2
- package/out/util/files.js +13 -9
- package/out/util/webhooks.js +2 -2
- package/out/views/main.handlebars +39 -11
- package/package.json +21 -19
package/out/util/cron.js
CHANGED
|
@@ -112,7 +112,8 @@ function filesCron(config, integration, period) {
|
|
|
112
112
|
}
|
|
113
113
|
const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient, projectId);
|
|
114
114
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
115
|
-
if ((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[syncSettings.provider])
|
|
115
|
+
if (((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[syncSettings.provider]) &&
|
|
116
|
+
intConfig[`new-${syncSettings.provider}-files`]) {
|
|
116
117
|
newFiles = yield (0, file_snapshot_1.getAllNewFiles)({
|
|
117
118
|
config,
|
|
118
119
|
integration,
|
|
@@ -160,7 +161,7 @@ function filesCron(config, integration, period) {
|
|
|
160
161
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
161
162
|
yield integration.updateCrowdin(projectId, crowdinClient, apiCredentials, intFiles, rootFolder, intConfig);
|
|
162
163
|
const newSyncSettingsFiels = allIntFiles.map((file) => (Object.assign(Object.assign({}, file), { schedule: true, sync: false })));
|
|
163
|
-
if (newFiles) {
|
|
164
|
+
if (Object.keys(newFiles).length) {
|
|
164
165
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(newSyncSettingsFiels), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
|
|
165
166
|
const currentFileSnapshot = yield (0, file_snapshot_1.getIntegrationSnapshot)(integration, apiCredentials, intConfig);
|
|
166
167
|
yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(currentFileSnapshot), syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
|
package/out/util/defaults.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Crowdin, { SourceFilesModel } from '@crowdin/crowdin-api-client';
|
|
2
|
-
import { ClientConfig, Config, IntegrationLogic } from '../models';
|
|
2
|
+
import { ClientConfig, Config, FileProcessLogic, IntegrationLogic } from '../models';
|
|
3
3
|
export declare function getRootFolder(config: Config, integration: IntegrationLogic, client: Crowdin, projectId: number): Promise<SourceFilesModel.Directory | undefined>;
|
|
4
4
|
export declare function getOauthRoute(integration: IntegrationLogic): string;
|
|
5
5
|
export declare function applyIntegrationModuleDefaults(config: Config, integration: IntegrationLogic): void;
|
|
6
|
+
export declare function applyFileProcessorsModuleDefaults(config: Config, fileModule: FileProcessLogic): void;
|
|
6
7
|
export declare function constructOauthUrl(config: Config, integration: IntegrationLogic): string;
|
|
7
8
|
export declare function convertClientConfig(clientConfig: ClientConfig): Config;
|
package/out/util/defaults.js
CHANGED
|
@@ -32,7 +32,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.convertClientConfig = exports.constructOauthUrl = exports.applyIntegrationModuleDefaults = exports.getOauthRoute = exports.getRootFolder = void 0;
|
|
35
|
+
exports.convertClientConfig = exports.constructOauthUrl = exports.applyFileProcessorsModuleDefaults = exports.applyIntegrationModuleDefaults = exports.getOauthRoute = exports.getRootFolder = void 0;
|
|
36
|
+
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
37
|
+
const s3_request_presigner_1 = require("@aws-sdk/s3-request-presigner");
|
|
36
38
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
37
39
|
const path_1 = require("path");
|
|
38
40
|
function getRootFolder(config, integration, client, projectId) {
|
|
@@ -273,6 +275,22 @@ function applyIntegrationModuleDefaults(config, integration) {
|
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
exports.applyIntegrationModuleDefaults = applyIntegrationModuleDefaults;
|
|
278
|
+
function applyFileProcessorsModuleDefaults(config, fileModule) {
|
|
279
|
+
var _a, _b;
|
|
280
|
+
const AWS_TMP_BUCKET_NAME = (_a = config.awsConfig) === null || _a === void 0 ? void 0 : _a.tmpBucketName;
|
|
281
|
+
const AWS_REGION = (_b = config.awsConfig) === null || _b === void 0 ? void 0 : _b.region;
|
|
282
|
+
if (AWS_TMP_BUCKET_NAME && AWS_REGION && !fileModule.storeFile) {
|
|
283
|
+
const s3 = new client_s3_1.S3Client({ region: AWS_REGION });
|
|
284
|
+
fileModule.storeFile = (content) => __awaiter(this, void 0, void 0, function* () {
|
|
285
|
+
const fileName = `file-${config.identifier}-${Date.now()}`;
|
|
286
|
+
const command = new client_s3_1.PutObjectCommand({ Bucket: AWS_TMP_BUCKET_NAME, Key: fileName, Body: content });
|
|
287
|
+
yield s3.send(command);
|
|
288
|
+
const getObjectCommand = new client_s3_1.GetObjectCommand({ Bucket: AWS_TMP_BUCKET_NAME, Key: fileName });
|
|
289
|
+
return (0, s3_request_presigner_1.getSignedUrl)(s3, getObjectCommand, { expiresIn: 3600 });
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
exports.applyFileProcessorsModuleDefaults = applyFileProcessorsModuleDefaults;
|
|
276
294
|
function constructOauthUrl(config, integration) {
|
|
277
295
|
var _a, _b, _c;
|
|
278
296
|
const oauth = integration.oauthLogin;
|
|
@@ -293,11 +311,15 @@ function convertClientConfig(clientConfig) {
|
|
|
293
311
|
const clientId = clientConfig.clientId || process.env.CROWDIN_CLIENT_ID;
|
|
294
312
|
const clientSecret = clientConfig.clientSecret || process.env.CROWDIN_CLIENT_SECRET;
|
|
295
313
|
const port = clientConfig.port || process.env.PORT || 3000;
|
|
314
|
+
const { region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION, tmpBucketName = process.env.AWS_TMP_BUCKET_NAME, } = clientConfig.awsConfig || {};
|
|
296
315
|
const sentryDsn = clientConfig.sentryDsn || process.env.SENTRY_DSN;
|
|
297
316
|
if (!baseUrl || !clientId || !clientSecret) {
|
|
298
317
|
throw new Error('One of following parameters are not defined [baseUrl, clientId, clientSecret]');
|
|
299
318
|
}
|
|
300
319
|
return Object.assign(Object.assign({}, clientConfig), { sentryDsn, baseUrl: baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl, clientId,
|
|
301
|
-
clientSecret,
|
|
320
|
+
clientSecret, awsConfig: {
|
|
321
|
+
tmpBucketName,
|
|
322
|
+
region,
|
|
323
|
+
}, port: Number(port), dbFolder: clientConfig.dbFolder || (0, path_1.join)(process.cwd(), 'db'), imagePath: clientConfig.imagePath || (0, path_1.join)(process.cwd(), 'logo.png') });
|
|
302
324
|
}
|
|
303
325
|
exports.convertClientConfig = convertClientConfig;
|
package/out/util/files.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ProcessFileString } from '../models';
|
|
1
3
|
export declare const MAX_BODY_SIZE: number;
|
|
2
|
-
export declare function storeFile(fileContent:
|
|
3
|
-
export declare function getFileContent(url: string
|
|
4
|
+
export declare function storeFile(fileContent: Buffer, folder: string): Promise<string>;
|
|
5
|
+
export declare function getFileContent(url: string): Promise<Buffer>;
|
|
6
|
+
export declare function getFileStrings(url: string): Promise<ProcessFileString[]>;
|
package/out/util/files.js
CHANGED
|
@@ -12,10 +12,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.getFileContent = exports.storeFile = exports.MAX_BODY_SIZE = void 0;
|
|
15
|
+
exports.getFileStrings = exports.getFileContent = exports.storeFile = exports.MAX_BODY_SIZE = void 0;
|
|
16
|
+
const axios_1 = __importDefault(require("axios"));
|
|
16
17
|
const fs_1 = __importDefault(require("fs"));
|
|
17
18
|
const path_1 = __importDefault(require("path"));
|
|
18
|
-
const axios_1 = __importDefault(require("axios"));
|
|
19
19
|
exports.MAX_BODY_SIZE = 4.9 * 1024 * 1024; //4.9mb
|
|
20
20
|
function storeFile(fileContent, folder) {
|
|
21
21
|
const fileName = `file${Date.now()}`;
|
|
@@ -29,15 +29,19 @@ function storeFile(fileContent, folder) {
|
|
|
29
29
|
}));
|
|
30
30
|
}
|
|
31
31
|
exports.storeFile = storeFile;
|
|
32
|
-
function getFileContent(url
|
|
32
|
+
function getFileContent(url) {
|
|
33
33
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
const response = (yield axios_1.default.get(url)).data;
|
|
35
|
-
if (isString) {
|
|
36
|
-
// the response is presented in the ndjson format
|
|
37
|
-
const jsonRows = response.split(/\n|\n\r/).filter(Boolean);
|
|
38
|
-
return jsonRows.map((jsonStringRow) => JSON.parse(jsonStringRow));
|
|
39
|
-
}
|
|
34
|
+
const response = (yield axios_1.default.get(url, { responseType: 'arraybuffer' })).data;
|
|
40
35
|
return response;
|
|
41
36
|
});
|
|
42
37
|
}
|
|
43
38
|
exports.getFileContent = getFileContent;
|
|
39
|
+
function getFileStrings(url) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const response = (yield axios_1.default.get(url)).data;
|
|
42
|
+
// the response is presented in the ndjson format
|
|
43
|
+
const jsonRows = response.split(/\n|\n\r/).filter(Boolean);
|
|
44
|
+
return jsonRows.map((jsonStringRow) => JSON.parse(jsonStringRow));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
exports.getFileStrings = getFileStrings;
|
package/out/util/webhooks.js
CHANGED
|
@@ -245,7 +245,7 @@ function prepareWebhookData(config, integration, webhookUrlParam, provider) {
|
|
|
245
245
|
if (isWebhookSync) {
|
|
246
246
|
syncSettings = (yield (0, storage_1.getStorage)().getSyncSettings(clientId, crowdinId, 'schedule', provider));
|
|
247
247
|
rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient.client, projectId);
|
|
248
|
-
if ((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) {
|
|
248
|
+
if (((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) && appSettings[`new-${provider}-files`]) {
|
|
249
249
|
newFiles = yield (0, file_snapshot_1.getAllNewFiles)({
|
|
250
250
|
config,
|
|
251
251
|
integration,
|
|
@@ -289,7 +289,7 @@ function updateCrowdinFromWebhookRequest(args) {
|
|
|
289
289
|
node_type: file.nodeType || file.node_type || '1' }, (file.type ? { type: file.type } : {}))));
|
|
290
290
|
const intFiles = allIntFiles.filter((file) => file.nodeType === '1');
|
|
291
291
|
const newSyncSettingsFiels = [...syncFiles, ...newFiles].map((file) => (Object.assign(Object.assign({}, file), { schedule: true, sync: false })));
|
|
292
|
-
if (newFiles) {
|
|
292
|
+
if (Object.keys(newFiles).length) {
|
|
293
293
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(newSyncSettingsFiels), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
|
|
294
294
|
const currentFileSnapshot = yield (0, file_snapshot_1.getIntegrationSnapshot)(integration, preparedIntegrationCredentials, appSettings);
|
|
295
295
|
yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(currentFileSnapshot), syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
|
|
@@ -5,6 +5,26 @@
|
|
|
5
5
|
<body>
|
|
6
6
|
<div class="i_w">
|
|
7
7
|
<div class="top">
|
|
8
|
+
{{#if notice}}
|
|
9
|
+
<crowdin-alert
|
|
10
|
+
id="notice"
|
|
11
|
+
title="{{notice.title}}"
|
|
12
|
+
{{#unless notice.icon}}
|
|
13
|
+
no-icon="true"
|
|
14
|
+
{{/unless}}
|
|
15
|
+
{{#if notice.type}}
|
|
16
|
+
type={{notice.type}}
|
|
17
|
+
{{/if}}
|
|
18
|
+
style="display: none; margin-bottom: 12px;"
|
|
19
|
+
>
|
|
20
|
+
<div class="box-center">
|
|
21
|
+
<p class="m-0">{{{notice.content}}}</p>
|
|
22
|
+
</div>
|
|
23
|
+
{{#if notice.close}}
|
|
24
|
+
<crowdin-button onclick="closeAlert(this, 'notice')" class="dismiss-alert" icon>close</crowdin-button>
|
|
25
|
+
{{/if}}
|
|
26
|
+
</crowdin-alert>
|
|
27
|
+
{{/if}}
|
|
8
28
|
{{#if checkSubscription}}
|
|
9
29
|
<crowdin-alert id="subscription-info" no-icon="true" type="warning" style="display: none; margin-bottom: 12px;">
|
|
10
30
|
<div class="box-center">
|
|
@@ -763,21 +783,29 @@
|
|
|
763
783
|
getSubscriptionInfo();
|
|
764
784
|
{{/if}}
|
|
765
785
|
|
|
786
|
+
function checkAlert(alert, suffix) {
|
|
787
|
+
const name = suffix ?? '{{name}}';
|
|
788
|
+
const revised = localStorage.getItem(`revised_${name}`) === '1';
|
|
789
|
+
if (!revised) {
|
|
790
|
+
alert.style.display = 'block';
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
function closeAlert(el, suffix) {
|
|
794
|
+
const name = suffix ?? '{{name}}';
|
|
795
|
+
const alert = el.closest('crowdin-alert');
|
|
796
|
+
alert.style.display = 'none';
|
|
797
|
+
localStorage.setItem(`revised_${name}`, 1);
|
|
798
|
+
}
|
|
799
|
+
|
|
766
800
|
{{#if uploadTranslations}}
|
|
767
801
|
const translationInfo = document.getElementById('translation-info');
|
|
768
|
-
function checkAlert(alert) {
|
|
769
|
-
const revised = localStorage.getItem('revised_{{name}}') === '1';
|
|
770
|
-
if (!revised) {
|
|
771
|
-
alert.style.display = 'block';
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function closeAlert(el) {
|
|
775
|
-
const alert = el.closest('crowdin-alert');
|
|
776
|
-
alert.style.display = 'none';
|
|
777
|
-
localStorage.setItem('revised_{{name}}', 1);
|
|
778
|
-
}
|
|
779
802
|
checkAlert(translationInfo);
|
|
780
803
|
{{/if}}
|
|
804
|
+
|
|
805
|
+
{{#if notice}}
|
|
806
|
+
const notice = document.getElementById('notice');
|
|
807
|
+
checkAlert(notice, 'notice');
|
|
808
|
+
{{/if}}
|
|
781
809
|
</script>
|
|
782
810
|
|
|
783
811
|
</html>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crowdin/app-project-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.1",
|
|
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",
|
|
@@ -14,12 +14,14 @@
|
|
|
14
14
|
"test": "jest"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@aws-sdk/client-s3": "^3.423.0",
|
|
18
|
+
"@aws-sdk/s3-request-presigner": "^3.423.0",
|
|
17
19
|
"@crowdin/crowdin-apps-functions": "0.5.1",
|
|
18
20
|
"@crowdin/logs-formatter": "^2.0.3",
|
|
19
21
|
"@godaddy/terminus": "^4.12.1",
|
|
20
|
-
"@types/pg": "^8.10.
|
|
22
|
+
"@types/pg": "^8.10.3",
|
|
21
23
|
"amqplib": "^0.10.3",
|
|
22
|
-
"crypto-js": "^4.
|
|
24
|
+
"crypto-js": "^4.1.1",
|
|
23
25
|
"express": "4.18.2",
|
|
24
26
|
"express-handlebars": "^5.3.5",
|
|
25
27
|
"mysql2": "^2.3.3",
|
|
@@ -31,40 +33,40 @@
|
|
|
31
33
|
"uuid": "^8.3.2"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
|
-
"@babel/preset-react": "^7.22.
|
|
36
|
+
"@babel/preset-react": "^7.22.15",
|
|
35
37
|
"@emotion/react": "^11.11.1",
|
|
36
38
|
"@emotion/styled": "^11.11.0",
|
|
37
|
-
"@mui/icons-material": "^5.14.
|
|
38
|
-
"@mui/material": "^5.14.
|
|
39
|
-
"@rjsf/core": "^5.
|
|
40
|
-
"@rjsf/mui": "^5.
|
|
41
|
-
"@rjsf/utils": "^5.
|
|
42
|
-
"@rjsf/validator-ajv8": "^5.
|
|
39
|
+
"@mui/icons-material": "^5.14.12",
|
|
40
|
+
"@mui/material": "^5.14.12",
|
|
41
|
+
"@rjsf/core": "^5.13.0",
|
|
42
|
+
"@rjsf/mui": "^5.13.0",
|
|
43
|
+
"@rjsf/utils": "^5.13.0",
|
|
44
|
+
"@rjsf/validator-ajv8": "^5.13.0",
|
|
43
45
|
"@rollup/plugin-babel": "^6.0.3",
|
|
44
46
|
"@rollup/plugin-commonjs": "^24.0.1",
|
|
45
47
|
"@rollup/plugin-json": "^6.0.0",
|
|
46
|
-
"@rollup/plugin-node-resolve": "^15.
|
|
48
|
+
"@rollup/plugin-node-resolve": "^15.2.1",
|
|
47
49
|
"@rollup/plugin-replace": "^5.0.2",
|
|
48
50
|
"@rollup/plugin-terser": "^0.4.3",
|
|
49
|
-
"@types/amqplib": "^0.10.
|
|
50
|
-
"@types/crypto-js": "^4.1.
|
|
51
|
-
"@types/express": "4.17.
|
|
51
|
+
"@types/amqplib": "^0.10.2",
|
|
52
|
+
"@types/crypto-js": "^4.1.2",
|
|
53
|
+
"@types/express": "4.17.18",
|
|
52
54
|
"@types/express-handlebars": "^5.3.1",
|
|
53
|
-
"@types/jest": "^29.5.
|
|
54
|
-
"@types/node": "^
|
|
55
|
-
"@types/node-cron": "^3.0.
|
|
55
|
+
"@types/jest": "^29.5.5",
|
|
56
|
+
"@types/node": "^16.18.57",
|
|
57
|
+
"@types/node-cron": "^3.0.9",
|
|
56
58
|
"@types/swagger-jsdoc": "^6.0.1",
|
|
57
59
|
"@typescript-eslint/eslint-plugin": "^2.3.1",
|
|
58
60
|
"@typescript-eslint/parser": "^2.3.1",
|
|
59
61
|
"eslint": "^6.4.0",
|
|
60
62
|
"eslint-config-prettier": "^6.3.0",
|
|
61
63
|
"eslint-plugin-prettier": "^3.1.1",
|
|
62
|
-
"jest": "^29.
|
|
64
|
+
"jest": "^29.7.0",
|
|
63
65
|
"jest-junit": "^15.0.0",
|
|
64
66
|
"prettier": "^2.8.8",
|
|
65
67
|
"react": "^18.2.0",
|
|
66
68
|
"react-dom": "^18.2.0",
|
|
67
|
-
"rollup": "^3.
|
|
69
|
+
"rollup": "^3.29.4",
|
|
68
70
|
"ts-jest": "^29.1.1",
|
|
69
71
|
"typescript": "^4.9.5"
|
|
70
72
|
},
|