@crowdin/app-project-module 0.105.0 → 0.106.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.
@@ -63,7 +63,8 @@ function handle(config, integration) {
63
63
  message.data = oauthCredentials;
64
64
  if (((_o = integration.oauthLogin) === null || _o === void 0 ? void 0 : _o.mode) === 'polling') {
65
65
  yield (0, storage_1.getStorage)().deleteMetadata((0, defaults_1.getOAuthPollingId)(clientId));
66
- yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthPollingId)(clientId), oauthCredentials, organization);
66
+ const encryptedCredentials = (0, util_1.encryptData)(config, JSON.stringify(oauthCredentials));
67
+ yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthPollingId)(clientId), encryptedCredentials, organization);
67
68
  }
68
69
  return res.render('oauth', { message: JSON.stringify(message), oauthMode: (_p = integration.oauthLogin) === null || _p === void 0 ? void 0 : _p.mode });
69
70
  }
@@ -1,5 +1,5 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- import { CrowdinClientRequest } from '../../../types';
3
+ import { Config, CrowdinClientRequest } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(integration: IntegrationLogic): (req: CrowdinClientRequest | 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;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: CrowdinClientRequest | 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;
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const storage_1 = require("../../../storage");
13
13
  const util_1 = require("../../../util");
14
14
  const defaults_1 = require("../util/defaults");
15
- function handle(integration) {
15
+ function handle(config, integration) {
16
16
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
17
17
  req.logInfo('Received OAuth polling request');
18
18
  const { oauthLogin } = integration;
@@ -22,9 +22,11 @@ function handle(integration) {
22
22
  return;
23
23
  }
24
24
  const oauthId = (0, defaults_1.getOAuthPollingId)(req.crowdinContext.clientId);
25
- const oauthCreds = yield (0, storage_1.getStorage)().getMetadata(oauthId);
26
- if (oauthCreds) {
25
+ const encryptedCreds = yield (0, storage_1.getStorage)().getMetadata(oauthId);
26
+ let oauthCreds;
27
+ if (encryptedCreds) {
27
28
  yield (0, storage_1.getStorage)().deleteMetadata(oauthId);
29
+ oauthCreds = JSON.parse((0, util_1.decryptData)(config, encryptedCreds));
28
30
  }
29
31
  res.send({ oauthCreds });
30
32
  }));
@@ -194,7 +194,7 @@ function register({ config, app }) {
194
194
  optional: false,
195
195
  checkSubscriptionExpiration: false,
196
196
  moduleKey: integrationLogic.key,
197
- }), (0, oauth_polling_1.default)(integrationLogic));
197
+ }), (0, oauth_polling_1.default)(config, integrationLogic));
198
198
  }
199
199
  }
