@crowdin/app-project-module 0.98.0-cf-1 → 0.98.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.
Files changed (134) hide show
  1. package/out/index.js +10 -25
  2. package/out/middlewares/crowdin-client.d.ts +1 -1
  3. package/out/middlewares/integration-credentials.d.ts +1 -1
  4. package/out/middlewares/integration-credentials.js +1 -4
  5. package/out/middlewares/render-ui-module.d.ts +3 -3
  6. package/out/middlewares/render-ui-module.js +13 -9
  7. package/out/middlewares/ui-module.d.ts +1 -1
  8. package/out/middlewares/ui-module.js +1 -4
  9. package/out/modules/about.d.ts +1 -1
  10. package/out/modules/about.js +2 -8
  11. package/out/modules/ai-prompt-provider/handlers/compile.d.ts +1 -1
  12. package/out/modules/ai-prompt-provider/index.js +2 -4
  13. package/out/modules/ai-provider/handlers/chat-completions.d.ts +1 -1
  14. package/out/modules/ai-provider/handlers/get-model-list.d.ts +1 -1
  15. package/out/modules/ai-provider/index.js +2 -4
  16. package/out/modules/ai-request-processors/handler.d.ts +1 -1
  17. package/out/modules/ai-tools/handlers/tool-calls.d.ts +1 -1
  18. package/out/modules/ai-tools/index.js +1 -1
  19. package/out/modules/context-menu/index.js +2 -2
  20. package/out/modules/custom-mt/handlers/translate.d.ts +1 -1
  21. package/out/modules/custom-mt/index.js +1 -3
  22. package/out/modules/custom-spell-check/handlers/get-languages-list.d.ts +1 -1
  23. package/out/modules/custom-spell-check/handlers/spell-check.d.ts +1 -1
  24. package/out/modules/custom-spell-check/index.js +4 -4
  25. package/out/modules/editor-right-panel/index.js +1 -1
  26. package/out/modules/external-qa-check/handlers/validate.d.ts +1 -1
  27. package/out/modules/external-qa-check/index.js +2 -2
  28. package/out/modules/file-processing/handlers/custom-file-format.d.ts +1 -1
  29. package/out/modules/file-processing/handlers/file-download.d.ts +1 -1
  30. package/out/modules/file-processing/handlers/pre-post-process.d.ts +1 -1
  31. package/out/modules/form-data-display.d.ts +1 -1
  32. package/out/modules/form-data-save.d.ts +1 -1
  33. package/out/modules/install.d.ts +1 -1
  34. package/out/modules/integration/handlers/crowdin-file-progress.d.ts +1 -1
  35. package/out/modules/integration/handlers/crowdin-files.d.ts +1 -1
  36. package/out/modules/integration/handlers/crowdin-files.js +6 -4
  37. package/out/modules/integration/handlers/crowdin-project.d.ts +1 -1
  38. package/out/modules/integration/handlers/crowdin-update.d.ts +1 -1
  39. package/out/modules/integration/handlers/crowdin-update.js +18 -4
  40. package/out/modules/integration/handlers/crowdin-webhook.d.ts +1 -1
  41. package/out/modules/integration/handlers/integration-data.d.ts +1 -1
  42. package/out/modules/integration/handlers/integration-data.js +17 -13
  43. package/out/modules/integration/handlers/integration-login.d.ts +1 -1
  44. package/out/modules/integration/handlers/integration-logout.d.ts +1 -1
  45. package/out/modules/integration/handlers/integration-update.d.ts +1 -1
  46. package/out/modules/integration/handlers/integration-webhook.d.ts +1 -1
  47. package/out/modules/integration/handlers/invite-users.d.ts +1 -1
  48. package/out/modules/integration/handlers/job-cancel.d.ts +1 -1
  49. package/out/modules/integration/handlers/job-info.d.ts +1 -1
  50. package/out/modules/integration/handlers/main.d.ts +1 -1
  51. package/out/modules/integration/handlers/main.js +3 -13
  52. package/out/modules/integration/handlers/oauth-login.d.ts +1 -1
  53. package/out/modules/integration/handlers/oauth-login.js +2 -10
  54. package/out/modules/integration/handlers/oauth-polling.d.ts +1 -1
  55. package/out/modules/integration/handlers/oauth-url.d.ts +1 -1
  56. package/out/modules/integration/handlers/settings-save.d.ts +1 -1
  57. package/out/modules/integration/handlers/settings.d.ts +1 -1
  58. package/out/modules/integration/handlers/sync-settings-save.d.ts +1 -1
  59. package/out/modules/integration/handlers/sync-settings.d.ts +1 -1
  60. package/out/modules/integration/handlers/user-errors.d.ts +1 -1
  61. package/out/modules/integration/handlers/users.d.ts +1 -1
  62. package/out/modules/integration/index.js +21 -27
  63. package/out/modules/integration/types.d.ts +11 -1
  64. package/out/modules/integration/util/defaults.js +51 -45
  65. package/out/modules/integration/util/files.d.ts +1 -0
  66. package/out/modules/integration/util/files.js +52 -4
  67. package/out/modules/integration/util/job.d.ts +1 -1
  68. package/out/modules/integration/util/job.js +3 -2
  69. package/out/modules/integration/util/types.d.ts +2 -0
  70. package/out/modules/modal/index.js +2 -2
  71. package/out/modules/organization-menu/index.js +4 -6
  72. package/out/modules/organization-settings-menu/index.js +4 -6
  73. package/out/modules/profile-resources-menu/index.js +4 -6
  74. package/out/modules/profile-settings-menu/index.js +4 -6
  75. package/out/modules/project-menu/index.js +1 -1
  76. package/out/modules/project-menu-crowdsource/index.js +1 -1
  77. package/out/modules/project-reports/index.js +2 -4
  78. package/out/modules/project-tools/index.js +2 -4
  79. package/out/modules/status.d.ts +1 -1
  80. package/out/modules/subscription-paid.d.ts +1 -1
  81. package/out/modules/uninstall.d.ts +1 -1
  82. package/out/modules/webhooks/handlers/webhook-handler.d.ts +1 -1
  83. package/out/modules/workflow-step-type/handlers/delete-step.d.ts +1 -1
  84. package/out/modules/workflow-step-type/handlers/step-settings-save.d.ts +1 -1
  85. package/out/modules/workflow-step-type/index.js +2 -3
  86. package/out/storage/index.js +1 -8
  87. package/out/storage/mysql.d.ts +1 -1
  88. package/out/storage/mysql.js +9 -1
  89. package/out/storage/postgre.d.ts +1 -1
  90. package/out/storage/postgre.js +11 -4
  91. package/out/storage/sqlite.d.ts +1 -1
  92. package/out/storage/sqlite.js +10 -4
  93. package/out/types.d.ts +1 -11
  94. package/out/util/credentials-masker.d.ts +1 -1
  95. package/out/util/handlebars.d.ts +1 -0
  96. package/out/util/handlebars.js +46 -0
  97. package/out/util/index.d.ts +0 -2
  98. package/out/util/index.js +2 -14
  99. package/out/views/about.handlebars +102 -0
  100. package/out/views/error.handlebars +54 -0
  101. package/out/views/form.handlebars +30 -0
  102. package/out/views/install.handlebars +16 -0
  103. package/out/views/login.handlebars +331 -0
  104. package/out/views/main.handlebars +1901 -0
  105. package/out/views/oauth.handlebars +11 -0
  106. package/out/views/partials/head.handlebars +53 -0
  107. package/out/views/subscription.handlebars +26 -0
  108. package/package.json +11 -12
  109. package/out/storage/d1.d.ts +0 -99
  110. package/out/storage/d1.js +0 -769
  111. package/out/util/jsx-renderer.d.ts +0 -6
  112. package/out/util/jsx-renderer.js +0 -13
  113. package/out/util/static-files.d.ts +0 -19
  114. package/out/util/static-files.js +0 -80
  115. package/out/views/AboutPage.d.ts +0 -9
  116. package/out/views/AboutPage.js +0 -79
  117. package/out/views/ErrorPage.d.ts +0 -18
  118. package/out/views/ErrorPage.js +0 -56
  119. package/out/views/FormPage.d.ts +0 -13
  120. package/out/views/FormPage.js +0 -27
  121. package/out/views/InstallPage.d.ts +0 -10
  122. package/out/views/InstallPage.js +0 -22
  123. package/out/views/LoginPage.d.ts +0 -33
  124. package/out/views/LoginPage.js +0 -199
  125. package/out/views/MainPage.d.ts +0 -79
  126. package/out/views/MainPage.js +0 -1613
  127. package/out/views/OAuthPage.d.ts +0 -7
  128. package/out/views/OAuthPage.js +0 -17
  129. package/out/views/SubscriptionPage.d.ts +0 -7
  130. package/out/views/SubscriptionPage.js +0 -26
  131. package/out/views/index.d.ts +0 -13
  132. package/out/views/index.js +0 -25
  133. package/out/views/layout/Head.d.ts +0 -9
  134. package/out/views/layout/Head.js +0 -54
