@crowdin/app-project-module 0.6.4 → 0.8.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 CHANGED
@@ -29,6 +29,8 @@ 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)
33
+ - [Custom MT](#custom-mt)
32
34
  - [Contributing](#contributing)
33
35
  - [Seeking Assistance](#seeking-assistance)
34
36
  - [License](#license)
@@ -153,7 +155,7 @@ By default login page for your app will require only to enter `apiToken` to com
153
155
  But there is also a possibility to customize it.
154
156
 
155
157
  ```javascript
156
- configuration.loginForm = {
158
+ configuration.integration.loginForm = {
157
159
  fields: [
158
160
  {
159
161
  key: 'username',
@@ -181,7 +183,7 @@ In case if third party service uses OAuth2 for authorization use `oauthLogin` fi
181
183
  Github example:
182
184
 
183
185
  ```javascript
184
- configuration.oauthLogin = {
186
+ configuration.integration.oauthLogin = {
185
187
  authorizationUrl: 'https://github.com/login/oauth/authorize',
186
188
  clientId: 'github_app_client_id',
187
189
  clientSecret: 'github_app_client_secret',
@@ -192,7 +194,7 @@ configuration.oauthLogin = {
192
194
  Google example:
193
195
 
194
196
  ```javascript
195
- configuration.oauthLogin = {
197
+ configuration.integration.oauthLogin = {
196
198
  scope: 'https%3A//www.googleapis.com/auth/userinfo.email',
197
199
  authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth',
198
200
  clientId: 'google_web_app_client_id',
@@ -239,7 +241,7 @@ const clientId = 'client_id';
239
241
  const clientSecret = 'client_secret';
240
242
  const tokenUrl = 'https://services.mailup.com/Authorization/OAuth/Token';
241
243
 
242
- configuration.oauthLogin = {
244
+ configuration.integration.oauthLogin = {
243
245
  authorizationUrl: 'https://services.mailup.com/Authorization/OAuth/LogOn',
244
246
  clientId,
245
247
  clientSecret,
@@ -374,6 +376,84 @@ configuration.integrartion.getIntegrationFiles = async (credentials, appSettings
374
376
  }
375
377
  ```
376
378
 
379
+ ## Custom File Format
380
+
381
+ Example of [custom file format module](https://support.crowdin.com/crowdin-apps-modules/#custom-file-format-module).
382
+
383
+ ```javascript
384
+ const crowdinModule = require('@crowdin/app-project-module');
385
+ const convert = require('xml-js');
386
+
387
+ const configuration = {
388
+ baseUrl: 'https://123.ngrok.io',
389
+ clientId: 'clientId',
390
+ clientSecret: 'clientSecret',
391
+ name: 'Sample App',
392
+ identifier: 'sample-app',
393
+ description: 'Sample App description',
394
+ dbFolder: __dirname,
395
+ imagePath: __dirname + '/' + 'logo.png',
396
+ customFileFormat: {
397
+ type: 'type-xyz',
398
+ multilingual: false,
399
+ signaturePatterns: {
400
+ fileName: '^.+\.xml$'
401
+ },
402
+ parseFile: async (file, req) => {
403
+ const xml = convert.xml2json(file, { compact: true, spaces: 4 });
404
+ const fileContent = JSON.parse(xml);
405
+ //parse logic
406
+ const strings = [];
407
+ return { strings };
408
+ },
409
+ buildFile: async (file, req, strings) => {
410
+ const xml = convert.xml2json(file, { compact: true, spaces: 4 });
411
+ const fileContent = JSON.parse(xml);
412
+ //build logic
413
+ const contentFile = convert.json2xml(
414
+ fileContent,
415
+ {
416
+ compact: true,
417
+ ignoreComment: false,
418
+ spaces: 4
419
+ }
420
+ );
421
+ return { contentFile }
422
+ }
423
+ }
424
+ };
425
+
426
+ crowdinModule.createApp(configuration);
427
+ ```
428
+
429
+ ## Custom MT (Machine Translation)
430
+
431
+ Example of [custom mt module](https://support.crowdin.com/crowdin-apps-modules/#custom-mt-machine-translation-module).
432
+
433
+ ```javascript
434
+ const crowdinModule = require('@crowdin/app-project-module');
435
+
436
+ const configuration = {
437
+ baseUrl: 'https://123.ngrok.io',
438
+ clientId: 'clientId',
439
+ clientSecret: 'clientSecret',
440
+ name: 'Sample App',
441
+ identifier: 'sample-app',
442
+ description: 'Sample App description',
443
+ dbFolder: __dirname,
444
+ imagePath: __dirname + '/' + 'logo.png',
445
+ customMT: {
446
+ translate: async (client, source, target, strings) => {
447
+ //translate strings
448
+ const translations = ['hello', 'world'];
449
+ return translations;
450
+ }
451
+ }
452
+ };
453
+
454
+ crowdinModule.createApp(configuration);
455
+ ```
456
+
377
457
  ## Contributing
378
458
 
379
459
  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 (config.integration.getCrowdinFiles) {
16
- const rootFolder = yield (0, util_1.getRootFolder)(config, req.crowdinApiClient, req.crowdinContext.jwtPayload.context.project_id);
17
- const files = config.integration.getCrowdinFiles
18
- ? yield config.integration.getCrowdinFiles(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, rootFolder, req.integrationSettings)
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 config.integration.updateCrowdin(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, req.integrationCredentials, req.body, rootFolder, req.integrationSettings);
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;
@@ -0,0 +1,4 @@
1
+ /// <reference types="qs" />
2
+ import { Response } from 'express';
3
+ import { CustomMTLogic } from '../../models';
4
+ export default function handle(config: CustomMTLogic): (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;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const util_1 = require("../../util");
13
+ function handle(config) {
14
+ return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
15
+ const source = req.query.source;
16
+ const target = req.query.target;
17
+ const body = req.body;
18
+ if (source === 'en' && target === 'de' && body.strings && body.strings[0] === 'validation') {
19
+ if (config.validate) {
20
+ yield config.validate(req.crowdinApiClient);
21
+ }
22
+ res.send({ data: { translations: [] } });
23
+ }
24
+ else {
25
+ const translations = yield config.translate(req.crowdinApiClient, source, target, body.strings);
26
+ res.send({ data: { translations } });
27
+ }
28
+ }));
29
+ }
30
+ exports.default = handle;
@@ -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 { 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(config) {
13
+ function handle(integration) {
14
14
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
15
- const files = yield config.integration.getIntegrationFiles(req.integrationCredentials, req.integrationSettings);
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 (config.integration.checkConnection) {
17
- yield config.integration.checkConnection(req.body.credentials);
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 config.integration.updateIntegration(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, req.integrationCredentials, req.body, rootFolder, req.integrationSettings);
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
  }
@@ -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 constructOauthUrl(config) {
13
+ function constructOauthUrl(config, integration) {
14
14
  var _a, _b, _c;
15
- const oauth = config.oauthLogin;
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)(config)}`;
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 = config.loginForm) === null || _a === void 0 ? void 0 : _a.fields;
42
- if (config.oauthLogin) {
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 (config.integration.getConfiguration) {
47
- const configurationFields = yield config.integration.getConfiguration(req.crowdinContext.jwtPayload.context.project_id, req.crowdinApiClient, req.integrationCredentials);
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 = config.integration.infoModal;
51
+ options.infoModal = integration.infoModal;
52
52
  return res.render(view, options);
53
53
  }));
54
54
  }
@@ -1,6 +1,37 @@
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
+ }
26
+ if (config.customMT) {
27
+ modules['custom-mt'] = [
28
+ {
29
+ key: config.identifier,
30
+ name: config.name,
31
+ url: '/translate',
32
+ },
33
+ ];
34
+ }
4
35
  return (_req, res) => {
5
36
  const manifest = {
6
37
  identifier: config.identifier,
@@ -16,17 +47,7 @@ function handle(config) {
16
47
  uninstall: '/uninstall',
17
48
  },
18
49
  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
- },
50
+ modules,
30
51
  };
31
52
  res.send(manifest);
32
53
  };
@@ -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 = config.oauthLogin) === null || _a === void 0 ? void 0 : _a.fieldsMapping) === null || _b === void 0 ? void 0 : _b.code) || 'code'];
21
- const oauthLogin = config.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 = config.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)(config)}`;
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 = config.oauthLogin) === null || _g === void 0 ? void 0 : _g.accessTokenUrl) || '', request, {
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 = __importStar(require("express"));
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,9 @@ 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"));
36
+ const translate_1 = __importDefault(require("./handlers/custom-mt/translate"));
34
37
  const install_1 = __importDefault(require("./handlers/install"));
35
38
  const integration_data_1 = __importDefault(require("./handlers/integration-data"));
36
39
  const integration_login_1 = __importDefault(require("./handlers/integration-login"));
@@ -47,9 +50,8 @@ const json_response_1 = __importDefault(require("./middlewares/json-response"));
47
50
  const storage_1 = require("./storage");
48
51
  const util_1 = require("./util");
49
52
  function addCrowdinEndpoints(app, config) {
50
- (0, util_1.applyDefaults)(config);
51
53
  (0, storage_1.connect)(config.dbFolder);
52
- app.use((0, express_1.json)());
54
+ app.use(express_1.default.json({ limit: '50mb' }));
53
55
  app.use('/assets', express_1.default.static((0, path_1.join)(__dirname, 'static')));
54
56
  app.set('views', (0, path_1.join)(__dirname, 'views'));
55
57
  app.engine('handlebars', (0, express_handlebars_1.default)({
@@ -66,26 +68,37 @@ function addCrowdinEndpoints(app, config) {
66
68
  }));
67
69
  app.set('view engine', 'handlebars');
68
70
  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
71
  app.post('/installed', (0, install_1.default)(config));
75
72
  app.post('/uninstall', (0, uninstall_1.default)());
76
- app.post('/api/settings', (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config), (0, settings_save_1.default)());
77
- app.post('/api/login', (0, crowdin_client_1.default)(config), (0, integration_login_1.default)(config));
78
- app.post('/api/logout', (0, crowdin_client_1.default)(config), (0, integration_logout_1.default)());
79
- app.get('/api/crowdin/files', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config), (0, crowdin_files_1.default)(config));
80
- app.get('/api/crowdin/project', json_response_1.default, (0, crowdin_client_1.default)(config), (0, crowdin_project_1.default)());
81
- app.get('/api/crowdin/file-progress/:fileId', (0, crowdin_client_1.default)(config), (0, crowdin_file_progress_1.default)());
82
- app.get('/api/integration/data', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config), (0, integration_data_1.default)(config));
83
- app.post('/api/crowdin/update', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config), (0, crowdin_update_1.default)(config));
84
- app.post('/api/integration/update', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config), (0, integration_update_1.default)(config));
85
- if (config.integration.cronJobs) {
86
- config.integration.cronJobs.forEach(job => {
87
- cron.schedule(job.expression, () => (0, util_1.runJob)(config, job).catch(console.error));
88
- });
73
+ app.get('/manifest.json', json_response_1.default, (0, manifest_1.default)(config));
74
+ const integrationLogic = config.integration;
75
+ if (integrationLogic) {
76
+ (0, util_1.applyDefaults)(config, integrationLogic);
77
+ app.get('/', (0, crowdin_client_1.default)(config, true), (0, integration_credentials_1.default)(config, integrationLogic, true), (0, main_1.default)(config, integrationLogic));
78
+ app.post('/api/settings', (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, settings_save_1.default)());
79
+ app.post('/api/login', (0, crowdin_client_1.default)(config), (0, integration_login_1.default)(config, integrationLogic));
80
+ app.post('/api/logout', (0, crowdin_client_1.default)(config), (0, integration_logout_1.default)());
81
+ 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));
82
+ app.get('/api/crowdin/project', json_response_1.default, (0, crowdin_client_1.default)(config), (0, crowdin_project_1.default)());
83
+ app.get('/api/crowdin/file-progress/:fileId', (0, crowdin_client_1.default)(config), (0, crowdin_file_progress_1.default)());
84
+ 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));
85
+ 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));
86
+ 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));
87
+ if (integrationLogic.oauthLogin) {
88
+ app.get((0, util_1.getOauthRoute)(integrationLogic), (0, oauth_login_1.default)(config, integrationLogic));
89
+ }
90
+ if (integrationLogic.cronJobs) {
91
+ integrationLogic.cronJobs.forEach(job => {
92
+ cron.schedule(job.expression, () => (0, util_1.runJob)(config, integrationLogic, job).catch(console.error));
93
+ });
94
+ }
95
+ }
96
+ if (config.customFileFormat) {
97
+ app.post('/process', (0, process_1.default)(config.baseUrl, config.customFileFormat.filesFolder || config.dbFolder, config.customFileFormat));
98
+ app.get('/file/download', (0, download_1.default)(config.customFileFormat.filesFolder || config.dbFolder));
99
+ }
100
+ if (config.customMT) {
101
+ app.post('/translate', (0, crowdin_client_1.default)(config), (0, translate_1.default)(config.customMT));
89
102
  }
90
103
  }