200
200
  if (integrationLogic.cronJobs) {
@@ -61,7 +61,6 @@ function applyIntegrationModuleDefaults(config, integration) {
61
61
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
62
62
  if (!integration.getCrowdinFiles) {
63
63
  integration.getCrowdinFiles = (projectId, client, rootFolder, config, mode) => __awaiter(this, void 0, void 0, function* () {
64
- const allBranches = (yield client.sourceFilesApi.withFetchAll().listProjectBranches(projectId)).data.map((d) => d.data);
65
64
  let options = {};
66
65
  if (rootFolder) {
67
66
  options = {
@@ -69,23 +68,38 @@ function applyIntegrationModuleDefaults(config, integration) {
69
68
  recursion: 'true',
70
69
  };
71
70
  }
71
+ const needDirectories = !mode || mode === 'directories' || mode === 'files';
72
+ const needFiles = !mode || mode === 'files';
73
+ const [branchesResponse, directoriesResponse, filesResponse] = yield Promise.all([
74
+ client.sourceFilesApi.withFetchAll().listProjectBranches(projectId),
75
+ needDirectories
76
+ ? client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)
77
+ : { data: [] },
78
+ needFiles ? client.sourceFilesApi.withFetchAll().listProjectFiles(projectId, options) : { data: [] },
79
+ ]);
80
+ const allBranches = branchesResponse.data.map((d) => d.data);
81
+ const allDirectories = directoriesResponse.data.map((d) => d.data);
82
+ const allFiles = filesResponse.data.map((d) => d.data);
83
+ const branchesMap = new Map(allBranches.map((b) => [b.id, b]));
84
+ const addedBranchIds = new Set();
72
85
  const res = [];
86
+ const addBranchIfNeeded = (branchId) => {
87
+ const branch = branchesMap.get(branchId);
88
+ if (branch && !addedBranchIds.has(branch.id)) {
89
+ addedBranchIds.add(branch.id);
90
+ res.push({
91
+ id: branch.id.toString(),
92
+ name: branch.name,
93
+ nodeType: '2',
94
+ });
95
+ }
96
+ return branch === null || branch === void 0 ? void 0 : branch.id;
97
+ };
73
98
  if (!mode || mode === 'directories') {
74
- const allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)).data.map((d) => d.data);
75
99
  allDirectories.forEach((e) => {
76
100
  let parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
77
101
  if (!parentId && e.branchId) {
78
- const branch = allBranches.find((branch) => branch.id === e.branchId);
79
- if (branch) {
80
- parentId = branch.id;
81
- if (!res.find((node) => node.id === branch.id.toString())) {
82
- res.push({
83
- id: branch.id.toString(),
84
- name: branch.name,
85
- nodeType: '2',
86
- });
87
- }
88
- }
102
+ parentId = addBranchIfNeeded(e.branchId);
89
103
  }
90
104
  res.push({
91
105
  id: e.id.toString(),
@@ -96,26 +110,15 @@ function applyIntegrationModuleDefaults(config, integration) {
96
110
  }
97
111
  if (!mode || mode === 'files') {
98
112
  const directoryIds = mode === 'files'
99
- ? (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)).data.map((d) => d.data.id)
113
+ ? allDirectories.map((d) => d.id)
100
114
  : res.filter((item) => !item.type && item.nodeType !== '2').map((d) => parseInt(d.id));
101
- let files = (yield client.sourceFilesApi.withFetchAll().listProjectFiles(projectId, options)).data.map((d) => d.data);
102
- files = files.filter((f) => (rootFolder && f.directoryId === rootFolder.id) ||
115
+ const filteredFiles = allFiles.filter((f) => (rootFolder && f.directoryId === rootFolder.id) ||
103
116
  directoryIds.includes(f.directoryId) ||
104
117
  (!rootFolder && !f.directoryId));
105
- files.forEach((e) => {
118
+ filteredFiles.forEach((e) => {
106
119
  let parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
107
120
  if (!parentId && e.branchId) {
108
- const branch = allBranches.find((branch) => branch.id === e.branchId);
109
- if (branch) {
110
- parentId = branch.id;
111
- if (!res.find((node) => node.id === branch.id.toString())) {
112
- res.push({
113
- id: branch.id.toString(),
114
- name: branch.name,
115
- nodeType: '2',
116
- });
117
- }
118
- }
121
+ parentId = addBranchIfNeeded(e.branchId);
119
122
  }
120
123
  res.push({
121
124
  id: e.id.toString(),
@@ -213,17 +213,25 @@ function markUnsyncedFiles({ integrationId, crowdinId, client, files, }) {
213
213
  let unsyncedFiles = (unsyncedFilesData === null || unsyncedFilesData === void 0 ? void 0 : unsyncedFilesData.files)
214
214
  ? JSON.parse(unsyncedFilesData === null || unsyncedFilesData === void 0 ? void 0 : unsyncedFilesData.files)
215
215
  : [];
216
- const fileIds = files.filter((file) => isFileLeaf(file)).map((file) => `${file.id}`);
217
- const idsToRemove = unsyncedFiles.filter((file) => !fileIds.includes(file.id)).map((file) => file.id);
218
- unsyncedFiles = unsyncedFiles.filter((file) => !idsToRemove.includes(file.id));
216
+ if (unsyncedFiles.length === 0) {
217
+ return files;
218
+ }
219
+ const fileIds = new Set(files.filter((file) => isFileLeaf(file)).map((file) => `${file.id}`));
220
+ const idsToRemove = unsyncedFiles.filter((file) => !fileIds.has(`${file.id}`)).map((file) => file.id);
221
+ if (idsToRemove.length > 0) {
222
+ unsyncedFiles = unsyncedFiles.filter((file) => !idsToRemove.includes(file.id));
223
+ yield (0, storage_1.getStorage)().updateUnsyncedFiles({
224
+ integrationId,
225
+ crowdinId,
226
+ files: JSON.stringify(unsyncedFiles),
227
+ });
228
+ }
229
+ if (unsyncedFiles.length === 0) {
230
+ return files;
231
+ }
219
232
  const userTimezone = (yield client.usersApi.getAuthenticatedUser()).data.timezone;
220
- yield (0, storage_1.getStorage)().updateUnsyncedFiles({
221
- integrationId,
222
- crowdinId,
223
- files: JSON.stringify(unsyncedFiles),
224
- });
225
- files = files.map((file) => {
226
- const unsynced = unsyncedFiles.find((unsyncedFile) => unsyncedFile.id === file.id);
233
+ return files.map((file) => {
234
+ const unsynced = unsyncedFiles.find((f) => `${f.id}` === `${file.id}`);
227
235
  if (unsynced && isFileLeaf(file)) {
228
236
  const formattedDate = (0, util_1.getFormattedDate)({ date: new Date(+unsynced.updatedAt), userTimezone });
229
237
  file.labels = [
@@ -238,7 +246,6 @@ function markUnsyncedFiles({ integrationId, crowdinId, client, files, }) {
238
246
  }
239
247
  return file;
240
248
  });
241
- return files;
242
249
  });
243
250
  }
244
251
  exports.markUnsyncedFiles = markUnsyncedFiles;
@@ -47,7 +47,7 @@ function handle(config) {
47
47
  let status = 'ok';
48
48
  let message = 'Filesystem access successful';
49
49
  try {
50
- const testFile = path_1.default.join(os_1.default.tmpdir(), 'status-check.txt');
50
+ const testFile = path_1.default.join(os_1.default.tmpdir(), `status-check-${Date.now()}.txt`);
51
51
  yield promises_1.default.writeFile(testFile, 'test');
52
52
  yield promises_1.default.unlink(testFile);
53
53
  }
@@ -277,9 +277,10 @@
277
277
  .then(localStorage.removeItem('revised_{{name}}'))
278
278
  .then(reloadLocation)
279
279
  .catch(e => {
280
+ const errorMessage = e.message || 'Credentials are not stored';
280
281
  loginButton.setAttribute('disabled', false);
281
282
  loginButton.setAttribute('is-loading', false);
282
- catchRejection(e, 'Credentials are not stored');
283
+ catchRejection(e, errorMessage);
283
284
  });
284
285
  }
285
286
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.105.0",
3
+ "version": "0.106.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",