@blocklet/sdk 1.8.15 → 1.8.18
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/component/index.js +79 -0
- package/lib/config.js +14 -0
- package/lib/database/index.js +41 -0
- package/lib/env.js +0 -37
- package/lib/index.js +4 -0
- package/lib/middlewares/component.js +28 -0
- package/lib/middlewares/index.js +2 -0
- package/lib/service/auth.js +3 -2
- package/package.json +14 -13
- package/lib/database.js +0 -98
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const axios = require('axios').default;
|
|
2
|
+
const get = require('lodash/get');
|
|
3
|
+
const joinURL = require('url-join');
|
|
4
|
+
const stableStringify = require('json-stable-stringify');
|
|
5
|
+
const { getParentComponentName } = require('@blocklet/meta/lib/util');
|
|
6
|
+
|
|
7
|
+
const getWallet = require('../wallet');
|
|
8
|
+
const config = require('../config');
|
|
9
|
+
|
|
10
|
+
const parseMountPoints = () => JSON.parse(process.env.BLOCKLET_MOUNT_POINTS);
|
|
11
|
+
const parsePorts = () => JSON.parse(process.env.BLOCKLET_WEB_PORTS);
|
|
12
|
+
|
|
13
|
+
const call = async ({ name, path: _path, data }) => {
|
|
14
|
+
const baseURL = name ? getChildWebEndpoint(name) : getParentWebEndpoint();
|
|
15
|
+
const url = joinURL(baseURL, _path);
|
|
16
|
+
|
|
17
|
+
return doCall({ url, data });
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const getWebEndpoint = (name) => {
|
|
21
|
+
const ports = parsePorts();
|
|
22
|
+
if (ports[name]) {
|
|
23
|
+
return `http://127.0.0.1:${ports[name]}`;
|
|
24
|
+
}
|
|
25
|
+
return '';
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const getChildWebEndpoint = (name) => {
|
|
29
|
+
const fullName = `${process.env.BLOCKLET_REAL_NAME}/${name}`;
|
|
30
|
+
return getWebEndpoint(fullName);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getParentWebEndpoint = () => {
|
|
34
|
+
const parentName = getParentComponentName(process.env.BLOCKLET_REAL_NAME);
|
|
35
|
+
return getWebEndpoint(parentName);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const getComponentMountPoint = (s) => {
|
|
39
|
+
const mountPoints = parseMountPoints();
|
|
40
|
+
const item = mountPoints.find((x) => [x.title, x.name, x.did].includes(s));
|
|
41
|
+
return item ? item.mountPoint : '';
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getComponentMountPoints = () => {
|
|
45
|
+
return parseMountPoints();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const sign = (data) => {
|
|
49
|
+
const wallet = getWallet();
|
|
50
|
+
const signData = typeof data === 'undefined' ? {} : data;
|
|
51
|
+
|
|
52
|
+
return { 'x-component-sig': wallet.sign(stableStringify(signData)) };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const doCall = async ({ url, data }) => {
|
|
56
|
+
try {
|
|
57
|
+
const resp = await axios.post(url, data, { headers: sign(data), timeout: 60000 });
|
|
58
|
+
config.logger.info(`call ${url} api success`);
|
|
59
|
+
return resp;
|
|
60
|
+
} catch (error) {
|
|
61
|
+
config.logger.error(`call ${url} api failed`, {
|
|
62
|
+
url,
|
|
63
|
+
responseStatus: get(error, 'response.status'),
|
|
64
|
+
responseData: get(error, 'response.data'),
|
|
65
|
+
error,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
throw new Error(`call ${url} api failed`);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
call,
|
|
74
|
+
getComponentMountPoint,
|
|
75
|
+
getComponentMountPoints,
|
|
76
|
+
getWebEndpoint,
|
|
77
|
+
getChildWebEndpoint,
|
|
78
|
+
getParentWebEndpoint,
|
|
79
|
+
};
|
package/lib/config.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
logger: {
|
|
5
|
+
info: console.log,
|
|
6
|
+
debug: (...args) => {
|
|
7
|
+
if (process.env.NODE_ENV === 'development') {
|
|
8
|
+
console.debug(...args);
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
warn: console.warn,
|
|
12
|
+
error: console.error,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { DataStore: BaseStore } = require('@nedb/core');
|
|
4
|
+
|
|
5
|
+
if (!process.env.BLOCKLET_DATA_DIR) {
|
|
6
|
+
throw new Error('Blocklet SDK must be used in blocklet runtime');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const DB_DIR = path.join(process.env.BLOCKLET_DATA_DIR, 'db');
|
|
10
|
+
fs.ensureDirSync(DB_DIR);
|
|
11
|
+
|
|
12
|
+
module.exports = class DataStore extends BaseStore {
|
|
13
|
+
constructor(name, options = {}) {
|
|
14
|
+
const filename = options.filename || path.join(DB_DIR, `${name}.db`);
|
|
15
|
+
super({
|
|
16
|
+
filename,
|
|
17
|
+
autoload: true,
|
|
18
|
+
timestampData: true,
|
|
19
|
+
onload: (err) => {
|
|
20
|
+
if (err) {
|
|
21
|
+
console.error(`failed to load disk database ${filename}`, err);
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
...options,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async exists(...args) {
|
|
29
|
+
const doc = await this.findOne(...args);
|
|
30
|
+
return !!doc;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async paginate({ condition = {}, sort = {}, page = 1, size = 100, projection = {} }) {
|
|
34
|
+
return this.cursor(condition)
|
|
35
|
+
.sort(sort)
|
|
36
|
+
.skip(Math.max(page * size - size, 0))
|
|
37
|
+
.limit(Math.max(size, 1))
|
|
38
|
+
.projection(projection)
|
|
39
|
+
.exec();
|
|
40
|
+
}
|
|
41
|
+
};
|
package/lib/env.js
CHANGED
|
@@ -1,35 +1,3 @@
|
|
|
1
|
-
const { getParentComponentName } = require('@blocklet/meta/lib/util');
|
|
2
|
-
|
|
3
|
-
const parsePorts = () => JSON.parse(process.env.BLOCKLET_WEB_PORTS);
|
|
4
|
-
const parseMountPoints = () => JSON.parse(process.env.BLOCKLET_MOUNT_POINTS);
|
|
5
|
-
|
|
6
|
-
const getComponentMountPoint = (s) => {
|
|
7
|
-
const mountPoints = parseMountPoints();
|
|
8
|
-
const item = mountPoints.find((x) => [x.title, x.name, x.did].includes(s));
|
|
9
|
-
return item ? item.mountPoint : '';
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const getComponentMountPoints = () => {
|
|
13
|
-
return parseMountPoints();
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const getWebEndpoint = (name) => {
|
|
17
|
-
const ports = parsePorts();
|
|
18
|
-
if (ports[name]) {
|
|
19
|
-
return `http://127.0.0.1:${ports[name]}`;
|
|
20
|
-
}
|
|
21
|
-
return '';
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const getChildWebEndpoint = (name) => {
|
|
25
|
-
const fullName = `${process.env.BLOCKLET_REAL_NAME}/${name}`;
|
|
26
|
-
return getWebEndpoint(fullName);
|
|
27
|
-
};
|
|
28
|
-
const getParentWebEndpoint = () => {
|
|
29
|
-
const parentName = getParentComponentName(process.env.BLOCKLET_REAL_NAME);
|
|
30
|
-
return getWebEndpoint(parentName);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
1
|
module.exports = Object.freeze({
|
|
34
2
|
appId: process.env.BLOCKLET_APP_ID,
|
|
35
3
|
appName: process.env.BLOCKLET_APP_NAME,
|
|
@@ -39,9 +7,4 @@ module.exports = Object.freeze({
|
|
|
39
7
|
dataDir: process.env.BLOCKLET_DATA_DIR,
|
|
40
8
|
cacheDir: process.env.BLOCKLET_CACHE_DIR,
|
|
41
9
|
mode: process.env.BLOCKLET_MODE,
|
|
42
|
-
getWebEndpoint,
|
|
43
|
-
getChildWebEndpoint,
|
|
44
|
-
getParentWebEndpoint,
|
|
45
|
-
getComponentMountPoints,
|
|
46
|
-
getComponentMountPoint,
|
|
47
10
|
});
|
package/lib/index.js
CHANGED
|
@@ -8,6 +8,8 @@ const Database = require('./database');
|
|
|
8
8
|
const env = require('./env');
|
|
9
9
|
const middlewares = require('./middlewares');
|
|
10
10
|
const getWallet = require('./wallet');
|
|
11
|
+
const component = require('./component');
|
|
12
|
+
const config = require('./config');
|
|
11
13
|
|
|
12
14
|
module.exports = {
|
|
13
15
|
AuthService,
|
|
@@ -20,4 +22,6 @@ module.exports = {
|
|
|
20
22
|
getWallet,
|
|
21
23
|
env,
|
|
22
24
|
middlewares,
|
|
25
|
+
component,
|
|
26
|
+
config,
|
|
23
27
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const stableStringify = require('json-stable-stringify');
|
|
2
|
+
|
|
3
|
+
const getWallet = require('../wallet');
|
|
4
|
+
const config = require('../config');
|
|
5
|
+
|
|
6
|
+
const verifySig = (req, res, next) => {
|
|
7
|
+
try {
|
|
8
|
+
const wallet = getWallet();
|
|
9
|
+
const sig = req.get('x-component-sig');
|
|
10
|
+
if (!sig) {
|
|
11
|
+
return res.status(400).json({ error: 'Bad Request' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const data = typeof req.body === 'undefined' ? {} : req.body;
|
|
15
|
+
|
|
16
|
+
const verified = wallet.verify(stableStringify(data), sig);
|
|
17
|
+
if (!verified) {
|
|
18
|
+
return res.status(401).json({ error: 'verify sig failed' });
|
|
19
|
+
}
|
|
20
|
+
} catch (error) {
|
|
21
|
+
config.logger.error(error);
|
|
22
|
+
return res.status(401).json({ error: 'verify sig failed' });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return next();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = { verifySig };
|
package/lib/middlewares/index.js
CHANGED
package/lib/service/auth.js
CHANGED
|
@@ -59,11 +59,12 @@ class AuthService extends Client {
|
|
|
59
59
|
'hasPermission',
|
|
60
60
|
|
|
61
61
|
// user passport
|
|
62
|
+
'issuePassportToUser',
|
|
63
|
+
'revokeUserPassport',
|
|
64
|
+
'enableUserPassport',
|
|
62
65
|
// 'getPassportIssuances',
|
|
63
66
|
// 'createPassportIssuance',
|
|
64
67
|
// 'deletePassportIssuance',
|
|
65
|
-
// 'revokeUserPassport',
|
|
66
|
-
// 'enableUserPassport',
|
|
67
68
|
|
|
68
69
|
// permission
|
|
69
70
|
'getPermissions',
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.8.
|
|
6
|
+
"version": "1.8.18",
|
|
7
7
|
"description": "graphql client to read/write data on abt node",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,20 +19,21 @@
|
|
|
19
19
|
"author": "linchen1987 <linchen.1987@foxmail.com> (http://github.com/linchen1987)",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/client": "1.8.
|
|
23
|
-
"@abtnode/constant": "1.8.
|
|
24
|
-
"@arcblock/did-auth": "1.17.
|
|
25
|
-
"@arcblock/jwt": "1.17.
|
|
26
|
-
"@arcblock/ws": "1.17.
|
|
27
|
-
"@blocklet/meta": "1.8.
|
|
28
|
-
"@did-connect/authenticator": "^2.1.
|
|
29
|
-
"@did-connect/handler": "^2.1.
|
|
30
|
-
"@nedb/core": "^
|
|
31
|
-
"@ocap/mcrypto": "1.17.
|
|
32
|
-
"@ocap/wallet": "1.17.
|
|
22
|
+
"@abtnode/client": "1.8.18",
|
|
23
|
+
"@abtnode/constant": "1.8.18",
|
|
24
|
+
"@arcblock/did-auth": "1.17.19",
|
|
25
|
+
"@arcblock/jwt": "1.17.19",
|
|
26
|
+
"@arcblock/ws": "1.17.19",
|
|
27
|
+
"@blocklet/meta": "1.8.18",
|
|
28
|
+
"@did-connect/authenticator": "^2.1.13",
|
|
29
|
+
"@did-connect/handler": "^2.1.13",
|
|
30
|
+
"@nedb/core": "^2.0.3",
|
|
31
|
+
"@ocap/mcrypto": "1.17.19",
|
|
32
|
+
"@ocap/wallet": "1.17.19",
|
|
33
33
|
"axios": "^0.27.2",
|
|
34
34
|
"fs-extra": "^10.1.0",
|
|
35
35
|
"joi": "^17.6.0",
|
|
36
|
+
"json-stable-stringify": "^1.0.1",
|
|
36
37
|
"lodash": "^4.17.21",
|
|
37
38
|
"lru-cache": "^6.0.0",
|
|
38
39
|
"url-join": "^4.0.1"
|
|
@@ -41,5 +42,5 @@
|
|
|
41
42
|
"detect-port": "^1.3.0",
|
|
42
43
|
"jest": "^27.5.1"
|
|
43
44
|
},
|
|
44
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "7d82c570913bedf740afca15c27ef10d05aa85fc"
|
|
45
46
|
}
|
package/lib/database.js
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
const { PromisedDatastore } = require('@nedb/core');
|
|
4
|
-
|
|
5
|
-
if (!process.env.BLOCKLET_DATA_DIR) {
|
|
6
|
-
throw new Error('valid BLOCKLET_DATA_DIR env is required');
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const DB_DIR = path.join(process.env.BLOCKLET_DATA_DIR, 'db');
|
|
10
|
-
fs.ensureDirSync(DB_DIR);
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* 判断查询的数据是否存在
|
|
14
|
-
* 因为函数的定义是判断指定条件是否存在,所以需要直接返回结果,而不是返回一个 nedb 对象或 nedb cursor 对象
|
|
15
|
-
* @returns Boolean
|
|
16
|
-
*/
|
|
17
|
-
async function exists(...args) {
|
|
18
|
-
const tmp = await this.findOne(...args);
|
|
19
|
-
return !!tmp;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* 分页查询
|
|
24
|
-
* 这里需要返回一个 nedb cursor 对象,因为后续可能还会链式操作别的方法,所以不能使用 await
|
|
25
|
-
* @param {number} page 页码
|
|
26
|
-
* @param {number} size 分页大小
|
|
27
|
-
* @returns nedb cursor
|
|
28
|
-
*/
|
|
29
|
-
function paginate(page, size) {
|
|
30
|
-
const tmp = this.skip(page * size - size).limit(size);
|
|
31
|
-
return tmp;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 代理 nedb cursor,如果需要对查询条件做扩展,需要把方法添加到这里
|
|
36
|
-
* @param {Nedb Cursor} cursor
|
|
37
|
-
* @returns nedb cursor
|
|
38
|
-
*/
|
|
39
|
-
function proxyCursor(cursor) {
|
|
40
|
-
return new Proxy(cursor, {
|
|
41
|
-
get(target, prop) {
|
|
42
|
-
if (prop === 'paginate') return paginate;
|
|
43
|
-
|
|
44
|
-
return target[prop];
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* 代理 nedb 对象,如果需要在 nedb 上增加方法,需要把方法添加到这里
|
|
51
|
-
* @param {Nedb} db nedb
|
|
52
|
-
* @returns promise
|
|
53
|
-
*/
|
|
54
|
-
function proxyNedb(db) {
|
|
55
|
-
return new Proxy(db, {
|
|
56
|
-
get(target, prop) {
|
|
57
|
-
const propFn = target[prop];
|
|
58
|
-
if (prop === 'exists') return exists;
|
|
59
|
-
|
|
60
|
-
if (PromisedDatastore.CURSOR_FN_LIST.includes(prop)) {
|
|
61
|
-
return function wrap(...args) {
|
|
62
|
-
const rawFn = propFn.bind(this)(...args);
|
|
63
|
-
return proxyCursor(rawFn);
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
return propFn;
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
module.exports = function Datastore(name, options = {}) {
|
|
72
|
-
if (!new.target) {
|
|
73
|
-
throw new Error("This function must called by 'new' command!");
|
|
74
|
-
}
|
|
75
|
-
const filename = options.filename || path.join(DB_DIR, `${name}.db`);
|
|
76
|
-
const db = new PromisedDatastore({
|
|
77
|
-
filename,
|
|
78
|
-
autoload: true,
|
|
79
|
-
timestampData: true,
|
|
80
|
-
onload: (err) => {
|
|
81
|
-
if (err) {
|
|
82
|
-
console.error(`failed to load disk database ${filename}`, err);
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
...options,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const proxyDb = proxyNedb(db);
|
|
89
|
-
|
|
90
|
-
// 如果直接返回 proxyDb,则无法使用 class 的 extends 进行类的方法扩展
|
|
91
|
-
// 这个 proxy 首先会判断自身是否有这个方法,如果有,则直接返回;如果没有,则会去 proxyDb 中查找
|
|
92
|
-
return new Proxy(this, {
|
|
93
|
-
get(target, prop) {
|
|
94
|
-
if (target[prop]) return target[prop];
|
|
95
|
-
return proxyDb[prop];
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
};
|