@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.
@@ -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
+ };
@@ -0,0 +1,7 @@
1
+ const ADMIN_ROLES = ['owner', 'admin'];
2
+
3
+ const canAccessAdmin = (role) => ADMIN_ROLES.includes(role);
4
+
5
+ module.exports = {
6
+ canAccessAdmin,
7
+ };
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
+ };
@@ -0,0 +1,10 @@
1
+ const create = (schema) => (data, locale) => {
2
+ const { error, value } = schema.validate(data, { errors: { language: locale || 'en' } });
3
+ if (error) {
4
+ throw new Error(error.message);
5
+ }
6
+
7
+ return value;
8
+ };
9
+
10
+ module.exports = { create };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/launcher-util",
3
- "version": "1.8.25",
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": "src/index.js",
12
- "directories": {
13
- "lib": "lib"
14
- },
11
+ "main": "lib/util.js",
15
12
  "files": [
16
- "src"
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.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": "a096cbfd8430d1a8024bc7f95da028bf6ed1b203"
39
+ "gitHead": "6dd1ea73f628b8c27a80c467f2b198418ea29a8c"
40
40
  }