@abtnode/blocklet-services 1.16.8-beta-b3039c78 → 1.16.8-beta-186fd5aa
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/api/emails/components/footer.js +1 -0
- package/api/emails/components/header.js +1 -1
- package/api/emails/components/layout.js +2 -2
- package/api/emails/libs/highlight.js +3 -3
- package/api/emails/pages/notification.js +4 -4
- package/api/emails/test.js +6 -6
- package/api/libs/email.js +19 -6
- package/api/services/studio/index.js +12 -2
- package/api/socket/channel/did.js +8 -4
- package/package.json +16 -16
|
@@ -15,6 +15,7 @@ const footer = {
|
|
|
15
15
|
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif",
|
|
16
16
|
fontSize: '12px',
|
|
17
17
|
lineHeight: '22px',
|
|
18
|
+
margin: 0,
|
|
18
19
|
};
|
|
19
20
|
const link = {
|
|
20
21
|
color: '#2754C5',
|
|
@@ -15,6 +15,6 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
15
15
|
const components_1 = require("@react-email/components");
|
|
16
16
|
function Header(_a) {
|
|
17
17
|
var { appInfo } = _a, props = __rest(_a, ["appInfo"]);
|
|
18
|
-
return ((0, jsx_runtime_1.jsx)(components_1.Section, Object.assign({}, props, { children: (0, jsx_runtime_1.jsx)(components_1.Img, { src: appInfo.logo, height: "
|
|
18
|
+
return ((0, jsx_runtime_1.jsx)(components_1.Section, Object.assign({}, props, { children: (0, jsx_runtime_1.jsx)(components_1.Img, { src: appInfo.logo, height: "50", alt: appInfo.title }) })));
|
|
19
19
|
}
|
|
20
20
|
exports.default = Header;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
4
|
const components_1 = require("@react-email/components");
|
|
5
|
-
function Layout({ children, mainStyle = {}, containerStyle = {}, }) {
|
|
6
|
-
return ((0, jsx_runtime_1.jsxs)(components_1.Html, { children: [(0, jsx_runtime_1.jsx)(components_1.Head, { children: (0, jsx_runtime_1.jsx)("title", { children:
|
|
5
|
+
function Layout({ children, mainStyle = {}, containerStyle = {}, subject, }) {
|
|
6
|
+
return ((0, jsx_runtime_1.jsxs)(components_1.Html, { children: [(0, jsx_runtime_1.jsx)(components_1.Head, { children: subject && (0, jsx_runtime_1.jsx)("title", { children: subject }) }), (0, jsx_runtime_1.jsx)(components_1.Body, Object.assign({ style: Object.assign(Object.assign({}, main), mainStyle) }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ style: Object.assign(Object.assign({}, main), mainStyle) }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ style: { padding: '30px 20px' } }, { children: (0, jsx_runtime_1.jsx)(components_1.Container, Object.assign({ style: Object.assign(Object.assign({}, container), containerStyle) }, { children: (0, jsx_runtime_1.jsx)("div", { children: children }) })) })) })) }))] }));
|
|
7
7
|
}
|
|
8
8
|
exports.default = Layout;
|
|
9
9
|
const main = {
|
|
@@ -42,13 +42,13 @@ const toClickableSpan = (str, isHighLight = true) => {
|
|
|
42
42
|
}
|
|
43
43
|
// HACK: 邮件中无法支持 dapp 的展示,缺少 dapp 链接,只能作为加粗展示
|
|
44
44
|
if ((0, func_1.isSameAddr)(type, 'dapp')) {
|
|
45
|
-
return `<em data-type="${type}" data-chain-id="${chainId}" data-did="${did}">${item.text}</em>`;
|
|
45
|
+
return `<em style="font-weight:bold;" data-type="${type}" data-chain-id="${chainId}" data-did="${did}">${item.text}</em>`;
|
|
46
46
|
}
|
|
47
47
|
if (url) {
|
|
48
|
-
return `<a target="_blank" href="${url}">${item.text}</a>`;
|
|
48
|
+
return `<a target="_blank" style="color:#4598fa;font-weight:bold;" href="${url}">${item.text}</a>`;
|
|
49
49
|
}
|
|
50
50
|
// 默认展示为加粗
|
|
51
|
-
return `<em data-type="${type}" data-chain-id="${chainId}" data-did="${did}">${item.text}</em>`;
|
|
51
|
+
return `<em style="font-weight:bold;" data-type="${type}" data-chain-id="${chainId}" data-did="${did}">${item.text}</em>`;
|
|
52
52
|
}
|
|
53
53
|
return item.text;
|
|
54
54
|
}
|
|
@@ -10,8 +10,8 @@ const footer_1 = __importDefault(require("../components/footer"));
|
|
|
10
10
|
const content_1 = __importDefault(require("../components/content"));
|
|
11
11
|
const layout_1 = __importDefault(require("../components/layout"));
|
|
12
12
|
const header_1 = __importDefault(require("../components/header"));
|
|
13
|
-
const NotificationEmail = ({ title, body = '', attachments = [], actions = [], appInfo, locale = 'en', }) => {
|
|
14
|
-
return ((0, jsx_runtime_1.jsxs)(layout_1.default, Object.assign({ mainStyle: main }, { children: [(0, jsx_runtime_1.jsx)(components_1.Preview, { children:
|
|
13
|
+
const NotificationEmail = ({ title, body = '', subject, attachments = [], actions = [], appInfo, locale = 'en', }) => {
|
|
14
|
+
return ((0, jsx_runtime_1.jsxs)(layout_1.default, Object.assign({ mainStyle: main, subject: subject }, { children: [(0, jsx_runtime_1.jsx)(components_1.Preview, { children: subject }), (0, jsx_runtime_1.jsx)(header_1.default, { appInfo: appInfo }), (0, jsx_runtime_1.jsx)(content_1.default, { style: container, title: title, content: body, attachments: attachments, actions: actions, locale: locale }), (0, jsx_runtime_1.jsx)(footer_1.default, { showCopyright: false, showBlocklet: true, appInfo: appInfo })] })));
|
|
15
15
|
};
|
|
16
16
|
exports.NotificationEmail = NotificationEmail;
|
|
17
17
|
exports.default = exports.NotificationEmail;
|
|
@@ -20,7 +20,7 @@ const main = {
|
|
|
20
20
|
fontFamily,
|
|
21
21
|
};
|
|
22
22
|
const container = {
|
|
23
|
-
margin: '
|
|
23
|
+
margin: '20px auto',
|
|
24
24
|
backgroundColor: '#ffffff',
|
|
25
|
-
padding: '5px 50px
|
|
25
|
+
padding: '5px 50px 30px 60px',
|
|
26
26
|
};
|
package/api/emails/test.js
CHANGED
|
@@ -6,13 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const notification_1 = __importDefault(require("./pages/notification"));
|
|
8
8
|
function Test() {
|
|
9
|
-
const title = '
|
|
9
|
+
const title = 'Head for blocklet email demo';
|
|
10
10
|
const body = 'User <DAMINGZHAO(did:abt:z1Y313EXfBK9FePjDh5cZy6sNY97TneEemB)> has a <Transaction(tx:beta:D20C566BB46A7B6B4DDEA0B42EB3996F0213C1C27C54533F3D40D7B5C6DA59FD)> and it will give your a <Badge (nft:beta:zjdivheWGgy6ucvsYYqP34hVeUgx6743GEfx)> on the DApp <OCAP Playground(dapp:beta:zNKeLKixvCM32TkVM1zmRDdAU3bvm3dTtAcM)>';
|
|
11
11
|
const attachments = [
|
|
12
12
|
{
|
|
13
13
|
type: 'token',
|
|
14
14
|
data: {
|
|
15
|
-
address: '
|
|
15
|
+
address: 'zjdivheWGgy6ucvsYYqP34hVeUgx6743GEfx',
|
|
16
16
|
decimal: 18,
|
|
17
17
|
amount: 10000,
|
|
18
18
|
chianHost: 'beta',
|
|
@@ -23,7 +23,7 @@ function Test() {
|
|
|
23
23
|
type: 'nft',
|
|
24
24
|
data: {
|
|
25
25
|
chianHost: 'beta',
|
|
26
|
-
did: '
|
|
26
|
+
did: 'zjdivheWGgy6ucvsYYqP34hVeUgx6743GEfx',
|
|
27
27
|
},
|
|
28
28
|
},
|
|
29
29
|
// {
|
|
@@ -155,12 +155,12 @@ function Test() {
|
|
|
155
155
|
},
|
|
156
156
|
];
|
|
157
157
|
const appInfo = {
|
|
158
|
-
title: 'Blocklet Email
|
|
158
|
+
title: 'Blocklet Email Demo',
|
|
159
159
|
logo: 'https://picsum.photos/200/100',
|
|
160
160
|
url: 'https://www.arcblock.io',
|
|
161
|
-
description: 'This is a
|
|
161
|
+
description: 'This is a demo blocklet for email test only',
|
|
162
162
|
version: '1.0.0',
|
|
163
163
|
};
|
|
164
|
-
return (0, jsx_runtime_1.jsx)(notification_1.default, { title: title, body: body, attachments: attachments, actions: actions, appInfo: appInfo });
|
|
164
|
+
return ((0, jsx_runtime_1.jsx)(notification_1.default, { title: title, body: body, attachments: attachments, actions: actions, appInfo: appInfo, subject: `[${appInfo.title}] ${title}` }));
|
|
165
165
|
}
|
|
166
166
|
exports.default = Test;
|
package/api/libs/email.js
CHANGED
|
@@ -3,6 +3,8 @@ const { render } = require('@react-email/components');
|
|
|
3
3
|
const { getSafeEnv } = require('@abtnode/core/lib/util');
|
|
4
4
|
const { getRuntimeEnvironments } = require('@abtnode/core/lib/util/blocklet');
|
|
5
5
|
const { emailConfigSchema } = require('@blocklet/sdk/lib/validators/email');
|
|
6
|
+
const logger = require('@abtnode/logger')('blocklet-services:notification');
|
|
7
|
+
const omit = require('lodash/omit');
|
|
6
8
|
|
|
7
9
|
const { NotificationEmail } = require('../emails/pages/notification');
|
|
8
10
|
const cache = require('../cache');
|
|
@@ -20,16 +22,18 @@ async function sendEmail(receiver, notification, { teamDid, node }) {
|
|
|
20
22
|
throw new Error('notification is required');
|
|
21
23
|
}
|
|
22
24
|
|
|
23
|
-
const blocklet = await node.getBlocklet({ did: teamDid,
|
|
24
|
-
|
|
25
|
+
const blocklet = await node.getBlocklet({ did: teamDid, useCache: true });
|
|
26
|
+
if (!blocklet) {
|
|
27
|
+
logger.warn(`Failed to get blocklet: ${teamDid}`);
|
|
28
|
+
}
|
|
29
|
+
const config = blocklet?.settings?.notification?.email || {};
|
|
25
30
|
|
|
26
31
|
if (!config.enabled) {
|
|
27
32
|
// skip send email
|
|
28
33
|
return;
|
|
29
34
|
}
|
|
30
|
-
delete config.enabled;
|
|
31
35
|
|
|
32
|
-
const { error, value: emailConfig } = emailConfigSchema.validate(config);
|
|
36
|
+
const { error, value: emailConfig } = emailConfigSchema.validate(omit(config, 'enabled'));
|
|
33
37
|
if (error) {
|
|
34
38
|
throw new Error(error.message);
|
|
35
39
|
}
|
|
@@ -50,12 +54,21 @@ async function sendEmail(receiver, notification, { teamDid, node }) {
|
|
|
50
54
|
url,
|
|
51
55
|
};
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
// TODO: @zhanghan notification 目前并没有 locale 信息,无法实现多 locale 提示
|
|
58
|
+
const subject = `[${appInfo.title}] ${notification.title || 'You have received a notification'}`;
|
|
59
|
+
|
|
60
|
+
const html = render(
|
|
61
|
+
NotificationEmail({
|
|
62
|
+
subject,
|
|
63
|
+
...notification,
|
|
64
|
+
appInfo,
|
|
65
|
+
})
|
|
66
|
+
);
|
|
54
67
|
const emailData = {
|
|
55
68
|
from: emailConfig.from,
|
|
56
69
|
to: receiver,
|
|
57
70
|
title: notification.title,
|
|
58
|
-
subject
|
|
71
|
+
subject,
|
|
59
72
|
html,
|
|
60
73
|
};
|
|
61
74
|
const transporter = cache.getTransport({ did: teamDid, config: emailConfig });
|
|
@@ -22,7 +22,12 @@ module.exports = {
|
|
|
22
22
|
return res.status(400).json({ error: 'Blocklet Studio can only be used for blocklets in development mode' });
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const component = blocklet.children.find((c) => c.meta.name === blocklet.meta.name);
|
|
26
|
+
if (!component || !component.deployedFrom) {
|
|
27
|
+
return res.status(400).json({ error: 'Can not find current component' });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const schemaFile = path.join(component.deployedFrom, BLOCKLET_PREFERENCE_FILE);
|
|
26
31
|
if (fs.existsSync(schemaFile)) {
|
|
27
32
|
try {
|
|
28
33
|
const schema = JSON.parse(fs.readFileSync(schemaFile, 'utf8'));
|
|
@@ -41,7 +46,12 @@ module.exports = {
|
|
|
41
46
|
return res.status(400).json({ error: 'Blocklet Studio can only be used for blocklets in development mode' });
|
|
42
47
|
}
|
|
43
48
|
|
|
44
|
-
const
|
|
49
|
+
const component = blocklet.children.find((c) => c.meta.name === blocklet.meta.name);
|
|
50
|
+
if (!component || !component.deployedFrom) {
|
|
51
|
+
return res.status(400).json({ error: 'Can not find current component' });
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const schemaFile = path.join(component.deployedFrom, BLOCKLET_PREFERENCE_FILE);
|
|
45
55
|
fs.writeFileSync(schemaFile, JSON.stringify(req.body, null, 2));
|
|
46
56
|
return res.json(req.body);
|
|
47
57
|
});
|
|
@@ -2,6 +2,7 @@ const {
|
|
|
2
2
|
validateReceiver,
|
|
3
3
|
validateNotification,
|
|
4
4
|
validateMessage,
|
|
5
|
+
NOTIFICATION_TYPES,
|
|
5
6
|
} = require('@blocklet/sdk/lib/validators/notification');
|
|
6
7
|
const { NODE_MODES } = require('@abtnode/constant');
|
|
7
8
|
const { getWalletDid } = require('@blocklet/sdk/lib/did');
|
|
@@ -90,10 +91,13 @@ const sendToDid = async ({ sender, receiver: rawDid, notification, options, node
|
|
|
90
91
|
}
|
|
91
92
|
});
|
|
92
93
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
// NOTICE: 目前只有 notification 的通知能够发送邮件,并且 type 可能为 undefined
|
|
95
|
+
if ([undefined, NOTIFICATION_TYPES.NOTIFICATION].includes(data.type)) {
|
|
96
|
+
for (const receiverEmail of receiverEmailList) {
|
|
97
|
+
sendEmail(receiverEmail, data, { teamDid: sender.appDid, node }).catch((error) => {
|
|
98
|
+
logger.error('Failed to send email', { error });
|
|
99
|
+
});
|
|
100
|
+
}
|
|
97
101
|
}
|
|
98
102
|
});
|
|
99
103
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.8-beta-
|
|
6
|
+
"version": "1.16.8-beta-186fd5aa",
|
|
7
7
|
"description": "Provide unified services for every blocklet",
|
|
8
8
|
"main": "api/index.js",
|
|
9
9
|
"files": [
|
|
@@ -33,16 +33,16 @@
|
|
|
33
33
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@abtnode/auth": "1.16.8-beta-
|
|
37
|
-
"@abtnode/client": "1.16.8-beta-
|
|
38
|
-
"@abtnode/constant": "1.16.8-beta-
|
|
39
|
-
"@abtnode/core": "1.16.8-beta-
|
|
40
|
-
"@abtnode/cron": "1.16.8-beta-
|
|
41
|
-
"@abtnode/db": "1.16.8-beta-
|
|
42
|
-
"@abtnode/logger": "1.16.8-beta-
|
|
43
|
-
"@abtnode/router-adapter": "1.16.8-beta-
|
|
44
|
-
"@abtnode/router-templates": "1.16.8-beta-
|
|
45
|
-
"@abtnode/util": "1.16.8-beta-
|
|
36
|
+
"@abtnode/auth": "1.16.8-beta-186fd5aa",
|
|
37
|
+
"@abtnode/client": "1.16.8-beta-186fd5aa",
|
|
38
|
+
"@abtnode/constant": "1.16.8-beta-186fd5aa",
|
|
39
|
+
"@abtnode/core": "1.16.8-beta-186fd5aa",
|
|
40
|
+
"@abtnode/cron": "1.16.8-beta-186fd5aa",
|
|
41
|
+
"@abtnode/db": "1.16.8-beta-186fd5aa",
|
|
42
|
+
"@abtnode/logger": "1.16.8-beta-186fd5aa",
|
|
43
|
+
"@abtnode/router-adapter": "1.16.8-beta-186fd5aa",
|
|
44
|
+
"@abtnode/router-templates": "1.16.8-beta-186fd5aa",
|
|
45
|
+
"@abtnode/util": "1.16.8-beta-186fd5aa",
|
|
46
46
|
"@arcblock/did": "^1.18.78",
|
|
47
47
|
"@arcblock/did-auth": "1.18.78",
|
|
48
48
|
"@arcblock/did-auth-storage-nedb": "^1.7.1",
|
|
@@ -51,11 +51,11 @@
|
|
|
51
51
|
"@arcblock/jwt": "1.18.78",
|
|
52
52
|
"@arcblock/validator": "^1.18.78",
|
|
53
53
|
"@arcblock/ws": "1.18.78",
|
|
54
|
-
"@blocklet/constant": "1.16.8-beta-
|
|
54
|
+
"@blocklet/constant": "1.16.8-beta-186fd5aa",
|
|
55
55
|
"@blocklet/form-builder": "^0.1.11",
|
|
56
56
|
"@blocklet/form-collector": "^0.1.6",
|
|
57
|
-
"@blocklet/meta": "1.16.8-beta-
|
|
58
|
-
"@blocklet/sdk": "1.16.8-beta-
|
|
57
|
+
"@blocklet/meta": "1.16.8-beta-186fd5aa",
|
|
58
|
+
"@blocklet/sdk": "1.16.8-beta-186fd5aa",
|
|
59
59
|
"@did-connect/authenticator": "^2.1.54",
|
|
60
60
|
"@did-connect/relay-adapter-express": "^2.1.54",
|
|
61
61
|
"@did-connect/storage-nedb": "^2.1.54",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"@nedb/multi": "^2.0.5"
|
|
97
97
|
},
|
|
98
98
|
"devDependencies": {
|
|
99
|
-
"@abtnode/ux": "1.16.8-beta-
|
|
99
|
+
"@abtnode/ux": "1.16.8-beta-186fd5aa",
|
|
100
100
|
"@arcblock/did-connect": "^2.5.39",
|
|
101
101
|
"@arcblock/icons": "^2.5.39",
|
|
102
102
|
"@arcblock/ux": "^2.5.39",
|
|
@@ -163,5 +163,5 @@
|
|
|
163
163
|
"url": "https://github.com/ArcBlock/blocklet-server/issues",
|
|
164
164
|
"email": "shijun@arcblock.io"
|
|
165
165
|
},
|
|
166
|
-
"gitHead": "
|
|
166
|
+
"gitHead": "3150c3a5c3e041fe7f5a3902418d9d62adee3173"
|
|
167
167
|
}
|