@abtnode/ux 1.16.14-beta-ab7f615e → 1.16.14-beta-cb53c14b

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.
Files changed (202) hide show
  1. package/es/actions.js +97 -0
  2. package/es/analytics/card.js +92 -0
  3. package/es/analytics/chart.js +96 -0
  4. package/es/analytics/cpu.js +36 -0
  5. package/es/analytics/disk.js +111 -0
  6. package/es/analytics/memory.js +72 -0
  7. package/es/analytics/runtime.js +173 -0
  8. package/es/analytics/traffic.js +259 -0
  9. package/es/blocklet/access/config-access.js +307 -0
  10. package/es/blocklet/access/index.js +216 -0
  11. package/es/blocklet/actions.js +474 -0
  12. package/es/blocklet/add-cert.js +177 -0
  13. package/es/blocklet/agreement-app.js +21 -0
  14. package/es/blocklet/agreement.js +127 -0
  15. package/es/blocklet/app-avatar.js +57 -0
  16. package/es/blocklet/audit-logs.js +259 -0
  17. package/es/blocklet/blocklet-source.js +48 -0
  18. package/es/blocklet/bundle-avatar.js +64 -0
  19. package/es/blocklet/component/add.js +1308 -0
  20. package/es/blocklet/component/configuration.js +122 -0
  21. package/es/blocklet/component/delete.js +134 -0
  22. package/es/blocklet/component/environment.js +370 -0
  23. package/es/blocklet/component/index.js +975 -0
  24. package/es/blocklet/component/line.js +20 -0
  25. package/es/blocklet/component/navigation/locale-tabs.js +225 -0
  26. package/es/blocklet/component/navigation/navigation-actions.js +112 -0
  27. package/es/blocklet/component/navigation/navigation-dialog.js +607 -0
  28. package/es/blocklet/component/navigation/navigation-preview.js +101 -0
  29. package/es/blocklet/component/navigation/simple-select.js +124 -0
  30. package/es/blocklet/component/select-store.js +155 -0
  31. package/es/blocklet/component/setting.js +109 -0
  32. package/es/blocklet/component/sortable-tree.js +126 -0
  33. package/es/blocklet/component/space-connector.js +199 -0
  34. package/es/blocklet/component/space-selector.js +178 -0
  35. package/es/blocklet/component/start.js +101 -0
  36. package/es/blocklet/component/store-blocklet-list.js +200 -0
  37. package/es/blocklet/component/switch-control.js +57 -0
  38. package/es/blocklet/config-navigation.js +331 -0
  39. package/es/blocklet/configuration.js +603 -0
  40. package/es/blocklet/disk-info.js +75 -0
  41. package/es/blocklet/icons.js +18 -0
  42. package/es/blocklet/install-from-url.js +337 -0
  43. package/es/blocklet/log.js +90 -0
  44. package/es/blocklet/migration.js +149 -0
  45. package/es/blocklet/mode.js +19 -0
  46. package/es/blocklet/notification/email.js +257 -0
  47. package/es/blocklet/notification/index.js +49 -0
  48. package/es/blocklet/oauth/auth0.js +145 -0
  49. package/es/blocklet/oauth/common-settings.js +133 -0
  50. package/es/blocklet/oauth/federated-detail-dialog.js +175 -0
  51. package/es/blocklet/oauth/federated-invite-dialog.js +83 -0
  52. package/es/blocklet/oauth/federated-join-dialog.js +111 -0
  53. package/es/blocklet/oauth/federated-site-list.js +338 -0
  54. package/es/blocklet/oauth/federated.js +81 -0
  55. package/es/blocklet/oauth/index.js +69 -0
  56. package/es/blocklet/overview.js +293 -0
  57. package/es/blocklet/page-group.js +19 -0
  58. package/es/blocklet/preferences/app-sk.js +142 -0
  59. package/es/blocklet/preferences/index.js +305 -0
  60. package/es/blocklet/purchase/common.js +95 -0
  61. package/es/blocklet/purchase/component-purchase.js +237 -0
  62. package/es/blocklet/purchase/index.js +4 -0
  63. package/es/blocklet/router/action/add-domain-alias.js +167 -0
  64. package/es/blocklet/router/action/add-rule.js +211 -0
  65. package/es/blocklet/router/action/config-routing-rule.js +232 -0
  66. package/es/blocklet/router/action/delete-domain-alias.js +99 -0
  67. package/es/blocklet/router/action/delete-rule.js +108 -0
  68. package/es/blocklet/router/action/update-rule.js +209 -0
  69. package/es/blocklet/router/domain-actions.js +64 -0
  70. package/es/blocklet/router/domain-status.js +88 -0
  71. package/es/blocklet/router/rule-actions.js +66 -0
  72. package/es/blocklet/router/rule-list.js +190 -0
  73. package/es/blocklet/router/util.js +131 -0
  74. package/es/blocklet/runtime-info.js +68 -0
  75. package/es/blocklet/status.js +91 -0
  76. package/es/blocklet/storage/action.js +134 -0
  77. package/es/blocklet/storage/backups.js +241 -0
  78. package/es/blocklet/storage/connect-to.js +373 -0
  79. package/es/blocklet/storage/connected.js +198 -0
  80. package/es/blocklet/storage/delete.js +113 -0
  81. package/es/blocklet/storage/disconnect.js +243 -0
  82. package/es/blocklet/storage/index.js +19 -0
  83. package/es/blocklet/storage/item.js +558 -0
  84. package/es/blocklet/storage/preview-nft.js +286 -0
  85. package/es/blocklet/transfer-owner.js +198 -0
  86. package/es/blocklet/types.js +18 -0
  87. package/es/blocklet/util.js +145 -0
  88. package/es/blocklet/version.js +141 -0
  89. package/es/card-selector.js +134 -0
  90. package/es/certificate.js +105 -0
  91. package/es/chain.js +13 -0
  92. package/es/click-to-copy.js +22 -0
  93. package/es/confirm.js +149 -0
  94. package/es/contexts/audit-log.js +152 -0
  95. package/es/contexts/blocklet.js +10 -0
  96. package/es/contexts/deleting-blocklets.js +70 -0
  97. package/es/contexts/node.js +17 -0
  98. package/es/contexts/session.js +8 -0
  99. package/es/contexts/team.js +10 -0
  100. package/es/delete-confirm.js +121 -0
  101. package/es/did-address.js +46 -0
  102. package/es/dot.js +14 -0
  103. package/es/exchange-passport.js +102 -0
  104. package/es/form/form-select-input.js +184 -0
  105. package/es/form/form-text-input.js +178 -0
  106. package/es/form/form-wrapper.js +88 -0
  107. package/es/form/input-triggers.js +98 -0
  108. package/es/form/required.js +8 -0
  109. package/es/hooks/blocklet.js +229 -0
  110. package/es/hooks/confirm.js +90 -0
  111. package/es/hooks/mobile-width.js +11 -0
  112. package/es/hooks/url-evaluation.js +155 -0
  113. package/es/hooks/use-app-logo.js +16 -0
  114. package/es/hooks/use-backup-progress.js +31 -0
  115. package/es/hooks/use-blocklet-info-for-connect-did-spaces.js +50 -0
  116. package/es/hooks/use-bundle-logo.js +27 -0
  117. package/es/hooks/use-navigation.js +347 -0
  118. package/es/hooks/use-passport-id.js +14 -0
  119. package/es/hooks/use-subscription.js +22 -0
  120. package/es/icons/empty-space-nft.svg +59 -0
  121. package/es/icons/empty-spaces-nft.svg +58 -0
  122. package/es/icons/long-arrow.svg +5 -0
  123. package/es/icons/space-connected.svg +3 -0
  124. package/es/icons/space-disconnect.svg +3 -0
  125. package/es/index.js +3 -0
  126. package/es/invitation/invitation-app.js +58 -0
  127. package/es/invitation/invitation-login.js +68 -0
  128. package/es/invitation/invitation-passport.js +144 -0
  129. package/es/invitation/invitation-receive.js +138 -0
  130. package/es/invitation/invitation-success.js +93 -0
  131. package/es/invitation/invitation-user.js +90 -0
  132. package/es/invitation/invitation.js +90 -0
  133. package/es/issue-passport.js +142 -0
  134. package/es/launch-blocklet/content-layout.js +58 -0
  135. package/es/launch-blocklet/page-header.js +43 -0
  136. package/es/layout/addon.js +114 -0
  137. package/es/layout/feedback.js +55 -0
  138. package/es/locales/en.js +1534 -0
  139. package/es/locales/index.js +9 -0
  140. package/es/locales/zh.js +1537 -0
  141. package/es/logs/clock.js +11 -0
  142. package/es/logs/download.js +132 -0
  143. package/es/logs/log-terminal.js +253 -0
  144. package/es/lost-passport.js +452 -0
  145. package/es/nav-logo.js +219 -0
  146. package/es/passport-tag.js +43 -0
  147. package/es/permission.js +57 -0
  148. package/es/relative-time.js +53 -0
  149. package/es/result-message.js +11 -0
  150. package/es/schema-form/color-input.js +98 -0
  151. package/es/schema-form/common-prop-types.js +13 -0
  152. package/es/schema-form/index.js +215 -0
  153. package/es/schema-form/passport-input.js +54 -0
  154. package/es/schema-form/text-input.js +57 -0
  155. package/es/store/add.js +179 -0
  156. package/es/store/delete.js +96 -0
  157. package/es/store/item.js +76 -0
  158. package/es/subscription.js +144 -0
  159. package/es/table-icons.js +34 -0
  160. package/es/table.js +52 -0
  161. package/es/tag.js +21 -0
  162. package/es/team/members/actions.js +89 -0
  163. package/es/team/members/index.js +636 -0
  164. package/es/team/members/invitations.js +188 -0
  165. package/es/team/members/invite-member.js +208 -0
  166. package/es/team/members/issue-passport.js +152 -0
  167. package/es/team/members/member.js +408 -0
  168. package/es/team/members/passport-issuances.js +155 -0
  169. package/es/team/members/passports.js +364 -0
  170. package/es/team/members/toggle-user-approval.js +122 -0
  171. package/es/team/members/transfer-node.js +256 -0
  172. package/es/team/members/util.js +14 -0
  173. package/es/team/passports/color.js +126 -0
  174. package/es/team/passports/detail.js +312 -0
  175. package/es/team/passports/index.js +282 -0
  176. package/es/team/passports/mutate-role.js +198 -0
  177. package/es/team/passports/trusted-factories.js +221 -0
  178. package/es/team/passports/trusted-factory.js +343 -0
  179. package/es/team/passports/trusted-issuer.js +296 -0
  180. package/es/team/passports/trusted-issuers.js +226 -0
  181. package/es/team/search-input.js +46 -0
  182. package/es/team/styles/dialog.js +72 -0
  183. package/es/team/styles/list-header.js +31 -0
  184. package/es/util/api.js +6 -0
  185. package/es/util/constants.js +2 -0
  186. package/es/util/index.js +598 -0
  187. package/es/util/mode.js +4 -0
  188. package/es/util/space-gateway.js +51 -0
  189. package/es/util/spaces.js +151 -0
  190. package/es/who-can-access/config.js +38 -0
  191. package/es/wrap-locale.js +15 -0
  192. package/lib/blocklet/component/space-connector.js +1 -1
  193. package/lib/blocklet/component/space-selector.js +1 -1
  194. package/lib/blocklet/storage/backups.js +1 -1
  195. package/lib/blocklet/storage/connect-to.js +1 -1
  196. package/lib/blocklet/storage/connected.js +1 -1
  197. package/lib/blocklet/storage/disconnect.js +1 -1
  198. package/lib/blocklet/storage/index.js +1 -1
  199. package/lib/blocklet/storage/item.js +1 -1
  200. package/lib/invitation/invitation-receive.js +1 -1
  201. package/lib/team/passports/trusted-factory.js +1 -1
  202. package/package.json +81 -18
