@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
@@ -0,0 +1,122 @@
1
+ import AnimationWaiter from '@arcblock/ux/lib/AnimationWaiter';
2
+ import { Box, Typography } from '@mui/material';
3
+ import PropTypes from 'prop-types';
4
+ import React from 'react';
5
+ import { useRequest as useRequestHook } from 'ahooks';
6
+ import { withQuery } from 'ufo';
7
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
8
+ import useRequest from '../../../contexts/request';
9
+ import { ActionCardBox, ErrorDisplay, LoadingContainer, ProductIntroCarousel, StyledProgress, TimeText } from './common-components';
10
+
11
+ /**
12
+ * 加载显示的通用布局组件
13
+ * 抽取三个阶段组件的共同结构,具体内容由外部传入
14
+ */
15
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
+ function LoadingDisplayLayout({
17
+ title,
18
+ // 进度条数据
19
+ progress,
20
+ elapsedTime,
21
+ estimatedTime,
22
+ // 动作描述数据
23
+ currentAction,
24
+ // 动画控制
25
+ tipFlag = null,
26
+ // 错误处理
27
+ error = null,
28
+ onRetry = null
29
+ }) {
30
+ const {
31
+ locale
32
+ } = useLocaleContext();
33
+ const {
34
+ t
35
+ } = useLocaleContext();
36
+ const {
37
+ api
38
+ } = useRequest();
39
+ const {
40
+ data: tips = []
41
+ } = useRequestHook(() => api.get(withQuery('/public/tips', {
42
+ locale
43
+ })).then(res => res.data?.tips || [], {
44
+ refreshDeps: [locale]
45
+ }));
46
+ return /*#__PURE__*/_jsxs(LoadingContainer, {
47
+ children: [/*#__PURE__*/_jsx(Typography, {
48
+ variant: "h3",
49
+ children: title
50
+ }), /*#__PURE__*/_jsx(Box, {
51
+ sx: {
52
+ '& div': {
53
+ p: 0,
54
+ m: 0
55
+ }
56
+ },
57
+ children: /*#__PURE__*/_jsx(AnimationWaiter, {
58
+ increaseSpeed: 0.3,
59
+ messageLoop: false,
60
+ size: 200
61
+ })
62
+ }), /*#__PURE__*/_jsxs(Box, {
63
+ sx: {
64
+ position: 'relative',
65
+ width: '100%'
66
+ },
67
+ children: [/*#__PURE__*/_jsx(Box, {
68
+ sx: {
69
+ display: 'flex',
70
+ alignItems: 'center',
71
+ justifyContent: 'flex-end',
72
+ mb: 1
73
+ },
74
+ children: /*#__PURE__*/_jsx(TimeText, {
75
+ children: t('loading.remainingTime', {
76
+ time: estimatedTime
77
+ })
78
+ })
79
+ }), /*#__PURE__*/_jsx(StyledProgress, {
80
+ value: progress
81
+ }), /*#__PURE__*/_jsxs(Box, {
82
+ sx: {
83
+ display: 'flex',
84
+ alignItems: 'center',
85
+ justifyContent: 'space-between',
86
+ my: 1
87
+ },
88
+ children: [/*#__PURE__*/_jsxs(Typography, {
89
+ variant: "caption",
90
+ color: "text.secondary",
91
+ children: [Math.round(progress), "% ", t('loading.completed')]
92
+ }), /*#__PURE__*/_jsx(TimeText, {
93
+ children: elapsedTime
94
+ })]
95
+ })]
96
+ }), /*#__PURE__*/_jsx(ActionCardBox, {
97
+ tipFlag: tipFlag || currentAction,
98
+ children: currentAction
99
+ }), /*#__PURE__*/_jsx(ProductIntroCarousel, {
100
+ tips: tips
101
+ }, locale), /*#__PURE__*/_jsx(ErrorDisplay, {
102
+ error: error,
103
+ onRetry: onRetry
104
+ })]
105
+ });
106
+ }
107
+ LoadingDisplayLayout.propTypes = {
108
+ // 基础信息
109
+ title: PropTypes.string.isRequired,
110
+ // 进度条数据
111
+ progress: PropTypes.number.isRequired,
112
+ elapsedTime: PropTypes.string.isRequired,
113
+ estimatedTime: PropTypes.string.isRequired,
114
+ // 动作描述数据
115
+ currentAction: PropTypes.string.isRequired,
116
+ // 动画控制
117
+ tipFlag: PropTypes.any,
118
+ // 可选项
119
+ error: PropTypes.string,
120
+ onRetry: PropTypes.func
121
+ };
122
+ export default LoadingDisplayLayout;
@@ -0,0 +1,45 @@
1
+ import LaunchResultMessage from '@blocklet/launcher-layout/lib/launch-result-message';
2
+ import Button from '@blocklet/launcher-ux/lib/button';
3
+ import PropTypes from 'prop-types';
4
+ import React, { useState } from 'react';
5
+
6
+ /**
7
+ * 重试错误消息组件
8
+ * 提供统一的错误展示和重试功能
9
+ */
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ export default function RetryErrorMessage({
12
+ title,
13
+ onRetry,
14
+ retryText
15
+ }) {
16
+ const [isLoading, setIsLoading] = useState(false);
17
+ const handleRetry = async e => {
18
+ e.preventDefault();
19
+ e.stopPropagation();
20
+ setIsLoading(true);
21
+ const result = onRetry();
22
+ if (result instanceof Promise) {
23
+ await result;
24
+ }
25
+ setIsLoading(false);
26
+ };
27
+ return /*#__PURE__*/_jsx(LaunchResultMessage, {
28
+ variant: "error",
29
+ title: title,
30
+ footer: /*#__PURE__*/_jsx(Button, {
31
+ size: "small",
32
+ style: {
33
+ marginTop: '-16px'
34
+ },
35
+ onClick: handleRetry,
36
+ loading: isLoading,
37
+ children: retryText
38
+ })
39
+ });
40
+ }
41
+ RetryErrorMessage.propTypes = {
42
+ title: PropTypes.string.isRequired,
43
+ onRetry: PropTypes.func.isRequired,
44
+ retryText: PropTypes.string.isRequired
45
+ };
@@ -0,0 +1,356 @@
1
+ import { useSetState } from 'ahooks';
2
+ import PropTypes from 'prop-types';
3
+ import React, { useEffect, useMemo } from 'react';
4
+ import { useNavigate } from 'react-router-dom';
5
+ import { LAUNCH_STATUS } from '@blocklet/launcher-util/es/constant';
6
+ import { useLocaleContext } from '../../contexts/locale';
7
+ import useRequest from '../../contexts/request';
8
+ import useSerialPolling from '../../hooks/use-serial-polling';
9
+ import { checkBlockletAccessible, getBlockletUrls, sortUrls, waitingForRaceAccessible } from '../../util';
10
+ import BaseServerlessLayout from './shared/base-serverless-layout';
11
+ import { AppSuccessDisplay, calculateEstimatedTime, useDisplayProgress, useElapsedTime, useFormatTime } from './shared/common-components';
12
+ import LoadingDisplayLayout from './shared/loading-display-layout';
13
+ import RetryErrorMessage from './shared/retry-error-message';
14
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
+ const CHECK_INTERVAL = 3000;
16
+ export default function LaunchServerless({
17
+ sessionId
18
+ }) {
19
+ const {
20
+ t
21
+ } = useLocaleContext();
22
+ const {
23
+ api
24
+ } = useRequest();
25
+ const navigate = useNavigate();
26
+ const [state, setState] = useSetState({
27
+ starting: true,
28
+ started: false,
29
+ checkingBlockletStatus: false,
30
+ checkingAccessible: false,
31
+ launchSession: null,
32
+ blockletInfo: null,
33
+ accessibleUrl: null,
34
+ urls: [],
35
+ error: '',
36
+ startTime: 0,
37
+ hasTryStart: false,
38
+ retryRequestCount: 0
39
+ });
40
+ const formatTime = useFormatTime();
41
+ const time = useElapsedTime(0);
42
+ const actions = useMemo(() => {
43
+ // 基础步骤时间
44
+ const steps = [{
45
+ message: t('startApp.waiting.starting'),
46
+ time: 5
47
+ }, {
48
+ message: t('startApp.waiting.parsing'),
49
+ time: 1
50
+ }, {
51
+ message: t('startApp.waiting.initializing'),
52
+ time: 3
53
+ }, {
54
+ message: t('startApp.waiting.initializingOwner'),
55
+ time: 2
56
+ }, {
57
+ message: t('startApp.waiting.creatingSecurityRules'),
58
+ time: 2
59
+ }, {
60
+ message: t('startApp.waiting.assigningDomain'),
61
+ time: 2
62
+ }, {
63
+ message: t('startApp.waiting.waitingForDomain'),
64
+ time: 10
65
+ }];
66
+
67
+ // 计算总时间
68
+ const totalTime = steps.reduce((acc, step) => acc + step.time, 0);
69
+
70
+ // 计算每个步骤的进度区间
71
+ let currentProgress = 0;
72
+ return steps.map(step => {
73
+ const progressPercent = step.time / totalTime * 100;
74
+ const range = [Math.round(currentProgress), Math.round(currentProgress + progressPercent)];
75
+ currentProgress += progressPercent;
76
+ return {
77
+ ...step,
78
+ range
79
+ };
80
+ });
81
+ }, [t]);
82
+ const estimatedTime = useMemo(() => {
83
+ const components = window.blockletMeta?.components || [];
84
+ const additionalTime = calculateEstimatedTime(components);
85
+ return actions.reduce((acc, action) => acc + action.time, 0) + additionalTime;
86
+ }, [actions]);
87
+ const displayProgress = useDisplayProgress(0, state.started ? 1 : estimatedTime);
88
+
89
+ // 根据当前进度获取对应的 action
90
+ const getCurrentAction = progress => {
91
+ const action = actions.find(({
92
+ range: [start, end]
93
+ }) => progress >= start && progress < end);
94
+ return action?.message || actions[actions.length - 1].message;
95
+ };
96
+ const checkOneAccessibleUrl = async urls => {
97
+ try {
98
+ const [accessibleUrl] = await waitingForRaceAccessible(urls);
99
+ return accessibleUrl;
100
+ } catch (error) {
101
+ console.error(error);
102
+ return null;
103
+ }
104
+ };
105
+ const getUrls = async blocklet => {
106
+ let {
107
+ urls
108
+ } = state;
109
+ if (urls.length === 0) {
110
+ urls = getBlockletUrls({
111
+ blocklet
112
+ });
113
+ const sortedUrls = await sortUrls(urls);
114
+ urls = sortedUrls;
115
+ if (urls.length > 0) {
116
+ setState({
117
+ urls
118
+ });
119
+ }
120
+ }
121
+ return urls;
122
+ };
123
+ const checkLaunchSession = async () => {
124
+ try {
125
+ const {
126
+ accessibleUrl
127
+ } = state;
128
+ if (!accessibleUrl) {
129
+ console.warn('the accessible url is not ready, retry getting accessible url');
130
+ setState({
131
+ checkingAccessible: true,
132
+ checkingBlockletStatus: false
133
+ });
134
+ return;
135
+ }
136
+ const blockletInfo = await checkBlockletAccessible(accessibleUrl);
137
+ if (!blockletInfo) {
138
+ console.warn('the blocklet is not ready or accessible url is not correct, retry getting accessible url');
139
+ return;
140
+ }
141
+ setState({
142
+ blockletInfo
143
+ });
144
+ if (blockletInfo.status === 'running') {
145
+ setState({
146
+ blockletInfo,
147
+ starting: false,
148
+ started: true,
149
+ checkingBlockletStatus: false,
150
+ checkingAccessible: false
151
+ });
152
+ } else if (blockletInfo.status === 'starting') {
153
+ if (!state.hasTryStart) {
154
+ setState(prev => {
155
+ if (Date.now() - prev.startTime > estimatedTime * 1000) {
156
+ api.post(`/launches/${sessionId}/start`);
157
+ return {
158
+ ...prev,
159
+ hasTryStart: true
160
+ };
161
+ }
162
+ return prev;
163
+ });
164
+ }
165
+ } else if (blockletInfo.status === 'stopped') {
166
+ api.post(`/launches/${sessionId}/start`);
167
+ } else {
168
+ console.warn('the blocklet is not installed!', blockletInfo.status, blockletInfo);
169
+ setState({
170
+ error: t('startApp.startFailed'),
171
+ starting: false,
172
+ checkingBlockletStatus: false
173
+ });
174
+ }
175
+ setState({
176
+ retryRequestCount: 0
177
+ });
178
+ } catch (error) {
179
+ setState(prev => {
180
+ if (prev.retryRequestCount < 5) {
181
+ console.warn('check launch session occurred error, retry', prev.retryRequestCount, error);
182
+ return {
183
+ ...prev,
184
+ retryRequestCount: prev.retryRequestCount + 1
185
+ };
186
+ }
187
+ return {
188
+ ...prev,
189
+ error: error.message,
190
+ starting: false,
191
+ retryRequestCount: 0
192
+ };
193
+ });
194
+ console.error(error);
195
+ }
196
+ };
197
+
198
+ // 串行检查,确保前一个请求完成后等待指定时间再发起下一个
199
+ useSerialPolling({
200
+ isEnabled: state.checkingBlockletStatus,
201
+ interval: CHECK_INTERVAL,
202
+ onPoll: checkLaunchSession
203
+ });
204
+
205
+ // 检查可用性 url
206
+ const checkAccessibleUrls = async () => {
207
+ try {
208
+ const urls = await getUrls(state.launchSession.blocklet);
209
+ const accessibleUrl = await checkOneAccessibleUrl(urls);
210
+ setState(prev => {
211
+ const obj = accessibleUrl ? {
212
+ ...prev,
213
+ checkingAccessible: false,
214
+ checkingBlockletStatus: true,
215
+ accessibleUrl
216
+ } : prev;
217
+ if (Date.now() - prev.startTime > estimatedTime * 1000) {
218
+ api.post(`/launches/${sessionId}/start`);
219
+ return {
220
+ ...obj,
221
+ hasTryStart: true
222
+ };
223
+ }
224
+ return obj;
225
+ });
226
+ } catch (error) {
227
+ // ignore
228
+ }
229
+ };
230
+ useSerialPolling({
231
+ isEnabled: state.checkingAccessible,
232
+ interval: 10000,
233
+ onPoll: checkAccessibleUrls
234
+ });
235
+ useEffect(() => {
236
+ const fetch = async (tryCount = 0) => {
237
+ setState({
238
+ startTime: Date.now()
239
+ });
240
+ try {
241
+ const {
242
+ data: {
243
+ launch: launchSession
244
+ }
245
+ } = await api.get(`/launches/${sessionId}?health=1`);
246
+ const urls = await getUrls(launchSession.blocklet);
247
+ launchSession.urls = urls;
248
+ [launchSession.appUrl] = urls;
249
+ setState({
250
+ launchSession,
251
+ urls
252
+ });
253
+ if (launchSession.status >= LAUNCH_STATUS.consuming) {
254
+ const notStarting = !['starting', 'running'].includes(launchSession.blockletStatus) && (!launchSession.metadata?.starting || launchSession.metadata.starting !== true);
255
+ if (notStarting) {
256
+ await api.post(`/launches/${sessionId}/start`).catch(error => {
257
+ console.error(error);
258
+ });
259
+ }
260
+ setState({
261
+ starting: true,
262
+ checkingAccessible: true
263
+ });
264
+ } else if (launchSession.status === LAUNCH_STATUS.allocated) {
265
+ navigate(`/install/${sessionId}${window.location.search || ''}`);
266
+ } else {
267
+ setState(prev => {
268
+ return {
269
+ ...prev,
270
+ starting: false,
271
+ started: false,
272
+ checkingBlockletStatus: false,
273
+ checkingAccessible: false,
274
+ error: t('startApp.installFailed')
275
+ };
276
+ });
277
+ }
278
+ } catch (error) {
279
+ if (tryCount > 0) {
280
+ setTimeout(() => {
281
+ fetch(tryCount - 1);
282
+ }, 1000);
283
+ } else {
284
+ setState({
285
+ error: error.message,
286
+ starting: false,
287
+ checkingBlockletStatus: false,
288
+ checkingAccessible: false
289
+ });
290
+ }
291
+ console.error('get launch session error', error);
292
+ }
293
+ };
294
+ if (window.blocklet.DEVELOPER_WORKFLOW_UI) {
295
+ setTimeout(() => {
296
+ fetch(0);
297
+ }, 10000);
298
+ } else {
299
+ fetch(0);
300
+ }
301
+ // eslint-disable-next-line react-hooks/exhaustive-deps
302
+ }, []);
303
+ const handleRetry = async () => {
304
+ if (['starting', 'stopped'].includes(state.blockletInfo.status)) {
305
+ await api.post(`/launches/${sessionId}/start`);
306
+ } else if (!state.blockletInfo && state.launchSession.status < LAUNCH_STATUS.allocated) {
307
+ await api.post('/serverless/allocate', {
308
+ launchId: sessionId
309
+ }).catch(error => {
310
+ console.error(error);
311
+ });
312
+ navigate(`/launch/${sessionId}${window.location.search || ''}`);
313
+ } else if (state.launchSession.status < LAUNCH_STATUS.consuming) {
314
+ await api.post('/serverless/install', {
315
+ launchId: sessionId
316
+ }).catch(error => {
317
+ console.error(error);
318
+ });
319
+ navigate(`/install/${sessionId}${window.location.search || ''}`);
320
+ } else {
321
+ await api.post(`/launches/${sessionId}/start`);
322
+ window.location.reload();
323
+ }
324
+ };
325
+ const showLoading = state.starting || displayProgress < 99;
326
+ const showSuccess = !showLoading && state.started && state.launchSession && displayProgress >= 99;
327
+ const showError = !showLoading && !showSuccess && state.error;
328
+ if (showError) {
329
+ console.error('showError', state.error);
330
+ }
331
+ return /*#__PURE__*/_jsxs(BaseServerlessLayout, {
332
+ title: t('startApp.pageTitle'),
333
+ children: [showLoading && /*#__PURE__*/_jsx(LoadingDisplayLayout, {
334
+ title: t('startApp.pageTitle'),
335
+ progress: state.started && displayProgress >= 99 ? 100 : displayProgress,
336
+ elapsedTime: formatTime(time),
337
+ estimatedTime: formatTime(estimatedTime),
338
+ currentAction: getCurrentAction(displayProgress),
339
+ error: null,
340
+ onRetry: null
341
+ }), showSuccess && /*#__PURE__*/_jsx(AppSuccessDisplay, {
342
+ accessibleUrl: state.accessibleUrl,
343
+ sessionId: sessionId,
344
+ blockletInfo: state.blockletInfo,
345
+ launchSession: state.launchSession,
346
+ urls: state.urls
347
+ }), showError && /*#__PURE__*/_jsx(RetryErrorMessage, {
348
+ title: t('startApp.startFailed'),
349
+ onRetry: handleRetry,
350
+ retryText: t('common.retry')
351
+ })]
352
+ });
353
+ }
354
+ LaunchServerless.propTypes = {
355
+ sessionId: PropTypes.string.isRequired
356
+ };
@@ -2,7 +2,7 @@ import { create as createRequestInstance } from '@blocklet/launcher-util/es/api'
2
2
  import get from 'lodash.get';
