@crowdin/app-project-module 0.16.1 → 0.16.3

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/README.md CHANGED
@@ -519,6 +519,42 @@ const configuration = {
519
519
  crowdinModule.createApp(configuration);
520
520
  ```
521
521
 
522
+ Also custom file format module can support strings export.
523
+
524
+ ```javascript
525
+ const crowdinModule = require('@crowdin/app-project-module');
526
+ const convert = require('xml-js');
527
+
528
+ const configuration = {
529
+ baseUrl: 'https://123.ngrok.io',
530
+ clientId: 'clientId',
531
+ clientSecret: 'clientSecret',
532
+ name: 'Sample App',
533
+ identifier: 'sample-app',
534
+ description: 'Sample App description',
535
+ dbFolder: __dirname,
536
+ imagePath: __dirname + '/' + 'logo.png',
537
+ customFileFormat: {
538
+ type: 'type-xyz',
539
+ stringsExport: true,
540
+ extensions: [
541
+ '.resx'
542
+ ],
543
+ parseFile: async (file, req, client, context, projectId) => {
544
+ //parse logic
545
+ return { strings: [] };
546
+ },
547
+ buildFile: async (file, req, strings, client, context, projectId) => {
548
+ const isStringsExport = !!req.file.path;
549
+ //export logic
550
+ return { contentFile: {} }
551
+ }
552
+ }
553
+ };
554
+
555
+ crowdinModule.createApp(configuration);
556
+ ```
557
+
522
558
  ### Custom MT
523
559
 
524
560
  Example of [custom mt module](https://support.crowdin.com/crowdin-apps-modules/#custom-mt-machine-translation-module).
@@ -15,14 +15,28 @@ function handle(config) {
15
15
  ];
16
16
  }
17
17
  if (config.customFileFormat) {
18
- modules['custom-file-format'] = [
19
- {
20
- key: config.identifier + '-ff',
21
- type: config.customFileFormat.type,
22
- signaturePatterns: config.customFileFormat.signaturePatterns,
23
- url: '/process',
24
- },
25
- ];
18
+ if (config.customFileFormat.stringsExport) {
19
+ modules['custom-file-format'] = [
20
+ {
21
+ key: config.identifier + '-ff',
22
+ type: config.customFileFormat.type,
23
+ stringsExport: true,
24
+ extensions: config.customFileFormat.extensions,
25
+ url: '/process',
26
+ },
27
+ ];
28
+ }
29
+ else {
30
+ modules['custom-file-format'] = [
31
+ {
32
+ key: config.identifier + '-ff',
33
+ type: config.customFileFormat.type,
34
+ multilingual: !!config.customFileFormat.multilingual,
35
+ signaturePatterns: config.customFileFormat.signaturePatterns,
36
+ url: '/process',
37
+ },
38
+ ];
39
+ }
26
40
  }
27
41
  if (config.customMT) {
28
42
  modules['custom-mt'] = [
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ const models_1 = require("../models");
3
4
  function handle(config) {
4
5
  return (req, res) => {
5
6
  var _a;
6
7
  const subscriptionInfo = req.subscriptionInfo;
7
- let showInfo = true;
8
- if ((_a = config.pricing) === null || _a === void 0 ? void 0 : _a.infoDisplayDaysThreshold) {
8
+ let showInfo = (subscriptionInfo === null || subscriptionInfo === void 0 ? void 0 : subscriptionInfo.type) === models_1.SubscriptionInfoType.TRIAL;
9
+ if (showInfo && ((_a = config.pricing) === null || _a === void 0 ? void 0 : _a.infoDisplayDaysThreshold)) {
9
10
  showInfo = config.pricing.infoDisplayDaysThreshold >= ((subscriptionInfo === null || subscriptionInfo === void 0 ? void 0 : subscriptionInfo.daysLeft) || 0);
10
11
  }
11
12
  res.send(Object.assign(Object.assign({}, (subscriptionInfo || {})), { showInfo }));
@@ -340,10 +340,15 @@ export interface CrowdinContextInfo {
340
340
  crowdinId: string;
341
341
  clientId: string;
342
342
  }
343
+ export declare enum SubscriptionInfoType {
344
+ TRIAL = "trial",
345
+ SUBSCRIPTION = "subscription"
346
+ }
343
347
  export interface SubscriptionInfo {
344
348
  expired: boolean;
345
349
  subscribeLink?: string;
346
350
  daysLeft?: number;
351
+ type?: SubscriptionInfoType;
347
352
  }
348
353
  export interface IntegrationCredentials {
349
354
  id: string;
@@ -385,6 +390,14 @@ export interface CustomFileFormatLogic {
385
390
  * Flag to automatically upload translations
386
391
  */
387
392
  autoUploadTranslations?: boolean;
393
+ /**
394
+ * Enable strings export
395
+ */
396
+ stringsExport?: boolean;
397
+ /**
398
+ * File extensions (used for strings export)
399
+ */
400
+ extensions?: string[];
388
401
  /**
389
402
  * Used for initial source file upload, source file update, and translation upload
390
403
  */
@@ -392,7 +405,7 @@ export interface CustomFileFormatLogic {
392
405
  /**
393
406
  * Used for translation download
394
407
  */
395
- buildFile: (fileContent: string | object, req: Omit<ProcessFileRequest, 'jobType' | 'file'>, strings: ProcessFileString[], client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<BuildFileResponse>;
408
+ buildFile: (fileContent: string | object, req: Omit<ProcessFileRequest, 'jobType'>, strings: ProcessFileString[], client: Crowdin, context: CrowdinContextInfo, projectId: number) => Promise<BuildFileResponse>;
396
409
  }
397
410
  export interface SignaturePatterns {
398
411
  fileName?: string;
@@ -409,6 +422,7 @@ export interface ProcessFileRequest {
409
422
  export interface ProcessFileRecord {
410
423
  content?: string;
411
424
  contentUrl?: string;
425
+ path?: string;
412
426
  }
413
427
  export declare enum ProcessFileJobType {
414
428
  PARSE_FILE = "parse-file",
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EditorPanelsMode = exports.ProcessFileJobType = exports.AccountType = exports.Scope = void 0;
3
+ exports.EditorPanelsMode = exports.ProcessFileJobType = exports.SubscriptionInfoType = exports.AccountType = exports.Scope = void 0;
4
4
  var Scope;
5
5
  (function (Scope) {
6
6
  Scope["ALL_SCOPES"] = "all";
@@ -22,6 +22,11 @@ var AccountType;
22
22
  AccountType["NORMAL"] = "normal";
23
23
  AccountType["ENTERPRISE"] = "enterprise";
24
24
  })(AccountType = exports.AccountType || (exports.AccountType = {}));
25
+ var SubscriptionInfoType;
26
+ (function (SubscriptionInfoType) {
27
+ SubscriptionInfoType["TRIAL"] = "trial";
28
+ SubscriptionInfoType["SUBSCRIPTION"] = "subscription";
29
+ })(SubscriptionInfoType = exports.SubscriptionInfoType || (exports.SubscriptionInfoType = {}));
25
30
  var ProcessFileJobType;
26
31
  (function (ProcessFileJobType) {
27
32
  ProcessFileJobType["PARSE_FILE"] = "parse-file";
@@ -112,7 +112,7 @@ function prepareIntegrationCredentials(config, integration, integrationCredentia
112
112
  }
113
113
  exports.prepareIntegrationCredentials = prepareIntegrationCredentials;
114
114
  const subscriptionCache = {};
115
- function addToCache(organization, appIdenfifier, validUntil, cachingSeconds, subscribeLink) {
115
+ function addToCache(organization, appIdenfifier, validUntil, type, cachingSeconds, subscribeLink) {
116
116
  if (!cachingSeconds) {
117
117
  return;
118
118
  }
@@ -123,6 +123,7 @@ function addToCache(organization, appIdenfifier, validUntil, cachingSeconds, sub
123
123
  cacheValidUntil: now,
124
124
  validUntil,
125
125
  subscribeLink,
126
+ type,
126
127
  };
127
128
  subscriptionCache[organization] = orgCache;
128
129
  }
@@ -148,25 +149,16 @@ function checkSubscription(config, token, organization, accountType) {
148
149
  if (isAppFree(config)) {
149
150
  return { expired: false };
150
151
  }
151
- //default 2 weeks
152
- const defaultSubscriptionPlan = 14;
153
- let days;
154
- if (organization) {
155
- days = ((_a = config.pricing) === null || _a === void 0 ? void 0 : _a.trialEnterprise) || ((_b = config.pricing) === null || _b === void 0 ? void 0 : _b.trial) || defaultSubscriptionPlan;
156
- }
157
- else {
158
- days = ((_c = config.pricing) === null || _c === void 0 ? void 0 : _c.trialCrowdin) || ((_d = config.pricing) === null || _d === void 0 ? void 0 : _d.trial) || defaultSubscriptionPlan;
159
- }
160
- (0, _1.log)(`Checking subscription plan. Subscriptino plan ${days} days`, config.logger);
152
+ (0, _1.log)('Checking subscription plan', config.logger);
161
153
  const appIdentifier = config.identifier;
162
154
  const cacheEntry = getFromCache(organization, appIdentifier);
163
155
  if (cacheEntry) {
164
- const { cacheValidUntil, validUntil, subscribeLink } = cacheEntry;
156
+ const { cacheValidUntil, validUntil, subscribeLink, type } = cacheEntry;
165
157
  if (cacheValidUntil.getTime() > Date.now()) {
166
- (0, _1.log)(`Loaded data from cache. Subscription is vali until ${validUntil.toISOString()}`, config.logger);
158
+ (0, _1.log)(`Loaded data from cache. Subscription is valid until ${validUntil.toISOString()}`, config.logger);
167
159
  const { expired, daysLeft } = validateSubscription(new Date(validUntil));
168
160
  (0, _1.log)(`expired ${expired}`, config.logger);
169
- return { expired, subscribeLink, daysLeft };
161
+ return { expired, subscribeLink, daysLeft, type };
170
162
  }
171
163
  }
172
164
  try {
@@ -178,19 +170,29 @@ function checkSubscription(config, token, organization, accountType) {
178
170
  (0, _1.log)(`Recieved subscription info. ${JSON.stringify(subscription)}`, config.logger);
179
171
  const { expired, daysLeft } = validateSubscription(new Date(subscription.expires));
180
172
  (0, _1.log)(`expired ${expired}`, config.logger);
181
- addToCache(organization, appIdentifier, new Date(subscription.expires), (_e = config.pricing) === null || _e === void 0 ? void 0 : _e.cachingSeconds);
182
- return { expired, daysLeft };
173
+ addToCache(organization, appIdentifier, new Date(subscription.expires), models_1.SubscriptionInfoType.SUBSCRIPTION, (_a = config.pricing) === null || _a === void 0 ? void 0 : _a.cachingSeconds);
174
+ return { expired, daysLeft, type: models_1.SubscriptionInfoType.SUBSCRIPTION };
183
175
  }
184
176
  catch (e) {
185
177
  if (e instanceof crowdinAppFunctions.PaymentRequiredError) {
186
178
  const { initializedAt, subscribeLink } = e;
187
179
  (0, _1.log)(`Recieved 402 payment error. initializedAt ${initializedAt}`, config.logger);
180
+ //default 2 weeks
181
+ const defaultSubscriptionPlan = 14;
182
+ let days;
183
+ if (organization) {
184
+ days = ((_b = config.pricing) === null || _b === void 0 ? void 0 : _b.trialEnterprise) || ((_c = config.pricing) === null || _c === void 0 ? void 0 : _c.trial) || defaultSubscriptionPlan;
185
+ }
186
+ else {
187
+ days = ((_d = config.pricing) === null || _d === void 0 ? void 0 : _d.trialCrowdin) || ((_e = config.pricing) === null || _e === void 0 ? void 0 : _e.trial) || defaultSubscriptionPlan;
188
+ }
189
+ (0, _1.log)(`Subscriptino trial plan ${days} days`, config.logger);
188
190
  const date = new Date(initializedAt);
189
191
  date.setDate(date.getDate() + days);
190
192
  const { expired, daysLeft } = validateSubscription(date);
191
193
  (0, _1.log)(`expired ${expired}`, config.logger);
192
- addToCache(organization, appIdentifier, new Date(date), (_f = config.pricing) === null || _f === void 0 ? void 0 : _f.cachingSeconds, subscribeLink);
193
- return { expired, subscribeLink, daysLeft };
194
+ addToCache(organization, appIdentifier, new Date(date), models_1.SubscriptionInfoType.TRIAL, (_f = config.pricing) === null || _f === void 0 ? void 0 : _f.cachingSeconds, subscribeLink);
195
+ return { expired, subscribeLink, daysLeft, type: models_1.SubscriptionInfoType.TRIAL };
194
196
  }
195
197
  if (config.onError) {
196
198
  config.onError(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crowdin/app-project-module",
3
- "version": "0.16.1",
3
+ "version": "0.16.3",
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",