@@ -0,0 +1,598 @@
1
+ /* eslint-disable max-len */
2
+ /* eslint-disable implicit-arrow-linebreak */
3
+ /* eslint-disable import/prefer-default-export */
4
+ import { DEFAULT_IP_DOMAIN_SUFFIX, DEFAULT_DID_DOMAIN, DOMAIN_FOR_IP_SITE, DOMAIN_FOR_IP_SITE_REGEXP, DOMAIN_FOR_DEFAULT_SITE, DOMAIN_FOR_INTERNAL_SITE, ROLES, WELLKNOWN_SERVICE_PATH_PREFIX, WELLKNOWN_PING_PREFIX, IP, SLOT_FOR_IP_DNS_SITE, WELLKNOWN_PATH_PREFIX, WEB_WALLET_URL, BLOCKLET_STORE_API_PREFIX } from '@abtnode/constant';
5
+ import qs from 'querystring';
6
+ import isUrl from 'is-url';
7
+ import humanizeUrl from 'humanize-url';
8
+ import filesize from 'filesize';
9
+ import joinUrl from 'url-join';
10
+ import get from 'lodash/get';
11
+ import last from 'lodash/last';
12
+ import trimEnd from 'lodash/trimEnd';
13
+ import { BLOCKLET_MODES } from '@blocklet/constant';
14
+ import { evaluateURLs, isDidDomain, isIpEcho, isSlpDomain } from '@abtnode/util/lib/url-evaluation';
15
+ import checkAccessible from '@abtnode/util/lib/url-evaluation/check-accessible-browser';
16
+ import axios from '@abtnode/util/lib/axios';
17
+ import normalizePathPrefix from '@abtnode/util/lib/normalize-path-prefix';
18
+ import urlPathFriendly from '@blocklet/meta/lib/url-path-friendly';
19
+ import formatError from '@abtnode/util/lib/format-error';
20
+ import dayjs from '@abtnode/util/lib/dayjs';
21
+ export { formatError };
22
+ export function sleep(t) {
23
+ // eslint-disable-next-line no-promise-executor-return
24
+ return new Promise(resolve => setTimeout(resolve, t));
25
+ }
26
+ export const validateDomain = (domain, locale = 'en') => {
27
+ if (!domain) {
28
+ return {
29
+ en: 'Site domain cannot be empty',
30
+ zh: '站点域名不能为空'
31
+ }[locale];
32
+ }
33
+ if (domain.endsWith(DEFAULT_IP_DOMAIN_SUFFIX)) {
34
+ return {
35
+ en: `Site domain cannot include ${DEFAULT_IP_DOMAIN_SUFFIX}`,
36
+ zh: `站点域名不能包含 ${DEFAULT_IP_DOMAIN_SUFFIX}`
37
+ }[locale];
38
+ }
39
+ return null;
40
+ };
41
+
42
+ /**
43
+ * get access url
44
+ * auto fix http/https, port, query
45
+ * docker friendly
46
+ */
47
+ export function getAccessUrl(hostname, path = '', params = undefined) {
48
+ if (!hostname) {
49
+ return '';
50
+ }
51
+ let protocol = 'http';
52
+ if (window.location.protocol === 'https:') {
53
+ if (isIpEcho(hostname) || isSlpDomain(hostname) || isDidDomain(hostname)) {
54
+ protocol = 'https';
55
+ }
56
+ }
57
+ let port = '';
58
+ const browserPort = Number(window.location.port);
59
+ if (process.env.NODE_ENV !== 'development' && browserPort && ![80, 443].includes(browserPort)) {
60
+ port = `:${browserPort}`;
61
+ }
62
+ const urlObj = new URL(`${protocol}://${hostname}${port}`);
63
+ urlObj.pathname = path;
64
+ const url = urlObj.href.replace(/\/$/, '');
65
+ if (!params || !Object.keys(params)) {
66
+ return url;
67
+ }
68
+ const searchParams = new URLSearchParams();
69
+ Object.keys(params).forEach(key => {
70
+ searchParams.append(key, params[key]);
71
+ });
72
+ return `${url}${urlObj.pathname === '/' ? '/' : ''}?${searchParams.toString()}`;
73
+ }
74
+ export function getBlockletUrl({
75
+ blocklet,
76
+ domain: inputDomain,
77
+ mountPoint: inputMountPoint,
78
+ params
79
+ } = {}) {
80
+ const {
81
+ site
82
+ } = blocklet;
83
+ if (!site) {
84
+ return null;
85
+ }
86
+ const domain = inputDomain || (site.domainAliases || [])[0];
87
+ if (!domain) {
88
+ return null;
89
+ }
90
+ let mountPoint = inputMountPoint;
91
+ if (!mountPoint) {
92
+ const rule = site.rules.filter(x => !x.from.pathPrefix.startsWith(WELLKNOWN_PATH_PREFIX))[0];
93
+ mountPoint = rule ? rule.from.pathPrefix : '/';
94
+ }
95
+ return getAccessUrl(domain.value, mountPoint, params);
96
+ }
97
+ export function getBlockletUrls({
98
+ blocklet,
99
+ mountPoint: inputMountPoint,
100
+ params
101
+ } = {}) {
102
+ const {
103
+ site
104
+ } = blocklet;
105
+ if (!site) {
106
+ return [];
107
+ }
108
+ const domains = site.domainAliases || [];
109
+ if (!domains.length) {
110
+ return [];
111
+ }
112
+ let mountPoint = inputMountPoint;
113
+ if (!mountPoint) {
114
+ const rules = site.rules.filter(x => !x.from.pathPrefix.startsWith(WELLKNOWN_PATH_PREFIX));
115
+ let rule = rules[0];
116
+ if (rule?.from?.pathPrefix !== '/') {
117
+ const rootRule = rules.find(x => x.from?.pathPrefix === '/');
118
+ if (rootRule) {
119
+ rule = rootRule;
120
+ }
121
+ }
122
+ mountPoint = normalizePathPrefix(rule?.from?.pathPrefix || '/');
123
+ }
124
+ return domains.map(domain => getAccessUrl(domain.value, mountPoint, params));
125
+ }
126
+ export function getExplorerLink(chainHost, did, type) {
127
+ if (!chainHost) return undefined;
128
+ try {
129
+ const chainUrl = new URL(chainHost);
130
+ switch (type) {
131
+ case 'asset':
132
+ chainUrl.pathname = `/explorer/assets/${did}`;
133
+ break;
134
+ case 'account':
135
+ chainUrl.pathname = `/explorer/accounts/${did}`;
136
+ break;
137
+ case 'tx':
138
+ chainUrl.pathname = `/explorer/txs/${did}`;
139
+ break;
140
+ case 'token':
141
+ chainUrl.pathname = `/explorer/tokens/${did}`;
142
+ break;
143
+ case 'factory':
144
+ chainUrl.pathname = `/explorer/factories/${did}`;
145
+ break;
146
+ case 'bridge':
147
+ chainUrl.pathname = `/explorer/bridges/${did}`;
148
+ break;
149
+ default:
150
+ chainUrl.pathname = '/';
151
+ }
152
+ return chainUrl.href;
153
+ } catch {
154
+ return undefined;
155
+ }
156
+ }
157
+ export function patchJsxToLocale(rawStr, replaceMap = {}) {
158
+ return rawStr.split(/{{|}}/).map(item => {
159
+ if (replaceMap[item]) {
160
+ if (replaceMap[item] instanceof Function) {
161
+ return replaceMap[item]();
162
+ }
163
+ return replaceMap[item];
164
+ }
165
+ return item;
166
+ }).filter(Boolean);
167
+ }
168
+ export function formatToDate(date, locale = 'en') {
169
+ if (!date) {
170
+ return '-';
171
+ }
172
+ return dayjs(date).locale(formatLocale(locale)).format('ll');
173
+ }
174
+ export function formatToDatetime(date, locale = 'en') {
175
+ if (!date) {
176
+ return '-';
177
+ }
178
+ return dayjs(date).locale(formatLocale(locale)).format('lll');
179
+ }
180
+ export function formatTime(date, format = 'lll', locale = 'en') {
181
+ if (!date) {
182
+ return '-';
183
+ }
184
+ return dayjs(date).locale(formatLocale(locale)).format(format);
185
+ }
186
+ export function formatDateTime(date, locale = 'en') {
187
+ return dayjs(date).locale(formatLocale(locale)).format('YYYY-MM-DD HH:mm');
188
+ }
189
+ export const formatLocale = (locale = 'en') => {
190
+ if (locale === 'tw') {
191
+ return 'zh';
192
+ }
193
+ return locale;
194
+ };
195
+ export const formatPrettyMsLocale = locale => locale === 'zh' ? 'zh_CN' : 'en_US';
196
+ export const parseQuery = str => str.replace(/^\?/, '').split('&').map(x => x.split('=')).filter(([key]) => !!key).reduce((memo, x) => {
197
+ const key = x[0];
198
+ const value = decodeURIComponent(x[1]) || true;
199
+ memo[key] = value;
200
+ return memo;
201
+ }, {});
202
+
203
+ // Append any query string url to api requests
204
+ export const appendParams = (url, extraParams = {}) => {
205
+ const [pathname, query = ''] = url.split('?');
206
+ const oldParams = parseQuery(query);
207
+ const params = Object.assign({}, oldParams, extraParams);
208
+ return `${pathname}?${qs.stringify(params)}`;
209
+ };
210
+ export const isInstalling = status => ['waiting', 'downloading', 'installing', 'upgrading'].includes(status);
211
+ export const isDownloading = status => ['waiting', 'downloading'].includes(status);
212
+ export const isRunning = status => status === 'running';
213
+ export const formatDiskSize = (size, serverPlatform = '') => {
214
+ const base = serverPlatform === 'linux' ? 2 : 10;
215
+ return filesize(size, {
216
+ base,
217
+ round: 2
218
+ });
219
+ };
220
+ export const checkInputByType = (type, value) => {
221
+ const typesMap = {
222
+ url: isUrl
223
+ };
224
+ if (!type) {
225
+ return true;
226
+ }
227
+ if (typesMap[type]) {
228
+ return typesMap[type](value);
229
+ }
230
+ return false;
231
+ };
232
+ export const formatUrl = url => humanizeUrl(url.split('?').shift());
233
+ export const formatPerson = person => {
234
+ if (!person) {
235
+ return '-';
236
+ }
237
+ if (typeof person === 'string') {
238
+ return person;
239
+ }
240
+ const name = person.name || '';
241
+ const u = person.url || person.web;
242
+ const url = u ? ` (${u})` : '';
243
+ const e = person.email || person.mail;
244
+ const email = e ? ` <${e}>` : '';
245
+ return name + email + url;
246
+ };
247
+ export const shouldCheckDomainStatus = domain => domain &&
248
+ // eslint-disable-line
249
+ ![DOMAIN_FOR_IP_SITE, DOMAIN_FOR_IP_SITE_REGEXP, DOMAIN_FOR_DEFAULT_SITE, DOMAIN_FOR_INTERNAL_SITE].includes(domain);
250
+ export const checkIsWildcardDomain = url => {
251
+ try {
252
+ if (!url) {
253
+ return false;
254
+ }
255
+ const tempUrl = url.startsWith('http') ? url : `http://${url}`;
256
+ const urlObj = new window.URL(tempUrl);
257
+ return decodeURIComponent(urlObj.host).split('.').some(x => x === '*');
258
+ } catch (error) {
259
+ console.error(url, error);
260
+ return false;
261
+ }
262
+ };
263
+ export const stringSortHandlerAsc = (strA = '', strB = '') => {
264
+ if (strA > strB) {
265
+ return 1;
266
+ }
267
+ if (strB > strA) {
268
+ return -1;
269
+ }
270
+ return 0;
271
+ };
272
+ export const getInviteLink = ({
273
+ inviteId,
274
+ endpoint
275
+ }) => {
276
+ if (!endpoint) {
277
+ return '';
278
+ }
279
+ const u = new URL(endpoint);
280
+ u.pathname = joinUrl(u.pathname, WELLKNOWN_SERVICE_PATH_PREFIX, 'invite');
281
+ u.searchParams.set('inviteId', inviteId);
282
+ return u.href;
283
+ };
284
+ export const getTransferAppLink = ({
285
+ transferId,
286
+ endpoint
287
+ }) => {
288
+ if (!endpoint) {
289
+ return '';
290
+ }
291
+ const u = new URL(endpoint);
292
+ u.pathname = joinUrl(u.pathname, WELLKNOWN_SERVICE_PATH_PREFIX, 'transfer');
293
+ u.searchParams.set('transferId', transferId);
294
+ return u.href;
295
+ };
296
+ export const getIssuePassportLink = ({
297
+ id,
298
+ endpoint
299
+ }) => {
300
+ if (!endpoint) {
301
+ return '';
302
+ }
303
+ const u = new URL(endpoint);
304
+ u.pathname = joinUrl(u.pathname, WELLKNOWN_SERVICE_PATH_PREFIX, 'issue-passport');
305
+ u.searchParams.set('id', id);
306
+ return u.href;
307
+ };
308
+ export const formatRegistryScreenshotPath = (did, asset) => {
309
+ if (asset.startsWith('/assets')) {
310
+ return asset;
311
+ }
312
+ return `/assets/${did}/screenshots/${asset}`;
313
+ };
314
+ export const formatRegistryLogoPath = (did, asset) => {
315
+ if (asset.startsWith('/assets')) {
316
+ return asset;
317
+ }
318
+ return `/assets/${did}/${asset}`;
319
+ };
320
+ export function getWebWalletUrl(info) {
321
+ try {
322
+ const url = window.localStorage.getItem('wallet_url');
323
+ if (url) {
324
+ return url;
325
+ }
326
+ } catch (err) {
327
+ // Do nothing
328
+ }
329
+ return info && info.webWalletUrl ? info.webWalletUrl : WEB_WALLET_URL;
330
+ }
331
+ export function isValidClusterSize(data) {
332
+ const {
333
+ value,
334
+ cpuCores
335
+ } = data;
336
+ if (!value) {
337
+ return '';
338
+ }
339
+ const v = Number(value);
340
+ if (Number.isNaN(v)) {
341
+ return 'Cluster size should be a number';
342
+ }
343
+ if (!Number.isInteger(v)) {
344
+ return 'Cluster size should be integer';
345
+ }
346
+ if (v <= 0 || v > cpuCores) {
347
+ return `Cluster size should between 1 to ${cpuCores}`;
348
+ }
349
+ return '';
350
+ }
351
+ export function isProtectedRole(role) {
352
+ return Object.values(ROLES).includes(role);
353
+ }
354
+ export function formatFactoryPrice(blocklet) {
355
+ if (!blocklet?.payment) {
356
+ return [];
357
+ }
358
+ const list = (blocklet.payment?.price || []).map(item => ({
359
+ name: item.symbol,
360
+ value: item.value
361
+ }));
362
+ return list;
363
+ }
364
+ export const getBlockletLogoUrl = ({
365
+ did,
366
+ baseUrl,
367
+ logoPath
368
+ }) => {
369
+ if (logoPath && logoPath.startsWith('http')) {
370
+ return logoPath;
371
+ }
372
+ if (baseUrl.startsWith('http') && logoPath) {
373
+ return joinUrl(baseUrl, formatRegistryLogoPath(did, logoPath));
374
+ }
375
+ const prefix = window.env.apiPrefix || '/';
376
+ let apiPrefix = prefix.replace(/^\/+/, '').replace(/\/+$/, '');
377
+ if (apiPrefix) {
378
+ apiPrefix = `/${apiPrefix}`;
379
+ }
380
+ return joinUrl(apiPrefix, `/blocklet/logo/${did}`);
381
+ };
382
+ export const getPathPrefix = () => window.env && window.env.apiPrefix ? window.env.apiPrefix : '/';
383
+ export const isUrlAccessible = url => checkAccessible(joinUrl(new URL(url).origin, WELLKNOWN_PING_PREFIX));
384
+ export const getAccessibleUrl = async urls => {
385
+ try {
386
+ const res = await evaluateURLs(urls);
387
+ return res[0].url;
388
+ } catch (error) {
389
+ console.warn('get accessible url failed');
390
+ return '';
391
+ }
392
+ };
393
+
394
+ /**
395
+ * 检查证书是否与 blocklet 匹配
396
+ * @param {string[]} blockletUrls - 通过 blocklet#interfaces#url 获取到的一组 url
397
+ * @param {object[]} matchedSites - 通过 certificate#matchedSites 获取到的一组 site
398
+ * @returns {boolean} - 匹配则返回 true
399
+ */
400
+ export const isCertificateMatch = (blockletUrls = [], matchedSites = []) => {
401
+ try {
402
+ return matchedSites.map(item => item.domain).some(domain => {
403
+ return blockletUrls.some(u => {
404
+ const url = new window.URL(u.startsWith('http') ? u : `http://${u}`);
405
+ return url.hostname === domain;
406
+ });
407
+ });
408
+ } catch (e) {
409
+ console.warn('domain match failed');
410
+ return false;
411
+ }
412
+ };
413
+ export const getBlockletUrlParams = (blocklet, locale) => (blocklet || {}).status === 'running' ? {
414
+ locale
415
+ } : {
416
+ locale,
417
+ __start__: 1
418
+ };
419
+
420
+ /**
421
+ * 判断是否在safari浏览器中
422
+ * 不传的ua情况下,使用当前页面的ua
423
+ * chrome浏览器的ua也会带有 Safari 字样,所以要排除 Chrome 字符串
424
+ * iPhone 设备下,所有浏览器都是 safari 的 webkit
425
+ * @param {String} ua userAgent 字符串
426
+ * @returns bool
427
+ */
428
+ export const isSafari = (ua = window.navigator.userAgent) => {
429
+ return ua.includes('iPhone') || ua.includes('Safari') && !ua.includes('Chrome');
430
+ };
431
+ export const isChrome = (ua = window.navigator.userAgent) => {
432
+ return ua.includes('Chrome');
433
+ };
434
+
435
+ /**
436
+ *
437
+ * @export
438
+ * @param {string} url
439
+ * @return {string}
440
+ */
441
+ export function deepDecodeURIComponent(url) {
442
+ let lastDecodeUrl = decodeURIComponent(url);
443
+ while (lastDecodeUrl !== decodeURIComponent(lastDecodeUrl)) {
444
+ lastDecodeUrl = decodeURIComponent(lastDecodeUrl);
445
+ }
446
+ return lastDecodeUrl;
447
+ }
448
+
449
+ /**
450
+ *
451
+ * @description 已知nextWorkflow的地址,提取它的statusUrl和token
452
+ * @export
453
+ * @param {string} nextWorkflow
454
+ * @returns {{
455
+ * statusUrl: string;
456
+ * token: string;
457
+ * }}
458
+ */
459
+ export function extractStatusUrlFromNextWorkflow(nextWorkflow) {
460
+ const nextWorkflowURL = new URL(deepDecodeURIComponent(nextWorkflow)).searchParams.get('url');
461
+ return {
462
+ statusUrl: nextWorkflowURL.replace('/auth?', '/status?'),
463
+ token: new URL(nextWorkflowURL).searchParams.get('_t_')
464
+ };
465
+ }
466
+ export function getBlockletMetaUrl(storeUrl, did) {
467
+ return joinUrl(storeUrl, BLOCKLET_STORE_API_PREFIX, `/blocklets/${did}/blocklet.json`);
468
+ }
469
+ export async function getAsset(chainHost, address) {
470
+ const result = await axios.post(joinUrl(chainHost, '/api/gql/'), JSON.stringify({
471
+ query: `{
472
+ getAssetState(address: "${address}") {
473
+ state {
474
+ address
475
+ data {
476
+ typeUrl
477
+ value
478
+ }
479
+ issuer
480
+ owner
481
+ parent
482
+ }
483
+ }
484
+ }`
485
+ }), {
486
+ headers: {
487
+ 'Content-Type': 'application/json',
488
+ Accept: 'application/json'
489
+ },
490
+ timeout: 60 * 1000
491
+ });
492
+ const state = get(result.data, 'data.getAssetState.state');
493
+ if (state && state.data.typeUrl === 'json') {
494
+ state.data.value = JSON.parse(state.data.value);
495
+ }
496
+ return state;
497
+ }
498
+ export function getAssetExpiration(asset) {
499
+ return last(get(asset, 'data.value.expirationDate', []));
500
+ }
501
+
502
+ /**
503
+ * 检查url是否 未添加到 store list 中
504
+ * @param {string} url - 需要检查的url
505
+ * @param {object[]} storeList - 后端的store list, 一般是 node.blockletRegistryList 或 blocklet.settings.storeList
506
+ * @returns {Object.freeze({
507
+ * isNew: boolean;
508
+ * decoded: string;
509
+ * })} - 返回判断是否是新的url和解码后的url
510
+ */
511
+ export const isNewStoreUrl = (url, storeList) => {
512
+ if (typeof url === 'string') {
513
+ let decoded = decodeURIComponent(url?.trim());
514
+ const regex = /^https?:\/\//;
515
+ if (!regex.test(decoded)) {
516
+ decoded = `https://${decoded}`;
517
+ }
518
+ decoded = trimEnd(decoded, '/');
519
+
520
+ // validate
521
+ try {
522
+ new URL(decoded); // eslint-disable-line no-new
523
+ } catch {
524
+ throw new Error('Invalid Blocklet Store URL');
525
+ }
526
+ if (storeList?.some(item => [url, decoded].includes(item.url))) {
527
+ return {
528
+ isNew: false,
529
+ decoded
530
+ };
531
+ }
532
+ return {
533
+ isNew: true,
534
+ decoded
535
+ };
536
+ }
537
+ return {
538
+ isNew: false,
539
+ decoded: ''
540
+ };
541
+ };
542
+ export const isBlockletDev = blocklet => blocklet.mode === BLOCKLET_MODES.DEVELOPMENT;
543
+ export const APP_PREFIX = window.env?.groupPathPrefix || '/';
544
+ export const BlockletAdminRoles = [ROLES.ADMIN, ROLES.OWNER];
545
+ export const toSlotDomain = domain => {
546
+ if (domain.endsWith(DEFAULT_IP_DOMAIN_SUFFIX)) {
547
+ const subDomain = domain.split('.').shift();
548
+ const matches = subDomain.match(IP);
549
+ if (matches) {
550
+ return domain.replace(matches[0].slice(1), SLOT_FOR_IP_DNS_SITE);
551
+ }
552
+ }
553
+ return domain;
554
+ };
555
+ export const getStoreList = ({
556
+ fromBlocklet,
557
+ nodeInfo,
558
+ blocklet
559
+ }) => {
560
+ const teamDid = fromBlocklet ? blocklet?.meta?.did : nodeInfo?.did;
561
+ const storeList = fromBlocklet ? blocklet?.settings?.storeList || [] : nodeInfo?.blockletRegistryList || [];
562
+ return {
563
+ teamDid,
564
+ storeList
565
+ };
566
+ };
567
+ const isDidDomainOrIpEchoDomain = domain => {
568
+ if (!domain) {
569
+ return false;
570
+ }
571
+ return domain.endsWith(DEFAULT_DID_DOMAIN) || domain.endsWith(DEFAULT_IP_DOMAIN_SUFFIX);
572
+ };
573
+ export const sortDomains = domains => {
574
+ return (domains || []).sort((x, y) => {
575
+ if (isDidDomainOrIpEchoDomain(x.value) && isDidDomainOrIpEchoDomain(y.value)) {
576
+ return 0;
577
+ }
578
+ if (isDidDomainOrIpEchoDomain(x.value)) {
579
+ return 1;
580
+ }
581
+ if (isDidDomainOrIpEchoDomain(y.value)) {
582
+ return -1;
583
+ }
584
+ return 1;
585
+ });
586
+ };
587
+ export const formatMountPoint = value => normalizePathPrefix(urlPathFriendly(value));
588
+ export const getRenewBlockletURL = ({
589
+ launcherUrl = '',
590
+ nftId = '',
591
+ locale = 'en'
592
+ }) => joinUrl(launcherUrl, `/instances/${nftId}/renewal?locale=${locale}&return-url=${encodeURIComponent(window.location.href)}`);
593
+ export const getSubscriptionURL = ({
594
+ launcherUrl = '',
595
+ nftId = '',
596
+ locale = 'en'
597
+ }) => joinUrl(launcherUrl, `/instances/${nftId}/subscription?locale=${locale}&return-url=${encodeURIComponent(window.location.href)}`);
598
+ export const nanoid = (length = 16) => [...Array(length)].map(() => Math.random().toString(36)[2]).join('');
@@ -0,0 +1,4 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+
3
+ // 当前模式是 内测模式 吗? @see: https://developer.aliyun.com/article/572525
4
+ export const enableDebug = localStorage.getItem('enableDebug') === 'true';
@@ -0,0 +1,51 @@
1
+ /* eslint-disable import/prefer-default-export */
2
+ import { isEmpty } from 'lodash';
3
+ import { getSpaceNameByEndpoint } from './spaces';
4
+
5
+ /**
6
+ * @description
7
+ * @export
8
+ * @param {{
9
+ * nodeApi: import('@abtnode/client'),
10
+ * blockletDid: string,
11
+ * spaceGateways: import('../blocklet/storage/connected').SpaceGateway[],
12
+ * }} { nodeApi, blockletDid, spaceGateways }
13
+ * @return {Promise<import('../blocklet/storage/connected').SpaceGateway[]>}
14
+ */
15
+ export async function updateSpaceGatewaysFromDIDSpaces({
16
+ blockletDid,
17
+ nodeApi,
18
+ spaceGateways
19
+ }) {
20
+ let shouldUpdate = false;
21
+ const latestSpaceGateways = await Promise.all(spaceGateways.map(async x => {
22
+ let {
23
+ name
24
+ } = x;
25
+ const newName = await getSpaceNameByEndpoint(x.endpoint);
26
+ if (!isEmpty(newName) && newName !== name) {
27
+ name = newName;
28
+ shouldUpdate = true;
29
+ }
30
+ return {
31
+ ...x,
32
+ name
33
+ };
34
+ }));
35
+ if (shouldUpdate) {
36
+ await Promise.all(latestSpaceGateways.filter(x => x.did).map(x => {
37
+ return nodeApi.updateBlockletSpaceGateway({
38
+ input: {
39
+ did: blockletDid,
40
+ where: {
41
+ did: x.did
42
+ },
43
+ spaceGateway: {
44
+ ...x
45
+ }
46
+ }
47
+ });
48
+ }));
49
+ }
50
+ return latestSpaceGateways;
51
+ }