@blocklet/launcher-util 1.8.25 → 1.8.28
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/lib/constant.js +102 -0
- package/lib/locale.js +19 -0
- package/lib/middleware.js +86 -0
- package/lib/permission.js +7 -0
- package/lib/util.js +101 -0
- package/lib/validator.js +10 -0
- package/package.json +9 -9
package/lib/constant.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const INSTANCE_STATUS = Object.freeze({
|
|
2
|
+
error: 0,
|
|
3
|
+
waiting: 5,
|
|
4
|
+
pending: 10,
|
|
5
|
+
starting: 20,
|
|
6
|
+
running: 30,
|
|
7
|
+
restarting: 40,
|
|
8
|
+
stopping: 50,
|
|
9
|
+
stopped: 60,
|
|
10
|
+
terminated: 70,
|
|
11
|
+
expired: 80,
|
|
12
|
+
underMaintenance: 90,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const PLAN_STATUS = Object.freeze({
|
|
16
|
+
draft: 10,
|
|
17
|
+
published: 20,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const SERVER_ACTIVITY_TYPE = Object.freeze({
|
|
21
|
+
purchase: 'purchase',
|
|
22
|
+
launch: 'launch',
|
|
23
|
+
createFailed: 'createFailed',
|
|
24
|
+
created: 'created',
|
|
25
|
+
start: 'start',
|
|
26
|
+
started: 'started',
|
|
27
|
+
startFailed: 'startFailed',
|
|
28
|
+
stop: 'stop',
|
|
29
|
+
stopped: 'stopped',
|
|
30
|
+
stopFailed: 'stopFailed',
|
|
31
|
+
restart: 'restart',
|
|
32
|
+
restarted: 'restarted',
|
|
33
|
+
restartFailed: 'restartFailed',
|
|
34
|
+
expired: 'expired',
|
|
35
|
+
terminate: 'terminate',
|
|
36
|
+
terminated: 'terminated',
|
|
37
|
+
terminateFailed: 'terminateFailed',
|
|
38
|
+
renewaled: 'renewaled',
|
|
39
|
+
transferred: 'transferred',
|
|
40
|
+
replacement: 'replacement',
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const toMap = (staus) =>
|
|
44
|
+
Object.keys(staus).reduce((acc, cur) => {
|
|
45
|
+
acc[staus[cur]] = cur;
|
|
46
|
+
return acc;
|
|
47
|
+
}, {});
|
|
48
|
+
|
|
49
|
+
const fromStatus = (map) => (status) => map[status];
|
|
50
|
+
|
|
51
|
+
const statusInstanceMap = toMap(INSTANCE_STATUS);
|
|
52
|
+
const planStatusMap = toMap(PLAN_STATUS);
|
|
53
|
+
|
|
54
|
+
const fromInstanceStatus = fromStatus(statusInstanceMap);
|
|
55
|
+
const fromPlanStatus = fromStatus(planStatusMap);
|
|
56
|
+
|
|
57
|
+
module.exports = Object.freeze({
|
|
58
|
+
SKU_STATUS: Object.freeze({
|
|
59
|
+
DISABLED: 0,
|
|
60
|
+
ENABLED: 1,
|
|
61
|
+
}),
|
|
62
|
+
SUPPORTED_EC2_TYPES: ['t2.micro', 't2.small', 't3.micro', 't3.small'],
|
|
63
|
+
ORDER_STATUS: Object.freeze({
|
|
64
|
+
normal: 10,
|
|
65
|
+
expired: 20,
|
|
66
|
+
}),
|
|
67
|
+
PAYMENT_STATUS: Object.freeze({
|
|
68
|
+
unpaid: 10,
|
|
69
|
+
paid: 20,
|
|
70
|
+
done: 30,
|
|
71
|
+
expired: 40,
|
|
72
|
+
canceled: 60,
|
|
73
|
+
failed: 70,
|
|
74
|
+
}),
|
|
75
|
+
PAYMENT_TYPES: {
|
|
76
|
+
purchase: 'purchase',
|
|
77
|
+
renewal: 'renewal',
|
|
78
|
+
autoRenewal: 'auto-renewal',
|
|
79
|
+
},
|
|
80
|
+
PAYMENT_METHODS: Object.freeze({
|
|
81
|
+
crypto: 'crypto',
|
|
82
|
+
stripe: 'stripe',
|
|
83
|
+
fiat: 'fiat', // TODO: 区分支付货币和支付方式
|
|
84
|
+
}),
|
|
85
|
+
DID_DOMAIN_SUFFIX: 'did.abtnet.io',
|
|
86
|
+
INSTANCE_STATUS,
|
|
87
|
+
fromInstanceStatus,
|
|
88
|
+
fromPlanStatus,
|
|
89
|
+
REDEEM_NFT_ID: 'redeem',
|
|
90
|
+
INSTANCE_MAX_NAME_LENGTH: 30,
|
|
91
|
+
INSTANCE_MAX_DESC_LENGTH: 50,
|
|
92
|
+
LAUNCH_TYPE: {
|
|
93
|
+
instant: 'instant',
|
|
94
|
+
redeem: 'redeem',
|
|
95
|
+
},
|
|
96
|
+
PLAN_STATUS,
|
|
97
|
+
SERVER_ACTIVITY_TYPE,
|
|
98
|
+
CURRENCY_TYPE: {
|
|
99
|
+
fiat: 'fiat',
|
|
100
|
+
crypto: 'crypto',
|
|
101
|
+
},
|
|
102
|
+
});
|
package/lib/locale.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module.exports = (locales) => {
|
|
2
|
+
const replace = (template, data) =>
|
|
3
|
+
(template || '').replace(/{(\w*)}/g, (_, key) =>
|
|
4
|
+
Object.prototype.hasOwnProperty.call(data || {}, key) ? data[key] : ''
|
|
5
|
+
);
|
|
6
|
+
|
|
7
|
+
const translate = (key, locale, params) => {
|
|
8
|
+
if (!locales[locale]) {
|
|
9
|
+
// eslint-disable-next-line no-param-reassign
|
|
10
|
+
locale = 'en';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return replace(locales[locale][key], params) || key;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const createTranslateFunc = (locale) => (key, params) => translate(key, locale || 'en', params);
|
|
17
|
+
|
|
18
|
+
return { translate, createTranslateFunc };
|
|
19
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
const pick = require('lodash.pick');
|
|
2
|
+
|
|
3
|
+
const { getSort } = require('./util');
|
|
4
|
+
|
|
5
|
+
const MAX_PAGING_SIZE = 100;
|
|
6
|
+
const DEFAULT_PAGING_SIZE = MAX_PAGING_SIZE;
|
|
7
|
+
const DEFAULT_PAGE = 1;
|
|
8
|
+
|
|
9
|
+
const pagination = (req, res, next) => {
|
|
10
|
+
const paging = {
|
|
11
|
+
page: DEFAULT_PAGE,
|
|
12
|
+
size: DEFAULT_PAGING_SIZE,
|
|
13
|
+
};
|
|
14
|
+
req.paging = paging;
|
|
15
|
+
|
|
16
|
+
if (!Number.isNaN(Number(req.query.page))) {
|
|
17
|
+
paging.page = Number(req.query.page);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (!Number.isNaN(Number(req.query.size))) {
|
|
21
|
+
const size = Number(req.query.size);
|
|
22
|
+
paging.size = size <= MAX_PAGING_SIZE ? size : MAX_PAGING_SIZE;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
paging.sort = getSort(req.query.sortby, req.query.sortdir);
|
|
26
|
+
|
|
27
|
+
next();
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const validate =
|
|
31
|
+
(schema, option = {}) =>
|
|
32
|
+
(req, res, next) => {
|
|
33
|
+
const { error, value } = schema.validate(req.body, {
|
|
34
|
+
errors: { language: req.query.locale || 'en' },
|
|
35
|
+
...option,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (error) {
|
|
39
|
+
res.status(400).json({ error: error.message });
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
req.data = value;
|
|
44
|
+
next();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const createAuditMiddleware =
|
|
48
|
+
({ baseURL, writer, formatterMap }) =>
|
|
49
|
+
(req, res, next) => {
|
|
50
|
+
if (['PUT', 'POST', 'PATCH', 'DELETE'].includes(req.method)) {
|
|
51
|
+
const originalResponse = res.end.bind(res);
|
|
52
|
+
const wrappedResponse = (...args) => {
|
|
53
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
54
|
+
const key = `${req.baseUrl}${req.route.path}`.replace(baseURL, req.method.toLowerCase());
|
|
55
|
+
const formater = formatterMap[key];
|
|
56
|
+
if (formater) {
|
|
57
|
+
const data = {
|
|
58
|
+
user: { ...pick(req.user, ['did', 'role', 'fullName']) },
|
|
59
|
+
id: formater.id,
|
|
60
|
+
resource: formater.resource,
|
|
61
|
+
payload: formater.format({ req, res }),
|
|
62
|
+
ip: req.get('x-Real-ip', ''),
|
|
63
|
+
ua: req.get('user-agent', ''),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
writer(data);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return originalResponse(...args);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
res.end = wrappedResponse;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
next();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
module.exports = {
|
|
80
|
+
createAuditMiddleware,
|
|
81
|
+
pagination,
|
|
82
|
+
validate,
|
|
83
|
+
DEFAULT_PAGE,
|
|
84
|
+
MAX_PAGING_SIZE,
|
|
85
|
+
DEFAULT_PAGING_SIZE,
|
|
86
|
+
};
|
package/lib/util.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require('moment-timezone');
|
|
2
|
+
const moment = require('moment');
|
|
3
|
+
const { BN, fromUnitToToken, fromTokenToUnit } = require('@ocap/util');
|
|
4
|
+
|
|
5
|
+
const calculatePrice = (duration, unitPrice, from) => {
|
|
6
|
+
// eslint-disable-next-line no-param-reassign
|
|
7
|
+
from = from || new Date();
|
|
8
|
+
|
|
9
|
+
const diffDays = moment(from).add(duration.value, duration.unit).diff(moment(from), 'days');
|
|
10
|
+
|
|
11
|
+
const unitPriceBN = new BN(fromTokenToUnit(unitPrice));
|
|
12
|
+
const diffDaysBN = new BN(diffDays);
|
|
13
|
+
const total = unitPriceBN.mul(diffDaysBN).toString();
|
|
14
|
+
|
|
15
|
+
return Number(fromUnitToToken(total).toString());
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const DURATION_LOCALE = {
|
|
19
|
+
en: {
|
|
20
|
+
d: ' day',
|
|
21
|
+
ds: ' days',
|
|
22
|
+
m: ' month',
|
|
23
|
+
ms: ' months',
|
|
24
|
+
y: ' year',
|
|
25
|
+
ys: ' years',
|
|
26
|
+
},
|
|
27
|
+
zh: {
|
|
28
|
+
d: '天',
|
|
29
|
+
ds: '天',
|
|
30
|
+
m: '个月',
|
|
31
|
+
ms: '个月',
|
|
32
|
+
y: '年',
|
|
33
|
+
ys: '年',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const prettyDurationUnit = ({ value, unit }, locale) => {
|
|
38
|
+
if (!Object.keys(DURATION_LOCALE).includes(locale)) {
|
|
39
|
+
// eslint-disable-next-line no-param-reassign
|
|
40
|
+
locale = 'en';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const localeKey = value > 1 ? `${unit}s` : unit;
|
|
44
|
+
return DURATION_LOCALE[locale][localeKey.toLowerCase()];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const prettyDuration = ({ value, unit }, locale) => {
|
|
48
|
+
return `${value}${prettyDurationUnit({ value, unit }, locale)}`;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const formatExpirationTime = (time, locale) => {
|
|
52
|
+
/* eslint-disable no-param-reassign */
|
|
53
|
+
if (!time) {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
locale = locale || 'en-us';
|
|
58
|
+
if (locale === 'zh') {
|
|
59
|
+
locale = 'zh-cn';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return moment(time).locale(locale).tz(Intl.DateTimeFormat().resolvedOptions().timeZone).format('lll z');
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const sortArrayByDate = (array, asc = true, field = undefined) =>
|
|
66
|
+
(array || []).sort((x, y) => {
|
|
67
|
+
let v1 = x;
|
|
68
|
+
let v2 = y;
|
|
69
|
+
if (typeof field !== 'undefined') {
|
|
70
|
+
v1 = v1[field];
|
|
71
|
+
v2 = v2[field];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (v1 === v2) {
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const directionResult = asc ? 1 : -1;
|
|
79
|
+
if (moment(v1).diff(moment(v2)) > 0) {
|
|
80
|
+
return directionResult;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return -1 * directionResult;
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const getSort = (sortby, sortdir) => {
|
|
87
|
+
if (sortby) {
|
|
88
|
+
return { [sortby]: sortdir };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { createdAt: -1 };
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
module.exports = {
|
|
95
|
+
calculatePrice,
|
|
96
|
+
prettyDurationUnit,
|
|
97
|
+
prettyDuration,
|
|
98
|
+
formatExpirationTime,
|
|
99
|
+
getSort,
|
|
100
|
+
sortArrayByDate,
|
|
101
|
+
};
|
package/lib/validator.js
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/launcher-util",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.28",
|
|
4
4
|
"description": "Common constants",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"constant"
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"author": "polunzh <polunzh@gmail.com>",
|
|
9
9
|
"homepage": "https://github.com/blocklet/launcher#readme",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
|
-
"main": "
|
|
12
|
-
"directories": {
|
|
13
|
-
"lib": "lib"
|
|
14
|
-
},
|
|
11
|
+
"main": "lib/util.js",
|
|
15
12
|
"files": [
|
|
16
|
-
"
|
|
13
|
+
"lib",
|
|
14
|
+
"LICENSE",
|
|
15
|
+
"package.json",
|
|
16
|
+
"README.md"
|
|
17
17
|
],
|
|
18
18
|
"publishConfig": {
|
|
19
19
|
"access": "public"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"url": "git+https://github.com/blocklet/launcher.git"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"lint": "eslint lib",
|
|
26
|
+
"lint": "eslint -v && eslint lib",
|
|
27
27
|
"test": "node jest.js --runInBand",
|
|
28
28
|
"coverage": "npm run test -- --coverage"
|
|
29
29
|
},
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"url": "https://github.com/blocklet/launcher/issues"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ocap/util": "^1.17.
|
|
34
|
+
"@ocap/util": "^1.17.19",
|
|
35
35
|
"lodash.pick": "^4.4.0",
|
|
36
36
|
"moment": "^2.29.4",
|
|
37
37
|
"moment-timezone": "^0.5.37"
|
|
38
38
|
},
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "6dd1ea73f628b8c27a80c467f2b198418ea29a8c"
|
|
40
40
|
}
|