@crowdin/app-project-module 0.35.0 → 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/sync-settings-save.js +2 -1
- package/out/models/index.d.ts +11 -11
- package/out/util/cron.js +3 -2
- package/out/util/files.d.ts +5 -2
- package/out/util/files.js +13 -9
- package/out/util/webhooks.js +2 -2
- package/package.json +1 -1
|
@@ -37,8 +37,7 @@ function handle(baseUrl, folder, config) {
|
|
|
37
37
|
file = Buffer.from(body.file.content, 'base64');
|
|
38
38
|
}
|
|
39
39
|
else if (body.file.contentUrl) {
|
|
40
|
-
|
|
41
|
-
file = Buffer.from(rawContent).toString('base64');
|
|
40
|
+
file = yield (0, files_1.getFileContent)(body.file.contentUrl);
|
|
42
41
|
}
|
|
43
42
|
let response = {};
|
|
44
43
|
let error;
|
|
@@ -71,7 +70,7 @@ function handleBuildFile(baseUrl, dataFolder, config, req, client, context, proj
|
|
|
71
70
|
strings = req.strings;
|
|
72
71
|
}
|
|
73
72
|
else {
|
|
74
|
-
strings = yield (0, files_1.
|
|
73
|
+
strings = yield (0, files_1.getFileStrings)(req.stringsUrl);
|
|
75
74
|
}
|
|
76
75
|
let res;
|
|
77
76
|
if ((req.file.id || !file) && config.exportStrings) {
|
|
@@ -113,9 +112,8 @@ function handleParseFile(baseUrl, dataFolder, config, req, client, context, proj
|
|
|
113
112
|
maxSize = maxSize / 2;
|
|
114
113
|
}
|
|
115
114
|
if (res.previewFile) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
response.preview = previewFileEncoded;
|
|
115
|
+
if (Buffer.byteLength(res.previewFile) < maxSize) {
|
|
116
|
+
response.preview = res.previewFile.toString('base64');
|
|
119
117
|
}
|
|
120
118
|
else {
|
|
121
119
|
let url;
|
|
@@ -141,16 +139,17 @@ function handleParseFile(baseUrl, dataFolder, config, req, client, context, proj
|
|
|
141
139
|
});
|
|
142
140
|
}
|
|
143
141
|
const stringsNDJson = strings.map((s) => JSON.stringify(s)).join('\n\r');
|
|
144
|
-
|
|
142
|
+
const bufferData = Buffer.from(stringsNDJson, 'utf8');
|
|
143
|
+
if (Buffer.byteLength(bufferData) < maxSize) {
|
|
145
144
|
response.strings = strings;
|
|
146
145
|
}
|
|
147
146
|
else {
|
|
148
147
|
let url;
|
|
149
148
|
if (config.storeFile) {
|
|
150
|
-
url = yield config.storeFile(
|
|
149
|
+
url = yield config.storeFile(bufferData);
|
|
151
150
|
}
|
|
152
151
|
else {
|
|
153
|
-
const storedFile = yield (0, files_1.storeFile)(
|
|
152
|
+
const storedFile = yield (0, files_1.storeFile)(bufferData, path_1.default.join(dataFolder, 'custom-file-format'));
|
|
154
153
|
url = `${baseUrl}?file=${storedFile}`;
|
|
155
154
|
}
|
|
156
155
|
response.stringsUrl = url;
|
|
@@ -30,14 +30,14 @@ function handle(baseConfig, config, folderName) {
|
|
|
30
30
|
let fileContent;
|
|
31
31
|
let rawContent;
|
|
32
32
|
if (body.stringsUrl) {
|
|
33
|
-
fileContent = yield (0, files_1.
|
|
33
|
+
fileContent = yield (0, files_1.getFileStrings)(body.stringsUrl);
|
|
34
34
|
}
|
|
35
35
|
else if (body.strings) {
|
|
36
36
|
fileContent = body.strings;
|
|
37
37
|
}
|
|
38
38
|
else if (body.file.contentUrl) {
|
|
39
39
|
rawContent = yield (0, files_1.getFileContent)(body.file.contentUrl);
|
|
40
|
-
fileContent =
|
|
40
|
+
fileContent = rawContent;
|
|
41
41
|
}
|
|
42
42
|
else if (body.file.content) {
|
|
43
43
|
rawContent = body.file.content;
|
|
@@ -45,18 +45,20 @@ function handle(baseConfig, config, folderName) {
|
|
|
45
45
|
}
|
|
46
46
|
if (body.jobType === models_1.ProcessFileJobType.PRE_IMPORT || body.jobType === models_1.ProcessFileJobType.POST_EXPORT) {
|
|
47
47
|
body.getRawContent = (encoding) => __awaiter(this, void 0, void 0, function* () {
|
|
48
|
-
|
|
48
|
+
if (typeof rawContent === 'string') {
|
|
49
|
+
return Buffer.from(rawContent, 'base64').toString(encoding);
|
|
50
|
+
}
|
|
51
|
+
return rawContent;
|
|
49
52
|
});
|
|
50
53
|
}
|
|
51
54
|
const fileProcessResult = yield config.fileProcess(body, fileContent, req.crowdinApiClient, req.crowdinContext, req.crowdinContext.jwtPayload.context.project_id);
|
|
52
55
|
switch (body.jobType) {
|
|
53
56
|
case models_1.ProcessFileJobType.PRE_IMPORT:
|
|
54
57
|
case models_1.ProcessFileJobType.POST_EXPORT:
|
|
55
|
-
const { contentFile,
|
|
58
|
+
const { contentFile, fileName, fileType, error: contentFileError, } = fileProcessResult;
|
|
56
59
|
if (contentFile) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
response.content = contentFileEncoded;
|
|
60
|
+
if (Buffer.byteLength(contentFile) < files_1.MAX_BODY_SIZE) {
|
|
61
|
+
response.content = contentFile.toString('base64');
|
|
60
62
|
}
|
|
61
63
|
else {
|
|
62
64
|
let url;
|
|
@@ -83,16 +85,17 @@ function handle(baseConfig, config, folderName) {
|
|
|
83
85
|
const { strings, error: stringsFileError } = fileProcessResult;
|
|
84
86
|
if (strings) {
|
|
85
87
|
const stringsNDJson = strings.map((s) => JSON.stringify(s)).join('\n\r');
|
|
86
|
-
|
|
88
|
+
const bufferData = Buffer.from(stringsNDJson, 'utf-8');
|
|
89
|
+
if (Buffer.byteLength(bufferData) < files_1.MAX_BODY_SIZE) {
|
|
87
90
|
response.strings = strings;
|
|
88
91
|
}
|
|
89
92
|
else {
|
|
90
93
|
let url;
|
|
91
94
|
if (config.storeFile) {
|
|
92
|
-
url = yield config.storeFile(
|
|
95
|
+
url = yield config.storeFile(bufferData);
|
|
93
96
|
}
|
|
94
97
|
else {
|
|
95
|
-
const storedFile = yield (0, files_1.storeFile)(
|
|
98
|
+
const storedFile = yield (0, files_1.storeFile)(bufferData, path_1.default.join(folderPath, folderName));
|
|
96
99
|
url = `${baseFilesUrl}?file=${storedFile}`;
|
|
97
100
|
}
|
|
98
101
|
response.stringsUrl = url;
|
|
@@ -37,7 +37,7 @@ function handle(config, integration) {
|
|
|
37
37
|
}
|
|
38
38
|
const crowdinFiles = yield (0, cron_1.skipFoldersFromIntegrationRequest)(config, integration, projectId, Object.assign(Object.assign({}, filesToSync), newFiles), crowdinClient.client);
|
|
39
39
|
const result = yield integration.updateIntegration(projectId, crowdinClient.client, preparedIntegrationCredentials, crowdinFiles, rootFolder, appSettings);
|
|
40
|
-
if (newFiles) {
|
|
40
|
+
if (Object.keys(newFiles).length) {
|
|
41
41
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(Object.assign(Object.assign({}, filesToSync), newFiles)), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
|
|
42
42
|
const currentFileSnapshot = yield (0, file_snapshot_1.getCrowdinSnapshot)(config, integration, crowdinClient.client, projectId, appSettings);
|
|
43
43
|
yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(currentFileSnapshot), syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
|
|
@@ -17,7 +17,8 @@ function handle(config, integration) {
|
|
|
17
17
|
var _a;
|
|
18
18
|
const { files, provider } = req.body;
|
|
19
19
|
yield (0, cron_1.createOrUpdateSyncSettings)(config, req, files, provider);
|
|
20
|
-
|
|
20
|
+
const appSettings = req.integrationSettings || {};
|
|
21
|
+
if (((_a = integration.syncNewElements) === null || _a === void 0 ? void 0 : _a[provider]) && appSettings[`new-${provider}-files`]) {
|
|
21
22
|
yield (0, file_snapshot_1.createOrUpdateFileSnapshot)(config, integration, req, provider);
|
|
22
23
|
}
|
|
23
24
|
res.status(204).end();
|
package/out/models/index.d.ts
CHANGED
|
@@ -571,7 +571,7 @@ export interface FileProcessLogic {
|
|
|
571
571
|
/**
|
|
572
572
|
* Override to store huge responses (by default they will be stored in fs)
|
|
573
573
|
*/
|
|
574
|
-
storeFile?: (content:
|
|
574
|
+
storeFile?: (content: Buffer) => Promise<string>;
|
|
575
575
|
}
|
|
576
576
|
export interface CustomFileFormatLogic extends FileProcessLogic {
|
|
577
577
|
/**
|
|
@@ -605,28 +605,29 @@ export interface CustomFileFormatLogic extends FileProcessLogic {
|
|
|
605
605
|
/**
|
|
606
606
|
* Used for initial source file upload, source file update, and translation upload
|
|
607
607
|
*/
|
|
608
|
-
parseFile?: (fileContent:
|
|
608
|
+
parseFile?: (fileContent: Buffer, req: Omit<ProcessFileRequest, 'jobType' | 'file'>, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<ParseFileResponse>;
|
|
609
609
|
/**
|
|
610
610
|
* Used for translation download
|
|
611
611
|
*/
|
|
612
|
-
buildFile?: (fileContent:
|
|
612
|
+
buildFile?: (fileContent: Buffer, req: Omit<ProcessFileRequest, 'jobType' | 'file'>, strings: ProcessFileString[], client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<BuildFileResponse>;
|
|
613
613
|
/**
|
|
614
614
|
* Used for strings export
|
|
615
615
|
*/
|
|
616
616
|
exportStrings?: (req: Omit<ProcessFileRequest, 'jobType'>, strings: ProcessFileString[], client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<BuildFileResponse>;
|
|
617
617
|
}
|
|
618
618
|
export type FileImportExportLogic = FilePreImportLogic | FilePostImportLogic | FilePreExportLogic | FilePostExportLogic;
|
|
619
|
+
export type FileImportExportContent = ProcessFileString[] | Buffer | undefined;
|
|
619
620
|
export interface FilePreImportLogic extends FileProcessLogic {
|
|
620
|
-
fileProcess: (req: ProcessFileRequest, content:
|
|
621
|
+
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<BuildFileResponse>;
|
|
621
622
|
}
|
|
622
623
|
export interface FilePostImportLogic extends FileProcessLogic {
|
|
623
|
-
fileProcess: (req: ProcessFileRequest, content:
|
|
624
|
+
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<ParseFileResponse>;
|
|
624
625
|
}
|
|
625
626
|
export interface FilePreExportLogic extends FileProcessLogic {
|
|
626
|
-
fileProcess: (req: ProcessFileRequest, content:
|
|
627
|
+
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<ParseFileResponse>;
|
|
627
628
|
}
|
|
628
629
|
export interface FilePostExportLogic extends FileProcessLogic {
|
|
629
|
-
fileProcess: (req: ProcessFileRequest, content:
|
|
630
|
+
fileProcess: (req: ProcessFileRequest, content: FileImportExportContent, client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<BuildFileResponse>;
|
|
630
631
|
}
|
|
631
632
|
export interface SignaturePatterns {
|
|
632
633
|
fileName?: string;
|
|
@@ -639,7 +640,7 @@ export interface ProcessFileRequest {
|
|
|
639
640
|
targetLanguages: LanguagesModel.Language[];
|
|
640
641
|
strings: ProcessFileString[];
|
|
641
642
|
stringsUrl: string;
|
|
642
|
-
getRawContent?: (encoding: BufferEncoding) => Promise<string>;
|
|
643
|
+
getRawContent?: (encoding: BufferEncoding) => Promise<string | Buffer>;
|
|
643
644
|
}
|
|
644
645
|
export interface ProcessFileRecord {
|
|
645
646
|
content?: string;
|
|
@@ -657,13 +658,12 @@ export declare enum ProcessFileJobType {
|
|
|
657
658
|
POST_EXPORT = "post-export-file"
|
|
658
659
|
}
|
|
659
660
|
export interface ParseFileResponse {
|
|
660
|
-
previewFile?:
|
|
661
|
+
previewFile?: Buffer;
|
|
661
662
|
strings?: ProcessFileString[];
|
|
662
663
|
error?: string;
|
|
663
664
|
}
|
|
664
665
|
export interface BuildFileResponse {
|
|
665
|
-
contentFile:
|
|
666
|
-
base64EncodedContent?: string;
|
|
666
|
+
contentFile: Buffer;
|
|
667
667
|
error?: string;
|
|
668
668
|
fileName?: string;
|
|
669
669
|
fileType?: string;
|
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/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);
|
package/package.json
CHANGED