@blocklet/launcher-workflow 2.4.4 → 2.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/components/in-progress-session.js +1 -1
- package/es/components/launch-serverless/allocate.js +181 -0
- package/es/components/launch-serverless/install.js +203 -0
- package/es/components/launch-serverless/shared/base-serverless-layout.js +53 -0
- package/es/components/launch-serverless/shared/common-components.js +605 -0
- package/es/components/launch-serverless/shared/loading-display-layout.js +122 -0
- package/es/components/launch-serverless/shared/retry-error-message.js +45 -0
- package/es/components/launch-serverless/start-app.js +356 -0
- package/es/contexts/request.js +2 -2
- package/es/hooks/use-serial-polling.js +43 -0
- package/es/install.js +28 -0
- package/es/launch.js +1 -1
- package/es/locales/en.js +71 -14
- package/es/locales/zh.js +68 -12
- package/es/paid.js +1 -1
- package/es/prepare.js +1 -1
- package/es/start-app.js +28 -0
- package/es/util.js +181 -2
- package/lib/components/in-progress-session.js +3 -3
- package/lib/components/launch-serverless/allocate.js +198 -0
- package/lib/components/launch-serverless/install.js +223 -0
- package/lib/components/launch-serverless/shared/base-serverless-layout.js +59 -0
- package/lib/components/launch-serverless/shared/common-components.js +635 -0
- package/lib/components/launch-serverless/shared/loading-display-layout.js +131 -0
- package/lib/components/launch-serverless/shared/retry-error-message.js +52 -0
- package/lib/components/launch-serverless/start-app.js +369 -0
- package/lib/contexts/request.js +2 -2
- package/lib/hooks/use-serial-polling.js +49 -0
- package/lib/install.js +35 -0
- package/lib/launch.js +2 -2
- package/lib/locales/en.js +71 -14
- package/lib/locales/zh.js +68 -12
- package/lib/paid.js +2 -2
- package/lib/prepare.js +2 -2
- package/lib/start-app.js +35 -0
- package/lib/util.js +214 -11
- package/package.json +16 -13
- package/es/components/launch-serverless.js +0 -115
- 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
|
+
};
|
package/lib/contexts/request.js
CHANGED
|
@@ -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
|
|
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,
|
|
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
|
|
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)(
|
|
36
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_allocate.default, {
|
|
37
37
|
sessionId: sessionId
|
|
38
38
|
});
|
|
39
39
|
}
|