@crowdin/app-project-module 0.36.0 → 0.38.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/out/handlers/manifest.js +12 -0
- package/out/index.js +3 -0
- package/out/middlewares/crowdin-client.js +1 -1
- package/out/middlewares/ui-module.js +4 -3
- package/out/models/index.d.ts +22 -2
- package/out/models/index.js +8 -8
- package/out/static/js/form.js +6 -6
- package/out/static/js/main.js +0 -1
- package/out/util/connection.d.ts +3 -2
- package/out/util/connection.js +7 -1
- package/out/util/cron.js +29 -2
- package/out/util/logger.d.ts +15 -0
- package/out/util/logger.js +73 -8
- package/out/util/webhooks.js +18 -2
- package/package.json +3 -3
package/out/static/js/main.js
CHANGED
package/out/util/connection.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
-
import { AccountType, Config, CrowdinCredentials, IntegrationCredentials, IntegrationLogic, SubscriptionInfo } from '../models';
|
|
3
|
-
export declare function prepareCrowdinClient({ config, credentials, autoRenew, }: {
|
|
2
|
+
import { AccountType, Config, CrowdinContextInfo, CrowdinCredentials, IntegrationCredentials, IntegrationLogic, SubscriptionInfo } from '../models';
|
|
3
|
+
export declare function prepareCrowdinClient({ config, credentials, autoRenew, context, }: {
|
|
4
4
|
config: Config;
|
|
5
5
|
credentials: CrowdinCredentials;
|
|
6
6
|
autoRenew?: boolean;
|
|
7
|
+
context?: CrowdinContextInfo;
|
|
7
8
|
}): Promise<{
|
|
8
9
|
client: Crowdin;
|
|
9
10
|
token: string;
|
package/out/util/connection.js
CHANGED
|
@@ -54,7 +54,7 @@ function refreshToken(config, credentials) {
|
|
|
54
54
|
};
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
-
function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
57
|
+
function prepareCrowdinClient({ config, credentials, autoRenew = false, context, }) {
|
|
58
58
|
var _a, _b;
|
|
59
59
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
60
|
//2 min as an extra buffer
|
|
@@ -114,6 +114,7 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
|
114
114
|
const res = yield axiosCustom.get(url, getHttpConfig(httpConfig));
|
|
115
115
|
return res.data;
|
|
116
116
|
}
|
|
117
|
+
(0, logger_1.logError)(e, context);
|
|
117
118
|
throw e;
|
|
118
119
|
}
|
|
119
120
|
});
|
|
@@ -130,6 +131,7 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
|
130
131
|
const res = yield axiosCustom.delete(url, getHttpConfig(httpConfig));
|
|
131
132
|
return res.data;
|
|
132
133
|
}
|
|
134
|
+
(0, logger_1.logError)(e, context);
|
|
133
135
|
throw e;
|
|
134
136
|
}
|
|
135
137
|
});
|
|
@@ -146,6 +148,7 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
|
146
148
|
const res = yield axiosCustom.head(url, getHttpConfig(httpConfig));
|
|
147
149
|
return res.data;
|
|
148
150
|
}
|
|
151
|
+
(0, logger_1.logError)(e, context);
|
|
149
152
|
throw e;
|
|
150
153
|
}
|
|
151
154
|
});
|
|
@@ -162,6 +165,7 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
|
162
165
|
const res = yield axiosCustom.patch(url, data, getHttpConfig(httpConfig));
|
|
163
166
|
return res.data;
|
|
164
167
|
}
|
|
168
|
+
(0, logger_1.logError)(e, context);
|
|
165
169
|
throw e;
|
|
166
170
|
}
|
|
167
171
|
});
|
|
@@ -178,6 +182,7 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
|
178
182
|
const res = yield axiosCustom.post(url, data, getHttpConfig(httpConfig));
|
|
179
183
|
return res.data;
|
|
180
184
|
}
|
|
185
|
+
(0, logger_1.logError)(e, context);
|
|
181
186
|
throw e;
|
|
182
187
|
}
|
|
183
188
|
});
|
|
@@ -194,6 +199,7 @@ function prepareCrowdinClient({ config, credentials, autoRenew = false, }) {
|
|
|
194
199
|
const res = yield axiosCustom.put(url, data, getHttpConfig(httpConfig));
|
|
195
200
|
return res.data;
|
|
196
201
|
}
|
|
202
|
+
(0, logger_1.logError)(e, context);
|
|
197
203
|
throw e;
|
|
198
204
|
}
|
|
199
205
|
});
|
package/out/util/cron.js
CHANGED
|
@@ -95,10 +95,25 @@ function filesCron(config, integration, period) {
|
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
const projectId = crowdinAppFunctions.getProjectId(integrationCredentials.id);
|
|
98
|
+
const context = {
|
|
99
|
+
jwtPayload: {
|
|
100
|
+
context: {
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
102
|
+
project_id: projectId,
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
104
|
+
organization_id: crowdinCredentials.organizationId,
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
106
|
+
organization_domain: crowdinCredentials.domain,
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
108
|
+
user_id: crowdinCredentials.userId,
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
};
|
|
98
112
|
const { client: crowdinClient, token } = yield (0, connection_1.prepareCrowdinClient)({
|
|
99
113
|
config,
|
|
100
114
|
credentials: crowdinCredentials,
|
|
101
115
|
autoRenew: true,
|
|
116
|
+
context,
|
|
102
117
|
});
|
|
103
118
|
const { expired } = yield (0, connection_1.checkSubscription)({
|
|
104
119
|
config,
|
|
@@ -159,7 +174,13 @@ function filesCron(config, integration, period) {
|
|
|
159
174
|
}
|
|
160
175
|
}
|
|
161
176
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
162
|
-
|
|
177
|
+
try {
|
|
178
|
+
yield integration.updateIntegration(projectId, crowdinClient, apiCredentials, filesToProcess, rootFolder, intConfig);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
(0, logger_1.logError)(e, context);
|
|
182
|
+
throw e;
|
|
183
|
+
}
|
|
163
184
|
if (Object.keys(newFiles).length) {
|
|
164
185
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(Object.assign(Object.assign({}, files), newFiles)), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
|
|
165
186
|
const currentFileSnapshot = yield (0, file_snapshot_1.getCrowdinSnapshot)(config, integration, crowdinClient, projectId, intConfig);
|
|
@@ -176,7 +197,13 @@ function filesCron(config, integration, period) {
|
|
|
176
197
|
const intFiles = allIntFiles.filter((file) => 'type' in file);
|
|
177
198
|
(0, logger_1.log)(`Executing updateCrowdin task for files cron job with period [${period}] for project ${projectId}. Files ${intFiles.length}`);
|
|
178
199
|
const apiCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
179
|
-
|
|
200
|
+
try {
|
|
201
|
+
yield integration.updateCrowdin(projectId, crowdinClient, apiCredentials, intFiles, rootFolder, intConfig);
|
|
202
|
+
}
|
|
203
|
+
catch (e) {
|
|
204
|
+
(0, logger_1.logError)(e, context);
|
|
205
|
+
throw e;
|
|
206
|
+
}
|
|
180
207
|
if (Object.keys(newFiles).length) {
|
|
181
208
|
const newSyncSettingsFields = allIntFiles.map((file) => (Object.assign(Object.assign({}, file), { schedule: true, sync: false })));
|
|
182
209
|
yield (0, storage_1.getStorage)().updateSyncSettings(JSON.stringify(newSyncSettingsFields), syncSettings.integrationId, syncSettings.crowdinId, 'schedule', syncSettings.provider);
|
package/out/util/logger.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AxiosError } from 'axios';
|
|
1
2
|
import { Config, CrowdinContextInfo } from '../models';
|
|
2
3
|
export type LogFunction = (message: string) => void;
|
|
3
4
|
export type LogErrorFunction = (error: any) => void;
|
|
@@ -12,4 +13,18 @@ export declare function withContext(context: CrowdinContextInfo): LogFunction;
|
|
|
12
13
|
export declare function withContextError(context: CrowdinContextInfo): LogFunction;
|
|
13
14
|
export declare function log(message: string, context?: CrowdinContextInfo): void;
|
|
14
15
|
export declare function logError(e: any, context?: CrowdinContextInfo): void;
|
|
16
|
+
export declare function isAxiosError(e: any): e is CustomAxiosError;
|
|
15
17
|
export declare function getErrorMessage(err: any): any;
|
|
18
|
+
interface CustomAxiosError extends AxiosError {
|
|
19
|
+
data?: any;
|
|
20
|
+
}
|
|
21
|
+
export declare class AppModuleError extends Error {
|
|
22
|
+
data: any;
|
|
23
|
+
isAxiosError: boolean;
|
|
24
|
+
constructor(error: CustomAxiosError | Error | string, data?: any);
|
|
25
|
+
}
|
|
26
|
+
export declare class AppModuleAggregateError extends Error {
|
|
27
|
+
errors: Error[] | AppModuleError[];
|
|
28
|
+
constructor(errors: Error[] | AppModuleError[], message: string);
|
|
29
|
+
}
|
|
30
|
+
export {};
|
package/out/util/logger.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.getErrorMessage = exports.logError = exports.log = exports.withContextError = exports.withContext = exports.prepareContext = exports.initialize = void 0;
|
|
26
|
+
exports.AppModuleAggregateError = exports.AppModuleError = exports.getErrorMessage = exports.isAxiosError = exports.logError = exports.log = exports.withContextError = exports.withContext = exports.prepareContext = exports.initialize = void 0;
|
|
27
27
|
const logsFormatter = __importStar(require("@crowdin/logs-formatter"));
|
|
28
28
|
let logConfig;
|
|
29
29
|
let onError;
|
|
@@ -49,6 +49,7 @@ function withContextError(context) {
|
|
|
49
49
|
}
|
|
50
50
|
exports.withContextError = withContextError;
|
|
51
51
|
function log(message, context) {
|
|
52
|
+
var _a, _b, _c;
|
|
52
53
|
if (logConfig === null || logConfig === void 0 ? void 0 : logConfig.enabled) {
|
|
53
54
|
if (logConfig.log) {
|
|
54
55
|
logConfig.log(message, context);
|
|
@@ -59,11 +60,20 @@ function log(message, context) {
|
|
|
59
60
|
logsFormatter.setContext({
|
|
60
61
|
project: {
|
|
61
62
|
id: context.jwtPayload.context.project_id,
|
|
63
|
+
identifier: (_a = context.jwtPayload.context.project_identifier) !== null && _a !== void 0 ? _a : '',
|
|
62
64
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
63
65
|
organization_id: context.jwtPayload.context.organization_id,
|
|
64
66
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
65
67
|
user_id: context.jwtPayload.context.user_id,
|
|
66
68
|
},
|
|
69
|
+
user: {
|
|
70
|
+
id: context.jwtPayload.context.user_id,
|
|
71
|
+
login: (_b = context.jwtPayload.context.user_login) !== null && _b !== void 0 ? _b : '',
|
|
72
|
+
},
|
|
73
|
+
organization: {
|
|
74
|
+
id: context.jwtPayload.context.organization_id,
|
|
75
|
+
domain: (_c = context.jwtPayload.context.organization_domain) !== null && _c !== void 0 ? _c : '',
|
|
76
|
+
},
|
|
67
77
|
});
|
|
68
78
|
prefix += ` Context [${JSON.stringify(prepareContext(context))}]`;
|
|
69
79
|
}
|
|
@@ -74,37 +84,71 @@ function log(message, context) {
|
|
|
74
84
|
}
|
|
75
85
|
exports.log = log;
|
|
76
86
|
function logError(e, context) {
|
|
87
|
+
var _a, _b, _c;
|
|
77
88
|
if (onError) {
|
|
78
89
|
onError(e, context);
|
|
79
90
|
}
|
|
80
91
|
else {
|
|
81
|
-
let message = `[${new Date().toISOString()}] Error.`;
|
|
82
92
|
if (context) {
|
|
83
93
|
logsFormatter.setContext({
|
|
84
94
|
project: {
|
|
85
95
|
id: context.jwtPayload.context.project_id,
|
|
96
|
+
identifier: (_a = context.jwtPayload.context.project_identifier) !== null && _a !== void 0 ? _a : '',
|
|
86
97
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
87
98
|
organization_id: context.jwtPayload.context.organization_id,
|
|
88
99
|
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
89
100
|
user_id: context.jwtPayload.context.user_id,
|
|
90
101
|
},
|
|
102
|
+
user: {
|
|
103
|
+
id: context.jwtPayload.context.user_id,
|
|
104
|
+
login: (_b = context.jwtPayload.context.user_login) !== null && _b !== void 0 ? _b : '',
|
|
105
|
+
},
|
|
106
|
+
organization: {
|
|
107
|
+
id: context.jwtPayload.context.organization_id,
|
|
108
|
+
domain: (_c = context.jwtPayload.context.organization_domain) !== null && _c !== void 0 ? _c : '',
|
|
109
|
+
},
|
|
91
110
|
});
|
|
92
|
-
message += ` Context ${JSON.stringify(prepareContext(context))}`;
|
|
93
111
|
}
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
112
|
+
if (e instanceof AppModuleAggregateError) {
|
|
113
|
+
if (e.errors && e.errors.length > 0) {
|
|
114
|
+
for (const error of e.errors) {
|
|
115
|
+
errorOutputByType(error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
98
118
|
}
|
|
99
119
|
else {
|
|
100
|
-
|
|
120
|
+
errorOutputByType(e);
|
|
101
121
|
}
|
|
102
122
|
}
|
|
103
123
|
}
|
|
104
124
|
exports.logError = logError;
|
|
125
|
+
function errorOutputByType(error) {
|
|
126
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
127
|
+
const message = error.message || error;
|
|
128
|
+
if (isAxiosError(error)) {
|
|
129
|
+
const request = error.config || error.data.config
|
|
130
|
+
? {
|
|
131
|
+
url: ((_a = error.config) === null || _a === void 0 ? void 0 : _a.url) || ((_b = error.data) === null || _b === void 0 ? void 0 : _b.config.url),
|
|
132
|
+
method: ((_c = error.config) === null || _c === void 0 ? void 0 : _c.method) || ((_d = error.data) === null || _d === void 0 ? void 0 : _d.config.method),
|
|
133
|
+
data: ((_e = error.config) === null || _e === void 0 ? void 0 : _e.data) || ((_f = error.data) === null || _f === void 0 ? void 0 : _f.config.data),
|
|
134
|
+
}
|
|
135
|
+
: {};
|
|
136
|
+
const response = error.response || error.data.response
|
|
137
|
+
? {
|
|
138
|
+
data: ((_g = error.response) === null || _g === void 0 ? void 0 : _g.data) || ((_h = error.data) === null || _h === void 0 ? void 0 : _h.response.data),
|
|
139
|
+
status: ((_j = error.response) === null || _j === void 0 ? void 0 : _j.status) || ((_k = error.data) === null || _k === void 0 ? void 0 : _k.response.status),
|
|
140
|
+
}
|
|
141
|
+
: {};
|
|
142
|
+
console.error(message, { attributes: { request, response } }, { backtrace: error.stack });
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
console.error(message, error.data ? { attributes: error.data } : '', error.stack ? { backtrace: error.stack } : '');
|
|
146
|
+
}
|
|
147
|
+
}
|
|
105
148
|
function isAxiosError(e) {
|
|
106
149
|
return !!e.isAxiosError;
|
|
107
150
|
}
|
|
151
|
+
exports.isAxiosError = isAxiosError;
|
|
108
152
|
function getErrorMessage(err) {
|
|
109
153
|
let message;
|
|
110
154
|
if (typeof err === 'string') {
|
|
@@ -119,3 +163,24 @@ function getErrorMessage(err) {
|
|
|
119
163
|
return message;
|
|
120
164
|
}
|
|
121
165
|
exports.getErrorMessage = getErrorMessage;
|
|
166
|
+
class AppModuleError extends Error {
|
|
167
|
+
constructor(error, data) {
|
|
168
|
+
super(typeof error === 'string' ? error : error.message);
|
|
169
|
+
this.isAxiosError = false;
|
|
170
|
+
this.name = 'AppModuleError';
|
|
171
|
+
this.data = typeof error === 'string' ? Object.assign({}, data) : Object.assign(Object.assign({}, error), data);
|
|
172
|
+
this.stack = typeof error === 'string' ? this.stack : error.stack;
|
|
173
|
+
if (isAxiosError(error)) {
|
|
174
|
+
this.isAxiosError = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
exports.AppModuleError = AppModuleError;
|
|
179
|
+
class AppModuleAggregateError extends Error {
|
|
180
|
+
constructor(errors, message) {
|
|
181
|
+
super(message);
|
|
182
|
+
this.name = 'AppModuleAggregateError';
|
|
183
|
+
this.errors = errors;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.AppModuleAggregateError = AppModuleAggregateError;
|
package/out/util/webhooks.js
CHANGED
|
@@ -91,7 +91,7 @@ function registerWebhooks(config, integration, client, crowdinContext, apiCreden
|
|
|
91
91
|
const webhookName = `${config.name} application hook ${crowdinContext.jwtPayload.sub}`;
|
|
92
92
|
const webhookUrl = makeCrowdinWebhookUrl(config, integration, crowdinContext);
|
|
93
93
|
const syncCondition = models_1.SyncCondition[Number(appSettings.condition)];
|
|
94
|
-
const events = HookConditionEvents[syncCondition];
|
|
94
|
+
const events = [...HookConditionEvents[syncCondition]];
|
|
95
95
|
const webhook = yield getCrowdinProjectWebhook(config, client, projectId, webhookName);
|
|
96
96
|
if (appSettings['new-crowdin-files']) {
|
|
97
97
|
events.push(exports.HookEvents.fileAdded);
|
|
@@ -226,8 +226,24 @@ function prepareWebhookData(config, integration, webhookUrlParam, provider) {
|
|
|
226
226
|
let appSettings = {};
|
|
227
227
|
const { projectId, crowdinId, clientId } = decodedUrlParam(config, webhookUrlParam);
|
|
228
228
|
const crowdinCredentials = yield (0, storage_1.getStorage)().getCrowdinCredentials(crowdinId);
|
|
229
|
-
const crowdinClient = yield (0, connection_1.prepareCrowdinClient)({ config, credentials: crowdinCredentials });
|
|
230
229
|
const integrationCredentials = yield (0, storage_1.getStorage)().getIntegrationCredentials(clientId);
|
|
230
|
+
const context = {
|
|
231
|
+
jwtPayload: {
|
|
232
|
+
context: {
|
|
233
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
234
|
+
project_id: projectId,
|
|
235
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
236
|
+
organization_id: crowdinCredentials === null || crowdinCredentials === void 0 ? void 0 : crowdinCredentials.organizationId,
|
|
237
|
+
// eslint-disable-next-line @typescript-eslint/camelcase
|
|
238
|
+
user_id: crowdinCredentials === null || crowdinCredentials === void 0 ? void 0 : crowdinCredentials.userId,
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
const crowdinClient = yield (0, connection_1.prepareCrowdinClient)({
|
|
243
|
+
config,
|
|
244
|
+
credentials: crowdinCredentials,
|
|
245
|
+
context,
|
|
246
|
+
});
|
|
231
247
|
const preparedIntegrationCredentials = yield (0, connection_1.prepareIntegrationCredentials)(config, integration, integrationCredentials);
|
|
232
248
|
if (integrationCredentials === null || integrationCredentials === void 0 ? void 0 : integrationCredentials.config) {
|
|
233
249
|
appSettings = JSON.parse(integrationCredentials.config);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crowdin/app-project-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"description": "Module that generates for you all common endpoints for serving standalone Crowdin App",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"types": "out/index.d.ts",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@aws-sdk/client-s3": "^3.423.0",
|
|
18
18
|
"@aws-sdk/s3-request-presigner": "^3.423.0",
|
|
19
|
-
"@crowdin/crowdin-apps-functions": "0.
|
|
20
|
-
"@crowdin/logs-formatter": "^2.0.
|
|
19
|
+
"@crowdin/crowdin-apps-functions": "0.6.0",
|
|
20
|
+
"@crowdin/logs-formatter": "^2.0.5",
|
|
21
21
|
"@godaddy/terminus": "^4.12.1",
|
|
22
22
|
"@types/pg": "^8.10.3",
|
|
23
23
|
"amqplib": "^0.10.3",
|