@crowdin/app-project-module 0.8.0 → 0.10.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 +128 -2
- package/out/handlers/custom-mt/translate.js +2 -1
- package/out/handlers/manifest.js +63 -3
- package/out/handlers/uninstall.d.ts +2 -1
- package/out/handlers/uninstall.js +6 -2
- package/out/index.d.ts +2 -2
- package/out/index.js +42 -4
- package/out/middlewares/crowdin-client.d.ts +6 -1
- package/out/middlewares/crowdin-client.js +34 -14
- package/out/models/index.d.ts +56 -1
- package/out/models/index.js +8 -1
- package/out/storage/index.d.ts +4 -0
- package/out/storage/index.js +31 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,6 +11,13 @@ Module expose two main methods:
|
|
|
11
11
|
|
|
12
12
|
In both options you will need to provide Crowdin App configuration file. Please refer to jsdoc for more details.
|
|
13
13
|
|
|
14
|
+
`addCrowdinEndpoints` will return an object with several methods to help you add your own custom logic [see example](#resources).
|
|
15
|
+
|
|
16
|
+
- `saveMetadata` to save metadata (may be associated with an organization, project, etc)
|
|
17
|
+
- `getMetadata` to get metadata
|
|
18
|
+
- `deleteMetadata` to delete metadata (usually useful in `onUninstall` hook)
|
|
19
|
+
- `establishCrowdinConnection` method that accept jwt token that you may forward from module UI and it will return back Crowdin client instance and the context.
|
|
20
|
+
|
|
14
21
|
## Status
|
|
15
22
|
|
|
16
23
|
[](https://www.npmjs.com/package/@crowdin/app-project-module)
|
|
@@ -31,6 +38,8 @@ In both options you will need to provide Crowdin App configuration file. Please
|
|
|
31
38
|
- [Error propagation](#error-propagation)
|
|
32
39
|
- [Custom File Format](#custom-file-format)
|
|
33
40
|
- [Custom MT](#custom-mt)
|
|
41
|
+
- [Resources](#resources)
|
|
42
|
+
- [Other modules](#other-modules)
|
|
34
43
|
- [Contributing](#contributing)
|
|
35
44
|
- [Seeking Assistance](#seeking-assistance)
|
|
36
45
|
- [License](#license)
|
|
@@ -426,7 +435,7 @@ const configuration = {
|
|
|
426
435
|
crowdinModule.createApp(configuration);
|
|
427
436
|
```
|
|
428
437
|
|
|
429
|
-
## Custom MT
|
|
438
|
+
## Custom MT
|
|
430
439
|
|
|
431
440
|
Example of [custom mt module](https://support.crowdin.com/crowdin-apps-modules/#custom-mt-machine-translation-module).
|
|
432
441
|
|
|
@@ -443,7 +452,7 @@ const configuration = {
|
|
|
443
452
|
dbFolder: __dirname,
|
|
444
453
|
imagePath: __dirname + '/' + 'logo.png',
|
|
445
454
|
customMT: {
|
|
446
|
-
translate: async (client, source, target, strings) => {
|
|
455
|
+
translate: async (client, context, projectId, source, target, strings) => {
|
|
447
456
|
//translate strings
|
|
448
457
|
const translations = ['hello', 'world'];
|
|
449
458
|
return translations;
|
|
@@ -454,6 +463,123 @@ const configuration = {
|
|
|
454
463
|
crowdinModule.createApp(configuration);
|
|
455
464
|
```
|
|
456
465
|
|
|
466
|
+
## Resources
|
|
467
|
+
|
|
468
|
+
Example of [resources module](https://support.crowdin.com/crowdin-apps-modules/#resources-module).
|
|
469
|
+
|
|
470
|
+
```javascript
|
|
471
|
+
const crowdinModule = require('@crowdin/app-project-module');
|
|
472
|
+
|
|
473
|
+
const configuration = {
|
|
474
|
+
baseUrl: 'https://123.ngrok.io',
|
|
475
|
+
clientId: 'clientId',
|
|
476
|
+
clientSecret: 'clientSecret',
|
|
477
|
+
name: 'Sample App',
|
|
478
|
+
identifier: 'sample-app',
|
|
479
|
+
description: 'Sample App description',
|
|
480
|
+
dbFolder: __dirname,
|
|
481
|
+
imagePath: __dirname + '/' + 'logo.png',
|
|
482
|
+
resources: {
|
|
483
|
+
fileName: 'setup.html',
|
|
484
|
+
uiPath: __dirname + '/' + 'public'
|
|
485
|
+
},
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
crowdinModule.createApp(configuration);
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
The resources module can work as an extension to other modules be something like a configuration UI for them.
|
|
492
|
+
|
|
493
|
+
```javascript
|
|
494
|
+
const crowdinModule = require('@crowdin/app-project-module');
|
|
495
|
+
const express = require('express');
|
|
496
|
+
|
|
497
|
+
const app = express();
|
|
498
|
+
|
|
499
|
+
const configuration = {
|
|
500
|
+
baseUrl: 'https://123.ngrok.io',
|
|
501
|
+
clientId: 'clientId',
|
|
502
|
+
clientSecret: 'clientSecret',
|
|
503
|
+
name: 'Sample App',
|
|
504
|
+
identifier: 'sample-app',
|
|
505
|
+
description: 'Sample App description',
|
|
506
|
+
dbFolder: __dirname,
|
|
507
|
+
imagePath: __dirname + '/' + 'logo.png',
|
|
508
|
+
resources: {
|
|
509
|
+
fileName: 'setup.html',
|
|
510
|
+
uiPath: __dirname + '/' + 'public'
|
|
511
|
+
},
|
|
512
|
+
customMT: {
|
|
513
|
+
translate,
|
|
514
|
+
},
|
|
515
|
+
onUninstall: cleanup
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
const crowdinApp = crowdinModule.addCrowdinEndpoints(app, configuration);
|
|
519
|
+
|
|
520
|
+
async function cleanup(organization) {
|
|
521
|
+
await crowdinApp.deleteMetadata(organization);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
async function translate(crowdinClient, context, projectId, source, target, strings) {
|
|
525
|
+
const organization = context.jwtPayload.domain || context.jwtPayload.context.organization_id;
|
|
526
|
+
const metadata = await crowdinApp.getMetadata(organization);
|
|
527
|
+
//do translation based on metadata
|
|
528
|
+
const translations = ['hello', 'world'];
|
|
529
|
+
return translations;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
//extra endpoints for resources UI
|
|
533
|
+
app.post('/metadata', async (req, res) => {
|
|
534
|
+
const { context } = await crowdinApp.establishCrowdinConnection(req.query.jwt);
|
|
535
|
+
const organization = context.jwtPayload.domain || context.jwtPayload.context.organization_id;
|
|
536
|
+
const metadata = await crowdinApp.getMetadata(organization);
|
|
537
|
+
await crowdinApp.saveMetadata(organization, req.body);
|
|
538
|
+
res.status(204).end();
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
app.get('/metadata', async (req, res) => {
|
|
542
|
+
const { context } = await crowdinApp.establishCrowdinConnection(req.query.jwt);
|
|
543
|
+
const organization = context.jwtPayload.domain || context.jwtPayload.context.organization_id;
|
|
544
|
+
const metadata = await crowdinApp.getMetadata(organization) || {};
|
|
545
|
+
res.status(200).send(metadata);
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
app.listen(3000, () => console.log('Crowdin app started'));
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## Other modules
|
|
552
|
+
|
|
553
|
+
Framework also supports following modules:
|
|
554
|
+
|
|
555
|
+
- [editor-panels module](https://support.crowdin.com/crowdin-apps-modules/#editor-panels-module)
|
|
556
|
+
- [project menu module](https://support.crowdin.com/crowdin-apps-modules/#project-menu-module)
|
|
557
|
+
- [tools module](https://support.crowdin.com/crowdin-apps-modules/#tools-module)
|
|
558
|
+
- [reports module](https://support.crowdin.com/crowdin-apps-modules/#reports-module)
|
|
559
|
+
|
|
560
|
+
Example of Reports Module:
|
|
561
|
+
|
|
562
|
+
```javascript
|
|
563
|
+
const crowdinModule = require('@crowdin/app-project-module');
|
|
564
|
+
|
|
565
|
+
const configuration = {
|
|
566
|
+
baseUrl: 'https://123.ngrok.io',
|
|
567
|
+
clientId: 'clientId',
|
|
568
|
+
clientSecret: 'clientSecret',
|
|
569
|
+
name: 'Sample App',
|
|
570
|
+
identifier: 'sample-app',
|
|
571
|
+
description: 'Sample App description',
|
|
572
|
+
dbFolder: __dirname,
|
|
573
|
+
imagePath: __dirname + '/' + 'logo.png',
|
|
574
|
+
reports: {
|
|
575
|
+
fileName: 'reports.html', //optional, only needed if file is not index.html
|
|
576
|
+
uiPath: __dirname + '/' + 'public' // folder where UI of the module is located (js, html, css files)
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
crowdinModule.createApp(configuration);
|
|
581
|
+
```
|
|
582
|
+
|
|
457
583
|
## Contributing
|
|
458
584
|
|
|
459
585
|
If you want to contribute please read the [Contributing](/CONTRIBUTING.md) guidelines.
|
|
@@ -15,6 +15,7 @@ function handle(config) {
|
|
|
15
15
|
const source = req.query.source;
|
|
16
16
|
const target = req.query.target;
|
|
17
17
|
const body = req.body;
|
|
18
|
+
const projectId = Number(req.query.project_id);
|
|
18
19
|
if (source === 'en' && target === 'de' && body.strings && body.strings[0] === 'validation') {
|
|
19
20
|
if (config.validate) {
|
|
20
21
|
yield config.validate(req.crowdinApiClient);
|
|
@@ -22,7 +23,7 @@ function handle(config) {
|
|
|
22
23
|
res.send({ data: { translations: [] } });
|
|
23
24
|
}
|
|
24
25
|
else {
|
|
25
|
-
const translations = yield config.translate(req.crowdinApiClient, source, target, body.strings);
|
|
26
|
+
const translations = yield config.translate(req.crowdinApiClient, req.crowdinContext, projectId, source, target, body.strings);
|
|
26
27
|
res.send({ data: { translations } });
|
|
27
28
|
}
|
|
28
29
|
}));
|
package/out/handlers/manifest.js
CHANGED
|
@@ -5,7 +5,7 @@ function handle(config) {
|
|
|
5
5
|
if (config.integration) {
|
|
6
6
|
modules.integrations = [
|
|
7
7
|
{
|
|
8
|
-
key: config.identifier,
|
|
8
|
+
key: config.identifier + '-int',
|
|
9
9
|
name: config.name,
|
|
10
10
|
description: config.description,
|
|
11
11
|
logo: '/logo.png',
|
|
@@ -16,7 +16,7 @@ function handle(config) {
|
|
|
16
16
|
if (config.customFileFormat) {
|
|
17
17
|
modules['custom-file-format'] = [
|
|
18
18
|
{
|
|
19
|
-
key: config.identifier,
|
|
19
|
+
key: config.identifier + '-ff',
|
|
20
20
|
type: config.customFileFormat.type,
|
|
21
21
|
signaturePatterns: config.customFileFormat.signaturePatterns,
|
|
22
22
|
url: '/process',
|
|
@@ -26,12 +26,72 @@ function handle(config) {
|
|
|
26
26
|
if (config.customMT) {
|
|
27
27
|
modules['custom-mt'] = [
|
|
28
28
|
{
|
|
29
|
-
key: config.identifier,
|
|
29
|
+
key: config.identifier + '-mt',
|
|
30
30
|
name: config.name,
|
|
31
31
|
url: '/translate',
|
|
32
32
|
},
|
|
33
33
|
];
|
|
34
34
|
}
|
|
35
|
+
if (config.resources) {
|
|
36
|
+
modules['organization-menu'] = [
|
|
37
|
+
{
|
|
38
|
+
key: config.identifier + '-resources',
|
|
39
|
+
name: config.name,
|
|
40
|
+
url: '/resources/' + (config.resources.fileName || 'index.html'),
|
|
41
|
+
icon: '/logo.png',
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
modules['resources'] = [
|
|
45
|
+
{
|
|
46
|
+
key: config.identifier + '-resources',
|
|
47
|
+
name: config.name,
|
|
48
|
+
url: '/resources/' + (config.resources.fileName || 'index.html'),
|
|
49
|
+
icon: '/logo.png',
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
if (config.editorPanels) {
|
|
54
|
+
modules['editor-panels'] = [
|
|
55
|
+
{
|
|
56
|
+
key: config.identifier + '-editor-panels',
|
|
57
|
+
name: config.name,
|
|
58
|
+
position: 'right',
|
|
59
|
+
url: '/editor-panels/' + (config.editorPanels.fileName || 'index.html'),
|
|
60
|
+
modes: config.editorPanels.modes,
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
if (config.projectMenu) {
|
|
65
|
+
modules['project-menu'] = [
|
|
66
|
+
{
|
|
67
|
+
key: config.identifier + '-project-menu',
|
|
68
|
+
name: config.name,
|
|
69
|
+
url: '/project-menu/' + (config.projectMenu.fileName || 'index.html'),
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
if (config.tools) {
|
|
74
|
+
modules['tools'] = [
|
|
75
|
+
{
|
|
76
|
+
key: config.identifier + '-tools',
|
|
77
|
+
name: config.name,
|
|
78
|
+
description: config.description,
|
|
79
|
+
logo: '/logo.png',
|
|
80
|
+
icon: '/logo.png',
|
|
81
|
+
url: '/tools/' + (config.tools.fileName || 'index.html'),
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
if (config.reports) {
|
|
86
|
+
modules['reports'] = [
|
|
87
|
+
{
|
|
88
|
+
key: config.identifier + '-reports',
|
|
89
|
+
name: config.name,
|
|
90
|
+
description: config.description,
|
|
91
|
+
url: '/reports/' + (config.reports.fileName || 'index.html'),
|
|
92
|
+
},
|
|
93
|
+
];
|
|
94
|
+
}
|
|
35
95
|
return (_req, res) => {
|
|
36
96
|
const manifest = {
|
|
37
97
|
identifier: config.identifier,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import { Request, Response } from 'express';
|
|
3
|
-
|
|
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;
|
|
@@ -11,10 +11,14 @@ 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() {
|
|
14
|
+
function handle(config) {
|
|
15
15
|
return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
16
16
|
const event = req.body;
|
|
17
|
-
|
|
17
|
+
const organization = (event.domain || event.organizationId).toString();
|
|
18
|
+
yield (0, storage_1.deleteCrowdinCredentials)(organization);
|
|
19
|
+
if (config.onUninstall) {
|
|
20
|
+
yield config.onUninstall(organization);
|
|
21
|
+
}
|
|
18
22
|
res.status(204).end();
|
|
19
23
|
}));
|
|
20
24
|
}
|
package/out/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Express } from 'express';
|
|
2
|
-
import { Config } from './models';
|
|
3
|
-
export declare function addCrowdinEndpoints(app: Express, config: Config):
|
|
2
|
+
import { Config, CrowdinAppUtilities } from './models';
|
|
3
|
+
export declare function addCrowdinEndpoints(app: Express, config: Config): CrowdinAppUtilities;
|
|
4
4
|
export declare function createApp(config: Config): void;
|
package/out/index.js
CHANGED
|
@@ -18,6 +18,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
18
|
__setModuleDefault(result, mod);
|
|
19
19
|
return result;
|
|
20
20
|
};
|
|
21
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
22
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
23
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
24
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
25
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
26
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
21
30
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
32
|
};
|
|
@@ -44,13 +53,13 @@ const manifest_1 = __importDefault(require("./handlers/manifest"));
|
|
|
44
53
|
const oauth_login_1 = __importDefault(require("./handlers/oauth-login"));
|
|
45
54
|
const settings_save_1 = __importDefault(require("./handlers/settings-save"));
|
|
46
55
|
const uninstall_1 = __importDefault(require("./handlers/uninstall"));
|
|
47
|
-
const crowdin_client_1 =
|
|
56
|
+
const crowdin_client_1 = __importStar(require("./middlewares/crowdin-client"));
|
|
48
57
|
const integration_credentials_1 = __importDefault(require("./middlewares/integration-credentials"));
|
|
49
58
|
const json_response_1 = __importDefault(require("./middlewares/json-response"));
|
|
50
|
-
const
|
|
59
|
+
const storage = __importStar(require("./storage"));
|
|
51
60
|
const util_1 = require("./util");
|
|
52
61
|
function addCrowdinEndpoints(app, config) {
|
|
53
|
-
|
|
62
|
+
storage.connect(config.dbFolder);
|
|
54
63
|
app.use(express_1.default.json({ limit: '50mb' }));
|
|
55
64
|
app.use('/assets', express_1.default.static((0, path_1.join)(__dirname, 'static')));
|
|
56
65
|
app.set('views', (0, path_1.join)(__dirname, 'views'));
|
|
@@ -69,7 +78,7 @@ function addCrowdinEndpoints(app, config) {
|
|
|
69
78
|
app.set('view engine', 'handlebars');
|
|
70
79
|
app.get('/logo.png', (req, res) => res.sendFile(config.imagePath || (0, path_1.join)(__dirname, 'logo.png')));
|
|
71
80
|
app.post('/installed', (0, install_1.default)(config));
|
|
72
|
-
app.post('/uninstall', (0, uninstall_1.default)());
|
|
81
|
+
app.post('/uninstall', (0, uninstall_1.default)(config));
|
|
73
82
|
app.get('/manifest.json', json_response_1.default, (0, manifest_1.default)(config));
|
|
74
83
|
const integrationLogic = config.integration;
|
|
75
84
|
if (integrationLogic) {
|
|
@@ -100,6 +109,35 @@ function addCrowdinEndpoints(app, config) {
|
|
|
100
109
|
if (config.customMT) {
|
|
101
110
|
app.post('/translate', (0, crowdin_client_1.default)(config), (0, translate_1.default)(config.customMT));
|
|
102
111
|
}
|
|
112
|
+
if (config.resources) {
|
|
113
|
+
app.use('/resources', express_1.default.static(config.resources.uiPath));
|
|
114
|
+
}
|
|
115
|
+
if (config.editorPanels) {
|
|
116
|
+
app.use('/editor-panels', express_1.default.static(config.editorPanels.uiPath));
|
|
117
|
+
}
|
|
118
|
+
if (config.projectMenu) {
|
|
119
|
+
app.use('/project-menu', express_1.default.static(config.projectMenu.uiPath));
|
|
120
|
+
}
|
|
121
|
+
if (config.tools) {
|
|
122
|
+
app.use('/tools', express_1.default.static(config.tools.uiPath));
|
|
123
|
+
}
|
|
124
|
+
if (config.reports) {
|
|
125
|
+
app.use('/reports', express_1.default.static(config.reports.uiPath));
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
getMetadata: storage.getMetadata,
|
|
129
|
+
saveMetadata: (id, metadata) => __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
const existing = yield storage.getMetadata(id);
|
|
131
|
+
if (existing) {
|
|
132
|
+
yield storage.updateMetadata(id, metadata);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
yield storage.saveMetadata(id, metadata);
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
deleteMetadata: storage.deleteMetadata,
|
|
139
|
+
establishCrowdinConnection: jwtToken => (0, crowdin_client_1.prepareCrowdinRequest)(jwtToken, config),
|
|
140
|
+
};
|
|
103
141
|
}
|
|
104
142
|
exports.addCrowdinEndpoints = addCrowdinEndpoints;
|
|
105
143
|
function createApp(config) {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
3
|
import { Response } from 'express';
|
|
3
|
-
import { Config } from '../models';
|
|
4
|
+
import { Config, CrowdinContextInfo } from '../models';
|
|
5
|
+
export declare function prepareCrowdinRequest(jwtToken: string, config: Config, optional?: boolean): Promise<{
|
|
6
|
+
context: CrowdinContextInfo;
|
|
7
|
+
client?: Crowdin;
|
|
8
|
+
}>;
|
|
4
9
|
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;
|
|
@@ -9,40 +9,60 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.prepareCrowdinRequest = void 0;
|
|
12
13
|
const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
|
|
13
14
|
const storage_1 = require("../storage");
|
|
14
15
|
const util_1 = require("../util");
|
|
15
|
-
function
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return res.status(403).send({ error: 'Access denied' });
|
|
20
|
-
}
|
|
16
|
+
function prepareCrowdinRequest(jwtToken, config, optional = false) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
let context;
|
|
19
|
+
let client;
|
|
21
20
|
try {
|
|
22
|
-
const jwtPayload = yield (0, crowdin_apps_functions_1.validateJwtToken)(
|
|
23
|
-
|
|
21
|
+
const jwtPayload = yield (0, crowdin_apps_functions_1.validateJwtToken)(jwtToken, config.clientSecret);
|
|
22
|
+
context = {
|
|
24
23
|
jwtPayload,
|
|
25
24
|
clientId: (0, crowdin_apps_functions_1.constructCrowdinIdFromJwtPayload)(jwtPayload),
|
|
26
25
|
crowdinId: `${jwtPayload.domain || jwtPayload.context.organization_id}`,
|
|
27
26
|
};
|
|
28
27
|
}
|
|
29
28
|
catch (e) {
|
|
30
|
-
|
|
29
|
+
throw new Error("Can't verify");
|
|
31
30
|
}
|
|
32
31
|
try {
|
|
33
|
-
const credentials = yield (0, storage_1.getCrowdinCredentials)(
|
|
32
|
+
const credentials = yield (0, storage_1.getCrowdinCredentials)(context.crowdinId);
|
|
34
33
|
if (!credentials) {
|
|
35
34
|
if (optional) {
|
|
36
|
-
return
|
|
35
|
+
return { context };
|
|
37
36
|
}
|
|
38
|
-
|
|
37
|
+
throw new Error("Can't find organization by id");
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
next();
|
|
39
|
+
client = yield (0, util_1.prepareCrowdinClient)(config, credentials);
|
|
42
40
|
}
|
|
43
41
|
catch (e) {
|
|
42
|
+
throw new Error('Access denied');
|
|
43
|
+
}
|
|
44
|
+
return { context, client };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
exports.prepareCrowdinRequest = prepareCrowdinRequest;
|
|
48
|
+
function handle(config, optional = false) {
|
|
49
|
+
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const tokenJwt = (req.query.tokenJwt || req.query.jwtToken);
|
|
51
|
+
if (!tokenJwt) {
|
|
44
52
|
return res.status(403).send({ error: 'Access denied' });
|
|
45
53
|
}
|
|
54
|
+
try {
|
|
55
|
+
const data = yield prepareCrowdinRequest(tokenJwt, config, optional);
|
|
56
|
+
req.crowdinContext = data.context;
|
|
57
|
+
if (data.client) {
|
|
58
|
+
req.crowdinApiClient = data.client;
|
|
59
|
+
}
|
|
60
|
+
next();
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
const message = typeof e === 'string' ? e : e.message;
|
|
64
|
+
return res.status(403).send({ error: message || 'Error' });
|
|
65
|
+
}
|
|
46
66
|
}));
|
|
47
67
|
}
|
|
48
68
|
exports.default = handle;
|
package/out/models/index.d.ts
CHANGED
|
@@ -50,6 +50,30 @@ export interface Config {
|
|
|
50
50
|
* custom MT module logic
|
|
51
51
|
*/
|
|
52
52
|
customMT?: CustomMTLogic;
|
|
53
|
+
/**
|
|
54
|
+
* resources module
|
|
55
|
+
*/
|
|
56
|
+
resources?: UiModule;
|
|
57
|
+
/**
|
|
58
|
+
* editor-panels module
|
|
59
|
+
*/
|
|
60
|
+
editorPanels?: EditorPanels;
|
|
61
|
+
/**
|
|
62
|
+
* project menu module
|
|
63
|
+
*/
|
|
64
|
+
projectMenu?: UiModule;
|
|
65
|
+
/**
|
|
66
|
+
* tools module
|
|
67
|
+
*/
|
|
68
|
+
tools?: UiModule;
|
|
69
|
+
/**
|
|
70
|
+
* reports module
|
|
71
|
+
*/
|
|
72
|
+
reports?: UiModule;
|
|
73
|
+
/**
|
|
74
|
+
* Uninstall hook for cleanup logic
|
|
75
|
+
*/
|
|
76
|
+
onUninstall?: (organization: string) => Promise<void>;
|
|
53
77
|
}
|
|
54
78
|
export interface IntegrationLogic {
|
|
55
79
|
/**
|
|
@@ -350,9 +374,40 @@ export interface ProcessFileString {
|
|
|
350
374
|
translations?: any;
|
|
351
375
|
}
|
|
352
376
|
export interface CustomMTLogic {
|
|
353
|
-
translate: (client: Crowdin, source: string, target: string, strings: string[]) => Promise<string[]>;
|
|
377
|
+
translate: (client: Crowdin, context: CrowdinContextInfo, projectId: number, source: string, target: string, strings: string[]) => Promise<string[]>;
|
|
354
378
|
validate?: (client: Crowdin) => Promise<void>;
|
|
355
379
|
}
|
|
356
380
|
export interface CustomMTRequest {
|
|
357
381
|
strings: string[];
|
|
358
382
|
}
|
|
383
|
+
export interface UiModule {
|
|
384
|
+
/**
|
|
385
|
+
* path to ui folder (e.g. {@example join(__dirname, 'public')})
|
|
386
|
+
*/
|
|
387
|
+
uiPath: string;
|
|
388
|
+
/**
|
|
389
|
+
* page name (default index.html)
|
|
390
|
+
*/
|
|
391
|
+
fileName?: string;
|
|
392
|
+
}
|
|
393
|
+
export interface EditorPanels extends UiModule {
|
|
394
|
+
/**
|
|
395
|
+
* The Editor's mode list where the module will be available.
|
|
396
|
+
*/
|
|
397
|
+
modes: EditorPanelsMode[];
|
|
398
|
+
}
|
|
399
|
+
export declare enum EditorPanelsMode {
|
|
400
|
+
ASSETS = "assets",
|
|
401
|
+
REVIEW = "review",
|
|
402
|
+
TRANSLATE = "TRANSLATE",
|
|
403
|
+
PROOFREAD = "proofread"
|
|
404
|
+
}
|
|
405
|
+
export interface CrowdinAppUtilities {
|
|
406
|
+
saveMetadata: (id: string, metadata: any) => Promise<void>;
|
|
407
|
+
getMetadata: (id: string) => Promise<any | undefined>;
|
|
408
|
+
deleteMetadata: (id: string) => Promise<void>;
|
|
409
|
+
establishCrowdinConnection: (jwtToken: string) => Promise<{
|
|
410
|
+
context: CrowdinContextInfo;
|
|
411
|
+
client?: Crowdin;
|
|
412
|
+
}>;
|
|
413
|
+
}
|
package/out/models/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ProcessFileJobType = exports.AccountType = void 0;
|
|
3
|
+
exports.EditorPanelsMode = exports.ProcessFileJobType = exports.AccountType = void 0;
|
|
4
4
|
var AccountType;
|
|
5
5
|
(function (AccountType) {
|
|
6
6
|
AccountType["NORMAL"] = "normal";
|
|
@@ -11,3 +11,10 @@ var ProcessFileJobType;
|
|
|
11
11
|
ProcessFileJobType["PARSE_FILE"] = "parse-file";
|
|
12
12
|
ProcessFileJobType["BUILD_FILE"] = "build-file";
|
|
13
13
|
})(ProcessFileJobType = exports.ProcessFileJobType || (exports.ProcessFileJobType = {}));
|
|
14
|
+
var EditorPanelsMode;
|
|
15
|
+
(function (EditorPanelsMode) {
|
|
16
|
+
EditorPanelsMode["ASSETS"] = "assets";
|
|
17
|
+
EditorPanelsMode["REVIEW"] = "review";
|
|
18
|
+
EditorPanelsMode["TRANSLATE"] = "TRANSLATE";
|
|
19
|
+
EditorPanelsMode["PROOFREAD"] = "proofread";
|
|
20
|
+
})(EditorPanelsMode = exports.EditorPanelsMode || (exports.EditorPanelsMode = {}));
|
package/out/storage/index.d.ts
CHANGED
|
@@ -11,3 +11,7 @@ export declare function updateIntegrationConfig(id: string, config: any): Promis
|
|
|
11
11
|
export declare function getIntegrationCredentials(id: string): Promise<IntegrationCredentials | undefined>;
|
|
12
12
|
export declare function getAllIntegrationCredentials(crowdinId: string): Promise<IntegrationCredentials[]>;
|
|
13
13
|
export declare function deleteIntegrationCredentials(id: string): Promise<void>;
|
|
14
|
+
export declare function saveMetadata(id: string, metadata: any): Promise<void>;
|
|
15
|
+
export declare function updateMetadata(id: string, metadata: any): Promise<void>;
|
|
16
|
+
export declare function getMetadata(id: string): Promise<any | undefined>;
|
|
17
|
+
export declare function deleteMetadata(id: string): Promise<void>;
|
package/out/storage/index.js
CHANGED
|
@@ -13,7 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
14
|
};
|
|
15
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
-
exports.deleteIntegrationCredentials = exports.getAllIntegrationCredentials = exports.getIntegrationCredentials = exports.updateIntegrationConfig = exports.updateIntegrationCredentials = exports.saveIntegrationCredentials = exports.deleteCrowdinCredentials = exports.getAllCrowdinCredentials = exports.getCrowdinCredentials = exports.updateCrowdinCredentials = exports.saveCrowdinCredentials = exports.connect = void 0;
|
|
16
|
+
exports.deleteMetadata = exports.getMetadata = exports.updateMetadata = exports.saveMetadata = exports.deleteIntegrationCredentials = exports.getAllIntegrationCredentials = exports.getIntegrationCredentials = exports.updateIntegrationConfig = exports.updateIntegrationCredentials = exports.saveIntegrationCredentials = exports.deleteCrowdinCredentials = exports.getAllCrowdinCredentials = exports.getCrowdinCredentials = exports.updateCrowdinCredentials = exports.saveCrowdinCredentials = exports.connect = void 0;
|
|
17
17
|
const path_1 = require("path");
|
|
18
18
|
const sqlite3_1 = __importDefault(require("sqlite3"));
|
|
19
19
|
let _res;
|
|
@@ -74,6 +74,13 @@ function connect(folder) {
|
|
|
74
74
|
crowdin_id varchar not null
|
|
75
75
|
);
|
|
76
76
|
`, []);
|
|
77
|
+
yield _run(`
|
|
78
|
+
create table if not exists app_metadata
|
|
79
|
+
(
|
|
80
|
+
id varchar not null primary key,
|
|
81
|
+
data varchar null
|
|
82
|
+
);
|
|
83
|
+
`, []);
|
|
77
84
|
_res();
|
|
78
85
|
}
|
|
79
86
|
catch (e) {
|
|
@@ -198,3 +205,26 @@ function deleteIntegrationCredentials(id) {
|
|
|
198
205
|
return run('DELETE FROM integration_credentials where id = ?', [id]);
|
|
199
206
|
}
|
|
200
207
|
exports.deleteIntegrationCredentials = deleteIntegrationCredentials;
|
|
208
|
+
function saveMetadata(id, metadata) {
|
|
209
|
+
return run('INSERT INTO app_metadata(id, data) VALUES (?, ?)', [id, JSON.stringify(metadata)]);
|
|
210
|
+
}
|
|
211
|
+
exports.saveMetadata = saveMetadata;
|
|
212
|
+
function updateMetadata(id, metadata) {
|
|
213
|
+
return run('UPDATE app_metadata SET data = ? WHERE id = ?', [JSON.stringify(metadata), id]);
|
|
214
|
+
}
|
|
215
|
+
exports.updateMetadata = updateMetadata;
|
|
216
|
+
function getMetadata(id) {
|
|
217
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
218
|
+
const row = yield get('SELECT data FROM app_metadata WHERE id = ?', [id]);
|
|
219
|
+
if (row) {
|
|
220
|
+
return JSON.parse(row.data);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
exports.getMetadata = getMetadata;
|
|
225
|
+
function deleteMetadata(id) {
|
|
226
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
227
|
+
yield run('DELETE FROM app_metadata where id = ?', [id]);
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
exports.deleteMetadata = deleteMetadata;
|
package/package.json
CHANGED