@@ -22,9 +22,10 @@ const files_1 = require("../util/files");
22
22
  const types_2 = require("../types");
23
23
  function handle(config, integration) {
24
24
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
25
- var _a, _b, _c;
25
+ var _a, _b, _c, _d;
26
26
  const projectId = req.crowdinContext.jwtPayload.context.project_id || (req === null || req === void 0 ? void 0 : req.body.projectId);
27
27
  const uploadTranslations = req.query.uploadTranslations === 'true' || ((_a = req.body) === null || _a === void 0 ? void 0 : _a.uploadTranslations);
28
+ const forcePushSources = req.query.forcePushSources === 'true' || ((_b = req.body) === null || _b === void 0 ? void 0 : _b.forcePushSources);
28
29
  req.logInfo(`Updating crowdin project ${projectId}`);
29
30
  const rootFolder = yield (0, defaults_1.getRootFolder)(config, integration, req.crowdinApiClient, projectId);
30
31
  if (rootFolder) {
@@ -38,14 +39,14 @@ function handle(config, integration) {
38
39
  });
39
40
  }
40
41
  // A request via API has a different structure
41
- if (((_b = config.api) === null || _b === void 0 ? void 0 : _b.default) && req.body.files) {
42
+ if (((_c = config.api) === null || _c === void 0 ? void 0 : _c.default) && req.body.files) {
42
43
  req.body = req.body.files;
43
44
  }
44
45
  let payload = req.body;
45
46
  const excludedTargetLanguages = yield (0, files_1.getExcludedTargetLanguages)({
46
47
  client: req.crowdinApiClient,
47
48
  projectId,
48
- languages: ((_c = req.query.languages) === null || _c === void 0 ? void 0 : _c.split(',')) || [],
49
+ languages: ((_d = req.query.languages) === null || _d === void 0 ? void 0 : _d.split(',')) || [],
49
50
  });
50
51
  yield (0, job_1.runAsJob)({
51
52
  integrationId: req.crowdinContext.clientId,
@@ -63,6 +64,9 @@ function handle(config, integration) {
63
64
  payload = yield (0, files_1.expandFilesTree)(payload, req, integration, job);
64
65
  payload = (0, lodash_uniqby_1.default)(payload, 'id');
65
66
  }
67
+ if (!forcePushSources && (payload === null || payload === void 0 ? void 0 : payload.length)) {
68
+ payload = yield (0, files_1.filterSyncedData)(payload);
69
+ }
66
70
  const result = yield integration.updateCrowdin({
67
71
  projectId,
68
72
  client: req.crowdinApiClient,
@@ -97,7 +101,17 @@ function handle(config, integration) {
97
101
  }
98
102
  return { message };
99
103
  }),
100
- onError: (e) => __awaiter(this, void 0, void 0, function* () {
104
+ onError: (e, job) => __awaiter(this, void 0, void 0, function* () {
105
+ try {
106
+ const currentJob = yield job.get();
107
+ if (currentJob === null || currentJob === void 0 ? void 0 : currentJob.processedEntities) {
108
+ const processedEntities = JSON.parse(currentJob.processedEntities);
109
+ yield (0, files_1.updateSyncedData)(req.crowdinContext.clientId, req.crowdinContext.crowdinId, processedEntities, types_2.Provider.INTEGRATION);
110
+ }
111
+ }
112
+ catch (syncError) {
113
+ (0, logger_1.logError)(syncError, req.crowdinContext);
114
+ }
101
115
  yield (0, logger_1.handleUserError)({
102
116
  action: 'Sync files to Crowdin',
103
117
  error: e,
@@ -2,4 +2,4 @@
2
2
  import { Request, Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -1,4 +1,4 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
3
  import { IntegrationLogic } from '../types';
4
- export default function handle(integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
4
+ export default function handle(integration: IntegrationLogic): (req: import("../../../types").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;
@@ -43,9 +43,11 @@ function handle(integration) {
43
43
  const excludePatterns = (_c = appSettings === null || appSettings === void 0 ? void 0 : appSettings.excludeByFilePath) === null || _c === void 0 ? void 0 : _c.split('\n').filter(Boolean);
44
44
  files = (0, files_1.filterFilesByPath)(files, includePatterns, excludePatterns);
45
45
  }
46
- if (((_e = (_d = integration.filtering) === null || _d === void 0 ? void 0 : _d.integrationFileStatus) === null || _e === void 0 ? void 0 : _e.isNew) ||
46
+ const needsFileStatus = ((_e = (_d = integration.filtering) === null || _d === void 0 ? void 0 : _d.integrationFileStatus) === null || _e === void 0 ? void 0 : _e.isNew) ||
47
47
  ((_g = (_f = integration.filtering) === null || _f === void 0 ? void 0 : _f.integrationFileStatus) === null || _g === void 0 ? void 0 : _g.isUpdated) ||
48
- ((_j = (_h = integration.filtering) === null || _h === void 0 ? void 0 : _h.integrationFileStatus) === null || _j === void 0 ? void 0 : _j.notSynced)) {
48
+ ((_j = (_h = integration.filtering) === null || _h === void 0 ? void 0 : _h.integrationFileStatus) === null || _j === void 0 ? void 0 : _j.notSynced) ||
49
+ integration.forcePushSources === true;
50
+ if (needsFileStatus) {
49
51
  const syncedData = yield (0, storage_1.getStorage)().getSyncedData(clientId, crowdinId, types_1.Provider.INTEGRATION);
50
52
  const syncedFiles = (syncedData === null || syncedData === void 0 ? void 0 : syncedData.files) ? JSON.parse(syncedData.files) : [];
51
53
  const lastSyncTimestamp = (syncedData === null || syncedData === void 0 ? void 0 : syncedData.updatedAt) ? Number(syncedData.updatedAt) : null;
@@ -54,23 +56,25 @@ function handle(integration) {
54
56
  if (!file.type) {
55
57
  return file;
56
58
  }
57
- const notSynced = ((_b = (_a = integration.filtering) === null || _a === void 0 ? void 0 : _a.integrationFileStatus) === null || _b === void 0 ? void 0 : _b.notSynced) === true
58
- ? !syncedFiles.some((syncedItem) => syncedItem.id === file.id)
59
- : false;
59
+ const syncedFile = syncedFiles.find((syncedItem) => syncedItem.id === file.id);
60
+ const notSynced = ((_b = (_a = integration.filtering) === null || _a === void 0 ? void 0 : _a.integrationFileStatus) === null || _b === void 0 ? void 0 : _b.notSynced) === true ? !syncedFile : false;
61
+ const fileSyncTimestamp = (syncedFile === null || syncedFile === void 0 ? void 0 : syncedFile.syncedAt) ? Number(syncedFile.syncedAt) : lastSyncTimestamp;
60
62
  const isNew = ((_d = (_c = integration.filtering) === null || _c === void 0 ? void 0 : _c.integrationFileStatus) === null || _d === void 0 ? void 0 : _d.isNew) === true
61
- ? !syncedFiles.some((syncedItem) => syncedItem.id === file.id) &&
62
- lastSyncTimestamp &&
63
+ ? !syncedFile &&
64
+ fileSyncTimestamp &&
63
65
  file.createdAt &&
64
66
  (typeof file.createdAt === 'string'
65
67
  ? new Date(file.createdAt).getTime()
66
- : file.createdAt) > Number(lastSyncTimestamp)
68
+ : file.createdAt) > fileSyncTimestamp
67
69
  : false;
68
- const isUpdated = ((_f = (_e = integration.filtering) === null || _e === void 0 ? void 0 : _e.integrationFileStatus) === null || _f === void 0 ? void 0 : _f.isUpdated) === true
69
- ? lastSyncTimestamp &&
70
+ const shouldCalculateIsUpdated = ((_f = (_e = integration.filtering) === null || _e === void 0 ? void 0 : _e.integrationFileStatus) === null || _f === void 0 ? void 0 : _f.isUpdated) === true ||
71
+ integration.forcePushSources === true;
72
+ const isUpdated = shouldCalculateIsUpdated
73
+ ? syncedFile &&
74
+ fileSyncTimestamp &&
70
75
  file.updatedAt &&
71
- (typeof file.updatedAt === 'string'
72
- ? new Date(file.updatedAt).getTime()
73
- : file.updatedAt) > Number(lastSyncTimestamp)
76
+ (typeof file.updatedAt === 'string' ? new Date(file.updatedAt).getTime() : file.updatedAt) >
77
+ fileSyncTimestamp
74
78
  : false;
75
79
  return Object.assign(Object.assign({}, file), { isNew,
76
80
  notSynced,
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config, CrowdinClientRequest } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | CrowdinClientRequest, 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;
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -2,4 +2,4 @@
2
2
  import { Request, Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -1,3 +1,3 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
3
+ export default function handle(): (req: import("../../../types").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;
@@ -1,3 +1,3 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
3
+ export default function handle(): (req: import("../../../types").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;
@@ -1,4 +1,4 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
3
  import { Config } from '../../../types';
4
- export default function handle(config: Config): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
4
+ export default function handle(config: Config): (req: import("../../../types").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;
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -14,7 +14,6 @@ const logger_1 = require("../../../util/logger");
14
14
  const subscription_1 = require("../../../util/subscription");
15
15
  const defaults_1 = require("../util/defaults");
16
16
  const users_1 = require("./users");
17
- const views_1 = require("../../../views");
18
17
  function handle(config, integration) {
19
18
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
20
19
  var _a, _b, _c, _d;
@@ -78,9 +77,11 @@ function handle(config, integration) {
78
77
  : {};
79
78
  options.integrationOneLevelFetching = integration.integrationOneLevelFetching;
80
79
  options.integrationSearchListener = integration.integrationSearchListener;
80
+ options.progressiveCrowdinFilesLoading = integration.progressiveCrowdinFilesLoading;
81
81
  options.checkSubscription = !(0, subscription_1.isAppFree)(config);
82
82
  options.uploadTranslations = integration.uploadTranslations;
83
83
  options.forcePushTranslations = integration.forcePushTranslations;
84
+ options.forcePushSources = integration.forcePushSources;
84
85
  options.excludedTargetLanguages = integration.excludedTargetLanguages;
85
86
  options.sentryData = process.env.SENTRY_DSN
86
87
  ? {
@@ -93,18 +94,7 @@ function handle(config, integration) {
93
94
  checkInterval: ((_d = integration.asyncProgress) === null || _d === void 0 ? void 0 : _d.checkInterval) || 1000,
94
95
  };
95
96
  logger(`Routing user to ${view} view`);
96
- let html;
97
- if (view === 'install') {
98
- html = (0, util_1.renderJSX)(views_1.InstallPage, options);
99
- }
100
- else if (view === 'login') {
101
- html = (0, util_1.renderJSX)(views_1.LoginPage, options);
102
- }
103
- else {
104
- html = (0, util_1.renderJSX)(views_1.MainPage, options);
105
- }
106
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
107
- return res.send(html);
97
+ return res.render(view, options);
108
98
  }));
109
99
  }
110
100
  exports.default = handle;
@@ -2,4 +2,4 @@
2
2
  import { Request, Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -18,7 +18,6 @@ const defaults_1 = require("../util/defaults");
18
18
  const logger_1 = require("../../../util/logger");
19
19
  const storage_1 = require("../../../storage");
20
20
  const crowdin_apps_functions_1 = require("@crowdin/crowdin-apps-functions");
21
- const views_1 = require("../../../views");
22
21
  function handle(config, integration) {
23
22
  return (0, util_1.runAsyncWrapper)((req, res) => __awaiter(this, void 0, void 0, function* () {
24
23
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
@@ -66,19 +65,12 @@ function handle(config, integration) {
66
65
  yield (0, storage_1.getStorage)().deleteMetadata((0, defaults_1.getOAuthPollingId)(clientId));
67
66
  yield (0, storage_1.getStorage)().saveMetadata((0, defaults_1.getOAuthPollingId)(clientId), oauthCredentials, organization);
68
67
  }
69
- const html = (0, util_1.renderJSX)(views_1.OAuthPage, {
70
- message: JSON.stringify(message),
71
- oauthMode: (_p = integration.oauthLogin) === null || _p === void 0 ? void 0 : _p.mode,
72
- });
73
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
74
- return res.send(html);
68
+ return res.render('oauth', { message: JSON.stringify(message), oauthMode: (_p = integration.oauthLogin) === null || _p === void 0 ? void 0 : _p.mode });
75
69
  }
76
70
  catch (e) {
77
71
  (0, logger_1.logError)(e);
78
72
  message.data = { error: (0, logger_1.getErrorMessage)(e) };
79
- const html = (0, util_1.renderJSX)(views_1.OAuthPage, { message: JSON.stringify(message) });
80
- res.setHeader('Content-Type', 'text/html; charset=utf-8');
81
- return res.send(html);
73
+ return res.render('oauth', { message: JSON.stringify(message) });
82
74
  }
83
75
  }));
84
76
  }
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { CrowdinClientRequest } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
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;
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config, CrowdinClientRequest } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | CrowdinClientRequest, 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;
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -1,3 +1,3 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
3
+ export default function handle(): (req: import("../../../types").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;
@@ -2,4 +2,4 @@
2
2
  import { Response } from 'express';
3
3
  import { Config } from '../../../types';
4
4
  import { IntegrationLogic } from '../types';
5
- export default function handle(config: Config, integration: IntegrationLogic): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(config: Config, integration: IntegrationLogic): (req: import("../../../types").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;
@@ -1,3 +1,3 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
3
+ export default function handle(): (req: import("../../../types").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;
@@ -1,3 +1,3 @@
1
1
  /// <reference types="qs" />
2
2
  import { Response } from 'express';
3
- export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
3
+ export default function handle(): (req: import("../../../types").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;
@@ -2,7 +2,7 @@
2
2
  import Crowdin, { UsersModel } from '@crowdin/crowdin-api-client';
3
3
  import { Response } from 'express';
4
4
  export type ProjectMember = UsersModel.ProjectMember | UsersModel.EnterpriseProjectMember;
5
- export default function handle(): (req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>> | import("../../../types").CrowdinClientRequest, res: Response<any, Record<string, any>>, next: Function) => void;
5
+ export default function handle(): (req: import("../../../types").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;
6
6
  export declare function isManager({ client, projectId, memberId, }: {
7
7
  client: Crowdin;
8
8
  projectId: number;
@@ -36,11 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  };
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.register = void 0;
39
+ const cron = __importStar(require("node-cron"));
39
40
  const crowdin_client_1 = __importDefault(require("../../middlewares/crowdin-client"));
40
41
  const integration_credentials_1 = __importDefault(require("../../middlewares/integration-credentials"));
41
42
  const json_response_1 = __importDefault(require("../../middlewares/json-response"));
42
43
  const util_1 = require("../../util");
43
- const static_files_1 = require("../../util/static-files");
44
44
  const defaults_1 = require("./util/defaults");
45
45
  const webhooks_1 = require("./util/webhooks");
46
46
  const crowdin_file_progress_1 = __importDefault(require("./handlers/crowdin-file-progress"));
@@ -75,7 +75,7 @@ function register({ config, app }) {
75
75
  return;
76
76
  }
77
77
  (0, defaults_1.applyIntegrationModuleDefaults)(config, integrationLogic);
78
- app.get((0, util_1.getLogoUrl)(integrationLogic, '/integration'), (0, static_files_1.serveFile)(config, integrationLogic.imagePath || config.imagePath));
78
+ app.get((0, util_1.getLogoUrl)(integrationLogic, '/integration'), (req, res) => res.sendFile(integrationLogic.imagePath || config.imagePath));
79
79
  app.get('/', (0, crowdin_client_1.default)({
80
80
  config,
81
81
  optional: true,
@@ -183,32 +183,25 @@ function register({ config, app }) {
183
183
  }), (0, oauth_polling_1.default)(integrationLogic));
184
184
  }
185
185
  }
186
- Promise.resolve().then(() => __importStar(require('node-cron'))).then((nodeCron) => {
187
- const cron = nodeCron.default || nodeCron;
188
- if (integrationLogic.cronJobs) {
189
- integrationLogic.cronJobs.forEach((job) => {
190
- cron.schedule(job.expression, () => (0, cron_1.runJob)({ config, integration: integrationLogic, job }).catch(console.error));
191
- });
192
- }
193
- if (integrationLogic.withCronSync) {
194
- cron.schedule('0 * * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '1' }).catch(console.error));
195
- cron.schedule('0 */3 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '3' }).catch(console.error));
196
- cron.schedule('0 */6 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '6' }).catch(console.error));
197
- cron.schedule('0 */12 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '12' }).catch(console.error));
198
- cron.schedule('0 0 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '24' }).catch(console.error));
186
+ if (integrationLogic.cronJobs) {
187
+ integrationLogic.cronJobs.forEach((job) => {
188
+ cron.schedule(job.expression, () => (0, cron_1.runJob)({ config, integration: integrationLogic, job }).catch(console.error));
189
+ });
190
+ }
191
+ if (integrationLogic.withCronSync) {
192
+ cron.schedule('0 * * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '1' }).catch(console.error));
193
+ cron.schedule('0 */3 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '3' }).catch(console.error));
194
+ cron.schedule('0 */6 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '6' }).catch(console.error));
195
+ cron.schedule('0 */12 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '12' }).catch(console.error));
196
+ cron.schedule('0 0 * * *', () => (0, cron_1.filesCron)({ config, integration: integrationLogic, period: '24' }).catch(console.error));
197
+ }
198
+ // remove user errors
199
+ cron.schedule('0 0 * * *', () => __awaiter(this, void 0, void 0, function* () {
200
+ if (integrationLogic.userErrorLifetimeDays) {
201
+ const date = (0, util_1.getPreviousDate)(integrationLogic.userErrorLifetimeDays);
202
+ yield (0, storage_1.getStorage)().deleteAllUsersErrorsOlderThan(`${date.getTime()}`);
199
203
  }
200
- // remove user errors
201
- cron.schedule('0 0 * * *', () => __awaiter(this, void 0, void 0, function* () {
202
- if (integrationLogic.userErrorLifetimeDays) {
203
- const date = (0, util_1.getPreviousDate)(integrationLogic.userErrorLifetimeDays);
204
- yield (0, storage_1.getStorage)().deleteAllUsersErrorsOlderThan(`${date.getTime()}`);
205
- }
206
- }));
207
- cron.schedule('0 0 1 * *', () => (0, cron_1.removeFinishedJobs)());
208
- })
209
- .catch(() => {
210
- // node-cron not available (e.g., Cloudflare Workers)
211
- });
204
+ }));
212
205
  if (integrationLogic.webhooks) {
213
206
  app.post(`${integrationLogic.webhooks.crowdinWebhookUrl
214
207
  ? integrationLogic.webhooks.crowdinWebhookUrl
@@ -245,5 +238,6 @@ function register({ config, app }) {
245
238
  checkSubscriptionExpiration: true,
246
239
  moduleKey: integrationLogic.key,
247
240
  }), (0, integration_credentials_1.default)(config, integrationLogic), (0, invite_users_1.default)());
241
+ cron.schedule('0 0 1 * *', () => (0, cron_1.removeFinishedJobs)());
248
242
  }
249
243
  exports.register = register;
@@ -36,7 +36,7 @@ export interface IntegrationLogic extends ModuleKey {
36
36
  /**
37
37
  * function to get crowdin files that are related with this integration
38
38
  */
39
- getCrowdinFiles?: (projectId: number, client: Crowdin, appRootFolder?: SourceFilesModel.Directory, config?: any) => Promise<TreeItem[]>;
39
+ getCrowdinFiles?: (projectId: number, client: Crowdin, appRootFolder?: SourceFilesModel.Directory, config?: any, mode?: CrowdinFilesLoadMode) => Promise<TreeItem[]>;
40
40
  /**
41
41
  * function to get data from integration
42
42
  */
@@ -160,6 +160,10 @@ export interface IntegrationLogic extends ModuleKey {
160
160
  * Enable integration next page event
161
161
  */
162
162
  integrationPagination?: boolean;
163
+ /**
164
+ * Enable progressive loading for Crowdin files (directories first, then files).
165
+ */
166
+ progressiveCrowdinFilesLoading?: boolean;
163
167
  /**
164
168
  * Enable the option to upload translations to crowdin that are already present in the integration.
165
169
  */
@@ -168,6 +172,10 @@ export interface IntegrationLogic extends ModuleKey {
168
172
  * Force sync translations from Crowdin to integration regardless of etag.
169
173
  */
170
174
  forcePushTranslations?: boolean;
175
+ /**
176
+ * Force sync sources from integration to Crowdin.
177
+ */
178
+ forcePushSources?: boolean;
171
179
  /**
172
180
  * Enable the option to upload file for translation into selected languages.
173
181
  */
@@ -352,6 +360,7 @@ export interface OAuthLogin {
352
360
  */
353
361
  performRefreshTokenRequest?: (currentCredentials: any, loginForm?: any) => Promise<any>;
354
362
  }
363
+ export type CrowdinFilesLoadMode = 'directories' | 'files';
355
364
  export interface BaseTreeItem {
356
365
  id: string;
357
366
  name: string;
@@ -363,6 +372,7 @@ export interface BaseTreeItem {
363
372
  tooltip?: string;
364
373
  path?: string;
365
374
  type?: string;
375
+ syncedAt?: string;
366
376
  }
367
377
  export interface File extends BaseTreeItem {
368
378
  type: SourceFilesModel.FileType;
@@ -60,7 +60,7 @@ exports.getOauthRoute = getOauthRoute;
60
60
  function applyIntegrationModuleDefaults(config, integration) {
61
61
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
62
62
  if (!integration.getCrowdinFiles) {
63
- integration.getCrowdinFiles = (projectId, client, rootFolder) => __awaiter(this, void 0, void 0, function* () {
63
+ integration.getCrowdinFiles = (projectId, client, rootFolder, config, mode) => __awaiter(this, void 0, void 0, function* () {
64
64
  const allBranches = (yield client.sourceFilesApi.withFetchAll().listProjectBranches(projectId)).data.map((d) => d.data);
65
65
  let options = {};
66
66
  if (rootFolder) {
@@ -69,57 +69,63 @@ function applyIntegrationModuleDefaults(config, integration) {
69
69
  recursion: 'true',
70
70
  };
71
71
  }
72
- const allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)).data.map((d) => d.data);
73
- const directoryIds = allDirectories.map((d) => d.id);
74
- let files = (yield client.sourceFilesApi.withFetchAll().listProjectFiles(projectId, options)).data.map((d) => d.data);
75
- files = files.filter((f) => (rootFolder && f.directoryId === rootFolder.id) ||
76
- directoryIds.includes(f.directoryId) ||
77
- (!rootFolder && !f.directoryId));
78
72
  const res = [];
79
- allDirectories.forEach((e) => {
80
- let parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
81
- if (!parentId && e.branchId) {
82
- const branch = allBranches.find((branch) => branch.id === e.branchId);
83
- if (branch) {
84
- parentId = branch.id;
85
- if (!res.find((node) => node.id === branch.id.toString())) {
86
- res.push({
87
- id: branch.id.toString(),
88
- name: branch.name,
89
- nodeType: '2',
90
- });
73
+ if (!mode || mode === 'directories') {
74
+ const allDirectories = (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)).data.map((d) => d.data);
75
+ allDirectories.forEach((e) => {
76
+ let parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
77
+ 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
+ }
91
88
  }
92
89
  }
93
- }
94
- res.push({
95
- id: e.id.toString(),
96
- parentId: parentId ? parentId.toString() : undefined,
97
- name: e.name,
90
+ res.push({
91
+ id: e.id.toString(),
92
+ parentId: parentId ? parentId.toString() : undefined,
93
+ name: e.name,
94
+ });
98
95
  });
99
- });
100
- files.forEach((e) => {
101
- let parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
102
- if (!parentId && e.branchId) {
103
- const branch = allBranches.find((branch) => branch.id === e.branchId);
104
- if (branch) {
105
- parentId = branch.id;
106
- if (!res.find((node) => node.id === branch.id.toString())) {
107
- res.push({
108
- id: branch.id.toString(),
109
- name: branch.name,
110
- nodeType: '2',
111
- });
96
+ }
97
+ if (!mode || mode === 'files') {
98
+ const directoryIds = mode === 'files'
99
+ ? (yield client.sourceFilesApi.withFetchAll().listProjectDirectories(projectId, options)).data.map((d) => d.data.id)
100
+ : 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) ||
103
+ directoryIds.includes(f.directoryId) ||
104
+ (!rootFolder && !f.directoryId));
105
+ files.forEach((e) => {
106
+ let parentId = rootFolder && e.directoryId === rootFolder.id ? undefined : e.directoryId;
107
+ 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
+ }
112
118
  }
113
119
  }
114
- }
115
- res.push({
116
- id: e.id.toString(),
117
- parentId: parentId ? parentId.toString() : undefined,
118
- name: e.title || e.name,
119
- type: e.type,
120
- excludedTargetLanguages: e.excludedTargetLanguages,
120
+ res.push({
121
+ id: e.id.toString(),
122
+ parentId: parentId ? parentId.toString() : undefined,
123
+ name: e.title || e.name,
124
+ type: e.type,
125
+ excludedTargetLanguages: e.excludedTargetLanguages,
126
+ });
121
127
  });
122
- });
128
+ }
123
129
  return res;
124
130
  });
125
131
  }
@@ -23,3 +23,4 @@ export declare function getParentFiles(allFiles: TreeItem[], fileCollection: Tre
23
23
  export declare function filterFilesByPatterns(files: TreeItem[], patterns: string[]): TreeItem[];
24
24
  export declare function filterFilesByPath(files: TreeItem[], includePatterns?: string[], excludePatterns?: string[]): TreeItem[];
25
25
  export declare function updateSyncedData(clientId: string, crowdinId: string, payload: any[], provider?: Provider): Promise<void>;
26
+ export declare function filterSyncedData(payload: any[]): Promise<any[]>;