@blocklet/launcher-workflow 2.4.3 → 2.4.5

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 (39) hide show
  1. package/es/components/in-progress-session.js +1 -1
  2. package/es/components/launch-serverless/allocate.js +181 -0
  3. package/es/components/launch-serverless/install.js +203 -0
  4. package/es/components/launch-serverless/shared/base-serverless-layout.js +53 -0
  5. package/es/components/launch-serverless/shared/common-components.js +605 -0
  6. package/es/components/launch-serverless/shared/loading-display-layout.js +122 -0
  7. package/es/components/launch-serverless/shared/retry-error-message.js +45 -0
  8. package/es/components/launch-serverless/start-app.js +356 -0
  9. package/es/contexts/request.js +2 -2
  10. package/es/hooks/use-serial-polling.js +43 -0
  11. package/es/install.js +28 -0
  12. package/es/launch.js +1 -1
  13. package/es/locales/en.js +71 -14
  14. package/es/locales/zh.js +68 -12
  15. package/es/paid.js +1 -1
  16. package/es/prepare.js +1 -1
  17. package/es/start-app.js +28 -0
  18. package/es/util.js +181 -2
  19. package/lib/components/in-progress-session.js +3 -3
  20. package/lib/components/launch-serverless/allocate.js +198 -0
  21. package/lib/components/launch-serverless/install.js +223 -0
  22. package/lib/components/launch-serverless/shared/base-serverless-layout.js +59 -0
  23. package/lib/components/launch-serverless/shared/common-components.js +635 -0
  24. package/lib/components/launch-serverless/shared/loading-display-layout.js +131 -0
  25. package/lib/components/launch-serverless/shared/retry-error-message.js +52 -0
  26. package/lib/components/launch-serverless/start-app.js +369 -0
  27. package/lib/contexts/request.js +2 -2
  28. package/lib/hooks/use-serial-polling.js +49 -0
  29. package/lib/install.js +35 -0
  30. package/lib/launch.js +2 -2
  31. package/lib/locales/en.js +71 -14
  32. package/lib/locales/zh.js +68 -12
  33. package/lib/paid.js +2 -2
  34. package/lib/prepare.js +2 -2
  35. package/lib/start-app.js +35 -0
  36. package/lib/util.js +214 -11
  37. package/package.json +15 -12
  38. package/es/components/launch-serverless.js +0 -115
  39. package/lib/components/launch-serverless.js +0 -89
package/es/locales/en.js CHANGED
@@ -39,15 +39,15 @@ export default {
39
39
  },
40
40
  prepare: {
41
41
  serverless: {
42
- preparing: 'Allocating space on the server. Please wait...',
43
- prepared: 'The space is ready. Redirecting to the server to continue the installation...',
44
- prepareFailed: 'Failed to allocate space!'
42
+ preparing: 'Setting up your space...',
43
+ prepared: 'Space is ready! Installing your blocklet...',
44
+ prepareFailed: 'Failed to set up your space!'
45
45
  }
46
46
  },
