@crowdin/app-project-module 0.27.0 → 0.28.0-10
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/CONTRIBUTING.md +19 -1
- package/README.md +1 -877
- package/out/handlers/crowdin-update.js +4 -3
- package/out/handlers/crowdin-webhook.d.ts +4 -0
- package/out/handlers/crowdin-webhook.js +43 -0
- package/out/handlers/form-data-display.d.ts +3 -0
- package/out/handlers/form-data-display.js +46 -0
- package/out/handlers/form-data-save.d.ts +3 -0
- package/out/handlers/form-data-save.js +56 -0
- package/out/handlers/integration-logout.js +4 -0
- package/out/handlers/integration-webhook.d.ts +4 -0
- package/out/handlers/integration-webhook.js +39 -0
- package/out/handlers/main.js +7 -1
- package/out/handlers/settings-save.d.ts +2 -2
- package/out/handlers/settings-save.js +8 -3
- package/out/handlers/uninstall.js +4 -0
- package/out/index.js +49 -9
- package/out/middlewares/render-ui-module.d.ts +4 -0
- package/out/middlewares/render-ui-module.js +33 -0
- package/out/models/index.d.ts +72 -6
- package/out/models/index.js +13 -1
- package/out/static/css/styles.css +96 -0
- package/out/static/js/dependent.js +307 -0
- package/out/static/js/form.js +115 -0
- package/out/static/js/main.js +11 -1
- package/out/util/cron.js +9 -10
- package/out/util/defaults.js +49 -12
- package/out/util/index.js +5 -1
- package/out/util/webhooks.d.ts +29 -0
- package/out/util/webhooks.js +308 -0
- package/out/views/form.handlebars +29 -0
- package/out/views/login.handlebars +84 -16
- package/out/views/main.handlebars +171 -88
- package/out/views/partials/head.handlebars +5 -4
- package/package.json +37 -23
package/out/static/js/main.js
CHANGED
|
@@ -23,9 +23,19 @@ function parentWindowPostMessage(data) {
|
|
|
23
23
|
|
|
24
24
|
window.addEventListener('message', handleMessage);
|
|
25
25
|
|
|
26
|
+
function isJson(string) {
|
|
27
|
+
try {
|
|
28
|
+
JSON.parse(string);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
|
|
26
36
|
function handleMessage(event) {
|
|
27
37
|
const eventData =
|
|
28
|
-
event.data && typeof event.data === 'string' ? JSON.parse(event.data) : {};
|
|
38
|
+
event.data && typeof event.data === 'string' && isJson(event.data) ? JSON.parse(event.data) : {};
|
|
29
39
|
if (postPromises[eventData.uid]) {
|
|
30
40
|
if (postPromises[eventData.uid].timer) {
|
|
31
41
|
clearTimeout(postPromises[eventData.uid].timer);
|
package/out/util/cron.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -31,15 +35,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
31
35
|
exports.filesCron = exports.runJob = void 0;
|
|
32
36
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
33
37
|
const _1 = require(".");
|
|
38
|
+
const models_1 = require("../models");
|
|
34
39
|
const storage_1 = require("../storage");
|
|
35
40
|
const connection_1 = require("./connection");
|
|
36
41
|
const defaults_1 = require("./defaults");
|
|
37
|
-
var SyncCondition;
|
|
38
|
-
(function (SyncCondition) {
|
|
39
|
-
SyncCondition["ALL"] = "0";
|
|
40
|
-
SyncCondition["TRANSLATED"] = "1";
|
|
41
|
-
SyncCondition["APPROVED"] = "2";
|
|
42
|
-
})(SyncCondition || (SyncCondition = {}));
|
|
43
42
|
function runJob(config, integration, job) {
|
|
44
43
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
44
|
(0, _1.log)(`Starting cron job with expression [${job.expression}]`, config.logger);
|
|
@@ -97,9 +96,9 @@ function filesCron(config, integration, period) {
|
|
|
97
96
|
const chunkSize = 10;
|
|
98
97
|
if (syncSettings.provider === 'crowdin') {
|
|
99
98
|
const crowdinFiles = files;
|
|
100
|
-
const onlyTranslated = intConfig.condition === SyncCondition.TRANSLATED;
|
|
101
|
-
const onlyApproved = intConfig.condition === SyncCondition.APPROVED;
|
|
102
|
-
const all = intConfig.condition === SyncCondition.ALL || intConfig.condition === undefined;
|
|
99
|
+
const onlyTranslated = +intConfig.condition === models_1.SyncCondition.TRANSLATED;
|
|
100
|
+
const onlyApproved = +intConfig.condition === models_1.SyncCondition.APPROVED;
|
|
101
|
+
const all = +intConfig.condition === models_1.SyncCondition.ALL || intConfig.condition === undefined;
|
|
103
102
|
const filesToProcess = all
|
|
104
103
|
? crowdinFiles
|
|
105
104
|
: yield getOnlyTranslatedOrApprovedFiles(config, projectId, crowdinFiles, crowdinClient, onlyApproved, onlyTranslated);
|
package/out/util/defaults.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -53,21 +57,20 @@ function getOauthRoute(integration) {
|
|
|
53
57
|
}
|
|
54
58
|
exports.getOauthRoute = getOauthRoute;
|
|
55
59
|
function applyDefaults(config, integration) {
|
|
60
|
+
var _a;
|
|
56
61
|
if (!integration.getCrowdinFiles) {
|
|
57
62
|
integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
|
|
58
63
|
const allBranches = (yield client.sourceFilesApi.withFetchAll().listProjectBranches(projectId)).data.map((d) => d.data);
|
|
59
|
-
let
|
|
64
|
+
let options = {};
|
|
60
65
|
if (rootFolder) {
|
|
61
|
-
|
|
66
|
+
options = {
|
|
62
67
|
directoryId: rootFolder.id,
|
|
63
68
|
recursion: 'true',
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId)).data.map((d) => d.data);
|
|
69
|
+
};
|
|
68
70
|
}
|
|
71
|
+
const allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)).data.map((d) => d.data);
|
|
69
72
|
const directoryIds = allDirectories.map((d) => d.id);
|
|
70
|
-
let files = (yield client.sourceFilesApi.withFetchAll().listProjectFiles(projectId)).data.map((d) => d.data);
|
|
73
|
+
let files = (yield client.sourceFilesApi.withFetchAll().listProjectFiles(projectId, options)).data.map((d) => d.data);
|
|
71
74
|
files = files.filter((f) => (rootFolder && f.directoryId === rootFolder.id) ||
|
|
72
75
|
directoryIds.includes(f.directoryId) ||
|
|
73
76
|
(!rootFolder && !f.directoryId));
|
|
@@ -135,22 +138,43 @@ function applyDefaults(config, integration) {
|
|
|
135
138
|
],
|
|
136
139
|
};
|
|
137
140
|
}
|
|
138
|
-
if (integration.withCronSync) {
|
|
141
|
+
if (integration.withCronSync || integration.webhooks) {
|
|
139
142
|
const getUserSettings = integration.getConfiguration;
|
|
140
143
|
integration.getConfiguration = (projectId, crowdinClient, integrationCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
141
144
|
let fields = [];
|
|
142
145
|
if (getUserSettings) {
|
|
143
146
|
fields = yield getUserSettings(projectId, crowdinClient, integrationCredentials);
|
|
144
147
|
}
|
|
145
|
-
|
|
148
|
+
const defaultSettings = [
|
|
146
149
|
{
|
|
147
150
|
label: 'Background synchronization',
|
|
148
151
|
},
|
|
149
|
-
|
|
152
|
+
];
|
|
153
|
+
const syncType = {
|
|
154
|
+
key: 'syncType',
|
|
155
|
+
label: 'Type of synchronization',
|
|
156
|
+
type: 'select',
|
|
157
|
+
defaultValue: '0',
|
|
158
|
+
options: [
|
|
159
|
+
{
|
|
160
|
+
value: '0',
|
|
161
|
+
label: 'None',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
};
|
|
165
|
+
defaultSettings.push(syncType);
|
|
166
|
+
if (integration.withCronSync) {
|
|
167
|
+
syncType.options.push({
|
|
168
|
+
value: '1',
|
|
169
|
+
label: 'Schedule',
|
|
170
|
+
});
|
|
171
|
+
defaultSettings.push({
|
|
150
172
|
key: 'schedule',
|
|
151
173
|
label: 'Sync schedule',
|
|
152
174
|
helpText: 'Set the frequency for pushing sources and translations',
|
|
153
175
|
type: 'select',
|
|
176
|
+
defaultValue: '0',
|
|
177
|
+
dependencySettings: "[{'#syncType-settings':{'type':'equal','value':['1']} }]",
|
|
154
178
|
options: [
|
|
155
179
|
{
|
|
156
180
|
value: '0',
|
|
@@ -177,12 +201,22 @@ function applyDefaults(config, integration) {
|
|
|
177
201
|
label: '24 hours',
|
|
178
202
|
},
|
|
179
203
|
],
|
|
180
|
-
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
if (integration.webhooks) {
|
|
207
|
+
syncType.options.push({
|
|
208
|
+
value: '2',
|
|
209
|
+
label: 'Webhooks',
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return [
|
|
213
|
+
...defaultSettings,
|
|
181
214
|
{
|
|
182
215
|
key: 'condition',
|
|
183
216
|
label: 'Files export settings',
|
|
184
217
|
type: 'select',
|
|
185
218
|
defaultValue: '0',
|
|
219
|
+
dependencySettings: "[{'#syncType-settings':{'type':'equal','value':['1','2']}}]",
|
|
186
220
|
options: [
|
|
187
221
|
{
|
|
188
222
|
value: '0',
|
|
@@ -207,6 +241,9 @@ function applyDefaults(config, integration) {
|
|
|
207
241
|
yield integration.getIntegrationFiles(apiCredentials);
|
|
208
242
|
});
|
|
209
243
|
}
|
|
244
|
+
if (integration.webhooks && !((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.urlParam)) {
|
|
245
|
+
integration.webhooks.urlParam = 'crowdinData';
|
|
246
|
+
}
|
|
210
247
|
}
|
|
211
248
|
exports.applyDefaults = applyDefaults;
|
|
212
249
|
function constructOauthUrl(config, integration) {
|
package/out/util/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
+
import { Config, CrowdinContextInfo, IntegrationLogic, Payload, UpdateIntegrationRequest, WebhookUrlParams } from '../models';
|
|
3
|
+
import { WebhooksModel } from '@crowdin/crowdin-api-client/out/webhooks';
|
|
4
|
+
import { Request } from 'express';
|
|
5
|
+
export declare function encodedUrlParam(config: Config, integration: IntegrationLogic, crowdinContext: CrowdinContextInfo): string;
|
|
6
|
+
export declare function decodedUrlParam(config: Config, data: string): WebhookUrlParams;
|
|
7
|
+
export declare function makeCrowdinWebhookUrl(config: Config, integration: IntegrationLogic, crowdinContext: CrowdinContextInfo): string;
|
|
8
|
+
export declare function registerWebhooks(config: Config, integration: IntegrationLogic, client: Crowdin, crowdinContext: CrowdinContextInfo, apiCredentials: any, appSettings: any): Promise<void>;
|
|
9
|
+
export declare function unregisterWebhooks(config: Config, integration: IntegrationLogic, client: Crowdin, crowdinContext: CrowdinContextInfo, apiCredentials: any, appSettings: any): Promise<void>;
|
|
10
|
+
export declare function getCrowdinProjectWebhook(config: Config, client: Crowdin, projectId: number, name: string): Promise<WebhooksModel.Webhook | undefined>;
|
|
11
|
+
export declare function getAllCrowdinProjectWebhooks(config: Config, client: Crowdin, projectId: number): Promise<WebhooksModel.Webhook[]>;
|
|
12
|
+
export declare function registerCrowdinWebhook(config: Config, url: string, client: Crowdin, crowdinContext: CrowdinContextInfo, events: WebhooksModel.Event[]): Promise<void>;
|
|
13
|
+
export declare function updateCrowdinWebhooks(config: Config, client: Crowdin, projectId: number, webhook: WebhooksModel.Webhook, events: WebhooksModel.Event[], url: string): Promise<void>;
|
|
14
|
+
export declare function unregisterCrowdinWebhooks(config: Config, client: Crowdin, projectId: number, webhook: WebhooksModel.Webhook): Promise<void>;
|
|
15
|
+
export declare function unregisterAllCrowdinWebhooks(config: Config, integration: IntegrationLogic, crowdinId: string): Promise<void>;
|
|
16
|
+
export declare function filterSyncFiles(events: Payload[], syncFileSettings: UpdateIntegrationRequest): UpdateIntegrationRequest;
|
|
17
|
+
export declare function prepareWebhookData(config: Config, integration: IntegrationLogic, webhookUrlParam: string, provider: string): Promise<{
|
|
18
|
+
projectId: number;
|
|
19
|
+
crowdinClient: {
|
|
20
|
+
client: Crowdin;
|
|
21
|
+
token: string;
|
|
22
|
+
};
|
|
23
|
+
preparedIntegrationCredentials: any;
|
|
24
|
+
rootFolder: import("@crowdin/crowdin-api-client").SourceFilesModel.Directory | undefined;
|
|
25
|
+
appSettings: any;
|
|
26
|
+
syncSettings: import("../models").IntegrationSyncSettings | null | undefined;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function updateCrowdinFromWebhookRequest(integration: IntegrationLogic, webhookData: any, req: Request): Promise<void | import("../models").ExtendedResult<void>>;
|
|
29
|
+
export declare function listenQueueMessage(config: Config, integration: IntegrationLogic, queueUrl: string, queueName: string): Promise<void>;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.listenQueueMessage = exports.updateCrowdinFromWebhookRequest = exports.prepareWebhookData = exports.filterSyncFiles = exports.unregisterAllCrowdinWebhooks = exports.unregisterCrowdinWebhooks = exports.updateCrowdinWebhooks = exports.registerCrowdinWebhook = exports.getAllCrowdinProjectWebhooks = exports.getCrowdinProjectWebhook = exports.unregisterWebhooks = exports.registerWebhooks = exports.makeCrowdinWebhookUrl = exports.decodedUrlParam = exports.encodedUrlParam = void 0;
|
|
39
|
+
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
40
|
+
const amqplib_1 = __importDefault(require("amqplib"));
|
|
41
|
+
const models_1 = require("../models");
|
|
42
|
+
const index_1 = require("./index");
|
|
43
|
+
const connection_1 = require("./connection");
|
|
44
|
+
const storage_1 = require("../storage");
|
|
45
|
+
const defaults_1 = require("./defaults");
|
|
46
|
+
const util_1 = require("../util");
|
|
47
|
+
const HookEvents = {
|
|
48
|
+
ALL: ['file.translated', 'file.approved'],
|
|
49
|
+
TRANSLATED: ['file.translated'],
|
|
50
|
+
APPROVED: ['file.approved'],
|
|
51
|
+
};
|
|
52
|
+
function encodedUrlParam(config, integration, crowdinContext) {
|
|
53
|
+
var _a;
|
|
54
|
+
const params = {
|
|
55
|
+
projectId: +crowdinContext.jwtPayload.context.project_id,
|
|
56
|
+
clientId: crowdinContext.clientId,
|
|
57
|
+
crowdinId: crowdinContext.crowdinId,
|
|
58
|
+
};
|
|
59
|
+
const encryptedParams = (0, index_1.encryptData)(config, JSON.stringify(params));
|
|
60
|
+
return `${(_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.urlParam}=${encodeURIComponent(encryptedParams)}`;
|
|
61
|
+
}
|
|
62
|
+
exports.encodedUrlParam = encodedUrlParam;
|
|
63
|
+
function decodedUrlParam(config, data) {
|
|
64
|
+
const params = (0, index_1.decryptData)(config, data);
|
|
65
|
+
return JSON.parse(params);
|
|
66
|
+
}
|
|
67
|
+
exports.decodedUrlParam = decodedUrlParam;
|
|
68
|
+
function makeCrowdinWebhookUrl(config, integration, crowdinContext) {
|
|
69
|
+
var _a;
|
|
70
|
+
const urlParam = encodedUrlParam(config, integration, crowdinContext);
|
|
71
|
+
return (`${config.baseUrl}${((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.crowdinWebhookUrl) ? integration.webhooks.crowdinWebhookUrl : '/api/crowdin/webhook'}` + `?${urlParam}`);
|
|
72
|
+
}
|
|
73
|
+
exports.makeCrowdinWebhookUrl = makeCrowdinWebhookUrl;
|
|
74
|
+
function registerWebhooks(config, integration, client, crowdinContext, apiCredentials, appSettings) {
|
|
75
|
+
var _a, _b;
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
const isWebhookSync = +appSettings.syncType === models_1.SyncType.WEBHOOKS;
|
|
78
|
+
const projectId = crowdinContext.jwtPayload.context.project_id;
|
|
79
|
+
const urlParam = encodedUrlParam(config, integration, crowdinContext);
|
|
80
|
+
if ((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.crowdinWebhooks) {
|
|
81
|
+
yield integration.webhooks.crowdinWebhooks(client, projectId, isWebhookSync, appSettings);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
const webhookName = `${config.name} application hook ${crowdinContext.jwtPayload.sub}`;
|
|
85
|
+
const webhookUrl = makeCrowdinWebhookUrl(config, integration, crowdinContext);
|
|
86
|
+
const syncCondition = models_1.SyncCondition[+appSettings.condition];
|
|
87
|
+
const events = HookEvents[syncCondition];
|
|
88
|
+
const webhook = yield getCrowdinProjectWebhook(config, client, projectId, webhookName);
|
|
89
|
+
if (isWebhookSync && webhook) {
|
|
90
|
+
yield updateCrowdinWebhooks(config, client, projectId, webhook, events, webhookUrl);
|
|
91
|
+
}
|
|
92
|
+
else if (isWebhookSync && !webhook) {
|
|
93
|
+
yield registerCrowdinWebhook(config, webhookUrl, client, crowdinContext, events);
|
|
94
|
+
}
|
|
95
|
+
else if (!isWebhookSync && webhook) {
|
|
96
|
+
yield unregisterCrowdinWebhooks(config, client, projectId, webhook);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if ((_b = integration.webhooks) === null || _b === void 0 ? void 0 : _b.integrationWebhooks) {
|
|
100
|
+
yield integration.webhooks.integrationWebhooks(apiCredentials, urlParam, isWebhookSync, appSettings);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
exports.registerWebhooks = registerWebhooks;
|
|
105
|
+
function unregisterWebhooks(config, integration, client, crowdinContext, apiCredentials, appSettings) {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
if ((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.crowdinWebhooks) {
|
|
109
|
+
yield integration.webhooks.crowdinWebhooks(client, crowdinContext.jwtPayload.context.project_id, false);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const webhookName = `${config.name} application hook ${crowdinContext.jwtPayload.sub}`;
|
|
113
|
+
const webhook = yield getCrowdinProjectWebhook(config, client, crowdinContext.jwtPayload.context.project_id, webhookName);
|
|
114
|
+
if (webhook) {
|
|
115
|
+
yield unregisterCrowdinWebhooks(config, client, crowdinContext.jwtPayload.context.project_id, webhook);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if ((_b = integration.webhooks) === null || _b === void 0 ? void 0 : _b.integrationWebhooks) {
|
|
119
|
+
const urlParam = encodedUrlParam(config, integration, crowdinContext);
|
|
120
|
+
yield integration.webhooks.integrationWebhooks(apiCredentials, urlParam, false, appSettings);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
exports.unregisterWebhooks = unregisterWebhooks;
|
|
125
|
+
function getCrowdinProjectWebhook(config, client, projectId, name) {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
const hooks = (yield client.webhooksApi.withFetchAll().listWebhooks(projectId)).data.map((e) => e.data);
|
|
128
|
+
return hooks.find((h) => h.name === name);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
exports.getCrowdinProjectWebhook = getCrowdinProjectWebhook;
|
|
132
|
+
function getAllCrowdinProjectWebhooks(config, client, projectId) {
|
|
133
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
const hooks = (yield client.webhooksApi.withFetchAll().listWebhooks(projectId)).data.map((e) => e.data);
|
|
135
|
+
return hooks.filter((h) => h.name.startsWith(`${config.name} application hook `));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
exports.getAllCrowdinProjectWebhooks = getAllCrowdinProjectWebhooks;
|
|
139
|
+
function createPayload(events) {
|
|
140
|
+
const payload = {};
|
|
141
|
+
for (const event of events) {
|
|
142
|
+
payload[event] = {
|
|
143
|
+
event: '{{event}}',
|
|
144
|
+
projectId: '{{projectId}}',
|
|
145
|
+
language: '{{targetLanguageId}}',
|
|
146
|
+
fileId: '{{fileId}}',
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return payload;
|
|
150
|
+
}
|
|
151
|
+
function registerCrowdinWebhook(config, url, client, crowdinContext, events) {
|
|
152
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
153
|
+
const name = `${config.name} application hook ${crowdinContext.jwtPayload.sub}`;
|
|
154
|
+
const payload = createPayload(events);
|
|
155
|
+
yield client.webhooksApi.addWebhook(crowdinContext.jwtPayload.context.project_id, {
|
|
156
|
+
name,
|
|
157
|
+
url,
|
|
158
|
+
events,
|
|
159
|
+
requestType: 'POST',
|
|
160
|
+
batchingEnabled: true,
|
|
161
|
+
payload,
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
exports.registerCrowdinWebhook = registerCrowdinWebhook;
|
|
166
|
+
function updateCrowdinWebhooks(config, client, projectId, webhook, events, url) {
|
|
167
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
const payload = createPayload(events);
|
|
169
|
+
yield client.webhooksApi.editWebhook(projectId, webhook.id, [
|
|
170
|
+
{
|
|
171
|
+
value: events,
|
|
172
|
+
op: 'replace',
|
|
173
|
+
path: '/events',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
value: payload,
|
|
177
|
+
op: 'replace',
|
|
178
|
+
path: '/payload',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
value: url,
|
|
182
|
+
op: 'replace',
|
|
183
|
+
path: '/url',
|
|
184
|
+
},
|
|
185
|
+
]);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
exports.updateCrowdinWebhooks = updateCrowdinWebhooks;
|
|
189
|
+
function unregisterCrowdinWebhooks(config, client, projectId, webhook) {
|
|
190
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
191
|
+
yield client.webhooksApi.deleteWebhook(projectId, webhook.id);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
exports.unregisterCrowdinWebhooks = unregisterCrowdinWebhooks;
|
|
195
|
+
function unregisterAllCrowdinWebhooks(config, integration, crowdinId) {
|
|
196
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
+
if (integration.webhooks) {
|
|
198
|
+
const crowdinCredentials = yield (0, storage_1.getStorage)().getCrowdinCredentials(crowdinId);
|
|
199
|
+
if (crowdinCredentials) {
|
|
200
|
+
const credentials = yield (0, storage_1.getStorage)().getAllIntegrationCredentials(crowdinId);
|
|
201
|
+
const projectIds = credentials.map((c) => crowdinAppFunctions.getProjectId(c.id));
|
|
202
|
+
const crowdinClient = yield (0, connection_1.prepareCrowdinClient)(config, crowdinCredentials);
|
|
203
|
+
yield Promise.all(projectIds.map((projectId) => __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
const webhooks = yield getAllCrowdinProjectWebhooks(config, crowdinClient.client, projectId);
|
|
205
|
+
yield Promise.all(webhooks.map((hook) => __awaiter(this, void 0, void 0, function* () { return yield unregisterCrowdinWebhooks(config, crowdinClient.client, projectId, hook); })));
|
|
206
|
+
})));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
exports.unregisterAllCrowdinWebhooks = unregisterAllCrowdinWebhooks;
|
|
212
|
+
function filterSyncFiles(events, syncFileSettings) {
|
|
213
|
+
const files = {};
|
|
214
|
+
events.forEach((event) => {
|
|
215
|
+
const fileId = event.fileId;
|
|
216
|
+
const language = event.language;
|
|
217
|
+
if (syncFileSettings[fileId] && syncFileSettings[fileId].includes(language)) {
|
|
218
|
+
if (files[fileId]) {
|
|
219
|
+
files[fileId] = [...files[fileId], event.language];
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
files[fileId] = [event.language];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return files;
|
|
227
|
+
}
|
|
228
|
+
exports.filterSyncFiles = filterSyncFiles;
|
|
229
|
+
function prepareWebhookData(config, integration, webhookUrlParam, provider) {
|
|
230
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
231
|
+
let rootFolder = undefined;
|
|
232
|
+
let appSettings = null;
|
|
233
|
+
let syncSettings = null;
|
|
234
|
+
const { projectId, crowdinId, clientId } = decodedUrlParam(config, webhookUrlParam);
|
|
235
|
+
const crowdinCredentials = yield (0, storage_1.getStorage)().getCrowdinCredentials(crowdinId);
|
|
236
|
+
const crowdinClient = yield (0, connection_1.prepareCrowdinClient)(config, crowdinCredentials);
|
|
237
|
+
const integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(clientId);
|
|
238
|
+
const preparedIntegrationCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
239
|
+
if (integrationCredentials === null || integrationCredentials === void 0 ? void 0 : integrationCredentials.config) {
|
|
240
|
+
appSettings = JSON.parse(integrationCredentials.config);
|
|
241
|
+
const isWebhookSync = +appSettings.syncType === models_1.SyncType.WEBHOOKS;
|
|
242
|
+
if (isWebhookSync) {
|
|
243
|
+
syncSettings = yield (0, storage_1.getStorage)().getSyncSettings(clientId, crowdinId, 'schedule', provider);
|
|
244
|
+
rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient.client, projectId);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return { projectId, crowdinClient, preparedIntegrationCredentials, rootFolder, appSettings, syncSettings };
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
exports.prepareWebhookData = prepareWebhookData;
|
|
251
|
+
function updateCrowdinFromWebhookRequest(integration, webhookData, req) {
|
|
252
|
+
var _a, _b;
|
|
253
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
254
|
+
let filesToSync = [];
|
|
255
|
+
const { projectId, crowdinClient, preparedIntegrationCredentials, rootFolder, appSettings, syncSettings } = webhookData;
|
|
256
|
+
if ((_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.integrationWebhookInterceptor) {
|
|
257
|
+
filesToSync = yield ((_b = integration.webhooks) === null || _b === void 0 ? void 0 : _b.integrationWebhookInterceptor(projectId, crowdinClient.client, preparedIntegrationCredentials, rootFolder, appSettings, syncSettings, req));
|
|
258
|
+
}
|
|
259
|
+
return yield integration.updateCrowdin(projectId, crowdinClient.client, preparedIntegrationCredentials, filesToSync, rootFolder, appSettings);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
exports.updateCrowdinFromWebhookRequest = updateCrowdinFromWebhookRequest;
|
|
263
|
+
function listenQueueMessage(config, integration, queueUrl, queueName) {
|
|
264
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
265
|
+
try {
|
|
266
|
+
const connection = yield amqplib_1.default.connect(queueUrl);
|
|
267
|
+
connection.once('close', function () {
|
|
268
|
+
setTimeout(() => {
|
|
269
|
+
listenQueueMessage(config, integration, queueUrl, queueName);
|
|
270
|
+
}, 3000);
|
|
271
|
+
return;
|
|
272
|
+
});
|
|
273
|
+
const channel = yield connection.createChannel();
|
|
274
|
+
if (channel) {
|
|
275
|
+
yield channel.assertQueue(queueName, { durable: true });
|
|
276
|
+
yield channel.prefetch(1);
|
|
277
|
+
yield channel.consume(queueName, consumer(channel, config, integration), { noAck: false });
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
setTimeout(() => {
|
|
282
|
+
listenQueueMessage(config, integration, queueUrl, queueName);
|
|
283
|
+
}, 3000);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
exports.listenQueueMessage = listenQueueMessage;
|
|
288
|
+
function consumer(channel, config, integration) {
|
|
289
|
+
return function (msg) {
|
|
290
|
+
var _a;
|
|
291
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
292
|
+
if (!msg) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
const data = JSON.parse(msg.content.toString());
|
|
297
|
+
const urlParam = (_a = integration.webhooks) === null || _a === void 0 ? void 0 : _a.urlParam;
|
|
298
|
+
const webhookUrlParam = data.query[urlParam];
|
|
299
|
+
const webhookData = yield prepareWebhookData(config, integration, webhookUrlParam, 'integration');
|
|
300
|
+
yield updateCrowdinFromWebhookRequest(integration, webhookData, data);
|
|
301
|
+
}
|
|
302
|
+
catch (e) {
|
|
303
|
+
(0, util_1.logError)(e, config.onError);
|
|
304
|
+
}
|
|
305
|
+
channel.ack(msg);
|
|
306
|
+
});
|
|
307
|
+
};
|
|
308
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
{{> head}}
|
|
4
|
+
<body>
|
|
5
|
+
<div
|
|
6
|
+
class="i_w"
|
|
7
|
+
style='max-width:680px; position: relative;'
|
|
8
|
+
>
|
|
9
|
+
<crowdin-card
|
|
10
|
+
is-shadowed
|
|
11
|
+
>
|
|
12
|
+
<div id="form"></div>
|
|
13
|
+
<div id="form-loading">
|
|
14
|
+
<crowdin-progress-indicator />
|
|
15
|
+
</div>
|
|
16
|
+
</crowdin-card>
|
|
17
|
+
</div>
|
|
18
|
+
<crowdin-toasts></crowdin-toasts>
|
|
19
|
+
<script>
|
|
20
|
+
/*<!--*/
|
|
21
|
+
var formGetDataUrl = '{{formGetDataUrl}}';
|
|
22
|
+
var formPostDataUrl = '{{formPostDataUrl}}';
|
|
23
|
+
var formSchema = {{{formSchema}}};
|
|
24
|
+
var formUiSchema = {{{formUiSchema}}};
|
|
25
|
+
/*-->*/
|
|
26
|
+
</script>
|
|
27
|
+
<script src="/assets/js/form.js"></script>
|
|
28
|
+
</body>
|
|
29
|
+
</html>
|