@crowdin/app-project-module 0.15.5 → 0.16.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/README.md +2 -1
- package/out/handlers/main.js +2 -0
- package/out/handlers/subscription-info.d.ts +3 -0
- package/out/handlers/subscription-info.js +14 -0
- package/out/index.js +2 -0
- package/out/middlewares/crowdin-client.d.ts +2 -1
- package/out/middlewares/crowdin-client.js +6 -4
- package/out/models/index.d.ts +7 -0
- package/out/static/css/styles.css +14 -0
- package/out/util/connection.d.ts +3 -5
- package/out/util/connection.js +22 -12
- package/out/views/main.handlebars +28 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,7 +186,8 @@ configuration.pricing = {
|
|
|
186
186
|
trial: 14, //amount of days to use app for free
|
|
187
187
|
trialCrowdin: 14, //amount of days specifically in crowdin workspace
|
|
188
188
|
trialEnterprise: 30, //amount of days specifically for enterprise
|
|
189
|
-
cachingSeconds: 12 * 60 * 60 //time in seconds of how long to cache subscription info
|
|
189
|
+
cachingSeconds: 12 * 60 * 60, //time in seconds of how long to cache subscription info
|
|
190
|
+
infoDisplayDaysThreshold: 14 //number of days threshold to check if subscription info should be displayed (if not defined then info will be always visible)
|
|
190
191
|
};
|
|
191
192
|
```
|
|
192
193
|
|
package/out/handlers/main.js
CHANGED
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
const util_1 = require("../util");
|
|
13
|
+
const connection_1 = require("../util/connection");
|
|
13
14
|
const defaults_1 = require("../util/defaults");
|
|
14
15
|
function constructOauthUrl(config, integration) {
|
|
15
16
|
var _a, _b, _c;
|
|
@@ -55,6 +56,7 @@ function handle(config, integration) {
|
|
|
55
56
|
options.infoModal = integration.infoModal;
|
|
56
57
|
options.withCronSync = integration.withCronSync;
|
|
57
58
|
options.withWebhookSync = integration.withWebhookSync;
|
|
59
|
+
options.checkSubscription = !(0, connection_1.isAppFree)(config);
|
|
58
60
|
(0, util_1.log)(`Routing user to ${view} view`, config.logger);
|
|
59
61
|
return res.render(view, options);
|
|
60
62
|
}), config.onError);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function handle(config) {
|
|
4
|
+
return (req, res) => {
|
|
5
|
+
var _a;
|
|
6
|
+
const subscriptionInfo = req.subscriptionInfo;
|
|
7
|
+
let showInfo = true;
|
|
8
|
+
if ((_a = config.pricing) === null || _a === void 0 ? void 0 : _a.infoDisplayDaysThreshold) {
|
|
9
|
+
showInfo = config.pricing.infoDisplayDaysThreshold >= ((subscriptionInfo === null || subscriptionInfo === void 0 ? void 0 : subscriptionInfo.daysLeft) || 0);
|
|
10
|
+
}
|
|
11
|
+
res.send(Object.assign(Object.assign({}, (subscriptionInfo || {})), { showInfo }));
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
exports.default = handle;
|
package/out/index.js
CHANGED
|
@@ -52,6 +52,7 @@ const main_1 = __importDefault(require("./handlers/main"));
|
|
|
52
52
|
const manifest_1 = __importDefault(require("./handlers/manifest"));
|
|
53
53
|
const oauth_login_1 = __importDefault(require("./handlers/oauth-login"));
|
|
54
54
|
const settings_save_1 = __importDefault(require("./handlers/settings-save"));
|
|
55
|
+
const subscription_info_1 = __importDefault(require("./handlers/subscription-info"));
|
|
55
56
|
const sync_settings_1 = __importDefault(require("./handlers/sync-settings"));
|
|
56
57
|
const sync_settings_save_1 = __importDefault(require("./handlers/sync-settings-save"));
|
|
57
58
|
const uninstall_1 = __importDefault(require("./handlers/uninstall"));
|
|
@@ -97,6 +98,7 @@ function addCrowdinEndpoints(app, config) {
|
|
|
97
98
|
(0, defaults_1.applyDefaults)(config, integrationLogic);
|
|
98
99
|
app.get('/logo/integration/logo.png', (req, res) => res.sendFile(integrationLogic.imagePath || config.imagePath || (0, path_1.join)(__dirname, 'logo.png')));
|
|
99
100
|
app.get('/', (0, crowdin_client_1.default)(config, true, false), (0, integration_credentials_1.default)(config, integrationLogic, true), (0, main_1.default)(config, integrationLogic));
|
|
101
|
+
app.get('/api/subscription-info', json_response_1.default, (0, crowdin_client_1.default)(config), (0, subscription_info_1.default)(config));
|
|
100
102
|
app.post('/api/settings', (0, crowdin_client_1.default)(config), (0, integration_credentials_1.default)(config, integrationLogic), (0, settings_save_1.default)(config));
|
|
101
103
|
app.post('/api/login', (0, crowdin_client_1.default)(config, false, false), (0, integration_login_1.default)(config, integrationLogic));
|
|
102
104
|
app.post('/api/logout', (0, crowdin_client_1.default)(config, false, false), (0, integration_logout_1.default)(config));
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/// <reference types="qs" />
|
|
2
2
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
3
3
|
import { Response } from 'express';
|
|
4
|
-
import { Config, CrowdinContextInfo } from '../models';
|
|
4
|
+
import { Config, CrowdinContextInfo, SubscriptionInfo } from '../models';
|
|
5
5
|
export declare function prepareCrowdinRequest(jwtToken: string, config: Config, optional?: boolean, checkSubscriptionExpiration?: boolean): Promise<{
|
|
6
6
|
context: CrowdinContextInfo;
|
|
7
7
|
client?: Crowdin;
|
|
8
|
+
subscriptionInfo?: SubscriptionInfo;
|
|
8
9
|
}>;
|
|
9
10
|
export default function handle(config: Config, optional?: boolean, checkSubscriptionExpiration?: boolean): (req: 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;
|
|
@@ -44,13 +44,14 @@ function prepareCrowdinRequest(jwtToken, config, optional = false, checkSubscrip
|
|
|
44
44
|
}
|
|
45
45
|
(0, util_1.log)('Building crowdin client instance', config.logger);
|
|
46
46
|
const { client, token } = yield (0, connection_1.prepareCrowdinClient)(config, credentials);
|
|
47
|
+
let subscriptionInfo;
|
|
47
48
|
if (checkSubscriptionExpiration) {
|
|
48
|
-
|
|
49
|
-
if (expired) {
|
|
50
|
-
throw new util_1.CodeError(subscribeLink || '', 402);
|
|
49
|
+
subscriptionInfo = yield (0, connection_1.checkSubscription)(config, token, credentials.id, credentials.type);
|
|
50
|
+
if (subscriptionInfo.expired) {
|
|
51
|
+
throw new util_1.CodeError(subscriptionInfo.subscribeLink || '', 402);
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
|
-
return { context, client };
|
|
54
|
+
return { context, client, subscriptionInfo };
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
57
|
exports.prepareCrowdinRequest = prepareCrowdinRequest;
|
|
@@ -66,6 +67,7 @@ function handle(config, optional = false, checkSubscriptionExpiration = true) {
|
|
|
66
67
|
if (data.client) {
|
|
67
68
|
req.crowdinApiClient = data.client;
|
|
68
69
|
}
|
|
70
|
+
req.subscriptionInfo = data.subscriptionInfo;
|
|
69
71
|
next();
|
|
70
72
|
}
|
|
71
73
|
catch (e) {
|
package/out/models/index.d.ts
CHANGED
|
@@ -322,6 +322,7 @@ export interface IntegrationRequest extends CrowdinClientRequest {
|
|
|
322
322
|
export interface CrowdinClientRequest extends Request {
|
|
323
323
|
crowdinApiClient: Crowdin;
|
|
324
324
|
crowdinContext: CrowdinContextInfo;
|
|
325
|
+
subscriptionInfo?: SubscriptionInfo;
|
|
325
326
|
}
|
|
326
327
|
export interface CrowdinCredentials {
|
|
327
328
|
id: string;
|
|
@@ -339,6 +340,11 @@ export interface CrowdinContextInfo {
|
|
|
339
340
|
crowdinId: string;
|
|
340
341
|
clientId: string;
|
|
341
342
|
}
|
|
343
|
+
export interface SubscriptionInfo {
|
|
344
|
+
expired: boolean;
|
|
345
|
+
subscribeLink?: string;
|
|
346
|
+
daysLeft?: number;
|
|
347
|
+
}
|
|
342
348
|
export interface IntegrationCredentials {
|
|
343
349
|
id: string;
|
|
344
350
|
credentials: any;
|
|
@@ -498,5 +504,6 @@ export interface Pricing {
|
|
|
498
504
|
trialCrowdin?: number;
|
|
499
505
|
trialEnterprise?: number;
|
|
500
506
|
cachingSeconds?: number;
|
|
507
|
+
infoDisplayDaysThreshold?: number;
|
|
501
508
|
}
|
|
502
509
|
export {};
|
|
@@ -12,6 +12,12 @@
|
|
|
12
12
|
justify-content: space-around;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
.box-center {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
.top {
|
|
16
22
|
text-align: right;
|
|
17
23
|
margin-bottom: 10px;
|
|
@@ -41,3 +47,11 @@
|
|
|
41
47
|
.login crowdin-h4 {
|
|
42
48
|
margin: 8px 0 16px;
|
|
43
49
|
}
|
|
50
|
+
|
|
51
|
+
.ml-1 {
|
|
52
|
+
margin-left: 8px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.m-0 {
|
|
56
|
+
margin: 0;
|
|
57
|
+
}
|
package/out/util/connection.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import Crowdin from '@crowdin/crowdin-api-client';
|
|
2
|
-
import { AccountType, Config, CrowdinCredentials, IntegrationCredentials, IntegrationLogic } from '../models';
|
|
2
|
+
import { AccountType, Config, CrowdinCredentials, IntegrationCredentials, IntegrationLogic, SubscriptionInfo } from '../models';
|
|
3
3
|
export declare function prepareCrowdinClient(config: Config, credentials: CrowdinCredentials): Promise<{
|
|
4
4
|
client: Crowdin;
|
|
5
5
|
token: string;
|
|
6
6
|
}>;
|
|
7
7
|
export declare function prepareIntegrationCredentials(config: Config, integration: IntegrationLogic, integrationCredentials: IntegrationCredentials): Promise<any>;
|
|
8
8
|
export declare function clearCache(organization: string): void;
|
|
9
|
-
export declare function
|
|
10
|
-
|
|
11
|
-
subscribeLink?: string;
|
|
12
|
-
}>;
|
|
9
|
+
export declare function isAppFree(config: Config): boolean;
|
|
10
|
+
export declare function checkSubscription(config: Config, token: string, organization: string, accountType: AccountType): Promise<SubscriptionInfo>;
|
package/out/util/connection.js
CHANGED
|
@@ -31,7 +31,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
31
31
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
32
32
|
};
|
|
33
33
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34
|
-
exports.checkSubscription = exports.clearCache = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = void 0;
|
|
34
|
+
exports.checkSubscription = exports.isAppFree = exports.clearCache = exports.prepareIntegrationCredentials = exports.prepareCrowdinClient = void 0;
|
|
35
35
|
const crowdin_api_client_1 = __importDefault(require("@crowdin/crowdin-api-client"));
|
|
36
36
|
const crowdinAppFunctions = __importStar(require("@crowdin/crowdin-apps-functions"));
|
|
37
37
|
const axios_1 = __importDefault(require("axios"));
|
|
@@ -133,19 +133,29 @@ function clearCache(organization) {
|
|
|
133
133
|
delete subscriptionCache[organization];
|
|
134
134
|
}
|
|
135
135
|
exports.clearCache = clearCache;
|
|
136
|
+
function isAppFree(config) {
|
|
137
|
+
return !config.pricing || config.pricing.planType === 'free';
|
|
138
|
+
}
|
|
139
|
+
exports.isAppFree = isAppFree;
|
|
140
|
+
function validateSubscription(date) {
|
|
141
|
+
const expired = date.getTime() < Date.now();
|
|
142
|
+
const daysLeft = Math.round((date.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
|
|
143
|
+
return { expired, daysLeft };
|
|
144
|
+
}
|
|
136
145
|
function checkSubscription(config, token, organization, accountType) {
|
|
146
|
+
var _a, _b, _c, _d, _e, _f;
|
|
137
147
|
return __awaiter(this, void 0, void 0, function* () {
|
|
138
|
-
if (
|
|
148
|
+
if (isAppFree(config)) {
|
|
139
149
|
return { expired: false };
|
|
140
150
|
}
|
|
141
151
|
//default 2 weeks
|
|
142
152
|
const defaultSubscriptionPlan = 14;
|
|
143
153
|
let days;
|
|
144
154
|
if (organization) {
|
|
145
|
-
days = config.pricing.trialEnterprise || config.pricing.trial || defaultSubscriptionPlan;
|
|
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;
|
|
146
156
|
}
|
|
147
157
|
else {
|
|
148
|
-
days = config.pricing.trialCrowdin || config.pricing.trial || defaultSubscriptionPlan;
|
|
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;
|
|
149
159
|
}
|
|
150
160
|
(0, _1.log)(`Checking subscription plan. Subscriptino plan ${days} days`, config.logger);
|
|
151
161
|
const appIdentifier = config.identifier;
|
|
@@ -154,9 +164,9 @@ function checkSubscription(config, token, organization, accountType) {
|
|
|
154
164
|
const { cacheValidUntil, validUntil, subscribeLink } = cacheEntry;
|
|
155
165
|
if (cacheValidUntil.getTime() > Date.now()) {
|
|
156
166
|
(0, _1.log)(`Loaded data from cache. Subscription is vali until ${validUntil.toISOString()}`, config.logger);
|
|
157
|
-
const expired = new Date(validUntil)
|
|
167
|
+
const { expired, daysLeft } = validateSubscription(new Date(validUntil));
|
|
158
168
|
(0, _1.log)(`expired ${expired}`, config.logger);
|
|
159
|
-
return { expired, subscribeLink };
|
|
169
|
+
return { expired, subscribeLink, daysLeft };
|
|
160
170
|
}
|
|
161
171
|
}
|
|
162
172
|
try {
|
|
@@ -166,10 +176,10 @@ function checkSubscription(config, token, organization, accountType) {
|
|
|
166
176
|
token,
|
|
167
177
|
});
|
|
168
178
|
(0, _1.log)(`Recieved subscription info. ${JSON.stringify(subscription)}`, config.logger);
|
|
169
|
-
const expired = new Date(subscription.expires)
|
|
179
|
+
const { expired, daysLeft } = validateSubscription(new Date(subscription.expires));
|
|
170
180
|
(0, _1.log)(`expired ${expired}`, config.logger);
|
|
171
|
-
addToCache(organization, appIdentifier, new Date(subscription.expires), config.pricing.cachingSeconds);
|
|
172
|
-
return { expired };
|
|
181
|
+
addToCache(organization, appIdentifier, new Date(subscription.expires), (_e = config.pricing) === null || _e === void 0 ? void 0 : _e.cachingSeconds);
|
|
182
|
+
return { expired, daysLeft };
|
|
173
183
|
}
|
|
174
184
|
catch (e) {
|
|
175
185
|
if (e instanceof crowdinAppFunctions.PaymentRequiredError) {
|
|
@@ -177,10 +187,10 @@ function checkSubscription(config, token, organization, accountType) {
|
|
|
177
187
|
(0, _1.log)(`Recieved 402 payment error. initializedAt ${initializedAt}`, config.logger);
|
|
178
188
|
const date = new Date(initializedAt);
|
|
179
189
|
date.setDate(date.getDate() + days);
|
|
180
|
-
const expired
|
|
190
|
+
const { expired, daysLeft } = validateSubscription(date);
|
|
181
191
|
(0, _1.log)(`expired ${expired}`, config.logger);
|
|
182
|
-
addToCache(organization, appIdentifier, new Date(date), config.pricing.cachingSeconds, subscribeLink);
|
|
183
|
-
return { expired, subscribeLink };
|
|
192
|
+
addToCache(organization, appIdentifier, new Date(date), (_f = config.pricing) === null || _f === void 0 ? void 0 : _f.cachingSeconds, subscribeLink);
|
|
193
|
+
return { expired, subscribeLink, daysLeft };
|
|
184
194
|
}
|
|
185
195
|
if (config.onError) {
|
|
186
196
|
config.onError(e);
|
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
<body>
|
|
6
6
|
<div class="i_w">
|
|
7
|
-
<div class=
|
|
7
|
+
<div class="top">
|
|
8
|
+
{{#if checkSubscription}}
|
|
9
|
+
<crowdin-alert id="subscription-info" no-icon="true" type="warning" style="display: none;">
|
|
10
|
+
<div class="box-center">
|
|
11
|
+
<p class="m-0"></p>
|
|
12
|
+
<crowdin-button class="ml-1" primary onclick="window.open(subscriptionLink,'_blank')">Subscribe</crowdin-button>
|
|
13
|
+
</div>
|
|
14
|
+
</crowdin-alert>
|
|
15
|
+
{{/if}}
|
|
8
16
|
{{#if infoModal}}
|
|
9
17
|
<crowdin-button icon-before="info" onclick="infoModal.open();">{{infoModal.title}}</crowdin-button>
|
|
10
18
|
{{/if}}
|
|
@@ -439,6 +447,25 @@
|
|
|
439
447
|
.finally(() => (appComponent.setAttribute(`is-${provider}-loading`, false)));
|
|
440
448
|
}
|
|
441
449
|
{{/if}}
|
|
450
|
+
|
|
451
|
+
{{#if checkSubscription}}
|
|
452
|
+
const subscriptionInfo = document.getElementById('subscription-info');
|
|
453
|
+
const subscriptionInfoText = subscriptionInfo.getElementsByTagName('p')[0];
|
|
454
|
+
function getSubscriptionInfo() {
|
|
455
|
+
checkOrigin()
|
|
456
|
+
.then(restParams => fetch('api/subscription-info' + restParams))
|
|
457
|
+
.then(checkResponse)
|
|
458
|
+
.then((res) => {
|
|
459
|
+
if (res.showInfo) {
|
|
460
|
+
subscriptionLink = res.subscribeLink;
|
|
461
|
+
subscriptionInfoText.textContent = `Your trial expires in ${res.daysLeft} days.`
|
|
462
|
+
subscriptionInfo.style.display = 'block';
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
getSubscriptionInfo();
|
|
468
|
+
{{/if}}
|
|
442
469
|
</script>
|
|
443
470
|
|
|
444
471
|
</html>
|
package/package.json
CHANGED