47
47
  launch: {
48
48
  pageTitle: 'Preparing Space',
49
49
  invalidFftId: 'Invalid Purchase NFT ID',
50
- launchApp: 'Launch App',
50
+ launchApp: 'Launch Blocklet',
51
51
  launching: 'Your Blocklet Space is being baked, please be patient, it usually takes about 5 minutes',
52
52
  launched: 'Your Blocklet Space is up and running',
53
53
  launchSuccess: 'Blocklet Space is successfully launched',
@@ -55,11 +55,11 @@ export default {
55
55
  waitingForLaunching: 'Your Blocklet Space launch request is being processed, please be patient, it usually takes about 5 minutes',
56
56
  accessServer: 'Access Blocklet Space',
57
57
  waiting: {
58
- starting: 'Starting Blocklet Space',
59
- securing: 'Securing Network',
60
- prepare: 'Prepare Storage',
61
- waiting: 'Waiting for Ready',
62
- done: 'Blocklet Space is Ready'
58
+ starting: 'Starting Blocklet Space...',
59
+ securing: 'Securing Network...',
60
+ prepare: 'Prepare Storage...',
61
+ waiting: 'Waiting for Ready...',
62
+ done: 'Blocklet Space is Ready...'
63
63
  },
64
64
  dialog: {
65
65
  title: 'Launch Blocklet Space',
@@ -74,6 +74,63 @@ export default {
74
74
  notFoundDescription: 'You can launch the Space by clicking the button below'
75
75
  }
76
76
  },
77
+ install: {
78
+ pageTitle: 'Install Blocklet',
79
+ waiting: {
80
+ verifying: 'Verifying blocklet metadata...',
81
+ downloading: 'Downloading blocklet...',
82
+ extracting: 'Extracting blocklet data...',
83
+ downloadingComponent: 'Downloading {name}',
84
+ extractingComponent: 'Extracting {name}',
85
+ installing: 'Installing blocklet components...',
86
+ installed: 'Blocklet is installed'
87
+ },
88
+ installing: 'Installing Blocklet...',
89
+ installed: 'Blocklet is installed',
90
+ installFailed: 'Install Blocklet Failed!'
91
+ },
92
+ startApp: {
93
+ pageTitle: 'Start Blocklet',
94
+ starting: 'Starting Blocklet...',
95
+ started: 'Blocklet is ready to use!',
96
+ startedDescription: 'Your blocklet has been successfully started and is now ready to use.',
97
+ startFailed: 'Start Blocklet Failed',
98
+ installFailed: 'Install Blocklet Failed',
99
+ visit: 'Visit Blocklet',
100
+ dashboard: 'View Blocklet Dashboard',
101
+ subscription: 'Manage Subscription',
102
+ unknownApp: 'Unknown Blocklet',
103
+ appInfo: 'Blocklet Information',
104
+ appDid: 'Blocklet DID',
105
+ serverUrl: 'Server URL',
106
+ status: 'Status',
107
+ version: 'Version',
108
+ running: 'Running',
109
+ myOrders: 'My Orders',
110
+ myOrdersDesc: 'View and manage all your orders',
111
+ projectName: 'Project Name',
112
+ visitUrl: 'Visit URL',
113
+ visitApp: 'Visit Blocklet',
114
+ visitAppDesc: 'Open your blocklet homepage',
115
+ dashboardDesc: 'View monitoring status and resource usage',
116
+ subscriptionDesc: 'Manage stake amount and renewal settings',
117
+ appManagement: 'Blocklet Management',
118
+ appManagementDesc: 'Change configuration and blocklet settings',
119
+ waiting: {
120
+ starting: 'Starting blocklet...',
121
+ parsing: 'Parsing blocklet metadata...',
122
+ initializing: 'Initializing blocklet configuration...',
123
+ initializingOwner: 'Initializing blocklet owner...',
124
+ creatingSecurityRules: 'Creating default security rules...',
125
+ assigningDomain: 'Assigning default domain name...',
126
+ waitingForDomain: 'Waiting for default domain name...'
127
+ }
128
+ },
129
+ loading: {
130
+ completed: 'completed',
131
+ retry: 'Retry',
132
+ remainingTime: 'About {time} remaining'
133
+ },
77
134
  start: {
78
135
  title: 'Starting Space',
79
136
  error: {
@@ -108,10 +165,10 @@ export default {
108
165
  morePlanPrompt: 'Flip the page to see more plans',
109
166
  redeem: 'Select purchased space',
110
167
  noProducts: 'No products available for purchase, please check your payment-kit config',
111
- serverlessNotSupported: 'This app is not allowed in sigular and on-demand space, please select dedicated space',
168
+ serverlessNotSupported: 'This blocklet is not allowed in sigular and on-demand space, please select dedicated space',
112
169
  componentCount: '{count} Component Included',
113
170
  componentsCount: '{count} Components Included',
114
- onDemandNotSupport: 'This app does not support installation in on-demand space, please purchase dedicated space or install in your own dedicated space',
171
+ onDemandNotSupport: 'This blocklet does not support installation in on-demand space, please purchase dedicated space or install in your own dedicated space',
115
172
  dialog: {
116
173
  title: 'Purchase Blocklet Space NFT',
117
174
  scan: 'Scan the QR code below with your DID wallet to complete purchase',
@@ -120,7 +177,7 @@ export default {
120
177
  },
121
178
  serverlessDialog: {
122
179
  title: 'Purchase successfully',
123
- redirectToStoreButton: 'Go to install the application →',
180
+ redirectToStoreButton: 'Go to install the blocklet →',
124
181
  purchaseServerlessSuccess: 'The purchase of Running Space is successful and you can go ahead and install Blocklet.'
125
182
  },
126
183
  inProgress: {
@@ -141,7 +198,7 @@ export default {
141
198
  paid: 'Current order has been paid',
142
199
  paidDescription: 'The current order has been paid, you can choose to purchase a new space or continue the launch process.',
143
200
  installed: 'Order has been installed',
144
- installedDescription: 'The current order has been successfully installed, you can choose to purchase a new space or jump to the current application.',
201
+ installedDescription: 'The current order has been successfully installed, you can choose to purchase a new space or jump to the current blocklet.',
145
202
  expired: 'Order has been expired',
146
203
  expiredDescription: 'The current order has expired, you can choose to purchase a new space.'
147
204
  }
@@ -156,7 +213,7 @@ export default {
156
213
  agreement: '{name} User Agreement',
157
214
  estimatedCost: 'Estimated Cost',
158
215
  estimatedCostFreeTrial: 'Estimated Cost After The Trial ends',
159
- estimatedCostHint: 'The total cost will vary depending on the actual number and duration of components used in the application. The calculation method is: Unit price of component * Number of components * Duration.',
216
+ estimatedCostHint: 'The total cost will vary depending on the actual number and duration of components used in the blocklet. The calculation method is: Unit price of component * Number of components * Duration.',
160
217
  freeTrial: 'Free Trial',
161
218
  freeTrialHint: 'Free trial for {duration}',
162
219
  stakeAmount: 'Stake Amount',
package/es/locales/zh.js CHANGED
@@ -47,7 +47,7 @@ export default {
47
47
  launch: {
48
48
  pageTitle: '准备空间',
49
49
  invalidFftId: '无效的购买凭证',
50
- launchApp: '启动应用',
50
+ launchApp: '启动 Blocklet',
51
51
  launching: '空间正在启动中, 大约需要 5 分钟',
52
52
  launched: '空间已启动',
53
53
  launchSuccess: '创建空间成功',
@@ -55,11 +55,11 @@ export default {
55
55
  waitingForLaunching: '空间正在启动中,大约需要 5 分钟',
56
56
  accessServer: '访问空间',
57
57
  waiting: {
58
- starting: '启动空间',
59
- securing: '确保空间的网络安全',
60
- prepare: '准备好空间存储',
61
- waiting: '等待空间就绪',
62
- done: '空间已准备就绪'
58
+ starting: '启动空间...',
59
+ securing: '确保空间的网络安全...',
60
+ prepare: '准备好空间存储...',
61
+ waiting: '等待空间就绪...',
62
+ done: '空间已准备就绪...'
63
63
  },
64
64
  dialog: {
65
65
  title: '创建空间',
@@ -74,6 +74,62 @@ export default {
74
74
  notFoundDescription: '您可以点击下面按钮启动空间'
75
75
  }
76
76
  },
77
+ install: {
78
+ pageTitle: '安装 Blocklet',
79
+ waiting: {
80
+ verifying: '验证 Blocklet 元数据...',
81
+ downloading: '下载 Blocklet...',
82
+ extracting: '提取 Blocklet 数据...',
83
+ downloadingComponent: '下载 {name}',
84
+ extractingComponent: '提取 {name}',
85
+ installing: '安装 Blocklet 组件...',
86
+ installed: 'Blocklet 已安装'
87
+ },
88
+ installing: '正在安装 Blocklet...',
89
+ installFailed: '安装 Blocklet 失败!'
90
+ },
91
+ startApp: {
92
+ pageTitle: '启动 Blocklet',
93
+ starting: '正在启动 Blocklet...',
94
+ started: 'Blocklet 启动成功',
95
+ startedDescription: '您的 Blocklet 已成功启动并准备就绪,现在可以开始使用了。',
96
+ startFailed: '启动 Blocklet 失败',
97
+ installFailed: '安装 Blocklet 失败',
98
+ visit: '访问 Blocklet',
99
+ dashboard: '查看 Blocklet 仪表盘',
100
+ subscription: '管理订阅',
101
+ unknownApp: '未知 Blocklet',
102
+ appInfo: 'Blocklet 信息',
103
+ appDid: 'Blocklet DID',
104
+ serverUrl: '服务器地址',
105
+ status: '状态',
106
+ version: '版本',
107
+ running: '运行中',
108
+ myOrders: '我的订单',
109
+ myOrdersDesc: '查看和管理您的所有订单',
110
+ projectName: '项目名称',
111
+ visitUrl: '访问地址',
112
+ visitApp: '访问 Blocklet',
113
+ visitAppDesc: '打开您的 Blocklet 主页面',
114
+ dashboardDesc: '查看监控状态和资源使用',
115
+ subscriptionDesc: '管理质押金额和续费设置',
116
+ appManagement: 'Blocklet 管理',
117
+ appManagementDesc: '更改配置和 Blocklet 设置',
118
+ waiting: {
119
+ starting: '正在启动 Blocklet...',
120
+ parsing: '正在解析 Blocklet 元数据...',
121
+ initializing: '正在初始化 Blocklet 配置...',
122
+ initializingOwner: '正在初始化 Blocklet 所有者...',
123
+ creatingSecurityRules: '正在创建默认安全规则...',
124
+ assigningDomain: '正在为 Blocklet 分配默认域名...',
125
+ waitingForDomain: '正在等待默认域名生效...'
126
+ }
127
+ },
128
+ loading: {
129
+ completed: '完成',
130
+ retry: '重试',
131
+ remainingTime: '大约需要 {time}'
132
+ },
77
133
  start: {
78
134
  title: '启动空间',
79
135
  error: {
@@ -108,10 +164,10 @@ export default {
108
164
  noPlan: '选择套餐以继续',
109
165
  hasPlan: '选用{name}',
110
166
  noProducts: '没有可购买的商品,请检查 PaymentKit 的配置',
111
- serverlessNotSupported: '该应用被禁止能在单应用或者按需空间中运行,请选择专用空间',
167
+ serverlessNotSupported: '该 Blocklet 被禁止能在单 Blocklet 或者按需空间中运行,请选择专用空间',
112
168
  componentCount: '共 {count} 个组件',
113
169
  componentsCount: '共 {count} 个组件',
114
- onDemandNotSupport: '该应用不支持安装在按需空间中,请购买专用空间,或者安装在自己已有的专用空间中',
170
+ onDemandNotSupport: '该 Blocklet 不支持安装在按需空间中,请购买专用空间,或者安装在自己已有的专用空间中',
115
171
  dialog: {
116
172
  title: '购买 Blocklet Server NFT',
117
173
  scan: '用您的 DID 钱包扫描下面的二维码完成购买',
@@ -120,8 +176,8 @@ export default {
120
176
  },
121
177
  serverlessDialog: {
122
178
  title: '购买成功',
123
- redirectToStoreButton: '去安装应用 →',
124
- purchaseServerlessSuccess: '购买运行空间成功,您可以去安装应用.'
179
+ redirectToStoreButton: '去安装 Blocklet →',
180
+ purchaseServerlessSuccess: '购买运行空间成功,您可以去安装 Blocklet.'
125
181
  },
126
182
  inProgress: {
127
183
  title: '未完成的订单',
@@ -141,7 +197,7 @@ export default {
141
197
  paid: '订单已支付',
142
198
  paidDescription: '检测当前订单已经支付,您可以选择购买新的空间,或者继续启动流程',
143
199
  installed: '订单已安装',
144
- installedDescription: '检测当前订单已经安装成功,您可以选择购买新的空间,或者跳转到当前应用。',
200
+ installedDescription: '检测当前订单已经安装成功,您可以选择购买新的空间,或者跳转到当前 Blocklet。',
145
201
  expired: '订单已过期',
146
202
  expiredDescription: '检测当前订单已经过期,您可以选择购买新的空间。'
147
203
  }
@@ -156,7 +212,7 @@ export default {
156
212
  agreement: '{name} 用户协议',
157
213
  estimatedCostFreeTrial: '试用结束后估算成本',
158
214
  estimatedCost: '估算成本',
159
- estimatedCostHint: '总成本会根据应用实际使用的组件数量和时长而变化,计算方式为: 组件单价*组件数量*时长',
215
+ estimatedCostHint: '总成本会根据 Blocklet 实际使用的组件数量和时长而变化,计算方式为: 组件单价*组件数量*时长',
160
216
  freeTrial: '免费试用',
161
217
  freeTrialHint: '免费试用{duration}',
162
218
  stakeAmount: '质押金额',
package/es/paid.js CHANGED
@@ -4,7 +4,7 @@ import CircularProgress from '@mui/material/CircularProgress';
4
4
  import { useRequest } from 'ahooks';
5
5
  import { useEffect } from 'react';
6
6
  import { useNavigate, useSearchParams } from 'react-router-dom';
7
- import joinURL from 'url-join';
7
+ import { joinURL } from 'ufo';
8
8
  import { useLocaleContext } from './contexts/locale';
9
9
  import useRequestContext from './contexts/request';
10
10
  import { useWorkflowContext } from './contexts/workflow';
package/es/prepare.js CHANGED
@@ -17,7 +17,7 @@ import { useCallback, useEffect, useMemo } from 'react';
17
17
  import { Link, useNavigate, useSearchParams } from 'react-router-dom';
18
18
  import useAsync from 'react-use/lib/useAsync';
19
19
  import useSetState from 'react-use/lib/useSetState';
20
- import joinURL from 'url-join';
20
+ import { joinURL } from 'ufo';
21
21
  import ConfirmDialog from './components/confirm';
22
22
  import Body from './components/layout/body';
23
23
  import Header from './components/layout/header';
@@ -0,0 +1,28 @@
1
+ import { useEffect } from 'react';
2
+ import { useParams } from 'react-router-dom';
3
+ import StartAppServerless from './components/launch-serverless/start-app';
4
+ import { useSessionContext } from './contexts/session';
5
+ import { jsx as _jsx } from "react/jsx-runtime";
6
+ export default function Launch() {
7
+ const {
8
+ sessionId
9
+ } = useParams();
10
+ const {
11
+ session
12
+ } = useSessionContext();
13
+ useEffect(() => {
14
+ if (!session.user) {
15
+ return session.login(() => {
16
+ session.refresh();
17
+ });
18
+ }
19
+ return () => {};
20
+ // eslint-disable-next-line react-hooks/exhaustive-deps
21
+ }, [session.user]);
22
+ if (!session.user) {
23
+ return '';
24
+ }
25
+ return /*#__PURE__*/_jsx(StartAppServerless, {
26
+ sessionId: sessionId
27
+ });
28
+ }
package/es/util.js CHANGED
@@ -1,9 +1,15 @@
1
+ import { WELLKNOWN_PATH_PREFIX, WELLKNOWN_PING_PREFIX } from '@abtnode/constant';
2
+ import axios from '@abtnode/util/lib/axios';
3
+ import normalizePathPrefix from '@abtnode/util/lib/normalize-path-prefix';
4
+ import tryWithTimeout from '@abtnode/util/lib/try-with-timeout';
5
+ import { evaluateURLs } from '@abtnode/util/lib/url-evaluation';
6
+ import checkAccessible from '@abtnode/util/lib/url-evaluation/check-accessible-browser';
1
7
  import { create as createRequestInstance } from '@blocklet/launcher-util/es/api';
2
8
  import { getFromQuery } from '@blocklet/launcher-ux/lib/util';
3
9
  import get from 'lodash.get';
4
10
  import noop from 'lodash.noop';
5
11
  import pick from 'lodash.pick';
6
- import joinURL from 'url-join';
12
+ import { joinURL } from 'ufo';
7
13
  export const BLOCKLET_STORE_URL = get(window, 'blocklet.LAUNCHER_BLOCKLET_STORE_URL') || 'https://store.blocklet.dev';
8
14
  export function getBlockletMetaUrl(registry, did) {
9
15
  return joinURL(registry, `/api/blocklets/${did}/blocklet.json?source=webapp`);
@@ -162,4 +168,177 @@ export const launchSession = {
162
168
  done(err);
163
169
  });
164
170
  }
165
- };
171
+ };
172
+ export function sleep(t) {
173
+ // eslint-disable-next-line no-promise-executor-return
174
+ return new Promise(resolve => setTimeout(resolve, t));
175
+ }
176
+ export const isUrlAccessible = url => checkAccessible(joinURL(new URL(url).origin, WELLKNOWN_PING_PREFIX));
177
+ export const checkBlockletAccessible = async (url, timeout = 5000, controller = null) => {
178
+ try {
179
+ const urlObj = new URL(url);
180
+ urlObj.protocol = 'https';
181
+ const res = await axios.get(joinURL(urlObj.toString(), '/api/__blocklet__.js?type=json'), {
182
+ timeout,
183
+ signal: controller?.signal,
184
+ validateStatus: status => {
185
+ return status >= 200 && status < 400 || status === 503; // 503 是 not running, 可以访问 blocklet service
186
+ }
187
+ });
188
+ return res.data;
189
+ } catch (error) {
190
+ return null;
191
+ }
192
+ };
193
+ export const checkUrlAccessible = async (url, timeout = 30 * 1000, controller = null) => {
194
+ try {
195
+ return await tryWithTimeout(async () => {
196
+ let res = null;
197
+ do {
198
+ res = await checkBlockletAccessible(url, 5000, controller);
199
+ await sleep(2000);
200
+ } while (!res && !controller?.signal?.aborted);
201
+ return res;
202
+ }, timeout);
203
+ } catch (error) {
204
+ console.error(error);
205
+ return null;
206
+ }
207
+ };
208
+ export const waitingForRaceAccessible = async (urls, timeout = 30 * 1000) => {
209
+ // Create an AbortController for each request
210
+ const controllers = urls.map(() => new AbortController());
211
+ try {
212
+ const tasks = urls.map((url, index) => checkUrlAccessible(url, timeout, controllers[index]).then(res => [url, res]).catch(error => {
213
+ // If this request failed but wasn't aborted, we should still propagate the error
214
+ if (error.name !== 'AbortError') {
215
+ throw error;
216
+ }
217
+ return null;
218
+ }));
219
+
220
+ // Add a timeout promise to the race
221
+ const timeoutPromise = new Promise((_, reject) => {
222
+ setTimeout(() => reject(new Error('All requests timed out')), timeout);
223
+ });
224
+
225
+ // Race all tasks including the timeout
226
+ const result = await Promise.race([
227
+ // Wait for the first successful response
228
+ ...tasks, timeoutPromise]);
229
+
230
+ // Cancel all other requests
231
+ controllers.forEach(controller => controller.abort());
232
+ return result;
233
+ } catch (error) {
234
+ // Cancel all requests on error
235
+ controllers.forEach(controller => controller.abort());
236
+ throw error;
237
+ }
238
+ };
239
+ const waitingForAccessible = async (urls, timeout = 30 * 1000) => {
240
+ const tasks = await urls.map(url => checkUrlAccessible(url, timeout));
241
+ const result = await Promise.all(tasks);
242
+ return result;
243
+ };
244
+ export const sortUrls = urls => {
245
+ return evaluateURLs(urls, {
246
+ checkAccessible: null
247
+ }).then(items => items.map(item => item.url));
248
+ };
249
+ export const getAccessibleUrl = async urls => {
250
+ try {
251
+ await waitingForAccessible(urls);
252
+ const res = await evaluateURLs(urls, {
253
+ checkAccessible: checkBlockletAccessible
254
+ });
255
+ return res[0].url;
256
+ } catch (error) {
257
+ console.warn('get accessible url failed', error);
258
+ return '';
259
+ }
260
+ };
261
+
262
+ /**
263
+ * get access url
264
+ * auto fix http/https, port, query
265
+ * docker friendly
266
+ */
267
+ export function getAccessUrl(hostname, path = '', params = undefined) {
268
+ if (!hostname) {
269
+ return '';
270
+ }
271
+ try {
272
+ let port = '';
273
+ const browserPort = Number(window.location.port);
274
+ if (process.env.NODE_ENV !== 'development' && browserPort && ![80, 443].includes(browserPort)) {
275
+ port = `:${browserPort}`;
276
+ }
277
+ const urlObj = new URL(`${window.location.protocol}//${hostname}${port}`);
278
+ urlObj.pathname = path;
279
+ const url = urlObj.href.replace(/\/$/, '');
280
+ if (!params || !Object.keys(params)) {
281
+ return url;
282
+ }
283
+ const searchParams = new URLSearchParams();
284
+ Object.keys(params).forEach(key => {
285
+ searchParams.append(key, params[key]);
286
+ });
287
+ return `${url}${urlObj.pathname === '/' ? '/' : ''}?${searchParams.toString()}`;
288
+ } catch (err) {
289
+ console.error(err);
290
+ return '';
291
+ }
292
+ }
293
+ export function getBlockletUrl({
294
+ blocklet,
295
+ domain: inputDomain,
296
+ mountPoint: inputMountPoint,
297
+ params
298
+ } = {}) {
299
+ const {
300
+ site
301
+ } = blocklet;
302
+ if (!site) {
303
+ return null;
304
+ }
305
+ const domain = inputDomain || (site.domainAliases || [])[0];
306
+ if (!domain) {
307
+ return null;
308
+ }
309
+ let mountPoint = inputMountPoint;
310
+ if (!mountPoint) {
311
+ const rule = site.rules.filter(x => !x.from.pathPrefix.startsWith(WELLKNOWN_PATH_PREFIX))[0];
312
+ mountPoint = rule ? rule.from.pathPrefix : '/';
313
+ }
314
+ return getAccessUrl(domain.value, mountPoint, params);
315
+ }
316
+ export function getBlockletUrls({
317
+ blocklet,
318
+ mountPoint: inputMountPoint,
319
+ params
320
+ } = {}) {
321
+ const {
322
+ site
323
+ } = blocklet;
324
+ if (!site) {
325
+ return [];
326
+ }
327
+ const domains = site.domainAliases || [];
328
+ if (!domains.length) {
329
+ return [];
330
+ }
331
+ let mountPoint = inputMountPoint;
332
+ if (!mountPoint) {
333
+ const rules = site.rules.filter(x => !x.from.pathPrefix.startsWith(WELLKNOWN_PATH_PREFIX));
334
+ let rule = rules[0];
335
+ if (rule?.from?.pathPrefix !== '/') {
336
+ const rootRule = rules.find(x => x.from?.pathPrefix === '/');
337
+ if (rootRule) {
338
+ rule = rootRule;
339
+ }
340
+ }
341
+ mountPoint = normalizePathPrefix(rule?.from?.pathPrefix || '/');
342
+ }
343
+ return domains.map(domain => getAccessUrl(domain.value, mountPoint, params));
344
+ }
@@ -11,7 +11,7 @@ var _Box = _interopRequireDefault(require("@mui/material/Box"));
11
11
  var _Link = _interopRequireDefault(require("@mui/material/Link"));
12
12
  var _react = require("react");
13
13
  var _useAsync = _interopRequireDefault(require("react-use/lib/useAsync"));
14
- var _urlJoin = _interopRequireDefault(require("url-join"));
14
+ var _ufo = require("ufo");
15
15
  var _locale = require("../contexts/locale");
16
16
  var _request = _interopRequireDefault(require("../contexts/request"));
17
17
  var _workflow = require("../contexts/workflow");
@@ -36,7 +36,7 @@ function InProgressSession() {
36
36
  const state = (0, _useAsync.default)(async () => {
37
37
  const {
38
38
  data
39
- } = await api.get((0, _urlJoin.default)(routerPrefix, '/launches/in-progress'));
39
+ } = await api.get((0, _ufo.joinURL)(routerPrefix, '/launches/in-progress'));
40
40
  if (data.launch) {
41
41
  if (localStorage.getItem(IGNORE_LAUNCH_SESSION_KEY) === data.launch.id) {
42
42
  return null;
@@ -59,7 +59,7 @@ function InProgressSession() {
59
59
  let continueBaseURL = '';
60
60
  try {
61
61
  continueBaseURL = (0, _util.getContinueLaunchURL)({
62
- baseURL: (0, _urlJoin.default)(window.location.origin, baseURL),
62
+ baseURL: (0, _ufo.joinURL)(window.location.origin, baseURL),
63
63
  launch: state.value
64
64
  });
65
65
  } catch (error) {