91
104
  exports.addCrowdinEndpoints = addCrowdinEndpoints;
@@ -14,10 +14,8 @@ const storage_1 = require("../storage");
14
14
  const util_1 = require("../util");
15
15
  function handle(config, optional = false) {
16
16
  return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
17
- const origin = req.query.origin;
18
- const clientId = req.query.client_id;
19
- const tokenJwt = req.query.tokenJwt;
20
- if (!origin || !clientId || !tokenJwt || clientId !== config.clientId) {
17
+ const tokenJwt = (req.query.tokenJwt || req.query.jwtToken);
18
+ if (!tokenJwt) {
21
19
  return res.status(403).send({ error: 'Access denied' });
22
20
  }
23
21
  try {
@@ -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);
@@ -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,19 @@ export interface Config {
39
39
  */
40
40
  imagePath?: string;
41
41
  /**
42
- * integration logic
42
+ * integration module logic
43
43
  */
44
- integration: IntegrationLogic;
44
+ integration?: IntegrationLogic;
45
+ /**
46
+ * custom file format module logic
47
+ */
48
+ customFileFormat?: CustomFileFormatLogic;
49
+ /**
50
+ * custom MT module logic
51
+ */
52
+ customMT?: CustomMTLogic;
53
+ }
54
+ export interface IntegrationLogic {
45
55
  /**
46
56
  * Customize your app login form
47
57
  */
@@ -50,8 +60,6 @@ export interface Config {
50
60
  * Define login process via OAuth2 protocol
51
61
  */
52
62
  oauthLogin?: OAuthLogin;
53
- }
54
- export interface IntegrationLogic {
55
63
  /**
56
64
  * 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
65
  */
@@ -275,3 +283,76 @@ export interface CronJob {
275
283
  task: (projectId: number, client: Crowdin, apiCredentials: any, appRootFolder?: SourceFilesModel.Directory, config?: any) => Promise<void>;
276
284
  expression: string;
277
285
  }
286
+ export interface CustomFileFormatLogic {
287
+ /**
288
+ * The type parameter value for a custom file format. Used for a custom format file upload via API.
289
+ */
290
+ type: string;
291
+ /**
292
+ * Folder where larger file will be temporary stored (default "{@link dbFolder}/custom-file-format")
293
+ */
294
+ filesFolder?: string;
295
+ /**
296
+ * This parameter is used to combine the content of multiple languages into one request when uploading and downloading translations in your Crowdin project.
297
+ */
298
+ multilingual?: boolean;
299
+ /**
300
+ * 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.
301
+ */
302
+ signaturePatterns?: SignaturePatterns;
303
+ /**
304
+ * Used for initial source file upload, source file update, and translation upload
305
+ */
306
+ parseFile: (fileContent: string | object, req: Omit<ProcessFileRequest, 'jobType' | 'file'>) => Promise<ParseFileResponse>;
307
+ /**
308
+ * Used for translation download
309
+ */
310
+ buildFile: (fileContent: string | object, req: Omit<ProcessFileRequest, 'jobType' | 'file'>, strings: ProcessFileString[]) => Promise<BuildFileResponse>;
311
+ }
312
+ export interface SignaturePatterns {
313
+ fileName?: string;
314
+ fileContent?: string;
315
+ }
316
+ export interface ProcessFileRequest {
317
+ jobType: ProcessFileJobType;
318
+ file: ProcessFileRecord;
319
+ sourceLanguage: LanguagesModel.Language;
320
+ targetLanguages: LanguagesModel.Language[];
321
+ strings: ProcessFileString[];
322
+ stringsUrl: string;
323
+ }
324
+ export interface ProcessFileRecord {
325
+ content?: string;
326
+ contentUrl?: string;
327
+ }
328
+ export declare enum ProcessFileJobType {
329
+ PARSE_FILE = "parse-file",
330
+ BUILD_FILE = "build-file"
331
+ }
332
+ export interface ParseFileResponse {
333
+ previewFile?: string;
334
+ strings?: ProcessFileString[];
335
+ }
336
+ export interface BuildFileResponse {
337
+ contentFile: string;
338
+ }
339
+ export interface ProcessFileString {
340
+ previewId?: number;
341
+ id: number;
342
+ identifier: string;
343
+ context?: string;
344
+ customData?: string;
345
+ maxLength?: number;
346
+ isHidden?: boolean;
347
+ hasPlurals?: boolean;
348
+ labels?: string[];
349
+ text: string | SourceStringsModel.PluralText;
350
+ translations?: any;
351
+ }
352
+ export interface CustomMTLogic {
353
+ translate: (client: Crowdin, source: string, target: string, strings: string[]) => Promise<string[]>;
354
+ validate?: (client: Crowdin) => Promise<void>;
355
+ }
356
+ export interface CustomMTRequest {
357
+ strings: string[];
358
+ }
@@ -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 = {}));
@@ -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(config: Config): string;
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(config) {
82
+ function getOauthRoute(integration) {
83
83
  var _a;
84
- return ((_a = config.oauthLogin) === null || _a === void 0 ? void 0 : _a.redirectUriRoute) || '/oauth/code';
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 (!config.integration.withRootFolder) {
89
+ if (!integration.withRootFolder) {
90
90
  return;
91
91
  }
92
- const folder = config.integration.appFolderName || config.name;
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 (!config.integration.getCrowdinFiles) {
101
- config.integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
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 (!config.loginForm) {
142
- config.loginForm = {
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 = config.oauthLogin) === null || _a === void 0 ? void 0 : _a.refresh) {
186
- const oauthLogin = config.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.6.4",
3
+ "version": "0.8.0",
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",