@abtnode/blocklet-services 1.16.19-beta-beb58af7 → 1.16.19-beta-626e4d43
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/index.js +1 -0
- package/api/middlewares/check-running.js +4 -2
- package/api/services/auth/index.js +20 -26
- package/api/services/auth/session.js +2 -3
- package/api/util/attach-shared-utils.js +32 -0
- package/build/asset-manifest.json +19 -19
- package/build/index.html +1 -1
- package/build/service-worker.js +1 -1
- package/build/static/js/{1946.383ddc49.chunk.js → 1946.b8762af5.chunk.js} +2 -2
- package/build/static/js/{3131.477fef7e.chunk.js → 3131.b2bb8f6c.chunk.js} +2 -2
- package/build/static/js/3842.780dc9e9.chunk.js +3 -0
- package/build/static/js/5785.38eedf8e.chunk.js +2 -0
- package/build/static/js/8283.20452732.chunk.js +2 -0
- package/build/static/js/8944.f4f91564.chunk.js +2 -0
- package/build/static/js/8983.020df395.chunk.js +2 -0
- package/build/static/js/9900.26718c8f.chunk.js +2 -0
- package/build/static/js/main.6fc39419.js +3 -0
- package/package.json +18 -18
- package/build/static/js/3842.9917fe86.chunk.js +0 -3
- package/build/static/js/5785.5636e84e.chunk.js +0 -2
- package/build/static/js/8283.f3a42d0f.chunk.js +0 -2
- package/build/static/js/8944.d4773634.chunk.js +0 -2
- package/build/static/js/8983.f509aca0.chunk.js +0 -2
- package/build/static/js/9900.2dea9cda.chunk.js +0 -2
- package/build/static/js/main.41cd395e.js +0 -3
- /package/build/static/js/{3842.9917fe86.chunk.js.LICENSE.txt → 3842.780dc9e9.chunk.js.LICENSE.txt} +0 -0
- /package/build/static/js/{main.41cd395e.js.LICENSE.txt → main.6fc39419.js.LICENSE.txt} +0 -0
package/api/index.js
CHANGED
|
@@ -268,6 +268,7 @@ module.exports = function createServer(node, serverOptions = {}) {
|
|
|
268
268
|
createConnectRelayRoutes.init(server, node, options, wsRouter);
|
|
269
269
|
authRoutes.attachDidAuthHandlers(server);
|
|
270
270
|
authRoutes.createPassportRoutes.init(server, node);
|
|
271
|
+
authRoutes.createCommonRoutes.init(server, node);
|
|
271
272
|
|
|
272
273
|
// API: gql
|
|
273
274
|
[
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { BlockletStatus } = require('@blocklet/constant');
|
|
2
2
|
const getBlockletMaintenanceTemplate = require('@abtnode/router-templates/lib/blocklet-maintenance');
|
|
3
3
|
const { findComponentByIdV2 } = require('@blocklet/meta/lib/util');
|
|
4
|
+
const logger = require('@abtnode/logger')(require('../../package.json').name);
|
|
4
5
|
|
|
5
6
|
const { shouldGotoStartPage, getRedirectUrl } = require('../util');
|
|
6
7
|
|
|
@@ -21,9 +22,10 @@ const checkRunning = async (req, res, next) => {
|
|
|
21
22
|
].includes(component.status)
|
|
22
23
|
) {
|
|
23
24
|
if (shouldGotoStartPage(req, component)) {
|
|
24
|
-
// FIXME: @wangshijun how to validate this token or generate token here?
|
|
25
25
|
if (req.query.setupToken) {
|
|
26
|
-
|
|
26
|
+
await req.attachSetupToken({ res, token: req.query.setupToken }).catch((error) => {
|
|
27
|
+
logger.error('attach login token failed when redirecting to starting page', { error }); // 不阻跳转
|
|
28
|
+
});
|
|
27
29
|
}
|
|
28
30
|
if (app.settings.initialized) {
|
|
29
31
|
res.redirect(getRedirectUrl({ req, pagePath: '/start' }));
|
|
@@ -14,6 +14,7 @@ const {
|
|
|
14
14
|
const { BLOCKLET_MODES } = require('@blocklet/constant');
|
|
15
15
|
const { setUserInfoHeaders } = require('@abtnode/auth/lib/auth');
|
|
16
16
|
const { getRolesFromAuthConfig } = require('@blocklet/meta/lib/util');
|
|
17
|
+
const logger = require('@abtnode/logger')(require('../../../package.json').name);
|
|
17
18
|
|
|
18
19
|
const initJwt = require('../../libs/jwt');
|
|
19
20
|
const initAuth = require('../../libs/connect/v1');
|
|
@@ -38,7 +39,7 @@ const createReceiveTransferAppOwnerRoutes = require('./connect/receive-transfer-
|
|
|
38
39
|
const createSessionRoutes = require('./session');
|
|
39
40
|
const createPassportRoutes = require('./passport');
|
|
40
41
|
const { getRedirectUrl, shouldIgnoreUrl } = require('../../util');
|
|
41
|
-
const {
|
|
42
|
+
const { PREFIXES } = require('../../util/constants');
|
|
42
43
|
|
|
43
44
|
const getTokenFromWsConnect = (req, options) => {
|
|
44
45
|
const cookies = cookie.parse(req.headers.cookie || '');
|
|
@@ -62,27 +63,6 @@ const REASON_404 = 'Not Found';
|
|
|
62
63
|
const init = ({ node, options }) => {
|
|
63
64
|
const { createSessionToken, verifySessionToken } = initJwt(node, options);
|
|
64
65
|
|
|
65
|
-
/**
|
|
66
|
-
* set user info to req.user
|
|
67
|
-
*/
|
|
68
|
-
const ensureUser = async ({ req, token } = {}) => {
|
|
69
|
-
try {
|
|
70
|
-
if (token) {
|
|
71
|
-
const teamDid = req.getBlockletDid();
|
|
72
|
-
const { secret } = await req.getBlockletInfo();
|
|
73
|
-
const opt = {
|
|
74
|
-
checkFromDb: (decoded) => sessionCacheDisabledUser.get(decoded?.did),
|
|
75
|
-
teamDid,
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const user = await verifySessionToken(token, secret, opt);
|
|
79
|
-
req.user = user;
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
// Do nothing
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
66
|
/**
|
|
87
67
|
* @typedef {object} CheckAuthRes
|
|
88
68
|
* @property {boolean} blocked
|
|
@@ -227,7 +207,7 @@ const init = ({ node, options }) => {
|
|
|
227
207
|
// set user info to req.user and req.headers
|
|
228
208
|
middlewares.userInfo = async (req, res, next) => {
|
|
229
209
|
const { token } = req;
|
|
230
|
-
await ensureUser({
|
|
210
|
+
await req.ensureUser({ token });
|
|
231
211
|
|
|
232
212
|
setUserInfoHeaders(req);
|
|
233
213
|
|
|
@@ -265,11 +245,25 @@ const init = ({ node, options }) => {
|
|
|
265
245
|
createSessionRoutes.init(router, node, createSessionToken, {
|
|
266
246
|
...options,
|
|
267
247
|
middlewares,
|
|
268
|
-
ensureUser,
|
|
269
248
|
createSessionToken,
|
|
270
249
|
verifySessionToken,
|
|
271
250
|
}),
|
|
272
251
|
};
|
|
252
|
+
routes.createCommonRoutes = {
|
|
253
|
+
init: (router) => {
|
|
254
|
+
PREFIXES.forEach((prefix) => {
|
|
255
|
+
router.get(`${prefix}/redirect-with-login`, async (req, res) => {
|
|
256
|
+
if (req.query.setupToken) {
|
|
257
|
+
await req.attachSetupToken({ res, token: req.query.setupToken }).catch((error) => {
|
|
258
|
+
logger.error('attach login token failed when redirecting with login', { error }); // 不阻塞跳转
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
res.redirect('/');
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
};
|
|
273
267
|
|
|
274
268
|
const ensureWsUser = async (req) => {
|
|
275
269
|
const token = getTokenFromWsConnect(req, options);
|
|
@@ -279,7 +273,7 @@ const init = ({ node, options }) => {
|
|
|
279
273
|
return;
|
|
280
274
|
}
|
|
281
275
|
|
|
282
|
-
await ensureUser({
|
|
276
|
+
await req.ensureUser({ token });
|
|
283
277
|
};
|
|
284
278
|
|
|
285
279
|
// auth middleware for websocket connect
|
|
@@ -292,7 +286,7 @@ const init = ({ node, options }) => {
|
|
|
292
286
|
return;
|
|
293
287
|
}
|
|
294
288
|
|
|
295
|
-
await ensureUser({
|
|
289
|
+
await req.ensureUser({ token });
|
|
296
290
|
|
|
297
291
|
setUserInfoHeaders(req);
|
|
298
292
|
|
|
@@ -20,14 +20,13 @@ module.exports = {
|
|
|
20
20
|
const {
|
|
21
21
|
verifySessionToken,
|
|
22
22
|
middlewares: { sessionBearerToken, refreshBearerToken },
|
|
23
|
-
ensureUser,
|
|
24
23
|
} = options;
|
|
25
24
|
const createToken = createTokenFn(createSessionToken);
|
|
26
25
|
|
|
27
26
|
PREFIXES.forEach((prefix) => {
|
|
28
27
|
const handleSession = async (req, res) => {
|
|
29
28
|
const { token } = req;
|
|
30
|
-
await ensureUser({
|
|
29
|
+
await req.ensureUser({ token });
|
|
31
30
|
|
|
32
31
|
if (!req.user) {
|
|
33
32
|
res.json({ user: null });
|
|
@@ -74,7 +73,7 @@ module.exports = {
|
|
|
74
73
|
const extraApi = `${prefix}/api/user/extra`;
|
|
75
74
|
const checkUser = async (req, res, next) => {
|
|
76
75
|
const { token } = req;
|
|
77
|
-
await ensureUser({
|
|
76
|
+
await req.ensureUser({ token });
|
|
78
77
|
if (!req.user) {
|
|
79
78
|
res.status(403).json(null);
|
|
80
79
|
} else {
|
|
@@ -8,6 +8,7 @@ const cache = require('../cache');
|
|
|
8
8
|
const formatContext = require('./format-context');
|
|
9
9
|
const getDynamicServiceConfig = require('./get-dynamic-service-config');
|
|
10
10
|
const getStaticServiceConfig = require('./get-static-service-config');
|
|
11
|
+
const initJwt = require('../libs/jwt');
|
|
11
12
|
|
|
12
13
|
module.exports = ({ node, req, options }) => {
|
|
13
14
|
req.getBlockletDid = () => req.headers['x-blocklet-did'] || get(options, 'blockletDid', '');
|
|
@@ -98,6 +99,37 @@ module.exports = ({ node, req, options }) => {
|
|
|
98
99
|
return cache.getBlockletInfo({ did, node });
|
|
99
100
|
};
|
|
100
101
|
|
|
102
|
+
const { verifySessionToken } = initJwt(node, options);
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* set user info to req.user
|
|
106
|
+
*/
|
|
107
|
+
req.ensureUser = async ({ token } = {}) => {
|
|
108
|
+
try {
|
|
109
|
+
if (token) {
|
|
110
|
+
const teamDid = req.getBlockletDid();
|
|
111
|
+
const { secret } = await req.getBlockletInfo();
|
|
112
|
+
const opt = {
|
|
113
|
+
checkFromDb: (decoded) => cache.sessionCacheDisabledUser.get(decoded?.did),
|
|
114
|
+
teamDid,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const user = await verifySessionToken(token, secret, opt);
|
|
118
|
+
req.user = user;
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// Do nothing
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
req.attachSetupToken = async ({ res, token }) => {
|
|
126
|
+
await req.ensureUser({ token });
|
|
127
|
+
|
|
128
|
+
if (req.user) {
|
|
129
|
+
res.cookie('login_token', token, { maxAge: 24 * 60 * 60 * 1000 });
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
101
133
|
req.cache = cache;
|
|
102
134
|
};
|
|
103
135
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": {
|
|
3
3
|
"main.css": "/.well-known/service/static/static/css/main.7ea79dc8.css",
|
|
4
|
-
"main.js": "/.well-known/service/static/static/js/main.
|
|
4
|
+
"main.js": "/.well-known/service/static/static/js/main.6fc39419.js",
|
|
5
5
|
"static/js/6218.4f3036a7.chunk.js": "/.well-known/service/static/static/js/6218.4f3036a7.chunk.js",
|
|
6
6
|
"static/js/4076.8055ce74.chunk.js": "/.well-known/service/static/static/js/4076.8055ce74.chunk.js",
|
|
7
7
|
"static/js/6658.98f9956d.chunk.js": "/.well-known/service/static/static/js/6658.98f9956d.chunk.js",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"static/js/779.cbad02fa.chunk.js": "/.well-known/service/static/static/js/779.cbad02fa.chunk.js",
|
|
12
12
|
"static/js/8622.03f917b3.chunk.js": "/.well-known/service/static/static/js/8622.03f917b3.chunk.js",
|
|
13
13
|
"static/js/1148.d3c53aea.chunk.js": "/.well-known/service/static/static/js/1148.d3c53aea.chunk.js",
|
|
14
|
-
"static/js/8944.
|
|
14
|
+
"static/js/8944.f4f91564.chunk.js": "/.well-known/service/static/static/js/8944.f4f91564.chunk.js",
|
|
15
15
|
"static/js/5468.21a861b9.chunk.js": "/.well-known/service/static/static/js/5468.21a861b9.chunk.js",
|
|
16
16
|
"static/js/9982.4f1ebb7f.chunk.js": "/.well-known/service/static/static/js/9982.4f1ebb7f.chunk.js",
|
|
17
17
|
"static/js/1359.add26d23.chunk.js": "/.well-known/service/static/static/js/1359.add26d23.chunk.js",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"static/js/4882.0435e418.chunk.js": "/.well-known/service/static/static/js/4882.0435e418.chunk.js",
|
|
22
22
|
"static/js/5434.523d071d.chunk.js": "/.well-known/service/static/static/js/5434.523d071d.chunk.js",
|
|
23
23
|
"static/js/3033.f950a32b.chunk.js": "/.well-known/service/static/static/js/3033.f950a32b.chunk.js",
|
|
24
|
-
"static/js/3842.
|
|
25
|
-
"static/js/3131.
|
|
26
|
-
"static/js/5785.
|
|
27
|
-
"static/js/8983.
|
|
28
|
-
"static/js/9900.
|
|
29
|
-
"static/js/8283.
|
|
24
|
+
"static/js/3842.780dc9e9.chunk.js": "/.well-known/service/static/static/js/3842.780dc9e9.chunk.js",
|
|
25
|
+
"static/js/3131.b2bb8f6c.chunk.js": "/.well-known/service/static/static/js/3131.b2bb8f6c.chunk.js",
|
|
26
|
+
"static/js/5785.38eedf8e.chunk.js": "/.well-known/service/static/static/js/5785.38eedf8e.chunk.js",
|
|
27
|
+
"static/js/8983.020df395.chunk.js": "/.well-known/service/static/static/js/8983.020df395.chunk.js",
|
|
28
|
+
"static/js/9900.26718c8f.chunk.js": "/.well-known/service/static/static/js/9900.26718c8f.chunk.js",
|
|
29
|
+
"static/js/8283.20452732.chunk.js": "/.well-known/service/static/static/js/8283.20452732.chunk.js",
|
|
30
30
|
"static/js/6326.2816fb2f.chunk.js": "/.well-known/service/static/static/js/6326.2816fb2f.chunk.js",
|
|
31
31
|
"static/js/2653.980158ea.chunk.js": "/.well-known/service/static/static/js/2653.980158ea.chunk.js",
|
|
32
32
|
"static/js/3593.b9a1a7f5.chunk.js": "/.well-known/service/static/static/js/3593.b9a1a7f5.chunk.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"static/js/356.df75c406.chunk.js": "/.well-known/service/static/static/js/356.df75c406.chunk.js",
|
|
39
39
|
"static/js/4023.8c5c7db4.chunk.js": "/.well-known/service/static/static/js/4023.8c5c7db4.chunk.js",
|
|
40
40
|
"static/js/8792.13a6919f.chunk.js": "/.well-known/service/static/static/js/8792.13a6919f.chunk.js",
|
|
41
|
-
"static/js/1946.
|
|
41
|
+
"static/js/1946.b8762af5.chunk.js": "/.well-known/service/static/static/js/1946.b8762af5.chunk.js",
|
|
42
42
|
"static/js/5569.e4bfe697.chunk.js": "/.well-known/service/static/static/js/5569.e4bfe697.chunk.js",
|
|
43
43
|
"static/css/5547.75913953.chunk.css": "/.well-known/service/static/static/css/5547.75913953.chunk.css",
|
|
44
44
|
"static/js/5547.1bea60f5.chunk.js": "/.well-known/service/static/static/js/5547.1bea60f5.chunk.js",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"index.html": "/.well-known/service/static/index.html",
|
|
122
122
|
"static/media/space-connected.svg": "/.well-known/service/static/static/media/space-connected.9a4e18fd2bc7d065191b0d241a131c28.svg",
|
|
123
123
|
"main.7ea79dc8.css.map": "/.well-known/service/static/static/css/main.7ea79dc8.css.map",
|
|
124
|
-
"main.
|
|
124
|
+
"main.6fc39419.js.map": "/.well-known/service/static/static/js/main.6fc39419.js.map",
|
|
125
125
|
"6218.4f3036a7.chunk.js.map": "/.well-known/service/static/static/js/6218.4f3036a7.chunk.js.map",
|
|
126
126
|
"4076.8055ce74.chunk.js.map": "/.well-known/service/static/static/js/4076.8055ce74.chunk.js.map",
|
|
127
127
|
"6658.98f9956d.chunk.js.map": "/.well-known/service/static/static/js/6658.98f9956d.chunk.js.map",
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
"779.cbad02fa.chunk.js.map": "/.well-known/service/static/static/js/779.cbad02fa.chunk.js.map",
|
|
132
132
|
"8622.03f917b3.chunk.js.map": "/.well-known/service/static/static/js/8622.03f917b3.chunk.js.map",
|
|
133
133
|
"1148.d3c53aea.chunk.js.map": "/.well-known/service/static/static/js/1148.d3c53aea.chunk.js.map",
|
|
134
|
-
"8944.
|
|
134
|
+
"8944.f4f91564.chunk.js.map": "/.well-known/service/static/static/js/8944.f4f91564.chunk.js.map",
|
|
135
135
|
"5468.21a861b9.chunk.js.map": "/.well-known/service/static/static/js/5468.21a861b9.chunk.js.map",
|
|
136
136
|
"9982.4f1ebb7f.chunk.js.map": "/.well-known/service/static/static/js/9982.4f1ebb7f.chunk.js.map",
|
|
137
137
|
"1359.add26d23.chunk.js.map": "/.well-known/service/static/static/js/1359.add26d23.chunk.js.map",
|
|
@@ -141,12 +141,12 @@
|
|
|
141
141
|
"4882.0435e418.chunk.js.map": "/.well-known/service/static/static/js/4882.0435e418.chunk.js.map",
|
|
142
142
|
"5434.523d071d.chunk.js.map": "/.well-known/service/static/static/js/5434.523d071d.chunk.js.map",
|
|
143
143
|
"3033.f950a32b.chunk.js.map": "/.well-known/service/static/static/js/3033.f950a32b.chunk.js.map",
|
|
144
|
-
"3842.
|
|
145
|
-
"3131.
|
|
146
|
-
"5785.
|
|
147
|
-
"8983.
|
|
148
|
-
"9900.
|
|
149
|
-
"8283.
|
|
144
|
+
"3842.780dc9e9.chunk.js.map": "/.well-known/service/static/static/js/3842.780dc9e9.chunk.js.map",
|
|
145
|
+
"3131.b2bb8f6c.chunk.js.map": "/.well-known/service/static/static/js/3131.b2bb8f6c.chunk.js.map",
|
|
146
|
+
"5785.38eedf8e.chunk.js.map": "/.well-known/service/static/static/js/5785.38eedf8e.chunk.js.map",
|
|
147
|
+
"8983.020df395.chunk.js.map": "/.well-known/service/static/static/js/8983.020df395.chunk.js.map",
|
|
148
|
+
"9900.26718c8f.chunk.js.map": "/.well-known/service/static/static/js/9900.26718c8f.chunk.js.map",
|
|
149
|
+
"8283.20452732.chunk.js.map": "/.well-known/service/static/static/js/8283.20452732.chunk.js.map",
|
|
150
150
|
"6326.2816fb2f.chunk.js.map": "/.well-known/service/static/static/js/6326.2816fb2f.chunk.js.map",
|
|
151
151
|
"2653.980158ea.chunk.js.map": "/.well-known/service/static/static/js/2653.980158ea.chunk.js.map",
|
|
152
152
|
"3593.b9a1a7f5.chunk.js.map": "/.well-known/service/static/static/js/3593.b9a1a7f5.chunk.js.map",
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
"356.df75c406.chunk.js.map": "/.well-known/service/static/static/js/356.df75c406.chunk.js.map",
|
|
159
159
|
"4023.8c5c7db4.chunk.js.map": "/.well-known/service/static/static/js/4023.8c5c7db4.chunk.js.map",
|
|
160
160
|
"8792.13a6919f.chunk.js.map": "/.well-known/service/static/static/js/8792.13a6919f.chunk.js.map",
|
|
161
|
-
"1946.
|
|
161
|
+
"1946.b8762af5.chunk.js.map": "/.well-known/service/static/static/js/1946.b8762af5.chunk.js.map",
|
|
162
162
|
"5569.e4bfe697.chunk.js.map": "/.well-known/service/static/static/js/5569.e4bfe697.chunk.js.map",
|
|
163
163
|
"5547.75913953.chunk.css.map": "/.well-known/service/static/static/css/5547.75913953.chunk.css.map",
|
|
164
164
|
"5547.1bea60f5.chunk.js.map": "/.well-known/service/static/static/js/5547.1bea60f5.chunk.js.map",
|
|
@@ -220,6 +220,6 @@
|
|
|
220
220
|
},
|
|
221
221
|
"entrypoints": [
|
|
222
222
|
"static/css/main.7ea79dc8.css",
|
|
223
|
-
"static/js/main.
|
|
223
|
+
"static/js/main.6fc39419.js"
|
|
224
224
|
]
|
|
225
225
|
}
|
package/build/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico?imageFilter=resize&w=32"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#000000"/><title>Blocklet Service</title><link rel="manifest" href="/.well-known/service/manifest.json"/><script src="/.well-known/service/api/env"></script><script src="/__blocklet__.js"></script><style>body{margin:0;padding:0}</style><script defer="defer" src="/.well-known/service/static/static/js/main.
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico?imageFilter=resize&w=32"/><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"/><meta name="theme-color" content="#000000"/><title>Blocklet Service</title><link rel="manifest" href="/.well-known/service/manifest.json"/><script src="/.well-known/service/api/env"></script><script src="/__blocklet__.js"></script><style>body{margin:0;padding:0}</style><script defer="defer" src="/.well-known/service/static/static/js/main.6fc39419.js"></script><link href="/.well-known/service/static/static/css/main.7ea79dc8.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
|