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