From 9cd470507c3720be2f4d73ecf433533a1124f9ef Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Thu, 1 Aug 2024 14:44:11 -0400 Subject: [PATCH 01/50] fix(striker-ui): add mini switch to host network config --- striker-ui/components/NetworkInitForm.tsx | 37 ++++++++ striker-ui/components/PrepareNetworkForm.tsx | 90 +++++++++++--------- 2 files changed, 88 insertions(+), 39 deletions(-) diff --git a/striker-ui/components/NetworkInitForm.tsx b/striker-ui/components/NetworkInitForm.tsx index be545fe33..12342ee10 100644 --- a/striker-ui/components/NetworkInitForm.tsx +++ b/striker-ui/components/NetworkInitForm.tsx @@ -642,6 +642,7 @@ const NetworkInitForm = forwardRef< expectHostDetail?: boolean; hostDetail?: APIHostDetail; hostSequence?: string; + mini?: boolean; toggleSubmitDisabled?: (testResult: boolean) => void; } >( @@ -650,6 +651,7 @@ const NetworkInitForm = forwardRef< expectHostDetail = false, hostDetail, hostSequence, + mini, toggleSubmitDisabled, }, ref, @@ -1366,6 +1368,40 @@ const NetworkInitForm = forwardRef< testInputToToggleSubmitDisabled, ]); + useEffect((): void => { + if (mini) { + setNetworkInputs((previous) => + previous.map((value) => { + const shallow = { ...value }; + + shallow.isRequired = false; + + return shallow; + }), + ); + + return; + } + + setNetworkInputs((previous) => + previous.map((value) => { + const shallow = { ...value }; + + const found = initRequiredNetworks.find( + (current) => + shallow.type === current.type && + shallow.typeCount === current.typeCount, + ); + + if (found) { + shallow.isRequired = true; + } + + return shallow; + }), + ); + }, [initRequiredNetworks, mini]); + useImperativeHandle( ref, () => ({ @@ -1638,6 +1674,7 @@ NetworkInitForm.defaultProps = { expectHostDetail: false, hostDetail: undefined, hostSequence: undefined, + mini: false, toggleSubmitDisabled: undefined, }; NetworkInitForm.displayName = 'NetworkInitForm'; diff --git a/striker-ui/components/PrepareNetworkForm.tsx b/striker-ui/components/PrepareNetworkForm.tsx index 2518938b5..41cbdf0df 100644 --- a/striker-ui/components/PrepareNetworkForm.tsx +++ b/striker-ui/components/PrepareNetworkForm.tsx @@ -17,6 +17,7 @@ import NetworkInitForm, { import OutlinedInputWithLabel from './OutlinedInputWithLabel'; import { Panel, PanelHeader } from './Panels'; import Spinner from './Spinner'; +import SwitchWithLabel from './SwitchWithLabel'; import { buildPeacefulStringTestBatch } from '../lib/test_input'; import { HeaderText } from './Text'; import useConfirmDialogProps from '../hooks/useConfirmDialogProps'; @@ -114,6 +115,8 @@ const PrepareNetworkForm: FC = ({ string | undefined >(); + const [mini, setMini] = useState(false); + const { buildFinishInputTestBatchFunction, buildInputFirstRenderFunction, @@ -149,12 +152,13 @@ const PrepareNetworkForm: FC = ({ expectHostDetail hostDetail={hostDetail} ref={netconfFormRef} + mini={mini} toggleSubmitDisabled={(valid) => { setValidity(INPUT_GROUP_ID_PREP_NET_NETCONF, valid); }} /> ), - [hostDetail, setValidity], + [hostDetail, mini, setValidity], ); const generalInputMessageArea = useMemo( () => ( @@ -220,36 +224,43 @@ const PrepareNetworkForm: FC = ({ confirmDialogRef.current.setOpen?.call(null, true); }} > - - } - inputTestBatch={buildPeacefulStringTestBatch( - INPUT_LABEL_PREP_NET_HOST_NAME, - () => { - setMessage(INPUT_ID_PREP_NET_HOST_NAME); - }, - { - onFinishBatch: buildFinishInputTestBatchFunction( - INPUT_ID_PREP_NET_HOST_NAME, - ), - }, - (message) => { - setMessage(INPUT_ID_PREP_NET_HOST_NAME, { - children: message, - }); - }, - )} - onFirstRender={buildInputFirstRenderFunction( - INPUT_ID_PREP_NET_HOST_NAME, - )} - required - /> + + + } + inputTestBatch={buildPeacefulStringTestBatch( + INPUT_LABEL_PREP_NET_HOST_NAME, + () => { + setMessage(INPUT_ID_PREP_NET_HOST_NAME); + }, + { + onFinishBatch: buildFinishInputTestBatchFunction( + INPUT_ID_PREP_NET_HOST_NAME, + ), + }, + (message) => { + setMessage(INPUT_ID_PREP_NET_HOST_NAME, { + children: message, + }); + }, + )} + onFirstRender={buildInputFirstRenderFunction( + INPUT_ID_PREP_NET_HOST_NAME, + )} + required + /> + setMini((previous) => !previous)} + /> + {generalInputMessageArea} {netconfForm} @@ -264,20 +275,21 @@ const PrepareNetworkForm: FC = ({ return result; }, [ - isLoadingHostDetail, - fatalErrorMessage, - panelHeaderElement, - hostDetail?.hostName, - hostDetail?.shortHostName, buildFinishInputTestBatchFunction, buildInputFirstRenderFunction, + fatalErrorMessage, generalInputMessageArea, - netconfForm, + hostDetail?.hostName, + hostDetail?.shortHostName, + hostUUID, isFormInvalid, + isLoadingHostDetail, + mini, + netconfForm, + panelHeaderElement, setConfirmDialogProps, - submitForm, - hostUUID, setMessage, + submitForm, ]); const getHostDetail = useCallback( From a00f56b5e8cf59abae26563439c4e79b83c29652 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Thu, 1 Aug 2024 22:39:13 -0400 Subject: [PATCH 02/50] docs(striker-ui): note config param to enable mini switch --- striker-ui/components/PrepareNetworkForm.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/striker-ui/components/PrepareNetworkForm.tsx b/striker-ui/components/PrepareNetworkForm.tsx index 41cbdf0df..e28340aec 100644 --- a/striker-ui/components/PrepareNetworkForm.tsx +++ b/striker-ui/components/PrepareNetworkForm.tsx @@ -255,6 +255,7 @@ const PrepareNetworkForm: FC = ({ )} required /> + {/* Look for the sys::minimal-network::enable = 0/1 config in /etc/anvil.conf to decide whether to show this switch */} Date: Tue, 13 Aug 2024 01:52:00 -0400 Subject: [PATCH 03/50] fix(striker-ui): record changed fields in formik utils --- striker-ui/hooks/useFormikUtils.ts | 48 +++++++++++++++++++----------- striker-ui/types/FormikUtils.d.ts | 1 + 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/striker-ui/hooks/useFormikUtils.ts b/striker-ui/hooks/useFormikUtils.ts index 5bb441634..050d425f0 100644 --- a/striker-ui/hooks/useFormikUtils.ts +++ b/striker-ui/hooks/useFormikUtils.ts @@ -1,26 +1,27 @@ -import { FormikConfig, FormikValues, useFormik } from 'formik'; -import { isEqual, isObject } from 'lodash'; +import { FormikConfig, FormikValues, getIn, setIn, useFormik } from 'formik'; +import { isEqual, isObject, isString } from 'lodash'; import { useCallback, useMemo, useState } from 'react'; import debounce from '../lib/debounce'; import getFormikErrorMessages from '../lib/getFormikErrorMessages'; -const isChainEqual = ( - chain: string[], - current: Tree, - initial: Tree, +const isEqualIn = ( + source: Tree, + path: string | string[], + target: Tree, ): boolean => { + const chain = isString(path) ? path.split('.') : path; const [part, ...remain] = chain; - if (!(part in current)) { + if (!(part in source)) { return false; } - const a = current[part]; - const b = initial[part]; + const a = source[part]; + const b = target[part]; if (isObject(a) && isObject(b) && remain.length) { - return isChainEqual(remain, a as Tree, b as Tree); + return isEqualIn(a as Tree, remain, b as Tree); } return !isEqual(a, b); @@ -29,16 +30,18 @@ const isChainEqual = ( const useFormikUtils = ( formikConfig: FormikConfig, ): FormikUtils => { + const [changed, setChanged] = useState>({}); const [changing, setChanging] = useState(false); const formik = useFormik({ ...formikConfig }); const getFieldChanged = useCallback( - (field: string) => { - const parts = field.split('.'); + (field: string): boolean => getIn(changed, field), + [changed], + ); - return isChainEqual(parts, formik.values, formik.initialValues); - }, + const getFieldIsDiff = useCallback( + (field: string) => isEqualIn(formik.values, field, formik.initialValues), [formik.initialValues, formik.values], ); @@ -48,8 +51,18 @@ const useFormikUtils = ( setChanging(false); }); - return (...args: Parameters) => { + return (...args: Parameters) => { setChanging(true); + + const [maybeEvent] = args; + + if (!isString(maybeEvent)) { + const event = maybeEvent as React.ChangeEvent<{ name: string }>; + const target = event.target ? event.target : event.currentTarget; + + setChanged((prev) => setIn(prev, target.name, true)); + } + base(...args); }; @@ -78,15 +91,16 @@ const useFormikUtils = ( const formikErrors = useMemo( () => getFormikErrorMessages(formik.errors, { - skip: (field) => !getFieldChanged(field), + skip: (field) => !getFieldIsDiff(field), }), - [formik.errors, getFieldChanged], + [formik.errors, getFieldIsDiff], ); return { disabledSubmit, formik, formikErrors, + getFieldChanged, handleChange: debounceHandleChange, }; }; diff --git a/striker-ui/types/FormikUtils.d.ts b/striker-ui/types/FormikUtils.d.ts index 878b012c4..8467b62de 100644 --- a/striker-ui/types/FormikUtils.d.ts +++ b/striker-ui/types/FormikUtils.d.ts @@ -15,5 +15,6 @@ type FormikUtils = { disabledSubmit: boolean; formik: Formik; formikErrors: Messages; + getFieldChanged: (field: string) => boolean; handleChange: FormikChangeHandler; }; From 9a4f1442d5d2c2d816733130c5d999b33187b7cd Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 13 Aug 2024 01:53:39 -0400 Subject: [PATCH 04/50] fix(striker-ui): draft new striker init form --- .../StrikerInit/StrikerInitForm.tsx | 286 ++++++++++++++++++ .../StrikerInit/strikerInitSchema.ts | 16 + striker-ui/types/StrikerInit.d.ts | 9 + 3 files changed, 311 insertions(+) create mode 100644 striker-ui/components/StrikerInit/StrikerInitForm.tsx create mode 100644 striker-ui/components/StrikerInit/strikerInitSchema.ts create mode 100644 striker-ui/types/StrikerInit.d.ts diff --git a/striker-ui/components/StrikerInit/StrikerInitForm.tsx b/striker-ui/components/StrikerInit/StrikerInitForm.tsx new file mode 100644 index 000000000..87b7d4c52 --- /dev/null +++ b/striker-ui/components/StrikerInit/StrikerInitForm.tsx @@ -0,0 +1,286 @@ +import { Grid } from '@mui/material'; +import { FC, useCallback, useMemo, useRef } from 'react'; + +import useFormikUtils from '../../hooks/useFormikUtils'; +import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; +import INPUT_TYPES from '../../lib/consts/INPUT_TYPES'; +import MessageGroup from '../MessageGroup'; +import strikerInitSchema from './strikerInitSchema'; +import ActionGroup from '../ActionGroup'; +import UncontrolledInput from '../UncontrolledInput'; +import pad from '../../lib/pad'; + +const guessHostName = ( + orgPrefix: string, + hostNumber: string, + domainName: string, +): string => + [orgPrefix, hostNumber, domainName].every((value) => value.length > 0) + ? `${orgPrefix}-striker${pad(hostNumber)}.${domainName}` + : ''; + +const guessOrgPrefix = (orgName: string, max = 5): string => { + const words: string[] = orgName + .split(/\s+/) + .filter((word) => !/^(?:and|of)$/.test(word)) + .slice(0, max); + + let result = ''; + + if (words.length > 1) { + result = words + .map((word) => word.substring(0, 1).toLocaleLowerCase()) + .join(''); + } else if (words.length === 1) { + result = words[0].substring(0, max).toLocaleLowerCase(); + } + + return result; +}; + +const StrikerInitForm: FC = () => { + const orgPrefixInputRef = + useRef>(null); + + const hostNameInputRef = + useRef>(null); + + const { + disabledSubmit, + formik, + formikErrors, + getFieldChanged, + handleChange, + } = useFormikUtils({ + initialValues: { + adminPassword: '', + confirmAdminPassword: '', + domainName: '', + hostName: '', + hostNumber: '', + organizationName: '', + organizationPrefix: '', + }, + onSubmit: (values, { setSubmitting }) => { + setSubmitting(false); + }, + validationSchema: strikerInitSchema, + }); + + const adminPasswordChain = useMemo(() => `adminPassword`, []); + const confirmAdminPasswordChain = useMemo(() => `confirmAdminPassword`, []); + const domainNameChain = useMemo(() => `domainName`, []); + const hostNameChain = useMemo(() => `hostName`, []); + const hostNumberChain = useMemo(() => `hostNumber`, []); + const orgNameChain = useMemo(() => `organizationName`, []); + const orgPrefixChain = useMemo(() => `organizationPrefix`, []); + + const buildHostNameGuesser = useCallback( + (key: string) => + (event: React.FocusEvent) => { + if (getFieldChanged(hostNameChain)) return; + + const { + target: { value }, + } = event; + + let { + values: { domainName, hostNumber, organizationPrefix }, + } = formik; + + switch (key) { + case domainNameChain: + domainName = value; + break; + case hostNumberChain: + hostNumber = value; + break; + case orgPrefixChain: + organizationPrefix = value; + break; + default: + break; + } + + const guess = guessHostName(organizationPrefix, hostNumber, domainName); + + hostNameInputRef.current?.set(guess); + + formik.setFieldValue(hostNameChain, guess); + }, + [ + domainNameChain, + formik, + getFieldChanged, + hostNameChain, + hostNumberChain, + orgPrefixChain, + ], + ); + + return ( + { + event.preventDefault(); + + formik.handleSubmit(event); + }} + spacing="1em" + > + + + + { + if (getFieldChanged(orgPrefixChain)) return; + + const { + target: { value }, + } = event; + + const guess = guessOrgPrefix(value); + + orgPrefixInputRef.current?.set(guess); + + formik.setFieldValue(orgPrefixChain, guess); + }} + onChange={handleChange} + required + value={formik.values.organizationName} + /> + } + /> + + + + } + ref={orgPrefixInputRef} + /> + + + + } + /> + + + + + + + + } + /> + + + + } + ref={hostNameInputRef} + /> + + + + + + + + } + /> + + + + } + /> + + + + + + + + + + + ); +}; + +export default StrikerInitForm; diff --git a/striker-ui/components/StrikerInit/strikerInitSchema.ts b/striker-ui/components/StrikerInit/strikerInitSchema.ts new file mode 100644 index 000000000..ecf33c8ce --- /dev/null +++ b/striker-ui/components/StrikerInit/strikerInitSchema.ts @@ -0,0 +1,16 @@ +import * as yup from 'yup'; + +const strikerInitSchema = yup.object({ + adminPassword: yup.string().required(), + confirmAdminPassword: yup + .string() + .oneOf([yup.ref('adminPassword')]) + .required(), + domainName: yup.string().required(), + hostName: yup.string().required(), + hostNumber: yup.number().required(), + organizationName: yup.string().required(), + organizationPrefix: yup.string().min(1).max(5).required(), +}); + +export default strikerInitSchema; diff --git a/striker-ui/types/StrikerInit.d.ts b/striker-ui/types/StrikerInit.d.ts new file mode 100644 index 000000000..1df727d27 --- /dev/null +++ b/striker-ui/types/StrikerInit.d.ts @@ -0,0 +1,9 @@ +type StrikerInitFormikValues = { + adminPassword: string; + confirmAdminPassword: string; + domainName: string; + hostName: string; + hostNumber: string; + organizationName: string; + organizationPrefix: string; +}; From 918a42bdd7ca32f6194acfae8ca5306538ef6df0 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 10 Sep 2024 19:09:31 -0400 Subject: [PATCH 05/50] fix(striker-ui-api): change /network-interface output --- .../src/lib/fconfig/buildNetworkLinkConfig.ts | 4 +- .../network-interface/getNetworkInterface.ts | 93 +++++++++++-------- .../src/types/ApiNetworkInterface.d.ts | 19 ++-- 3 files changed, 69 insertions(+), 47 deletions(-) diff --git a/striker-ui-api/src/lib/fconfig/buildNetworkLinkConfig.ts b/striker-ui-api/src/lib/fconfig/buildNetworkLinkConfig.ts index 366cf9a25..6b69ee55c 100644 --- a/striker-ui-api/src/lib/fconfig/buildNetworkLinkConfig.ts +++ b/striker-ui-api/src/lib/fconfig/buildNetworkLinkConfig.ts @@ -7,12 +7,12 @@ export const buildNetworkLinkConfig = ( ) => interfaces.reduce((previous, iface, index) => { if (iface) { - const { networkInterfaceMACAddress } = iface; + const { mac } = iface; const linkNumber = index + 1; previous[ cvar(configStep, `${networkShortName}_link${linkNumber}_mac_to_set`) - ] = { step: configStep, value: networkInterfaceMACAddress }; + ] = { step: configStep, value: mac }; } return previous; diff --git a/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts b/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts index 31e7fefc5..7c02203b1 100644 --- a/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts +++ b/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts @@ -1,60 +1,75 @@ import { DELETED, LOCAL } from '../../consts'; import buildGetRequestHandler from '../buildGetRequestHandler'; +import { buildQueryResultReducer } from '../../buildQueryResultModifier'; import { toHostUUID } from '../../convertHostUUID'; export const getNetworkInterface = buildGetRequestHandler( (request, buildQueryOptions) => { const { - params: { hostUUID: rHostUUID = LOCAL }, + params: { hostUUID: rHostUuid = LOCAL }, } = request; - const hostUUID = toHostUUID(rHostUUID); + const hostUuid = toHostUUID(rHostUuid); const query = ` SELECT - network_interface_uuid, - network_interface_mac_address, - network_interface_name, + a.network_interface_uuid, + a.network_interface_mac_address, + a.network_interface_name, CASE - WHEN network_interface_link_state = '1' - AND network_interface_operational = 'up' + WHEN a.network_interface_link_state = '1' + AND a.network_interface_operational = 'up' THEN 'up' ELSE 'down' - END AS network_interface_state, - network_interface_speed, - ROW_NUMBER() OVER(ORDER BY modified_date ASC) AS network_interface_order - FROM network_interfaces - WHERE network_interface_operational != '${DELETED}' - AND network_interface_name NOT SIMILAR TO '(vnet\\d+|virbr\\d+-nic)%' - AND network_interface_host_uuid = '${hostUUID}';`; + END AS iface_state, + a.network_interface_speed, + ROW_NUMBER() OVER(ORDER BY a.modified_date ASC) AS iface_order, + b.ip_address_address, + b.ip_address_subnet_mask, + b.ip_address_gateway, + b.ip_address_dns + FROM network_interfaces AS a + LEFT JOIN ip_addresses AS b + ON b.ip_address_on_uuid = a.network_interface_uuid + WHERE a.network_interface_operational != '${DELETED}' + AND a.network_interface_name NOT SIMILAR TO '(vnet\\d+|virbr\\d+-nic)%' + AND a.network_interface_host_uuid = '${hostUuid}';`; if (buildQueryOptions) { - buildQueryOptions.afterQueryReturn = (queryStdout) => { - let result = queryStdout; - - if (queryStdout instanceof Array) { - result = queryStdout.map( - ([ - networkInterfaceUUID, - networkInterfaceMACAddress, - networkInterfaceName, - networkInterfaceState, - networkInterfaceSpeed, - networkInterfaceOrder, - ]) => ({ - networkInterfaceUUID, - networkInterfaceMACAddress, - networkInterfaceName, - networkInterfaceState, - networkInterfaceSpeed, - networkInterfaceOrder, - }), - ); - } - - return result; - }; + buildQueryOptions.afterQueryReturn = + buildQueryResultReducer( + (previous, row) => { + const [ + uuid, + mac, + name, + state, + speed, + order, + ip, + subnetMask, + gateway, + dns, + ] = row; + + previous[uuid] = { + dns, + gateway, + ip, + mac, + name, + order: Number(order), + speed: Number(speed), + state, + subnetMask, + uuid, + }; + + return previous; + }, + {}, + ); } return query; diff --git a/striker-ui-api/src/types/ApiNetworkInterface.d.ts b/striker-ui-api/src/types/ApiNetworkInterface.d.ts index 12c1cd994..6d1468066 100644 --- a/striker-ui-api/src/types/ApiNetworkInterface.d.ts +++ b/striker-ui-api/src/types/ApiNetworkInterface.d.ts @@ -1,8 +1,15 @@ type NetworkInterfaceOverview = { - networkInterfaceUUID: string; - networkInterfaceMACAddress: string; - networkInterfaceName: string; - networkInterfaceState: string; - networkInterfaceSpeed: number; - networkInterfaceOrder: number; + dns: null | string; + gateway: null | string; + ip: null | string; + mac: string; + name: string; + order: number; + // Unit: Mbps + speed: number; + state: string; + subnetMask: null | string; + uuid: string; }; + +type NetworkInterfaceOverviewList = Record; From 5d2288d56e94a66a2cc729e65f76a6532c501dc1 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 18 Sep 2024 16:02:01 -0400 Subject: [PATCH 06/50] fix(striker-ui): add page body --- striker-ui/components/PageBody.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 striker-ui/components/PageBody.tsx diff --git a/striker-ui/components/PageBody.tsx b/striker-ui/components/PageBody.tsx new file mode 100644 index 000000000..2b3f502b0 --- /dev/null +++ b/striker-ui/components/PageBody.tsx @@ -0,0 +1,18 @@ +import { Grid } from '@mui/material'; +import { FC } from 'react'; + +const PageBody: FC = (props) => { + const { children } = props; + + return ( + + + + {children} + + + + ); +}; + +export default PageBody; From dd834acba944235674cda695c0e55cd7ee7ed4f2 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 18 Sep 2024 16:03:35 -0400 Subject: [PATCH 07/50] fix(striker-ui): add iface drag handle --- .../HostNetInit/IfaceDragHandle.tsx | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 striker-ui/components/HostNetInit/IfaceDragHandle.tsx diff --git a/striker-ui/components/HostNetInit/IfaceDragHandle.tsx b/striker-ui/components/HostNetInit/IfaceDragHandle.tsx new file mode 100644 index 000000000..489ca5eba --- /dev/null +++ b/striker-ui/components/HostNetInit/IfaceDragHandle.tsx @@ -0,0 +1,37 @@ +import { Box, styled } from '@mui/material'; + +import { BLUE, GREY } from '../../lib/consts/DEFAULT_THEME'; + +const PREFIX = 'IfaceDragHandle'; + +const ifaceDragHandleClasses = { + applied: `${PREFIX}-applied`, +}; + +const IfaceDragHandle = styled(Box)({ + alignItems: 'center', + display: 'flex', + flexDirection: 'row', + + '&:hover': { + cursor: 'grab', + }, + + '& > svg': { + color: GREY, + }, + + [`&.${ifaceDragHandleClasses.applied}`]: { + '&:hover': { + cursor: 'auto', + }, + + '& > svg': { + color: BLUE, + }, + }, +}); + +export { ifaceDragHandleClasses }; + +export default IfaceDragHandle; From f09bc5464b53fe25a2284d79fad5e5d6e9a908cb Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 18 Sep 2024 16:04:18 -0400 Subject: [PATCH 08/50] fix(striker-ui): add drag area --- .../components/HostNetInit/DragArea.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 striker-ui/components/HostNetInit/DragArea.tsx diff --git a/striker-ui/components/HostNetInit/DragArea.tsx b/striker-ui/components/HostNetInit/DragArea.tsx new file mode 100644 index 000000000..cd995bdc9 --- /dev/null +++ b/striker-ui/components/HostNetInit/DragArea.tsx @@ -0,0 +1,20 @@ +import { Box, styled } from '@mui/material'; + +const PREFIX = 'DragArea'; + +const dragAreaClasses = { + dragging: `${PREFIX}-dragging`, +}; + +const DragArea = styled(Box)({ + position: 'relative', + + [`&.${dragAreaClasses.dragging}`]: { + cursor: 'grabbing', + userSelect: 'none', + }, +}); + +export { dragAreaClasses }; + +export default DragArea; From c1a5a66f1a4cd2be50836a04a3efb9432757b4f3 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 18 Sep 2024 16:07:05 -0400 Subject: [PATCH 09/50] fix(striker-ui): add draggable data grid --- .../components/HostNetInit/DragDataGrid.tsx | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 striker-ui/components/HostNetInit/DragDataGrid.tsx diff --git a/striker-ui/components/HostNetInit/DragDataGrid.tsx b/striker-ui/components/HostNetInit/DragDataGrid.tsx new file mode 100644 index 000000000..0a2e68aea --- /dev/null +++ b/striker-ui/components/HostNetInit/DragDataGrid.tsx @@ -0,0 +1,34 @@ +import { iconButtonClasses, styled } from '@mui/material'; +import { DataGrid, gridClasses } from '@mui/x-data-grid'; + +import { GREY } from '../../lib/consts/DEFAULT_THEME'; + +const PREFIX = 'DragDataGrid'; + +const dragDataGridClasses = { + draggable: `${PREFIX}-draggable`, +}; + +const DragDataGrid = styled(DataGrid)({ + color: GREY, + + [`& .${iconButtonClasses.root}`]: { + color: 'inherit', + }, + + [`& .${gridClasses.cell}:focus`]: { + outline: 'none', + }, + + [`& .${gridClasses.row}.${dragDataGridClasses.draggable}:hover`]: { + cursor: 'grab', + + [`& .${gridClasses.cell} p`]: { + cursor: 'auto', + }, + }, +}); + +export { dragDataGridClasses }; + +export default DragDataGrid; From d9cba576ef8ef8bb3ca7e103e8974bada6ed71c3 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 25 Sep 2024 12:14:02 -0400 Subject: [PATCH 10/50] fix(striker-ui): add initial host network init form components --- .../HostNetInit/HostNetInitInputGroup.tsx | 381 ++++++++++++++++++ .../HostNetInit/HostNetInputGroup.tsx | 248 ++++++++++++ .../components/HostNetInit/SimpleIface.tsx | 71 ++++ .../HostNetInit/hostNetInitSchema.ts | 23 ++ .../components/HostNetInit/hostNetSchema.ts | 24 ++ striker-ui/types/APINetworkInterface.d.ts | 21 + striker-ui/types/HostNetInit.d.ts | 71 ++++ 7 files changed, 839 insertions(+) create mode 100644 striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx create mode 100644 striker-ui/components/HostNetInit/HostNetInputGroup.tsx create mode 100644 striker-ui/components/HostNetInit/SimpleIface.tsx create mode 100644 striker-ui/components/HostNetInit/hostNetInitSchema.ts create mode 100644 striker-ui/components/HostNetInit/hostNetSchema.ts create mode 100644 striker-ui/types/HostNetInit.d.ts diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx new file mode 100644 index 000000000..de77c173a --- /dev/null +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -0,0 +1,381 @@ +import { + Check as MuiCheckIcon, + DragHandle as MuiDragHandleIcon, +} from '@mui/icons-material'; +import { Box, BoxProps, Grid } from '@mui/material'; +import { capitalize, cloneDeep } from 'lodash'; +import { FC, useMemo, useState } from 'react'; +import { v4 as uuidv4 } from 'uuid'; + +import DragArea, { dragAreaClasses } from './DragArea'; +import DragDataGrid, { dragDataGridClasses } from './DragDataGrid'; +import HostNetInputGroup from './HostNetInputGroup'; +import IfaceDragHandle, { ifaceDragHandleClasses } from './IfaceDragHandle'; +import IconButton from '../IconButton'; +import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; +import { FloatingIface } from './SimpleIface'; +import Spinner from '../Spinner'; +import { MonoText } from '../Text'; +import UncontrolledInput from '../UncontrolledInput'; +import useFetch from '../../hooks/useFetch'; + +const HostNetInitInputGroup = ( + ...[props]: Parameters>> +): ReturnType>> => { + const { formikUtils, host, onFetchSuccess } = props; + + const { formik, getFieldChanged, handleChange } = formikUtils; + + const [ifaceHeld, setIfaceHeld] = useState(); + + const [dragPosition, setDragPosition] = useState({ + x: 0, + y: 0, + }); + + const ifacesApplied = useMemo( + () => + Object.values(formik.values.networkInit.networks).reduce< + Record + >((applied, network) => { + network.interfaces.forEach((uuid) => { + if (uuid.length > 0) applied[uuid] = true; + }); + + return applied; + }, {}), + [formik.values.networkInit.networks], + ); + + const hostNets = useMemo( + () => Object.entries(formik.values.networkInit.networks), + [formik.values.networkInit.networks], + ); + + const chains = useMemo(() => { + const base = 'networkInit'; + + return { + dns: `${base}.dns`, + gateway: `${base}.gateway`, + networks: `${base}.networks`, + }; + }, []); + + const { data: ifaces } = useFetch( + `/init/network-interface/${host.uuid}`, + { + onSuccess: (data) => { + const values = Object.values(data); + + const ifnCandidates = values.filter( + (value) => + !ifacesApplied[value.uuid] && + value.ip && + !/^10\.[12]/.test(value.ip), + ); + + if (host.sequence > 0) { + const bcnSlots = hostNets.filter(([, value]) => value.type === 'bcn'); + + bcnSlots.forEach(([key, slot]) => { + const chain = `${chains.networks}.${key}`; + + if (getFieldChanged(chain)) return; + + const slotClone = cloneDeep(slot); + + slotClone.ip = `10.20${slot.sequence}.4.${host.sequence}`; + slotClone.subnetMask = '255.255.0.0'; + + formik.setFieldValue(chain, slotClone, true); + }); + } + + const ifnSlots = hostNets.filter(([, value]) => value.type === 'ifn'); + + // eslint-disable-next-line complexity + ifnSlots.forEach(([key, slot]) => { + const chain = `${chains.networks}.${key}`; + + if (slot.interfaces[0] !== '' || getFieldChanged(chain)) { + return; + } + + const slotClone = cloneDeep(slot); + const candidate = ifnCandidates.shift(); + + if (!candidate) return; + + slotClone.interfaces[0] = candidate.uuid; + slotClone.ip = candidate.ip || ''; + slotClone.subnetMask = candidate.subnetMask || ''; + + formik.setFieldValue(chain, slotClone, true); + formik.setFieldValue(chains.dns, candidate.dns || '', true); + formik.setFieldValue(chains.gateway, candidate.gateway || '', true); + }); + + onFetchSuccess?.call(null, data); + }, + refreshInterval: 2000, + }, + ); + + const ifacesValue = useMemo(() => ifaces && Object.values(ifaces), [ifaces]); + + const dragAreaProps = useMemo(() => { + if (!ifaceHeld) return undefined; + + return { + className: dragAreaClasses.dragging, + onMouseLeave: () => setIfaceHeld(undefined), + onMouseMove: (event) => { + const { + currentTarget, + nativeEvent: { clientX, clientY }, + } = event; + + const { left, top } = currentTarget.getBoundingClientRect(); + + setDragPosition({ + x: clientX - left, + y: clientY - top, + }); + }, + onMouseUp: () => setIfaceHeld(undefined), + }; + }, [ifaceHeld]); + + if (!ifaces || !ifacesValue) { + return ; + } + + return ( + + + { + const { clientX, clientY, currentTarget } = event; + + const { left, top } = currentTarget.getBoundingClientRect(); + + setDragPosition({ + x: clientX - left, + y: clientY - top, + }); + }} + {...dragAreaProps} + > + {ifaceHeld && ( + + )} + { + const { row } = cell; + + let className; + let handleMouseDown: + | React.MouseEventHandler + | undefined = () => { + setIfaceHeld(row.uuid); + }; + let icon = ; + + if (ifacesApplied[row.uuid]) { + className = ifaceDragHandleClasses.applied; + handleMouseDown = undefined; + icon = ; + } + + return ( + + {icon} + + ); + }, + sortable: false, + width: 1, + }, + { + field: 'name', + flex: 1, + headerName: 'Name', + }, + { + field: 'mac', + flex: 1, + headerName: 'MAC', + renderCell: (cell) => { + const { value } = cell; + + return {value}; + }, + }, + { + field: 'state', + flex: 1, + headerName: 'State', + renderCell: (cell) => { + const { value } = cell; + + return capitalize(value); + }, + }, + { + field: 'speed', + flex: 1, + headerName: 'Speed', + renderCell: (cell) => { + const { value } = cell; + + return `${value} Mbps`; + }, + }, + { + field: 'order', + flex: 1, + headerName: 'Order', + }, + ]} + componentsProps={{ + row: { + onMouseDown: ( + event: React.MouseEvent, + ): void => { + const { target } = event; + + const element = target as HTMLDivElement; + + const uuid = element.parentElement?.dataset.id; + + if (!uuid) return; + + if (ifacesApplied[uuid]) return; + + setIfaceHeld(uuid); + }, + }, + }} + disableColumnMenu + disableSelectionOnClick + getRowClassName={(cell) => { + const { row } = cell; + + return ifaceHeld || ifacesApplied[row.uuid] + ? '' + : dragDataGridClasses.draggable; + }} + getRowId={(row) => row.uuid} + hideFooter + initialState={{ + sorting: { sortModel: [{ field: 'name', sort: 'asc' }] }, + }} + rows={ifacesValue} + /> + div': { + scrollSnapAlign: 'start', + }, + + '& > :not(div:first-child)': { + marginLeft: '1em', + }, + }} + > + {hostNets.map((entry) => { + const [key] = entry; + + return ( + + formikUtils={formikUtils} + host={host} + ifaceHeld={ifaceHeld} + ifaces={ifaces} + ifacesApplied={ifacesApplied} + ifacesValue={ifacesValue} + key={`hostnet-${key}`} + netId={key} + /> + ); + })} + + + + + { + const key = uuidv4(); + + formik.setFieldValue( + `${chains.networks}.${key}`, + { + interfaces: ['', ''], + ip: '', + sequence: '', + subnetMask: '', + type: '', + }, + true, + ); + }} + /> + + + + } + /> + + + + } + /> + + + ); +}; + +export default HostNetInitInputGroup; diff --git a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx new file mode 100644 index 000000000..3a11bbbdc --- /dev/null +++ b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx @@ -0,0 +1,248 @@ +import { Grid } from '@mui/material'; +import { FC, useMemo } from 'react'; + +import NETWORK_TYPES from '../../lib/consts/NETWORK_TYPES'; + +import Autocomplete from '../Autocomplete'; +import DropArea from '../DropArea'; +import IconButton from '../IconButton'; +import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; +import { InnerPanel, InnerPanelBody, InnerPanelHeader } from '../Panels'; +import SelectWithLabel from '../SelectWithLabel'; +import { BodyText } from '../Text'; +import UncontrolledInput from '../UncontrolledInput'; + +const NETOPS: Record = { + striker: ['bcn', 'ifn'], + subnode: ['bcn', 'ifn', 'sn'], +}; + +const HostNetInputGroup = ( + ...[props]: Parameters>> +): ReturnType>> => { + const { + formikUtils, + host, + ifaceHeld, + ifaces, + ifacesApplied, + ifacesValue, + netId, + } = props; + + const { formik, handleChange } = formikUtils; + + const netTypeOptions = useMemo(() => { + let base: string[] = NETOPS[host.type]; + + if (!base) return []; + + const nets = formik.values.networkInit.networks; + + if ( + host.type === 'subnode' && + ifacesValue.length >= 8 && + (nets[netId].type === 'mn' || + Object.values(nets).every((net) => net.type !== 'mn')) + ) { + base = [...base, 'mn'].sort(); + } + + return base.map((type) => ({ + displayValue: NETWORK_TYPES[type] ?? 'Unknown network', + value: type, + })); + }, [ + formik.values.networkInit.networks, + host.type, + ifacesValue.length, + netId, + ]); + + const chains = useMemo(() => { + const ns = 'networkInit.networks'; + const n = `${ns}.${netId}`; + + return { + ip: `${n}.ip`, + link1: `${n}.interfaces.0`, + link2: `${n}.interfaces.1`, + networks: ns, + sequence: `${n}.sequence`, + subnetMask: `${n}.subnetMask`, + type: `${n}.type`, + }; + }, [netId]); + + return ( + + + + + + + + + } + /> + + + {!/^default/.test(netId) && ( + { + const { [netId]: rm, ...keep } = + formik.values.networkInit.networks; + + formik.setFieldValue(chains.networks, keep, true); + }} + sx={{ + padding: '.2em', + position: 'absolute', + right: '-9px', + top: '-4px', + }} + /> + )} + + + + + { + if (!ifaceHeld) return; + + formik.setFieldValue(chains.link1, ifaceHeld, true); + }} + > + + ifacesApplied[option.uuid] && + option.uuid !== + formik.values.networkInit.networks[netId].interfaces[0] + } + getOptionLabel={(option) => option.name} + id={chains.link1} + isOptionEqualToValue={(option, value) => + option.uuid === value.uuid + } + label="Link 1" + noOptionsText="No matching interface" + onChange={(event, value) => { + formik.setFieldValue( + chains.link1, + value ? value.uuid : '', + true, + ); + }} + openOnFocus + options={ifacesValue} + renderOption={(optionProps, option) => ( +
  • + {option.name} +
  • + )} + value={ + ifaces[ + formik.values.networkInit.networks[netId].interfaces[0] + ] ?? null + } + /> +
    +
    + + { + if (!ifaceHeld) return; + + formik.setFieldValue(chains.link2, ifaceHeld, true); + }} + > + + ifacesApplied[option.uuid] && + option.uuid !== + formik.values.networkInit.networks[netId].interfaces[1] + } + getOptionLabel={(option) => option.name} + id={chains.link2} + isOptionEqualToValue={(option, value) => + option.uuid === value.uuid + } + label="Link 2" + noOptionsText="No matching interface" + onChange={(event, value) => { + formik.setFieldValue( + chains.link2, + value ? value.uuid : '', + true, + ); + }} + openOnFocus + options={ifacesValue} + renderOption={(optionProps, option) => ( +
  • + {option.name} +
  • + )} + value={ + ifaces[ + formik.values.networkInit.networks[netId].interfaces[1] + ] ?? null + } + /> +
    +
    + + + } + /> + + + + } + /> + +
    +
    +
    + ); +}; + +export default HostNetInputGroup; diff --git a/striker-ui/components/HostNetInit/SimpleIface.tsx b/striker-ui/components/HostNetInit/SimpleIface.tsx new file mode 100644 index 000000000..419864411 --- /dev/null +++ b/striker-ui/components/HostNetInit/SimpleIface.tsx @@ -0,0 +1,71 @@ +import { Box, styled } from '@mui/material'; +import { FC, useMemo } from 'react'; + +import { BLACK, BORDER_RADIUS, GREY } from '../../lib/consts/DEFAULT_THEME'; + +import Decorator from '../Decorator'; +import IconButton from '../IconButton'; +import { MonoText } from '../Text'; + +const BaseIface = styled(Box)({ + alignItems: 'center', + display: 'flex', + flexDirection: 'row', + + '& > :not(:first-child)': { + marginLeft: '.5em', + }, +}); + +const BaseFloatingIface = styled(BaseIface)({ + borderColor: GREY, + borderRadius: BORDER_RADIUS, + borderStyle: 'solid', + borderWidth: '1px', + backgroundColor: BLACK, + padding: '.6em 1.2em', + position: 'absolute', + zIndex: 999, +}); + +const SimpleIface: FC = (props) => { + const { iface } = props; + + const decoratorColour = useMemo( + () => (iface.state === 'up' ? 'ok' : 'off'), + [iface.state], + ); + + return ( + <> + + {iface.name} + + ); +}; + +export const FloatingIface: FC = (props) => { + const { boxProps, iface } = props; + + return ( + + {iface.name} + + ); +}; + +export const AppliedIface: FC = (props) => { + const { boxProps, iface, onClose } = props; + + return ( + + + + + ); +}; diff --git a/striker-ui/components/HostNetInit/hostNetInitSchema.ts b/striker-ui/components/HostNetInit/hostNetInitSchema.ts new file mode 100644 index 000000000..55dbbbba1 --- /dev/null +++ b/striker-ui/components/HostNetInit/hostNetInitSchema.ts @@ -0,0 +1,23 @@ +import * as yup from 'yup'; + +import { REP_IPV4_CSV } from '../../lib/consts/REG_EXP_PATTERNS'; + +import buildYupDynamicObject from '../../lib/buildYupDynamicObject'; +import hostNetSchema from './hostNetSchema'; +import { yupIpv4 } from '../../lib/yupMatches'; + +const hostNetInitSchema = yup.object({ + dns: yup + .string() + .matches( + REP_IPV4_CSV, + 'DNS must be a comma-separated list of IPv4 addresses', + ), + // Test gateway to make sure it's in one of the host's networks + gateway: yupIpv4().required(), + networks: yup.lazy((nets) => + yup.object(buildYupDynamicObject(nets, hostNetSchema)), + ), +}); + +export default hostNetInitSchema; diff --git a/striker-ui/components/HostNetInit/hostNetSchema.ts b/striker-ui/components/HostNetInit/hostNetSchema.ts new file mode 100644 index 000000000..3777a305a --- /dev/null +++ b/striker-ui/components/HostNetInit/hostNetSchema.ts @@ -0,0 +1,24 @@ +import * as yup from 'yup'; + +import { REP_UUID } from '../../lib/consts/REG_EXP_PATTERNS'; + +import { yupIpv4 } from '../../lib/yupMatches'; + +const hostNetSchema = yup.object({ + interfaces: yup + .array() + .of(yup.string()) + .length(2) + .required() + .test({ + name: 'atleast1', + message: 'At least 1 network interface is required', + test: (list) => list.some((value = '') => REP_UUID.test(value)), + }), + ip: yupIpv4().required(), + sequence: yup.number().required(), + subnetMask: yupIpv4().required(), + type: yup.string().oneOf(['bcn', 'ifn', 'mn', 'sn']), +}); + +export default hostNetSchema; diff --git a/striker-ui/types/APINetworkInterface.d.ts b/striker-ui/types/APINetworkInterface.d.ts index 7cdfac980..202bb17f8 100644 --- a/striker-ui/types/APINetworkInterface.d.ts +++ b/striker-ui/types/APINetworkInterface.d.ts @@ -1,3 +1,6 @@ +/** + * @deprecated + */ type NetworkInterfaceOverviewMetadata = { networkInterfaceUUID: string; networkInterfaceMACAddress: string; @@ -6,3 +9,21 @@ type NetworkInterfaceOverviewMetadata = { networkInterfaceSpeed: number; networkInterfaceOrder: number; }; + +type APINetworkInterfaceOverview = { + dns: null | string; + gateway: null | string; + ip: null | string; + mac: string; + name: string; + order: number; + // Unit: mbps + speed: number; + state: string; + subnetMask: null | string; + uuid: string; +}; + +type APINetworkInterfaceOverviewList = { + [uuid: string]: APINetworkInterfaceOverview; +}; diff --git a/striker-ui/types/HostNetInit.d.ts b/striker-ui/types/HostNetInit.d.ts new file mode 100644 index 000000000..75d9f5888 --- /dev/null +++ b/striker-ui/types/HostNetInit.d.ts @@ -0,0 +1,71 @@ +type HostNetFormikValues = { + interfaces: [string, string]; + ip: string; + sequence: string; + subnetMask: string; + type: string; +}; + +type HostNetInitFormikValues = { + dns: string; + gateway: string; + networks: Record; +}; + +type HostNetInitFormikExtension = { + networkInit: HostNetInitFormikValues; +}; + +type HostNetInitHost = { + sequence: number; + type: string; + uuid: string; +}; + +/** HostNetInputGroup */ + +type HostNetInputGroupOptionalProps = { + hostNetValueId?: string; + ifaceHeld?: string; +}; + +type HostNetInputGroupProps = + HostNetInputGroupOptionalProps & { + formikUtils: FormikUtils; + ifaces: APINetworkInterfaceOverviewList; + ifacesApplied: Record; + ifacesValue: APINetworkInterfaceOverview[]; + host: HostNetInitHost; + netId: string; + }; + +/** HostNetInitInputGroup */ + +type DragPosition = { + x: number; + y: number; +}; + +type HostNetInitInputGroupOptionalProps = { + onFetchSuccess?: (data: APINetworkInterfaceOverviewList) => void; +}; + +type HostNetInitInputGroupProps = + HostNetInitInputGroupOptionalProps & { + formikUtils: FormikUtils; + host: HostNetInitHost; + }; + +/** SimpleIface */ + +type SimpleIfaceOptionalProps = { + boxProps?: import('@mui/material').BoxProps; +}; + +type SimpleIfaceProps = SimpleIfaceOptionalProps & { + iface: APINetworkInterfaceOverview; +}; + +type AppliedIfaceProps = SimpleIfaceProps & { + onClose: React.MouseEventHandler; +}; From eeecfe8e833fa752185ec07c511f1830b94bebe5 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 25 Sep 2024 12:17:19 -0400 Subject: [PATCH 11/50] fix(striker-ui-api): include network sequence, i.e., bcn1,2,... in build network config --- striker-ui-api/src/lib/fconfig/buildNetworkConfig.ts | 7 +++++-- striker-ui-api/src/types/ApiHost.d.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/striker-ui-api/src/lib/fconfig/buildNetworkConfig.ts b/striker-ui-api/src/lib/fconfig/buildNetworkConfig.ts index 3252f443a..ed7b563c9 100644 --- a/striker-ui-api/src/lib/fconfig/buildNetworkConfig.ts +++ b/striker-ui-api/src/lib/fconfig/buildNetworkConfig.ts @@ -15,12 +15,15 @@ export const buildNetworkConfig = ( counters: Record; data: FormConfigData; }>( - (previous, { createBridge, interfaces, ipAddress, subnetMask, type }) => { + ( + previous, + { createBridge, interfaces, ipAddress, sequence, subnetMask, type }, + ) => { const { counters } = previous; counters[type] = counters[type] ? counters[type] + 1 : 1; - const networkShortName = `${type}${counters[type]}`; + const networkShortName = `${type}${sequence}`; previous.data = { ...previous.data, diff --git a/striker-ui-api/src/types/ApiHost.d.ts b/striker-ui-api/src/types/ApiHost.d.ts index 215c82ff1..3e05f79dc 100644 --- a/striker-ui-api/src/types/ApiHost.d.ts +++ b/striker-ui-api/src/types/ApiHost.d.ts @@ -68,7 +68,7 @@ type InitializeStrikerNetworkForm = { createBridge?: StringBoolean; interfaces: Array; ipAddress: string; - name: string; + sequence: number; subnetMask: string; type: string; }; From 8a9255a64e34aa51c581ecb6011884a58ca8f3ab Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 27 Sep 2024 16:01:17 -0400 Subject: [PATCH 12/50] fix(striker-ui): update local value when origin changes in uncontrolled input --- striker-ui/components/UncontrolledInput.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/striker-ui/components/UncontrolledInput.tsx b/striker-ui/components/UncontrolledInput.tsx index f4d0b5e90..7b644819a 100644 --- a/striker-ui/components/UncontrolledInput.tsx +++ b/striker-ui/components/UncontrolledInput.tsx @@ -48,11 +48,11 @@ const UncontrolledInput = forwardRef( const { onChange: inputOnChange, - [valueKey]: inputValue, + [valueKey]: originValue, ...restInputProps } = inputProps; - const [value, setValue] = useState(inputValue); + const [value, setValue] = useState(originValue); const baseChangeEventHandler = useCallback< React.ChangeEventHandler @@ -88,6 +88,11 @@ const UncontrolledInput = forwardRef( // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + // Always update the input's local value when the origin changes + useEffect(() => { + setValue(originValue); + }, [originValue]); + useImperativeHandle( ref, () => ({ From 2a110e82114f0adcbc397335b37ce7063efe860d Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 27 Sep 2024 16:30:43 -0400 Subject: [PATCH 13/50] fix(striker-ui): remove extra props spreading in panel --- striker-ui/components/Panels/Panel.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/striker-ui/components/Panels/Panel.tsx b/striker-ui/components/Panels/Panel.tsx index f4b0437f3..f13f98443 100644 --- a/striker-ui/components/Panels/Panel.tsx +++ b/striker-ui/components/Panels/Panel.tsx @@ -87,7 +87,6 @@ const styledScrollbars = ( const Panel: FC = ({ children, - classes: rootClasses, className: rootClassName, paperProps: { className: paperClassName, @@ -96,14 +95,7 @@ const Panel: FC = ({ sx: rootSx, ...restRootProps }) => ( - + {styledScrollbars} From e90abacbe927c5f840a93cda806c78c412c7135f Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 27 Sep 2024 17:40:21 -0400 Subject: [PATCH 14/50] fix(striker-ui-api): expose job detail endpoint during init stage --- striker-ui-api/src/routes/init.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/striker-ui-api/src/routes/init.ts b/striker-ui-api/src/routes/init.ts index 4cdb16471..b736c7ce7 100644 --- a/striker-ui-api/src/routes/init.ts +++ b/striker-ui-api/src/routes/init.ts @@ -3,7 +3,7 @@ import express from 'express'; import { assertInit } from '../middlewares'; import { configStriker } from '../lib/request_handlers/host'; -import { getJob } from '../lib/request_handlers/job'; +import { getJob, getJobDetail } from '../lib/request_handlers/job'; import { getNetworkInterface } from '../lib/request_handlers/network-interface'; const router = express.Router(); @@ -28,6 +28,13 @@ router }), getJob, ) + .get( + '/job/:uuid', + assertInit({ + fail: ({ path }, response) => response.redirect(307, `/api${path}`), + }), + getJobDetail, + ) .get( '/network-interface/:hostUUID?', assertInit({ From 7153ec365dcfc4dadb341e1c49fda065c6ac02d5 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 27 Sep 2024 17:46:32 -0400 Subject: [PATCH 15/50] fix(striker-ui-api): send job uuid when init striker --- .../src/lib/request_handlers/host/configStriker.ts | 8 +++++--- striker-ui-api/src/types/ApiHost.d.ts | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/host/configStriker.ts b/striker-ui-api/src/lib/request_handlers/host/configStriker.ts index 8ca0f4779..0b1df24c2 100644 --- a/striker-ui-api/src/lib/request_handlers/host/configStriker.ts +++ b/striker-ui-api/src/lib/request_handlers/host/configStriker.ts @@ -19,7 +19,7 @@ import { cvar } from '../../varn'; export const configStriker: RequestHandler< unknown, - undefined, + InitializeStrikerResponseBody, Partial > = async (request, response) => { const { body = {} } = request; @@ -120,6 +120,8 @@ export const configStriker: RequestHandler< const configEntries = Object.entries(configData); + let jobUuid: string; + try { const localHostUuid = getLocalHostUUID(); @@ -143,7 +145,7 @@ export const configStriker: RequestHandler< ); } - await job({ + jobUuid = await job({ file: __filename, job_command: SERVER_PATHS.usr.sbin['anvil-configure-host'].self, job_data: buildJobData({ @@ -160,5 +162,5 @@ export const configStriker: RequestHandler< return response.status(500).send(); } - response.status(200).send(); + response.status(200).send({ jobUuid }); }; diff --git a/striker-ui-api/src/types/ApiHost.d.ts b/striker-ui-api/src/types/ApiHost.d.ts index 3e05f79dc..a0d6de872 100644 --- a/striker-ui-api/src/types/ApiHost.d.ts +++ b/striker-ui-api/src/types/ApiHost.d.ts @@ -86,6 +86,10 @@ type InitializeStrikerForm = { organizationPrefix: string; }; +type InitializeStrikerResponseBody = { + jobUuid: string; +}; + type PrepareHostRequestBody = { enterpriseUUID?: string; hostIPAddress: string; From f62c7fc6221122ab941cbca5b0b30f4d22a3ec79 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Fri, 27 Sep 2024 21:24:58 -0400 Subject: [PATCH 16/50] fix(striker-ui): complete striker init form --- striker-ui/components/HostNetInit/index.tsx | 4 + .../StrikerConfig/SimpleOperationsPanel.tsx | 4 +- .../components/StrikerInit/StrikerInit.tsx | 82 +++++++ .../StrikerInit/StrikerInitForm.tsx | 231 +++++++++++++++--- .../StrikerInit/StrikerInitProgress.tsx | 118 +++++++++ .../StrikerInit/StrikerInitSummary.tsx | 111 +++++++++ .../StrikerInit/strikerInitSchema.ts | 3 + striker-ui/pages/init/index.tsx | 15 +- striker-ui/types/APIHost.d.ts | 8 +- striker-ui/types/StrikerInit.d.ts | 28 ++- 10 files changed, 559 insertions(+), 45 deletions(-) create mode 100644 striker-ui/components/HostNetInit/index.tsx create mode 100644 striker-ui/components/StrikerInit/StrikerInit.tsx create mode 100644 striker-ui/components/StrikerInit/StrikerInitProgress.tsx create mode 100644 striker-ui/components/StrikerInit/StrikerInitSummary.tsx diff --git a/striker-ui/components/HostNetInit/index.tsx b/striker-ui/components/HostNetInit/index.tsx new file mode 100644 index 000000000..7d3146d96 --- /dev/null +++ b/striker-ui/components/HostNetInit/index.tsx @@ -0,0 +1,4 @@ +import HostNetInitInputGroup from './HostNetInitInputGroup'; +import hostNetInitSchema from './hostNetInitSchema'; + +export { HostNetInitInputGroup, hostNetInitSchema }; diff --git a/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx b/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx index 94c35cd92..c32c8ec17 100644 --- a/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx +++ b/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx @@ -123,9 +123,7 @@ const SimpleOperationsPanel: FC = ({
    - - Reconfigure striker - + Reconfigure striker { + const [initJobUuid, setInitJobUuid] = useState(); + + const { + confirmDialog, + finishConfirm, + setConfirmDialogLoading, + setConfirmDialogOpen, + setConfirmDialogProps, + } = useConfirmDialog({ + initial: { + scrollContent: true, + wide: true, + }, + }); + + const formTools = useMemo( + () => ({ + add: { open: () => null }, + confirm: { + finish: finishConfirm, + loading: setConfirmDialogLoading, + open: (v = true) => setConfirmDialogOpen(v), + prepare: setConfirmDialogProps, + }, + edit: { open: () => null }, + }), + [ + finishConfirm, + setConfirmDialogLoading, + setConfirmDialogOpen, + setConfirmDialogProps, + ], + ); + + const { data: detail, loading: loadingDetail } = + useFetch('/host/local'); + + if (loadingDetail) { + return ( + + + + ); + } + + if (initJobUuid) { + return ( + + ); + } + + return ( + <> + + + {detail ? 'Rei' : 'I'}nitialize Striker + + { + setInitJobUuid(data.jobUuid); + }} + tools={formTools} + /> + + {confirmDialog} + + ); +}; + +export default StrikerInit; diff --git a/striker-ui/components/StrikerInit/StrikerInitForm.tsx b/striker-ui/components/StrikerInit/StrikerInitForm.tsx index 87b7d4c52..6f48fc458 100644 --- a/striker-ui/components/StrikerInit/StrikerInitForm.tsx +++ b/striker-ui/components/StrikerInit/StrikerInitForm.tsx @@ -1,14 +1,101 @@ import { Grid } from '@mui/material'; +import { Netmask } from 'netmask'; import { FC, useCallback, useMemo, useRef } from 'react'; +import { v4 as uuidv4 } from 'uuid'; -import useFormikUtils from '../../hooks/useFormikUtils'; -import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; import INPUT_TYPES from '../../lib/consts/INPUT_TYPES'; + +import ActionGroup from '../ActionGroup'; +import api from '../../lib/api'; +import handleAPIError from '../../lib/handleAPIError'; +import { HostNetInitInputGroup } from '../HostNetInit'; import MessageGroup from '../MessageGroup'; +import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; +import pad from '../../lib/pad'; import strikerInitSchema from './strikerInitSchema'; -import ActionGroup from '../ActionGroup'; +import StrikerInitSummary from './StrikerInitSummary'; import UncontrolledInput from '../UncontrolledInput'; -import pad from '../../lib/pad'; +import useFormikUtils from '../../hooks/useFormikUtils'; + +const buildFormikInitialValues = ( + detail?: APIHostDetail, +): StrikerInitFormikValues => { + let domainName = ''; + let hostName = ''; + let hostNumber = ''; + + let dns = ''; + let gateway = ''; + let networks: Record = { + defaultbcn: { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'bcn', + }, + defaultifn: { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'ifn', + }, + }; + + let organizationName = ''; + let organizationPrefix = ''; + + if (detail) { + ({ + dns = '', + domain: domainName = '', + gateway = '', + hostName = '', + sequence: hostNumber = '', + organization: organizationName = '', + prefix: organizationPrefix = '', + } = detail); + + const { networks: nets = {} } = detail; + + networks = Object.entries(nets).reduce>( + (previous, [nid, value]) => { + const { ip, link1Uuid, link2Uuid = '', subnetMask, type } = value; + + const sequence = nid.replace(/^.*(\d+)$/, '$1'); + + const key = sequence === '1' ? `default${type}` : uuidv4(); + + previous[key] = { + interfaces: [link1Uuid, link2Uuid], + ip, + sequence, + subnetMask, + type, + }; + + return previous; + }, + {}, + ); + } + + return { + adminPassword: '', + confirmAdminPassword: '', + domainName, + hostName, + hostNumber, + networkInit: { + dns, + gateway, + networks, + }, + organizationName, + organizationPrefix, + }; +}; const guessHostName = ( orgPrefix: string, @@ -38,12 +125,103 @@ const guessOrgPrefix = (orgName: string, max = 5): string => { return result; }; -const StrikerInitForm: FC = () => { - const orgPrefixInputRef = - useRef>(null); +const StrikerInitForm: FC = (props) => { + const { detail, onSubmitSuccess, tools } = props; + + const ifaces = useRef(null); - const hostNameInputRef = - useRef>(null); + const formikUtils = useFormikUtils({ + initialValues: buildFormikInitialValues(detail), + onSubmit: (values, { setSubmitting }) => { + const { networkInit: netInit, ...restValues } = values; + const { networks, ...restNetInit } = netInit; + + const ns = Object.values(networks); + + const rqbody = { + ...restValues, + ...restNetInit, + gatewayInterface: ns.reduce((previous, n) => { + const { ip, sequence, subnetMask, type } = n; + + let subnet: Netmask; + + try { + subnet = new Netmask(`${ip}/${subnetMask}`); + } catch (error) { + return previous; + } + + if (subnet.contains(netInit.gateway)) { + return `${type}${sequence}`; + } + + return previous; + }, ''), + networks: ns.map((n) => { + const { interfaces, ip, sequence, subnetMask, type } = n; + + return { + interfaces: interfaces.map((ifUuid) => + ifUuid + ? { + mac: ifaces.current?.[ifUuid]?.mac, + } + : null, + ), + ipAddress: ip, + sequence, + subnetMask, + type, + }; + }), + }; + + tools.confirm.prepare({ + actionProceedText: 'Initialize', + content: ifaces.current && ( + + ), + onCancelAppend: () => setSubmitting(false), + onProceedAppend: () => { + tools.confirm.loading(true); + + api + .put('/init', rqbody) + .then((response) => { + onSubmitSuccess?.call(null, response.data); + + tools.confirm.finish('Success', { + children: ( + <>Successfully registered striker initialization job. + ), + }); + }) + .catch((error) => { + const emsg = handleAPIError(error); + + emsg.children = ( + <> + Failed to register striker initialization job. {emsg.children} + + ); + + tools.confirm.finish('Error', emsg); + + setSubmitting(false); + }); + }, + titleText: `Initialize ${values.hostName} with the following?`, + }); + + tools.confirm.open(); + }, + validationSchema: strikerInitSchema, + }); const { disabledSubmit, @@ -51,21 +229,7 @@ const StrikerInitForm: FC = () => { formikErrors, getFieldChanged, handleChange, - } = useFormikUtils({ - initialValues: { - adminPassword: '', - confirmAdminPassword: '', - domainName: '', - hostName: '', - hostNumber: '', - organizationName: '', - organizationPrefix: '', - }, - onSubmit: (values, { setSubmitting }) => { - setSubmitting(false); - }, - validationSchema: strikerInitSchema, - }); + } = formikUtils; const adminPasswordChain = useMemo(() => `adminPassword`, []); const confirmAdminPasswordChain = useMemo(() => `confirmAdminPassword`, []); @@ -104,8 +268,6 @@ const StrikerInitForm: FC = () => { const guess = guessHostName(organizationPrefix, hostNumber, domainName); - hostNameInputRef.current?.set(guess); - formik.setFieldValue(hostNameChain, guess); }, [ @@ -148,8 +310,6 @@ const StrikerInitForm: FC = () => { const guess = guessOrgPrefix(value); - orgPrefixInputRef.current?.set(guess); - formik.setFieldValue(orgPrefixChain, guess); }} onChange={handleChange} @@ -173,7 +333,6 @@ const StrikerInitForm: FC = () => { value={formik.values.organizationPrefix} /> } - ref={orgPrefixInputRef} /> @@ -223,7 +382,6 @@ const StrikerInitForm: FC = () => { value={formik.values.hostName} /> } - ref={hostNameInputRef} />
    @@ -264,6 +422,19 @@ const StrikerInitForm: FC = () => { + + { + ifaces.current = data; + }} + /> + diff --git a/striker-ui/components/StrikerInit/StrikerInitProgress.tsx b/striker-ui/components/StrikerInit/StrikerInitProgress.tsx new file mode 100644 index 000000000..11fb1e801 --- /dev/null +++ b/striker-ui/components/StrikerInit/StrikerInitProgress.tsx @@ -0,0 +1,118 @@ +import { Grid } from '@mui/material'; +import { FC, useMemo, useRef } from 'react'; + +import { ProgressBar } from '../Bars'; +import Link from '../Link'; +import { InnerPanel, InnerPanelBody, InnerPanelHeader, Panel } from '../Panels'; +import Pre from '../Pre'; +import ScrollBox from '../ScrollBox'; +import Spinner from '../Spinner'; +import { BodyText } from '../Text'; +import useFetch from '../../hooks/useFetch'; + +const CenterPanel: FC = (props) => { + const { children } = props; + + return ( + + {children} + + ); +}; + +const StrikerInitProgress: FC = (props) => { + const { jobUuid, reinit } = props; + + const redirectTimeout = useRef(null); + + const redirectParams = useMemo<{ label: string; path: string }>(() => { + let label = 'login'; + let path = '/login'; + + if (reinit) { + label = 'striker config'; + path = '/config'; + } + + return { label, path }; + }, [reinit]); + + const { data: initJob } = useFetch(`/job/${jobUuid}`, { + onSuccess: (data) => { + const { progress } = data; + + if (redirectTimeout.current === null && progress === 100) { + redirectTimeout.current = setTimeout( + (url: string) => { + window.location.replace(url); + }, + 3000, + redirectParams.path, + ); + } + }, + refreshInterval: 2000, + }); + + const statusList = useMemo(() => { + if (!initJob?.status) return
    Loading...
    ; + + const { status } = initJob; + + const content = Object.values(status) + .reduce((previous, entry) => `${previous}${entry.value}\n\n`, '') + .trimEnd(); + + return
    {content}
    ; + }, [initJob]); + + if (!initJob) { + return ( + + + + ); + } + + return ( + + + + + You will be auto redirected to {redirectParams.label} after + initialization completes. If not, you can manually access{' '} + + {redirectParams.label} + {' '} + after completion. + + + + + + + + + Status + + + + {statusList} + + + + + + + ); +}; + +export default StrikerInitProgress; diff --git a/striker-ui/components/StrikerInit/StrikerInitSummary.tsx b/striker-ui/components/StrikerInit/StrikerInitSummary.tsx new file mode 100644 index 000000000..53e8bf7a6 --- /dev/null +++ b/striker-ui/components/StrikerInit/StrikerInitSummary.tsx @@ -0,0 +1,111 @@ +import { Grid } from '@mui/material'; +import { FC } from 'react'; + +import NETWORK_TYPES from '../../lib/consts/NETWORK_TYPES'; + +import { BodyText, InlineMonoText, MonoText } from '../Text'; + +const StrikerInitSummary: FC = (props) => { + const { gatewayIface, ifaces, values } = props; + + return ( + + + Organization name + + + {values.organizationName} + + + Organization prefix + + + {values.organizationPrefix} + + + Striker number + + + {values.hostNumber} + + + Domain name + + + {values.domainName} + + + Host name + + + {values.hostName} + + + Networks + + {Object.entries(values.networkInit.networks).map((net) => { + const [netId, { interfaces, ip, sequence, subnetMask, type }] = net; + + return ( + + + + + {NETWORK_TYPES[type]} {sequence} ( + + {`${type.toUpperCase()}${sequence}`} + + ) + + + {interfaces.map((ifaceUuid, ifaceIndex) => { + let key = `network-confirm-${netId}-interface${ifaceIndex}`; + let ifaceName = 'none'; + + if (ifaceUuid !== '') { + key = `${key}-${ifaceUuid}`; + ifaceName = ifaces[ifaceUuid]?.name; + } + + return ( + + + {`Link ${ifaceIndex + 1}`} + + + {ifaceName} + + + ); + })} + + {`${ip}/${subnetMask}`} + + + + ); + })} + + + Gateway + + + {values.networkInit.gateway} + + + Gateway network + + + {gatewayIface.toUpperCase()} + + + Domain name server(s) + + + {values.networkInit.dns} + + + ); +}; + +export default StrikerInitSummary; diff --git a/striker-ui/components/StrikerInit/strikerInitSchema.ts b/striker-ui/components/StrikerInit/strikerInitSchema.ts index ecf33c8ce..1cb7c40bc 100644 --- a/striker-ui/components/StrikerInit/strikerInitSchema.ts +++ b/striker-ui/components/StrikerInit/strikerInitSchema.ts @@ -1,5 +1,7 @@ import * as yup from 'yup'; +import { hostNetInitSchema } from '../HostNetInit'; + const strikerInitSchema = yup.object({ adminPassword: yup.string().required(), confirmAdminPassword: yup @@ -11,6 +13,7 @@ const strikerInitSchema = yup.object({ hostNumber: yup.number().required(), organizationName: yup.string().required(), organizationPrefix: yup.string().min(1).max(5).required(), + networkInit: hostNetInitSchema, }); export default strikerInitSchema; diff --git a/striker-ui/pages/init/index.tsx b/striker-ui/pages/init/index.tsx index 49759a116..f2bdeb269 100644 --- a/striker-ui/pages/init/index.tsx +++ b/striker-ui/pages/init/index.tsx @@ -1,17 +1,12 @@ import { FC } from 'react'; -import { Box as MUIBox } from '@mui/material'; -import StrikerInitForm from '../../components/StrikerInitForm'; +import PageBody from '../../components/PageBody'; +import StrikerInit from '../../components/StrikerInit/StrikerInit'; const Init: FC = () => ( - - - + + + ); export default Init; diff --git a/striker-ui/types/APIHost.d.ts b/striker-ui/types/APIHost.d.ts index f72370188..816918118 100644 --- a/striker-ui/types/APIHost.d.ts +++ b/striker-ui/types/APIHost.d.ts @@ -84,4 +84,10 @@ type APIHostDetail = APIHostOverview & { strikerUser?: string; }; -type APIDeleteHostConnectionRequestBody = { [key: 'local' | string]: string[] }; +type APIDeleteHostConnectionRequestBody = { + [key: 'local' | string]: string[]; +}; + +type APIStrikerInitResponseBody = { + jobUuid: string; +}; diff --git a/striker-ui/types/StrikerInit.d.ts b/striker-ui/types/StrikerInit.d.ts index 1df727d27..d1aa7c41c 100644 --- a/striker-ui/types/StrikerInit.d.ts +++ b/striker-ui/types/StrikerInit.d.ts @@ -1,4 +1,4 @@ -type StrikerInitFormikValues = { +type StrikerInitFormikValues = HostNetInitFormikExtension & { adminPassword: string; confirmAdminPassword: string; domainName: string; @@ -7,3 +7,29 @@ type StrikerInitFormikValues = { organizationName: string; organizationPrefix: string; }; + +/** StrikerInitForm */ + +type StrikerInitFormOptionalProps = { + detail?: APIHostDetail; + onSubmitSuccess?: (data: APIStrikerInitResponseBody) => void; +}; + +type StrikerInitFormProps = StrikerInitFormOptionalProps & { + tools: CrudListFormTools; +}; + +/** StrikerInitProgress */ + +type StrikerInitProgressProps = { + jobUuid: string; + reinit: boolean; +}; + +/** StrikerInitSummary */ + +type StrikerInitSummaryProps = { + gatewayIface: string; + ifaces: APINetworkInterfaceOverviewList; + values: StrikerInitFormikValues; +}; From 3b6ed03f52cc34551ca979730f81f1cb1b44d7cf Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Sat, 28 Sep 2024 03:43:52 -0400 Subject: [PATCH 17/50] fix(striker-ui): relocate styles in tabs, tab --- striker-ui/components/Tab.tsx | 35 +++++++++---------- striker-ui/components/Tabs.tsx | 62 ++++++++++++++++------------------ 2 files changed, 46 insertions(+), 51 deletions(-) diff --git a/striker-ui/components/Tab.tsx b/striker-ui/components/Tab.tsx index 4fe61beef..48d155d42 100644 --- a/striker-ui/components/Tab.tsx +++ b/striker-ui/components/Tab.tsx @@ -1,7 +1,8 @@ import { - Tab as MUITab, + Tab as MuiTab, tabClasses as muiTabClasses, - TabProps as MUITabProps, + TabProps as MuiTabProps, + styled, } from '@mui/material'; import { FC, useMemo } from 'react'; @@ -9,7 +10,18 @@ import { BLUE, BORDER_RADIUS, GREY } from '../lib/consts/DEFAULT_THEME'; import { BodyText } from './Text'; -const Tab: FC = ({ label: originalLabel, ...restTabProps }) => { +const BaseTab = styled(MuiTab)({ + borderRadius: BORDER_RADIUS, + color: GREY, + padding: '.4em .8em', + textTransform: 'none', + + [`&.${muiTabClasses.selected}`]: { + color: BLUE, + }, +}); + +const Tab: FC = ({ label: originalLabel, ...restTabProps }) => { const label = useMemo( () => typeof originalLabel === 'string' ? ( @@ -20,22 +32,7 @@ const Tab: FC = ({ label: originalLabel, ...restTabProps }) => { [originalLabel], ); - return ( - - ); + return ; }; export default Tab; diff --git a/striker-ui/components/Tabs.tsx b/striker-ui/components/Tabs.tsx index 97a78105b..eb7aa54b9 100644 --- a/striker-ui/components/Tabs.tsx +++ b/striker-ui/components/Tabs.tsx @@ -1,8 +1,9 @@ import { Breakpoint, tabClasses as muiTabClasses, - Tabs as MUITabs, + Tabs as MuiTabs, tabsClasses as muiTabsClasses, + styled, useMediaQuery, useTheme, } from '@mui/material'; @@ -13,6 +14,33 @@ import { BLUE, BORDER_RADIUS } from '../lib/consts/DEFAULT_THEME'; const TABS_MIN_HEIGHT = '1em'; const TABS_VERTICAL_MIN_HEIGHT = '1.8em'; +const BaseTabs = styled(MuiTabs)({ + minHeight: TABS_MIN_HEIGHT, + + [`&.${muiTabsClasses.vertical}`]: { + minHeight: TABS_VERTICAL_MIN_HEIGHT, + + [`& .${muiTabClasses.root}`]: { + alignItems: 'flex-start', + minHeight: TABS_VERTICAL_MIN_HEIGHT, + paddingLeft: '2em', + }, + + [`& .${muiTabsClasses.indicator}`]: { + right: 'initial', + }, + }, + + [`& .${muiTabClasses.root}`]: { + minHeight: TABS_MIN_HEIGHT, + }, + + [`& .${muiTabsClasses.indicator}`]: { + backgroundColor: BLUE, + borderRadius: BORDER_RADIUS, + }, +}); + const Tabs: FC = ({ orientation: rawOrientation, variant = 'fullWidth', @@ -61,37 +89,7 @@ const Tabs: FC = ({ }, [mapToBreakpointUp, rawOrientation]); return ( - + ); }; From f35e64dcfcef7acb28ca8f4060c0153b81bda225 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Sat, 28 Sep 2024 03:45:56 -0400 Subject: [PATCH 18/50] fix(striker-ui): hoist api host net list conversion --- .../StrikerInit/StrikerInitForm.tsx | 23 ++--------------- striker-ui/lib/toHostNetList.ts | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 striker-ui/lib/toHostNetList.ts diff --git a/striker-ui/components/StrikerInit/StrikerInitForm.tsx b/striker-ui/components/StrikerInit/StrikerInitForm.tsx index 6f48fc458..4e88e4620 100644 --- a/striker-ui/components/StrikerInit/StrikerInitForm.tsx +++ b/striker-ui/components/StrikerInit/StrikerInitForm.tsx @@ -1,7 +1,6 @@ import { Grid } from '@mui/material'; import { Netmask } from 'netmask'; import { FC, useCallback, useMemo, useRef } from 'react'; -import { v4 as uuidv4 } from 'uuid'; import INPUT_TYPES from '../../lib/consts/INPUT_TYPES'; @@ -14,6 +13,7 @@ import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; import pad from '../../lib/pad'; import strikerInitSchema from './strikerInitSchema'; import StrikerInitSummary from './StrikerInitSummary'; +import toHostNetList from '../../lib/toHostNetList'; import UncontrolledInput from '../UncontrolledInput'; import useFormikUtils from '../../hooks/useFormikUtils'; @@ -59,26 +59,7 @@ const buildFormikInitialValues = ( const { networks: nets = {} } = detail; - networks = Object.entries(nets).reduce>( - (previous, [nid, value]) => { - const { ip, link1Uuid, link2Uuid = '', subnetMask, type } = value; - - const sequence = nid.replace(/^.*(\d+)$/, '$1'); - - const key = sequence === '1' ? `default${type}` : uuidv4(); - - previous[key] = { - interfaces: [link1Uuid, link2Uuid], - ip, - sequence, - subnetMask, - type, - }; - - return previous; - }, - {}, - ); + networks = toHostNetList(nets); } return { diff --git a/striker-ui/lib/toHostNetList.ts b/striker-ui/lib/toHostNetList.ts new file mode 100644 index 000000000..7a0a65429 --- /dev/null +++ b/striker-ui/lib/toHostNetList.ts @@ -0,0 +1,25 @@ +import { v4 as uuidv4 } from 'uuid'; + +const toHostNetList = (networks: APIHostNetworkList) => + Object.entries(networks).reduce>( + (previous, [nid, value]) => { + const { ip, link1Uuid, link2Uuid = '', subnetMask, type } = value; + + const sequence = nid.replace(/^.*(\d+)$/, '$1'); + + const key = sequence === '1' ? `default${type}` : uuidv4(); + + previous[key] = { + interfaces: [link1Uuid, link2Uuid], + ip, + sequence, + subnetMask, + type, + }; + + return previous; + }, + {}, + ); + +export default toHostNetList; From dea4b95993845754383bea2d392d2b9d92aa45b8 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Sat, 28 Sep 2024 03:47:37 -0400 Subject: [PATCH 19/50] fix(striker-ui): add initial manage host network pieces --- .../components/ManageHostNetwork/HostTabs.tsx | 47 ++++++ .../ManageHostNetwork/ManageHostNetwork.tsx | 46 ++++++ .../ManageHostNetwork/PrepareHostNetwork.tsx | 19 +++ .../PrepareHostNetworkForm.tsx | 149 ++++++++++++++++++ .../prepareHostNetworkSchema.ts | 10 ++ striker-ui/types/ManageHostNetwork.d.ts | 25 +++ 6 files changed, 296 insertions(+) create mode 100644 striker-ui/components/ManageHostNetwork/HostTabs.tsx create mode 100644 striker-ui/components/ManageHostNetwork/ManageHostNetwork.tsx create mode 100644 striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx create mode 100644 striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx create mode 100644 striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts create mode 100644 striker-ui/types/ManageHostNetwork.d.ts diff --git a/striker-ui/components/ManageHostNetwork/HostTabs.tsx b/striker-ui/components/ManageHostNetwork/HostTabs.tsx new file mode 100644 index 000000000..37f7d043c --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/HostTabs.tsx @@ -0,0 +1,47 @@ +import { Grid } from '@mui/material'; +import { FC } from 'react'; + +import Tab from '../Tab'; +import Tabs from '../Tabs'; +import { BodyText } from '../Text'; + +const HostTabs: FC = (props) => { + const { list: hostValues, setValue, value } = props; + + return ( + { + setValue(hostUuid); + }} + orientation="vertical" + value={value} + > + {hostValues.map((host) => { + const { anvil, hostStatus, hostUUID, shortHostName } = host; + + return ( + + + {shortHostName} + + + {anvil ? `in ${anvil.name}` : 'is free'} + + + {hostStatus} + + + } + value={hostUUID} + /> + ); + })} + + ); +}; + +export default HostTabs; diff --git a/striker-ui/components/ManageHostNetwork/ManageHostNetwork.tsx b/striker-ui/components/ManageHostNetwork/ManageHostNetwork.tsx new file mode 100644 index 000000000..ab9c67481 --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/ManageHostNetwork.tsx @@ -0,0 +1,46 @@ +import { FC, useMemo, useState } from 'react'; + +import Divider from '../Divider'; +import HostTabs from './HostTabs'; +import { Panel } from '../Panels'; +import PrepareHostNetwork from './PrepareHostNetwork'; +import useFetch from '../../hooks/useFetch'; +import TabContent from '../TabContent'; +import Spinner from '../Spinner'; + +const ManageHostNetwork: FC = () => { + const [hostUuid, setHostUuid] = useState(false); + + const { data: hosts } = useFetch('/host?types=dr,node'); + + const hostValues = useMemo( + () => hosts && Object.values(hosts), + [hosts], + ); + + if (!hostValues) { + return ( + + + + ); + } + + return ( + + + {hostUuid && } + {hostValues.map((host) => ( + + + + ))} + + ); +}; + +export default ManageHostNetwork; diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx new file mode 100644 index 000000000..9d549bf5a --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx @@ -0,0 +1,19 @@ +import { FC } from 'react'; + +import PrepareHostNetworkForm from './PrepareHostNetworkForm'; +import Spinner from '../Spinner'; +import useFetch from '../../hooks/useFetch'; + +const PrepareHostNetwork: FC = (props) => { + const { uuid } = props; + + const { data: detail } = useFetch(`/host/${uuid}`); + + if (!detail) { + return ; + } + + return ; +}; + +export default PrepareHostNetwork; diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx new file mode 100644 index 000000000..175c59f4c --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx @@ -0,0 +1,149 @@ +import { Grid } from '@mui/material'; +import { FC, useMemo } from 'react'; + +import ActionGroup from '../ActionGroup'; +import { HostNetInitInputGroup } from '../HostNetInit'; +import MessageGroup from '../MessageGroup'; +import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; +import UncontrolledInput from '../UncontrolledInput'; +import useFormikUtils from '../../hooks/useFormikUtils'; +import SwitchWithLabel from '../SwitchWithLabel'; +import prepareHostNetworkSchema from './prepareHostNetworkSchema'; +import toHostNetList from '../../lib/toHostNetList'; + +const buildFormikInitialValues = ( + detail: APIHostDetail, +): PrepareHostNetworkFormikValues => { + const { dns = '', gateway = '', hostName = '', networks: nets } = detail; + + let networks: Record = { + defaultbcn: { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'bcn', + }, + defaultifn: { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'ifn', + }, + defaultsn: { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'sn', + }, + }; + + if (nets) { + networks = toHostNetList(nets); + } + + return { + hostName, + mini: false, + networkInit: { + dns, + gateway, + networks, + }, + }; +}; + +const PrepareHostNetworkForm: FC = (props) => { + const { detail, uuid } = props; + + const formikUtils = useFormikUtils({ + initialValues: buildFormikInitialValues(detail), + onSubmit: (values, { setSubmitting }) => { + setSubmitting(false); + }, + validationSchema: prepareHostNetworkSchema, + }); + + const { disabledSubmit, formik, formikErrors, handleChange } = formikUtils; + + const sequence = useMemo(() => { + const trailing = detail.shortHostName.replace(/^.*(\d+)$/, '$1'); + + return Number(trailing); + }, [detail.shortHostName]); + + const chains = useMemo( + () => ({ + mini: `mini`, + hostName: `hostName`, + }), + [], + ); + + return ( + { + event.preventDefault(); + + formik.handleSubmit(event); + }} + spacing="1em" + > + + + } + /> + + + + + + + + + + + + + + + ); +}; + +export default PrepareHostNetworkForm; diff --git a/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts b/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts new file mode 100644 index 000000000..cfbe0bcfe --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts @@ -0,0 +1,10 @@ +import * as yup from 'yup'; + +import { hostNetInitSchema } from '../HostNetInit'; + +const prepareHostNetworkSchema = yup.object({ + name: yup.string().required(), + networkInit: hostNetInitSchema, +}); + +export default prepareHostNetworkSchema; diff --git a/striker-ui/types/ManageHostNetwork.d.ts b/striker-ui/types/ManageHostNetwork.d.ts new file mode 100644 index 000000000..122e9009b --- /dev/null +++ b/striker-ui/types/ManageHostNetwork.d.ts @@ -0,0 +1,25 @@ +type PrepareHostNetworkFormikValues = HostNetInitFormikExtension & { + hostName: string; + mini: boolean; +}; + +/** HostTabs */ + +type HostTabsProps = { + list: APIHostOverview[]; + setValue: (value: string) => void; + value: false | string; +}; + +/** PrepareHostNetwork */ + +type PrepareHostNetworkProps = { + uuid: string; +}; + +/** PrepareHostNetworkForm */ + +type PrepareHostNetworkFormProps = { + detail: APIHostDetail; + uuid: string; +}; From 3209abf0ce2acf2e1d1a81c1c8f55fb4bf91da06 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Sun, 29 Sep 2024 04:42:39 -0400 Subject: [PATCH 20/50] fix(striker-ui-api): include configured bool in host overview --- .../src/lib/request_handlers/host/getHost.ts | 19 ++++++++++++++++--- striker-ui-api/src/types/ApiHost.d.ts | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/striker-ui-api/src/lib/request_handlers/host/getHost.ts b/striker-ui-api/src/lib/request_handlers/host/getHost.ts index e5faf3245..9b43cd6df 100644 --- a/striker-ui-api/src/lib/request_handlers/host/getHost.ts +++ b/striker-ui-api/src/lib/request_handlers/host/getHost.ts @@ -30,7 +30,8 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => { a.host_type, a.host_uuid, b.anvil_uuid, - b.anvil_name + b.anvil_name, + c.variable_value FROM hosts AS a LEFT JOIN anvils AS b ON a.host_uuid IN ( @@ -38,14 +39,25 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => { b.anvil_node2_host_uuid, b.anvil_dr1_host_uuid ) + LEFT JOIN variables AS c + ON c.variable_name = 'system::configured' + AND c.variable_source_table = 'hosts' + AND a.host_uuid = c.variable_source_uuid ${condition} ORDER BY a.host_name ASC;`; let afterQueryReturn: QueryResultModifierFunction | undefined = buildQueryResultReducer<{ [hostUUID: string]: HostOverview }>( (previous, row) => { - const [hostName, hostStatus, hostType, hostUUID, anvilUuid, anvilName] = - row; + const [ + hostName, + hostStatus, + hostType, + hostUUID, + anvilUuid, + anvilName, + hostConfigured, + ] = row; const key = toLocal(hostUUID, localHostUUID); @@ -60,6 +72,7 @@ export const getHost = buildGetRequestHandler((request, buildQueryOptions) => { previous[key] = { anvil, + hostConfigured: hostConfigured === '1', hostName, hostStatus, hostType, diff --git a/striker-ui-api/src/types/ApiHost.d.ts b/striker-ui-api/src/types/ApiHost.d.ts index a0d6de872..e4637b42f 100644 --- a/striker-ui-api/src/types/ApiHost.d.ts +++ b/striker-ui-api/src/types/ApiHost.d.ts @@ -53,6 +53,7 @@ type HostOverview = { name: string; uuid: string; }; + hostConfigured: boolean; hostName: string; hostStatus: string; hostType: string; From fc6830071d662e6f09466d1bb668be1ecb3e929d Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 04:21:09 -0400 Subject: [PATCH 21/50] fix(striker-ui): patch prepare host network; see details - hoist logic for building striker init/prepare host request body - finish prepare host network request summary and submission - finish guess logic for host networks - finish mini switch --- .../HostNetInit/HostNetInitInputGroup.tsx | 83 +++----- .../HostNetInit/HostNetInputGroup.tsx | 3 +- .../components/HostNetInit/guessHostNets.ts | 195 ++++++++++++++++++ .../ManageHostNetwork/PrepareHostNetwork.tsx | 42 +++- .../PrepareHostNetworkForm.tsx | 117 +++++++++-- .../PrepareHostNetworkSummary.tsx | 92 +++++++++ .../StrikerInit/StrikerInitForm.tsx | 52 +---- striker-ui/lib/buildInitRequestBody.ts | 54 +++++ striker-ui/types/HostNetInit.d.ts | 1 + striker-ui/types/ManageHostNetwork.d.ts | 9 + 10 files changed, 522 insertions(+), 126 deletions(-) create mode 100644 striker-ui/components/HostNetInit/guessHostNets.ts create mode 100644 striker-ui/components/ManageHostNetwork/PrepareHostNetworkSummary.tsx create mode 100644 striker-ui/lib/buildInitRequestBody.ts diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index de77c173a..ce91cf96a 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -3,12 +3,13 @@ import { DragHandle as MuiDragHandleIcon, } from '@mui/icons-material'; import { Box, BoxProps, Grid } from '@mui/material'; -import { capitalize, cloneDeep } from 'lodash'; -import { FC, useMemo, useState } from 'react'; +import { capitalize } from 'lodash'; +import { FC, useMemo, useRef, useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; import DragArea, { dragAreaClasses } from './DragArea'; import DragDataGrid, { dragDataGridClasses } from './DragDataGrid'; +import guessHostNets from './guessHostNets'; import HostNetInputGroup from './HostNetInputGroup'; import IfaceDragHandle, { ifaceDragHandleClasses } from './IfaceDragHandle'; import IconButton from '../IconButton'; @@ -24,7 +25,9 @@ const HostNetInitInputGroup = ( ): ReturnType>> => { const { formikUtils, host, onFetchSuccess } = props; - const { formik, getFieldChanged, handleChange } = formikUtils; + const { formik, handleChange } = formikUtils; + + const firstResponse = useRef(true); const [ifaceHeld, setIfaceHeld] = useState(); @@ -33,7 +36,7 @@ const HostNetInitInputGroup = ( y: 0, }); - const ifacesApplied = useMemo( + const appliedIfaces = useMemo( () => Object.values(formik.values.networkInit.networks).reduce< Record @@ -58,6 +61,7 @@ const HostNetInitInputGroup = ( return { dns: `${base}.dns`, gateway: `${base}.gateway`, + networkInit: base, networks: `${base}.networks`, }; }, []); @@ -66,54 +70,13 @@ const HostNetInitInputGroup = ( `/init/network-interface/${host.uuid}`, { onSuccess: (data) => { - const values = Object.values(data); - - const ifnCandidates = values.filter( - (value) => - !ifacesApplied[value.uuid] && - value.ip && - !/^10\.[12]/.test(value.ip), - ); - - if (host.sequence > 0) { - const bcnSlots = hostNets.filter(([, value]) => value.type === 'bcn'); - - bcnSlots.forEach(([key, slot]) => { - const chain = `${chains.networks}.${key}`; - - if (getFieldChanged(chain)) return; - - const slotClone = cloneDeep(slot); - - slotClone.ip = `10.20${slot.sequence}.4.${host.sequence}`; - slotClone.subnetMask = '255.255.0.0'; - - formik.setFieldValue(chain, slotClone, true); - }); - } - - const ifnSlots = hostNets.filter(([, value]) => value.type === 'ifn'); - - // eslint-disable-next-line complexity - ifnSlots.forEach(([key, slot]) => { - const chain = `${chains.networks}.${key}`; - - if (slot.interfaces[0] !== '' || getFieldChanged(chain)) { - return; - } - - const slotClone = cloneDeep(slot); - const candidate = ifnCandidates.shift(); - - if (!candidate) return; - - slotClone.interfaces[0] = candidate.uuid; - slotClone.ip = candidate.ip || ''; - slotClone.subnetMask = candidate.subnetMask || ''; - - formik.setFieldValue(chain, slotClone, true); - formik.setFieldValue(chains.dns, candidate.dns || '', true); - formik.setFieldValue(chains.gateway, candidate.gateway || '', true); + guessHostNets({ + appliedIfaces, + chains, + data, + host, + firstResponse, + formikUtils, }); onFetchSuccess?.call(null, data); @@ -122,7 +85,7 @@ const HostNetInitInputGroup = ( }, ); - const ifacesValue = useMemo(() => ifaces && Object.values(ifaces), [ifaces]); + const ifaceValues = useMemo(() => ifaces && Object.values(ifaces), [ifaces]); const dragAreaProps = useMemo(() => { if (!ifaceHeld) return undefined; @@ -147,7 +110,7 @@ const HostNetInitInputGroup = ( }; }, [ifaceHeld]); - if (!ifaces || !ifacesValue) { + if (!ifaces || !ifaceValues) { return ; } @@ -193,7 +156,7 @@ const HostNetInitInputGroup = ( }; let icon = ; - if (ifacesApplied[row.uuid]) { + if (appliedIfaces[row.uuid]) { className = ifaceDragHandleClasses.applied; handleMouseDown = undefined; icon = ; @@ -265,7 +228,7 @@ const HostNetInitInputGroup = ( if (!uuid) return; - if (ifacesApplied[uuid]) return; + if (appliedIfaces[uuid]) return; setIfaceHeld(uuid); }, @@ -276,7 +239,7 @@ const HostNetInitInputGroup = ( getRowClassName={(cell) => { const { row } = cell; - return ifaceHeld || ifacesApplied[row.uuid] + return ifaceHeld || appliedIfaces[row.uuid] ? '' : dragDataGridClasses.draggable; }} @@ -285,7 +248,7 @@ const HostNetInitInputGroup = ( initialState={{ sorting: { sortModel: [{ field: 'name', sort: 'asc' }] }, }} - rows={ifacesValue} + rows={ifaceValues} /> ( host={host} ifaceHeld={ifaceHeld} ifaces={ifaces} - ifacesApplied={ifacesApplied} - ifacesValue={ifacesValue} + ifacesApplied={appliedIfaces} + ifacesValue={ifaceValues} key={`hostnet-${key}`} netId={key} /> diff --git a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx index 3a11bbbdc..42e62f651 100644 --- a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx @@ -13,6 +13,7 @@ import { BodyText } from '../Text'; import UncontrolledInput from '../UncontrolledInput'; const NETOPS: Record = { + dr: ['bcn', 'ifn', 'sn'], striker: ['bcn', 'ifn'], subnode: ['bcn', 'ifn', 'sn'], }; @@ -40,7 +41,7 @@ const HostNetInputGroup = ( const nets = formik.values.networkInit.networks; if ( - host.type === 'subnode' && + ['dr', 'subnode'].includes(host.type) && ifacesValue.length >= 8 && (nets[netId].type === 'mn' || Object.values(nets).every((net) => net.type !== 'mn')) diff --git a/striker-ui/components/HostNetInit/guessHostNets.ts b/striker-ui/components/HostNetInit/guessHostNets.ts new file mode 100644 index 000000000..34bb96b21 --- /dev/null +++ b/striker-ui/components/HostNetInit/guessHostNets.ts @@ -0,0 +1,195 @@ +import { cloneDeep } from 'lodash'; +import { v4 as uuidv4 } from 'uuid'; + +const guessHostNets = ({ + appliedIfaces, + chains, + data, + host, + firstResponse, + formikUtils, +}: { + appliedIfaces: Record; + chains: Record<'dns' | 'gateway' | 'networkInit' | 'networks', string>; + data: APINetworkInterfaceOverviewList; + host: HostNetInitHost; + firstResponse: React.MutableRefObject; + formikUtils: FormikUtils; +}) => { + const { formik, getFieldChanged } = formikUtils; + + // Clone at the level that includes all possible changes. + const clone = cloneDeep(formik.values.networkInit); + + const ifaceValues = Object.values(data); + + if (firstResponse.current) { + firstResponse.current = false; + + if (host.type === 'subnode' && ifaceValues.length >= 8) { + const nyuId = uuidv4(); + + clone.networks[nyuId] = { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'mn', + }; + } + } + + // Categorize unapplied interfaces based on their IP. + const candidates = ifaceValues.reduce< + Record<'bcn' | 'ifn' | 'mn' | 'sn', APINetworkInterfaceOverview[]> + >( + (previous, iface) => { + const { ip, uuid } = iface; + + if (appliedIfaces[uuid] || !ip) { + return previous; + } + + if (/^10\.10/.test(ip)) { + previous.sn.push(iface); + } else if (/^10\.19/.test(ip)) { + previous.mn.push(iface); + } else if (/^10\.20/.test(ip)) { + previous.bcn.push(iface); + } else { + previous.ifn.push(iface); + } + + return previous; + }, + { + bcn: [], + ifn: [], + mn: [], + sn: [], + }, + ); + + const hostNets = Object.entries(formik.values.networkInit.networks); + + // Categorize slots based on their type. + const slots = hostNets.reduce< + Record<'bcn' | 'ifn' | 'mn' | 'sn', [string, HostNetFormikValues][]> + >( + (previous, pair) => { + const [, slotValues] = pair; + + if (slotValues.type === 'bcn') { + previous.bcn.push(pair); + } else if (slotValues.type === 'ifn') { + previous.ifn.push(pair); + } else if (slotValues.type === 'mn') { + previous.mn.push(pair); + } else if (slotValues.type === 'sn') { + previous.sn.push(pair); + } + + return previous; + }, + { + bcn: [], + ifn: [], + mn: [], + sn: [], + }, + ); + + if (host.sequence > 0) { + const slotTypes: ['bcn', 'mn', 'sn'] = ['bcn', 'mn', 'sn']; + + const ipo2Prefixes = { + bcn: '20', + sn: '10', + }; + + slotTypes.forEach((slotType) => { + let ipo3 = '??'; + + if (host.parentSequence) { + ipo3 = + host.type === 'striker' + ? '4' + : String(10 + 2 * (host.parentSequence - 1)); + } + + slots[slotType].forEach(([key]) => { + const slot = clone.networks[key]; + + const netChain = `${chains.networks}.${key}`; + const ifChain = `${netChain}.interfaces.0`; + const ipChain = `${netChain}.ip`; + const maskChain = `${netChain}.subnetMask`; + + if (!getFieldChanged(ipChain)) { + const ipo2 = + slotType === 'mn' + ? '199' + : `${ipo2Prefixes[slotType]}${slot.sequence}`; + + const ip = `10.${ipo2}.${ipo3}.${host.sequence}`; + + slot.ip = ip; + } + + if (!getFieldChanged(maskChain)) { + slot.subnetMask = '255.255.0.0'; + } + + if (!getFieldChanged(ifChain)) { + const found = candidates[slotType].find( + (value) => value.ip === slot.ip, + ); + + if (found) { + slot.interfaces[0] = found.uuid; + } + } + }); + }); + } + + // eslint-disable-next-line complexity + slots.ifn.forEach(([key]) => { + const slot = clone.networks[key]; + + const netChain = `${chains.networks}.${key}`; + const ifChain = `${netChain}.interfaces.0`; + const ipChain = `${netChain}.ip`; + const maskChain = `${netChain}.subnetMask`; + + const candidate = candidates.ifn.shift(); + + if (!candidate) return; + + if (!getFieldChanged(ifChain)) { + slot.interfaces[0] = candidate.uuid; + } + + if (!getFieldChanged(ipChain)) { + slot.ip = candidate.ip || ''; + } + + if (!getFieldChanged(maskChain)) { + slot.subnetMask = candidate.subnetMask || ''; + } + + if (slot.sequence !== '1') return; + + if (!getFieldChanged(chains.dns)) { + clone.dns = candidate.dns || ''; + } + + if (!getFieldChanged(chains.gateway)) { + clone.gateway = candidate.gateway || ''; + } + }); + + formik.setFieldValue(chains.networkInit, clone, true); +}; + +export default guessHostNets; diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx index 9d549bf5a..9ca32084d 100644 --- a/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx @@ -1,19 +1,57 @@ -import { FC } from 'react'; +import { FC, useMemo } from 'react'; import PrepareHostNetworkForm from './PrepareHostNetworkForm'; import Spinner from '../Spinner'; +import useConfirmDialog from '../../hooks/useConfirmDialog'; import useFetch from '../../hooks/useFetch'; const PrepareHostNetwork: FC = (props) => { const { uuid } = props; + const { + confirmDialog, + finishConfirm, + setConfirmDialogLoading, + setConfirmDialogOpen, + setConfirmDialogProps, + } = useConfirmDialog({ + initial: { + scrollContent: true, + wide: true, + }, + }); + + const formTools = useMemo( + () => ({ + add: { open: () => null }, + confirm: { + finish: finishConfirm, + loading: setConfirmDialogLoading, + open: (v = true) => setConfirmDialogOpen(v), + prepare: setConfirmDialogProps, + }, + edit: { open: () => null }, + }), + [ + finishConfirm, + setConfirmDialogLoading, + setConfirmDialogOpen, + setConfirmDialogProps, + ], + ); + const { data: detail } = useFetch(`/host/${uuid}`); if (!detail) { return ; } - return ; + return ( + <> + ; + {confirmDialog} + + ); }; export default PrepareHostNetwork; diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx index 175c59f4c..0c1f76807 100644 --- a/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx @@ -1,15 +1,19 @@ import { Grid } from '@mui/material'; -import { FC, useMemo } from 'react'; +import { FC, useMemo, useRef } from 'react'; import ActionGroup from '../ActionGroup'; +import api from '../../lib/api'; +import buildInitRequestBody from '../../lib/buildInitRequestBody'; +import handleAPIError from '../../lib/handleAPIError'; import { HostNetInitInputGroup } from '../HostNetInit'; import MessageGroup from '../MessageGroup'; import OutlinedInputWithLabel from '../OutlinedInputWithLabel'; -import UncontrolledInput from '../UncontrolledInput'; -import useFormikUtils from '../../hooks/useFormikUtils'; -import SwitchWithLabel from '../SwitchWithLabel'; import prepareHostNetworkSchema from './prepareHostNetworkSchema'; +import PrepareHostNetworkSummary from './PrepareHostNetworkSummary'; +import SwitchWithLabel from '../SwitchWithLabel'; import toHostNetList from '../../lib/toHostNetList'; +import UncontrolledInput from '../UncontrolledInput'; +import useFormikUtils from '../../hooks/useFormikUtils'; const buildFormikInitialValues = ( detail: APIHostDetail, @@ -24,21 +28,25 @@ const buildFormikInitialValues = ( subnetMask: '', type: 'bcn', }, - defaultifn: { + }; + + if (detail.hostType === 'node') { + networks.defaultifn = { interfaces: ['', ''], ip: '', sequence: '1', subnetMask: '', type: 'ifn', - }, - defaultsn: { + }; + + networks.defaultsn = { interfaces: ['', ''], ip: '', sequence: '1', subnetMask: '', type: 'sn', - }, - }; + }; + } if (nets) { networks = toHostNetList(nets); @@ -56,28 +64,89 @@ const buildFormikInitialValues = ( }; const PrepareHostNetworkForm: FC = (props) => { - const { detail, uuid } = props; + const { detail, tools, uuid } = props; + + const ifaces = useRef(null); const formikUtils = useFormikUtils({ initialValues: buildFormikInitialValues(detail), onSubmit: (values, { setSubmitting }) => { - setSubmitting(false); + const requestBody = buildInitRequestBody(values, ifaces.current); + + tools.confirm.prepare({ + actionProceedText: 'Prepare network', + content: ifaces.current && ( + + ), + onCancelAppend: () => setSubmitting(false), + onProceedAppend: () => { + tools.confirm.loading(true); + + api + .put( + `/host/${detail.hostUUID}?handler=subnode-network`, + requestBody, + ) + .then(() => { + tools.confirm.finish('Success', { + children: ( + <> + Successfully started network config on{' '} + {detail.shortHostName} + + ), + }); + }) + .catch((error) => { + const emsg = handleAPIError(error); + + emsg.children = ( + <> + Failed to prepare network on {detail.shortHostName}.{' '} + {emsg.children} + + ); + + tools.confirm.finish('Error', emsg); + + setSubmitting(false); + }); + }, + titleText: `Prepare network on ${detail.shortHostName} with the following?`, + }); + + tools.confirm.open(); }, validationSchema: prepareHostNetworkSchema, }); const { disabledSubmit, formik, formikErrors, handleChange } = formikUtils; - const sequence = useMemo(() => { - const trailing = detail.shortHostName.replace(/^.*(\d+)$/, '$1'); + const hostType = useMemo( + () => detail.hostType.replace('node', 'subnode'), + [detail.hostType], + ); + + const { parentSequence, sequence } = useMemo(() => { + const numbers = detail.shortHostName.replace(/^.*a(\d+).*n(\d+)$/, '$1,$2'); - return Number(trailing); + const [parentSeq, seq] = numbers.split(',', 2); + + return { + parentSequence: Number(parentSeq), + sequence: Number(seq), + }; }, [detail.shortHostName]); const chains = useMemo( () => ({ - mini: `mini`, hostName: `hostName`, + mini: `mini`, + networks: `networkInit.networks`, }), [], ); @@ -113,7 +182,17 @@ const PrepareHostNetworkForm: FC = (props) => { id={chains.mini} label="Minimal config" name={chains.mini} - onChange={formik.handleChange} + onChange={(event, checked) => { + if (checked) { + const { defaultbcn } = formik.values.networkInit.networks; + + formik.setFieldValue(chains.networks, { defaultbcn }, true); + } else { + formik.resetForm(); + } + + formik.handleChange(event); + }} checked={formik.values.mini} /> @@ -121,10 +200,14 @@ const PrepareHostNetworkForm: FC = (props) => { { + ifaces.current = data; + }} /> diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetworkSummary.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkSummary.tsx new file mode 100644 index 000000000..5d0656e31 --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkSummary.tsx @@ -0,0 +1,92 @@ +import { Grid } from '@mui/material'; +import { FC } from 'react'; + +import NETWORK_TYPES from '../../lib/consts/NETWORK_TYPES'; + +import { BodyText, InlineMonoText, MonoText } from '../Text'; + +// TODO: this is a modified copy of StrikerInitSummary, find a way to remove +// duplcation. + +const PrepareHostNetworkSummary: FC = ( + props, +) => { + const { gatewayIface, ifaces, values } = props; + + return ( + + + Host name + + + {values.hostName} + + + Networks + + {Object.entries(values.networkInit.networks).map((net) => { + const [netId, { interfaces, ip, sequence, subnetMask, type }] = net; + + return ( + + + + + {NETWORK_TYPES[type]} {sequence} ( + + {`${type.toUpperCase()}${sequence}`} + + ) + + + {interfaces.map((ifaceUuid, ifaceIndex) => { + let key = `network-confirm-${netId}-interface${ifaceIndex}`; + let ifaceName = 'none'; + + if (ifaceUuid !== '') { + key = `${key}-${ifaceUuid}`; + ifaceName = ifaces[ifaceUuid]?.name; + } + + return ( + + + {`Link ${ifaceIndex + 1}`} + + + {ifaceName} + + + ); + })} + + {`${ip}/${subnetMask}`} + + + + ); + })} + + + Gateway + + + {values.networkInit.gateway} + + + Gateway network + + + {gatewayIface.toUpperCase()} + + + Domain name server(s) + + + {values.networkInit.dns} + + + ); +}; + +export default PrepareHostNetworkSummary; diff --git a/striker-ui/components/StrikerInit/StrikerInitForm.tsx b/striker-ui/components/StrikerInit/StrikerInitForm.tsx index 4e88e4620..0fe76c463 100644 --- a/striker-ui/components/StrikerInit/StrikerInitForm.tsx +++ b/striker-ui/components/StrikerInit/StrikerInitForm.tsx @@ -1,11 +1,12 @@ import { Grid } from '@mui/material'; -import { Netmask } from 'netmask'; + import { FC, useCallback, useMemo, useRef } from 'react'; import INPUT_TYPES from '../../lib/consts/INPUT_TYPES'; import ActionGroup from '../ActionGroup'; import api from '../../lib/api'; +import buildInitRequestBody from '../../lib/buildInitRequestBody'; import handleAPIError from '../../lib/handleAPIError'; import { HostNetInitInputGroup } from '../HostNetInit'; import MessageGroup from '../MessageGroup'; @@ -114,55 +115,13 @@ const StrikerInitForm: FC = (props) => { const formikUtils = useFormikUtils({ initialValues: buildFormikInitialValues(detail), onSubmit: (values, { setSubmitting }) => { - const { networkInit: netInit, ...restValues } = values; - const { networks, ...restNetInit } = netInit; - - const ns = Object.values(networks); - - const rqbody = { - ...restValues, - ...restNetInit, - gatewayInterface: ns.reduce((previous, n) => { - const { ip, sequence, subnetMask, type } = n; - - let subnet: Netmask; - - try { - subnet = new Netmask(`${ip}/${subnetMask}`); - } catch (error) { - return previous; - } - - if (subnet.contains(netInit.gateway)) { - return `${type}${sequence}`; - } - - return previous; - }, ''), - networks: ns.map((n) => { - const { interfaces, ip, sequence, subnetMask, type } = n; - - return { - interfaces: interfaces.map((ifUuid) => - ifUuid - ? { - mac: ifaces.current?.[ifUuid]?.mac, - } - : null, - ), - ipAddress: ip, - sequence, - subnetMask, - type, - }; - }), - }; + const requestBody = buildInitRequestBody(values, ifaces.current); tools.confirm.prepare({ actionProceedText: 'Initialize', content: ifaces.current && ( @@ -172,7 +131,7 @@ const StrikerInitForm: FC = (props) => { tools.confirm.loading(true); api - .put('/init', rqbody) + .put('/init', requestBody) .then((response) => { onSubmitSuccess?.call(null, response.data); @@ -407,6 +366,7 @@ const StrikerInitForm: FC = (props) => { ( + values: Values, + ifaces: APINetworkInterfaceOverviewList | null, +) => { + const { networkInit: netInit, ...restValues } = values; + const { networks, ...restNetInit } = netInit; + + const ns = Object.values(networks); + + const requestBody = { + ...restValues, + ...restNetInit, + gatewayInterface: ns.reduce((previous, n) => { + const { ip, sequence, subnetMask, type } = n; + + let subnet: Netmask; + + try { + subnet = new Netmask(`${ip}/${subnetMask}`); + } catch (error) { + return previous; + } + + if (subnet.contains(netInit.gateway)) { + return `${type}${sequence}`; + } + + return previous; + }, ''), + networks: ns.map((n) => { + const { interfaces, ip, sequence, subnetMask, type } = n; + + return { + interfaces: interfaces.map((ifUuid) => + ifUuid + ? { + mac: ifaces?.[ifUuid]?.mac, + } + : null, + ), + ipAddress: ip, + sequence, + subnetMask, + type, + }; + }), + }; + + return requestBody; +}; + +export default buildInitRequestBody; diff --git a/striker-ui/types/HostNetInit.d.ts b/striker-ui/types/HostNetInit.d.ts index 75d9f5888..633fcdfd9 100644 --- a/striker-ui/types/HostNetInit.d.ts +++ b/striker-ui/types/HostNetInit.d.ts @@ -17,6 +17,7 @@ type HostNetInitFormikExtension = { }; type HostNetInitHost = { + parentSequence: number; sequence: number; type: string; uuid: string; diff --git a/striker-ui/types/ManageHostNetwork.d.ts b/striker-ui/types/ManageHostNetwork.d.ts index 122e9009b..364670de8 100644 --- a/striker-ui/types/ManageHostNetwork.d.ts +++ b/striker-ui/types/ManageHostNetwork.d.ts @@ -21,5 +21,14 @@ type PrepareHostNetworkProps = { type PrepareHostNetworkFormProps = { detail: APIHostDetail; + tools: CrudListFormTools; uuid: string; }; + +/** PrepareHostNetworkSummary */ + +type PrepareHostNetworkSummaryProps = { + gatewayIface: string; + ifaces: APINetworkInterfaceOverviewList; + values: PrepareHostNetworkFormikValues; +}; From a32d712dab360ccb5ec7d52e629650e8c5b4e349 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 04:29:43 -0400 Subject: [PATCH 22/50] fix(striker-ui): replace tab in manage-element page --- .../components/ManageHostNetwork/index.tsx | 4 + striker-ui/pages/manage-element/index.tsx | 91 +++---------------- 2 files changed, 18 insertions(+), 77 deletions(-) create mode 100644 striker-ui/components/ManageHostNetwork/index.tsx diff --git a/striker-ui/components/ManageHostNetwork/index.tsx b/striker-ui/components/ManageHostNetwork/index.tsx new file mode 100644 index 000000000..35d057b4e --- /dev/null +++ b/striker-ui/components/ManageHostNetwork/index.tsx @@ -0,0 +1,4 @@ +import ManageHostNetwork from './ManageHostNetwork'; +import prepareHostNetworkSchema from './prepareHostNetworkSchema'; + +export { ManageHostNetwork, prepareHostNetworkSchema }; diff --git a/striker-ui/pages/manage-element/index.tsx b/striker-ui/pages/manage-element/index.tsx index 9342f193d..767b48ea0 100644 --- a/striker-ui/pages/manage-element/index.tsx +++ b/striker-ui/pages/manage-element/index.tsx @@ -1,24 +1,20 @@ import Head from 'next/head'; import { useRouter } from 'next/router'; -import { FC, ReactElement, useEffect, useMemo, useState } from 'react'; +import { FC, useEffect, useState } from 'react'; -import api from '../../lib/api'; import getQueryParam from '../../lib/getQueryParam'; import Grid from '../../components/Grid'; -import handleAPIError from '../../lib/handleAPIError'; import Header from '../../components/Header'; import ManageFencePanel from '../../components/ManageFence'; import { ManageHost } from '../../components/ManageHost'; +import { ManageHostNetwork } from '../../components/ManageHostNetwork'; import ManageManifestPanel from '../../components/ManageManifest'; import ManageUpsPanel from '../../components/ManageUps'; import { Panel, PanelHeader } from '../../components/Panels'; -import PrepareNetworkForm from '../../components/PrepareNetworkForm'; -import Spinner from '../../components/Spinner'; import Tab from '../../components/Tab'; import TabContent from '../../components/TabContent'; import Tabs from '../../components/Tabs'; import { HeaderText } from '../../components/Text'; -import useIsFirstRender from '../../hooks/useIsFirstRender'; const TAB_ID_PREPARE_HOST = 'prepare-host'; const TAB_ID_PREPARE_NETWORK = 'prepare-network'; @@ -57,77 +53,18 @@ const PrepareHostTabContent: FC = () => ( /> ); -const PrepareNetworkTabContent: FC = () => { - const isFirstRender = useIsFirstRender(); - - const [hostOverviewList, setHostOverviewList] = useState< - APIHostOverviewList | undefined - >(); - const [hostSubTabId, setHostSubTabId] = useState(false); - - const hostSubTabs = useMemo(() => { - let result: ReactElement | undefined; - - if (hostOverviewList) { - const hostOverviewPairs = Object.entries(hostOverviewList); - - result = ( - { - setHostSubTabId(newSubTabId); - }} - orientation="vertical" - value={hostSubTabId} - > - {hostOverviewPairs.map(([hostUUID, { shortHostName }]) => ( - - ))} - - ); - } else { - result = ; - } - - return result; - }, [hostOverviewList, hostSubTabId]); - - if (isFirstRender) { - api - .get('/host', { params: { types: ['dr', 'node'] } }) - .then(({ data }) => { - setHostOverviewList(data); - setHostSubTabId(Object.keys(data)[0]); - }) - .catch((error) => { - handleAPIError(error); - }); - } - - return ( - {hostSubTabs}, - sm: 2, - }, - 'preparenetwork-center-column': { - children: ( - - ), - ...STEP_CONTENT_GRID_CENTER_COLUMN, - }, - }} - /> - ); -}; +const PrepareNetworkTabContent: FC = () => ( + , + ...STEP_CONTENT_GRID_CENTER_COLUMN, + }, + }} + /> +); const ManageFenceTabContent: FC = () => ( Date: Tue, 1 Oct 2024 14:43:48 -0400 Subject: [PATCH 23/50] fix(striker-ui): correct auto add mn in host net init --- .../HostNetInit/HostNetInitInputGroup.tsx | 4 +-- .../components/HostNetInit/guessHostNets.ts | 26 +++++++++---------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index ce91cf96a..b968cd490 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -27,7 +27,7 @@ const HostNetInitInputGroup = ( const { formik, handleChange } = formikUtils; - const firstResponse = useRef(true); + const autoAddMn = useRef(true); const [ifaceHeld, setIfaceHeld] = useState(); @@ -75,7 +75,7 @@ const HostNetInitInputGroup = ( chains, data, host, - firstResponse, + autoAddMn, formikUtils, }); diff --git a/striker-ui/components/HostNetInit/guessHostNets.ts b/striker-ui/components/HostNetInit/guessHostNets.ts index 34bb96b21..b0251ba5c 100644 --- a/striker-ui/components/HostNetInit/guessHostNets.ts +++ b/striker-ui/components/HostNetInit/guessHostNets.ts @@ -6,14 +6,14 @@ const guessHostNets = ({ chains, data, host, - firstResponse, + autoAddMn, formikUtils, }: { appliedIfaces: Record; chains: Record<'dns' | 'gateway' | 'networkInit' | 'networks', string>; data: APINetworkInterfaceOverviewList; host: HostNetInitHost; - firstResponse: React.MutableRefObject; + autoAddMn: React.MutableRefObject; formikUtils: FormikUtils; }) => { const { formik, getFieldChanged } = formikUtils; @@ -23,20 +23,18 @@ const guessHostNets = ({ const ifaceValues = Object.values(data); - if (firstResponse.current) { - firstResponse.current = false; + if (autoAddMn.current && host.type === 'subnode' && ifaceValues.length >= 8) { + const nyuId = uuidv4(); - if (host.type === 'subnode' && ifaceValues.length >= 8) { - const nyuId = uuidv4(); + clone.networks[nyuId] = { + interfaces: ['', ''], + ip: '', + sequence: '1', + subnetMask: '', + type: 'mn', + }; - clone.networks[nyuId] = { - interfaces: ['', ''], - ip: '', - sequence: '1', - subnetMask: '', - type: 'mn', - }; - } + autoAddMn.current = false; } // Categorize unapplied interfaces based on their IP. From cbfc9a079caa3a1bd3315926bac99e10356ac256 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 14:55:19 -0400 Subject: [PATCH 24/50] fix(striker-ui): correct net ip 3rd octet guess in host net init --- striker-ui/components/HostNetInit/guessHostNets.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/striker-ui/components/HostNetInit/guessHostNets.ts b/striker-ui/components/HostNetInit/guessHostNets.ts index b0251ba5c..75227f822 100644 --- a/striker-ui/components/HostNetInit/guessHostNets.ts +++ b/striker-ui/components/HostNetInit/guessHostNets.ts @@ -108,11 +108,10 @@ const guessHostNets = ({ slotTypes.forEach((slotType) => { let ipo3 = '??'; - if (host.parentSequence) { - ipo3 = - host.type === 'striker' - ? '4' - : String(10 + 2 * (host.parentSequence - 1)); + if (host.type === 'striker') { + ipo3 = '4'; + } else if (host.parentSequence) { + ipo3 = String(10 + 2 * (host.parentSequence - 1)); } slots[slotType].forEach(([key]) => { From c3cad3272980ebd87b7a38c795d7ffe20fbbb9db Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 14:56:19 -0400 Subject: [PATCH 25/50] fix(striker-ui): disable add net when not enough ifaces in host net init --- .../components/HostNetInit/HostNetInitInputGroup.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index b968cd490..ff603d859 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -50,11 +50,6 @@ const HostNetInitInputGroup = ( [formik.values.networkInit.networks], ); - const hostNets = useMemo( - () => Object.entries(formik.values.networkInit.networks), - [formik.values.networkInit.networks], - ); - const chains = useMemo(() => { const base = 'networkInit'; @@ -85,6 +80,11 @@ const HostNetInitInputGroup = ( }, ); + const hostNets = useMemo( + () => Object.entries(formik.values.networkInit.networks), + [formik.values.networkInit.networks], + ); + const ifaceValues = useMemo(() => ifaces && Object.values(ifaces), [ifaces]); const dragAreaProps = useMemo(() => { @@ -292,6 +292,7 @@ const HostNetInitInputGroup = ( = ifaceValues.length} mapPreset="add" onClick={() => { const key = uuidv4(); From 890d42e582cd693338198052ffd6f1e7aa0a152c Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 15:12:43 -0400 Subject: [PATCH 26/50] fix(striker-ui-api): always expose /init/job/:uuid, remove /init/job --- striker-ui-api/src/routes/init.ts | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/striker-ui-api/src/routes/init.ts b/striker-ui-api/src/routes/init.ts index b736c7ce7..abf8a64af 100644 --- a/striker-ui-api/src/routes/init.ts +++ b/striker-ui-api/src/routes/init.ts @@ -3,38 +3,13 @@ import express from 'express'; import { assertInit } from '../middlewares'; import { configStriker } from '../lib/request_handlers/host'; -import { getJob, getJobDetail } from '../lib/request_handlers/job'; +import { getJobDetail } from '../lib/request_handlers/job'; import { getNetworkInterface } from '../lib/request_handlers/network-interface'; const router = express.Router(); router - .get( - '/job', - (request, response, next) => { - const { - path, - query: { command }, - } = request; - - const script = 'anvil-configure-host'; - - if (command === script) return next(); - - return response.redirect(`/api/init${path}?command=${script}`); - }, - assertInit({ - fail: (request, response, next) => next(), - }), - getJob, - ) - .get( - '/job/:uuid', - assertInit({ - fail: ({ path }, response) => response.redirect(307, `/api${path}`), - }), - getJobDetail, - ) + .get('/job/:uuid', getJobDetail) .get( '/network-interface/:hostUUID?', assertInit({ From cf3f299777fac4d2d9e036eaad1711fc43e91c44 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 15:22:04 -0400 Subject: [PATCH 27/50] fix(striker-ui): correct fetch job url in striker init progress --- striker-ui/components/StrikerInit/StrikerInitProgress.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui/components/StrikerInit/StrikerInitProgress.tsx b/striker-ui/components/StrikerInit/StrikerInitProgress.tsx index 11fb1e801..94230603c 100644 --- a/striker-ui/components/StrikerInit/StrikerInitProgress.tsx +++ b/striker-ui/components/StrikerInit/StrikerInitProgress.tsx @@ -45,7 +45,7 @@ const StrikerInitProgress: FC = (props) => { return { label, path }; }, [reinit]); - const { data: initJob } = useFetch(`/job/${jobUuid}`, { + const { data: initJob } = useFetch(`/init/job/${jobUuid}`, { onSuccess: (data) => { const { progress } = data; From 40b05018d0866a39686c410bedaddd054f34739f Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 15:23:11 -0400 Subject: [PATCH 28/50] fix(striker-ui): uncap title in striker init --- striker-ui/components/StrikerInit/StrikerInit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui/components/StrikerInit/StrikerInit.tsx b/striker-ui/components/StrikerInit/StrikerInit.tsx index 5f078292d..da93f3886 100644 --- a/striker-ui/components/StrikerInit/StrikerInit.tsx +++ b/striker-ui/components/StrikerInit/StrikerInit.tsx @@ -64,7 +64,7 @@ const StrikerInit: FC = () => { <> - {detail ? 'Rei' : 'I'}nitialize Striker + {detail ? 'Rei' : 'I'}nitialize striker Date: Tue, 1 Oct 2024 15:35:39 -0400 Subject: [PATCH 29/50] fix(striker-ui): don't render semicolon in prepare host network --- striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx index 9ca32084d..50c9cd33d 100644 --- a/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetwork.tsx @@ -48,7 +48,7 @@ const PrepareHostNetwork: FC = (props) => { return ( <> - ; + {confirmDialog} ); From dd1876415193a239fdb218273dc26f48bb221619 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 15:37:24 -0400 Subject: [PATCH 30/50] fix(striker-ui): correct prop name in prepare host network schema --- .../components/ManageHostNetwork/prepareHostNetworkSchema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts b/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts index cfbe0bcfe..2b0189d44 100644 --- a/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts +++ b/striker-ui/components/ManageHostNetwork/prepareHostNetworkSchema.ts @@ -3,7 +3,7 @@ import * as yup from 'yup'; import { hostNetInitSchema } from '../HostNetInit'; const prepareHostNetworkSchema = yup.object({ - name: yup.string().required(), + hostName: yup.string().required(), networkInit: hostNetInitSchema, }); From 3b71d50a9e78b7667c9aedbcf8fd1733681c7950 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 15:38:22 -0400 Subject: [PATCH 31/50] fix(striker-ui): add empty message in tabs of manage host network --- striker-ui/components/ManageHostNetwork/HostTabs.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/striker-ui/components/ManageHostNetwork/HostTabs.tsx b/striker-ui/components/ManageHostNetwork/HostTabs.tsx index 37f7d043c..6e0e92090 100644 --- a/striker-ui/components/ManageHostNetwork/HostTabs.tsx +++ b/striker-ui/components/ManageHostNetwork/HostTabs.tsx @@ -8,6 +8,10 @@ import { BodyText } from '../Text'; const HostTabs: FC = (props) => { const { list: hostValues, setValue, value } = props; + if (hostValues.length === 0) { + return No host(s) found.; + } + return ( Date: Tue, 1 Oct 2024 18:19:52 -0400 Subject: [PATCH 32/50] fix(striker-ui): don't guess if there're existing values in host net init --- .../components/HostNetInit/guessHostNets.ts | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/striker-ui/components/HostNetInit/guessHostNets.ts b/striker-ui/components/HostNetInit/guessHostNets.ts index 75227f822..9a8b23a07 100644 --- a/striker-ui/components/HostNetInit/guessHostNets.ts +++ b/striker-ui/components/HostNetInit/guessHostNets.ts @@ -114,15 +114,19 @@ const guessHostNets = ({ ipo3 = String(10 + 2 * (host.parentSequence - 1)); } + // eslint-disable-next-line complexity slots[slotType].forEach(([key]) => { const slot = clone.networks[key]; + const initialSlot: HostNetFormikValues | undefined = + formik.initialValues.networkInit.networks[key]; + const netChain = `${chains.networks}.${key}`; const ifChain = `${netChain}.interfaces.0`; const ipChain = `${netChain}.ip`; const maskChain = `${netChain}.subnetMask`; - if (!getFieldChanged(ipChain)) { + if (!getFieldChanged(ipChain) && !initialSlot?.ip) { const ipo2 = slotType === 'mn' ? '199' @@ -133,11 +137,11 @@ const guessHostNets = ({ slot.ip = ip; } - if (!getFieldChanged(maskChain)) { + if (!getFieldChanged(maskChain) && !initialSlot?.subnetMask) { slot.subnetMask = '255.255.0.0'; } - if (!getFieldChanged(ifChain)) { + if (!getFieldChanged(ifChain) && !initialSlot?.interfaces[0]) { const found = candidates[slotType].find( (value) => value.ip === slot.ip, ); @@ -154,6 +158,11 @@ const guessHostNets = ({ slots.ifn.forEach(([key]) => { const slot = clone.networks[key]; + const initialSlot: HostNetFormikValues | undefined = + formik.initialValues.networkInit.networks[key]; + const initialParent: HostNetInitFormikValues = + formik.initialValues.networkInit; + const netChain = `${chains.networks}.${key}`; const ifChain = `${netChain}.interfaces.0`; const ipChain = `${netChain}.ip`; @@ -163,25 +172,25 @@ const guessHostNets = ({ if (!candidate) return; - if (!getFieldChanged(ifChain)) { + if (!getFieldChanged(ifChain) && !initialSlot?.interfaces[0]) { slot.interfaces[0] = candidate.uuid; } - if (!getFieldChanged(ipChain)) { + if (!getFieldChanged(ipChain) && !initialSlot?.ip) { slot.ip = candidate.ip || ''; } - if (!getFieldChanged(maskChain)) { + if (!getFieldChanged(maskChain) && !initialSlot?.subnetMask) { slot.subnetMask = candidate.subnetMask || ''; } if (slot.sequence !== '1') return; - if (!getFieldChanged(chains.dns)) { + if (!getFieldChanged(chains.dns) && !initialParent.dns) { clone.dns = candidate.dns || ''; } - if (!getFieldChanged(chains.gateway)) { + if (!getFieldChanged(chains.gateway) && !initialParent.gateway) { clone.gateway = candidate.gateway || ''; } }); From bba94bfdfcaea17a59233672bfe53d5f1f7b23cd Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 19:16:13 -0400 Subject: [PATCH 33/50] fix(striker-ui): correct ip 2nd octet guess in host net init --- striker-ui/components/HostNetInit/guessHostNets.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/striker-ui/components/HostNetInit/guessHostNets.ts b/striker-ui/components/HostNetInit/guessHostNets.ts index 9a8b23a07..cb5dd4738 100644 --- a/striker-ui/components/HostNetInit/guessHostNets.ts +++ b/striker-ui/components/HostNetInit/guessHostNets.ts @@ -101,8 +101,8 @@ const guessHostNets = ({ const slotTypes: ['bcn', 'mn', 'sn'] = ['bcn', 'mn', 'sn']; const ipo2Prefixes = { - bcn: '20', - sn: '10', + bcn: 200, + sn: 100, }; slotTypes.forEach((slotType) => { @@ -110,7 +110,7 @@ const guessHostNets = ({ if (host.type === 'striker') { ipo3 = '4'; - } else if (host.parentSequence) { + } else if (host.parentSequence > 0) { ipo3 = String(10 + 2 * (host.parentSequence - 1)); } @@ -129,8 +129,8 @@ const guessHostNets = ({ if (!getFieldChanged(ipChain) && !initialSlot?.ip) { const ipo2 = slotType === 'mn' - ? '199' - : `${ipo2Prefixes[slotType]}${slot.sequence}`; + ? 199 + : ipo2Prefixes[slotType] + Number(slot.sequence); const ip = `10.${ipo2}.${ipo3}.${host.sequence}`; From 3520451f7af008aa6e4e1711381a8d5fb40f0b2b Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 19:16:59 -0400 Subject: [PATCH 34/50] fix(striker-ui): make net type required in host net input group --- striker-ui/components/HostNetInit/HostNetInputGroup.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx index 42e62f651..a0f73fb4f 100644 --- a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx @@ -85,6 +85,7 @@ const HostNetInputGroup = ( label="Network type" name={chains.type} onChange={formik.handleChange} + required selectItems={netTypeOptions} value={formik.values.networkInit.networks[netId].type} /> From 2a0654df98c85fb0e334636f79d8a914822ddbd0 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 19:23:44 -0400 Subject: [PATCH 35/50] fix(striker-ui): align variable names in host net init --- .../HostNetInit/HostNetInitInputGroup.tsx | 4 ++-- .../components/HostNetInit/HostNetInputGroup.tsx | 16 ++++++++-------- striker-ui/types/HostNetInit.d.ts | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index ff603d859..980a9933d 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -276,12 +276,12 @@ const HostNetInitInputGroup = ( return ( + appliedIfaces={appliedIfaces} formikUtils={formikUtils} host={host} ifaceHeld={ifaceHeld} ifaces={ifaces} - ifacesApplied={appliedIfaces} - ifacesValue={ifaceValues} + ifaceValues={ifaceValues} key={`hostnet-${key}`} netId={key} /> diff --git a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx index a0f73fb4f..721a2e146 100644 --- a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx @@ -22,12 +22,12 @@ const HostNetInputGroup = ( ...[props]: Parameters>> ): ReturnType>> => { const { + appliedIfaces, formikUtils, host, ifaceHeld, ifaces, - ifacesApplied, - ifacesValue, + ifaceValues, netId, } = props; @@ -42,7 +42,7 @@ const HostNetInputGroup = ( if ( ['dr', 'subnode'].includes(host.type) && - ifacesValue.length >= 8 && + ifaceValues.length >= 8 && (nets[netId].type === 'mn' || Object.values(nets).every((net) => net.type !== 'mn')) ) { @@ -56,7 +56,7 @@ const HostNetInputGroup = ( }, [ formik.values.networkInit.networks, host.type, - ifacesValue.length, + ifaceValues.length, netId, ]); @@ -136,7 +136,7 @@ const HostNetInputGroup = ( - ifacesApplied[option.uuid] && + appliedIfaces[option.uuid] && option.uuid !== formik.values.networkInit.networks[netId].interfaces[0] } @@ -155,7 +155,7 @@ const HostNetInputGroup = ( ); }} openOnFocus - options={ifacesValue} + options={ifaceValues} renderOption={(optionProps, option) => (
  • {option.name} @@ -180,7 +180,7 @@ const HostNetInputGroup = ( - ifacesApplied[option.uuid] && + appliedIfaces[option.uuid] && option.uuid !== formik.values.networkInit.networks[netId].interfaces[1] } @@ -199,7 +199,7 @@ const HostNetInputGroup = ( ); }} openOnFocus - options={ifacesValue} + options={ifaceValues} renderOption={(optionProps, option) => (
  • {option.name} diff --git a/striker-ui/types/HostNetInit.d.ts b/striker-ui/types/HostNetInit.d.ts index 633fcdfd9..3cc0f919e 100644 --- a/striker-ui/types/HostNetInit.d.ts +++ b/striker-ui/types/HostNetInit.d.ts @@ -32,10 +32,10 @@ type HostNetInputGroupOptionalProps = { type HostNetInputGroupProps = HostNetInputGroupOptionalProps & { + appliedIfaces: Record; formikUtils: FormikUtils; ifaces: APINetworkInterfaceOverviewList; - ifacesApplied: Record; - ifacesValue: APINetworkInterfaceOverview[]; + ifaceValues: APINetworkInterfaceOverview[]; host: HostNetInitHost; netId: string; }; From fd5a57546aa35225e10a80ec2ea47456b1463bc6 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 19:36:08 -0400 Subject: [PATCH 36/50] fix(striker-ui): order most recently changed iface first --- .../request_handlers/network-interface/getNetworkInterface.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts b/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts index 7c02203b1..d5f10ff16 100644 --- a/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts +++ b/striker-ui-api/src/lib/request_handlers/network-interface/getNetworkInterface.ts @@ -24,7 +24,7 @@ export const getNetworkInterface = buildGetRequestHandler( ELSE 'down' END AS iface_state, a.network_interface_speed, - ROW_NUMBER() OVER(ORDER BY a.modified_date ASC) AS iface_order, + ROW_NUMBER() OVER(ORDER BY a.modified_date DESC) AS iface_order, b.ip_address_address, b.ip_address_subnet_mask, b.ip_address_gateway, From 007a2704218bfa420a02843f83bf41e61119731f Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 19:39:51 -0400 Subject: [PATCH 37/50] fix(striker-ui): readd re param to reconfig striker link --- striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx b/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx index c32c8ec17..94c35cd92 100644 --- a/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx +++ b/striker-ui/components/StrikerConfig/SimpleOperationsPanel.tsx @@ -123,7 +123,9 @@ const SimpleOperationsPanel: FC = ({ - Reconfigure striker + + Reconfigure striker + Date: Tue, 1 Oct 2024 19:45:48 -0400 Subject: [PATCH 38/50] fix(striker-ui): expand page width if sm breakpoint --- striker-ui/components/PageBody.tsx | 4 ++-- striker-ui/pages/manage-element/index.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/striker-ui/components/PageBody.tsx b/striker-ui/components/PageBody.tsx index 2b3f502b0..2d63baf7f 100644 --- a/striker-ui/components/PageBody.tsx +++ b/striker-ui/components/PageBody.tsx @@ -5,9 +5,9 @@ const PageBody: FC = (props) => { const { children } = props; return ( - + - + {children} diff --git a/striker-ui/pages/manage-element/index.tsx b/striker-ui/pages/manage-element/index.tsx index 767b48ea0..c091e45fb 100644 --- a/striker-ui/pages/manage-element/index.tsx +++ b/striker-ui/pages/manage-element/index.tsx @@ -30,8 +30,8 @@ const MAP_TO_PAGE_TITLE: Record = { [TAB_ID_MANAGE_MANIFEST]: 'Manage Manifests', }; const PAGE_TITLE_LOADING = 'Loading'; -const STEP_CONTENT_GRID_COLUMNS = { md: 8, sm: 6, xs: 1 }; -const STEP_CONTENT_GRID_CENTER_COLUMN = { md: 6, sm: 4, xs: 1 }; +const STEP_CONTENT_GRID_COLUMNS = { md: 8, xs: 1 }; +const STEP_CONTENT_GRID_CENTER_COLUMN = { md: 6, xs: 1 }; const PrepareHostTabContent: FC = () => ( Date: Tue, 1 Oct 2024 20:09:06 -0400 Subject: [PATCH 39/50] fix(striker-ui): always update step query param in /manage-element --- striker-ui/pages/manage-element/index.tsx | 50 +++++++++++++---------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/striker-ui/pages/manage-element/index.tsx b/striker-ui/pages/manage-element/index.tsx index c091e45fb..c5d1eed55 100644 --- a/striker-ui/pages/manage-element/index.tsx +++ b/striker-ui/pages/manage-element/index.tsx @@ -106,33 +106,37 @@ const ManageManifestContent: FC = () => ( ); const ManageElement: FC = () => { - const { - isReady, - query: { step: rawStep }, - } = useRouter(); + const { isReady, push, query } = useRouter(); const [pageTabId, setPageTabId] = useState(false); const [pageTitle, setPageTitle] = useState(PAGE_TITLE_LOADING); useEffect(() => { - if (isReady) { - let step = getQueryParam(rawStep, { - fallbackValue: TAB_ID_PREPARE_HOST, - }); - - if (!MAP_TO_PAGE_TITLE[step]) { - step = TAB_ID_PREPARE_HOST; - } - - if (pageTitle === PAGE_TITLE_LOADING) { - setPageTitle(MAP_TO_PAGE_TITLE[step]); - } - - if (!pageTabId) { - setPageTabId(step); - } + if (!isReady) return; + + const { step: rawStep } = query; + + let step = getQueryParam(rawStep, { + fallbackValue: TAB_ID_PREPARE_HOST, + }); + + if (!MAP_TO_PAGE_TITLE[step]) { + step = TAB_ID_PREPARE_HOST; + } + + push({ query: { ...query, step } }, undefined, { shallow: true }); + + if (pageTitle === PAGE_TITLE_LOADING) { + setPageTitle(MAP_TO_PAGE_TITLE[step]); + } + + if (!pageTabId) { + setPageTabId(step); } - }, [isReady, pageTabId, pageTitle, rawStep]); + + // Everything should be available when router is ready. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isReady]); return ( <> @@ -145,6 +149,10 @@ const ManageElement: FC = () => { onChange={(event, newTabId) => { setPageTabId(newTabId); setPageTitle(MAP_TO_PAGE_TITLE[newTabId]); + + push({ query: { ...query, step: newTabId } }, undefined, { + shallow: true, + }); }} orientation={{ xs: 'vertical', sm: 'horizontal' }} value={pageTabId} From b1351835f917dd6961f44afeb01fc5b29b23e06f Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 20:39:02 -0400 Subject: [PATCH 40/50] fix(striker-ui): reduce spacing between network type,# in host net input group --- striker-ui/components/HostNetInit/HostNetInputGroup.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx index 721a2e146..eaab58045 100644 --- a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx @@ -78,7 +78,7 @@ const HostNetInputGroup = ( return ( - + ( input={ Date: Tue, 1 Oct 2024 20:39:56 -0400 Subject: [PATCH 41/50] fix(striker-ui): show 4 networks on large breakpoint in host net init --- striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index 980a9933d..1ef5b0442 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -257,6 +257,7 @@ const HostNetInitInputGroup = ( xs: '100%', sm: '50%', md: 'calc(100% / 3)', + lg: '25%', }, gridAutoFlow: 'column', overflowX: 'scroll', From 97ae262e7711602855e6596905a33a6688decef8 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Tue, 1 Oct 2024 20:46:20 -0400 Subject: [PATCH 42/50] fix(striker-ui): add expandable space before mini switch in prepare host network form --- .../components/ManageHostNetwork/PrepareHostNetworkForm.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx index 0c1f76807..6f697ad38 100644 --- a/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx +++ b/striker-ui/components/ManageHostNetwork/PrepareHostNetworkForm.tsx @@ -153,7 +153,7 @@ const PrepareHostNetworkForm: FC = (props) => { return ( { @@ -177,6 +177,7 @@ const PrepareHostNetworkForm: FC = (props) => { } /> + Date: Tue, 1 Oct 2024 20:59:39 -0400 Subject: [PATCH 43/50] fix(striker-ui): show host status in tabs of manage host network --- .../components/ManageHostNetwork/HostTabs.tsx | 21 +++++++++++-------- striker-ui/types/APIHost.d.ts | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/striker-ui/components/ManageHostNetwork/HostTabs.tsx b/striker-ui/components/ManageHostNetwork/HostTabs.tsx index 6e0e92090..915c293bd 100644 --- a/striker-ui/components/ManageHostNetwork/HostTabs.tsx +++ b/striker-ui/components/ManageHostNetwork/HostTabs.tsx @@ -1,9 +1,11 @@ import { Grid } from '@mui/material'; import { FC } from 'react'; +import { DIVIDER } from '../../lib/consts/DEFAULT_THEME'; + import Tab from '../Tab'; import Tabs from '../Tabs'; -import { BodyText } from '../Text'; +import { BodyText, MonoText } from '../Text'; const HostTabs: FC = (props) => { const { list: hostValues, setValue, value } = props; @@ -22,24 +24,25 @@ const HostTabs: FC = (props) => { value={value} > {hostValues.map((host) => { - const { anvil, hostStatus, hostUUID, shortHostName } = host; + const { hostConfigured, hostStatus, hostUUID, shortHostName } = host; return ( + - {shortHostName} - - - {anvil ? `in ${anvil.name}` : 'is free'} + {shortHostName} - - {hostStatus} + + + {hostStatus} + {hostConfigured ? ', configured' : ''} + } + sx={{ textAlign: 'left' }} value={hostUUID} /> ); diff --git a/striker-ui/types/APIHost.d.ts b/striker-ui/types/APIHost.d.ts index 816918118..8a462d852 100644 --- a/striker-ui/types/APIHost.d.ts +++ b/striker-ui/types/APIHost.d.ts @@ -43,6 +43,7 @@ type APIHostOverview = { name: string; uuid: string; }; + hostConfigured: boolean; hostName: string; hostStatus: APIHostStatus; hostType: string; From bed68bfa9665124b42cea90b60bc38d36c0cba57 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Oct 2024 00:04:15 -0400 Subject: [PATCH 44/50] fix(striker-ui): hoist styles in decorator --- striker-ui/components/Decorator.tsx | 67 +++++++++++++---------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/striker-ui/components/Decorator.tsx b/striker-ui/components/Decorator.tsx index 37640e561..04a71d69c 100644 --- a/striker-ui/components/Decorator.tsx +++ b/striker-ui/components/Decorator.tsx @@ -1,5 +1,6 @@ -import { Box as MUIBox, BoxProps as MUIBoxProps } from '@mui/material'; +import { Box, BoxProps, styled } from '@mui/material'; import { FC } from 'react'; + import { BLUE, GREY, @@ -8,9 +9,9 @@ import { BORDER_RADIUS, } from '../lib/consts/DEFAULT_THEME'; -export type Colours = 'ok' | 'off' | 'error' | 'warning'; +type Colours = 'ok' | 'off' | 'error' | 'warning'; -type DecoratorProps = MUIBoxProps & { +type DecoratorProps = BoxProps & { colour: Colours; }; @@ -23,40 +24,32 @@ const classes = { off: `${PREFIX}-off`, }; -const Decorator: FC = ({ - colour, - sx, - ...restDecoratorProps -}): JSX.Element => ( - +const BaseBox = styled(Box)({ + borderRadius: BORDER_RADIUS, + height: '100%', + width: '1.4em', + + [`&.${classes.ok}`]: { + backgroundColor: BLUE, + }, + + [`&.${classes.warning}`]: { + backgroundColor: PURPLE, + }, + + [`&.${classes.error}`]: { + backgroundColor: RED, + }, + + [`&.${classes.off}`]: { + backgroundColor: GREY, + }, +}); + +const Decorator: FC = ({ colour, ...restDecoratorProps }) => ( + ); +export type { Colours }; + export default Decorator; From 43beb227f8ce30dc2404d958d1661b13af25d91e Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Oct 2024 00:05:47 -0400 Subject: [PATCH 45/50] fix(striker-ui): add indicator for lost connection to api in host net init iface table --- .../HostNetInit/HostNetInitInputGroup.tsx | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index 1ef5b0442..4a403875f 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -7,8 +7,10 @@ import { capitalize } from 'lodash'; import { FC, useMemo, useRef, useState } from 'react'; import { v4 as uuidv4 } from 'uuid'; +import Decorator, { Colours } from '../Decorator'; import DragArea, { dragAreaClasses } from './DragArea'; import DragDataGrid, { dragDataGridClasses } from './DragDataGrid'; +import FlexBox from '../FlexBox'; import guessHostNets from './guessHostNets'; import HostNetInputGroup from './HostNetInputGroup'; import IfaceDragHandle, { ifaceDragHandleClasses } from './IfaceDragHandle'; @@ -36,6 +38,8 @@ const HostNetInitInputGroup = ( y: 0, }); + const [lostConnection, setLostConnection] = useState(false); + const appliedIfaces = useMemo( () => Object.values(formik.values.networkInit.networks).reduce< @@ -64,7 +68,12 @@ const HostNetInitInputGroup = ( const { data: ifaces } = useFetch( `/init/network-interface/${host.uuid}`, { + onError: () => { + setLostConnection(true); + }, onSuccess: (data) => { + setLostConnection(false); + guessHostNets({ appliedIfaces, chains, @@ -178,6 +187,30 @@ const HostNetInitInputGroup = ( field: 'name', flex: 1, headerName: 'Name', + renderCell: (cell) => { + const { row, value } = cell; + const { state } = row; + + let colour: Colours; + + if (lostConnection || state === 'down') { + colour = 'warning'; + } else if (state === 'up') { + colour = 'ok'; + } else { + colour = 'error'; + } + + return ( + + + {value} + + ); + }, }, { field: 'mac', @@ -196,7 +229,7 @@ const HostNetInitInputGroup = ( renderCell: (cell) => { const { value } = cell; - return capitalize(value); + return lostConnection ? 'Lost' : capitalize(value); }, }, { From 705fb5da66a92ee20bf15c2fac81d341725cf93b Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Oct 2024 00:14:48 -0400 Subject: [PATCH 46/50] build(striker-ui): bump micromatch 4.0.4->4.0.8 --- striker-ui/package-lock.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/striker-ui/package-lock.json b/striker-ui/package-lock.json index 648c1df10..709a7c37b 100644 --- a/striker-ui/package-lock.json +++ b/striker-ui/package-lock.json @@ -5440,13 +5440,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" @@ -11192,13 +11192,13 @@ "dev": true }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.3", + "picomatch": "^2.3.1" } }, "mime-db": { From 4b9657b41e787d9b63367bc387a37ac3b08e8483 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Oct 2024 12:22:47 -0400 Subject: [PATCH 47/50] fix(striker-ui): correct linting errors from build --- striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx | 6 +++--- striker-ui/components/HostNetInit/HostNetInputGroup.tsx | 4 +++- striker-ui/components/HostNetInit/guessHostNets.ts | 4 +++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx index 4a403875f..383977e30 100644 --- a/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInitInputGroup.tsx @@ -42,9 +42,9 @@ const HostNetInitInputGroup = ( const appliedIfaces = useMemo( () => - Object.values(formik.values.networkInit.networks).reduce< - Record - >((applied, network) => { + Object.values( + formik.values.networkInit.networks, + ).reduce>((applied, network) => { network.interfaces.forEach((uuid) => { if (uuid.length > 0) applied[uuid] = true; }); diff --git a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx index eaab58045..86e47251e 100644 --- a/striker-ui/components/HostNetInit/HostNetInputGroup.tsx +++ b/striker-ui/components/HostNetInit/HostNetInputGroup.tsx @@ -44,7 +44,9 @@ const HostNetInputGroup = ( ['dr', 'subnode'].includes(host.type) && ifaceValues.length >= 8 && (nets[netId].type === 'mn' || - Object.values(nets).every((net) => net.type !== 'mn')) + Object.values(nets).every( + (net) => net.type !== 'mn', + )) ) { base = [...base, 'mn'].sort(); } diff --git a/striker-ui/components/HostNetInit/guessHostNets.ts b/striker-ui/components/HostNetInit/guessHostNets.ts index cb5dd4738..357787586 100644 --- a/striker-ui/components/HostNetInit/guessHostNets.ts +++ b/striker-ui/components/HostNetInit/guessHostNets.ts @@ -68,7 +68,9 @@ const guessHostNets = ({ }, ); - const hostNets = Object.entries(formik.values.networkInit.networks); + const hostNets = Object.entries( + formik.values.networkInit.networks, + ); // Categorize slots based on their type. const slots = hostNets.reduce< From d0bd8dd4891d752e4d35ef338560df2b63bfce14 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Oct 2024 12:24:50 -0400 Subject: [PATCH 48/50] chore(striker-ui): update next-env.d.ts after npm i --- striker-ui/next-env.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui/next-env.d.ts b/striker-ui/next-env.d.ts index 4f11a03dc..a4a7b3f5c 100644 --- a/striker-ui/next-env.d.ts +++ b/striker-ui/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. From 68386a4e5a12290a3b8d8259a6e397799e9e2883 Mon Sep 17 00:00:00 2001 From: Tsu-ba-me Date: Wed, 2 Oct 2024 12:25:33 -0400 Subject: [PATCH 49/50] build(striker-ui-api): rebuild --- striker-ui-api/out/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/striker-ui-api/out/index.js b/striker-ui-api/out/index.js index 31c191511..b22b06913 100644 --- a/striker-ui-api/out/index.js +++ b/striker-ui-api/out/index.js @@ -1,2 +1,2 @@ /*! For license information please see index.js.LICENSE.txt */ -(()=>{var e={9078:(e,t,n)=>{"use strict";var r=n(159),a=n(983);function o(e){if(!(this instanceof o))return new o(e);this.headers=e.headers,this.negotiator=new r(e)}function i(e){return-1===e.indexOf("/")?a.lookup(e):e}function s(e){return"string"==typeof e}e.exports=o,o.prototype.type=o.prototype.types=function(e){var t=e;if(t&&!Array.isArray(t)){t=new Array(arguments.length);for(var n=0;n{"use strict";function t(e,n,r){for(var a=0;a0&&Array.isArray(o)?t(o,n,r-1):n.push(o)}return n}function n(e,t){for(var r=0;r{"use strict";n.r(t),n.d(t,{default:()=>yi}),n(5666),n(2222),n(1539),n(8674);var r=n(7846),a=n.n(r),o=n(9268),i=n.n(o),s=n(9383),c=(n(5827),n(9720),n(4916),n(4723),n(4603),n(9714),n(9070),n(7941),n(2526),n(7327),n(5003),n(9554),n(4747),n(9337),n(3321),n(9753),n(1817),n(2165),n(6992),n(8783),n(3948),n(7042),n(8309),n(1038),n(9491)),u=n.n(c),p=n(2081),l=n(4108),d=n(4151);function f(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return m(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?m(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function m(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},a=r.body,o=r.uuid,i=h({},a);o&&(i.uuid=o);var s,c=Object.entries(g[e]).reduce((function(e,t){var n=f(t,2),r=n[0],a=n[1],o=i[r];return void 0!==o&&e.push(a,String(o)),e}),["--".concat(e),"--".concat(t),"--yes"]);(0,d.HQ)({commandArgs:c},"Manage alerts with args: ");try{var m=s=(0,p.spawnSync)(l.us.usr.sbin["anvil-manage-alerts"].self,c,{encoding:"utf-8",timeout:3e4}),v=m.error,b=m.signal,y=m.status,x=m.stderr,w=m.stdout;(0,d.HQ)({error:v,signal:b,status:y,stderr:x,stdout:w},"Manage alerts returned: "),u().strictEqual(y,0,"Expected status to be 0, but got [".concat(y,"]")),u().strictEqual(v,void 0,"Expected no error, but got [".concat(v,"]"))}catch(v){throw new Error("Failed to complete manage alerts; CAUSE: ".concat(v))}return{uuid:null===(n=s.stdout.match(new RegExp(l.Ke)))||void 0===n?void 0:n[0]}},x=(n(8285),n(9653),n(972)),w=function(e,t){var n=e.hostUuid,r=e.level,a=e.mailRecipientUuid,o=(0,x.N)(n,"string"),i=(0,x.N)(r,"number"),s=(0,x.N)(a,"string");return t&&u()(l.Qt.test(t),"Expected valid UUIDv4; got [".concat(t,"]")),u()(l.Qt.test(o),"Expected valid host UUIDv4; got [".concat(o,"]")),u()(Number.isSafeInteger(i),"Expected level to be an integer; got [".concat(i,"]")),u()(l.Qt.test(s),"Expected valid mail recipient UUIDv4; got [".concat(s,"]")),{hostUuid:o,level:i,mailRecipientUuid:s}},_=(n(5212),n(6699),n(6363));const S=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.beforeReturn,r=t.elementWrapper,a=void 0===r?"":r,o=t.onEach,i=t.separator,s=void 0===i?"":i,c="".concat(a).concat(s).concat(a),u=e instanceof Array&&e.length>0?"".concat(a).concat(e.slice(1).reduce((function(e,t){return"".concat(e).concat(c).concat((0,_.Z)(o,{notCallableReturn:t,parameters:[t]}))}),e[0])).concat(a):void 0;return(0,_.Z)(n,{notCallableReturn:u,parameters:[u]})};var E=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.onFallback,a=n.beforeReturn,o=void 0===a?function(e){return e?"".concat(t," IN (").concat(e,")"):(0,_.Z)(r,{notCallableReturn:""})}:a;return S(e,{beforeReturn:o,elementWrapper:"'",separator:", "})},A=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=n.onFallback,a=(0,x.N)(e,"string[]",{modifierType:"sql"}),o=E(a,t,{onFallback:r});return{after:o,before:a}},k=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"all",t=arguments.length>1?arguments[1]:void 0;return e instanceof Array&&!e.some((function(e){return["all","*"].includes(e)}))?E(e,t):""},O=n(9829);function j(e){return j="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},j(e)}function C(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}function R(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){C(o,r,a,i,s,"next",e)}function s(e){C(o,r,a,i,s,"throw",e)}i(void 0)}))}}const I=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.beforeRespond;return function(){var t=R(regeneratorRuntime.mark((function t(r,a){var o,i,s,c;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if((0,d.Cr)("Calling CLI script to get data."),o={},t.prev=2,"function"!=typeof e){t.next=9;break}return t.next=6,e(r,o);case 6:t.t0=t.sent,t.next=10;break;case 9:t.t0=e;case 10:return s=t.t0,t.next=13,(0,O.IO)(s);case 13:i=t.sent,t.next=20;break;case 16:return t.prev=16,t.t1=t.catch(2),(0,d.x5)("Failed to execute query; CAUSE: ".concat(t.t1)),t.abrupt("return",a.status(500).send());case 20:(0,d.HQ)(i,"Query stdout pre-hooks (type=[".concat(j(i),"]): ")),c=o.afterQueryReturn,i=(0,_.Z)(c,{parameters:[i],notCallableReturn:i}),i=(0,_.Z)(n,{parameters:[i],notCallableReturn:i}),(0,d.HQ)(i,"Query stdout post-hooks (type=[".concat(j(i),"]): ")),a.json(i);case 26:case"end":return t.stop()}}),t,null,[[2,16]])})));return function(e,n){return t.apply(this,arguments)}}()};var T=function(e){return function(t){return t instanceof Array?e(t):t}},P=function(e,t){return T((function(n){return n.reduce(e,t)}))},N=(n(5306),function(e){return e.replace(/-.*$/,"")}),U=function(e){return e.replace(/[.].*$/,"")};function D(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);nMath.max(t,Math.min(e,n)),z={"b-B":8n,"b-kB":8000n,"b-MB":8000000n,"b-GB":8000000000n,"b-TB":8000000000000n,"b-PB":8000000000000000n,"b-EB":8000000000000000000n,"b-ZB":8000000000000000000000n,"b-YB":8000000000000000000000000n,"b-KiB":8192n,"b-MiB":8388608n,"b-GiB":8589934592n,"b-TiB":8796093022208n,"b-PiB":9007199254740992n,"b-EiB":9223372036854775808n,"b-ZiB":9444732965739290427392n,"b-YiB":9671406556917033397649408n,"b-b":1n,"b-kbit":1000n,"b-Mbit":1000000n,"b-Gbit":1000000000n,"b-Tbit":1000000000000n,"b-Pbit":1000000000000000n,"b-Ebit":1000000000000000000n,"b-Zbit":1000000000000000000000n,"b-Ybit":1000000000000000000000000n,"b-Kibit":1024n,"b-Mibit":1048576n,"b-Gibit":1073741824n,"b-Tibit":1099511627776n,"b-Pibit":1125899906842624n,"b-Eibit":1152921504606846976n,"b-Zibit":1180591620717411303424n,"b-Yibit":1208925819614629174706176n},$=["byte","ibyte","bit","ibit"],W=["B","kB","MB","GB","TB","PB","EB","ZB","YB","B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB","b","kbit","Mbit","Gbit","Tbit","Pbit","Ebit","Zbit","Ybit","b","Kibit","Mibit","Gibit","Tibit","Pibit","Eibit","Zibit","Yibit"],G=e=>BigInt(10**e),Q=({precision:e,value:t},n,{isReverse:r}={})=>{if("b"===n)return{precision:e,value:t};const a=z[`b-${n}`];if(r)return{precision:e,value:t*a};const o=String(a).length;return{precision:e+o,value:t*G(o)/a}},Z=(e,{fromUnit:t="B",locale:n,precision:r,toUnit:a}={})=>{let o;try{o=J(e)}catch(e){return}const{max:i,min:s}=Y(r),{unit:c}=K(t,"B");o=Q(o,c,{isReverse:!0});const u=X(o,c,{toUnit:a});o=Q(o,u),o=V(o,{toPrecision:B(o.precision,s,i)}),o=ee(o,s);const p=(({precision:e,value:t},{bigintFormatOptions:n,numberFormatOptions:r,locale:a}={})=>{const o=G(e),i=t/o,s=t%o;let[c,u]="0.",p=i.toString(),l=s.toString();if(a){const e="string"==typeof a?a:void 0;[c,u]=.1.toLocaleString(e,r),p=i.toLocaleString(e,n),l=s.toLocaleString(e,{...n,useGrouping:!1})}let d=p;return e>0&&(d+=`${u}${l.padStart(e,c)}`),d})(o,{locale:n});return{value:p,unit:u}},V=({precision:e,value:t},{toPrecision:n=0}={})=>{const r={precision:n,value:t};if(n>e)r.value*=G(n-e);else if(n4&&(r.value+=1n)}return r},K=(e,t,n=W)=>{const r=n.indexOf(e);return r<0?{unit:t,unitIndex:0}:{unit:n[r],unitIndex:r}},J=e=>{var t,n;const r=String(e).split(/\D/,2),a=null!==(t=null===(n=r[1])||void 0===n?void 0:n.length)&&void 0!==t?t:0,o=r.join("");if(0===o.length)throw Error("Value is blank.");return{value:BigInt(o),precision:a}},Y=(e={})=>{var t,n;return"number"==typeof e?{max:e,min:e}:{max:null!==(t=e.max)&&void 0!==t?t:2,min:null!==(n=e.min)&&void 0!==n?n:0}},X=({precision:e,value:t},n,{conversionTable:r=z,toUnit:a,units:o=W,unitSections:i=$,unitSectionLength:s=9}={})=>{const c=o.indexOf(a);return c>=0?o[c]:((e,t,n,r,a,o,i)=>{let s=o.indexOf(n),c=t;s<0&&(s=((e,t)=>{const n=`${"i"===e[1]?"i":""}${/B$/.test(e)?"byte":"bit"}`,r=t.findIndex((e=>e===n));return{section:n,index:r}})(t,o).index);let u=s*i;const p=u+i;for(;u=r[`b-${t}`]?c=t:u=p}return c})(t/G(e),n,a,r,o,i,s)},ee=({precision:e,value:t},n)=>{const r={precision:e,value:t},a=e-n;let o=!0;for(let e=1;o&&e<=a;e+=1)0n===r.value%10n?(r.value/=10n,r.precision-=1):o=!1;return r};function te(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:{},t=e.isSummary,n=void 0!==t&&t,r="\n host_uuid,\n host_name,\n scan_hardware_cpu_cores,\n scan_hardware_ram_total",a="";return n&&(r="\n MIN(scan_hardware_cpu_cores) AS anvil_total_cpu_cores,\n MIN(scan_hardware_ram_total) AS anvil_total_memory",a="GROUP BY anvil_uuid"),"\n SELECT\n anvil_uuid,\n ".concat(r,"\n FROM anvils AS anv\n JOIN hosts AS hos\n ON host_uuid IN (\n anvil_node1_host_uuid,\n anvil_node2_host_uuid,\n anvil_dr1_host_uuid\n )\n JOIN scan_hardware AS sca_har\n ON host_uuid = scan_hardware_host_uuid\n ").concat(a)},i=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.isSummary,n=void 0!==t&&t,r="\n server_uuid,\n server_name,\n server_cpu_cores,\n server_memory_value,\n server_memory_unit",a="";return n&&(r="SUM(server_cpu_cores) AS anvil_total_allocated_cpu_cores",a="GROUP BY server_anvil_uuid"),"\n SELECT\n server_anvil_uuid,\n ".concat(r,"\n FROM servers AS ser\n JOIN (\n SELECT\n server_definition_server_uuid,\n CAST(\n SUBSTRING(\n server_definition_xml, 'cores=''([\\d]*)'''\n ) AS INTEGER\n ) AS server_cpu_cores,\n CAST(\n SUBSTRING(\n server_definition_xml, 'memory.*>([\\d]*)e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:2;return"message_022".concat(e)},fe=function(){var e,t=(e=regeneratorRuntime.mark((function e(t){var n,r,a,o,i,s,c,p,l,f,m,v;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.anvils,r=t.anvilUuid,a=t.hosts,o=n.anvil_uuid[r]){e.next=4;break}throw new Error("Anvil information not found with UUID ".concat(r));case 4:return i=o.anvil_name,s=o.anvil_node1_host_uuid,c=o.anvil_node2_host_uuid,p={anvil_name:i,anvil_state:"optimal",anvil_uuid:r,hosts:[]},e.prev=6,e.next=9,(0,O.IO)("SELECT\n COUNT(a.server_name),\n b.host_uuid\n FROM servers AS a\n JOIN hosts AS b\n ON a.server_host_uuid = b.host_uuid\n JOIN anvils AS c\n ON b.host_uuid IN (\n c.anvil_node1_host_uuid,\n c.anvil_node2_host_uuid\n )\n WHERE c.anvil_uuid = '".concat(r,"'\n AND a.server_state = 'running'\n GROUP BY b.host_uuid, b.host_name\n ORDER BY b.host_name;"));case 9:l=e.sent,e.next=16;break;case 12:throw e.prev=12,e.t0=e.catch(6),(0,d.x5)("Failed to get subnodes' server count; CAUSE: ".concat(e.t0)),e.t0;case 16:f=regeneratorRuntime.mark((function e(){var t,n,r,o,i,s,c,f,h,b,g,y,x,w,_;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(t=v[m],n=a.host_uuid[t],r=n.host_status,o=n.short_host_name,i=p.hosts,s=l.find((function(e){return 2===e.length&&e[1]===t})),c=s?s[0]:0,f={host_name:o,host_uuid:t,maintenance_mode:!1,server_count:c,state:"offline",state_message:de(),state_percent:0},i.push(f),"online"===r){e.next=9;break}return e.abrupt("return","continue");case 9:return h=void 0,e.prev=10,e.next=13,(0,O.IO)("SELECT\n scan_cluster_node_in_ccm,\n scan_cluster_node_crmd_member,\n scan_cluster_node_cluster_member,\n scan_cluster_node_maintenance_mode\n FROM\n scan_cluster_nodes\n WHERE\n scan_cluster_node_host_uuid = '".concat(t,"';"));case 13:h=e.sent,u().ok(h.length,"No node cluster info"),e.next=21;break;case 17:return e.prev=17,e.t0=e.catch(10),(0,d.x5)("Failed to get node ".concat(t," cluster status; CAUSE: ").concat(e.t0)),e.abrupt("return","continue");case 21:b=ue(h,1),g=ue(b[0],4),y=g[0],x=g[1],w=g[2],_=g[3],f.maintenance_mode=Boolean(_),w?(f.state="online",f.state_message=de(3),f.state_percent=100):x?(f.state="crmd",f.state_message=de(4),f.state_percent=75):y?(f.state="in_ccm",f.state_message=de(5),f.state_percent=50):(f.state="booted",f.state_message=de(6),f.state_percent=25);case 24:case"end":return e.stop()}}),e,null,[[10,17]])})),m=0,v=[s,c];case 18:if(!(me.length)&&(t=e.length);for(var n=0,r=new Array(t);n([\\d]*)0&&(c=String(s.reduce((function(e,t){var n,r,a=he(t,2),o=a[0],i=a[1],s=null!==(n=null===(r=Z(o,{fromUnit:i,toUnit:"B"}))||void 0===r?void 0:r.value)&&void 0!==n?n:"0";return e+BigInt(s)}),BigInt(0)))),e.abrupt("return",n.status(200).send({allocated:c,hosts:i,reserved:String(l.Su),total:o}));case 28:case"end":return e.stop()}}),e,null,[[1,7],[15,21]])})),function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){ge(o,r,a,i,s,"next",e)}function s(e){ge(o,r,a,i,s,"throw",e)}i(void 0)}))});return function(e,n){return t.apply(this,arguments)}}();function xe(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}function we(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return _e(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_e(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function _e(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);nt?1:-1},Ae=function(e){var t=Object.entries(e).sort((function(e,t){var n=we(e,2),r=n[0],a=n[1].type,o=we(t,2),i=o[0],s="bond"===a,c="bond"===o[1].type;return s&&c?Ee(r,i):s?-1:c?1:Ee(r,i)})).reduce((function(e,t){var n=we(t,2),r=n[0],a=n[1],o=a.type;if("bond"===o){var i=a,s=i.active_interface,c=i.uuid;e[c]={active_interface:s,bond_name:r,bond_uuid:c,links:[]}}else if("interface"===o){var u=a,p=u.bond_uuid,d=u.operational,f=u.speed,m=u.uuid;if(!l.Qt.test(p))return e;var v=e[p],h=v.active_interface,b=v.links,g="up"===d?"optimal":"down";b.forEach((function(e){var t=e.link_speed,n=e.link_state;tf&&(g=Se(g))})),b.push({is_active:r===h,link_name:r,link_speed:f,link_state:g,link_uuid:m})}return e}),{});return Object.values(t)},ke=function(){var e,t=(e=regeneratorRuntime.mark((function e(t,n){var r,a,o,i,s,c,p,f,m,v,h,b,g,y,w;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:r=t.params.anvilUuid,a=(0,x.N)(r,"string",{modifierType:"sql"}),e.prev=2,u()(l.Qt.test(a),"Param UUID must be a valid UUIDv4; got [".concat(a,"]")),e.next=10;break;case 6:return e.prev=6,e.t0=e.catch(2),(0,d.x5)("Failed to assert value during get anvil network; CAUSE: ".concat(e.t0)),e.abrupt("return",n.status(400).send());case 10:return e.prev=10,e.next=13,(0,O.nP)();case 13:return o=e.sent,e.next=16,(0,O.zM)();case 16:i=e.sent,e.next=23;break;case 19:return e.prev=19,e.t1=e.catch(10),(0,d.x5)("Failed to get anvil and host data; CAUSE: ".concat(e.t1)),e.abrupt("return",n.status(500).send());case 23:s=o.anvil_uuid[a],c=s.anvil_node1_host_uuid,p=s.anvil_node2_host_uuid,f={hosts:[]},m=0,v=[c,p];case 26:if(!(me.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&(m.badSshKeys=h.reduce((function(e,t){var n,r,a=(r=2,function(e){if(Array.isArray(e))return e}(n=t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(n,r)||function(e,t){if(e){if("string"==typeof e)return Fe(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Fe(e,t):void 0}}(n,r)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),o=a[0],i=a[1],s=e[i],c=void 0===s?[]:s;return c.push(o),e[i]=c,e}),{})),n.status(200).send(m);case 40:case"end":return e.stop()}}),e,null,[[6,12],[16,22],[27,33]])})),function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){Me(o,r,a,i,s,"next",e)}function s(e){Me(o,r,a,i,s,"throw",e)}i(void 0)}))});return function(e,n){return t.apply(this,arguments)}}();function qe(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Be(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==i[1]?i[1]:{}).isActiveMember){e.next=3;break}return e.abrupt("return",void 0);case 3:return e.next=5,(0,O.IO)("SELECT\n CASE\n WHEN host_status = 'online'\n THEN CAST('1' AS BOOLEAN)\n ELSE CAST('0' AS BOOLEAN)\n END\n FROM hosts WHERE host_uuid = '".concat(t,"';"));case 5:return n=e.sent,u().ok(n.length,"No entry found"),r=$e(n,1),a=$e(r[0],1),o=a[0],e.abrupt("return",o?{job_command:l.us.usr.sbin["anvil-safe-start"].self,job_description:"job_0337",job_host_uuid:t,job_name:"set_membership::join",job_title:"job_0336"}:void 0);case 9:case"end":return e.stop()}}),e)}))),function(e){return Ve.apply(this,arguments)}),leave:(Ze=Qe(regeneratorRuntime.mark((function e(t){var n,r,a=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=a.length>1&&void 0!==a[1]?a[1]:{},r=n.isActiveMember,e.abrupt("return",r?{job_command:l.us.usr.sbin["anvil-safe-stop"].self,job_description:"job_0339",job_host_uuid:t,job_name:"set_membership::leave",job_title:"job_0338"}:void 0);case 2:case"end":return e.stop()}}),e)}))),function(e){return Ze.apply(this,arguments)})},Je=function(e){return function(){var t=Qe(regeneratorRuntime.mark((function t(n,r){var a,o,i,s,c;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:a=n.params.uuid,o=(0,x.N)(a,"string",{modifierType:"sql"}),t.prev=2,u()(l.Qt.test(o),"Param UUID must be a valid UUIDv4; got: [".concat(o,"]")),t.next=10;break;case 6:return t.prev=6,t.t0=t.catch(2),(0,d.x5)("Failed to assert value when changing host membership; CAUSE: ".concat(t.t0)),t.abrupt("return",r.status(500).send());case 10:return t.prev=10,t.next=13,(0,O.IO)("SELECT\n scan_cluster_node_in_ccm,\n scan_cluster_node_crmd_member,\n scan_cluster_node_cluster_member\n FROM scan_cluster_nodes\n WHERE scan_cluster_node_host_uuid = '".concat(o,"';"));case 13:i=t.sent,u().ok(i.length,"No entry found"),t.next=21;break;case 17:return t.prev=17,t.t1=t.catch(10),(0,d.x5)("Failed to get cluster status of host ".concat(o,"; CAUSE: ").concat(t.t1)),t.abrupt("return",r.status(500).send());case 21:return s=i[0].every((function(e){return Boolean(e)})),t.prev=22,t.next=25,Ke[e](o,{isActiveMember:s});case 25:if(!(c=t.sent)){t.next=29;break}return t.next=29,(0,O.ZP)(Be({file:__filename},c));case 29:t.next=35;break;case 31:return t.prev=31,t.t2=t.catch(22),(0,d.x5)("Failed to initiate ".concat(e," cluster for host ").concat(o,"; CAUSE: ").concat(t.t2)),t.abrupt("return",r.status(500).send());case 35:return t.abrupt("return",r.status(204).send());case 36:case"end":return t.stop()}}),t,null,[[2,6],[10,17],[22,31]])})));return function(e,n){return t.apply(this,arguments)}}()},Ye=Je("join"),Xe=Je("leave");function et(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||nt(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function tt(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=nt(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,a=function(){};return{s:a,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw o}}}}function nt(e,t){if(e){if("string"==typeof e)return rt(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?rt(e,t):void 0}}function rt(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:{},t=e.uuid;return{job_command:"".concat(l.us.usr.sbin["striker-boot-machine"].self," --host-uuid '").concat(t,"'"),job_description:"job_0335",job_name:"set_power::on",job_title:"job_0334"}},startserver:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.runOn,n=e.uuid;return{job_command:"".concat(l.us.usr.sbin["anvil-boot-server"].self),job_data:"server-uuid=".concat(n),job_description:"job_0341",job_host_uuid:t,job_name:"set_power::server::on",job_title:"job_0340"}},stop:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.isStopServers,n=e.uuid,r=e.runOn,a=void 0===r?n:r;return{job_command:"".concat(l.us.usr.sbin["anvil-safe-stop"].self," --power-off").concat(t?" --stop-servers":""),job_description:"job_0333",job_host_uuid:a,job_name:"set_power::off",job_title:"job_0332"}},stopserver:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.force,n=e.runOn,r=e.uuid,a=l.us.usr.sbin["anvil-shutdown-server"].self;return t&&(a+=" --immediate"),{job_command:a,job_data:"server-uuid=".concat(r),job_description:"job_0343",job_host_uuid:n,job_name:"set_power::server::off",job_title:"job_0342"}}},pt=function(){var e=ct(regeneratorRuntime.mark((function e(t,n){var r;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=ot({file:__filename},ut[t](n)),e.next=3,(0,O.ZP)(r);case 3:return e.abrupt("return",e.sent);case 4:case"end":return e.stop()}}),e)})));return function(t,n){return e.apply(this,arguments)}}(),lt=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.getJobHostUuid;return function(){var t=ct(regeneratorRuntime.mark((function t(r,a){var o,i,s,c;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:o=r.params.uuid,i=r.query.force,s=(0,x.N)(i,"boolean"),t.prev=2,o&&u()(l.Qt.test(o),"Param UUID must be a valid UUIDv4; got [".concat(o,"]")),t.next=10;break;case 6:return t.prev=6,t.t0=t.catch(2),(0,d.x5)("Failed to ".concat(e,"; CAUSE: ").concat(t.t0)),t.abrupt("return",a.status(400).send());case 10:return t.prev=10,t.next=13,null==n?void 0:n.call(null,o);case 13:return c=t.sent,t.next=16,pt(e,{force:s,runOn:c,uuid:o});case 16:t.next=22;break;case 18:return t.prev=18,t.t1=t.catch(10),(0,d.x5)("Failed to ".concat(e," ").concat(null!=o?o:l.Fe,"; CAUSE: ").concat(t.t1)),t.abrupt("return",a.status(500).send());case 22:a.status(204).send();case 23:case"end":return t.stop()}}),t,null,[[2,6],[10,18]])})));return function(e,n){return t.apply(this,arguments)}}()},dt=function(e){return function(){var t=ct(regeneratorRuntime.mark((function t(n,r){var a,o,i,s,c,p;return regeneratorRuntime.wrap((function(t){for(;;)switch(t.prev=t.next){case 0:a=n.params.uuid,o=(0,x.N)(a,"string",{modifierType:"sql"}),t.prev=2,u()(l.Qt.test(o),"Param UUID must be a valid UUIDv4; got: [".concat(o,"]")),t.next=10;break;case 6:return t.prev=6,t.t0=t.catch(2),(0,d.x5)("Failed to assert value during power operation on anvil subnode"),t.abrupt("return",r.status(400).send());case 10:return t.prev=10,t.next=13,(0,O.IO)("SELECT anvil_node1_host_uuid, anvil_node2_host_uuid\n FROM anvils WHERE anvil_uuid = '".concat(o,"';"));case 13:i=t.sent,u().ok(i.length,"No entry found"),t.next=21;break;case 17:return t.prev=17,t.t1=t.catch(10),(0,d.x5)("Failed to get anvil subnodes' UUID; CAUSE: ".concat(t.t1)),t.abrupt("return",r.status(500).send());case 21:s=tt(i[0]),t.prev=22,s.s();case 24:if((c=s.n()).done){t.next=37;break}return p=c.value,t.prev=26,t.next=29,pt(e,{isStopServers:!0,uuid:p});case 29:t.next=35;break;case 31:return t.prev=31,t.t2=t.catch(26),(0,d.x5)("Failed to ".concat(e," host ").concat(p,"; CAUSE: ").concat(t.t2)),t.abrupt("return",r.status(500).send());case 35:t.next=24;break;case 37:t.next=42;break;case 39:t.prev=39,t.t3=t.catch(22),s.e(t.t3);case 42:return t.prev=42,s.f(),t.finish(42);case 45:return t.abrupt("return",r.status(204).send());case 46:case"end":return t.stop()}}),t,null,[[2,6],[10,17],[22,39,42,45],[26,31]])})));return function(e,n){return t.apply(this,arguments)}}()},ft=function(e){return lt(e,{getJobHostUuid:(t=ct(regeneratorRuntime.mark((function e(t){var n,r,a,o,i;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(t){e.next=2;break}return e.abrupt("return");case 2:return e.prev=2,e.next=5,(0,O.IO)("SELECT\n COALESCE(a.server_host_uuid, b.anvil_node1_host_uuid)\n FROM servers AS a\n LEFT JOIN anvils AS b\n ON a.server_anvil_uuid = b.anvil_uuid\n WHERE server_state != '".concat(l.oZ,"'\n AND server_uuid = '").concat(t,"';"));case 5:r=e.sent,u().ok(r.length,"No entry found"),a=et(r,1),o=et(a[0],1),(i=o[0])&&(n=i),e.next=14;break;case 11:throw e.prev=11,e.t0=e.catch(2),new Error("Failed to get server host; CAUSE: ".concat(e.t0));case 14:return e.abrupt("return",n);case 15:case"end":return e.stop()}}),e,null,[[2,11]])}))),function(e){return t.apply(this,arguments)})});var t},mt=lt("poweroff"),vt=lt("reboot"),ht=n(9831),bt=n(5230);function gt(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return yt(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?yt(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function yt(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw o}}}}function fn(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}(e,In);return Un(function(e){for(var t=1;t2&&void 0!==arguments[2]?arguments[2]:2;return t.reduce((function(t,r,a){if(r){var o=r.networkInterfaceMACAddress,i=a+1;t[Ln(n,"".concat(e,"_link").concat(i,"_mac_to_set"))]={step:n,value:o}}return t}),{})};function Mn(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Hn(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Hn(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Hn(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.netconfStep,r=void 0===n?2:n,a=t.netcountStep,o=void 0===a?1:a,i=e.reduce((function(e,t){var n,a=t.createBridge,o=t.interfaces,i=t.ipAddress,s=t.subnetMask,c=t.type,u=e.counters;u[c]=u[c]?u[c]+1:1;var p="".concat(c).concat(u[c]);return e.data=Bn(Bn({},e.data),{},(zn(n={},Ln(r,"".concat(p,"_ip")),{step:r,value:i}),zn(n,Ln(r,"".concat(p,"_subnet_mask")),{step:r,value:s}),n),Fn(p,o)),a&&(e.data[Ln(r,"".concat(p,"_create_bridge"))]={step:r,value:a}),e}),{counters:{},data:{}}),s=i.counters,c=i.data;return Object.entries(s).forEach((function(e){var t=Mn(e,2),n=t[0],r=t[1];c[Ln(o,"".concat(n,"_count"))]={value:r}})),c};function Wn(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0,"Data host number can only contain digits; got [".concat(E,"]")),u()(l.ah.test(A),"Data network DNS must be a comma separated list of valid IPv4 addresses; got [".concat(A,"]")),u()(l.tf.test(k),"Data network gateway must be a valid IPv4 address; got [".concat(k,"]")),u()(l.OU.test(j),"Data gateway interface must be a peaceful string; got [".concat(j,"]")),u()(C.length>0,"Data organization name cannot be empty; got [".concat(C,"]")),u()(/^[a-z0-9]{1,5}$/.test(R),"Data organization prefix can only contain 1 to 5 lowercase alphanumeric characters; got [".concat(R,"]")),e.next=28;break;case 24:return e.prev=24,e.t0=e.catch(12),(0,d.x5)("Failed to assert value when trying to initialize striker; CAUSE: ".concat(e.t0,".")),e.abrupt("return",n.status(400).send());case 28:I=Qn((Zn(r={},Ln(1,"domain"),{value:_}),Zn(r,Ln(1,"organization"),{value:C}),Zn(r,Ln(1,"prefix"),{value:R}),Zn(r,Ln(1,"sequence"),{value:E}),Zn(r,Ln(2,"dns"),{step:2,value:A}),Zn(r,Ln(2,"gateway"),{step:2,value:k}),Zn(r,Ln(2,"gateway_interface"),{step:2,value:j}),Zn(r,Ln(2,"host_name"),{step:2,value:S}),Zn(r,Ln(2,"striker_password"),{step:2,value:w}),Zn(r,Ln(2,"striker_user"),{step:2,value:"admin"}),r),$n(b)),(0,d.HQ)(I,"Config data before initiating striker config: "),T=Object.entries(I),e.prev=31,P=(0,O.gA)(),N=0,U=T;case 34:if(!(Ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw o}}}}function nr(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.locales;return"".concat(e[0].toLocaleUpperCase(n)).concat(e.slice(1))},ir=function(){for(var e=arguments.length,t=new Array(e),n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},a=t[0],o=t.length;if(!a)return n;var i=1,s=r[a];return r[a]=i0&&void 0!==arguments[0]?arguments[0]:{},t=e.keys,n=void 0===t?"*":t,r=k(n,"WHERE a.host_uuid");(0,d.Cr)("condHostUUIDs=[".concat(r,"]"));var a="\n SELECT\n a.host_ipmi,\n a.host_name,\n a.host_status,\n a.host_type,\n a.host_uuid,\n b.variable_name,\n b.variable_value,\n SUBSTRING(\n b.variable_name, '".concat(hr,"([^:]+)'\n ) as cvar_name,\n SUBSTRING(\n b.variable_name, '").concat(hr,"([a-z]{2,3})\\d+'\n ) AS network_type,\n SUBSTRING(\n b.variable_name, '").concat(hr,"[a-z]{2,3}\\d+_(link\\d+)'\n ) AS network_link,\n c.network_interface_uuid\n FROM hosts AS a\n LEFT JOIN variables AS b\n ON b.variable_source_uuid = a.host_uuid\n AND (\n b.variable_name LIKE '").concat(vr,"%'\n OR b.variable_name = 'install-target::enabled'\n )\n LEFT JOIN network_interfaces AS c\n ON b.variable_name LIKE '%link%_mac%'\n AND b.variable_value = c.network_interface_mac_address\n AND a.host_uuid = c.network_interface_host_uuid\n ").concat(r,"\n ORDER BY a.host_name ASC,\n cvar_name ASC,\n b.variable_name ASC;"),o=T((function(e){if(0===e.length)return{};var t=pr(e[0],5),n=t[0],r=t[1],a=t[2],o=t[3],i=t[4],s=U(r),c={command:n,ip:n.replace(/^.*--ip\s+([^\s'"]+).*$/,"$1"),password:n.replace(/^.*--password\s+"(.*)"$/,"$1"),username:n.replace(/^.*--username\s+(\w+).*$/,"$1")};return e.reduce((function(e,t){var n=t[5],r=t[6],a=t[8],o=t[9],i=t[10];if(!n)return e;var s=cr(n.split("::")),c=s[0],u=s.slice(1),p=br[c](u);return gr(p,r,e),o?(p[p.length-1]="".concat(o,"Uuid"),gr(p,i,e)):a&&(p[p.length-1]="type",gr(p,a,e)),e}),{hostName:r,hostStatus:a,hostType:o,hostUUID:i,ipmi:c,shortHostName:s})}));return{query:a,afterQueryReturn:o}};function xr(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&(s+="WHERE ".concat(i));var c="\n SELECT\n a.host_name,\n a.host_status,\n a.host_type,\n a.host_uuid,\n b.anvil_uuid,\n b.anvil_name\n FROM hosts AS a\n LEFT JOIN anvils AS b\n ON a.host_uuid IN (\n b.anvil_node1_host_uuid,\n b.anvil_node2_host_uuid,\n b.anvil_dr1_host_uuid\n )\n ".concat(s,"\n ORDER BY a.host_name ASC;"),u=P((function(e,t){var n,r,a,i=(a=6,function(e){if(Array.isArray(e))return e}(r=t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(r,a)||function(e,t){if(e){if("string"==typeof e)return xr(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?xr(e,t):void 0}}(r,a)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),s=i[0],c=i[1],u=i[2],p=i[3],l=i[4],d=i[5];return l&&(n={name:d,uuid:l}),e[(0,er.s)(p,o)]={anvil:n,hostName:s,hostStatus:c,hostType:u,hostUUID:p,shortHostName:U(s)},e}),{});if(r){var p=yr({keys:(0,x.N)(r,"string[]",{modifierType:"sql"})});c=p.query,u=p.afterQueryReturn}return t&&(t.afterQueryReturn=u),c})),_r=function(e,t){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},a=r.fallbackResult,o=void 0===a?[]:a;return null!==(n=e.match(t))&&void 0!==n?n:o};function Sr(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}function Er(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Ar(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ar(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Ar(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},r=n.defaultPort,a=void 0===r?5432:r,o=n.defaultUser,i=void 0===o?"admin":o;return Object.entries(t).reduce((function(t,n){var r=Er(n,2),o=r[0],s=r[1],c=s.host,u=s.ping,p=s.port,l=void 0===p?a:p,d=s.user,f=void 0===d?i:d,m=Number(l);return o===e?(t.inbound.port=m,t.inbound.user=f):t.peer[c]={hostUUID:o,ipAddress:c,isPing:"1"===u,port:m,user:f},t}),{inbound:{ipAddress:{},port:a,user:i},peer:{}})},Or=I(function(){var e=function(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){Sr(o,r,a,i,s,"next",e)}function s(e){Sr(o,r,a,i,s,"throw",e)}i(void 0)}))}}(regeneratorRuntime.mark((function e(t,n){var r,a,o,i,s,c,u,p,l,f;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=t.query.hostUUIDs,o="a.ip_address_host_uuid",i=(0,O.gA)(),s=A(r,o,{onFallback:function(){return"".concat(o," = '").concat(i,"'")}}),c=s.after,u=s.before,p=u.length>0?u:[i],l=function(e){return(0,er.s)(e,i)},(0,d.Cr)("condHostUUIDs=[".concat(c,"]")),e.prev=7,e.next=10,(0,O.pT)();case 10:a=e.sent,e.next=16;break;case 13:throw e.prev=13,e.t0=e.catch(7),new Error("Failed to get anvil data; CAUSE: ".concat(e.t0));case 16:return f=p.reduce((function(e,t){return e[l(t)]=kr(t,a),e}),{}),(0,d.HQ)(f,"connections="),n&&(n.afterQueryReturn=P((function(e,t){var n=Er(t,4),r=n[0],a=n[1],o=n[2],i=n[3],s=Er(_r(i,/^(.*n)(\d+)_link(\d+)$/),4),c=s[1],u=s[2],p=s[3],d=l(a);return f[d].inbound.ipAddress[o]={hostUUID:a,ifaceId:i,ipAddress:o,ipAddressUUID:r,networkLinkNumber:Number(p),networkNumber:Number(u),networkType:c},e}),f)),e.abrupt("return","SELECT\n a.ip_address_uuid,\n a.ip_address_host_uuid,\n a.ip_address_address,\n CASE\n WHEN a.ip_address_on_type = 'interface'\n THEN (\n CASE\n WHEN b.network_interface_name ~* '.*n\\d+_link\\d+'\n THEN b.network_interface_name\n ELSE b.network_interface_device\n END\n )\n ELSE d.bond_active_interface\n END AS network_name\n FROM ip_addresses AS a\n LEFT JOIN network_interfaces AS b\n ON a.ip_address_on_uuid = b.network_interface_uuid\n LEFT JOIN bridges AS c\n ON a.ip_address_on_uuid = c.bridge_uuid\n LEFT JOIN bonds AS d\n ON c.bridge_uuid = d.bond_bridge_uuid\n OR a.ip_address_on_uuid = d.bond_uuid\n WHERE ".concat(c,"\n AND a.ip_address_note != 'DELETED';"));case 20:case"end":return e.stop()}}),e,null,[[7,13]])})));return function(t,n){return e.apply(this,arguments)}}()),jr=I((function(e,t){var n=e.params.hostUUID,r=(0,er.H)(n),a=yr({keys:[(0,_n.f)(r)]}),o=a.afterQueryReturn,i=a.query;return t&&(t.afterQueryReturn=o),i}));function Cr(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}var Rr=function(){var e=function(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){Cr(o,r,a,i,s,"next",e)}function s(e){Cr(o,r,a,i,s,"throw",e)}i(void 0)}))}}(regeneratorRuntime.mark((function e(t,n){var r,a,o,i,s,c,p,f,m,v,h,b,g,y,w,_,S,E,A,k,j,C,R,I;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:r=t.body,a=(r=void 0===r?{}:r).enterpriseUUID,o=r.hostIPAddress,i=r.hostName,s=r.hostPassword,c=r.hostSSHPort,p=r.hostType,f=r.hostUser,m=r.hostUUID,v=r.redhatPassword,h=r.redhatUser,b=Boolean(a),g=Boolean(m),y=Boolean(v)||Boolean(h),w=(0,x.N)(a,"string"),_=(0,x.N)(o,"string"),S=(0,x.N)(i,"string"),E=(0,x.N)(s,"string"),A=(0,x.N)(c,"number",{fallback:22}),k=(0,x.N)(p,"string"),j=(0,x.N)(f,"string",{fallback:"root"}),C=(0,x.N)(m,"string"),R=(0,x.N)(v,"string"),I=(0,x.N)(h,"string"),e.prev=16,u()(l.tf.test(_),"Data host IP address must be a valid IPv4 address; got [".concat(_,"]")),u()(l.FZ.test(S),"Data host name can only contain alphanumeric, hyphen, and dot characters; got [".concat(S,"]")),u()(l.OU.test(E),"Data host password must be peaceful string; got [".concat(E,"]")),u()(/^node|dr$/.test(k),'Data host type must be one of "node" or "dr"; got ['.concat(k,"]")),u()(l.OU.test(j),"Data host user must be a peaceful string; got [".concat(j,"]")),b&&u()(l.Qt.test(w),"Data enterprise UUID must be a valid UUIDv4; got [".concat(w,"]")),g&&u()(l.Qt.test(C),"Data host UUID must be a valid UUIDv4; got [".concat(C,"]")),y&&(u()(l.OU.test(R),"Data redhat password must be a peaceful string; got [".concat(R,"]")),u()(l.OU.test(I),"Data redhat user must be a peaceful string; got [".concat(I,"]"))),e.next=31;break;case 27:return e.prev=27,e.t0=e.catch(16),(0,d.x5)("Failed to assert value when trying to prepare host; CAUSE: ".concat(e.t0)),e.abrupt("return",n.status(400).send());case 31:if(e.prev=31,!g){e.next=35;break}return e.next=35,(0,O.VD)({file:__filename,update_value_only:1,variable_name:"system::configured",variable_source_table:"hosts",variable_source_uuid:C,variable_value:0});case 35:return e.next=37,(0,O.ZP)({file:__filename,job_command:l.us.usr.sbin["striker-initialize-host"].self,job_data:Dn({obj:{enterprise_uuid:w,host_ip_address:_,host_name:S,password:E,rh_password:R,rh_user:I,ssh_port:A,type:k}}),job_description:"job_0022",job_name:"initialize::".concat(k,"::").concat(_),job_title:"job_002".concat("dr"===k?"1":"0")});case 37:e.next=43;break;case 39:return e.prev=39,e.t1=e.catch(31),(0,d.x5)("Failed to init host; CAUSE: ".concat(e.t1)),e.abrupt("return",n.status(500).send());case 43:n.status(200).send();case 44:case"end":return e.stop()}}),e,null,[[16,27],[31,39]])})));return function(t,n){return e.apply(this,arguments)}}();function Ir(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Tr(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0)try{u=(0,d.hT)("--date","@".concat(i),"--rfc-3339","ns"),c="a.modified_date >= '".concat(u,"'")}catch(e){(0,d.x5)("Failed to convert value [".concat(i,"] to rfc-3339 format; CAUSE: ").concat(e))}else c="\n a.modified_date >= (\n LEAST(\n (\n SELECT modified_date\n FROM jobs\n WHERE job_progress < 100\n ORDER BY modified_date ASC\n LIMIT 1\n ),\n NOW() - INTERVAL '1 hour'\n )\n )";return s&&(c="".concat(c," AND a.job_command LIKE '%").concat(s,"%'")),p="\n SELECT\n a.job_uuid,\n a.job_name,\n a.job_title,\n b.host_uuid,\n b.host_name,\n a.job_progress,\n a.job_picked_up_at,\n ROUND(\n EXTRACT(epoch from a.modified_date)\n ) AS modified_epoch\n FROM jobs AS a\n JOIN hosts AS b\n ON a.job_host_uuid = b.host_uuid\n WHERE ".concat(c,"\n AND a.job_name NOT LIKE 'get_server_screenshot%'\n ORDER BY a.modified_date DESC;"),e.prev=7,e.next=10,(0,O.IO)(p);case 10:l=e.sent,e.next=18;break;case 13:return e.prev=13,e.t0=e.catch(7),f=new Le.V("c2b683b","Failed to get jobs; CAUSE: ".concat(e.t0)),(0,d.x5)(f.toString()),e.abrupt("return",n.status(500).send(f.body));case 18:return m=l.map(function(){var e=Zr(regeneratorRuntime.mark((function e(t){var n,r,a,o,i,s,c,u,p,l,d;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return m=8,n=function(e){if(Array.isArray(e))return e}(f=t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(f,m)||function(e,t){if(e){if("string"==typeof e)return Gr(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Gr(e,t):void 0}}(f,m)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),r=n[0],a=n[1],o=n[2],i=n[3],s=n[4],c=n[5],u=n[6],p=n[7],l=U(s),e.next=4,(0,O.Iu)(o);case 4:return d=e.sent,e.abrupt("return",{host:{name:s,shortName:l,uuid:i},modified:Number(p),name:a,progress:Number(c),started:Number(u),title:d,uuid:r});case 6:case"end":return e.stop()}var f,m}),e)})));return function(t){return e.apply(this,arguments)}}()),e.next=21,Promise.all(m);case 21:return v=e.sent,h=v.reduce((function(e,t){return e[t.uuid]=t,e}),{}),e.abrupt("return",n.status(200).send(h));case 24:case"end":return e.stop()}}),e,null,[[7,13]])})));return function(t,n){return e.apply(this,arguments)}}();function Kr(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Jr(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Jr(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Jr(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0||(t+=1,!1)})),e.splice(0,t),e},ta=function(){var e=Xr(regeneratorRuntime.mark((function e(t,n){var r,a,o,i,s,c,u,p,l,f,m,v,h,b,g,y,x,w,_,S,E,A,k,j,C,R,I,T,P,N,D,L;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return r=t.params.uuid,a="\n SELECT\n a.job_uuid,\n a.job_command,\n a.job_data,\n a.job_picked_up_by,\n a.job_picked_up_at,\n a.job_updated,\n a.job_name,\n a.job_progress,\n a.job_title,\n a.job_description,\n a.job_status,\n ROUND(\n EXTRACT(epoch from a.modified_date)\n ) AS modified_epoch,\n b.host_uuid,\n b.host_name\n FROM jobs AS a\n JOIN hosts AS b\n ON a.job_host_uuid = b.host_uuid\n WHERE a.job_uuid = '".concat(r,"';"),e.prev=2,e.next=5,(0,O.IO)(a);case 5:o=e.sent,e.next=12;break;case 8:return e.prev=8,e.t0=e.catch(2),i=new Le.V("249068d","Failed to get job ".concat(r,"; CAUSE: ").concat(e.t0)),e.abrupt("return",n.status(500).send(i.body));case 12:if(o.length){e.next=15;break}return s=new Le.V("b4e559c","No job found with identifier ".concat(r)),e.abrupt("return",n.status(404).send(s.body));case 15:return c=Kr(o,1),u=c[0],p=Kr(u,14),l=p[0],f=p[1],m=p[2],v=p[3],h=p[4],b=p[5],g=p[6],y=p[7],x=p[8],w=p[9],_=p[10],S=p[11],E=p[12],A=p[13],e.next=19,(0,O.Iu)(x);case 19:return k=e.sent,e.next=22,(0,O.Iu)(w);case 22:return j=e.sent,C=U(A),R=ea(m.split(/,|\n/)),I=R.reduce((function(e,t,n){var r=Kr(t.split(/=/),2),a=r[0],o=r[1];return e[n]={name:a,value:o},e}),{}),T=ea(_.split(/(?=(?:brand|email|error|file|header|job|log|message|name|ok|prefix|striker|suffix|t|title|type|unit|ups|warning)_\d{4,})/g)),P=T.map(function(){var e=Xr(regeneratorRuntime.mark((function e(t){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,(0,O.Iu)(t.replace(/\n/g,"\\n"));case 2:return e.t0=e.sent,e.abrupt("return",{value:e.t0});case 4:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),e.next=30,Promise.all(P);case 30:return N=e.sent,D=N.reduce((function(e,t,n){return e[n]=t,e}),{}),(0,d.HQ)({dataLines:R,data:I,rStatusLines:T,statusLines:N,status:D}),L={command:f,data:I,description:j,host:{name:A,shortName:C,uuid:E},modified:Number(S),name:g,pid:Number(v),progress:Number(y),started:Number(h),status:D,title:k,updated:Number(b),uuid:l},e.abrupt("return",n.status(200).send(L));case 35:case"end":return e.stop()}}),e,null,[[2,8]])})));return function(t,n){return e.apply(this,arguments)}}();function na(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw o}}}}function Da(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);nu?p=1:ic?p=1:ol?d=1:cp?d=1:s0&&(j=za(E[0],4),C=j[0],R=j[1],I=j[2],T=j[3],k={description:R,hosts:{1:{uuid:I},2:{uuid:T}},uuid:C}),P={anvil:k,domain:s,hostConfig:{hosts:Object.entries(p).sort(Wa).reduce((function(e,t){var n=za(t,2),r=n[0],a=n[1],o=a.fence,i=void 0===o?{}:o,s=a.ipmi_ip,c=a.name,p=a.network,l=a.ups,f=void 0===l?{}:l,m=qa(r),v=m.name,h=m.number;return(0,d.Cr)("host=".concat(v,",n=").concat(h)),"node"!==v||(e[r]={fences:Object.entries(i).sort(Wa).reduce((function(e,t){var n=za(t,2),r=n[0],a=n[1].port,o=u[r];if(o){var i=o.uuid;e[r]={fenceName:r,fencePort:a,fenceUuid:i}}return e}),{}),hostName:c,hostNumber:h,hostType:v,ipmiIp:s,networks:Object.entries(p).sort(Ga).reduce((function(e,t){var n=za(t,2),r=n[0],a=n[1].ip,o=qa(r),i=o.name,s=o.number;return(0,d.Cr)("hostnetwork=".concat(i,",n=").concat(s)),e[r]={networkIp:a,networkNumber:s,networkType:i},e}),{}),upses:Object.entries(f).sort(Wa).reduce((function(e,t){var n=za(t,2),r=n[0],a=n[1].used,o=_[r];if(o){var i=o.uuid;e[r]={isUsed:Boolean(a),upsName:r,upsUuid:i}}return e}),{})}),e}),{})},name:l,networkConfig:{dnsCsv:m,mtu:Number(v),networks:Object.entries(h).sort(Ga).reduce((function(e,t){var n=za(t,2),r=n[0],a=n[1],o=a.gateway,i=a.network,s=a.subnet,c=qa(r),u=c.name,p=c.number;return(0,d.Cr)("network=".concat(u,",n=").concat(p)),e[r]={networkGateway:o,networkMinIp:i,networkNumber:p,networkSubnetMask:s,networkType:u},e}),{}),ntpCsv:b},prefix:g,sequence:Number(y)},n.status(200).send(P);case 33:case"end":return e.stop()}}),e,null,[[2,8],[19,25]])})));return function(t,n){return e.apply(this,arguments)}}();function Za(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Va(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var o,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,o=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw o}}}}function fo(e,t){if(e){if("string"==typeof e)return mo(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?mo(e,t):void 0}}function mo(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);nt.timestamp?1:-1})),h=v.pop(),(0,d.HQ)(h,"Latest server screenshot: "),h&&(b=h.name,g=h.timestamp,y=(0,sn.readFileSync)(pn().join(f,b),{encoding:"base64"}),p.screenshot=y,p.timestamp=g),e.abrupt("return",n.send(p));case 30:if(!c){e.next=44;break}return e.prev=31,e.next=34,(0,O.eX)(r);case 34:w=e.sent,e.next=41;break;case 37:return e.prev=37,e.t2=e.catch(31),(0,d.x5)("Failed to get server ".concat(r," VNC info; CAUSE: ").concat(e.t2)),e.abrupt("return",n.status(500).send());case 41:return e.abrupt("return",n.send(w));case 44:n.send();case 45:case"end":return e.stop()}}),e,null,[[4,8],[15,19],[31,37]])})));return function(t,n){return e.apply(this,arguments)}}(),So=i().Router();So.delete("/",ho).delete("/:serverUuid",ho).get("/",go).get("/:serverUUID",_o).post("/",uo);const Eo=So;function Ao(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}var ko=function(){var e=function(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){Ao(o,r,a,i,s,"next",e)}function s(e){Ao(o,r,a,i,s,"throw",e)}i(void 0)}))}}(regeneratorRuntime.mark((function e(t,n){var r,a,o,i,s,c,u;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:r=t.body,a=Object.keys(r),o=0,i=a;case 3:if(!(oe.length)&&(t=e.length);for(var n=0,r=new Array(t);n1){var p=i.slice(u.length),l=u.slice(0,-1).replace(/\/+/g,"/"),f="".concat(l).concat(p);return console.log("redirect=".concat(f)),a.redirect(f)}u="/index"}var m=/\.html$/.test(u)?u:"".concat(u,".html"),v="".concat(Po).concat(m),h=(0,sn.existsSync)(v);return(0,d.Cr)("static:[".concat(u,"] requested; html=").concat(h)),h?(0,s.assertInit)({fail:function(e,t,n){var r=e.path,a="/init";return t.setHeader("Cache-Control","must-revalidate, no-store"),r.startsWith(a)?n():t.redirect(a)},invert:!0,succeed:(0,s.assertAuthentication)({fail:function(e,t,n,r){var a="/login";return t.path.startsWith(a)?r():n.redirect(e?"".concat(a,"?rt=").concat(e):a)},failReturnTo:!u.startsWith("/login"),succeed:function(e,t,n){var r=e.path,a=e.query,o=a.re,i=a.rt,s=void 0===i?"/":i;return r.startsWith("/login")?t.redirect(String(s)):r.startsWith("/init")&&!o?t.redirect("/"):n()}})}).apply(void 0,t):o()}),i().static(Po,{extensions:["html"]}));const No=To;function Uo(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}var Do=function(){var e=function(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){Uo(o,r,a,i,s,"next",e)}function s(e){Uo(o,r,a,i,s,"throw",e)}i(void 0)}))}}(regeneratorRuntime.mark((function e(t,n){var r,a,o,i,s,c,p,f,m,v,h,b;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:r=t.body,a=(r=void 0===r?{}:r).agent,o=r.ipAddress,i=r.name,s=t.params.uuid,c=(0,x.N)(a,"string"),p=(0,x.N)(o,"string"),f=(0,x.N)(i,"string"),m=(0,x.N)(s,"string",{fallback:(0,d.Vj)()}),e.prev=7,u()(l.OU.test(c),"Agent must be a peaceful string; got [".concat(c,"]")),u()(l.tf.test(p),"IP address must be a valid IPv4; got [".concat(p,"]")),u()(l.OU.test(f),"Name must be a peaceful string; got [".concat(f,"]")),u()(l.Qt.test(m),"UPS UUID must be a valid UUIDv4; got [".concat(m,"]")),e.next=18;break;case 14:return e.prev=14,e.t0=e.catch(7),(0,d.x5)("Assert value failed when working with UPS; CAUSE: ".concat(e.t0)),e.abrupt("return",n.status(400).send());case 18:return v=(0,O.AB)(),e.prev=19,e.next=22,(0,O.cW)("INSERT INTO\n upses (\n ups_uuid,\n ups_name,\n ups_agent,\n ups_ip_address,\n modified_date\n ) VALUES (\n '".concat(m,"',\n '").concat(f,"',\n '").concat(c,"',\n '").concat(p,"',\n '").concat(v,"'\n ) ON CONFLICT (ups_uuid)\n DO UPDATE SET\n ups_name = '").concat(f,"',\n ups_agent = '").concat(c,"',\n ups_ip_address = '").concat(p,"',\n modified_date = '").concat(v,"';"));case 22:h=e.sent,u()(0===h,"Write exited with code ".concat(h)),e.next=30;break;case 26:return e.prev=26,e.t1=e.catch(19),(0,d.x5)("Failed to write UPS record; CAUSE: ".concat(e.t1)),e.abrupt("return",n.status(500).send());case 30:return b=s?200:201,e.abrupt("return",n.status(b).send());case 32:case"end":return e.stop()}}),e,null,[[7,14],[19,26]])})));return function(t,n){return e.apply(this,arguments)}}();function Lo(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}var Fo=zt({delete:function(){var e=function(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){Lo(o,r,a,i,s,"next",e)}function s(e){Lo(o,r,a,i,s,"throw",e)}i(void 0)}))}}(regeneratorRuntime.mark((function e(t){var n;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,(0,O.cW)("UPDATE upses\n SET ups_ip_address = '".concat(l.oZ,"'\n WHERE ups_uuid IN (").concat(S(t,{elementWrapper:"'",separator:","}),");"));case 2:if(0===(n=e.sent)){e.next=5;break}throw Error("Write exited with code ".concat(n));case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()});function Mo(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}function Go(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return Qo(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Qo(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function Qo(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n]+href=[\\"]+([^\s]+)[\\"]+.+[>]([^<]+)[<]/),u=zo(zo({},s),{},{brand:o,description:i,links:{}});if(c){var p=Go(c,4),l=p[1],d=p[2],f=p[3];u.description=l,u.links[0]={linkHref:d,linkLabel:f}}return/apc/i.test(o)&&(e[r]=u),e}),{}),n.status(200).send(a);case 13:case"end":return e.stop()}}),e,null,[[0,6]])})));return function(t,n){return e.apply(this,arguments)}}(),Ko=Do,Jo=i().Router();Jo.delete("/:uuid?",Fo).get("/",Ho).get("/template",Vo).post("/",Do).put("/:uuid",Ko);const Yo=Jo;function Xo(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return ei(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?ei(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function ei(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0?s:[o],(0,d.HQ)({ulist:c}),e.prev=10,p=0,u()(c.every((function(e,t){return p=t,l.Qt.test(e)})),"All UUIDs must be valid UUIDv4; failed at ".concat(p,", got [").concat(c[p],"]")),e.next=19;break;case 15:return e.prev=15,e.t0=e.catch(10),(0,d.x5)("Failed to assert value during delete user; CAUSE: ".concat(e.t0)),e.abrupt("return",n.status(400).send());case 19:return e.prev=19,e.next=22,(0,O.cW)("UPDATE users\n SET user_algorithm = '".concat(l.oZ,"'\n WHERE user_uuid IN (").concat(S(c,{elementWrapper:"'",separator:","}),");"));case 22:f=e.sent,u()(0===f,"Write exited with code ".concat(f)),e.next=30;break;case 26:return e.prev=26,e.t1=e.catch(19),(0,d.x5)("Failed to delete user(s); CAUSE: ".concat(e.t1)),e.abrupt("return",n.status(500).send());case 30:n.status(204).send();case 31:case"end":return e.stop()}}),e,null,[[10,15],[19,26]])})));return function(t,n){return e.apply(this,arguments)}}();function oi(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n2&&void 0!==arguments[2]?arguments[2]:{},a=r.assign,o=void 0===a?function(e){return[e]}:a,i=r.key,s=r.route,c=void 0===s?"/":s;if("route"in n){var u=o(n),p=u.length;(0,d.Cr)("Set up route ".concat(c," with ").concat(p," handler(s)")),t.use.apply(t,[c].concat(mi(u)))}else i?e(t,n[i],{assign:o,route:pn().posix.join(c,String(i))}):Object.entries(n).forEach((function(n){var r=fi(n,2),a=r[0],i=r[1];e(t,i,{assign:o,route:pn().posix.join(c,a)})}))};function gi(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}const yi=function(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){gi(o,r,a,i,s,"next",e)}function s(e){gi(o,r,a,i,s,"throw",e)}i(void 0)}))}}(regeneratorRuntime.mark((function e(){var t;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return(t=i()()).use((0,o.json)()),t.use(a()({origin:!0,credentials:!0})),e.t0=t,e.next=6,s.session;case 6:return e.t1=e.sent,e.t0.use.call(e.t0,e.t1),t.use(s.passport.initialize()),t.use(s.passport.authenticate("session")),t.use((function(e,t,n){var r=e.originalUrl,a=e.method;(0,d.Cr)("Received ".concat(a," ").concat(r)),n()})),bi(t,di.private,{assign:function(e){return[s.guardApi,e]},route:"/api"}),bi(t,di.public,{route:"/api"}),t.use(di.static),e.abrupt("return",t);case 15:case"end":return e.stop()}}),e)})))()},6864:(e,t,n)=>{"use strict";function r(e){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},r(e)}function a(e,t){for(var n=0;nd}),n(8304),n(8309),n(2222),n(489),n(2772),n(3710),n(1539),n(9714),n(2419),n(4812),n(6992),n(2579),n(8783),n(3948),n(8011),n(9070),n(2526),n(1817),n(2165);var d=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&p(e,t)}(d,e);var t,n,r,s,c=(t=d,n=u(),function(){var e,r=l(t);if(n){var a=l(this).constructor;e=Reflect.construct(r,arguments,a)}else e=r.apply(this,arguments);return o(this,e)});function d(e,t){var n;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,d),n=c.call(this,t),Object.setPrototypeOf(i(n),d.prototype),n.code=e,n}return r=d,(s=[{key:"body",get:function(){return{code:this.code,message:this.message,name:this.name}}},{key:"toString",value:function(){return"".concat(this.name,"(").concat(this.code,"): ").concat(this.message)}}])&&a(r.prototype,s),Object.defineProperty(r,"prototype",{writable:!1}),d}(s(Error))},9829:(e,t,n)=>{"use strict";n.d(t,{Pd:()=>I,pQ:()=>F,HI:()=>H,nP:()=>z,Yu:()=>q,pT:()=>$,M6:()=>W,zM:()=>G,tS:()=>Q,gA:()=>Z,R5:()=>V,QY:()=>K,rV:()=>J,Q7:()=>Y,eX:()=>X,OP:()=>D,ZP:()=>U,IO:()=>P,lu:()=>T,AB:()=>M,Iu:()=>ee,VD:()=>L,cW:()=>N}),n(8304),n(489),n(2419),n(8011),n(7941),n(2526),n(9753),n(1817),n(2165),n(8783),n(1038),n(7042),n(8309),n(5003),n(9554),n(4747),n(9337),n(3321),n(5666),n(7327),n(1539),n(2222),n(2564),n(4916),n(5306),n(2772),n(9600),n(8674),n(1249),n(935),n(3210),n(6992),n(3948),n(9653),n(3123),n(9070);var r=n(2081),a=n(2361),o=n.n(a),i=n(7147),s=n(4108),c=function(e){return e.replace(/\s+/g," ")},u=(n(2481),n(4151));function p(e){return p="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},p(e)}var l=["args"],d=["args","gid","restartInterval","stdio","uid"],f=["job_progress","line"];function m(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||x(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function v(e,t,n,r,a,o,i){try{var s=e[o](i),c=s.value}catch(e){return void n(e)}s.done?t(c):Promise.resolve(c).then(r,a)}function h(e){return function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){v(o,r,a,i,s,"next",e)}function s(e){v(o,r,a,i,s,"throw",e)}i(void 0)}))}}function b(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function g(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}function S(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function E(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{},n=t.eventEmitterOptions,r=void 0===n?{}:n,a=t.startOptions,o=void 0===a?{}:a;S(this,c),C(O(e=i.call(this,r)),"MAP_TO_EVT_HDL",{connected:function(t){var n=t.options,r=t.ps;(0,u.HQ)(n,"Successfully started anvil-access-module daemon (pid=".concat(r.pid,"): ")),e.emit("active",r.pid)}});var s=o.args,p=void 0===s?[]:s,d=_(o,l),f=[].concat(y(p),["--emit-events",c.VERBOSE]).filter((function(e){return""!==e}));return e.ps=e.start(g({args:f},d)),e}return t=c,n=[{key:"start",value:function(){var e,t,n=this,a=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},o=a.args,i=void 0===o?[]:o,c=a.gid,p=void 0===c?s.cI:c,l=a.restartInterval,f=void 0===l?1e4:l,m=a.stdio,v=void 0===m?"pipe":m,h=a.uid,b=void 0===h?s.NF:h,y=_(a,d),x=g({args:i,gid:p,restartInterval:f,stdio:v,uid:b},y);(0,u.HQ)(x,"Starting anvil-access-module daemon with: ");var w=(0,r.spawn)(s.us.usr.sbin["anvil-access-module"].self,i,g({gid:p,stdio:v,uid:b},y));w.once("error",(function(e){(0,u.x5)("anvil-access-module daemon (pid=".concat(w.pid,") error: ").concat(e.message),e)})),w.once("close",(function(e,t){(0,u.HQ)({code:e,options:x,signal:t},"anvil-access-module daemon (pid=".concat(w.pid,") closed: ")),n.emit("inactive",w.pid),(0,u.Cr)("Waiting ".concat(f," before restarting.")),setTimeout((function(){n.ps=n.start(x)}),f)})),null===(e=w.stderr)||void 0===e||e.setEncoding("utf-8").on("data",(function(e){(0,u.x5)("anvil-access-module daemon stderr: ".concat(e))}));var S="";return null===(t=w.stdout)||void 0===t||t.setEncoding("utf-8").on("data",(function(e){for(var t=e.replace(/(\n)?event=([^\n]*)\n/g,(function(){for(var e,t=arguments.length,r=new Array(t),a=0;a1?a-1:0),i=1;i2&&void 0!==arguments[2]?arguments[2]:{},r=n.prefix,a=void 0===r?"":r,o=e.repeat(t);return o?"".concat(a).concat(o):""}("v",s.ST,{prefix:"-"}));var I=new R,T=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a,o,i,s,c,u,p=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=p.length>1&&void 0!==p[1]?p[1]:{},r=n.params,a=void 0===r?[]:r,o=n.pre,i="".concat((void 0===o?["Database"]:o).join("->"),"->").concat(t),s=a.map((function(e){var t;try{t=JSON.stringify(e)}catch(n){t=String(e)}return'"'.concat(t.replaceAll('"','\\"'),'"')})),e.next=5,I.interact.apply(I,["x",i].concat(y(s)));case 5:return c=e.sent,u=c.sub_results,e.abrupt("return",u);case 8:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),P=function(e){return I.interact("r",c(e))},N=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,I.interact("w",c(t));case 2:return n=e.sent,r=n.write_code,e.abrupt("return",r);case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),U=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a,o,i,c,u,p;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.job_progress,r=void 0===n?s.sw:n,a=t.line,o=void 0===a?0:a,i=_(t,f),e.next=3,T("insert_or_update_jobs",{params:[g({job_progress:r,line:o},i)]});case 3:return c=e.sent,u=m(c,1),p=u[0],e.abrupt("return",p);case 7:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),D=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("insert_or_update_users",{params:[t]});case 2:return n=e.sent,r=m(n,1),a=r[0],e.abrupt("return",a);case 6:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),L=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("insert_or_update_variables",{params:[t]});case 2:return n=e.sent,r=m(n,1),a=r[0],e.abrupt("return",a);case 6:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),F=function(e,t,n,r){var a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{jobHostUUID:void 0},o=a.jobHostUUID,i={file:__filename,job_command:s.us.usr.sbin["anvil-sync-shared"].self,job_data:t,job_name:"storage::".concat(e),job_title:"job_".concat(n),job_description:"job_".concat(r)};return o&&(i.job_host_uuid=o),U(i)},M=function(){var e;try{e=(0,u.hT)("--rfc-3339","ns").trim()}catch(e){throw new Error("Failed to get timestamp for database use; CAUSE: ".concat(e))}return e},H=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("encrypt_password",{params:[t],pre:["Account"]});case 2:return n=e.sent,r=m(n,1),a=r[0],e.abrupt("return",a);case 6:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),q=function(){var e=h(regeneratorRuntime.mark((function e(){var t,n,r,a,o,i,s,c=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:for(t=c.length,n=new Array(t),r=0;r")),e.next=4,I.interact("x",a);case 4:return o=e.sent,i=m(o.sub_results,1),s=i[0],(0,u.HQ)(s,"".concat(a," data: ")),e.abrupt("return",s);case 9:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),B=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a,o,i,s,c;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.keys,r=t.operator,a=t.value,o="data->".concat(n.join("->")),e.next=4,I.interact("x",o,r,a);case 4:return i=e.sent,s=m(i.sub_results,1),c=s[0],(0,u.HQ)(c,"".concat(o," data: ")),e.abrupt("return",c);case 9:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),z=function(){var e=h(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("get_anvils");case 2:return e.abrupt("return",q("anvils"));case 3:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),$=function(){var e=h(regeneratorRuntime.mark((function e(){var t,n,r;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,B({keys:["database"],operator:"=",value:"{}"});case 2:return e.next=4,T("read_config",{pre:["Storage"]});case 4:if(t=e.sent,n=m(t,1),r=n[0],0===Number(r)){e.next=9;break}throw new Error("Failed to read config");case 9:return e.abrupt("return",q("database"));case 10:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),W=function(){var e=h(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("get_fence_data",{pre:["Striker"]});case 2:return e.abrupt("return",q("fence_data"));case 3:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),G=function(){var e=h(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("get_hosts");case 2:return e.abrupt("return",q("hosts"));case 3:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),Q=function(){var e;try{e=(0,i.readFileSync)(s.us.etc.hostname.self,{encoding:"utf-8"}).trim()}catch(e){throw new Error("Failed to get local host name; CAUSE: ".concat(e))}return(0,u.Cr)("localHostName=".concat(e)),e},Z=function(){var e;try{e=(0,i.readFileSync)(s.us.etc.anvil["host.uuid"].self,{encoding:"utf-8"}).trim()}catch(e){throw new Error("Failed to get local host UUID; CAUSE: ".concat(e))}return(0,u.Cr)("localHostUUID=[".concat(e,"]")),e},V=function(){var e=h(regeneratorRuntime.mark((function e(t){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("load_manifest",{params:[{manifest_uuid:t}],pre:["Striker"]});case 2:return e.abrupt("return",q("manifests"));case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),K=function(){var e=h(regeneratorRuntime.mark((function e(t,n){var r,a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(r=n){e.next=6;break}return e.next=4,G();case 4:a=e.sent,r=a.host_uuid[t].short_host_name;case 6:return e.next=8,T("load_interfaces",{params:[{host:r,host_uuid:t}],pre:["Network"]});case 8:return e.abrupt("return",q("network"));case 9:case"end":return e.stop()}}),e)})));return function(t,n){return e.apply(this,arguments)}}(),J=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a,o,i,s,c,u,p,l,d,f,v=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=v.length>1&&void 0!==v[1]?v[1]:{},r=n.password,a=n.port,e.next=3,T("get_peer_data",{params:[{password:r,port:a,target:t}],pre:["Striker"]});case 3:return o=e.sent,i=m(o,2),s=i[0],c=i[1],u=c.host_name,p=c.host_os,l=c.host_uuid,d=c.internet,f=c.os_registered,e.abrupt("return",{hostName:u,hostOS:p,hostUUID:l,isConnected:"1"===s,isInetConnected:"1"===d,isOSRegistered:"yes"===f});case 13:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),Y=function(){var e=h(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,T("get_ups_data",{pre:["Striker"]});case 2:return e.abrupt("return",q("ups_data"));case 3:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),X=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a,o,i,s,c,p,l,d;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,P("SELECT variable_value FROM variables WHERE variable_name = 'server::".concat(t,"::vncinfo';"));case 2:if((n=e.sent).length){e.next=5;break}throw new Error("No record found");case 5:return r=m(n,1),a=m(r[0],1),o=a[0],i=o.split(":"),s=m(i,2),c=s[0],p=s[1],l=Number(p),d={domain:c,port:l,protocol:"ws"},(0,u.HQ)(d,"VNC info for server [".concat(t,"]: ")),e.abrupt("return",d);case 12:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),ee=function(){var e=h(regeneratorRuntime.mark((function e(t){var n,r,a;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n="",e.prev=1,e.next=4,T("parse_banged_string",{params:[{key_string:t}],pre:["Words"]});case 4:r=e.sent,a=m(r,1),n=a[0],e.next=12;break;case 9:e.prev=9,e.t0=e.catch(1),(0,u.x5)("Failed to translate; CAUSE: ".concat(e.t0));case 12:return e.abrupt("return",n);case 13:case"end":return e.stop()}}),e,null,[[1,9]])})));return function(t){return e.apply(this,arguments)}}()},6363:(e,t,n)=>{"use strict";function r(e){return function(e){if(Array.isArray(e))return a(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?a(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);no}),n(9753),n(2526),n(1817),n(1539),n(2165),n(6992),n(8783),n(3948),n(1038),n(7042),n(8309),n(4916);const o=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.parameters,a=void 0===n?[]:n,o=t.notCallableReturn;return"function"==typeof e?e.apply(void 0,r(a)):o}},3233:(e,t,n)=>{"use strict";n.d(t,{Q:()=>a}),n(2222);var r=n(4108),a=function(e){return"".concat(r.gM,".").concat(e)}},4541:(e,t,n)=>{"use strict";n.d(t,{F:()=>r});var r="local"},9831:(e,t,n)=>{"use strict";n.d(t,{FZ:()=>u,Ke:()=>c,OU:()=>d,Qt:()=>f,ah:()=>l,tf:()=>p}),n(2222),n(4603),n(4916),n(9714);var r="[a-f0-9]",a="(?:25[0-5]|(?:2[0-4]|1[0-9]|[1-9]|)[0-9])",o="[a-z0-9]",i="[a-z0-9-]",s="(?:".concat(a,"[.]){3}").concat(a),c="".concat(r,"{8}-(?:").concat(r,"{4}-){3}").concat(r,"{12}"),u=new RegExp("^(?:".concat(o,"(?:").concat(i,"{0,61}").concat(o,")?[.])+").concat(o).concat(i,"{0,61}").concat(o,"$")),p=new RegExp("^".concat(s,"$")),l=new RegExp("(?:".concat(s,",)*").concat(s)),d=/^[^'"/\\><}{]+$/,f=new RegExp("^".concat(c,"$"))},5230:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o}),n(9554),n(1539),n(4747),n(7941),n(9600);var r=n(1017),a=n.n(r);const o=function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:a().parse(process.cwd()).root;return Object.keys(t).forEach((function(r){if("self"!==r){var o=a().join(n,r);t[r].self=o,e(t[r],o)}})),t}({etc:{anvil:{"host.uuid":{}},hostname:{}},mnt:{shared:{incoming:{}}},opt:{alteeve:{screenshots:{}}},tmp:{},usr:{bin:{date:{},getent:{},mkfifo:{},openssl:{},"osinfo-query":{},psql:{},rm:{},sed:{},uuidgen:{}},sbin:{"anvil-access-module":{},"anvil-boot-server":{},"anvil-configure-host":{},"anvil-delete-server":{},"anvil-join-anvil":{},"anvil-manage-alerts":{},"anvil-manage-keys":{},"anvil-manage-power":{},"anvil-provision-server":{},"anvil-safe-start":{},"anvil-safe-stop":{},"anvil-shutdown-server":{},"anvil-sync-shared":{},"anvil-update-system":{},"striker-boot-machine":{},"striker-initialize-host":{},"striker-manage-install-target":{},"striker-manage-peers":{}}},var:{www:{html:{}}}})},4108:(e,t,n)=>{"use strict";n.d(t,{Vn:()=>l,gM:()=>p,ST:()=>d,sw:()=>f,oZ:()=>c,bR:()=>b,rj:()=>g,Uq:()=>y,Fe:()=>x.F,Su:()=>w,Im:()=>S,cI:()=>h,px:()=>m,NF:()=>v,Ke:()=>E.Ke,FZ:()=>E.FZ,tf:()=>E.tf,ah:()=>E.ah,OU:()=>E.OU,Qt:()=>E.Qt,us:()=>i.Z,C_:()=>s,wO:()=>A});var r,a,o,i=n(5230),s="striker-ui-api::session::secret",c="DELETED",u=(n(9653),n(4151)),p=null!==(r=process.env.COOKIE_PREFIX)&&void 0!==r?r:"suiapi",l=Number(process.env.COOKIE_ORIGINAL_MAX_AGE)||288e5,d=Number(process.env.DEBUG_ACCESS)||0,f=Number(process.env.DEFAULT_JOB_PROGRESS)||0,m=Number(process.env.PORT)||8080,v=(0,u.Sd)(null!==(a=process.env.PUID)&&void 0!==a?a:"striker-ui-api"),h=(0,u.X2)(null!==(o=process.env.PGID)&&void 0!==o?o:v),b=1,g=2,y="host_key_changed::",x=n(4541),w=8589934592;function _(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n{"use strict";n.d(t,{H:()=>o,s:()=>i});var r=n(4541),a=n(9829),o=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,a.gA)();return e===r.F?t:e},i=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:(0,a.gA)();return e===t?r.F:e}},972:(e,t,n)=>{"use strict";n.d(t,{N:()=>i}),n(4678),n(5827),n(1539),n(4916),n(3123);var r=n(6363),a={none:void 0,sql:n(4633).f},o={boolean:function(e){return Boolean(e)},number:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;return parseFloat(String(e))||n},string:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return e?t(e):n},"string[]":function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=n;return e instanceof Array?r=e.reduce((function(e,n){return n&&e.push(t(n)),e}),[]):e&&(r=t(e).split(/[,;]/)),r}},i=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=n.fallback,s=n.modifierType,c=void 0===s?"none":s,u=n.modifier,p=void 0===u?a[c]:u;return o[t](e,(function(e){var t=String(e);return(0,r.Z)(p,{notCallableReturn:t,parameters:[t]})}),i)}},4633:(e,t,n)=>{"use strict";n.d(t,{f:()=>r}),n(4916),n(5306);var r=function(e){return e.replace(/'/g,"''")}},4151:(e,t,n)=>{"use strict";n.d(t,{Cr:()=>b,HQ:()=>g,Sd:()=>v,Tt:()=>u,Vj:()=>y,X2:()=>m,aq:()=>l,hT:()=>p,rm:()=>d,x5:()=>h}),n(2222),n(9653),n(4916),n(3123),n(3210),n(9070),n(7941),n(2526),n(7327),n(1539),n(5003),n(9554),n(4747),n(9337),n(3321);var r=n(2081),a=n(5230);function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},n=t.eol,r=void 0===n?"\n":n,a=t.stream,o=void 0===a?"stdout":a;return process[o].write("".concat(e).concat(r))},u=function(){for(var e=arguments.length,t=new Array(e),n=0;n1&&void 0!==arguments[1]?arguments[1]:"Variables: ";return c("".concat(t).concat(JSON.stringify(e,null,2)))},y=function(){return function(){for(var e=arguments.length,t=new Array(e),n=0;n{"use strict";n.r(t),n.d(t,{assertAuthentication:()=>N,assertInit:()=>H,guardApi:()=>U,passport:()=>m,proxyServerVnc:()=>V,proxyServerVncUpgrade:()=>K,session:()=>P}),n(5666),n(2222),n(8309),n(1539),n(8674),n(9753),n(2526),n(1817),n(2165),n(6992),n(8783),n(3948),n(7042),n(1038),n(4916);var r=n(8212),a=n.n(r),o=n(8462),i=n(4108),s=n(9829),c=n(972),u=n(4151);function p(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return l(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?l(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0,"No existing session secret found."),o=n[0],c=1,r=function(e){if(Array.isArray(e))return e}(o)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(o,c)||function(e,t){if(e){if("string"==typeof e)return x(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?x(e,t):void 0}}(o,c)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),t=r[0],(0,u.Cr)("Found an existing session secret."),e.abrupt("return",t);case 11:e.prev=11,e.t0=e.catch(0),(0,u.x5)("Failed to get session secret from database; CAUSE: ".concat(e.t0));case 14:try{t=(0,u.aq)("rand","-base64","32").trim(),(0,u.Cr)("Generated a new session secret.")}catch(e){(0,u.x5)("Failed to generate session secret; CAUSE: ".concat(e)),process.exit(i.rj)}return e.prev=15,e.next=18,(0,s.VD)({file:__filename,variable_name:i.C_,variable_value:t});case 18:a=e.sent,(0,u.Cr)("Recorded session secret as variable identified by ".concat(a,".")),e.next=26;break;case 22:e.prev=22,e.t1=e.catch(15),(0,u.x5)("Failed to record session secret; CAUSE: ".concat(e.t1)),process.exit(i.rj);case 26:return e.abrupt("return",t);case 27:case"end":return e.stop()}var o,c}),e,null,[[0,11],[15,22]])})),function(){var t=this,n=arguments;return new Promise((function(r,a){var o=e.apply(t,n);function i(e){w(o,r,a,i,s,"next",e)}function s(e){w(o,r,a,i,s,"throw",e)}i(void 0)}))});return function(){return t.apply(this,arguments)}}();function S(e){return S="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},S(e)}function E(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return O(this,m),f.call(this,e)}return t=m,n=[{key:"destroy",value:(p=k(regeneratorRuntime.mark((function e(t,n){var r;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return(0,u.Cr)("Destroy session ".concat(t)),e.prev=1,e.next=4,(0,s.cW)("UPDATE sessions\n SET session_salt = '".concat(i.oZ,"', modified_date = '").concat((0,s.AB)(),"'\n WHERE session_uuid = '").concat(t,"';"));case 4:r=e.sent,h()(0===r,"Write exited with code ".concat(r)),e.next=12;break;case 8:return e.prev=8,e.t0=e.catch(1),(0,u.x5)("Failed to complete DB write in destroy session ".concat(t,"; CAUSE: ").concat(e.t0)),e.abrupt("return",null==n?void 0:n.call(null,e.t0));case 12:return e.abrupt("return",null==n?void 0:n.call(null));case 13:case"end":return e.stop()}}),e,null,[[1,8]])}))),function(e,t){return p.apply(this,arguments)})},{key:"get",value:(c=k(regeneratorRuntime.mark((function e(t,n){var r,a,o,c,p,l;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return(0,u.Cr)("Get session ".concat(t)),e.prev=1,e.next=4,(0,s.IO)("SELECT\n s.session_uuid,\n u.user_uuid,\n s.modified_date\n FROM sessions AS s\n JOIN users AS u\n ON s.session_user_uuid = u.user_uuid\n WHERE s.session_salt != '".concat(i.oZ,"'\n AND s.session_uuid = '").concat(t,"';"));case 4:r=e.sent,e.next=10;break;case 7:return e.prev=7,e.t0=e.catch(1),e.abrupt("return",n(e.t0));case 10:if(r.length){e.next=12;break}return e.abrupt("return",n(null));case 12:return d=r[0],f=3,a=function(e){if(Array.isArray(e))return e}(d)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,s=!1;try{for(n=n.call(e);!(i=(r=n.next()).done)&&(o.push(r.value),!t||o.length!==t);i=!0);}catch(e){s=!0,a=e}finally{try{i||null==n.return||n.return()}finally{if(s)throw a}}return o}}(d,f)||function(e,t){if(e){if("string"==typeof e)return E(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?E(e,t):void 0}}(d,f)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}(),o=a[1],c=a[2],p=m.calculateCookieMaxAge(c),l={cookie:{maxAge:p,originalMaxAge:i.Vn},passport:{user:o}},e.abrupt("return",n(null,l));case 16:case"end":return e.stop()}var d,f}),e,null,[[1,7]])}))),function(e,t){return c.apply(this,arguments)})},{key:"set",value:(o=k(regeneratorRuntime.mark((function e(t,n,r){var a,o,i,c,p;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return(0,u.HQ)({session:n},"Set session ".concat(t,": ")),a=n.passport,o=(a=void 0===a?{}:a).user,e.prev=4,h().ok(o,"Missing user identifier"),i=(0,s.gA)(),c=(0,s.AB)(),e.next=10,(0,s.cW)("INSERT INTO\n sessions (\n session_uuid,\n session_host_uuid,\n session_user_uuid,\n session_salt,\n modified_date\n )\n VALUES\n (\n '".concat(t,"',\n '").concat(i,"',\n '").concat(o,"',\n '',\n '").concat(c,"'\n )\n ON CONFLICT (session_uuid)\n DO UPDATE SET modified_date = '").concat(c,"';"));case 10:p=e.sent,h()(0===p,"Write exited with code ".concat(p)),e.next=18;break;case 14:return e.prev=14,e.t0=e.catch(4),(0,u.x5)("Failed to complete DB write in set session ".concat(t,"; CAUSE: ").concat(e.t0)),e.abrupt("return",null==r?void 0:r.call(null,e.t0));case 18:return e.abrupt("return",null==r?void 0:r.call(null));case 19:case"end":return e.stop()}}),e,null,[[4,14]])}))),function(e,t,n){return o.apply(this,arguments)})},{key:"touch",value:(a=k(regeneratorRuntime.mark((function e(t,n,r){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return(0,u.HQ)({session:n},"Touch session ".concat(t,": ")),e.abrupt("return",null==r?void 0:r.call(null));case 2:case"end":return e.stop()}}),e)}))),function(e,t,n){return a.apply(this,arguments)})}],r=[{key:"calculateCookieMaxAge",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.Vn,n=Date.parse(e),r=n+t,a=r-Date.now();return(0,u.HQ)({sessionModifiedDate:e,sessionDeadlineEpoch:r,cookieMaxAge:a}),a}}],n&&j(t.prototype,n),r&&j(t,r),Object.defineProperty(t,"prototype",{writable:!1}),m}(b.Store);const P=k(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.t0=g(),e.t1={httpOnly:!0,maxAge:i.Vn,secure:!1},e.t2=function(e){var t=e.originalUrl,n=(0,u.Vj)();return(0,u.Cr)("Generated session identifier ".concat(n,"; access to ").concat(t)),n},e.t3=(0,y.Q)("sid"),e.next=6,_();case 6:return e.t4=e.sent,e.t5=new T,e.t6={cookie:e.t1,genid:e.t2,name:e.t3,resave:!1,saveUninitialized:!1,secret:e.t4,store:e.t5},e.abrupt("return",(0,e.t0)(e.t6));case 10:case"end":return e.stop()}}),e)})))();var N=function(){var e,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.fail,r=void 0===n?function(e,t,n){return n.status(404).send()}:n,a=t.failReturnTo,o=t.succeed,i=void 0===o?function(e,t,n){return n()}:o;!0===a?e=function(e){var t=e.originalUrl,n=e.url;return t||n}:"string"==typeof a&&(e=function(){return a});var s="string"==typeof r?function(e,t,n){return n.redirect(e?"".concat(r,"?rt=").concat(e):r)}:r,c="string"==typeof i?function(e,t){return t.redirect(i)}:i;return function(){for(var t,n=arguments.length,r=new Array(n),a=0;a0&&void 0!==arguments[0]?arguments[0]:{},t=e.fail,n=void 0===t?function(e,t){return t.status(401).send()}:t,r=e.hostUuid,a=void 0===r?i.Fe:r,o=e.invert,c=e.succeed,p=void 0===c?function(e,t,n){return n()}:c;return F(regeneratorRuntime.mark((function e(){var t,r,i,c,l,d,f,m=arguments;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:for(t=m.length,r=new Array(t),i=0;i0&&void 0!==arguments[0]?arguments[0]:"";return e.replace(new RegExp("^".concat(Q,"/(").concat(i.Ke,")")),"$1")},V=(0,B.createProxyMiddleware)({changeOrigin:!0,pathFilter:"".concat(Q,"/*"),router:(W=regeneratorRuntime.mark((function e(t){var n,r,a,o,i,c;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=t.url,r=Z(n),(0,u.Cr)("Got param [".concat(r,"] from [").concat(n,"]")),e.prev=3,e.next=6,(0,s.eX)(r);case 6:c=e.sent,a=c.domain,o=c.port,i=c.protocol,e.next=16;break;case 12:return e.prev=12,e.t0=e.catch(3),(0,u.x5)("Failed to get server ".concat(r," VNC info; CAUSE: ").concat(e.t0)),e.abrupt("return");case 16:return e.abrupt("return",{host:a,protocol:i,port:o});case 17:case"end":return e.stop()}}),e,null,[[3,12]])})),G=function(){var e=this,t=arguments;return new Promise((function(n,r){var a=W.apply(e,t);function o(e){$(a,n,r,o,i,"next",e)}function i(e){$(a,n,r,o,i,"throw",e)}o(void 0)}))},function(e){return G.apply(this,arguments)}),on:{error:function(e,t,n){if((0,u.x5)("VNC proxy error: ".concat(e)),n){var r=Z(t.url),a=(0,y.Q)("vncerror.".concat(r)),o=new z.V("72c969b","".concat(e.name,": ").concat(e.message)),s=JSON.stringify(o.body),c=encodeURIComponent(s),p="".concat(a,"=j:").concat(c,"; Path=/server; SameSite=Lax; Max-Age=3");if((0,u.HQ)({errapiCookie:p},"Error cookie: "),"writeHead"in n)return(0,u.Cr)("Found ServerResponse object"),n.writeHead(500,{"Set-Cookie":"".concat(p)}).end();(0,u.Cr)("Found Socket object");var l=t.headers["sec-websocket-key"],d=(0,q.createHash)("sha1").update(l+i.wO,"binary").digest("base64"),f=["HTTP/1.1 101 Switching Protocols","Connection: upgrade","Sec-WebSocket-Accept: ".concat(d),"Set-Cookie: ".concat(p),"Upgrade: websocket"];n.end("".concat(f.join("\r\n"),"\r\n"),"utf-8")}else(0,u.x5)("Missing response; got [".concat(n,"]"))}},ws:!0}),K=null!==(M=V.upgrade)&&void 0!==M?M:function(){(0,u.Cr)("No upgrade handler for server VNC connection(s).")}},46:(e,t,n)=>{"use strict";var r=n(412)("body-parser"),a=Object.create(null);function o(e){return function(){return function(e){var t=a[e];if(void 0!==t)return t;switch(e){case"json":t=n(6035);break;case"raw":t=n(187);break;case"text":t=n(6560);break;case"urlencoded":t=n(4861)}return a[e]=t}(e)}}t=e.exports=r.function((function(e){var n=Object.create(e||null,{type:{configurable:!0,enumerable:!0,value:void 0,writable:!0}}),r=t.urlencoded(n),a=t.json(n);return function(e,t,n){a(e,t,(function(a){if(a)return n(a);r(e,t,n)}))}}),"bodyParser: use individual json/urlencoded middlewares"),Object.defineProperty(t,"json",{configurable:!0,enumerable:!0,get:o("json")}),Object.defineProperty(t,"raw",{configurable:!0,enumerable:!0,get:o("raw")}),Object.defineProperty(t,"text",{configurable:!0,enumerable:!0,get:o("text")}),Object.defineProperty(t,"urlencoded",{configurable:!0,enumerable:!0,get:o("urlencoded")})},3211:(e,t,n)=>{"use strict";var r=n(9009),a=n(6149),o=n(1045),i=n(4914),s=n(338),c=n(8170),u=n(9796);e.exports=function(e,t,n,p,l,d){var f,m,v=d;e._body=!0;var h=null!==v.encoding?v.encoding:null,b=v.verify;try{m=function(e,t,n){var a,o=(e.headers["content-encoding"]||"identity").toLowerCase(),i=e.headers["content-length"];if(t('content-encoding "%s"',o),!1===n&&"identity"!==o)throw r(415,"content encoding unsupported",{encoding:o,type:"encoding.unsupported"});switch(o){case"deflate":a=u.createInflate(),t("inflate body"),e.pipe(a);break;case"gzip":a=u.createGunzip(),t("gunzip body"),e.pipe(a);break;case"identity":(a=e).length=i;break;default:throw r(415,'unsupported content encoding "'+o+'"',{encoding:o,type:"encoding.unsupported"})}return a}(e,l,v.inflate),f=m.length,m.length=void 0}catch(e){return n(e)}if(v.length=f,v.encoding=b?null:h,null===v.encoding&&null!==h&&!i.encodingExists(h))return n(r(415,'unsupported charset "'+h.toUpperCase()+'"',{charset:h.toLowerCase(),type:"charset.unsupported"}));l("read body"),o(m,v,(function(o,u){var d;if(o)return d="encoding.unsupported"===o.type?r(415,'unsupported charset "'+h.toUpperCase()+'"',{charset:h.toLowerCase(),type:"charset.unsupported"}):r(400,o),m!==e&&(c(e),a(m,!0)),void function(e,t){s.isFinished(e)?t():(s(e,t),e.resume())}(e,(function(){n(r(400,d))}));if(b)try{l("verify body"),b(e,t,u,h)}catch(e){return void n(r(403,e,{body:u,type:e.type||"entity.verify.failed"}))}var f=u;try{l("parse body"),f="string"!=typeof u&&null!==h?i.decode(u,h):u,e.body=p(f)}catch(e){return void n(r(400,e,{body:f,type:e.type||"entity.parse.failed"}))}n()}))}},6035:(e,t,n)=>{"use strict";var r=n(9830),a=n(7811),o=n(9009),i=n(5158)("body-parser:json"),s=n(3211),c=n(273);e.exports=function(e){var t=e||{},n="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,f=!1!==t.inflate,m=t.reviver,v=!1!==t.strict,h=t.type||"application/json",b=t.verify||!1;if(!1!==b&&"function"!=typeof b)throw new TypeError("option verify must be function");var g="function"!=typeof h?function(e){return function(t){return Boolean(c(t,e))}}(h):h;function y(e){if(0===e.length)return{};if(v){var t=(n=e,(r=u.exec(n))?r[1]:void 0);if("{"!==t&&"["!==t)throw i("strict violation"),function(e,t){var n=e.indexOf(t),r="";if(-1!==n){r=e.substring(0,n)+p;for(var a=n+1;a{"use strict";var r=n(9830),a=n(5158)("body-parser:raw"),o=n(3211),i=n(273);e.exports=function(e){var t=e||{},n=!1!==t.inflate,s="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,c=t.type||"application/octet-stream",u=t.verify||!1;if(!1!==u&&"function"!=typeof u)throw new TypeError("option verify must be function");var p="function"!=typeof c?function(e){return function(t){return Boolean(i(t,e))}}(c):c;function l(e){return e}return function(e,t,r){return e._body?(a("body already parsed"),void r()):(e.body=e.body||{},i.hasBody(e)?(a("content-type %j",e.headers["content-type"]),p(e)?void o(e,t,r,l,a,{encoding:null,inflate:n,limit:s,verify:u}):(a("skip parsing"),void r())):(a("skip empty body"),void r()))}}},6560:(e,t,n)=>{"use strict";var r=n(9830),a=n(7811),o=n(5158)("body-parser:text"),i=n(3211),s=n(273);e.exports=function(e){var t=e||{},n=t.defaultCharset||"utf-8",c=!1!==t.inflate,u="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,p=t.type||"text/plain",l=t.verify||!1;if(!1!==l&&"function"!=typeof l)throw new TypeError("option verify must be function");var d="function"!=typeof p?function(e){return function(t){return Boolean(s(t,e))}}(p):p;function f(e){return e}return function(e,t,r){if(e._body)return o("body already parsed"),void r();if(e.body=e.body||{},!s.hasBody(e))return o("skip empty body"),void r();if(o("content-type %j",e.headers["content-type"]),!d(e))return o("skip parsing"),void r();var p=function(e){try{return(a.parse(e).parameters.charset||"").toLowerCase()}catch(e){return}}(e)||n;i(e,t,r,f,o,{encoding:p,inflate:c,limit:u,verify:l})}}},4861:(e,t,n)=>{"use strict";var r=n(9830),a=n(7811),o=n(9009),i=n(5158)("body-parser:urlencoded"),s=n(412)("body-parser"),c=n(3211),u=n(273);e.exports=function(e){var t=e||{};void 0===t.extended&&s("undefined extended: provide extended option");var n=!1!==t.extended,p=!1!==t.inflate,f="number"!=typeof t.limit?r.parse(t.limit||"100kb"):t.limit,m=t.type||"application/x-www-form-urlencoded",v=t.verify||!1;if(!1!==v&&"function"!=typeof v)throw new TypeError("option verify must be function");var h=n?function(e){var t=void 0!==e.parameterLimit?e.parameterLimit:1e3,n=d("qs");if(isNaN(t)||t<1)throw new TypeError("option parameterLimit must be a positive number");return isFinite(t)&&(t|=0),function(e){var r=l(e,t);if(void 0===r)throw i("too many parameters"),o(413,"too many parameters",{type:"parameters.too.many"});var a=Math.max(100,r);return i("parse extended urlencoding"),n(e,{allowPrototypes:!0,arrayLimit:a,depth:1/0,parameterLimit:t})}}(t):function(e){var t=void 0!==e.parameterLimit?e.parameterLimit:1e3,n=d("querystring");if(isNaN(t)||t<1)throw new TypeError("option parameterLimit must be a positive number");return isFinite(t)&&(t|=0),function(e){if(void 0===l(e,t))throw i("too many parameters"),o(413,"too many parameters",{type:"parameters.too.many"});return i("parse urlencoding"),n(e,void 0,void 0,{maxKeys:t})}}(t),b="function"!=typeof m?function(e){return function(t){return Boolean(u(t,e))}}(m):m;function g(e){return e.length?h(e):{}}return function(e,t,n){if(e._body)return i("body already parsed"),void n();if(e.body=e.body||{},!u.hasBody(e))return i("skip empty body"),void n();if(i("content-type %j",e.headers["content-type"]),!b(e))return i("skip parsing"),void n();var r=function(e){try{return(a.parse(e).parameters.charset||"").toLowerCase()}catch(e){return}}(e)||"utf-8";if("utf-8"!==r)return i("invalid charset"),void n(o(415,'unsupported charset "'+r.toUpperCase()+'"',{charset:r,type:"charset.unsupported"}));c(e,t,n,g,i,{debug:i,encoding:r,inflate:p,limit:f,verify:v})}};var p=Object.create(null);function l(e,t){for(var n=0,r=0;-1!==(r=e.indexOf("&",r));)if(r++,++n===t)return;return n}function d(e){var t=p[e];if(void 0!==t)return t.parse;switch(e){case"qs":t=n(129);break;case"querystring":t=n(3477)}return p[e]=t,t.parse}},6744:(e,t,n)=>{"use strict";const r=n(3349),a=n(7529),o=n(8050),i=n(4339),s=(e,t={})=>{let n=[];if(Array.isArray(e))for(const r of e){const e=s.create(r,t);Array.isArray(e)?n.push(...e):n.push(e)}else n=[].concat(s.create(e,t));return t&&!0===t.expand&&!0===t.nodupes&&(n=[...new Set(n)]),n};s.parse=(e,t={})=>i(e,t),s.stringify=(e,t={})=>r("string"==typeof e?s.parse(e,t):e,t),s.compile=(e,t={})=>("string"==typeof e&&(e=s.parse(e,t)),a(e,t)),s.expand=(e,t={})=>{"string"==typeof e&&(e=s.parse(e,t));let n=o(e,t);return!0===t.noempty&&(n=n.filter(Boolean)),!0===t.nodupes&&(n=[...new Set(n)]),n},s.create=(e,t={})=>""===e||e.length<3?[e]:!0!==t.expand?s.compile(e,t):s.expand(e,t),e.exports=s},7529:(e,t,n)=>{"use strict";const r=n(2664),a=n(3083);e.exports=(e,t={})=>{const n=(e,o={})=>{const i=a.isInvalidBrace(o),s=!0===e.invalid&&!0===t.escapeInvalid,c=!0===i||!0===s,u=!0===t.escapeInvalid?"\\":"";let p="";if(!0===e.isOpen)return u+e.value;if(!0===e.isClose)return console.log("node.isClose",u,e.value),u+e.value;if("open"===e.type)return c?u+e.value:"(";if("close"===e.type)return c?u+e.value:")";if("comma"===e.type)return"comma"===e.prev.type?"":c?e.value:"|";if(e.value)return e.value;if(e.nodes&&e.ranges>0){const n=a.reduce(e.nodes),o=r(...n,{...t,wrap:!1,toRegex:!0,strictZeros:!0});if(0!==o.length)return n.length>1&&o.length>1?`(${o})`:o}if(e.nodes)for(const t of e.nodes)p+=n(t,e);return p};return n(e)}},6611:e=>{"use strict";e.exports={MAX_LENGTH:1e4,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:"\n",CHAR_NO_BREAK_SPACE:" ",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:"\t",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\ufeff"}},8050:(e,t,n)=>{"use strict";const r=n(2664),a=n(3349),o=n(3083),i=(e="",t="",n=!1)=>{const r=[];if(e=[].concat(e),!(t=[].concat(t)).length)return e;if(!e.length)return n?o.flatten(t).map((e=>`{${e}}`)):t;for(const a of e)if(Array.isArray(a))for(const e of a)r.push(i(e,t,n));else for(let e of t)!0===n&&"string"==typeof e&&(e=`{${e}}`),r.push(Array.isArray(e)?i(a,e,n):a+e);return o.flatten(r)};e.exports=(e,t={})=>{const n=void 0===t.rangeLimit?1e3:t.rangeLimit,s=(e,c={})=>{e.queue=[];let u=c,p=c.queue;for(;"brace"!==u.type&&"root"!==u.type&&u.parent;)u=u.parent,p=u.queue;if(e.invalid||e.dollar)return void p.push(i(p.pop(),a(e,t)));if("brace"===e.type&&!0!==e.invalid&&2===e.nodes.length)return void p.push(i(p.pop(),["{}"]));if(e.nodes&&e.ranges>0){const s=o.reduce(e.nodes);if(o.exceedsLimit(...s,t.step,n))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let c=r(...s,t);return 0===c.length&&(c=a(e,t)),p.push(i(p.pop(),c)),void(e.nodes=[])}const l=o.encloseBrace(e);let d=e.queue,f=e;for(;"brace"!==f.type&&"root"!==f.type&&f.parent;)f=f.parent,d=f.queue;for(let t=0;t{"use strict";const r=n(3349),{MAX_LENGTH:a,CHAR_BACKSLASH:o,CHAR_BACKTICK:i,CHAR_COMMA:s,CHAR_DOT:c,CHAR_LEFT_PARENTHESES:u,CHAR_RIGHT_PARENTHESES:p,CHAR_LEFT_CURLY_BRACE:l,CHAR_RIGHT_CURLY_BRACE:d,CHAR_LEFT_SQUARE_BRACKET:f,CHAR_RIGHT_SQUARE_BRACKET:m,CHAR_DOUBLE_QUOTE:v,CHAR_SINGLE_QUOTE:h,CHAR_NO_BREAK_SPACE:b,CHAR_ZERO_WIDTH_NOBREAK_SPACE:g}=n(6611);e.exports=(e,t={})=>{if("string"!=typeof e)throw new TypeError("Expected a string");const n=t||{},y="number"==typeof n.maxLength?Math.min(a,n.maxLength):a;if(e.length>y)throw new SyntaxError(`Input length (${e.length}), exceeds max characters (${y})`);const x={type:"root",input:e,nodes:[]},w=[x];let _=x,S=x,E=0;const A=e.length;let k,O=0,j=0;const C=()=>e[O++],R=e=>{if("text"===e.type&&"dot"===S.type&&(S.type="text"),!S||"text"!==S.type||"text"!==e.type)return _.nodes.push(e),e.parent=_,e.prev=S,S=e,e;S.value+=e.value};for(R({type:"bos"});O0){if(_.ranges>0){_.ranges=0;const e=_.nodes.shift();_.nodes=[e,{type:"text",value:r(_)}]}R({type:"comma",value:k}),_.commas++}else if(k===c&&j>0&&0===_.commas){const e=_.nodes;if(0===j||0===e.length){R({type:"text",value:k});continue}if("dot"===S.type){if(_.range=[],S.value+=k,S.type="range",3!==_.nodes.length&&5!==_.nodes.length){_.invalid=!0,_.ranges=0,S.type="text";continue}_.ranges++,_.args=[];continue}if("range"===S.type){e.pop();const t=e[e.length-1];t.value+=S.value+k,S=t,_.ranges--;continue}R({type:"dot",value:k})}else R({type:"text",value:k});else{if("brace"!==_.type){R({type:"text",value:k});continue}const e="close";_=w.pop(),_.close=!0,R({type:e,value:k}),j--,_=w[w.length-1]}else{j++;const e=S.value&&"$"===S.value.slice(-1)||!0===_.dollar;_=R({type:"brace",open:!0,close:!1,dollar:e,depth:j,commas:0,ranges:0,nodes:[]}),w.push(_),R({type:"open",value:k})}else{const e=k;let n;for(!0!==t.keepQuotes&&(k="");O{e.nodes||("open"===e.type&&(e.isOpen=!0),"close"===e.type&&(e.isClose=!0),e.nodes||(e.type="text"),e.invalid=!0)}));const e=w[w.length-1],t=e.nodes.indexOf(_);e.nodes.splice(t,1,..._.nodes)}}while(w.length>0);return R({type:"eos"}),x}},3349:(e,t,n)=>{"use strict";const r=n(3083);e.exports=(e,t={})=>{const n=(e,a={})=>{const o=t.escapeInvalid&&r.isInvalidBrace(a),i=!0===e.invalid&&!0===t.escapeInvalid;let s="";if(e.value)return(o||i)&&r.isOpenOrClose(e)?"\\"+e.value:e.value;if(e.value)return e.value;if(e.nodes)for(const t of e.nodes)s+=n(t);return s};return n(e)}},3083:(e,t)=>{"use strict";t.isInteger=e=>"number"==typeof e?Number.isInteger(e):"string"==typeof e&&""!==e.trim()&&Number.isInteger(Number(e)),t.find=(e,t)=>e.nodes.find((e=>e.type===t)),t.exceedsLimit=(e,n,r=1,a)=>!1!==a&&!(!t.isInteger(e)||!t.isInteger(n))&&(Number(n)-Number(e))/Number(r)>=a,t.escapeNode=(e,t=0,n)=>{const r=e.nodes[t];r&&(n&&r.type===n||"open"===r.type||"close"===r.type)&&!0!==r.escaped&&(r.value="\\"+r.value,r.escaped=!0)},t.encloseBrace=e=>"brace"===e.type&&e.commas>>0+e.ranges>>0==0&&(e.invalid=!0,!0),t.isInvalidBrace=e=>!("brace"!==e.type||!0!==e.invalid&&!e.dollar&&(e.commas>>0+e.ranges>>0!=0&&!0===e.open&&!0===e.close||(e.invalid=!0,0))),t.isOpenOrClose=e=>"open"===e.type||"close"===e.type||!0===e.open||!0===e.close,t.reduce=e=>e.reduce(((e,t)=>("text"===t.type&&e.push(t.value),"range"===t.type&&(t.type="text"),e)),[]),t.flatten=(...e)=>{const t=[],n=e=>{for(let r=0;r{"use strict";const{parseContentType:r}=n(1510),a=[n(7626),n(4403)].filter((function(e){return"function"==typeof e.detect}));e.exports=e=>{if("object"==typeof e&&null!==e||(e={}),"object"!=typeof e.headers||null===e.headers||"string"!=typeof e.headers["content-type"])throw new Error("Missing Content-Type");return function(e){const t=e.headers,n=r(t["content-type"]);if(!n)throw new Error("Malformed content type");for(const r of a){if(!r.detect(n))continue;const a={limits:e.limits,headers:t,conType:n,highWaterMark:void 0,fileHwm:void 0,defCharset:void 0,defParamCharset:void 0,preservePath:!1};return e.highWaterMark&&(a.highWaterMark=e.highWaterMark),e.fileHwm&&(a.fileHwm=e.fileHwm),a.defCharset=e.defCharset,a.defParamCharset=e.defParamCharset,a.preservePath=e.preservePath,new r(a)}throw new Error(`Unsupported content type: ${t["content-type"]}`)}(e)}},7626:(e,t,n)=>{"use strict";const{Readable:r,Writable:a}=n(2781),o=n(1301),{basename:i,convertToUTF8:s,getDecoder:c,parseContentType:u,parseDisposition:p}=n(1510),l=Buffer.from("\r\n"),d=Buffer.from("\r"),f=Buffer.from("-");function m(){}const v=16384;class h{constructor(e){this.header=Object.create(null),this.pairCount=0,this.byteCount=0,this.state=0,this.name="",this.value="",this.crlf=0,this.cb=e}reset(){this.header=Object.create(null),this.pairCount=0,this.byteCount=0,this.state=0,this.name="",this.value="",this.crlf=0}push(e,t,n){let r=t;for(;t{if(this._read(),0==--t._fileEndsLeft&&t._finalcb){const e=t._finalcb;t._finalcb=null,process.nextTick(e)}}))}_read(e){const t=this._readcb;t&&(this._readcb=null,t())}}const g={push:(e,t)=>{},destroy:()=>{}};function y(e,t){return e}function x(e,t,n){if(n)return t(n);t(n=w(e))}function w(e){if(e._hparser)return new Error("Malformed part header");const t=e._fileStream;return t&&(e._fileStream=null,t.destroy(new Error("Unexpected end of file"))),e._complete?void 0:new Error("Unexpected end of form")}const _=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],S=[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1];e.exports=class extends a{constructor(e){if(super({autoDestroy:!0,emitClose:!0,highWaterMark:"number"==typeof e.highWaterMark?e.highWaterMark:void 0}),!e.conType.params||"string"!=typeof e.conType.params.boundary)throw new Error("Multipart: Boundary not found");const t=e.conType.params.boundary,n="string"==typeof e.defParamCharset&&e.defParamCharset?c(e.defParamCharset):y,r=e.defCharset||"utf8",a=e.preservePath,v={autoDestroy:!0,emitClose:!0,highWaterMark:"number"==typeof e.fileHwm?e.fileHwm:void 0},x=e.limits,w=x&&"number"==typeof x.fieldSize?x.fieldSize:1048576,_=x&&"number"==typeof x.fileSize?x.fileSize:1/0,S=x&&"number"==typeof x.files?x.files:1/0,E=x&&"number"==typeof x.fields?x.fields:1/0,A=x&&"number"==typeof x.parts?x.parts:1/0;let k=-1,O=0,j=0,C=!1;this._fileEndsLeft=0,this._fileStream=void 0,this._complete=!1;let R,I,T,P,N,U=0,D=0,L=!1,F=!1,M=!1;this._hparser=null;const H=new h((e=>{let t;if(this._hparser=null,C=!1,P="text/plain",I=r,T="7bit",N=void 0,L=!1,!e["content-disposition"])return void(C=!0);const o=p(e["content-disposition"][0],n);if(o&&"form-data"===o.type){if(o.params&&(o.params.name&&(N=o.params.name),o.params["filename*"]?t=o.params["filename*"]:o.params.filename&&(t=o.params.filename),void 0===t||a||(t=i(t))),e["content-type"]){const t=u(e["content-type"][0]);t&&(P=`${t.type}/${t.subtype}`,t.params&&"string"==typeof t.params.charset&&(I=t.params.charset.toLowerCase()))}if(e["content-transfer-encoding"]&&(T=e["content-transfer-encoding"][0].toLowerCase()),"application/octet-stream"===P||void 0!==t){if(j===S)return F||(F=!0,this.emit("filesLimit")),void(C=!0);if(++j,0===this.listenerCount("file"))return void(C=!0);U=0,this._fileStream=new b(v,this),++this._fileEndsLeft,this.emit("file",N,this._fileStream,{filename:t,encoding:T,mimeType:P})}else{if(O===E)return M||(M=!0,this.emit("fieldsLimit")),void(C=!0);if(++O,0===this.listenerCount("field"))return void(C=!0);R=[],D=0}}else C=!0}));let q=0;const B=(e,t,n,r,a)=>{e:for(;t;){if(null!==this._hparser){const e=this._hparser.push(t,n,r);if(-1===e){this._hparser=null,H.reset(),this.emit("error",new Error("Malformed part header"));break}n=e}if(n===r)break;if(0!==q){if(1===q){switch(t[n]){case 45:q=2,++n;break;case 13:q=3,++n;break;default:q=0}if(n===r)return}if(2===q){if(q=0,45===t[n])return this._complete=!0,void(this._bparser=g);const e=this._writecb;this._writecb=m,B(!1,f,0,1,!1),this._writecb=e}else if(3===q){if(q=0,10===t[n]){if(++n,k>=A)break;if(this._hparser=H,n===r)break;continue e}{const e=this._writecb;this._writecb=m,B(!1,d,0,1,!1),this._writecb=e}}}if(!C)if(this._fileStream){let e;const o=Math.min(r-n,_-U);a?e=t.slice(n,n+o):(e=Buffer.allocUnsafe(o),t.copy(e,0,n,n+o)),U+=e.length,U===_?(e.length>0&&this._fileStream.push(e),this._fileStream.emit("limit"),this._fileStream.truncated=!0,C=!0):this._fileStream.push(e)||(this._writecb&&(this._fileStream._readcb=this._writecb),this._writecb=null)}else if(void 0!==R){let e;const o=Math.min(r-n,w-D);a?e=t.slice(n,n+o):(e=Buffer.allocUnsafe(o),t.copy(e,0,n,n+o)),D+=o,R.push(e),D===w&&(C=!0,L=!0)}break}if(e){if(q=1,this._fileStream)this._fileStream.push(null),this._fileStream=null;else if(void 0!==R){let e;switch(R.length){case 0:e="";break;case 1:e=s(R[0],I,0);break;default:e=s(Buffer.concat(R,D),I,0)}R=void 0,D=0,this.emit("field",N,e,{nameTruncated:!1,valueTruncated:L,encoding:T,mimeType:P})}++k===A&&this.emit("partsLimit")}};this._bparser=new o(`\r\n--${t}`,B),this._writecb=null,this._finalcb=null,this.write(l)}static detect(e){return"multipart"===e.type&&"form-data"===e.subtype}_write(e,t,n){this._writecb=n,this._bparser.push(e,0),this._writecb&&function(e,t){const n=e._writecb;e._writecb=null,n&&n()}(this)}_destroy(e,t){this._hparser=null,this._bparser=g,e||(e=w(this));const n=this._fileStream;n&&(this._fileStream=null,n.destroy(e)),t(e)}_final(e){if(this._bparser.destroy(),!this._complete)return e(new Error("Unexpected end of form"));this._fileEndsLeft?this._finalcb=x.bind(null,this,e):x(this,e)}}},4403:(e,t,n)=>{"use strict";const{Writable:r}=n(2781),{getDecoder:a}=n(1510);function o(e,t,n,r){if(n>=r)return r;if(-1===e._byte){const a=c[t[n++]];if(-1===a)return-1;if(a>=8&&(e._encode=2),ne.fieldNameSizeLimit){for(e._keyTrunc||e._lastPose.fieldSizeLimit){for(e._valTrunc||e._lastPos=this.fieldsLimit)return n();let r=0;const a=e.length;if(this._lastPos=0,-2!==this._byte){if(r=o(this,e,r,a),-1===r)return n(new Error("Malformed urlencoded form"));if(r>=a)return n();this._inKey?++this._bytesKey:++this._bytesVal}e:for(;r0&&this.emit("field",this._key,"",{nameTruncated:this._keyTrunc,valueTruncated:!1,encoding:this.charset,mimeType:"text/plain"}),this._key="",this._val="",this._keyTrunc=!1,this._valTrunc=!1,this._bytesKey=0,this._bytesVal=0,++this._fields>=this.fieldsLimit)return this.emit("fieldsLimit"),n();continue;case 43:this._lastPos=a)return n();++this._bytesKey,r=i(this,e,r,a);continue}++r,++this._bytesKey,r=i(this,e,r,a)}this._lastPos0||this._bytesVal>0)&&this.emit("field",this._key,this._val,{nameTruncated:this._keyTrunc,valueTruncated:this._valTrunc,encoding:this.charset,mimeType:"text/plain"}),this._key="",this._val="",this._keyTrunc=!1,this._valTrunc=!1,this._bytesKey=0,this._bytesVal=0,++this._fields>=this.fieldsLimit)return this.emit("fieldsLimit"),n();continue e;case 43:this._lastPos=a)return n();++this._bytesVal,r=s(this,e,r,a);continue}++r,++this._bytesVal,r=s(this,e,r,a)}this._lastPos0||this._bytesVal>0)&&(this._inKey?this._key=this._decoder(this._key,this._encode):this._val=this._decoder(this._val,this._encode),this.emit("field",this._key,this._val,{nameTruncated:this._keyTrunc,valueTruncated:this._valTrunc,encoding:this.charset,mimeType:"text/plain"})),e()}}},1510:function(e){"use strict";function t(e,t,n){for(;t=128?r=2:0===r&&(r=1);continue}return}break}}if(m+=e.slice(d,t),m=o(m,f,r),void 0===m)return}else{if(++t===e.length)return;if(34===e.charCodeAt(t)){d=++t;let n=!1;for(;t{if(0===e.length)return"";if("string"==typeof e){if(t<2)return e;e=Buffer.from(e,"latin1")}return e.utf8Slice(0,e.length)},latin1:(e,t)=>0===e.length?"":"string"==typeof e?e:e.latin1Slice(0,e.length),utf16le:(e,t)=>0===e.length?"":("string"==typeof e&&(e=Buffer.from(e,"latin1")),e.ucs2Slice(0,e.length)),base64:(e,t)=>0===e.length?"":("string"==typeof e&&(e=Buffer.from(e,"latin1")),e.base64Slice(0,e.length)),other:(e,t)=>{if(0===e.length)return"";"string"==typeof e&&(e=Buffer.from(e,"latin1"));try{return new TextDecoder(this).decode(e)}catch{}}};function o(e,t,n){const a=r(t);if(a)return a(e,n)}const i=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],s=[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],c=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,0,0,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],u=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,1,0,0,0,0,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],p=[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1];e.exports={basename:function(e){if("string"!=typeof e)return"";for(let t=e.length-1;t>=0;--t)switch(e.charCodeAt(t)){case 47:case 92:return".."===(e=e.slice(t+1))||"."===e?"":e}return".."===e||"."===e?"":e},convertToUTF8:o,getDecoder:r,parseContentType:function(e){if(0===e.length)return;const n=Object.create(null);let r=0;for(;r{"use strict";e.exports=function(e,t){return"string"==typeof e?i(e):"number"==typeof e?o(e,t):null},e.exports.format=o,e.exports.parse=i;var t=/\B(?=(\d{3})+(?!\d))/g,n=/(?:\.0*|(\.[^0]+)0+)$/,r={b:1,kb:1024,mb:1<<20,gb:1<<30,tb:Math.pow(1024,4),pb:Math.pow(1024,5)},a=/^((-|\+)?(\d+(?:\.\d+)?)) *(kb|mb|gb|tb|pb)$/i;function o(e,a){if(!Number.isFinite(e))return null;var o=Math.abs(e),i=a&&a.thousandsSeparator||"",s=a&&a.unitSeparator||"",c=a&&void 0!==a.decimalPlaces?a.decimalPlaces:2,u=Boolean(a&&a.fixedDecimals),p=a&&a.unit||"";p&&r[p.toLowerCase()]||(p=o>=r.pb?"PB":o>=r.tb?"TB":o>=r.gb?"GB":o>=r.mb?"MB":o>=r.kb?"KB":"B");var l=(e/r[p.toLowerCase()]).toFixed(c);return u||(l=l.replace(n,"$1")),i&&(l=l.split(".").map((function(e,n){return 0===n?e.replace(t,i):e})).join(".")),l+s+p}function i(e){if("number"==typeof e&&!isNaN(e))return e;if("string"!=typeof e)return null;var t,n=a.exec(e),o="b";return n?(t=parseFloat(n[1]),o=n[4].toLowerCase()):(t=parseInt(e,10),o="b"),isNaN(t)?null:Math.floor(r[o]*t)}},1924:(e,t,n)=>{"use strict";var r=n(210),a=n(5559),o=a(r("String.prototype.indexOf"));e.exports=function(e,t){var n=r(e,!!t);return"function"==typeof n&&o(e,".prototype.")>-1?a(n):n}},5559:(e,t,n)=>{"use strict";var r=n(8612),a=n(210),o=a("%Function.prototype.apply%"),i=a("%Function.prototype.call%"),s=a("%Reflect.apply%",!0)||r.call(i,o),c=a("%Object.getOwnPropertyDescriptor%",!0),u=a("%Object.defineProperty%",!0),p=a("%Math.max%");if(u)try{u({},"a",{value:1})}catch(e){u=null}e.exports=function(e){var t=s(r,i,arguments);if(c&&u){var n=c(t,"length");n.configurable&&u(t,"length",{value:1+p(0,e.length-(arguments.length-1))})}return t};var l=function(){return s(r,o,arguments)};u?u(e.exports,"apply",{value:l}):e.exports.apply=l},7389:(e,t,n)=>{"use strict";e.exports=function(e,t){var n=t||{},a=n.type||"attachment",o=function(e,t){if(void 0!==e){var n={};if("string"!=typeof e)throw new TypeError("filename must be a string");if(void 0===t&&(t=!0),"string"!=typeof t&&"boolean"!=typeof t)throw new TypeError("fallback must be a string or boolean");if("string"==typeof t&&c.test(t))throw new TypeError("fallback must be ISO-8859-1 string");var a=r(e),o=d.test(a),s="string"!=typeof t?t&&b(a):r(t),u="string"==typeof s&&s!==a;return(u||!o||i.test(a))&&(n["filename*"]=a),(o||u)&&(n.filename=u?s:a),n}}(e,n.fallback);return function(e){var t=e.parameters,n=e.type;if(!n||"string"!=typeof n||!f.test(n))throw new TypeError("invalid type");var r=String(n).toLowerCase();if(t&&"object"==typeof t)for(var a,o=Object.keys(t).sort(),i=0;i?@[\\\]{}\x7f]/g,i=/%[0-9A-Fa-f]{2}/,s=/%([0-9A-Fa-f]{2})/g,c=/[^\x20-\x7e\xa0-\xff]/g,u=/\\([\u0000-\u007f])/g,p=/([\\"])/g,l=/;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g,d=/^[\x20-\x7e\x80-\xff]+$/,f=/^[!#$%&'*+.0-9A-Z^_`a-z|~-]+$/,m=/^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/,v=/^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/;function h(e){var t=m.exec(e);if(!t)throw new TypeError("invalid extended field value");var n,r=t[1].toLowerCase(),o=t[2].replace(s,g);switch(r){case"iso-8859-1":n=b(o);break;case"utf-8":n=a.from(o,"binary").toString("utf8");break;default:throw new TypeError("unsupported charset in extended field")}return n}function b(e){return String(e).replace(c,"?")}function g(e,t){return String.fromCharCode(parseInt(t,16))}function y(e){return"%"+String(e).charCodeAt(0).toString(16).toUpperCase()}function x(e){return'"'+String(e).replace(p,"\\$1")+'"'}function w(e){var t=String(e);return"UTF-8''"+encodeURIComponent(t).replace(o,y)}function _(e,t){this.type=e,this.parameters=t}},7296:(e,t,n)=>{var r=n(4300),a=r.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function i(e,t,n){return a(e,t,n)}a.from&&a.alloc&&a.allocUnsafe&&a.allocUnsafeSlow?e.exports=r:(o(r,t),t.Buffer=i),i.prototype=Object.create(a.prototype),o(a,i),i.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return a(e,t,n)},i.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=a(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},i.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return a(e)},i.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},7811:(e,t)=>{"use strict";var n=/; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g,r=/^[\u000b\u0020-\u007e\u0080-\u00ff]+$/,a=/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/,o=/\\([\u000b\u0020-\u00ff])/g,i=/([\\"])/g,s=/^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;function c(e){var t=String(e);if(a.test(t))return t;if(t.length>0&&!r.test(t))throw new TypeError("invalid parameter value");return'"'+t.replace(i,"\\$1")+'"'}function u(e){this.parameters=Object.create(null),this.type=e}t.format=function(e){if(!e||"object"!=typeof e)throw new TypeError("argument obj is required");var t=e.parameters,n=e.type;if(!n||!s.test(n))throw new TypeError("invalid type");var r=n;if(t&&"object"==typeof t)for(var o,i=Object.keys(t).sort(),u=0;u{var r=n(6113);function a(e){return r.createHash("sha1").update(e).digest("hex")}t.sign=function(e,t){if("string"!=typeof e)throw new TypeError("Cookie value must be provided as a string.");if("string"!=typeof t)throw new TypeError("Secret string must be provided.");return e+"."+r.createHmac("sha256",t).update(e).digest("base64").replace(/\=+$/,"")},t.unsign=function(e,n){if("string"!=typeof e)throw new TypeError("Signed cookie string must be provided.");if("string"!=typeof n)throw new TypeError("Secret string must be provided.");var r=e.slice(0,e.lastIndexOf("."));return a(t.sign(r,n))==a(e)&&r}},6489:(e,t)=>{"use strict";t.parse=function(e,t){if("string"!=typeof e)throw new TypeError("argument str must be a string");for(var n={},r=(t||{}).decode||a,o=0;o{var r=n(614),a=n(6330),o=TypeError;e.exports=function(e){if(r(e))return e;throw o(a(e)+" is not a function")}},9483:(e,t,n)=>{var r=n(4411),a=n(6330),o=TypeError;e.exports=function(e){if(r(e))return e;throw o(a(e)+" is not a constructor")}},6077:(e,t,n)=>{var r=n(614),a=String,o=TypeError;e.exports=function(e){if("object"==typeof e||r(e))return e;throw o("Can't set "+a(e)+" as a prototype")}},1223:(e,t,n)=>{var r=n(5112),a=n(30),o=n(3070).f,i=r("unscopables"),s=Array.prototype;null==s[i]&&o(s,i,{configurable:!0,value:a(null)}),e.exports=function(e){s[i][e]=!0}},1530:(e,t,n)=>{"use strict";var r=n(8710).charAt;e.exports=function(e,t,n){return t+(n?r(e,t).length:1)}},5787:(e,t,n)=>{var r=n(7976),a=TypeError;e.exports=function(e,t){if(r(t,e))return e;throw a("Incorrect invocation")}},9670:(e,t,n)=>{var r=n(111),a=String,o=TypeError;e.exports=function(e){if(r(e))return e;throw o(a(e)+" is not an object")}},7556:(e,t,n)=>{var r=n(7293);e.exports=r((function(){if("function"==typeof ArrayBuffer){var e=new ArrayBuffer(8);Object.isExtensible(e)&&Object.defineProperty(e,"a",{value:8})}}))},8533:(e,t,n)=>{"use strict";var r=n(2092).forEach,a=n(9341)("forEach");e.exports=a?[].forEach:function(e){return r(this,e,arguments.length>1?arguments[1]:void 0)}},8457:(e,t,n)=>{"use strict";var r=n(9974),a=n(6916),o=n(7908),i=n(3411),s=n(7659),c=n(4411),u=n(6244),p=n(6135),l=n(4121),d=n(1246),f=Array;e.exports=function(e){var t=o(e),n=c(this),m=arguments.length,v=m>1?arguments[1]:void 0,h=void 0!==v;h&&(v=r(v,m>2?arguments[2]:void 0));var b,g,y,x,w,_,S=d(t),E=0;if(!S||this===f&&s(S))for(b=u(t),g=n?new this(b):f(b);b>E;E++)_=h?v(t[E],E):t[E],p(g,E,_);else for(w=(x=l(t,S)).next,g=n?new this:[];!(y=a(w,x)).done;E++)_=h?i(x,v,[y.value,E],!0):y.value,p(g,E,_);return g.length=E,g}},1318:(e,t,n)=>{var r=n(5656),a=n(1400),o=n(6244),i=function(e){return function(t,n,i){var s,c=r(t),u=o(c),p=a(i,u);if(e&&n!=n){for(;u>p;)if((s=c[p++])!=s)return!0}else for(;u>p;p++)if((e||p in c)&&c[p]===n)return e||p||0;return!e&&-1}};e.exports={includes:i(!0),indexOf:i(!1)}},2092:(e,t,n)=>{var r=n(9974),a=n(1702),o=n(8361),i=n(7908),s=n(6244),c=n(5417),u=a([].push),p=function(e){var t=1==e,n=2==e,a=3==e,p=4==e,l=6==e,d=7==e,f=5==e||l;return function(m,v,h,b){for(var g,y,x=i(m),w=o(x),_=r(v,h),S=s(w),E=0,A=b||c,k=t?A(m,S):n||d?A(m,0):void 0;S>E;E++)if((f||E in w)&&(y=_(g=w[E],E,x),e))if(t)k[E]=y;else if(y)switch(e){case 3:return!0;case 5:return g;case 6:return E;case 2:u(k,g)}else switch(e){case 4:return!1;case 7:u(k,g)}return l?-1:a||p?p:k}};e.exports={forEach:p(0),map:p(1),filter:p(2),some:p(3),every:p(4),find:p(5),findIndex:p(6),filterReject:p(7)}},1194:(e,t,n)=>{var r=n(7293),a=n(5112),o=n(7392),i=a("species");e.exports=function(e){return o>=51||!r((function(){var t=[];return(t.constructor={})[i]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},9341:(e,t,n)=>{"use strict";var r=n(7293);e.exports=function(e,t){var n=[][e];return!!n&&r((function(){n.call(null,t||function(){return 1},1)}))}},3671:(e,t,n)=>{var r=n(9662),a=n(7908),o=n(8361),i=n(6244),s=TypeError,c=function(e){return function(t,n,c,u){r(n);var p=a(t),l=o(p),d=i(p),f=e?d-1:0,m=e?-1:1;if(c<2)for(;;){if(f in l){u=l[f],f+=m;break}if(f+=m,e?f<0:d<=f)throw s("Reduce of empty array with no initial value")}for(;e?f>=0:d>f;f+=m)f in l&&(u=n(u,l[f],f,p));return u}};e.exports={left:c(!1),right:c(!0)}},3658:(e,t,n)=>{"use strict";var r=n(9781),a=n(3157),o=TypeError,i=Object.getOwnPropertyDescriptor,s=r&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(e){return e instanceof TypeError}}();e.exports=s?function(e,t){if(a(e)&&!i(e,"length").writable)throw o("Cannot set read only .length");return e.length=t}:function(e,t){return e.length=t}},1589:(e,t,n)=>{var r=n(1400),a=n(6244),o=n(6135),i=Array,s=Math.max;e.exports=function(e,t,n){for(var c=a(e),u=r(t,c),p=r(void 0===n?c:n,c),l=i(s(p-u,0)),d=0;u{var r=n(1702);e.exports=r([].slice)},4362:(e,t,n)=>{var r=n(1589),a=Math.floor,o=function(e,t){var n=e.length,c=a(n/2);return n<8?i(e,t):s(e,o(r(e,0,c),t),o(r(e,c),t),t)},i=function(e,t){for(var n,r,a=e.length,o=1;o0;)e[r]=e[--r];r!==o++&&(e[r]=n)}return e},s=function(e,t,n,r){for(var a=t.length,o=n.length,i=0,s=0;i{var r=n(3157),a=n(4411),o=n(111),i=n(5112)("species"),s=Array;e.exports=function(e){var t;return r(e)&&(t=e.constructor,(a(t)&&(t===s||r(t.prototype))||o(t)&&null===(t=t[i]))&&(t=void 0)),void 0===t?s:t}},5417:(e,t,n)=>{var r=n(7475);e.exports=function(e,t){return new(r(e))(0===t?0:t)}},3411:(e,t,n)=>{var r=n(9670),a=n(9212);e.exports=function(e,t,n,o){try{return o?t(r(n)[0],n[1]):t(n)}catch(t){a(e,"throw",t)}}},7072:(e,t,n)=>{var r=n(5112)("iterator"),a=!1;try{var o=0,i={next:function(){return{done:!!o++}},return:function(){a=!0}};i[r]=function(){return this},Array.from(i,(function(){throw 2}))}catch(e){}e.exports=function(e,t){if(!t&&!a)return!1;var n=!1;try{var o={};o[r]=function(){return{next:function(){return{done:n=!0}}}},e(o)}catch(e){}return n}},4326:(e,t,n)=>{var r=n(1702),a=r({}.toString),o=r("".slice);e.exports=function(e){return o(a(e),8,-1)}},648:(e,t,n)=>{var r=n(1694),a=n(614),o=n(4326),i=n(5112)("toStringTag"),s=Object,c="Arguments"==o(function(){return arguments}());e.exports=r?o:function(e){var t,n,r;return void 0===e?"Undefined":null===e?"Null":"string"==typeof(n=function(e,t){try{return e[t]}catch(e){}}(t=s(e),i))?n:c?o(t):"Object"==(r=o(t))&&a(t.callee)?"Arguments":r}},5631:(e,t,n)=>{"use strict";var r=n(30),a=n(7045),o=n(9190),i=n(9974),s=n(5787),c=n(8554),u=n(408),p=n(1656),l=n(6178),d=n(6340),f=n(9781),m=n(2423).fastKey,v=n(9909),h=v.set,b=v.getterFor;e.exports={getConstructor:function(e,t,n,p){var l=e((function(e,a){s(e,d),h(e,{type:t,index:r(null),first:void 0,last:void 0,size:0}),f||(e.size=0),c(a)||u(a,e[p],{that:e,AS_ENTRIES:n})})),d=l.prototype,v=b(t),g=function(e,t,n){var r,a,o=v(e),i=y(e,t);return i?i.value=n:(o.last=i={index:a=m(t,!0),key:t,value:n,previous:r=o.last,next:void 0,removed:!1},o.first||(o.first=i),r&&(r.next=i),f?o.size++:e.size++,"F"!==a&&(o.index[a]=i)),e},y=function(e,t){var n,r=v(e),a=m(t);if("F"!==a)return r.index[a];for(n=r.first;n;n=n.next)if(n.key==t)return n};return o(d,{clear:function(){for(var e=v(this),t=e.index,n=e.first;n;)n.removed=!0,n.previous&&(n.previous=n.previous.next=void 0),delete t[n.index],n=n.next;e.first=e.last=void 0,f?e.size=0:this.size=0},delete:function(e){var t=this,n=v(t),r=y(t,e);if(r){var a=r.next,o=r.previous;delete n.index[r.index],r.removed=!0,o&&(o.next=a),a&&(a.previous=o),n.first==r&&(n.first=a),n.last==r&&(n.last=o),f?n.size--:t.size--}return!!r},forEach:function(e){for(var t,n=v(this),r=i(e,arguments.length>1?arguments[1]:void 0);t=t?t.next:n.first;)for(r(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!y(this,e)}}),o(d,n?{get:function(e){var t=y(this,e);return t&&t.value},set:function(e,t){return g(this,0===e?0:e,t)}}:{add:function(e){return g(this,e=0===e?0:e,e)}}),f&&a(d,"size",{configurable:!0,get:function(){return v(this).size}}),l},setStrong:function(e,t,n){var r=t+" Iterator",a=b(t),o=b(r);p(e,t,(function(e,t){h(this,{type:r,target:e,state:a(e),kind:t,last:void 0})}),(function(){for(var e=o(this),t=e.kind,n=e.last;n&&n.removed;)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?l("keys"==t?n.key:"values"==t?n.value:[n.key,n.value],!1):(e.target=void 0,l(void 0,!0))}),n?"entries":"values",!n,!0),d(t)}}},7710:(e,t,n)=>{"use strict";var r=n(2109),a=n(7854),o=n(1702),i=n(4705),s=n(8052),c=n(2423),u=n(408),p=n(5787),l=n(614),d=n(8554),f=n(111),m=n(7293),v=n(7072),h=n(8003),b=n(9587);e.exports=function(e,t,n){var g=-1!==e.indexOf("Map"),y=-1!==e.indexOf("Weak"),x=g?"set":"add",w=a[e],_=w&&w.prototype,S=w,E={},A=function(e){var t=o(_[e]);s(_,e,"add"==e?function(e){return t(this,0===e?0:e),this}:"delete"==e?function(e){return!(y&&!f(e))&&t(this,0===e?0:e)}:"get"==e?function(e){return y&&!f(e)?void 0:t(this,0===e?0:e)}:"has"==e?function(e){return!(y&&!f(e))&&t(this,0===e?0:e)}:function(e,n){return t(this,0===e?0:e,n),this})};if(i(e,!l(w)||!(y||_.forEach&&!m((function(){(new w).entries().next()})))))S=n.getConstructor(t,e,g,x),c.enable();else if(i(e,!0)){var k=new S,O=k[x](y?{}:-0,1)!=k,j=m((function(){k.has(1)})),C=v((function(e){new w(e)})),R=!y&&m((function(){for(var e=new w,t=5;t--;)e[x](t,t);return!e.has(-0)}));C||((S=t((function(e,t){p(e,_);var n=b(new w,e,S);return d(t)||u(t,n[x],{that:n,AS_ENTRIES:g}),n}))).prototype=_,_.constructor=S),(j||R)&&(A("delete"),A("has"),g&&A("get")),(R||O)&&A(x),y&&_.clear&&delete _.clear}return E[e]=S,r({global:!0,constructor:!0,forced:S!=w},E),h(S,e),y||n.setStrong(S,e,g),S}},9920:(e,t,n)=>{var r=n(2597),a=n(3887),o=n(1236),i=n(3070);e.exports=function(e,t,n){for(var s=a(t),c=i.f,u=o.f,p=0;p{var r=n(5112)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[r]=!1,"/./"[e](t)}catch(e){}}return!1}},8544:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},6178:e=>{e.exports=function(e,t){return{value:e,done:t}}},8880:(e,t,n)=>{var r=n(9781),a=n(3070),o=n(9114);e.exports=r?function(e,t,n){return a.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},9114:e=>{e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},6135:(e,t,n)=>{"use strict";var r=n(4948),a=n(3070),o=n(9114);e.exports=function(e,t,n){var i=r(t);i in e?a.f(e,i,o(0,n)):e[i]=n}},7045:(e,t,n)=>{var r=n(6339),a=n(3070);e.exports=function(e,t,n){return n.get&&r(n.get,t,{getter:!0}),n.set&&r(n.set,t,{setter:!0}),a.f(e,t,n)}},8052:(e,t,n)=>{var r=n(614),a=n(3070),o=n(6339),i=n(3072);e.exports=function(e,t,n,s){s||(s={});var c=s.enumerable,u=void 0!==s.name?s.name:t;if(r(n)&&o(n,u,s),s.global)c?e[t]=n:i(t,n);else{try{s.unsafe?e[t]&&(c=!0):delete e[t]}catch(e){}c?e[t]=n:a.f(e,t,{value:n,enumerable:!1,configurable:!s.nonConfigurable,writable:!s.nonWritable})}return e}},9190:(e,t,n)=>{var r=n(8052);e.exports=function(e,t,n){for(var a in t)r(e,a,t[a],n);return e}},3072:(e,t,n)=>{var r=n(7854),a=Object.defineProperty;e.exports=function(e,t){try{a(r,e,{value:t,configurable:!0,writable:!0})}catch(n){r[e]=t}return t}},5117:(e,t,n)=>{"use strict";var r=n(6330),a=TypeError;e.exports=function(e,t){if(!delete e[t])throw a("Cannot delete property "+r(t)+" of "+r(e))}},9781:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},4154:e=>{var t="object"==typeof document&&document.all,n=void 0===t&&void 0!==t;e.exports={all:t,IS_HTMLDDA:n}},317:(e,t,n)=>{var r=n(7854),a=n(111),o=r.document,i=a(o)&&a(o.createElement);e.exports=function(e){return i?o.createElement(e):{}}},7207:e=>{var t=TypeError;e.exports=function(e){if(e>9007199254740991)throw t("Maximum allowed index exceeded");return e}},8324:e=>{e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},8509:(e,t,n)=>{var r=n(317)("span").classList,a=r&&r.constructor&&r.constructor.prototype;e.exports=a===Object.prototype?void 0:a},8886:(e,t,n)=>{var r=n(8113).match(/firefox\/(\d+)/i);e.exports=!!r&&+r[1]},7871:(e,t,n)=>{var r=n(3823),a=n(5268);e.exports=!r&&!a&&"object"==typeof window&&"object"==typeof document},9363:e=>{e.exports="function"==typeof Bun&&Bun&&"string"==typeof Bun.version},3823:e=>{e.exports="object"==typeof Deno&&Deno&&"object"==typeof Deno.version},256:(e,t,n)=>{var r=n(8113);e.exports=/MSIE|Trident/.test(r)},1528:(e,t,n)=>{var r=n(8113);e.exports=/ipad|iphone|ipod/i.test(r)&&"undefined"!=typeof Pebble},6833:(e,t,n)=>{var r=n(8113);e.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(r)},5268:(e,t,n)=>{var r=n(4326);e.exports="undefined"!=typeof process&&"process"==r(process)},1036:(e,t,n)=>{var r=n(8113);e.exports=/web0s(?!.*chrome)/i.test(r)},8113:e=>{e.exports="undefined"!=typeof navigator&&String(navigator.userAgent)||""},7392:(e,t,n)=>{var r,a,o=n(7854),i=n(8113),s=o.process,c=o.Deno,u=s&&s.versions||c&&c.version,p=u&&u.v8;p&&(a=(r=p.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!a&&i&&(!(r=i.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=i.match(/Chrome\/(\d+)/))&&(a=+r[1]),e.exports=a},8008:(e,t,n)=>{var r=n(8113).match(/AppleWebKit\/(\d+)\./);e.exports=!!r&&+r[1]},748:e=>{e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},2109:(e,t,n)=>{var r=n(7854),a=n(1236).f,o=n(8880),i=n(8052),s=n(3072),c=n(9920),u=n(4705);e.exports=function(e,t){var n,p,l,d,f,m=e.target,v=e.global,h=e.stat;if(n=v?r:h?r[m]||s(m,{}):(r[m]||{}).prototype)for(p in t){if(d=t[p],l=e.dontCallGetSet?(f=a(n,p))&&f.value:n[p],!u(v?p:m+(h?".":"#")+p,e.forced)&&void 0!==l){if(typeof d==typeof l)continue;c(d,l)}(e.sham||l&&l.sham)&&o(d,"sham",!0),i(n,p,d,e)}}},7293:e=>{e.exports=function(e){try{return!!e()}catch(e){return!0}}},7007:(e,t,n)=>{"use strict";n(4916);var r=n(1470),a=n(8052),o=n(2261),i=n(7293),s=n(5112),c=n(8880),u=s("species"),p=RegExp.prototype;e.exports=function(e,t,n,l){var d=s(e),f=!i((function(){var t={};return t[d]=function(){return 7},7!=""[e](t)})),m=f&&!i((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[u]=function(){return n},n.flags="",n[d]=/./[d]),n.exec=function(){return t=!0,null},n[d](""),!t}));if(!f||!m||n){var v=r(/./[d]),h=t(d,""[e],(function(e,t,n,a,i){var s=r(e),c=t.exec;return c===o||c===p.exec?f&&!i?{done:!0,value:v(t,n,a)}:{done:!0,value:s(n,t,a)}:{done:!1}}));a(String.prototype,e,h[0]),a(p,d,h[1])}l&&c(p[d],"sham",!0)}},6677:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){return Object.isExtensible(Object.preventExtensions({}))}))},2104:(e,t,n)=>{var r=n(4374),a=Function.prototype,o=a.apply,i=a.call;e.exports="object"==typeof Reflect&&Reflect.apply||(r?i.bind(o):function(){return i.apply(o,arguments)})},9974:(e,t,n)=>{var r=n(1470),a=n(9662),o=n(4374),i=r(r.bind);e.exports=function(e,t){return a(e),void 0===t?e:o?i(e,t):function(){return e.apply(t,arguments)}}},4374:(e,t,n)=>{var r=n(7293);e.exports=!r((function(){var e=function(){}.bind();return"function"!=typeof e||e.hasOwnProperty("prototype")}))},7065:(e,t,n)=>{"use strict";var r=n(1702),a=n(9662),o=n(111),i=n(2597),s=n(206),c=n(4374),u=Function,p=r([].concat),l=r([].join),d={},f=function(e,t,n){if(!i(d,t)){for(var r=[],a=0;a{var r=n(4374),a=Function.prototype.call;e.exports=r?a.bind(a):function(){return a.apply(a,arguments)}},6530:(e,t,n)=>{var r=n(9781),a=n(2597),o=Function.prototype,i=r&&Object.getOwnPropertyDescriptor,s=a(o,"name"),c=s&&"something"===function(){}.name,u=s&&(!r||r&&i(o,"name").configurable);e.exports={EXISTS:s,PROPER:c,CONFIGURABLE:u}},5668:(e,t,n)=>{var r=n(1702),a=n(9662);e.exports=function(e,t,n){try{return r(a(Object.getOwnPropertyDescriptor(e,t)[n]))}catch(e){}}},1470:(e,t,n)=>{var r=n(4326),a=n(1702);e.exports=function(e){if("Function"===r(e))return a(e)}},1702:(e,t,n)=>{var r=n(4374),a=Function.prototype,o=a.call,i=r&&a.bind.bind(o,o);e.exports=r?i:function(e){return function(){return o.apply(e,arguments)}}},5005:(e,t,n)=>{var r=n(7854),a=n(614),o=function(e){return a(e)?e:void 0};e.exports=function(e,t){return arguments.length<2?o(r[e]):r[e]&&r[e][t]}},1246:(e,t,n)=>{var r=n(648),a=n(8173),o=n(8554),i=n(7497),s=n(5112)("iterator");e.exports=function(e){if(!o(e))return a(e,s)||a(e,"@@iterator")||i[r(e)]}},4121:(e,t,n)=>{var r=n(6916),a=n(9662),o=n(9670),i=n(6330),s=n(1246),c=TypeError;e.exports=function(e,t){var n=arguments.length<2?s(e):t;if(a(n))return o(r(n,e));throw c(i(e)+" is not iterable")}},8044:(e,t,n)=>{var r=n(1702),a=n(3157),o=n(614),i=n(4326),s=n(1340),c=r([].push);e.exports=function(e){if(o(e))return e;if(a(e)){for(var t=e.length,n=[],r=0;r{var r=n(9662),a=n(8554);e.exports=function(e,t){var n=e[t];return a(n)?void 0:r(n)}},647:(e,t,n)=>{var r=n(1702),a=n(7908),o=Math.floor,i=r("".charAt),s=r("".replace),c=r("".slice),u=/\$([$&'`]|\d{1,2}|<[^>]*>)/g,p=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,t,n,r,l,d){var f=n+e.length,m=r.length,v=p;return void 0!==l&&(l=a(l),v=u),s(d,v,(function(a,s){var u;switch(i(s,0)){case"$":return"$";case"&":return e;case"`":return c(t,0,n);case"'":return c(t,f);case"<":u=l[c(s,1,-1)];break;default:var p=+s;if(0===p)return a;if(p>m){var d=o(p/10);return 0===d?a:d<=m?void 0===r[d-1]?i(s,1):r[d-1]+i(s,1):a}u=r[p-1]}return void 0===u?"":u}))}},7854:e=>{var t=function(e){return e&&e.Math==Math&&e};e.exports=t("object"==typeof globalThis&&globalThis)||t("object"==typeof window&&window)||t("object"==typeof self&&self)||t("object"==typeof global&&global)||function(){return this}()||Function("return this")()},2597:(e,t,n)=>{var r=n(1702),a=n(7908),o=r({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return o(a(e),t)}},3501:e=>{e.exports={}},842:e=>{e.exports=function(e,t){try{1==arguments.length?console.error(e):console.error(e,t)}catch(e){}}},490:(e,t,n)=>{var r=n(5005);e.exports=r("document","documentElement")},4664:(e,t,n)=>{var r=n(9781),a=n(7293),o=n(317);e.exports=!r&&!a((function(){return 7!=Object.defineProperty(o("div"),"a",{get:function(){return 7}}).a}))},8361:(e,t,n)=>{var r=n(1702),a=n(7293),o=n(4326),i=Object,s=r("".split);e.exports=a((function(){return!i("z").propertyIsEnumerable(0)}))?function(e){return"String"==o(e)?s(e,""):i(e)}:i},9587:(e,t,n)=>{var r=n(614),a=n(111),o=n(7674);e.exports=function(e,t,n){var i,s;return o&&r(i=t.constructor)&&i!==n&&a(s=i.prototype)&&s!==n.prototype&&o(e,s),e}},2788:(e,t,n)=>{var r=n(1702),a=n(614),o=n(5465),i=r(Function.toString);a(o.inspectSource)||(o.inspectSource=function(e){return i(e)}),e.exports=o.inspectSource},2423:(e,t,n)=>{var r=n(2109),a=n(1702),o=n(3501),i=n(111),s=n(2597),c=n(3070).f,u=n(8006),p=n(1156),l=n(2050),d=n(9711),f=n(6677),m=!1,v=d("meta"),h=0,b=function(e){c(e,v,{value:{objectID:"O"+h++,weakData:{}}})},g=e.exports={enable:function(){g.enable=function(){},m=!0;var e=u.f,t=a([].splice),n={};n[v]=1,e(n).length&&(u.f=function(n){for(var r=e(n),a=0,o=r.length;a{var r,a,o,i=n(4811),s=n(7854),c=n(111),u=n(8880),p=n(2597),l=n(5465),d=n(6200),f=n(3501),m="Object already initialized",v=s.TypeError,h=s.WeakMap;if(i||l.state){var b=l.state||(l.state=new h);b.get=b.get,b.has=b.has,b.set=b.set,r=function(e,t){if(b.has(e))throw v(m);return t.facade=e,b.set(e,t),t},a=function(e){return b.get(e)||{}},o=function(e){return b.has(e)}}else{var g=d("state");f[g]=!0,r=function(e,t){if(p(e,g))throw v(m);return t.facade=e,u(e,g,t),t},a=function(e){return p(e,g)?e[g]:{}},o=function(e){return p(e,g)}}e.exports={set:r,get:a,has:o,enforce:function(e){return o(e)?a(e):r(e,{})},getterFor:function(e){return function(t){var n;if(!c(t)||(n=a(t)).type!==e)throw v("Incompatible receiver, "+e+" required");return n}}}},7659:(e,t,n)=>{var r=n(5112),a=n(7497),o=r("iterator"),i=Array.prototype;e.exports=function(e){return void 0!==e&&(a.Array===e||i[o]===e)}},3157:(e,t,n)=>{var r=n(4326);e.exports=Array.isArray||function(e){return"Array"==r(e)}},614:(e,t,n)=>{var r=n(4154),a=r.all;e.exports=r.IS_HTMLDDA?function(e){return"function"==typeof e||e===a}:function(e){return"function"==typeof e}},4411:(e,t,n)=>{var r=n(1702),a=n(7293),o=n(614),i=n(648),s=n(5005),c=n(2788),u=function(){},p=[],l=s("Reflect","construct"),d=/^\s*(?:class|function)\b/,f=r(d.exec),m=!d.exec(u),v=function(e){if(!o(e))return!1;try{return l(u,p,e),!0}catch(e){return!1}},h=function(e){if(!o(e))return!1;switch(i(e)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return m||!!f(d,c(e))}catch(e){return!0}};h.sham=!0,e.exports=!l||a((function(){var e;return v(v.call)||!v(Object)||!v((function(){e=!0}))||e}))?h:v},4705:(e,t,n)=>{var r=n(7293),a=n(614),o=/#|\.prototype\./,i=function(e,t){var n=c[s(e)];return n==p||n!=u&&(a(t)?r(t):!!t)},s=i.normalize=function(e){return String(e).replace(o,".").toLowerCase()},c=i.data={},u=i.NATIVE="N",p=i.POLYFILL="P";e.exports=i},5988:(e,t,n)=>{var r=n(111),a=Math.floor;e.exports=Number.isInteger||function(e){return!r(e)&&isFinite(e)&&a(e)===e}},8554:e=>{e.exports=function(e){return null==e}},111:(e,t,n)=>{var r=n(614),a=n(4154),o=a.all;e.exports=a.IS_HTMLDDA?function(e){return"object"==typeof e?null!==e:r(e)||e===o}:function(e){return"object"==typeof e?null!==e:r(e)}},1913:e=>{e.exports=!1},7850:(e,t,n)=>{var r=n(111),a=n(4326),o=n(5112)("match");e.exports=function(e){var t;return r(e)&&(void 0!==(t=e[o])?!!t:"RegExp"==a(e))}},2190:(e,t,n)=>{var r=n(5005),a=n(614),o=n(7976),i=n(3307),s=Object;e.exports=i?function(e){return"symbol"==typeof e}:function(e){var t=r("Symbol");return a(t)&&o(t.prototype,s(e))}},408:(e,t,n)=>{var r=n(9974),a=n(6916),o=n(9670),i=n(6330),s=n(7659),c=n(6244),u=n(7976),p=n(4121),l=n(1246),d=n(9212),f=TypeError,m=function(e,t){this.stopped=e,this.result=t},v=m.prototype;e.exports=function(e,t,n){var h,b,g,y,x,w,_,S=n&&n.that,E=!(!n||!n.AS_ENTRIES),A=!(!n||!n.IS_RECORD),k=!(!n||!n.IS_ITERATOR),O=!(!n||!n.INTERRUPTED),j=r(t,S),C=function(e){return h&&d(h,"normal",e),new m(!0,e)},R=function(e){return E?(o(e),O?j(e[0],e[1],C):j(e[0],e[1])):O?j(e,C):j(e)};if(A)h=e.iterator;else if(k)h=e;else{if(!(b=l(e)))throw f(i(e)+" is not iterable");if(s(b)){for(g=0,y=c(e);y>g;g++)if((x=R(e[g]))&&u(v,x))return x;return new m(!1)}h=p(e,b)}for(w=A?e.next:h.next;!(_=a(w,h)).done;){try{x=R(_.value)}catch(e){d(h,"throw",e)}if("object"==typeof x&&x&&u(v,x))return x}return new m(!1)}},9212:(e,t,n)=>{var r=n(6916),a=n(9670),o=n(8173);e.exports=function(e,t,n){var i,s;a(e);try{if(!(i=o(e,"return"))){if("throw"===t)throw n;return n}i=r(i,e)}catch(e){s=!0,i=e}if("throw"===t)throw n;if(s)throw i;return a(i),n}},3061:(e,t,n)=>{"use strict";var r=n(3383).IteratorPrototype,a=n(30),o=n(9114),i=n(8003),s=n(7497),c=function(){return this};e.exports=function(e,t,n,u){var p=t+" Iterator";return e.prototype=a(r,{next:o(+!u,n)}),i(e,p,!1,!0),s[p]=c,e}},1656:(e,t,n)=>{"use strict";var r=n(2109),a=n(6916),o=n(1913),i=n(6530),s=n(614),c=n(3061),u=n(9518),p=n(7674),l=n(8003),d=n(8880),f=n(8052),m=n(5112),v=n(7497),h=n(3383),b=i.PROPER,g=i.CONFIGURABLE,y=h.IteratorPrototype,x=h.BUGGY_SAFARI_ITERATORS,w=m("iterator"),_="keys",S="values",E="entries",A=function(){return this};e.exports=function(e,t,n,i,m,h,k){c(n,t,i);var O,j,C,R=function(e){if(e===m&&U)return U;if(!x&&e in P)return P[e];switch(e){case _:case S:case E:return function(){return new n(this,e)}}return function(){return new n(this)}},I=t+" Iterator",T=!1,P=e.prototype,N=P[w]||P["@@iterator"]||m&&P[m],U=!x&&N||R(m),D="Array"==t&&P.entries||N;if(D&&(O=u(D.call(new e)))!==Object.prototype&&O.next&&(o||u(O)===y||(p?p(O,y):s(O[w])||f(O,w,A)),l(O,I,!0,!0),o&&(v[I]=A)),b&&m==S&&N&&N.name!==S&&(!o&&g?d(P,"name",S):(T=!0,U=function(){return a(N,this)})),m)if(j={values:R(S),keys:h?U:R(_),entries:R(E)},k)for(C in j)(x||T||!(C in P))&&f(P,C,j[C]);else r({target:t,proto:!0,forced:x||T},j);return o&&!k||P[w]===U||f(P,w,U,{name:m}),v[t]=U,j}},3383:(e,t,n)=>{"use strict";var r,a,o,i=n(7293),s=n(614),c=n(111),u=n(30),p=n(9518),l=n(8052),d=n(5112),f=n(1913),m=d("iterator"),v=!1;[].keys&&("next"in(o=[].keys())?(a=p(p(o)))!==Object.prototype&&(r=a):v=!0),!c(r)||i((function(){var e={};return r[m].call(e)!==e}))?r={}:f&&(r=u(r)),s(r[m])||l(r,m,(function(){return this})),e.exports={IteratorPrototype:r,BUGGY_SAFARI_ITERATORS:v}},7497:e=>{e.exports={}},6244:(e,t,n)=>{var r=n(7466);e.exports=function(e){return r(e.length)}},6339:(e,t,n)=>{var r=n(1702),a=n(7293),o=n(614),i=n(2597),s=n(9781),c=n(6530).CONFIGURABLE,u=n(2788),p=n(9909),l=p.enforce,d=p.get,f=String,m=Object.defineProperty,v=r("".slice),h=r("".replace),b=r([].join),g=s&&!a((function(){return 8!==m((function(){}),"length",{value:8}).length})),y=String(String).split("String"),x=e.exports=function(e,t,n){"Symbol("===v(f(t),0,7)&&(t="["+h(f(t),/^Symbol\(([^)]*)\)/,"$1")+"]"),n&&n.getter&&(t="get "+t),n&&n.setter&&(t="set "+t),(!i(e,"name")||c&&e.name!==t)&&(s?m(e,"name",{value:t,configurable:!0}):e.name=t),g&&n&&i(n,"arity")&&e.length!==n.arity&&m(e,"length",{value:n.arity});try{n&&i(n,"constructor")&&n.constructor?s&&m(e,"prototype",{writable:!1}):e.prototype&&(e.prototype=void 0)}catch(e){}var r=l(e);return i(r,"source")||(r.source=b(y,"string"==typeof t?t:"")),e};Function.prototype.toString=x((function(){return o(this)&&d(this).source||u(this)}),"toString")},4758:e=>{var t=Math.ceil,n=Math.floor;e.exports=Math.trunc||function(e){var r=+e;return(r>0?n:t)(r)}},5948:(e,t,n)=>{var r,a,o,i,s,c=n(7854),u=n(9974),p=n(1236).f,l=n(261).set,d=n(8572),f=n(6833),m=n(1528),v=n(1036),h=n(5268),b=c.MutationObserver||c.WebKitMutationObserver,g=c.document,y=c.process,x=c.Promise,w=p(c,"queueMicrotask"),_=w&&w.value;if(!_){var S=new d,E=function(){var e,t;for(h&&(e=y.domain)&&e.exit();t=S.get();)try{t()}catch(e){throw S.head&&r(),e}e&&e.enter()};f||h||v||!b||!g?!m&&x&&x.resolve?((i=x.resolve(void 0)).constructor=x,s=u(i.then,i),r=function(){s(E)}):h?r=function(){y.nextTick(E)}:(l=u(l,c),r=function(){l(E)}):(a=!0,o=g.createTextNode(""),new b(E).observe(o,{characterData:!0}),r=function(){o.data=a=!a}),_=function(e){S.head||r(),S.add(e)}}e.exports=_},8523:(e,t,n)=>{"use strict";var r=n(9662),a=TypeError,o=function(e){var t,n;this.promise=new e((function(e,r){if(void 0!==t||void 0!==n)throw a("Bad Promise constructor");t=e,n=r})),this.resolve=r(t),this.reject=r(n)};e.exports.f=function(e){return new o(e)}},3929:(e,t,n)=>{var r=n(7850),a=TypeError;e.exports=function(e){if(r(e))throw a("The method doesn't accept regular expressions");return e}},2814:(e,t,n)=>{var r=n(7854),a=n(7293),o=n(1702),i=n(1340),s=n(3111).trim,c=n(1361),u=o("".charAt),p=r.parseFloat,l=r.Symbol,d=l&&l.iterator,f=1/p(c+"-0")!=-1/0||d&&!a((function(){p(Object(d))}));e.exports=f?function(e){var t=s(i(e)),n=p(t);return 0===n&&"-"==u(t,0)?-0:n}:p},30:(e,t,n)=>{var r,a=n(9670),o=n(6048),i=n(748),s=n(3501),c=n(490),u=n(317),p=n(6200)("IE_PROTO"),l=function(){},d=function(e){return"",e=e.removeChild(e.firstChild)):"string"==typeof r.is?e=c.createElement(t,{is:r.is}):(e=c.createElement(t),"select"===t&&(c=e,r.multiple?c.multiple=!0:r.size&&(c.size=r.size))):e=c.createElementNS(e,t),e[rz]=n,e[rT]=r,l(e,n,!1,!1),n.stateNode=e;e:{switch(c=eS(t,r),t){case"dialog":rt("cancel",e),rt("close",e),i=r;break;case"iframe":case"object":case"embed":rt("load",e),i=r;break;case"video":case"audio":for(i=0;ioo&&(n.flags|=128,r=!0,uN(s,!1),n.lanes=4194304)}}else{if(!r){if(null!==(e=aa(c))){if(n.flags|=128,r=!0,null!==(t=e.updateQueue)&&(n.updateQueue=t,n.flags|=4),uN(s,!0),null===s.tail&&"hidden"===s.tailMode&&!c.alternate&&!lf)return uz(n),null}else 2*eJ()-s.renderingStartTime>oo&&1073741824!==t&&(n.flags|=128,r=!0,uN(s,!1),n.lanes=4194304)}s.isBackwards?(c.sibling=n.child,n.child=c):(null!==(t=s.last)?t.sibling=c:n.child=c,s.last=c)}if(null!==s.tail)return n=s.tail,s.rendering=n,s.tail=n.sibling,s.renderingStartTime=eJ(),n.sibling=null,t=al.current,rB(al,r?1&t|2:1&t),n;return uz(n),null;case 22:case 23:return oT(),r=null!==n.memoizedState,null!==e&&null!==e.memoizedState!==r&&(n.flags|=8192),r&&0!=(1&n.mode)?0!=(1073741824&u5)&&(uz(n),6&n.subtreeFlags&&(n.flags|=8192)):uz(n),null;case 24:case 25:return null}throw Error(f(156,n.tag))}(t,n,u5))){u8=t;return}}else{if(null!==(t=function(e,n){switch(li(n),n.tag){case 1:return rY(n.type)&&rX(),65536&(e=n.flags)?(n.flags=-65537&e|128,n):null;case 3:return an(),rj(rQ),rj(rW),ao(),0!=(65536&(e=n.flags))&&0==(128&e)?(n.flags=-65537&e|128,n):null;case 5:return ar(n),null;case 13:if(rj(al),null!==(e=n.memoizedState)&&null!==e.dehydrated){if(null===n.alternate)throw Error(f(340));lk()}return 65536&(e=n.flags)?(n.flags=-65537&e|128,n):null;case 19:return rj(al),null;case 4:return an(),null;case 10:return lz(n.type._context),null;case 22:case 23:return oT(),null;default:return null}}(t,n))){t.flags&=32767,u8=t;return}if(null!==e)e.flags|=32768,e.subtreeFlags=0,e.deletions=null;else{u7=6,u8=null;return}}if(null!==(n=n.sibling)){u8=n;return}u8=n=e}while(null!==n);0===u7&&(u7=5)}function oU(e,n,t){var r=nc,l=u2.transition;try{u2.transition=null,nc=1,function(e,n,t,r){do oV();while(null!==op);if(0!=(6&u3))throw Error(f(327));t=e.finishedWork;var l=e.finishedLanes;if(null!==t){if(e.finishedWork=null,e.finishedLanes=0,t===e.current)throw Error(f(177));e.callbackNode=null,e.callbackPriority=0;var a=t.lanes|t.childLanes;if(function(e,n){var t=e.pendingLanes&~n;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=n,e.mutableReadLanes&=n,e.entangledLanes&=n,n=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0r&&(l=r,r=a,a=l),l=tV(t,a);var u=tV(t,r);l&&u&&(1!==e.rangeCount||e.anchorNode!==l.node||e.anchorOffset!==l.offset||e.focusNode!==u.node||e.focusOffset!==u.offset)&&((n=n.createRange()).setStart(l.node,l.offset),e.removeAllRanges(),a>r?(e.addRange(n),e.extend(u.node,u.offset)):(n.setEnd(u.node,u.offset),e.addRange(n)))}}for(n=[],e=t;e=e.parentNode;)1===e.nodeType&&n.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof t.focus&&t.focus(),t=0;te?16:e,null===op)var r=!1;else{if(e=op,op=null,om=0,0!=(6&u3))throw Error(f(331));var l=u3;for(u3|=4,uM=e.current;null!==uM;){var a=uM,u=a.child;if(0!=(16&uM.flags)){var o=a.deletions;if(null!==o){for(var i=0;ieJ()-ou?oL(e,0):or|=t),oS(e,n)}function oB(e,n){0===n&&(0==(1&e.mode)?n=1:(n=nt,0==(130023424&(nt<<=1))&&(nt=4194304)));var t=ob();null!==(e=lD(e,n))&&(ni(e,n,t),oS(e,t))}function oH(e){var n=e.memoizedState,t=0;null!==n&&(t=n.retryLane),oB(e,t)}function oW(e,n){var t=0;switch(e.tag){case 13:var r=e.stateNode,l=e.memoizedState;null!==l&&(t=l.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(f(314))}null!==r&&r.delete(n),oB(e,t)}function oQ(e,n,t,r){this.tag=e,this.key=t,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=n,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function oq(e,n,t,r){return new oQ(e,n,t,r)}function oK(e){return!(!(e=e.prototype)||!e.isReactComponent)}function oY(e,n){var t=e.alternate;return null===t?((t=oq(e.tag,n,e.key,e.mode)).elementType=e.elementType,t.type=e.type,t.stateNode=e.stateNode,t.alternate=e,e.alternate=t):(t.pendingProps=n,t.type=e.type,t.flags=0,t.subtreeFlags=0,t.deletions=null),t.flags=14680064&e.flags,t.childLanes=e.childLanes,t.lanes=e.lanes,t.child=e.child,t.memoizedProps=e.memoizedProps,t.memoizedState=e.memoizedState,t.updateQueue=e.updateQueue,n=e.dependencies,t.dependencies=null===n?null:{lanes:n.lanes,firstContext:n.firstContext},t.sibling=e.sibling,t.index=e.index,t.ref=e.ref,t}function oX(e,n,t,r,l,a){var u=2;if(r=e,"function"==typeof e)oK(e)&&(u=1);else if("string"==typeof e)u=5;else e:switch(e){case z:return oG(t.children,l,a,n);case T:u=8,l|=8;break;case L:return(e=oq(12,t,n,2|l)).elementType=L,e.lanes=a,e;case O:return(e=oq(13,t,n,l)).elementType=O,e.lanes=a,e;case D:return(e=oq(19,t,n,l)).elementType=D,e.lanes=a,e;case V:return oZ(t,l,a,n);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case R:u=10;break e;case M:u=9;break e;case F:u=11;break e;case I:u=14;break e;case U:u=16,r=null;break e}throw Error(f(130,null==e?e:typeof e,""))}return(n=oq(u,t,n,l)).elementType=e,n.type=r,n.lanes=a,n}function oG(e,n,t,r){return(e=oq(7,e,r,n)).lanes=t,e}function oZ(e,n,t,r){return(e=oq(22,e,r,n)).elementType=V,e.lanes=t,e.stateNode={isHidden:!1},e}function oJ(e,n,t){return(e=oq(6,e,null,n)).lanes=t,e}function o0(e,n,t){return(n=oq(4,null!==e.children?e.children:[],e.key,n)).lanes=t,n.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},n}function o1(e,n,t,r,l){this.tag=n,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=no(0),this.expirationTimes=no(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=no(0),this.identifierPrefix=r,this.onRecoverableError=l,this.mutableSourceEagerHydrationData=null}function o2(e,n,t,r,l,a,u,o,i){return e=new o1(e,n,t,o,i),1===n?(n=1,!0===a&&(n|=8)):n=0,a=oq(3,null,null,n),e.current=a,a.stateNode=e,a.memoizedState={element:r,isDehydrated:t,cache:null,transitions:null,pendingSuspenseBoundaries:null},lU(a),e}function o3(e){if(!e)return rH;e=e._reactInternals;e:{if(eW(e)!==e||1!==e.tag)throw Error(f(170));var n=e;do{switch(n.tag){case 3:n=n.stateNode.context;break e;case 1:if(rY(n.type)){n=n.stateNode.__reactInternalMemoizedMergedChildContext;break e}}n=n.return}while(null!==n);throw Error(f(171))}if(1===e.tag){var t=e.type;if(rY(t))return rZ(e,t,n)}return n}function o4(e,n,t,r,l,a,u,o,i){return(e=o2(t,r,!0,e,l,a,u,o,i)).context=o3(null),t=e.current,(a=l$(r=ob(),l=ok(t))).callback=null!=n?n:null,lA(t,a,l),e.current.lanes=l,ni(e,l,r),oS(e,r),e}function o8(e,n,t,r){var l=n.current,a=ob(),u=ok(l);return t=o3(t),null===n.context?n.context=t:n.pendingContext=t,(n=l$(a,u)).payload={element:e},null!==(r=void 0===r?null:r)&&(n.callback=r),null!==(e=lA(l,n,u))&&(ow(e,l,u,a),lj(e,l,u)),u}function o6(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function o5(e,n){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var t=e.retryLane;e.retryLane=0!==t&&t>>1,l=e[r];if(0>>1;ra(i,t))sa(c,i)?(e[r]=c,e[s]=t,r=s):(e[r]=i,e[o]=t,r=o);else if(sa(c,t))e[r]=c,e[s]=t,r=s;else break}}return n}function a(e,n){var t=e.sortIndex-n.sortIndex;return 0!==t?t:e.id-n.id}if("object"==typeof performance&&"function"==typeof performance.now){var u,o=performance;n.unstable_now=function(){return o.now()}}else{var i=Date,s=i.now();n.unstable_now=function(){return i.now()-s}}var c=[],f=[],d=1,p=null,m=3,h=!1,g=!1,v=!1,y="function"==typeof setTimeout?setTimeout:null,b="function"==typeof clearTimeout?clearTimeout:null,k="undefined"!=typeof setImmediate?setImmediate:null;function w(e){for(var n=r(f);null!==n;){if(null===n.callback)l(f);else if(n.startTime<=e)l(f),n.sortIndex=n.expirationTime,t(c,n);else break;n=r(f)}}function S(e){if(v=!1,w(e),!g){if(null!==r(c))g=!0,M(x);else{var n=r(f);null!==n&&F(S,n.startTime-e)}}}function x(e,t){g=!1,v&&(v=!1,b(C),C=-1),h=!0;var a=m;try{for(w(t),p=r(c);null!==p&&(!(p.expirationTime>t)||e&&!z());){var u=p.callback;if("function"==typeof u){p.callback=null,m=p.priorityLevel;var o=u(p.expirationTime<=t);t=n.unstable_now(),"function"==typeof o?p.callback=o:p===r(c)&&l(c),w(t)}else l(c);p=r(c)}if(null!==p)var i=!0;else{var s=r(f);null!==s&&F(S,s.startTime-t),i=!1}return i}finally{p=null,m=a,h=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var E=!1,_=null,C=-1,P=5,N=-1;function z(){return!(n.unstable_now()-Ne||125u?(e.sortIndex=a,t(f,e),null===r(c)&&e===r(f)&&(v?(b(C),C=-1):v=!0,F(S,a-u))):(e.sortIndex=o,t(c,e),g||h||(g=!0,M(x))),e},n.unstable_shouldYield=z,n.unstable_wrapCallback=function(e){var n=m;return function(){var t=m;m=n;try{return e.apply(this,arguments)}finally{m=t}}}},63840:function(e,n,t){e.exports=t(60053)}}]); \ No newline at end of file diff --git a/striker-ui/out/_next/static/chunks/framework-ff7f418116f76b2d.js b/striker-ui/out/_next/static/chunks/framework-ff7f418116f76b2d.js deleted file mode 100644 index 036156a59..000000000 --- a/striker-ui/out/_next/static/chunks/framework-ff7f418116f76b2d.js +++ /dev/null @@ -1,33 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[774],{64448:function(e,n,t){/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var r,l,a,u,o,i,s=t(67294),c=t(63840);function f(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t