@crowdin/app-project-module 0.31.0 → 0.32.1
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/out/handlers/custom-mt/translate.d.ts +2 -2
- package/out/handlers/custom-mt/translate.js +8 -6
- package/out/handlers/file-processing/custom-file-format.d.ts +2 -2
- package/out/handlers/file-processing/custom-file-format.js +4 -4
- package/out/handlers/file-processing/file-download.d.ts +1 -1
- package/out/handlers/file-processing/file-download.js +3 -2
- package/out/handlers/file-processing/pre-post-process.d.ts +2 -2
- package/out/handlers/file-processing/pre-post-process.js +11 -3
- package/out/handlers/form-data-display.d.ts +1 -1
- package/out/handlers/form-data-save.d.ts +1 -1
- package/out/handlers/install.d.ts +1 -1
- package/out/handlers/install.js +5 -3
- package/out/handlers/integration/crowdin-file-progress.d.ts +2 -2
- package/out/handlers/integration/crowdin-file-progress.js +4 -4
- package/out/handlers/integration/crowdin-files.d.ts +1 -1
- package/out/handlers/integration/crowdin-files.js +4 -4
- package/out/handlers/integration/crowdin-project.d.ts +2 -2
- package/out/handlers/integration/crowdin-project.js +4 -4
- package/out/handlers/integration/crowdin-update.d.ts +1 -1
- package/out/handlers/integration/crowdin-update.js +4 -4
- package/out/handlers/integration/crowdin-webhook.d.ts +1 -1
- package/out/handlers/integration/crowdin-webhook.js +1 -1
- package/out/handlers/integration/integration-data.d.ts +2 -2
- package/out/handlers/integration/integration-data.js +4 -4
- package/out/handlers/integration/integration-login.d.ts +2 -2
- package/out/handlers/integration/integration-login.js +4 -4
- package/out/handlers/integration/integration-logout.d.ts +1 -1
- package/out/handlers/integration/integration-logout.js +4 -4
- package/out/handlers/integration/integration-update.d.ts +1 -1
- package/out/handlers/integration/integration-update.js +3 -3
- package/out/handlers/integration/integration-webhook.d.ts +1 -1
- package/out/handlers/integration/integration-webhook.js +1 -1
- package/out/handlers/integration/main.d.ts +1 -1
- package/out/handlers/integration/main.js +5 -3
- package/out/handlers/integration/oauth-login.d.ts +1 -1
- package/out/handlers/integration/oauth-login.js +6 -10
- package/out/handlers/integration/oauth-url.d.ts +2 -2
- package/out/handlers/integration/oauth-url.js +3 -3
- package/out/handlers/integration/settings-save.d.ts +1 -1
- package/out/handlers/integration/settings-save.js +2 -2
- package/out/handlers/integration/settings.d.ts +1 -2
- package/out/handlers/integration/settings.js +2 -2
- package/out/handlers/integration/sync-settings-save.d.ts +1 -1
- package/out/handlers/integration/sync-settings-save.js +1 -1
- package/out/handlers/integration/sync-settings.d.ts +1 -2
- package/out/handlers/integration/sync-settings.js +4 -4
- package/out/handlers/integration/synced-files.d.ts +1 -2
- package/out/handlers/integration/synced-files.js +4 -4
- package/out/handlers/manifest.js +7 -7
- package/out/handlers/subscription-paid.d.ts +1 -2
- package/out/handlers/subscription-paid.js +4 -3
- package/out/handlers/uninstall.d.ts +1 -1
- package/out/handlers/uninstall.js +7 -6
- package/out/index.d.ts +1 -1
- package/out/index.js +36 -33
- package/out/middlewares/crowdin-client.d.ts +4 -1
- package/out/middlewares/crowdin-client.js +26 -16
- package/out/middlewares/integration-credentials.d.ts +1 -1
- package/out/middlewares/integration-credentials.js +2 -2
- package/out/middlewares/render-ui-module.d.ts +2 -2
- package/out/middlewares/render-ui-module.js +2 -2
- package/out/middlewares/ui-module.d.ts +1 -1
- package/out/middlewares/ui-module.js +17 -6
- package/out/models/index.d.ts +8 -4
- package/out/models/index.js +1 -0
- package/out/storage/index.js +4 -4
- package/out/util/api/api.js +4 -4
- package/out/util/connection.d.ts +11 -2
- package/out/util/connection.js +17 -16
- package/out/util/cron.js +43 -25
- package/out/util/file-snapshot.d.ts +1 -1
- package/out/util/file-snapshot.js +4 -4
- package/out/util/index.d.ts +3 -6
- package/out/util/index.js +12 -42
- package/out/util/logger.d.ts +14 -0
- package/out/util/logger.js +71 -0
- package/out/util/synced-files.js +4 -4
- package/out/util/webhooks.d.ts +1 -1
- package/out/util/webhooks.js +6 -6
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const express_1 = __importDefault(require("express"));
|
|
16
16
|
const util_1 = require("../util");
|
|
17
|
-
function handle(
|
|
17
|
+
function handle(moduleConfig) {
|
|
18
18
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
19
19
|
if (moduleConfig.formSchema) {
|
|
20
20
|
return res.render('form', {
|
|
@@ -28,6 +28,6 @@ function handle(config, moduleConfig) {
|
|
|
28
28
|
return express_1.default.static(moduleConfig.uiPath)(req, res, next);
|
|
29
29
|
}
|
|
30
30
|
throw new Error('uiPath or formSchema should be provided for module');
|
|
31
|
-
})
|
|
31
|
+
}));
|
|
32
32
|
}
|
|
33
33
|
exports.default = handle;
|
|
@@ -1,4 +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, allowUnauthorized?: boolean): (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;
|
|
4
|
+
export default function handle(config: Config, allowUnauthorized?: boolean): (req: import("../models").CrowdinClientRequest | Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: Function) => void;
|
|
@@ -13,6 +13,7 @@ const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
|
|
|
13
13
|
const storage_1 = require("../storage");
|
|
14
14
|
const util_1 = require("../util");
|
|
15
15
|
const connection_1 = require("../util/connection");
|
|
16
|
+
const logger_1 = require("../util/logger");
|
|
16
17
|
function handle(config, allowUnauthorized = false) {
|
|
17
18
|
return (0, util_1.runAsyncWrapper)((req, res, next) => __awaiter(this, void 0, void 0, function* () {
|
|
18
19
|
if (allowUnauthorized) {
|
|
@@ -23,21 +24,31 @@ function handle(config, allowUnauthorized = false) {
|
|
|
23
24
|
if (!jwtToken) {
|
|
24
25
|
return res.status(403).send({ error: 'Access denied' });
|
|
25
26
|
}
|
|
26
|
-
(0,
|
|
27
|
+
(0, logger_1.log)('Validating jwt token from incoming request');
|
|
27
28
|
const jwtPayload = yield (0, crowdin_apps_functions_1.validateJwtToken)(jwtToken, config.clientSecret, config.jwtValidationOptions);
|
|
28
29
|
const id = `${jwtPayload.domain || jwtPayload.context.organization_id}`;
|
|
29
|
-
(0,
|
|
30
|
+
const logInfo = (0, logger_1.withContext)({
|
|
31
|
+
orgId: id,
|
|
32
|
+
userId: (0, crowdin_apps_functions_1.constructCrowdinIdFromJwtPayload)(jwtPayload),
|
|
33
|
+
projectId: jwtPayload.context.project_id,
|
|
34
|
+
});
|
|
35
|
+
logInfo('Loading crowdin credentials');
|
|
30
36
|
const credentials = yield (0, storage_1.getStorage)().getCrowdinCredentials(id);
|
|
31
37
|
if (!credentials) {
|
|
32
38
|
throw new Error("Can't find organization by id");
|
|
33
39
|
}
|
|
34
|
-
(
|
|
35
|
-
const { token } = yield (0, connection_1.prepareCrowdinClient)(config, credentials);
|
|
36
|
-
const { expired, subscribeLink } = yield (0, connection_1.checkSubscription)(
|
|
40
|
+
logInfo('Building crowdin client instance');
|
|
41
|
+
const { token } = yield (0, connection_1.prepareCrowdinClient)({ config, credentials });
|
|
42
|
+
const { expired, subscribeLink } = yield (0, connection_1.checkSubscription)({
|
|
43
|
+
config,
|
|
44
|
+
token,
|
|
45
|
+
organization: credentials.id,
|
|
46
|
+
accountType: credentials.type,
|
|
47
|
+
});
|
|
37
48
|
if (expired) {
|
|
38
49
|
return res.render('subscription', { subscribeLink });
|
|
39
50
|
}
|
|
40
51
|
next();
|
|
41
|
-
})
|
|
52
|
+
}));
|
|
42
53
|
}
|
|
43
54
|
exports.default = handle;
|
package/out/models/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { JwtPayload, VerifyOptions } from '@crowdin/crowdin-apps-functions';
|
|
|
3
3
|
import { Request } from 'express';
|
|
4
4
|
import { MySQLStorageConfig } from '../storage/mysql';
|
|
5
5
|
import { PostgreStorageConfig } from '../storage/postgre';
|
|
6
|
+
import { LogContext, LogErrorFunction, LogFunction } from '../util/logger';
|
|
6
7
|
export interface ClientConfig extends ImagePath {
|
|
7
8
|
/**
|
|
8
9
|
* Authentication Crowdin App type: "authorization_code", "crowdin_app". Default: "crowdin_app"
|
|
@@ -130,7 +131,7 @@ export interface ClientConfig extends ImagePath {
|
|
|
130
131
|
/**
|
|
131
132
|
* Error interceptor (can be used to log error in centralized place)
|
|
132
133
|
*/
|
|
133
|
-
onError?: (error: any) => void;
|
|
134
|
+
onError?: (error: any, context?: LogContext) => void;
|
|
134
135
|
/**
|
|
135
136
|
* Disable global error handling of unhandledRejection and uncaughtException events
|
|
136
137
|
*/
|
|
@@ -478,6 +479,8 @@ export interface CrowdinClientRequest extends Request {
|
|
|
478
479
|
crowdinApiClient: Crowdin;
|
|
479
480
|
crowdinContext: CrowdinContextInfo;
|
|
480
481
|
subscriptionInfo?: SubscriptionInfo;
|
|
482
|
+
logInfo: LogFunction;
|
|
483
|
+
logError: LogErrorFunction;
|
|
481
484
|
}
|
|
482
485
|
export interface CrowdinCredentials {
|
|
483
486
|
id: string;
|
|
@@ -609,6 +612,7 @@ export interface ProcessFileRequest {
|
|
|
609
612
|
targetLanguages: LanguagesModel.Language[];
|
|
610
613
|
strings: ProcessFileString[];
|
|
611
614
|
stringsUrl: string;
|
|
615
|
+
getRawContent?: (encoding: string) => Promise<string>;
|
|
612
616
|
}
|
|
613
617
|
export interface ProcessFileRecord {
|
|
614
618
|
content?: string;
|
|
@@ -824,7 +828,7 @@ export interface ApiModule {
|
|
|
824
828
|
}
|
|
825
829
|
export interface Logger {
|
|
826
830
|
enabled: boolean;
|
|
827
|
-
log?: (message: string) => void;
|
|
831
|
+
log?: (message: string, context?: LogContext) => void;
|
|
828
832
|
}
|
|
829
833
|
export interface Pricing {
|
|
830
834
|
planType: 'free' | 'recurring';
|
|
@@ -882,7 +886,6 @@ export interface UpdateCrowdinWebhookPayloadsArgs {
|
|
|
882
886
|
req: Request;
|
|
883
887
|
}
|
|
884
888
|
export interface CreateOrUpdateSyncedFilesArgs {
|
|
885
|
-
config: Config;
|
|
886
889
|
req: IntegrationRequest;
|
|
887
890
|
fileIds: string[];
|
|
888
891
|
}
|
|
@@ -895,7 +898,8 @@ export interface IntegrationSyncedFiles {
|
|
|
895
898
|
export declare enum UserPermissions {
|
|
896
899
|
OWNER = "owner",
|
|
897
900
|
MANAGERS = "managers",
|
|
898
|
-
ALL_MEMBERS = "all"
|
|
901
|
+
ALL_MEMBERS = "all",
|
|
902
|
+
GUESTS = "guests"
|
|
899
903
|
}
|
|
900
904
|
export declare enum ProjectPermissions {
|
|
901
905
|
OWN = "own",
|
package/out/models/index.js
CHANGED
|
@@ -96,6 +96,7 @@ var UserPermissions;
|
|
|
96
96
|
UserPermissions["OWNER"] = "owner";
|
|
97
97
|
UserPermissions["MANAGERS"] = "managers";
|
|
98
98
|
UserPermissions["ALL_MEMBERS"] = "all";
|
|
99
|
+
UserPermissions["GUESTS"] = "guests";
|
|
99
100
|
})(UserPermissions = exports.UserPermissions || (exports.UserPermissions = {}));
|
|
100
101
|
var ProjectPermissions;
|
|
101
102
|
(function (ProjectPermissions) {
|
package/out/storage/index.js
CHANGED
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.getStorage = exports.initialize = void 0;
|
|
13
|
-
const
|
|
13
|
+
const logger_1 = require("../util/logger");
|
|
14
14
|
const mysql_1 = require("./mysql");
|
|
15
15
|
const postgre_1 = require("./postgre");
|
|
16
16
|
const sqlite_1 = require("./sqlite");
|
|
@@ -18,15 +18,15 @@ let storage;
|
|
|
18
18
|
function initialize(config) {
|
|
19
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
20
|
if (config.postgreConfig) {
|
|
21
|
-
(0,
|
|
21
|
+
(0, logger_1.log)('Using PostgreSQL database');
|
|
22
22
|
storage = new postgre_1.PostgreStorage(config.postgreConfig);
|
|
23
23
|
}
|
|
24
24
|
else if (config.mysqlConfig) {
|
|
25
|
-
(0,
|
|
25
|
+
(0, logger_1.log)('Using MySQL database');
|
|
26
26
|
storage = new mysql_1.MySQLStorage(config.mysqlConfig);
|
|
27
27
|
}
|
|
28
28
|
else {
|
|
29
|
-
(0,
|
|
29
|
+
(0, logger_1.log)('Using SQLite database');
|
|
30
30
|
storage = new sqlite_1.SQLiteStorage({ dbFolder: config.dbFolder });
|
|
31
31
|
}
|
|
32
32
|
yield storage.migrate();
|
package/out/util/api/api.js
CHANGED
|
@@ -200,7 +200,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
200
200
|
* data:
|
|
201
201
|
* $ref: '#/components/schemas/FileProgress'
|
|
202
202
|
*/
|
|
203
|
-
app.get('/file-progress', (0, crowdin_client_1.default)(config), (0, crowdin_file_progress_1.default)(config
|
|
203
|
+
app.get('/file-progress', (0, crowdin_client_1.default)(config), (0, crowdin_file_progress_1.default)(config.projectIntegration));
|
|
204
204
|
/**
|
|
205
205
|
* @openapi
|
|
206
206
|
* /integration-files:
|
|
@@ -222,7 +222,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
222
222
|
* $ref: '#/components/schemas/IntegrationFiles'
|
|
223
223
|
*
|
|
224
224
|
*/
|
|
225
|
-
app.get('/integration-files', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_data_1.default)(config
|
|
225
|
+
app.get('/integration-files', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, integration_data_1.default)(config.projectIntegration));
|
|
226
226
|
/**
|
|
227
227
|
* @openapi
|
|
228
228
|
* /crowdin-update:
|
|
@@ -289,7 +289,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
289
289
|
* data:
|
|
290
290
|
* $ref: '#/components/schemas/SettingsResponse'
|
|
291
291
|
*/
|
|
292
|
-
app.get('/settings', (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, settings_1.default)(
|
|
292
|
+
app.get('/settings', (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, settings_1.default)());
|
|
293
293
|
/**
|
|
294
294
|
* @openapi
|
|
295
295
|
* /settings:
|
|
@@ -338,7 +338,7 @@ function addDefaultApiEndpoints(app, config) {
|
|
|
338
338
|
* - { $ref: '#/components/schemas/CrowdinSyncSettingsResponse' }
|
|
339
339
|
* - { $ref: '#/components/schemas/IntegrationSyncSettingsResponse' }
|
|
340
340
|
*/
|
|
341
|
-
app.get('/sync-settings', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, sync_settings_1.default)(
|
|
341
|
+
app.get('/sync-settings', json_response_1.default, (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, config.projectIntegration), (0, sync_settings_1.default)());
|
|
342
342
|
/**
|
|
343
343
|
* @openapi
|
|
344
344
|
* /sync-settings:
|
package/out/util/connection.d.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
2
|
import { AccountType, Config, CrowdinCredentials, IntegrationCredentials, IntegrationLogic, SubscriptionInfo } from '../models';
|
|
3
|
-
export declare function prepareCrowdinClient(config
|
|
3
|
+
export declare function prepareCrowdinClient({ config, credentials, autoRenew, }: {
|
|
4
|
+
config: Config;
|
|
5
|
+
credentials: CrowdinCredentials;
|
|
6
|
+
autoRenew?: boolean;
|
|
7
|
+
}): Promise<{
|
|
4
8
|
client: Crowdin;
|
|
5
9
|
token: string;
|
|
6
10
|
}>;
|
|
7
11
|
export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
|
|
8
12
|
export declare function clearCache(organization: string): void;
|
|
9
13
|
export declare function isAppFree(config: Config): boolean;
|
|
10
|
-
export declare function checkSubscription(config
|
|
14
|
+
export declare function checkSubscription({ config, token, organization, accountType, }: {
|
|
15
|
+
config: Config;
|
|
16
|
+
token: string;
|
|
17
|
+
organization: string;
|
|
18
|
+
accountType: AccountType;
|
|
19
|
+
}): Promise<SubscriptionInfo>;
|
package/out/util/connection.js
CHANGED
|
@@ -20,6 +20,7 @@ const _1 = require(".");
|
|
|
20
20
|
const models_1 = require("../models");
|
|
21
21
|
const storage_1 = require("../storage");
|
|
22
22
|
const axios_2 = require("./axios");
|
|
23
|
+
const logger_1 = require("./logger");
|
|
23
24
|
const axiosCustom = new axios_2.AxiosProvider().axios;
|
|
24
25
|
function refreshToken(config, credentials) {
|
|
25
26
|
var _a, _b;
|
|
@@ -53,7 +54,7 @@ function refreshToken(config, credentials) {
|
|
|
53
54
|
};
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
|
-
function prepareCrowdinClient(config, credentials, autoRenew = false) {
|
|
57
|
+
function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
57
58
|
var _a, _b;
|
|
58
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
59
60
|
//2 min as an extra buffer
|
|
@@ -206,9 +207,9 @@ function prepareCrowdinClient(config, credentials, autoRenew = false) {
|
|
|
206
207
|
exports.prepareCrowdinClient = prepareCrowdinClient;
|
|
207
208
|
function refreshCrowdinCreds({ config, credentials }) {
|
|
208
209
|
return __awaiter(this, void 0, void 0, function* () {
|
|
209
|
-
(0,
|
|
210
|
+
(0, logger_1.log)('Crowdin credentials have expired. Requesting a new credentials');
|
|
210
211
|
const newCredentials = yield refreshToken(config, credentials);
|
|
211
|
-
(0,
|
|
212
|
+
(0, logger_1.log)('Saving updated crowdin credentials in the database');
|
|
212
213
|
const newCrowdinCredentials = {
|
|
213
214
|
id: credentials.id,
|
|
214
215
|
appSecret: credentials.appSecret,
|
|
@@ -234,13 +235,13 @@ function prepareIntegrationCredentials(config, integration, integrationCredentia
|
|
|
234
235
|
return __awaiter(this, void 0, void 0, function* () {
|
|
235
236
|
const credentials = JSON.parse((0, _1.decryptData)(config, integrationCredentials.credentials));
|
|
236
237
|
if ((_a = integration.oauthLogin) === null || _a === void 0 ? void 0 : _a.refresh) {
|
|
237
|
-
(0,
|
|
238
|
+
(0, logger_1.log)('Checking if integration credentials need to be refreshed');
|
|
238
239
|
const oauthLogin = integration.oauthLogin;
|
|
239
240
|
const { expireIn } = credentials;
|
|
240
241
|
//2 min as an extra buffer
|
|
241
242
|
const isExpired = expireIn - 120 < Date.now() / 1000;
|
|
242
243
|
if (isExpired) {
|
|
243
|
-
(0,
|
|
244
|
+
(0, logger_1.log)('Integration credentials have expired. Requesting a new credentials');
|
|
244
245
|
let newCredentials;
|
|
245
246
|
if (oauthLogin.performRefreshTokenRequest) {
|
|
246
247
|
newCredentials = yield oauthLogin.performRefreshTokenRequest(credentials);
|
|
@@ -264,7 +265,7 @@ function prepareIntegrationCredentials(config, integration, integrationCredentia
|
|
|
264
265
|
if (newCredentials[((_g = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _g === void 0 ? void 0 : _g.refreshToken) || 'refresh_token']) {
|
|
265
266
|
credentials.refreshToken = newCredentials[((_h = oauthLogin === null || oauthLogin === void 0 ? void 0 : oauthLogin.fieldsMapping) === null || _h === void 0 ? void 0 : _h.refreshToken) || 'refresh_token'];
|
|
266
267
|
}
|
|
267
|
-
(0,
|
|
268
|
+
(0, logger_1.log)('Saving updated integration credentials in the database');
|
|
268
269
|
yield (0, storage_1.getStorage)().updateIntegrationCredentials(integrationCredentials.id, (0, _1.encryptData)(config, JSON.stringify(credentials)));
|
|
269
270
|
}
|
|
270
271
|
}
|
|
@@ -304,21 +305,21 @@ function validateSubscription(date) {
|
|
|
304
305
|
const daysLeft = Math.round((date.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
|
|
305
306
|
return { expired, daysLeft };
|
|
306
307
|
}
|
|
307
|
-
function checkSubscription(config, token, organization, accountType) {
|
|
308
|
+
function checkSubscription({ config, token, organization, accountType, }) {
|
|
308
309
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
309
310
|
return __awaiter(this, void 0, void 0, function* () {
|
|
310
311
|
if (isAppFree(config)) {
|
|
311
312
|
return { expired: false };
|
|
312
313
|
}
|
|
313
|
-
(0,
|
|
314
|
+
(0, logger_1.log)('Checking subscription plan');
|
|
314
315
|
const appIdentifier = config.identifier;
|
|
315
316
|
const cacheEntry = getFromCache(organization, appIdentifier);
|
|
316
317
|
if (cacheEntry) {
|
|
317
318
|
const { cacheValidUntil, validUntil, subscribeLink, type } = cacheEntry;
|
|
318
319
|
if (cacheValidUntil.getTime() > Date.now()) {
|
|
319
|
-
(0,
|
|
320
|
+
(0, logger_1.log)(`Loaded data from cache. Subscription is valid until ${validUntil.toISOString()}`);
|
|
320
321
|
const { expired, daysLeft } = validateSubscription(new Date(validUntil));
|
|
321
|
-
(0,
|
|
322
|
+
(0, logger_1.log)(`expired ${expired}`);
|
|
322
323
|
return { expired, subscribeLink, daysLeft, type };
|
|
323
324
|
}
|
|
324
325
|
}
|
|
@@ -329,16 +330,16 @@ function checkSubscription(config, token, organization, accountType) {
|
|
|
329
330
|
token,
|
|
330
331
|
baseUrl: (_a = config.crowdinUrls) === null || _a === void 0 ? void 0 : _a.subscriptionUrl,
|
|
331
332
|
});
|
|
332
|
-
(0,
|
|
333
|
+
(0, logger_1.log)(`Recieved subscription info. ${JSON.stringify(subscription)}`);
|
|
333
334
|
const { expired, daysLeft } = validateSubscription(new Date(subscription.expires));
|
|
334
|
-
(0,
|
|
335
|
+
(0, logger_1.log)(`expired ${expired}`);
|
|
335
336
|
addToCache(organization, appIdentifier, new Date(subscription.expires), models_1.SubscriptionInfoType.SUBSCRIPTION, (_b = config.pricing) === null || _b === void 0 ? void 0 : _b.cachingSeconds);
|
|
336
337
|
return { expired, daysLeft, type: models_1.SubscriptionInfoType.SUBSCRIPTION };
|
|
337
338
|
}
|
|
338
339
|
catch (e) {
|
|
339
340
|
if (e instanceof crowdin_apps_functions_1.PaymentRequiredError) {
|
|
340
341
|
const { initializedAt, subscribeLink } = e;
|
|
341
|
-
(0,
|
|
342
|
+
(0, logger_1.log)(`Recieved 402 payment error. initializedAt ${initializedAt}`);
|
|
342
343
|
//default 2 weeks
|
|
343
344
|
const defaultSubscriptionPlan = 14;
|
|
344
345
|
let days;
|
|
@@ -348,11 +349,11 @@ function checkSubscription(config, token, organization, accountType) {
|
|
|
348
349
|
else {
|
|
349
350
|
days = ((_e = config.pricing) === null || _e === void 0 ? void 0 : _e.trialCrowdin) || ((_f = config.pricing) === null || _f === void 0 ? void 0 : _f.trial) || defaultSubscriptionPlan;
|
|
350
351
|
}
|
|
351
|
-
(0,
|
|
352
|
+
(0, logger_1.log)(`Subscriptino trial plan ${days} days`);
|
|
352
353
|
const date = new Date(initializedAt);
|
|
353
354
|
date.setDate(date.getDate() + days);
|
|
354
355
|
const { expired, daysLeft } = validateSubscription(date);
|
|
355
|
-
(0,
|
|
356
|
+
(0, logger_1.log)(`expired ${expired}`);
|
|
356
357
|
addToCache(organization, appIdentifier, new Date(date), models_1.SubscriptionInfoType.TRIAL, (_g = config.pricing) === null || _g === void 0 ? void 0 : _g.cachingSeconds, subscribeLink);
|
|
357
358
|
return { expired, subscribeLink, daysLeft, type: models_1.SubscriptionInfoType.TRIAL };
|
|
358
359
|
}
|
|
@@ -362,7 +363,7 @@ function checkSubscription(config, token, organization, accountType) {
|
|
|
362
363
|
else {
|
|
363
364
|
console.error(e);
|
|
364
365
|
}
|
|
365
|
-
(0,
|
|
366
|
+
(0, logger_1.log)('Recieved http error from subscription request. Returning expired=false');
|
|
366
367
|
return { expired: false };
|
|
367
368
|
}
|
|
368
369
|
});
|
package/out/util/cron.js
CHANGED
|
@@ -34,21 +34,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
35
|
exports.createOrUpdateSyncSettings = exports.skipFoldersFromIntegrationRequest = exports.filesCron = exports.runJob = void 0;
|
|
36
36
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
37
|
-
const _1 = require(".");
|
|
38
37
|
const models_1 = require("../models");
|
|
39
38
|
const storage_1 = require("../storage");
|
|
40
39
|
const connection_1 = require("./connection");
|
|
41
40
|
const defaults_1 = require("./defaults");
|
|
42
41
|
const file_snapshot_1 = require("./file-snapshot");
|
|
42
|
+
const logger_1 = require("./logger");
|
|
43
43
|
function runJob(config, integration, job) {
|
|
44
44
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
(0,
|
|
45
|
+
(0, logger_1.log)(`Starting cron job with expression [${job.expression}]`);
|
|
46
46
|
const crowdinCredentialsList = yield (0, storage_1.getStorage)().getAllCrowdinCredentials();
|
|
47
47
|
yield Promise.all(crowdinCredentialsList.map((crowdinCredentials) => __awaiter(this, void 0, void 0, function* () {
|
|
48
|
-
const { token, client: crowdinClient } = yield (0, connection_1.prepareCrowdinClient)(
|
|
49
|
-
|
|
48
|
+
const { token, client: crowdinClient } = yield (0, connection_1.prepareCrowdinClient)({
|
|
49
|
+
config,
|
|
50
|
+
credentials: crowdinCredentials,
|
|
51
|
+
autoRenew: true,
|
|
52
|
+
});
|
|
53
|
+
const { expired } = yield (0, connection_1.checkSubscription)({
|
|
54
|
+
config,
|
|
55
|
+
token,
|
|
56
|
+
organization: crowdinCredentials.id,
|
|
57
|
+
accountType: crowdinCredentials.type,
|
|
58
|
+
});
|
|
50
59
|
if (expired) {
|
|
51
|
-
(0,
|
|
60
|
+
(0, logger_1.log)(`Subscription expired. Skipping job [${job.expression}] for organization ${crowdinCredentials.id}`);
|
|
52
61
|
return;
|
|
53
62
|
}
|
|
54
63
|
const integrationCredentialsList = yield (0, storage_1.getStorage)().getAllIntegrationCredentials(crowdinCredentials.id);
|
|
@@ -57,18 +66,18 @@ function runJob(config, integration, job) {
|
|
|
57
66
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
58
67
|
const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient, projectId);
|
|
59
68
|
const intConfig = integrationCredentials.config ? JSON.parse(integrationCredentials.config) : undefined;
|
|
60
|
-
(0,
|
|
69
|
+
(0, logger_1.log)(`Executing task for cron job with expression [${job.expression}] for project ${projectId}`);
|
|
61
70
|
yield job.task(projectId, crowdinClient, apiCredentials, rootFolder, intConfig);
|
|
62
|
-
(0,
|
|
71
|
+
(0, logger_1.log)(`Task for cron job with expression [${job.expression}] for project ${projectId} completed`);
|
|
63
72
|
}
|
|
64
73
|
})));
|
|
65
|
-
(0,
|
|
74
|
+
(0, logger_1.log)(`Cron job with expression [${job.expression}] completed`);
|
|
66
75
|
});
|
|
67
76
|
}
|
|
68
77
|
exports.runJob = runJob;
|
|
69
78
|
function filesCron(config, integration, period) {
|
|
70
79
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
-
(0,
|
|
80
|
+
(0, logger_1.log)(`Starting files cron job with period [${period}]`);
|
|
72
81
|
const syncSettingsList = yield (0, storage_1.getStorage)().getAllSyncSettingsByType('schedule');
|
|
73
82
|
yield Promise.all(syncSettingsList.map((syncSettings) => __awaiter(this, void 0, void 0, function* () {
|
|
74
83
|
var _a;
|
|
@@ -86,10 +95,19 @@ function filesCron(config, integration, period) {
|
|
|
86
95
|
return;
|
|
87
96
|
}
|
|
88
97
|
const projectId = crowdinAppFunctions.getProjectId(integrationCredentials.id);
|
|
89
|
-
const { client: crowdinClient, token } = yield (0, connection_1.prepareCrowdinClient)(
|
|
90
|
-
|
|
98
|
+
const { client: crowdinClient, token } = yield (0, connection_1.prepareCrowdinClient)({
|
|
99
|
+
config,
|
|
100
|
+
credentials: crowdinCredentials,
|
|
101
|
+
autoRenew: true,
|
|
102
|
+
});
|
|
103
|
+
const { expired } = yield (0, connection_1.checkSubscription)({
|
|
104
|
+
config,
|
|
105
|
+
token,
|
|
106
|
+
organization: crowdinCredentials.id,
|
|
107
|
+
accountType: crowdinCredentials.type,
|
|
108
|
+
});
|
|
91
109
|
if (expired) {
|
|
92
|
-
(0,
|
|
110
|
+
(0, logger_1.log)(`Subscription expired. Skipping job [${period}] for organization ${crowdinCredentials.id}`);
|
|
93
111
|
return;
|
|
94
112
|
}
|
|
95
113
|
const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, crowdinClient, projectId);
|
|
@@ -115,10 +133,10 @@ function filesCron(config, integration, period) {
|
|
|
115
133
|
const filesToProcess = all
|
|
116
134
|
? crowdinFiles
|
|
117
135
|
: yield getOnlyTranslatedOrApprovedFiles(config, projectId, crowdinFiles, crowdinClient, onlyApproved, onlyTranslated);
|
|
118
|
-
(0,
|
|
136
|
+
(0, logger_1.log)(`Executing updateIntegration task for files cron job with period [${period}] for project ${projectId}.Files ${Object.keys(filesToProcess).length}`);
|
|
119
137
|
if (!all) {
|
|
120
138
|
if (Object.keys(filesToProcess).length === 0) {
|
|
121
|
-
(0,
|
|
139
|
+
(0, logger_1.log)(`There is no ${onlyApproved ? 'approved' : 'translated'} file`);
|
|
122
140
|
return;
|
|
123
141
|
}
|
|
124
142
|
}
|
|
@@ -129,7 +147,7 @@ function filesCron(config, integration, period) {
|
|
|
129
147
|
const currentFileSnapshot = yield (0, file_snapshot_1.getCrowdinSnapshot)(config, integration, crowdinClient, projectId, intConfig);
|
|
130
148
|
yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(currentFileSnapshot), syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
|
|
131
149
|
}
|
|
132
|
-
(0,
|
|
150
|
+
(0, logger_1.log)(`updateIntegration task for files cron job with period [${period}] for project ${projectId} completed`);
|
|
133
151
|
}
|
|
134
152
|
else {
|
|
135
153
|
const allIntFiles = [...files, ...newFiles].map((file) => (Object.assign({ id: file.id, name: file.name, parentId: file.parent_id || file.parentId,
|
|
@@ -138,7 +156,7 @@ function filesCron(config, integration, period) {
|
|
|
138
156
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
139
157
|
node_type: file.nodeType || file.node_type }, (file.type ? { type: file.type } : {}))));
|
|
140
158
|
const intFiles = allIntFiles.filter((file) => 'type' in file);
|
|
141
|
-
(0,
|
|
159
|
+
(0, logger_1.log)(`Executing updateCrowdin task for files cron job with period [${period}] for project ${projectId}. Files ${intFiles.length}`);
|
|
142
160
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
143
161
|
yield integration.updateCrowdin(projectId, crowdinClient, apiCredentials, intFiles, rootFolder, intConfig);
|
|
144
162
|
const newSyncSettingsFiels = allIntFiles.map((file) => (Object.assign(Object.assign({}, file), { schedule: true, sync: false })));
|
|
@@ -147,16 +165,16 @@ function filesCron(config, integration, period) {
|
|
|
147
165
|
const currentFileSnapshot = yield (0, file_snapshot_1.getIntegrationSnapshot)(integration, apiCredentials, intConfig);
|
|
148
166
|
yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(currentFileSnapshot), syncSettings.integrationId, syncSettings.crowdinId, syncSettings.provider);
|
|
149
167
|
}
|
|
150
|
-
(0,
|
|
168
|
+
(0, logger_1.log)(`updateCrowdin task for files cron job with period [${period}] for project ${projectId} completed`);
|
|
151
169
|
}
|
|
152
170
|
})));
|
|
153
|
-
(0,
|
|
171
|
+
(0, logger_1.log)(`Files cron job with period [${period}] completed`);
|
|
154
172
|
});
|
|
155
173
|
}
|
|
156
174
|
exports.filesCron = filesCron;
|
|
157
175
|
function getOnlyTranslatedOrApprovedFiles(config, projectId, crowdinFiles, crowdinClient, onlyApproved, onlyTranslated) {
|
|
158
176
|
return __awaiter(this, void 0, void 0, function* () {
|
|
159
|
-
(0,
|
|
177
|
+
(0, logger_1.log)(`Filtering files to process only ${onlyApproved ? 'approved' : 'translated'} files`);
|
|
160
178
|
const filesInfo = yield Promise.all(Object.keys(crowdinFiles).map((fileId) => __awaiter(this, void 0, void 0, function* () {
|
|
161
179
|
const res = yield crowdinClient.translationStatusApi
|
|
162
180
|
.withFetchAll()
|
|
@@ -180,26 +198,26 @@ function getOnlyTranslatedOrApprovedFiles(config, projectId, crowdinFiles, crowd
|
|
|
180
198
|
}
|
|
181
199
|
if (onlyTranslated) {
|
|
182
200
|
if (languageInfo.translationProgress === 100) {
|
|
183
|
-
(0,
|
|
201
|
+
(0, logger_1.log)(`File ${fileId} is fully translated for language ${language}`);
|
|
184
202
|
if (!filteredFiles[fileId]) {
|
|
185
203
|
filteredFiles[fileId] = [];
|
|
186
204
|
}
|
|
187
205
|
filteredFiles[fileId].push(language);
|
|
188
206
|
}
|
|
189
207
|
else {
|
|
190
|
-
(0,
|
|
208
|
+
(0, logger_1.log)(`File ${fileId} is not fully translated for language ${language}, progress ${languageInfo.translationProgress}`);
|
|
191
209
|
}
|
|
192
210
|
}
|
|
193
211
|
if (onlyApproved) {
|
|
194
212
|
if (languageInfo.approvalProgress === 100) {
|
|
195
|
-
(0,
|
|
213
|
+
(0, logger_1.log)(`File ${fileId} is fully approved for language ${language}`);
|
|
196
214
|
if (!filteredFiles[fileId]) {
|
|
197
215
|
filteredFiles[fileId] = [];
|
|
198
216
|
}
|
|
199
217
|
filteredFiles[fileId].push(language);
|
|
200
218
|
}
|
|
201
219
|
else {
|
|
202
|
-
(0,
|
|
220
|
+
(0, logger_1.log)(`File ${fileId} is not fully approved for language ${language}, progress ${languageInfo.approvalProgress}`);
|
|
203
221
|
}
|
|
204
222
|
}
|
|
205
223
|
});
|
|
@@ -238,11 +256,11 @@ function createOrUpdateSyncSettings(config, req, files, provider, onlyCreate = f
|
|
|
238
256
|
return __awaiter(this, void 0, void 0, function* () {
|
|
239
257
|
const existingSettings = yield (0, storage_1.getStorage)().getSyncSettings(req.crowdinContext.clientId, req.crowdinContext.crowdinId, 'schedule', provider);
|
|
240
258
|
if (!existingSettings) {
|
|
241
|
-
(0,
|
|
259
|
+
(0, logger_1.log)(`Saving sync settings for type schedule and provider ${provider} ${JSON.stringify(files, null, 2)}`);
|
|
242
260
|
yield (0, storage_1.getStorage)().saveSyncSettings(JSON.stringify(files), req.crowdinContext.clientId, req.crowdinContext.crowdinId, 'schedule', provider);
|
|
243
261
|
}
|
|
244
262
|
else if (!onlyCreate) {
|
|
245
|
-
(0,
|
|
263
|
+
(0, logger_1.log)(`Updating sync settings for type schedule and provider ${provider} ${JSON.stringify(files, null, 2)}`);
|
|
246
264
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(files), req.crowdinContext.clientId, req.crowdinContext.crowdinId, 'schedule', provider);
|
|
247
265
|
}
|
|
248
266
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Config, GetAllNewFilesArgs, IntegrationLogic, IntegrationRequest, Provider, TreeItem, UpdateIntegrationRequest } from '../models';
|
|
2
1
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
+
import { Config, GetAllNewFilesArgs, IntegrationLogic, IntegrationRequest, Provider, TreeItem, UpdateIntegrationRequest } from '../models';
|
|
3
3
|
export declare function getFileDiff(currentFiles: TreeItem[], savedFiles: TreeItem[]): TreeItem[];
|
|
4
4
|
export declare function getAllNewFiles(args: GetAllNewFilesArgs): Promise<TreeItem[] | UpdateIntegrationRequest>;
|
|
5
5
|
export declare function getCrowdinSnapshot(config: Config, integration: IntegrationLogic, crowdinApiClient: Crowdin, projectId: number, integrationSettings: any): Promise<TreeItem[]>;
|
|
@@ -11,9 +11,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.createOrUpdateFileSnapshot = exports.getIntegrationSnapshot = exports.getCrowdinSnapshot = exports.getAllNewFiles = exports.getFileDiff = void 0;
|
|
13
13
|
const models_1 = require("../models");
|
|
14
|
-
const index_1 = require("./index");
|
|
15
|
-
const defaults_1 = require("./defaults");
|
|
16
14
|
const storage_1 = require("../storage");
|
|
15
|
+
const defaults_1 = require("./defaults");
|
|
16
|
+
const index_1 = require("./index");
|
|
17
17
|
function getFileDiff(currentFiles, savedFiles) {
|
|
18
18
|
return currentFiles.filter((x) => !savedFiles.some((x2) => x2.id === x.id));
|
|
19
19
|
}
|
|
@@ -138,11 +138,11 @@ function createOrUpdateFileSnapshot(config, integration, req, provider) {
|
|
|
138
138
|
files = yield getIntegrationSnapshot(integration, req.integrationCredentials, req.integrationSettings);
|
|
139
139
|
}
|
|
140
140
|
if (existingSnapshot) {
|
|
141
|
-
|
|
141
|
+
req.logInfo(`Updating file snapshot for provider ${provider} ${JSON.stringify(files, null, 2)}`);
|
|
142
142
|
yield (0, storage_1.getStorage)().updateFilesSnapshot(JSON.stringify(files), req.crowdinContext.clientId, req.crowdinContext.crowdinId, provider);
|
|
143
143
|
}
|
|
144
144
|
else {
|
|
145
|
-
|
|
145
|
+
req.logInfo(`Saving file snapshot for provider ${provider} ${JSON.stringify(files, null, 2)}`);
|
|
146
146
|
yield (0, storage_1.getStorage)().saveFilesSnapshot(JSON.stringify(files), req.crowdinContext.clientId, req.crowdinContext.crowdinId, provider);
|
|
147
147
|
}
|
|
148
148
|
});
|
package/out/util/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { Request, Response } from 'express';
|
|
2
|
-
import { Config,
|
|
2
|
+
import { Config, CrowdinClientRequest, ExtendedResult, ImagePath } from '../models';
|
|
3
3
|
export declare class CodeError extends Error {
|
|
4
4
|
code: number | undefined;
|
|
5
5
|
constructor(message: string, code?: number);
|
|
6
6
|
}
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function getMessage(err: any): any;
|
|
9
|
-
export declare function runAsyncWrapper(callback: Function, onError?: (e: any) => void): (req: Request, res: Response, next: Function) => void;
|
|
10
|
-
export declare function logError(e: any, onError?: (e: any) => void): void;
|
|
7
|
+
export declare function runAsyncWrapper(callback: Function): (req: Request | CrowdinClientRequest, res: Response, next: Function) => void;
|
|
11
8
|
export declare function encryptData(config: Config, data: string): string;
|
|
12
9
|
export declare function decryptData(config: Config, data: string): string;
|
|
13
10
|
export declare function executeWithRetry<T>(func: () => Promise<T>, numOfRetries?: number): Promise<T>;
|
|
14
11
|
export declare function isExtendedResultType<T>(data?: T | ExtendedResult<T>): data is ExtendedResult<T>;
|
|
15
|
-
export declare function getLogoUrl(
|
|
12
|
+
export declare function getLogoUrl(moduleConfig?: ImagePath, modulePath?: string): string;
|