3
3
  import PropTypes from 'prop-types';
4
4
  import { createContext, useContext } from 'react';
5
- import joinUrl from 'url-join';
5
+ import { joinURL } from 'ufo';
6
6
  import { useLocaleContext } from './locale';
7
7
  import { useSessionContext } from './session';
8
8
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -22,7 +22,7 @@ export function RequestProvider({
22
22
  } = useLocaleContext();
23
23
  const configRequest = r => {
24
24
  r.interceptors.request.use(config => {
25
- config.url = joinUrl('/api', config.url);
25
+ config.url = joinURL('/api', config.url);
26
26
  if (!config.params) {
27
27
  config.params = {};
28
28
  }
@@ -0,0 +1,43 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ /**
4
+ * A hook for serial polling that ensures each request is completed before starting the next one.
5
+ * This prevents request overlapping and maintains a consistent interval between completed requests.
6
+ *
7
+ * @param {Object} options
8
+ * @param {boolean} options.isEnabled - Whether to enable the polling
9
+ * @param {number} options.interval - Time to wait after a request completes before starting the next one (in ms)
10
+ * @param {Function} options.onPoll - Async function to be called for each poll
11
+ */
12
+ export default function useSerialPolling({
13
+ isEnabled,
14
+ interval = 3000,
15
+ onPoll
16
+ }) {
17
+ const onPollRef = useRef(onPoll);
18
+ onPollRef.current = onPoll;
19
+ useEffect(() => {
20
+ let timeoutId;
21
+ let isActive = true;
22
+ const scheduleNextPoll = async () => {
23
+ if (!isActive || !isEnabled) return;
24
+ try {
25
+ await onPollRef.current();
26
+ } catch (error) {
27
+ console.error('Serial polling error:', error);
28
+ }
29
+
30
+ // Only schedule next poll if still active and enabled
31
+ if (isActive && isEnabled) {
32
+ timeoutId = setTimeout(scheduleNextPoll, interval);
33
+ }
34
+ };
35
+ if (isEnabled) {
36
+ scheduleNextPoll();
37
+ }
38
+ return () => {
39
+ isActive = false;
40
+ if (timeoutId) clearTimeout(timeoutId);
41
+ };
42
+ }, [isEnabled, interval]);
43
+ }
package/es/install.js ADDED
@@ -0,0 +1,28 @@
1
+ import { useEffect } from 'react';
2
+ import { useParams } from 'react-router-dom';
3
+ import InstallingServerless from './components/launch-serverless/install';
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(InstallingServerless, {
26
+ sessionId: sessionId
27
+ });
28
+ }
package/es/launch.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useEffect } from 'react';
2
2
  import { useParams, useSearchParams } from 'react-router-dom';
3
- import LaunchServerless from './components/launch-serverless';
3
+ import LaunchServerless from './components/launch-serverless/allocate';
4
4
  import LaunchDedicated from './components/launch-dedicated';
5
5
  import { useSessionContext } from './contexts/session';
6
6
  import { jsx as _jsx } from "react/jsx-runtime";