@crowdin/app-project-module 0.6.4 → 0.7.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/README.md +55 -4
- package/out/handlers/crowdin-files.d.ts +2 -2
- package/out/handlers/crowdin-files.js +5 -5
- package/out/handlers/crowdin-update.d.ts +2 -2
- package/out/handlers/crowdin-update.js +3 -3
- package/out/handlers/custom-file-format/download.d.ts +3 -0
- package/out/handlers/custom-file-format/download.js +31 -0
- package/out/handlers/custom-file-format/process.d.ts +4 -0
- package/out/handlers/custom-file-format/process.js +110 -0
- package/out/handlers/integration-data.d.ts +2 -2
- package/out/handlers/integration-data.js +2 -2
- package/out/handlers/integration-login.d.ts +2 -2
- package/out/handlers/integration-login.js +3 -3
- package/out/handlers/integration-update.d.ts +2 -2
- package/out/handlers/integration-update.js +3 -3
- package/out/handlers/main.d.ts +2 -2
- package/out/handlers/main.js +10 -10
- package/out/handlers/manifest.js +23 -11
- package/out/handlers/oauth-login.d.ts +2 -2
- package/out/handlers/oauth-login.js +6 -6
- package/out/index.js +30 -21
- package/out/middlewares/integration-credentials.d.ts +2 -2
- package/out/middlewares/integration-credentials.js +2 -2
- package/out/models/index.d.ts +75 -5
- package/out/models/index.js +6 -1
- package/out/util/index.d.ts +6 -6
- package/out/util/index.js +16 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,6 +29,7 @@ In both options you will need to provide Crowdin App configuration file. Please
|
|
|
29
29
|
- [Info window](#info-window)
|
|
30
30
|
- [Background tasks](#background-tasks)
|
|
31
31
|
- [Error propagation](#error-propagation)
|
|
32
|
+
- [Custom File Format](#custom-file-format)
|
|
32
33
|
- [Contributing](#contributing)
|
|
33
34
|
- [Seeking Assistance](#seeking-assistance)
|
|
34
35
|
- [License](#license)
|
|
@@ -153,7 +154,7 @@ By default login page for your app will require only to enter `apiToken` to com
|
|
|
153
154
|
But there is also a possibility to customize it.
|
|
154
155
|
|
|
155
156
|
```javascript
|
|
156
|
-
configuration.loginForm = {
|
|
157
|
+
configuration.integration.loginForm = {
|
|
157
158
|
fields: [
|
|
158
159
|
{
|
|
159
160
|
key: 'username',
|
|
@@ -181,7 +182,7 @@ In case if third party service uses OAuth2 for authorization use `oauthLogin` fi
|
|
|
181
182
|
Github example:
|
|
182
183
|
|
|
183
184
|
```javascript
|
|
184
|
-
configuration.oauthLogin = {
|
|
185
|
+
configuration.integration.oauthLogin = {
|
|
185
186
|
authorizationUrl: 'https://github.com/login/oauth/authorize',
|
|
186
187
|
clientId: 'github_app_client_id',
|
|
187
188
|
clientSecret: 'github_app_client_secret',
|
|
@@ -192,7 +193,7 @@ configuration.oauthLogin = {
|
|
|
192
193
|
Google example:
|
|
193
194
|
|
|
194
195
|
```javascript
|
|
195
|
-
configuration.oauthLogin = {
|
|
196
|
+
configuration.integration.oauthLogin = {
|
|
196
197
|
scope: 'https%3A//www.googleapis.com/auth/userinfo.email',
|
|
197
198
|
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
|
|
198
199
|
clientId: 'google_web_app_client_id',
|
|
@@ -239,7 +240,7 @@ const clientId = 'client_id';
|
|
|
239
240
|
const clientSecret = 'client_secret';
|
|
240
241
|
const tokenUrl = 'https://services.mailup.com/Authorization/OAuth/Token';
|
|
241
242
|
|
|
242
|
-
configuration.oauthLogin = {
|
|
243
|
+
configuration.integration.oauthLogin = {
|
|
243
244
|
authorizationUrl: 'https://services.mailup.com/Authorization/OAuth/LogOn',
|
|
244
245
|
clientId,
|
|
245
246
|
clientSecret,
|
|
@@ -374,6 +375,56 @@ configuration.integrartion.getIntegrationFiles = async (credentials, appSettings
|
|
|
374
375
|
}
|
|
375
376
|
```
|
|
376
377
|
|
|
378
|
+
## Custom File Format
|
|
379
|
+
|
|
380
|
+
There is also a possibility to declare [custom file format module](https://support.crowdin.com/crowdin-apps-modules/#custom-file-format-module).
|
|
381
|
+
|
|
382
|
+
```javascript
|
|
383
|
+
const crowdinModule = require('@crowdin/app-project-module');
|
|
384
|
+
const convert = require('xml-js');
|
|
385
|
+
|
|
386
|
+
const configuration = {
|
|
387
|
+
baseUrl: 'https://123.ngrok.io',
|
|
388
|
+
clientId: 'clientId',
|
|
389
|
+
clientSecret: 'clientSecret',
|
|
390
|
+
name: 'Sample App',
|
|
391
|
+
identifier: 'sample-app',
|
|
392
|
+
description: 'Sample App description',
|
|
393
|
+
dbFolder: __dirname,
|
|
394
|
+
imagePath: __dirname + '/' + 'logo.png',
|
|
395
|
+
customFileFormat: {
|
|
396
|
+
type: 'type-xyz',
|
|
397
|
+
multilingual: false,
|
|
398
|
+
signaturePatterns: {
|
|
399
|
+
fileName: '^.+\.xml$'
|
|
400
|
+
},
|
|
401
|
+
parseFile: async (file, req) => {
|
|
402
|
+
const xml = convert.xml2json(file, { compact: true, spaces: 4 });
|
|
403
|
+
const fileContent = JSON.parse(xml);
|
|
404
|
+
//parse logic
|
|
405
|
+
const strings = [];
|
|
406
|
+
return { strings };
|
|
407
|
+
},
|
|
408
|
+
buildFile: async (file, req, strings) => {
|
|
409
|
+
const xml = convert.xml2json(file, { compact: true, spaces: 4 });
|
|
410
|
+
const fileContent = JSON.parse(xml);
|
|
411
|
+
//build logic
|
|
412
|
+
const contentFile = convert.json2xml(
|
|
413
|
+
fileContent,
|
|
414
|
+
{
|
|
415
|
+
compact: true,
|
|
416
|
+
ignoreComment: false,
|
|
417
|
+
spaces: 4
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
return { contentFile }
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
crowdinModule.createApp(configuration);
|
|
426
|
+
```
|
|
427
|
+
|
|
377
428
|
## Contributing
|
|
378
429
|
|
|
379
430
|
If you want to contribute please read the [Contributing](/CONTRIBUTING.md) guidelines.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic): (req: 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;
|
|
@@ -10,12 +10,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const util_1 = require("../util");
|
|
13
|
-
function handle(config) {
|
|
13
|
+
function handle(config, integration) {
|
|
14
14
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
if (
|
|
16
|
-
const rootFolder = yield (0, util_1.getRootFolder)(config, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
|
|
17
|
-
const files =
|
|
18
|
-
? yield
|
|
15
|
+
if (integration.getCrowdinFiles) {
|
|
16
|
+
const rootFolder = yield (0, util_1.getRootFolder)(config, integration, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
|
|
17
|
+
const files = integration.getCrowdinFiles
|
|
18
|
+
? yield integration.getCrowdinFiles(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, rootFolder, req.integrationSettings)
|
|
19
19
|
: [];
|
|
20
20
|
res.send(files);
|
|
21
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic): (req: 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;
|
|
@@ -10,10 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const util_1 = require("../util");
|
|
13
|
-
function handle(config) {
|
|
13
|
+
function handle(config, integration) {
|
|
14
14
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
const rootFolder = yield (0, util_1.getRootFolder)(config, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
|
|
16
|
-
yield
|
|
15
|
+
const rootFolder = yield (0, util_1.getRootFolder)(config, integration, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
|
|
16
|
+
yield integration.updateCrowdin(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, req.integrationCredentials, req.body, rootFolder, req.integrationSettings);
|
|
17
17
|
res.status(204).end();
|
|
18
18
|
}));
|
|
19
19
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Request, Response } from 'express';
|
|
3
|
+
export default function handle(folder: string): (req: 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,31 @@
|
|
|
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
|
+
function handle(folder) {
|
|
19
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
const filePath = path_1.default.join(folder, 'custom-file-format', req.query.file);
|
|
21
|
+
res.download(filePath, function (err) {
|
|
22
|
+
if (err) {
|
|
23
|
+
console.error(err);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
fs_1.default.unlinkSync(filePath);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
exports.default = handle;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/// <reference types="qs" />
|
|
2
|
+
import { Request, Response } from 'express';
|
|
3
|
+
import { CustomFileFormatLogic } from '../../models';
|
|
4
|
+
export default function handle(baseUrl: string, folder: string, config: CustomFileFormatLogic): (req: 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,110 @@
|
|
|
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 axios_1 = __importDefault(require("axios"));
|
|
16
|
+
const fs_1 = __importDefault(require("fs"));
|
|
17
|
+
const path_1 = __importDefault(require("path"));
|
|
18
|
+
const models_1 = require("../../models");
|
|
19
|
+
const util_1 = require("../../util");
|
|
20
|
+
const MAX_BODY_SIZE = 5 * 1024 * 1024; //5mb
|
|
21
|
+
function storeFile(fileContent, folder) {
|
|
22
|
+
const fileName = `file${Date.now()}`;
|
|
23
|
+
return new Promise((res, rej) => fs_1.default.writeFile(path_1.default.join(folder, 'custom-file-format', fileName), fileContent, err => {
|
|
24
|
+
if (err) {
|
|
25
|
+
rej(err);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
res(fileName);
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
function handleBuildFile(baseUrl, dataFolder, config, file, req) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
const response = {};
|
|
35
|
+
if (!req.strings && !req.stringsUrl) {
|
|
36
|
+
throw new Error('Bad payload received: No strings found');
|
|
37
|
+
}
|
|
38
|
+
let strings;
|
|
39
|
+
if (req.strings) {
|
|
40
|
+
strings = req.strings;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
strings = (yield axios_1.default.get(req.stringsUrl)).data;
|
|
44
|
+
}
|
|
45
|
+
const res = yield config.buildFile(file, req, strings);
|
|
46
|
+
const contentFileEncoded = Buffer.from(res.contentFile).toString('base64');
|
|
47
|
+
if (Buffer.byteLength(contentFileEncoded, 'utf8') < MAX_BODY_SIZE) {
|
|
48
|
+
response.content = contentFileEncoded;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
const storedFile = yield storeFile(res.contentFile, dataFolder);
|
|
52
|
+
response.contentUrl = `${baseUrl}?file=${storedFile}`;
|
|
53
|
+
}
|
|
54
|
+
return response;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function handleParseFile(baseUrl, dataFolder, config, file, req) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const response = {};
|
|
60
|
+
const res = yield config.parseFile(file, req);
|
|
61
|
+
if (res.previewFile) {
|
|
62
|
+
const previewFileEncoded = Buffer.from(res.previewFile).toString('base64');
|
|
63
|
+
if (Buffer.byteLength(previewFileEncoded, 'utf8') < MAX_BODY_SIZE) {
|
|
64
|
+
response.preview = previewFileEncoded;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const storedFile = yield storeFile(res.previewFile, dataFolder);
|
|
68
|
+
response.previewUrl = `${baseUrl}?file=${storedFile}`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (res.strings) {
|
|
72
|
+
const stringsJson = JSON.stringify(res.strings);
|
|
73
|
+
if (Buffer.byteLength(stringsJson, 'utf8') < MAX_BODY_SIZE) {
|
|
74
|
+
response.strings = res.strings;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const storedFile = yield storeFile(stringsJson, dataFolder);
|
|
78
|
+
response.stringsUrl = `${baseUrl}?file=${storedFile}`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return response;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function handle(baseUrl, folder, config) {
|
|
85
|
+
if (!fs_1.default.existsSync(path_1.default.join(folder, 'custom-file-format'))) {
|
|
86
|
+
fs_1.default.mkdirSync(path_1.default.join(folder, 'custom-file-format'), { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
const baseFilesUrl = `${baseUrl}/file/download`;
|
|
90
|
+
const body = req.body;
|
|
91
|
+
let file;
|
|
92
|
+
if (body.file.content) {
|
|
93
|
+
file = Buffer.from(body.file.content, 'base64').toString();
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
file = (yield axios_1.default.get(body.file.contentUrl || '')).data;
|
|
97
|
+
}
|
|
98
|
+
let response = {};
|
|
99
|
+
switch (body.jobType) {
|
|
100
|
+
case models_1.ProcessFileJobType.BUILD_FILE:
|
|
101
|
+
response = yield handleBuildFile(baseFilesUrl, folder, config, file, body);
|
|
102
|
+
break;
|
|
103
|
+
case models_1.ProcessFileJobType.PARSE_FILE:
|
|
104
|
+
response = yield handleParseFile(baseFilesUrl, folder, config, file, body);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
res.send({ data: response });
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
exports.default = handle;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import {
|
|
4
|
-
export default function handle(
|
|
3
|
+
import { IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(integration: IntegrationLogic): (req: 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;
|
|
@@ -10,9 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const util_1 = require("../util");
|
|
13
|
-
function handle(
|
|
13
|
+
function handle(integration) {
|
|
14
14
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
const files = yield
|
|
15
|
+
const files = yield integration.getIntegrationFiles(req.integrationCredentials, req.integrationSettings);
|
|
16
16
|
res.send(files);
|
|
17
17
|
}));
|
|
18
18
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic): (req: 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;
|
|
@@ -11,10 +11,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const storage_1 = require("../storage");
|
|
13
13
|
const util_1 = require("../util");
|
|
14
|
-
function handle(config) {
|
|
14
|
+
function handle(config, integration) {
|
|
15
15
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
|
-
if (
|
|
17
|
-
yield
|
|
16
|
+
if (integration.checkConnection) {
|
|
17
|
+
yield integration.checkConnection(req.body.credentials);
|
|
18
18
|
}
|
|
19
19
|
yield (0, storage_1.saveIntegrationCredentials)(req.crowdinContext.clientId, (0, util_1.encryptData)(config.clientSecret, JSON.stringify(req.body.credentials)), req.crowdinContext.crowdinId);
|
|
20
20
|
res.status(204).end();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic): (req: 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;
|
|
@@ -10,10 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const util_1 = require("../util");
|
|
13
|
-
function handle(config) {
|
|
13
|
+
function handle(config, integration) {
|
|
14
14
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
15
|
-
const rootFolder = yield (0, util_1.getRootFolder)(config, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
|
|
16
|
-
yield
|
|
15
|
+
const rootFolder = yield (0, util_1.getRootFolder)(config, integration, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
|
|
16
|
+
yield integration.updateIntegration(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, req.integrationCredentials, req.body, rootFolder, req.integrationSettings);
|
|
17
17
|
res.status(204).end();
|
|
18
18
|
}));
|
|
19
19
|
}
|
package/out/handlers/main.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic): (req: 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;
|
package/out/handlers/main.js
CHANGED
|
@@ -10,12 +10,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const util_1 = require("../util");
|
|
13
|
-
function constructOauthUrl(config) {
|
|
13
|
+
function constructOauthUrl(config, integration) {
|
|
14
14
|
var _a, _b, _c;
|
|
15
|
-
const oauth =
|
|
15
|
+
const oauth = integration.oauthLogin;
|
|
16
16
|
let url = (oauth === null || oauth === void 0 ? void 0 : oauth.authorizationUrl) || '';
|
|
17
17
|
url += `?${((_a = oauth === null || oauth === void 0 ? void 0 : oauth.fieldsMapping) === null || _a === void 0 ? void 0 : _a.clientId) || 'client_id'}=${oauth === null || oauth === void 0 ? void 0 : oauth.clientId}`;
|
|
18
|
-
url += `&${((_b = oauth === null || oauth === void 0 ? void 0 : oauth.fieldsMapping) === null || _b === void 0 ? void 0 : _b.redirectUri) || 'redirect_uri'}=${config.baseUrl}${(0, util_1.getOauthRoute)(
|
|
18
|
+
url += `&${((_b = oauth === null || oauth === void 0 ? void 0 : oauth.fieldsMapping) === null || _b === void 0 ? void 0 : _b.redirectUri) || 'redirect_uri'}=${config.baseUrl}${(0, util_1.getOauthRoute)(integration)}`;
|
|
19
19
|
if (oauth === null || oauth === void 0 ? void 0 : oauth.scope) {
|
|
20
20
|
url += `&${((_c = oauth === null || oauth === void 0 ? void 0 : oauth.fieldsMapping) === null || _c === void 0 ? void 0 : _c.scope) || 'scope'}=${oauth === null || oauth === void 0 ? void 0 : oauth.scope}`;
|
|
21
21
|
}
|
|
@@ -24,7 +24,7 @@ function constructOauthUrl(config) {
|
|
|
24
24
|
}
|
|
25
25
|
return url;
|
|
26
26
|
}
|
|
27
|
-
function handle(config) {
|
|
27
|
+
function handle(config, integration) {
|
|
28
28
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
29
29
|
var _a;
|
|
30
30
|
const installed = !!req.crowdinApiClient;
|
|
@@ -38,17 +38,17 @@ function handle(config) {
|
|
|
38
38
|
}
|
|
39
39
|
else if (!loggedIn) {
|
|
40
40
|
view = 'login';
|
|
41
|
-
options.loginFields = (_a =
|
|
42
|
-
if (
|
|
43
|
-
options.oauthUrl = constructOauthUrl(config);
|
|
41
|
+
options.loginFields = (_a = integration.loginForm) === null || _a === void 0 ? void 0 : _a.fields;
|
|
42
|
+
if (integration.oauthLogin) {
|
|
43
|
+
options.oauthUrl = constructOauthUrl(config, integration);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
else if (
|
|
47
|
-
const configurationFields = yield
|
|
46
|
+
else if (integration.getConfiguration) {
|
|
47
|
+
const configurationFields = yield integration.getConfiguration(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, req.integrationCredentials);
|
|
48
48
|
options.configurationFields = configurationFields;
|
|
49
49
|
options.config = JSON.stringify(req.integrationSettings || {});
|
|
50
50
|
}
|
|
51
|
-
options.infoModal =
|
|
51
|
+
options.infoModal = integration.infoModal;
|
|
52
52
|
return res.render(view, options);
|
|
53
53
|
}));
|
|
54
54
|
}
|
package/out/handlers/manifest.js
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
function handle(config) {
|
|
4
|
+
const modules = {};
|
|
5
|
+
if (config.integration) {
|
|
6
|
+
modules.integrations = [
|
|
7
|
+
{
|
|
8
|
+
key: config.identifier,
|
|
9
|
+
name: config.name,
|
|
10
|
+
description: config.description,
|
|
11
|
+
logo: '/logo.png',
|
|
12
|
+
url: '/',
|
|
13
|
+
},
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
if (config.customFileFormat) {
|
|
17
|
+
modules['custom-file-format'] = [
|
|
18
|
+
{
|
|
19
|
+
key: config.identifier,
|
|
20
|
+
type: config.customFileFormat.type,
|
|
21
|
+
signaturePatterns: config.customFileFormat.signaturePatterns,
|
|
22
|
+
url: '/process',
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
}
|
|
4
26
|
return (_req, res) => {
|
|
5
27
|
const manifest = {
|
|
6
28
|
identifier: config.identifier,
|
|
@@ -16,17 +38,7 @@ function handle(config) {
|
|
|
16
38
|
uninstall: '/uninstall',
|
|
17
39
|
},
|
|
18
40
|
scopes: ['project'],
|
|
19
|
-
modules
|
|
20
|
-
integrations: [
|
|
21
|
-
{
|
|
22
|
-
key: config.identifier,
|
|
23
|
-
name: config.name,
|
|
24
|
-
description: config.description,
|
|
25
|
-
logo: '/logo.png',
|
|
26
|
-
url: '/',
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
},
|
|
41
|
+
modules,
|
|
30
42
|
};
|
|
31
43
|
res.send(manifest);
|
|
32
44
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Request, Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic): (req: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -14,26 +14,26 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const axios_1 = __importDefault(require("axios"));
|
|
16
16
|
const util_1 = require("../util");
|
|
17
|
-
function handle(config) {
|
|
17
|
+
function handle(config, integration) {
|
|
18
18
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
20
|
-
const code = req.query[((_b = (_a =
|
|
21
|
-
const oauthLogin =
|
|
20
|
+
const code = req.query[((_b = (_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.fieldsMapping) === null || _b === void 0 ? void 0 : _b.code) || 'code'];
|
|
21
|
+
const oauthLogin = integration.oauthLogin;
|
|
22
22
|
let credentials;
|
|
23
23
|
if (oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.performGetTokenRequest) {
|
|
24
24
|
credentials = yield oauthLogin.performGetTokenRequest(code);
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
27
27
|
const request = {};
|
|
28
|
-
const oauthLogin =
|
|
28
|
+
const oauthLogin = integration.oauthLogin;
|
|
29
29
|
request[((_c = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _c === void 0 ? void 0 : _c.code) || 'code'] = code;
|
|
30
30
|
request[((_d = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _d === void 0 ? void 0 : _d.clientId) || 'client_id'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientId;
|
|
31
31
|
request[((_e = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _e === void 0 ? void 0 : _e.clientSecret) || 'client_secret'] = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.clientSecret;
|
|
32
|
-
request[((_f = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _f === void 0 ? void 0 : _f.redirectUri) || 'redirect_uri'] = `${config.baseUrl}${(0, util_1.getOauthRoute)(
|
|
32
|
+
request[((_f = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _f === void 0 ? void 0 : _f.redirectUri) || 'redirect_uri'] = `${config.baseUrl}${(0, util_1.getOauthRoute)(integration)}`;
|
|
33
33
|
if (oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraAccessTokenParameters) {
|
|
34
34
|
Object.entries(oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.extraAccessTokenParameters).forEach(([key, value]) => (request[key] = value));
|
|
35
35
|
}
|
|
36
|
-
credentials = (yield axios_1.default.post(((_g =
|
|
36
|
+
credentials = (yield axios_1.default.post(((_g = integration.oauthLogin) === null || _g === void 0 ? void 0 : _g.accessTokenUrl) || '', request, {
|
|
37
37
|
headers: { Accept: 'application/json' },
|
|
38
38
|
})).data;
|
|
39
39
|
}
|
package/out/index.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
25
|
exports.createApp = exports.addCrowdinEndpoints = void 0;
|
|
26
|
-
const express_1 =
|
|
26
|
+
const express_1 = __importDefault(require("express"));
|
|
27
27
|
const express_handlebars_1 = __importDefault(require("express-handlebars"));
|
|
28
28
|
const cron = __importStar(require("node-cron"));
|
|
29
29
|
const path_1 = require("path");
|
|
@@ -31,6 +31,8 @@ const crowdin_file_progress_1 = __importDefault(require("./handlers/crowdin-file
|
|
|
31
31
|
const crowdin_files_1 = __importDefault(require("./handlers/crowdin-files"));
|
|
32
32
|
const crowdin_project_1 = __importDefault(require("./handlers/crowdin-project"));
|
|
33
33
|
const crowdin_update_1 = __importDefault(require("./handlers/crowdin-update"));
|
|
34
|
+
const download_1 = __importDefault(require("./handlers/custom-file-format/download"));
|
|
35
|
+
const process_1 = __importDefault(require("./handlers/custom-file-format/process"));
|
|
34
36
|
const install_1 = __importDefault(require("./handlers/install"));
|
|
35
37
|
const integration_data_1 = __importDefault(require("./handlers/integration-data"));
|
|
36
38
|
const integration_login_1 = __importDefault(require("./handlers/integration-login"));
|
|
@@ -47,9 +49,8 @@ const json_response_1 = __importDefault(require("./middlewares/json-response"));
|
|
|
47
49
|
const storage_1 = require("./storage");
|
|
48
50
|
const util_1 = require("./util");
|
|
49
51
|
function addCrowdinEndpoints(app, config) {
|
|
50
|
-
(0, util_1.applyDefaults)(config);
|
|
51
52
|
(0, storage_1.connect)(config.dbFolder);
|
|
52
|
-
app.use(
|
|
53
|
+
app.use(express_1.default.json({ limit: '50mb' }));
|
|
53
54
|
app.use('/assets', express_1.default.static((0, path_1.join)(__dirname, 'static')));
|
|
54
55
|
app.set('views', (0, path_1.join)(__dirname, 'views'));
|
|
55
56
|
app.engine('handlebars', (0, express_handlebars_1.default)({
|
|
@@ -66,26 +67,34 @@ function addCrowdinEndpoints(app, config) {
|
|
|
66
67
|
}));
|
|
67
68
|
app.set('view engine', 'handlebars');
|
|
68
69
|
app.get('/logo.png', (req, res) => res.sendFile(config.imagePath || (0, path_1.join)(__dirname, 'logo.png')));
|
|
69
|
-
if (config.oauthLogin) {
|
|
70
|
-
app.get((0, util_1.getOauthRoute)(config), (0, oauth_login_1.default)(config));
|
|
71
|
-
}
|
|
72
|
-
app.get('/', (0, crowdin_client_1.default)(config, true), (0, integration_credentials_1.default)(config, true), (0, main_1.default)(config));
|
|
73
|
-
app.get('/manifest.json', json_response_1.default, (0, manifest_1.default)(config));
|
|
74
70
|
app.post('/installed', (0, install_1.default)(config));
|
|
75
71
|
app.post('/uninstall', (0, uninstall_1.default)());
|
|
76
|
-
app.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
72
|
+
app.get('/manifest.json', json_response_1.default, (0, manifest_1.default)(config));
|
|
73
|
+
const integrationLogic = config.integration;
|
|
74
|
+
if (integrationLogic) {
|
|
75
|
+
(0, util_1.applyDefaults)(config, integrationLogic);
|
|
76
|
+
app.get('/', (0, crowdin_client_1.default)(config, true), (0, integration_credentials_1.default)(config, integrationLogic, true), (0, main_1.default)(config, integrationLogic));
|
|
77
|
+
app.post('/api/settings', (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, settings_save_1.default)());
|
|
78
|
+
app.post('/api/login', (0, crowdin_client_1.default)(config), (0, integration_login_1.default)(config, integrationLogic));
|
|
79
|
+
app.post('/api/logout', (0, crowdin_client_1.default)(config), (0, integration_logout_1.default)());
|
|
80
|
+
app.get('/api/crowdin/files', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, crowdin_files_1.default)(config, integrationLogic));
|
|
81
|
+
app.get('/api/crowdin/project', json_response_1.default, (0, crowdin_client_1.default)(config), (0, crowdin_project_1.default)());
|
|
82
|
+
app.get('/api/crowdin/file-progress/:fileId', (0, crowdin_client_1.default)(config), (0, crowdin_file_progress_1.default)());
|
|
83
|
+
app.get('/api/integration/data', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_data_1.default)(integrationLogic));
|
|
84
|
+
app.post('/api/crowdin/update', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, crowdin_update_1.default)(config, integrationLogic));
|
|
85
|
+
app.post('/api/integration/update', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, integration_update_1.default)(config, integrationLogic));
|
|
86
|
+
if (integrationLogic.oauthLogin) {
|
|
87
|
+
app.get((0, util_1.getOauthRoute)(integrationLogic), (0, oauth_login_1.default)(config, integrationLogic));
|
|
88
|
+
}
|
|
89
|
+
if (integrationLogic.cronJobs) {
|
|
90
|
+
integrationLogic.cronJobs.forEach(job => {
|
|
91
|
+
cron.schedule(job.expression, () => (0, util_1.runJob)(config, integrationLogic, job).catch(console.error));
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (config.customFileFormat) {
|
|
96
|
+
app.post('/process', (0, process_1.default)(config.baseUrl, config.customFileFormat.filesFolder || config.dbFolder, config.customFileFormat));
|
|
97
|
+
app.get('/file/download', (0, download_1.default)(config.customFileFormat.filesFolder || config.dbFolder));
|
|
89
98
|
}
|
|
90
99
|
}
|
|
91
100
|
exports.addCrowdinEndpoints = addCrowdinEndpoints;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
-
export default function handle(config: Config, optional?: boolean): (req: 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
|
+
import { Config, IntegrationLogic } from '../models';
|
|
4
|
+
export default function handle(config: Config, integration: IntegrationLogic, optional?: boolean): (req: 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;
|
|
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const storage_1 = require("../storage");
|
|
13
13
|
const util_1 = require("../util");
|
|
14
|
-
function handle(config, optional = false) {
|
|
14
|
+
function handle(config, integration, optional = false) {
|
|
15
15
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
16
16
|
const clientId = req.crowdinContext.clientId;
|
|
17
17
|
const integrationCredentials = yield (0, storage_1.getIntegrationCredentials)(clientId);
|
|
@@ -25,7 +25,7 @@ function handle(config, optional = false) {
|
|
|
25
25
|
req.integrationSettings = JSON.parse(integrationCredentials.config);
|
|
26
26
|
}
|
|
27
27
|
try {
|
|
28
|
-
req.integrationCredentials = yield (0, util_1.prepareIntegrationCredentials)(config, integrationCredentials);
|
|
28
|
+
req.integrationCredentials = yield (0, util_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
29
29
|
}
|
|
30
30
|
catch (e) {
|
|
31
31
|
console.error(e);
|
package/out/models/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Crowdin, { SourceFilesModel } from '@crowdin/crowdin-api-client';
|
|
1
|
+
import Crowdin, { LanguagesModel, SourceFilesModel, SourceStringsModel } from '@crowdin/crowdin-api-client';
|
|
2
2
|
import { JwtPayload } from '@crowdin/crowdin-apps-functions';
|
|
3
3
|
import { Request } from 'express';
|
|
4
4
|
export interface Config {
|
|
@@ -39,9 +39,15 @@ export interface Config {
|
|
|
39
39
|
*/
|
|
40
40
|
imagePath?: string;
|
|
41
41
|
/**
|
|
42
|
-
* integration logic
|
|
42
|
+
* integration module logic
|
|
43
43
|
*/
|
|
44
|
-
integration
|
|
44
|
+
integration?: IntegrationLogic;
|
|
45
|
+
/**
|
|
46
|
+
* custom file format module logic
|
|
47
|
+
*/
|
|
48
|
+
customFileFormat?: CustomFileFormatLogic;
|
|
49
|
+
}
|
|
50
|
+
export interface IntegrationLogic {
|
|
45
51
|
/**
|
|
46
52
|
* Customize your app login form
|
|
47
53
|
*/
|
|
@@ -50,8 +56,6 @@ export interface Config {
|
|
|
50
56
|
* Define login process via OAuth2 protocol
|
|
51
57
|
*/
|
|
52
58
|
oauthLogin?: OAuthLogin;
|
|
53
|
-
}
|
|
54
|
-
export interface IntegrationLogic {
|
|
55
59
|
/**
|
|
56
60
|
* name of the root folder in Crowdin where files from integration will be stored, default your app name, will be ignored in case if {@link withRootFolder} is false
|
|
57
61
|
*/
|
|
@@ -275,3 +279,69 @@ export interface CronJob {
|
|
|
275
279
|
task: (projectId: number, client: Crowdin, apiCredentials: any, appRootFolder?: SourceFilesModel.Directory, config?: any) => Promise<void>;
|
|
276
280
|
expression: string;
|
|
277
281
|
}
|
|
282
|
+
export interface CustomFileFormatLogic {
|
|
283
|
+
/**
|
|
284
|
+
* The type parameter value for a custom file format. Used for a custom format file upload via API.
|
|
285
|
+
*/
|
|
286
|
+
type: string;
|
|
287
|
+
/**
|
|
288
|
+
* Folder where larger file will be temporary stored (default "{@link dbFolder}/custom-file-format")
|
|
289
|
+
*/
|
|
290
|
+
filesFolder?: string;
|
|
291
|
+
/**
|
|
292
|
+
* This parameter is used to combine the content of multiple languages into one request when uploading and downloading translations in your Crowdin project.
|
|
293
|
+
*/
|
|
294
|
+
multilingual?: boolean;
|
|
295
|
+
/**
|
|
296
|
+
* Contains fileName and/or fileContent regular expressions used to detect file type when uploading a new source file via UI (or via API without specified type parameter). If the file matches regular expressions, it's labeled as a custom format file.
|
|
297
|
+
*/
|
|
298
|
+
signaturePatterns?: SignaturePatterns;
|
|
299
|
+
/**
|
|
300
|
+
* Used for initial source file upload, source file update, and translation upload
|
|
301
|
+
*/
|
|
302
|
+
parseFile: (fileContent: string | object, req: Omit<ProcessFileRequest, 'jobType' | 'file'>) => Promise<ParseFileResponse>;
|
|
303
|
+
/**
|
|
304
|
+
* Used for translation download
|
|
305
|
+
*/
|
|
306
|
+
buildFile: (fileContent: string | object, req: Omit<ProcessFileRequest, 'jobType' | 'file'>, strings: ProcessFileString[]) => Promise<BuildFileResponse>;
|
|
307
|
+
}
|
|
308
|
+
export interface SignaturePatterns {
|
|
309
|
+
fileName?: string;
|
|
310
|
+
fileContent?: string;
|
|
311
|
+
}
|
|
312
|
+
export interface ProcessFileRequest {
|
|
313
|
+
jobType: ProcessFileJobType;
|
|
314
|
+
file: ProcessFileRecord;
|
|
315
|
+
sourceLanguage: LanguagesModel.Language;
|
|
316
|
+
targetLanguages: LanguagesModel.Language[];
|
|
317
|
+
strings: ProcessFileString[];
|
|
318
|
+
stringsUrl: string;
|
|
319
|
+
}
|
|
320
|
+
export interface ProcessFileRecord {
|
|
321
|
+
content?: string;
|
|
322
|
+
contentUrl?: string;
|
|
323
|
+
}
|
|
324
|
+
export declare enum ProcessFileJobType {
|
|
325
|
+
PARSE_FILE = "parse-file",
|
|
326
|
+
BUILD_FILE = "build-file"
|
|
327
|
+
}
|
|
328
|
+
export interface ParseFileResponse {
|
|
329
|
+
previewFile?: string;
|
|
330
|
+
strings?: ProcessFileString[];
|
|
331
|
+
}
|
|
332
|
+
export interface BuildFileResponse {
|
|
333
|
+
contentFile: string;
|
|
334
|
+
}
|
|
335
|
+
export interface ProcessFileString {
|
|
336
|
+
previewId?: number;
|
|
337
|
+
id: number;
|
|
338
|
+
identifier: string;
|
|
339
|
+
context?: string;
|
|
340
|
+
customData?: string;
|
|
341
|
+
maxLength?: number;
|
|
342
|
+
isHidden?: boolean;
|
|
343
|
+
hasPlurals?: boolean;
|
|
344
|
+
labels?: string[];
|
|
345
|
+
text: string | SourceStringsModel.PluralText;
|
|
346
|
+
translations?: any;
|
|
347
|
+
}
|
package/out/models/index.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AccountType = void 0;
|
|
3
|
+
exports.ProcessFileJobType = exports.AccountType = void 0;
|
|
4
4
|
var AccountType;
|
|
5
5
|
(function (AccountType) {
|
|
6
6
|
AccountType["NORMAL"] = "normal";
|
|
7
7
|
AccountType["ENTERPRISE"] = "enterprise";
|
|
8
8
|
})(AccountType = exports.AccountType || (exports.AccountType = {}));
|
|
9
|
+
var ProcessFileJobType;
|
|
10
|
+
(function (ProcessFileJobType) {
|
|
11
|
+
ProcessFileJobType["PARSE_FILE"] = "parse-file";
|
|
12
|
+
ProcessFileJobType["BUILD_FILE"] = "build-file";
|
|
13
|
+
})(ProcessFileJobType = exports.ProcessFileJobType || (exports.ProcessFileJobType = {}));
|
package/out/util/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Crowdin, { SourceFilesModel } from '@crowdin/crowdin-api-client';
|
|
2
2
|
import { Request, Response } from 'express';
|
|
3
|
-
import { Config, CronJob, CrowdinCredentials, IntegrationCredentials } from '../models';
|
|
3
|
+
import { Config, CronJob, CrowdinCredentials, IntegrationCredentials, IntegrationLogic } from '../models';
|
|
4
4
|
export declare class CodeError extends Error {
|
|
5
5
|
code: number | undefined;
|
|
6
6
|
constructor(message: string, code?: number);
|
|
@@ -8,9 +8,9 @@ export declare class CodeError extends Error {
|
|
|
8
8
|
export declare function runAsyncWrapper(callback: Function): (req: Request, res: Response, next: Function) => void;
|
|
9
9
|
export declare function encryptData(secret: string, data: string): string;
|
|
10
10
|
export declare function decryptData(secret: string, data: string): string;
|
|
11
|
-
export declare function getOauthRoute(
|
|
12
|
-
export declare function getRootFolder(config: Config, client: Crowdin, projectId: number): Promise<SourceFilesModel.Directory | undefined>;
|
|
13
|
-
export declare function applyDefaults(config: Config): void;
|
|
11
|
+
export declare function getOauthRoute(integration: IntegrationLogic): string;
|
|
12
|
+
export declare function getRootFolder(config: Config, integration: IntegrationLogic, client: Crowdin, projectId: number): Promise<SourceFilesModel.Directory | undefined>;
|
|
13
|
+
export declare function applyDefaults(config: Config, integration: IntegrationLogic): void;
|
|
14
14
|
export declare function prepareCrowdinClient(config: Config, credentials: CrowdinCredentials): Promise<Crowdin>;
|
|
15
|
-
export declare function prepareIntegrationCredentials(config: Config, integrationCredentials: IntegrationCredentials): Promise<any>;
|
|
16
|
-
export declare function runJob(config: Config, job: CronJob): Promise<void>;
|
|
15
|
+
export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
|
|
16
|
+
export declare function runJob(config: Config, integration: IntegrationLogic, job: CronJob): Promise<void>;
|
package/out/util/index.js
CHANGED
|
@@ -79,26 +79,26 @@ function decryptData(secret, data) {
|
|
|
79
79
|
return crypto.AES.decrypt(data, secret).toString(crypto.enc.Utf8);
|
|
80
80
|
}
|
|
81
81
|
exports.decryptData = decryptData;
|
|
82
|
-
function getOauthRoute(
|
|
82
|
+
function getOauthRoute(integration) {
|
|
83
83
|
var _a;
|
|
84
|
-
return ((_a =
|
|
84
|
+
return ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.redirectUriRoute) || '/oauth/code';
|
|
85
85
|
}
|
|
86
86
|
exports.getOauthRoute = getOauthRoute;
|
|
87
|
-
function getRootFolder(config, client, projectId) {
|
|
87
|
+
function getRootFolder(config, integration, client, projectId) {
|
|
88
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
-
if (!
|
|
89
|
+
if (!integration.withRootFolder) {
|
|
90
90
|
return;
|
|
91
91
|
}
|
|
92
|
-
const folder =
|
|
92
|
+
const folder = integration.appFolderName || config.name;
|
|
93
93
|
const directories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId)).data.map(d => d.data);
|
|
94
94
|
const { folder: rootFolder } = yield crowdinAppFunctions.getOrCreateFolder(directories, client, projectId, folder);
|
|
95
95
|
return rootFolder;
|
|
96
96
|
});
|
|
97
97
|
}
|
|
98
98
|
exports.getRootFolder = getRootFolder;
|
|
99
|
-
function applyDefaults(config) {
|
|
100
|
-
if (!
|
|
101
|
-
|
|
99
|
+
function applyDefaults(config, integration) {
|
|
100
|
+
if (!integration.getCrowdinFiles) {
|
|
101
|
+
integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
|
|
102
102
|
let allDirectories;
|
|
103
103
|
if (rootFolder) {
|
|
104
104
|
allDirectories = (yield client.sourceFilesApi
|
|
@@ -138,8 +138,8 @@ function applyDefaults(config) {
|
|
|
138
138
|
return res;
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
|
-
if (!
|
|
142
|
-
|
|
141
|
+
if (!integration.loginForm) {
|
|
142
|
+
integration.loginForm = {
|
|
143
143
|
fields: [
|
|
144
144
|
{
|
|
145
145
|
helpText: 'You need to create standard api key',
|
|
@@ -178,12 +178,12 @@ function prepareCrowdinClient(config, credentials) {
|
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
exports.prepareCrowdinClient = prepareCrowdinClient;
|
|
181
|
-
function prepareIntegrationCredentials(config, integrationCredentials) {
|
|
181
|
+
function prepareIntegrationCredentials(config, integration, integrationCredentials) {
|
|
182
182
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
183
183
|
return __awaiter(this, void 0, void 0, function* () {
|
|
184
184
|
const credentials = JSON.parse(decryptData(config.clientSecret, integrationCredentials.credentials));
|
|
185
|
-
if ((_a =
|
|
186
|
-
const oauthLogin =
|
|
185
|
+
if ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.refresh) {
|
|
186
|
+
const oauthLogin = integration.oauthLogin;
|
|
187
187
|
const { expireIn } = credentials;
|
|
188
188
|
//2 min as an extra buffer
|
|
189
189
|
const isExpired = expireIn + 120 < Date.now() / 1000;
|
|
@@ -218,7 +218,7 @@ function prepareIntegrationCredentials(config, integrationCredentials) {
|
|
|
218
218
|
});
|
|
219
219
|
}
|
|
220
220
|
exports.prepareIntegrationCredentials = prepareIntegrationCredentials;
|
|
221
|
-
function runJob(config, job) {
|
|
221
|
+
function runJob(config, integration, job) {
|
|
222
222
|
return __awaiter(this, void 0, void 0, function* () {
|
|
223
223
|
const crowdinCredentialsList = yield (0, storage_1.getAllCrowdinCredentials)();
|
|
224
224
|
yield Promise.all(crowdinCredentialsList.map((crowdinCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -226,8 +226,8 @@ function runJob(config, job) {
|
|
|
226
226
|
const integrationCredentialsList = yield (0, storage_1.getAllIntegrationCredentials)(crowdinCredentials.id);
|
|
227
227
|
yield Promise.all(integrationCredentialsList.map((integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
228
228
|
const projectId = crowdinAppFunctions.getProjectId(integrationCredentials.id);
|
|
229
|
-
const apiCredentials = yield prepareIntegrationCredentials(config, integrationCredentials);
|
|
230
|
-
const rootFolder = yield getRootFolder(config, crowdinClient, projectId);
|
|
229
|
+
const apiCredentials = yield prepareIntegrationCredentials(config, integration, integrationCredentials);
|
|
230
|
+
const rootFolder = yield getRootFolder(config, integration, crowdinClient, projectId);
|
|
231
231
|
const intConfig = integrationCredentials.config
|
|
232
232
|
? JSON.parse(integrationCredentials.config)
|
|
233
233
|
: undefined;
|
package/package.json
CHANGED