@crowdin/app-project-module 0.6.3 → 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 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 (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;
@@ -24,7 +24,13 @@ function handle(config) {
24
24
  expire: (new Date().getTime() / 1000 + token.expiresIn).toString(),
25
25
  type: event.domain ? models_1.AccountType.ENTERPRISE : models_1.AccountType.NORMAL,
26
26
  };
27
- yield (0, storage_1.saveCrowdinCredentials)(credentials);
27
+ const existingCredentials = yield (0, storage_1.getCrowdinCredentials)(credentials.id);
28
+ if (!!existingCredentials) {
29
+ yield (0, storage_1.updateCrowdinCredentials)(credentials);
30
+ }
31
+ else {
32
+ yield (0, storage_1.saveCrowdinCredentials)(credentials);
33
+ }
28
34
  res.status(204).end();
29
35
  }));
30
36
  }
@@ -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,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 = 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,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((0, express_1.json)());
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.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
- });
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);
@@ -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: IntegrationLogic;
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
+ }
@@ -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.3",
3
+ "version": "0.7.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",