@verdaccio/ui-components 5.0.0-next-9.19 → 5.0.0-next-9.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/use-data-mutation.js +1 -4
- package/build/api/use-data-mutation.js.map +1 -1
- package/build/api/use-data-mutation.mjs +1 -4
- package/build/api/use-data-mutation.mjs.map +1 -1
- package/build/api/use-data.d.ts +1 -0
- package/build/api/use-data.js +3 -2
- package/build/api/use-data.js.map +1 -1
- package/build/api/use-data.mjs +3 -3
- package/build/api/use-data.mjs.map +1 -1
- package/build/components/ActionBar/ActionBar.js +4 -2
- package/build/components/ActionBar/ActionBar.js.map +1 -1
- package/build/components/ActionBar/ActionBar.mjs +4 -2
- package/build/components/ActionBar/ActionBar.mjs.map +1 -1
- package/build/components/ActionBar/ActionBarAction.js +1 -1
- package/build/components/ActionBar/ActionBarAction.mjs +1 -1
- package/build/components/AppRoute/AppRoute.js +13 -0
- package/build/components/AppRoute/AppRoute.js.map +1 -1
- package/build/components/AppRoute/AppRoute.mjs +13 -0
- package/build/components/AppRoute/AppRoute.mjs.map +1 -1
- package/build/components/Author/Author.js +1 -1
- package/build/components/Author/Author.mjs +1 -1
- package/build/components/CopyClipboard/CopyToClipBoard.js +5 -0
- package/build/components/CopyClipboard/CopyToClipBoard.js.map +1 -1
- package/build/components/CopyClipboard/CopyToClipBoard.mjs +5 -0
- package/build/components/CopyClipboard/CopyToClipBoard.mjs.map +1 -1
- package/build/components/CopyClipboard/utils.js +14 -1
- package/build/components/CopyClipboard/utils.js.map +1 -1
- package/build/components/CopyClipboard/utils.mjs +14 -1
- package/build/components/CopyClipboard/utils.mjs.map +1 -1
- package/build/components/Dependencies/Dependencies.js +2 -1
- package/build/components/Dependencies/Dependencies.js.map +1 -1
- package/build/components/Dependencies/Dependencies.mjs +2 -1
- package/build/components/Dependencies/Dependencies.mjs.map +1 -1
- package/build/components/Dependencies/DependencyBlock.js +1 -1
- package/build/components/Dependencies/DependencyBlock.mjs +1 -1
- package/build/components/Developers/Title.js +1 -1
- package/build/components/Developers/Title.mjs +1 -1
- package/build/components/Developers/get-unique-developer-values.js +2 -1
- package/build/components/Developers/get-unique-developer-values.js.map +1 -1
- package/build/components/Developers/get-unique-developer-values.mjs +2 -1
- package/build/components/Developers/get-unique-developer-values.mjs.map +1 -1
- package/build/components/Distribution/Dist.js +3 -3
- package/build/components/Distribution/Dist.js.map +1 -1
- package/build/components/Distribution/Dist.mjs +3 -3
- package/build/components/Distribution/Dist.mjs.map +1 -1
- package/build/components/Engines/Engines.js +1 -1
- package/build/components/Engines/Engines.mjs +1 -1
- package/build/components/Forbidden/Forbidden.js +1 -1
- package/build/components/Forbidden/Forbidden.mjs +1 -1
- package/build/components/FundButton/FundButton.js +4 -3
- package/build/components/FundButton/FundButton.js.map +1 -1
- package/build/components/FundButton/FundButton.mjs +4 -3
- package/build/components/FundButton/FundButton.mjs.map +1 -1
- package/build/components/GenericError/GenericError.d.ts +3 -0
- package/build/components/GenericError/GenericError.js +60 -0
- package/build/components/GenericError/GenericError.js.map +1 -0
- package/build/components/GenericError/GenericError.mjs +54 -0
- package/build/components/GenericError/GenericError.mjs.map +1 -0
- package/build/components/GenericError/index.d.ts +1 -0
- package/build/components/GenericError/index.js +2 -0
- package/build/components/GenericError/index.mjs +2 -0
- package/build/components/Help/Help.js +1 -1
- package/build/components/Help/Help.mjs +1 -1
- package/build/components/Install/Install.js +1 -1
- package/build/components/Install/Install.mjs +1 -1
- package/build/components/Install/InstallListItem.js +2 -2
- package/build/components/Install/InstallListItem.js.map +1 -1
- package/build/components/Install/InstallListItem.mjs +2 -2
- package/build/components/Install/InstallListItem.mjs.map +1 -1
- package/build/components/Keywords/KeywordListItems.js +1 -1
- package/build/components/Keywords/KeywordListItems.js.map +1 -1
- package/build/components/Keywords/KeywordListItems.mjs +1 -1
- package/build/components/Keywords/KeywordListItems.mjs.map +1 -1
- package/build/components/Keywords/Keywords.js +2 -2
- package/build/components/Keywords/Keywords.js.map +1 -1
- package/build/components/Keywords/Keywords.mjs +2 -2
- package/build/components/Keywords/Keywords.mjs.map +1 -1
- package/build/components/LoginDialog/LoginDialogCloseButton.js +1 -1
- package/build/components/LoginDialog/LoginDialogCloseButton.mjs +1 -1
- package/build/components/LoginDialog/LoginDialogForm.js +2 -1
- package/build/components/LoginDialog/LoginDialogForm.js.map +1 -1
- package/build/components/LoginDialog/LoginDialogForm.mjs +2 -1
- package/build/components/LoginDialog/LoginDialogForm.mjs.map +1 -1
- package/build/components/LoginForm/Login.d.ts +1 -0
- package/build/components/LoginForm/Login.js +6 -4
- package/build/components/LoginForm/Login.js.map +1 -1
- package/build/components/LoginForm/Login.mjs +9 -7
- package/build/components/LoginForm/Login.mjs.map +1 -1
- package/build/components/LoginForm/PasswordField.js +4 -6
- package/build/components/LoginForm/PasswordField.js.map +1 -1
- package/build/components/LoginForm/PasswordField.mjs +4 -6
- package/build/components/LoginForm/PasswordField.mjs.map +1 -1
- package/build/components/LoginForm/UsernameField.js +4 -6
- package/build/components/LoginForm/UsernameField.js.map +1 -1
- package/build/components/LoginForm/UsernameField.mjs +4 -6
- package/build/components/LoginForm/UsernameField.mjs.map +1 -1
- package/build/components/LoginForm/styles.js +1 -1
- package/build/components/LoginForm/styles.mjs +1 -1
- package/build/components/LoginForm/useLoginForm.js +13 -3
- package/build/components/LoginForm/useLoginForm.js.map +1 -1
- package/build/components/LoginForm/useLoginForm.mjs +14 -4
- package/build/components/LoginForm/useLoginForm.mjs.map +1 -1
- package/build/components/NoItems/NoItems.js +2 -2
- package/build/components/NoItems/NoItems.mjs +1 -1
- package/build/components/NotFound/NotFound.js +1 -1
- package/build/components/NotFound/NotFound.mjs +1 -1
- package/build/components/Package/Package.d.ts +1 -1
- package/build/components/Package/Package.js +28 -29
- package/build/components/Package/Package.js.map +1 -1
- package/build/components/Package/Package.mjs +29 -30
- package/build/components/Package/Package.mjs.map +1 -1
- package/build/components/Person/Person.js +1 -1
- package/build/components/Person/Person.js.map +1 -1
- package/build/components/Person/Person.mjs +1 -1
- package/build/components/Person/Person.mjs.map +1 -1
- package/build/components/RawViewer/RawViewer.js +1 -1
- package/build/components/RawViewer/RawViewer.mjs +1 -1
- package/build/components/RegistryInfoDialog/RegistryInfoDialog.js +1 -1
- package/build/components/RegistryInfoDialog/RegistryInfoDialog.mjs +1 -1
- package/build/components/Repository/Repository.js +5 -8
- package/build/components/Repository/Repository.js.map +1 -1
- package/build/components/Repository/Repository.mjs +5 -8
- package/build/components/Repository/Repository.mjs.map +1 -1
- package/build/components/Search/AutoComplete/AutoComplete.d.ts +1 -0
- package/build/components/Search/AutoComplete/AutoComplete.js +4 -4
- package/build/components/Search/AutoComplete/AutoComplete.js.map +1 -1
- package/build/components/Search/AutoComplete/AutoComplete.mjs +4 -4
- package/build/components/Search/AutoComplete/AutoComplete.mjs.map +1 -1
- package/build/components/Search/Search.js +12 -4
- package/build/components/Search/Search.js.map +1 -1
- package/build/components/Search/Search.mjs +13 -5
- package/build/components/Search/Search.mjs.map +1 -1
- package/build/components/Search/SearchItem.js +1 -1
- package/build/components/Search/SearchItem.mjs +1 -1
- package/build/components/SettingsMenu/SettingsMenu.js +1 -1
- package/build/components/SettingsMenu/SettingsMenu.mjs +1 -1
- package/build/components/SideBarTitle/SideBarTitle.js +2 -2
- package/build/components/SideBarTitle/SideBarTitle.js.map +1 -1
- package/build/components/SideBarTitle/SideBarTitle.mjs +2 -2
- package/build/components/SideBarTitle/SideBarTitle.mjs.map +1 -1
- package/build/components/UpLinks/UpLinks.js +1 -1
- package/build/components/UpLinks/UpLinks.mjs +1 -1
- package/build/components/Versions/HistoryList.js +2 -2
- package/build/components/Versions/HistoryList.js.map +1 -1
- package/build/components/Versions/HistoryList.mjs +2 -2
- package/build/components/Versions/HistoryList.mjs.map +1 -1
- package/build/components/Versions/Versions.js +22 -21
- package/build/components/Versions/Versions.js.map +1 -1
- package/build/components/Versions/Versions.mjs +22 -21
- package/build/components/Versions/Versions.mjs.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +4 -0
- package/build/index.mjs +4 -2
- package/build/pages/Stage/StageDetail.d.ts +2 -0
- package/build/pages/Stage/StageDetail.js +8 -0
- package/build/pages/Stage/StageDetail.js.map +1 -0
- package/build/pages/Stage/StageDetail.mjs +8 -0
- package/build/pages/Stage/StageDetail.mjs.map +1 -0
- package/build/pages/Stage/StageList.d.ts +2 -0
- package/build/pages/Stage/StageList.js +8 -0
- package/build/pages/Stage/StageList.js.map +1 -0
- package/build/pages/Stage/StageList.mjs +8 -0
- package/build/pages/Stage/StageList.mjs.map +1 -0
- package/build/pages/Stage/index.d.ts +2 -0
- package/build/pages/Version/Version.js +4 -1
- package/build/pages/Version/Version.js.map +1 -1
- package/build/pages/Version/Version.mjs +4 -1
- package/build/pages/Version/Version.mjs.map +1 -1
- package/build/providers/AuthProvider/AuthProvider.js +9 -7
- package/build/providers/AuthProvider/AuthProvider.js.map +1 -1
- package/build/providers/AuthProvider/AuthProvider.mjs +10 -8
- package/build/providers/AuthProvider/AuthProvider.mjs.map +1 -1
- package/build/providers/AuthProvider/utils.d.ts +12 -0
- package/build/providers/AuthProvider/utils.js +22 -0
- package/build/providers/AuthProvider/utils.js.map +1 -1
- package/build/providers/AuthProvider/utils.mjs +21 -2
- package/build/providers/AuthProvider/utils.mjs.map +1 -1
- package/build/providers/DownloadProvider/DownloadProvider.d.ts +1 -0
- package/build/providers/DownloadProvider/DownloadProvider.js +27 -4
- package/build/providers/DownloadProvider/DownloadProvider.js.map +1 -1
- package/build/providers/DownloadProvider/DownloadProvider.mjs +27 -6
- package/build/providers/DownloadProvider/DownloadProvider.mjs.map +1 -1
- package/build/providers/ManifestsProvider/ManifestsProvider.js +1 -1
- package/build/providers/ManifestsProvider/ManifestsProvider.js.map +1 -1
- package/build/providers/ManifestsProvider/ManifestsProvider.mjs +1 -1
- package/build/providers/ManifestsProvider/ManifestsProvider.mjs.map +1 -1
- package/build/providers/SearchProvider/SearchProvider.d.ts +1 -0
- package/build/providers/SearchProvider/SearchProvider.js +8 -6
- package/build/providers/SearchProvider/SearchProvider.js.map +1 -1
- package/build/providers/SearchProvider/SearchProvider.mjs +8 -6
- package/build/providers/SearchProvider/SearchProvider.mjs.map +1 -1
- package/build/providers/TranslatorProvider/TranslatorProvider.js +5 -3
- package/build/providers/TranslatorProvider/TranslatorProvider.js.map +1 -1
- package/build/providers/TranslatorProvider/TranslatorProvider.mjs +5 -3
- package/build/providers/TranslatorProvider/TranslatorProvider.mjs.map +1 -1
- package/build/providers/VersionProvider/VersionProvider.js +3 -3
- package/build/providers/VersionProvider/VersionProvider.js.map +1 -1
- package/build/providers/VersionProvider/VersionProvider.mjs +3 -3
- package/build/providers/VersionProvider/VersionProvider.mjs.map +1 -1
- package/build/sections/Detail/Tabs.js +1 -1
- package/build/sections/Detail/Tabs.mjs +1 -1
- package/build/sections/Footer/Footer.js +1 -1
- package/build/sections/Footer/Footer.mjs +1 -1
- package/build/sections/Header/Header.d.ts +0 -1
- package/build/sections/Header/Header.js +16 -14
- package/build/sections/Header/Header.js.map +1 -1
- package/build/sections/Header/Header.mjs +17 -15
- package/build/sections/Header/Header.mjs.map +1 -1
- package/build/sections/Header/HeaderGreetings.js +1 -1
- package/build/sections/Header/HeaderGreetings.mjs +1 -1
- package/build/sections/Header/HeaderMenu.js +26 -7
- package/build/sections/Header/HeaderMenu.js.map +1 -1
- package/build/sections/Header/HeaderMenu.mjs +26 -7
- package/build/sections/Header/HeaderMenu.mjs.map +1 -1
- package/build/sections/Header/HeaderRight.js +1 -1
- package/build/sections/Header/HeaderRight.mjs +1 -1
- package/build/sections/Header/HeaderSettingsDialog.js +1 -1
- package/build/sections/Header/HeaderSettingsDialog.mjs +1 -1
- package/build/sections/Header/LanguageSwitch.js +1 -1
- package/build/sections/Header/LanguageSwitch.mjs +1 -1
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.js +1 -1
- package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.mjs +1 -1
- package/build/sections/Home/Home.js +4 -3
- package/build/sections/Home/Home.js.map +1 -1
- package/build/sections/Home/Home.mjs +5 -4
- package/build/sections/Home/Home.mjs.map +1 -1
- package/build/sections/Security/AddUser.js +33 -18
- package/build/sections/Security/AddUser.js.map +1 -1
- package/build/sections/Security/AddUser.mjs +37 -22
- package/build/sections/Security/AddUser.mjs.map +1 -1
- package/build/sections/Security/ChangePassword.js +17 -15
- package/build/sections/Security/ChangePassword.js.map +1 -1
- package/build/sections/Security/ChangePassword.mjs +19 -17
- package/build/sections/Security/ChangePassword.mjs.map +1 -1
- package/build/sections/Security/Login.js +51 -35
- package/build/sections/Security/Login.js.map +1 -1
- package/build/sections/Security/Login.mjs +54 -38
- package/build/sections/Security/Login.mjs.map +1 -1
- package/build/sections/Security/Success.js +28 -24
- package/build/sections/Security/Success.js.map +1 -1
- package/build/sections/Security/Success.mjs +29 -25
- package/build/sections/Security/Success.mjs.map +1 -1
- package/build/sections/Stage/StageActions.d.ts +15 -0
- package/build/sections/Stage/StageActions.js +101 -0
- package/build/sections/Stage/StageActions.js.map +1 -0
- package/build/sections/Stage/StageActions.mjs +99 -0
- package/build/sections/Stage/StageActions.mjs.map +1 -0
- package/build/sections/Stage/StageDetail.d.ts +3 -0
- package/build/sections/Stage/StageDetail.js +110 -0
- package/build/sections/Stage/StageDetail.js.map +1 -0
- package/build/sections/Stage/StageDetail.mjs +108 -0
- package/build/sections/Stage/StageDetail.mjs.map +1 -0
- package/build/sections/Stage/StageList.d.ts +3 -0
- package/build/sections/Stage/StageList.js +153 -0
- package/build/sections/Stage/StageList.js.map +1 -0
- package/build/sections/Stage/StageList.mjs +151 -0
- package/build/sections/Stage/StageList.mjs.map +1 -0
- package/build/sections/Stage/index.d.ts +6 -0
- package/build/sections/Stage/index.js +13 -0
- package/build/sections/Stage/index.mjs +6 -0
- package/build/sections/Stage/types.d.ts +22 -0
- package/build/sections/Stage/useRequireSession.d.ts +14 -0
- package/build/sections/Stage/useRequireSession.js +33 -0
- package/build/sections/Stage/useRequireSession.js.map +1 -0
- package/build/sections/Stage/useRequireSession.mjs +33 -0
- package/build/sections/Stage/useRequireSession.mjs.map +1 -0
- package/build/sections/Stage/useStage.d.ts +34 -0
- package/build/sections/Stage/useStage.js +71 -0
- package/build/sections/Stage/useStage.js.map +1 -0
- package/build/sections/Stage/useStage.mjs +65 -0
- package/build/sections/Stage/useStage.mjs.map +1 -0
- package/build/store/api.js +7 -4
- package/build/store/api.js.map +1 -1
- package/build/store/api.mjs +7 -4
- package/build/store/api.mjs.map +1 -1
- package/build/types/packageMeta.d.ts +3 -2
- package/build/utils/cli-utils.js +2 -2
- package/build/utils/cli-utils.js.map +1 -1
- package/build/utils/cli-utils.mjs +2 -2
- package/build/utils/cli-utils.mjs.map +1 -1
- package/build/utils/index.js +1 -0
- package/build/utils/index.mjs +2 -2
- package/build/utils/routes.d.ts +5 -1
- package/build/utils/routes.js +4 -0
- package/build/utils/routes.js.map +1 -1
- package/build/utils/routes.mjs +4 -0
- package/build/utils/routes.mjs.map +1 -1
- package/build/utils/schemas.d.ts +1 -0
- package/build/utils/schemas.js +4 -4
- package/build/utils/schemas.js.map +1 -1
- package/build/utils/schemas.mjs +4 -4
- package/build/utils/schemas.mjs.map +1 -1
- package/build/utils/session-id.d.ts +8 -0
- package/build/utils/session-id.js +26 -0
- package/build/utils/session-id.js.map +1 -0
- package/build/utils/session-id.mjs +26 -0
- package/build/utils/session-id.mjs.map +1 -0
- package/build/utils/token.d.ts +1 -0
- package/build/utils/token.js +12 -8
- package/build/utils/token.js.map +1 -1
- package/build/utils/token.mjs +12 -9
- package/build/utils/token.mjs.map +1 -1
- package/build/utils/url.js +1 -1
- package/build/utils/url.js.map +1 -1
- package/build/utils/url.mjs +1 -1
- package/build/utils/url.mjs.map +1 -1
- package/build/utils/utils.d.ts +10 -0
- package/build/utils/utils.js +26 -0
- package/build/utils/utils.js.map +1 -1
- package/build/utils/utils.mjs +25 -1
- package/build/utils/utils.mjs.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StageList.js","names":[],"sources":["../../../src/sections/Stage/StageList.tsx"],"sourcesContent":["import {\n Box,\n Button,\n Chip,\n CircularProgress,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TablePagination,\n TableRow,\n Typography,\n} from '@mui/material';\nimport React, { useCallback, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { Route } from '../../utils';\nimport StageActions from './StageActions';\nimport { useRequireSession } from './useRequireSession';\nimport type { StagePackageVersion } from './types';\nimport { downloadStagedTarball, useStageList } from './useStage';\n\nconst StageList: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const isLoggedIn = useRequireSession();\n const [page, setPage] = useState(0);\n const [perPage, setPerPage] = useState(10);\n const [actionError, setActionError] = useState(false);\n const { data, error, isLoading, mutate } = useStageList(page, perPage);\n\n const handleDownload = useCallback(async (item: StagePackageVersion) => {\n try {\n setActionError(false);\n await downloadStagedTarball(item);\n } catch (err) {\n console.error('Error downloading staged tarball:', err);\n setActionError(true);\n }\n }, []);\n\n // the redirect lands on the next effect; rendering the table meanwhile would\n // only show an empty state that is about to disappear\n if (!isLoggedIn) {\n return null;\n }\n\n if (isLoading) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" padding={4}>\n <CircularProgress />\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box padding={2}>\n <Typography color=\"error\" role=\"alert\">\n {t('stage.error.list')}\n </Typography>\n </Box>\n );\n }\n\n const items = data?.items ?? [];\n\n return (\n <Box padding={2}>\n <Typography component=\"h1\" gutterBottom={true} variant=\"h5\">\n {t('stage.title')}\n </Typography>\n <Typography color=\"text.secondary\" gutterBottom={true} variant=\"body2\">\n {t('stage.description')}\n </Typography>\n\n {actionError && (\n <Typography color=\"error\" role=\"alert\" variant=\"body2\">\n {t('stage.error.action')}\n </Typography>\n )}\n\n {items.length === 0 ? (\n <Typography color=\"text.secondary\" marginTop={2}>\n {t('stage.empty')}\n </Typography>\n ) : (\n <TableContainer component={Paper} sx={{ marginTop: 2, overflowX: 'auto' }}>\n <Table aria-label={t('stage.title')} data-testid=\"stage-table\" size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{t('stage.column.package')}</TableCell>\n <TableCell>{t('stage.column.version')}</TableCell>\n <TableCell>{t('stage.column.tag')}</TableCell>\n <TableCell>{t('stage.column.stagedBy')}</TableCell>\n <TableCell>{t('stage.column.date')}</TableCell>\n <TableCell align=\"right\">{t('stage.column.actions')}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {items.map((item) => (\n <TableRow data-testid={`stage-row-${item.id}`} hover={true} key={item.id}>\n <TableCell>\n <Button\n onClick={() => navigate(Route.STAGE_DETAIL.replace(':stageId', item.id))}\n size=\"small\"\n sx={{ textTransform: 'none' }}\n >\n {item.packageName}\n </Button>\n </TableCell>\n <TableCell>{item.version}</TableCell>\n <TableCell>\n <Chip label={item.tag} size=\"small\" />\n </TableCell>\n <TableCell>{item.actor}</TableCell>\n <TableCell>{new Date(item.createdAt).toLocaleString()}</TableCell>\n <TableCell align=\"right\">\n <Box alignItems=\"center\" display=\"flex\" gap={1} justifyContent=\"flex-end\">\n <Button\n data-testid={`stage-download-${item.id}`}\n onClick={() => handleDownload(item)}\n size=\"small\"\n >\n {t('stage.action.download')}\n </Button>\n <StageActions item={item} onDone={() => mutate()} />\n </Box>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n <TablePagination\n component=\"div\"\n count={data?.total ?? 0}\n onPageChange={(_event, nextPage) => setPage(nextPage)}\n onRowsPerPageChange={(event) => {\n setPerPage(Number.parseInt(event.target.value, 10));\n setPage(0);\n }}\n page={page}\n rowsPerPage={perPage}\n rowsPerPageOptions={[10, 25, 50, 100]}\n />\n </TableContainer>\n )}\n </Box>\n );\n};\n\nexport default StageList;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Route as Route$1 } from "../../utils/routes.mjs";
|
|
2
|
+
import "../../utils/index.mjs";
|
|
3
|
+
import { downloadStagedTarball, useStageList } from "./useStage.mjs";
|
|
4
|
+
import StageActions from "./StageActions.mjs";
|
|
5
|
+
import { useRequireSession } from "./useRequireSession.mjs";
|
|
6
|
+
import { useCallback, useState } from "react";
|
|
7
|
+
import { useTranslation } from "react-i18next";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { useNavigate } from "react-router";
|
|
10
|
+
import { Box, Button, Chip, CircularProgress, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, Typography } from "@mui/material";
|
|
11
|
+
//#region src/sections/Stage/StageList.tsx
|
|
12
|
+
var StageList = () => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const navigate = useNavigate();
|
|
15
|
+
const isLoggedIn = useRequireSession();
|
|
16
|
+
const [page, setPage] = useState(0);
|
|
17
|
+
const [perPage, setPerPage] = useState(10);
|
|
18
|
+
const [actionError, setActionError] = useState(false);
|
|
19
|
+
const { data, error, isLoading, mutate } = useStageList(page, perPage);
|
|
20
|
+
const handleDownload = useCallback(async (item) => {
|
|
21
|
+
try {
|
|
22
|
+
setActionError(false);
|
|
23
|
+
await downloadStagedTarball(item);
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error("Error downloading staged tarball:", err);
|
|
26
|
+
setActionError(true);
|
|
27
|
+
}
|
|
28
|
+
}, []);
|
|
29
|
+
if (!isLoggedIn) return null;
|
|
30
|
+
if (isLoading) return /* @__PURE__ */ jsx(Box, {
|
|
31
|
+
display: "flex",
|
|
32
|
+
justifyContent: "center",
|
|
33
|
+
padding: 4,
|
|
34
|
+
children: /* @__PURE__ */ jsx(CircularProgress, {})
|
|
35
|
+
});
|
|
36
|
+
if (error) return /* @__PURE__ */ jsx(Box, {
|
|
37
|
+
padding: 2,
|
|
38
|
+
children: /* @__PURE__ */ jsx(Typography, {
|
|
39
|
+
color: "error",
|
|
40
|
+
role: "alert",
|
|
41
|
+
children: t("stage.error.list")
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
const items = data?.items ?? [];
|
|
45
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
46
|
+
padding: 2,
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
49
|
+
component: "h1",
|
|
50
|
+
gutterBottom: true,
|
|
51
|
+
variant: "h5",
|
|
52
|
+
children: t("stage.title")
|
|
53
|
+
}),
|
|
54
|
+
/* @__PURE__ */ jsx(Typography, {
|
|
55
|
+
color: "text.secondary",
|
|
56
|
+
gutterBottom: true,
|
|
57
|
+
variant: "body2",
|
|
58
|
+
children: t("stage.description")
|
|
59
|
+
}),
|
|
60
|
+
actionError && /* @__PURE__ */ jsx(Typography, {
|
|
61
|
+
color: "error",
|
|
62
|
+
role: "alert",
|
|
63
|
+
variant: "body2",
|
|
64
|
+
children: t("stage.error.action")
|
|
65
|
+
}),
|
|
66
|
+
items.length === 0 ? /* @__PURE__ */ jsx(Typography, {
|
|
67
|
+
color: "text.secondary",
|
|
68
|
+
marginTop: 2,
|
|
69
|
+
children: t("stage.empty")
|
|
70
|
+
}) : /* @__PURE__ */ jsxs(TableContainer, {
|
|
71
|
+
component: Paper,
|
|
72
|
+
sx: {
|
|
73
|
+
marginTop: 2,
|
|
74
|
+
overflowX: "auto"
|
|
75
|
+
},
|
|
76
|
+
children: [/* @__PURE__ */ jsxs(Table, {
|
|
77
|
+
"aria-label": t("stage.title"),
|
|
78
|
+
"data-testid": "stage-table",
|
|
79
|
+
size: "small",
|
|
80
|
+
children: [/* @__PURE__ */ jsx(TableHead, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
81
|
+
/* @__PURE__ */ jsx(TableCell, { children: t("stage.column.package") }),
|
|
82
|
+
/* @__PURE__ */ jsx(TableCell, { children: t("stage.column.version") }),
|
|
83
|
+
/* @__PURE__ */ jsx(TableCell, { children: t("stage.column.tag") }),
|
|
84
|
+
/* @__PURE__ */ jsx(TableCell, { children: t("stage.column.stagedBy") }),
|
|
85
|
+
/* @__PURE__ */ jsx(TableCell, { children: t("stage.column.date") }),
|
|
86
|
+
/* @__PURE__ */ jsx(TableCell, {
|
|
87
|
+
align: "right",
|
|
88
|
+
children: t("stage.column.actions")
|
|
89
|
+
})
|
|
90
|
+
] }) }), /* @__PURE__ */ jsx(TableBody, { children: items.map((item) => /* @__PURE__ */ jsxs(TableRow, {
|
|
91
|
+
"data-testid": `stage-row-${item.id}`,
|
|
92
|
+
hover: true,
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Button, {
|
|
95
|
+
onClick: () => navigate(Route$1.STAGE_DETAIL.replace(":stageId", item.id)),
|
|
96
|
+
size: "small",
|
|
97
|
+
sx: { textTransform: "none" },
|
|
98
|
+
children: item.packageName
|
|
99
|
+
}) }),
|
|
100
|
+
/* @__PURE__ */ jsx(TableCell, { children: item.version }),
|
|
101
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Chip, {
|
|
102
|
+
label: item.tag,
|
|
103
|
+
size: "small"
|
|
104
|
+
}) }),
|
|
105
|
+
/* @__PURE__ */ jsx(TableCell, { children: item.actor }),
|
|
106
|
+
/* @__PURE__ */ jsx(TableCell, { children: new Date(item.createdAt).toLocaleString() }),
|
|
107
|
+
/* @__PURE__ */ jsx(TableCell, {
|
|
108
|
+
align: "right",
|
|
109
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
110
|
+
alignItems: "center",
|
|
111
|
+
display: "flex",
|
|
112
|
+
gap: 1,
|
|
113
|
+
justifyContent: "flex-end",
|
|
114
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
115
|
+
"data-testid": `stage-download-${item.id}`,
|
|
116
|
+
onClick: () => handleDownload(item),
|
|
117
|
+
size: "small",
|
|
118
|
+
children: t("stage.action.download")
|
|
119
|
+
}), /* @__PURE__ */ jsx(StageActions, {
|
|
120
|
+
item,
|
|
121
|
+
onDone: () => mutate()
|
|
122
|
+
})]
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
]
|
|
126
|
+
}, item.id)) })]
|
|
127
|
+
}), /* @__PURE__ */ jsx(TablePagination, {
|
|
128
|
+
component: "div",
|
|
129
|
+
count: data?.total ?? 0,
|
|
130
|
+
onPageChange: (_event, nextPage) => setPage(nextPage),
|
|
131
|
+
onRowsPerPageChange: (event) => {
|
|
132
|
+
setPerPage(Number.parseInt(event.target.value, 10));
|
|
133
|
+
setPage(0);
|
|
134
|
+
},
|
|
135
|
+
page,
|
|
136
|
+
rowsPerPage: perPage,
|
|
137
|
+
rowsPerPageOptions: [
|
|
138
|
+
10,
|
|
139
|
+
25,
|
|
140
|
+
50,
|
|
141
|
+
100
|
|
142
|
+
]
|
|
143
|
+
})]
|
|
144
|
+
})
|
|
145
|
+
]
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
//#endregion
|
|
149
|
+
export { StageList as default };
|
|
150
|
+
|
|
151
|
+
//# sourceMappingURL=StageList.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StageList.mjs","names":[],"sources":["../../../src/sections/Stage/StageList.tsx"],"sourcesContent":["import {\n Box,\n Button,\n Chip,\n CircularProgress,\n Paper,\n Table,\n TableBody,\n TableCell,\n TableContainer,\n TableHead,\n TablePagination,\n TableRow,\n Typography,\n} from '@mui/material';\nimport React, { useCallback, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { useNavigate } from 'react-router';\n\nimport { Route } from '../../utils';\nimport StageActions from './StageActions';\nimport { useRequireSession } from './useRequireSession';\nimport type { StagePackageVersion } from './types';\nimport { downloadStagedTarball, useStageList } from './useStage';\n\nconst StageList: React.FC = () => {\n const { t } = useTranslation();\n const navigate = useNavigate();\n const isLoggedIn = useRequireSession();\n const [page, setPage] = useState(0);\n const [perPage, setPerPage] = useState(10);\n const [actionError, setActionError] = useState(false);\n const { data, error, isLoading, mutate } = useStageList(page, perPage);\n\n const handleDownload = useCallback(async (item: StagePackageVersion) => {\n try {\n setActionError(false);\n await downloadStagedTarball(item);\n } catch (err) {\n console.error('Error downloading staged tarball:', err);\n setActionError(true);\n }\n }, []);\n\n // the redirect lands on the next effect; rendering the table meanwhile would\n // only show an empty state that is about to disappear\n if (!isLoggedIn) {\n return null;\n }\n\n if (isLoading) {\n return (\n <Box display=\"flex\" justifyContent=\"center\" padding={4}>\n <CircularProgress />\n </Box>\n );\n }\n\n if (error) {\n return (\n <Box padding={2}>\n <Typography color=\"error\" role=\"alert\">\n {t('stage.error.list')}\n </Typography>\n </Box>\n );\n }\n\n const items = data?.items ?? [];\n\n return (\n <Box padding={2}>\n <Typography component=\"h1\" gutterBottom={true} variant=\"h5\">\n {t('stage.title')}\n </Typography>\n <Typography color=\"text.secondary\" gutterBottom={true} variant=\"body2\">\n {t('stage.description')}\n </Typography>\n\n {actionError && (\n <Typography color=\"error\" role=\"alert\" variant=\"body2\">\n {t('stage.error.action')}\n </Typography>\n )}\n\n {items.length === 0 ? (\n <Typography color=\"text.secondary\" marginTop={2}>\n {t('stage.empty')}\n </Typography>\n ) : (\n <TableContainer component={Paper} sx={{ marginTop: 2, overflowX: 'auto' }}>\n <Table aria-label={t('stage.title')} data-testid=\"stage-table\" size=\"small\">\n <TableHead>\n <TableRow>\n <TableCell>{t('stage.column.package')}</TableCell>\n <TableCell>{t('stage.column.version')}</TableCell>\n <TableCell>{t('stage.column.tag')}</TableCell>\n <TableCell>{t('stage.column.stagedBy')}</TableCell>\n <TableCell>{t('stage.column.date')}</TableCell>\n <TableCell align=\"right\">{t('stage.column.actions')}</TableCell>\n </TableRow>\n </TableHead>\n <TableBody>\n {items.map((item) => (\n <TableRow data-testid={`stage-row-${item.id}`} hover={true} key={item.id}>\n <TableCell>\n <Button\n onClick={() => navigate(Route.STAGE_DETAIL.replace(':stageId', item.id))}\n size=\"small\"\n sx={{ textTransform: 'none' }}\n >\n {item.packageName}\n </Button>\n </TableCell>\n <TableCell>{item.version}</TableCell>\n <TableCell>\n <Chip label={item.tag} size=\"small\" />\n </TableCell>\n <TableCell>{item.actor}</TableCell>\n <TableCell>{new Date(item.createdAt).toLocaleString()}</TableCell>\n <TableCell align=\"right\">\n <Box alignItems=\"center\" display=\"flex\" gap={1} justifyContent=\"flex-end\">\n <Button\n data-testid={`stage-download-${item.id}`}\n onClick={() => handleDownload(item)}\n size=\"small\"\n >\n {t('stage.action.download')}\n </Button>\n <StageActions item={item} onDone={() => mutate()} />\n </Box>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n <TablePagination\n component=\"div\"\n count={data?.total ?? 0}\n onPageChange={(_event, nextPage) => setPage(nextPage)}\n onRowsPerPageChange={(event) => {\n setPerPage(Number.parseInt(event.target.value, 10));\n setPage(0);\n }}\n page={page}\n rowsPerPage={perPage}\n rowsPerPageOptions={[10, 25, 50, 100]}\n />\n </TableContainer>\n )}\n </Box>\n );\n};\n\nexport default StageList;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const require_useStage = require("./useStage.js");
|
|
2
|
+
require("./StageActions.js");
|
|
3
|
+
const require_useRequireSession = require("./useRequireSession.js");
|
|
4
|
+
const require_StageList = require("./StageList.js");
|
|
5
|
+
const require_StageDetail = require("./StageDetail.js");
|
|
6
|
+
exports.StageDetail = require_StageDetail.default;
|
|
7
|
+
exports.StageList = require_StageList.default;
|
|
8
|
+
exports.approveStagedVersion = require_useStage.approveStagedVersion;
|
|
9
|
+
exports.downloadStagedTarball = require_useStage.downloadStagedTarball;
|
|
10
|
+
exports.rejectStagedVersion = require_useStage.rejectStagedVersion;
|
|
11
|
+
exports.useRequireSession = require_useRequireSession.useRequireSession;
|
|
12
|
+
exports.useStageItem = require_useStage.useStageItem;
|
|
13
|
+
exports.useStageList = require_useStage.useStageList;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { approveStagedVersion, downloadStagedTarball, rejectStagedVersion, useStageItem, useStageList } from "./useStage.mjs";
|
|
2
|
+
import "./StageActions.mjs";
|
|
3
|
+
import { useRequireSession } from "./useRequireSession.mjs";
|
|
4
|
+
import StageList from "./StageList.mjs";
|
|
5
|
+
import StageDetail from "./StageDetail.mjs";
|
|
6
|
+
export { StageDetail, StageList, approveStagedVersion, downloadStagedTarball, rejectStagedVersion, useRequireSession, useStageItem, useStageList };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A package version awaiting review, as served by `GET /-/stage`.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the `StagePackageVersion` schema documented by npmjs.
|
|
5
|
+
*/
|
|
6
|
+
export interface StagePackageVersion {
|
|
7
|
+
id: string;
|
|
8
|
+
packageName: string;
|
|
9
|
+
version: string;
|
|
10
|
+
tag: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
actor: string;
|
|
13
|
+
actorType: string;
|
|
14
|
+
access: 'public' | 'private';
|
|
15
|
+
shasum: string;
|
|
16
|
+
}
|
|
17
|
+
export interface StagePackageList {
|
|
18
|
+
items: StagePackageVersion[];
|
|
19
|
+
page: number;
|
|
20
|
+
perPage: number;
|
|
21
|
+
total: number;
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Send anonymous visitors home instead of letting them sit on a page that
|
|
3
|
+
* cannot load.
|
|
4
|
+
*
|
|
5
|
+
* Every stage endpoint requires authentication, so rendering the view without a
|
|
6
|
+
* session only produces a `401` and an error message that says nothing useful.
|
|
7
|
+
* Login lives in a header dialog rather than on a route, so the way back is the
|
|
8
|
+
* home page.
|
|
9
|
+
*
|
|
10
|
+
* @returns whether there is a session; callers should render nothing when false,
|
|
11
|
+
* since the redirect happens on the next effect and the view would otherwise
|
|
12
|
+
* fire a request it cannot complete.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useRequireSession(): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_routes = require("../../utils/routes.js");
|
|
2
|
+
require("../../utils/index.js");
|
|
3
|
+
const require_AuthProvider = require("../../providers/AuthProvider/AuthProvider.js");
|
|
4
|
+
require("../../providers/AuthProvider/index.js");
|
|
5
|
+
let react = require("react");
|
|
6
|
+
let react_router = require("react-router");
|
|
7
|
+
//#region src/sections/Stage/useRequireSession.ts
|
|
8
|
+
/**
|
|
9
|
+
* Send anonymous visitors home instead of letting them sit on a page that
|
|
10
|
+
* cannot load.
|
|
11
|
+
*
|
|
12
|
+
* Every stage endpoint requires authentication, so rendering the view without a
|
|
13
|
+
* session only produces a `401` and an error message that says nothing useful.
|
|
14
|
+
* Login lives in a header dialog rather than on a route, so the way back is the
|
|
15
|
+
* home page.
|
|
16
|
+
*
|
|
17
|
+
* @returns whether there is a session; callers should render nothing when false,
|
|
18
|
+
* since the redirect happens on the next effect and the view would otherwise
|
|
19
|
+
* fire a request it cannot complete.
|
|
20
|
+
*/
|
|
21
|
+
function useRequireSession() {
|
|
22
|
+
const { userState } = require_AuthProvider.useAuth();
|
|
23
|
+
const navigate = (0, react_router.useNavigate)();
|
|
24
|
+
const isLoggedIn = Boolean(userState?.token);
|
|
25
|
+
(0, react.useEffect)(() => {
|
|
26
|
+
if (!isLoggedIn) navigate(require_routes.Route.ROOT);
|
|
27
|
+
}, [isLoggedIn, navigate]);
|
|
28
|
+
return isLoggedIn;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
exports.useRequireSession = useRequireSession;
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=useRequireSession.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRequireSession.js","names":[],"sources":["../../../src/sections/Stage/useRequireSession.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { useNavigate } from 'react-router';\n\nimport { useAuth } from '../../providers/AuthProvider';\nimport { Route } from '../../utils';\n\n/**\n * Send anonymous visitors home instead of letting them sit on a page that\n * cannot load.\n *\n * Every stage endpoint requires authentication, so rendering the view without a\n * session only produces a `401` and an error message that says nothing useful.\n * Login lives in a header dialog rather than on a route, so the way back is the\n * home page.\n *\n * @returns whether there is a session; callers should render nothing when false,\n * since the redirect happens on the next effect and the view would otherwise\n * fire a request it cannot complete.\n */\nexport function useRequireSession(): boolean {\n const { userState } = useAuth();\n const navigate = useNavigate();\n const isLoggedIn = Boolean(userState?.token);\n\n useEffect(() => {\n if (!isLoggedIn) {\n navigate(Route.ROOT);\n }\n }, [isLoggedIn, navigate]);\n\n return isLoggedIn;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,oBAA6B;CAC3C,MAAM,EAAE,cAAc,qBAAA,QAAQ;CAC9B,MAAM,YAAA,GAAW,aAAA,YAAA,CAAY;CAC7B,MAAM,aAAa,QAAQ,WAAW,KAAK;CAE3C,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,CAAC,YACH,SAAS,eAAA,MAAM,IAAI;CAEvB,GAAG,CAAC,YAAY,QAAQ,CAAC;CAEzB,OAAO;AACT"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Route as Route$1 } from "../../utils/routes.mjs";
|
|
2
|
+
import "../../utils/index.mjs";
|
|
3
|
+
import { useAuth } from "../../providers/AuthProvider/AuthProvider.mjs";
|
|
4
|
+
import "../../providers/AuthProvider/index.mjs";
|
|
5
|
+
import { useEffect } from "react";
|
|
6
|
+
import { useNavigate } from "react-router";
|
|
7
|
+
//#region src/sections/Stage/useRequireSession.ts
|
|
8
|
+
/**
|
|
9
|
+
* Send anonymous visitors home instead of letting them sit on a page that
|
|
10
|
+
* cannot load.
|
|
11
|
+
*
|
|
12
|
+
* Every stage endpoint requires authentication, so rendering the view without a
|
|
13
|
+
* session only produces a `401` and an error message that says nothing useful.
|
|
14
|
+
* Login lives in a header dialog rather than on a route, so the way back is the
|
|
15
|
+
* home page.
|
|
16
|
+
*
|
|
17
|
+
* @returns whether there is a session; callers should render nothing when false,
|
|
18
|
+
* since the redirect happens on the next effect and the view would otherwise
|
|
19
|
+
* fire a request it cannot complete.
|
|
20
|
+
*/
|
|
21
|
+
function useRequireSession() {
|
|
22
|
+
const { userState } = useAuth();
|
|
23
|
+
const navigate = useNavigate();
|
|
24
|
+
const isLoggedIn = Boolean(userState?.token);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!isLoggedIn) navigate(Route$1.ROOT);
|
|
27
|
+
}, [isLoggedIn, navigate]);
|
|
28
|
+
return isLoggedIn;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { useRequireSession };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=useRequireSession.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRequireSession.mjs","names":[],"sources":["../../../src/sections/Stage/useRequireSession.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport { useNavigate } from 'react-router';\n\nimport { useAuth } from '../../providers/AuthProvider';\nimport { Route } from '../../utils';\n\n/**\n * Send anonymous visitors home instead of letting them sit on a page that\n * cannot load.\n *\n * Every stage endpoint requires authentication, so rendering the view without a\n * session only produces a `401` and an error message that says nothing useful.\n * Login lives in a header dialog rather than on a route, so the way back is the\n * home page.\n *\n * @returns whether there is a session; callers should render nothing when false,\n * since the redirect happens on the next effect and the view would otherwise\n * fire a request it cannot complete.\n */\nexport function useRequireSession(): boolean {\n const { userState } = useAuth();\n const navigate = useNavigate();\n const isLoggedIn = Boolean(userState?.token);\n\n useEffect(() => {\n if (!isLoggedIn) {\n navigate(Route.ROOT);\n }\n }, [isLoggedIn, navigate]);\n\n return isLoggedIn;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,oBAA6B;CAC3C,MAAM,EAAE,cAAc,QAAQ;CAC9B,MAAM,WAAW,YAAY;CAC7B,MAAM,aAAa,QAAQ,WAAW,KAAK;CAE3C,gBAAgB;EACd,IAAI,CAAC,YACH,SAAS,QAAM,IAAI;CAEvB,GAAG,CAAC,YAAY,QAAQ,CAAC;CAEzB,OAAO;AACT"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { StagePackageList, StagePackageVersion } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Page through the staged versions the logged in user is allowed to see.
|
|
4
|
+
*
|
|
5
|
+
* The registry filters by permission before paginating, so `total` always
|
|
6
|
+
* matches what this user can actually reach.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useStageList(page: number, perPage: number): {
|
|
9
|
+
data: StagePackageList | undefined;
|
|
10
|
+
error: any;
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
mutate: import("swr").KeyedMutator<StagePackageList>;
|
|
13
|
+
};
|
|
14
|
+
/** A single staged version. */
|
|
15
|
+
export declare function useStageItem(stageId?: string): {
|
|
16
|
+
data: StagePackageVersion | undefined;
|
|
17
|
+
error: any;
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
mutate: import("swr").KeyedMutator<StagePackageVersion>;
|
|
20
|
+
};
|
|
21
|
+
/** Approve a staged version, publishing it for real. */
|
|
22
|
+
export declare function approveStagedVersion(stageId: string): Promise<{
|
|
23
|
+
message: string;
|
|
24
|
+
}>;
|
|
25
|
+
/** Reject a staged version, dropping it and its tarball. */
|
|
26
|
+
export declare function rejectStagedVersion(stageId: string): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Download the staged tarball.
|
|
29
|
+
*
|
|
30
|
+
* The endpoint is authenticated, so a plain `<a href>` would get a 401: the
|
|
31
|
+
* blob has to be fetched through the API client, which attaches the bearer
|
|
32
|
+
* token, and then handed to the browser.
|
|
33
|
+
*/
|
|
34
|
+
export declare function downloadStagedTarball(item: StagePackageVersion): Promise<void>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
2
|
+
const require_url = require("../../utils/url.js");
|
|
3
|
+
const require_routes = require("../../utils/routes.js");
|
|
4
|
+
const require_api = require("../../store/api.js");
|
|
5
|
+
const require_configuration = require("../../configuration.js");
|
|
6
|
+
const require_utils = require("../../store/utils.js");
|
|
7
|
+
const require_AuthProvider = require("../../providers/AuthProvider/AuthProvider.js");
|
|
8
|
+
require("../../providers/AuthProvider/index.js");
|
|
9
|
+
let swr = require("swr");
|
|
10
|
+
swr = require_runtime.__toESM(swr);
|
|
11
|
+
//#region src/sections/Stage/useStage.ts
|
|
12
|
+
function stageUrl(path = "") {
|
|
13
|
+
return `${require_utils.stripTrailingSlash(require_configuration.getConfiguration().base)}${require_routes.APIRoute.STAGE}${path}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Page through the staged versions the logged in user is allowed to see.
|
|
17
|
+
*
|
|
18
|
+
* The registry filters by permission before paginating, so `total` always
|
|
19
|
+
* matches what this user can actually reach.
|
|
20
|
+
*/
|
|
21
|
+
function useStageList(page, perPage) {
|
|
22
|
+
const { userState } = require_AuthProvider.useAuth();
|
|
23
|
+
const url = `${stageUrl()}?page=${page}&perPage=${perPage}`;
|
|
24
|
+
const { data, error, isLoading, mutate } = (0, swr.default)(userState?.token ? url : null, () => require_api.default.request(url));
|
|
25
|
+
return {
|
|
26
|
+
data,
|
|
27
|
+
error,
|
|
28
|
+
isLoading,
|
|
29
|
+
mutate
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** A single staged version. */
|
|
33
|
+
function useStageItem(stageId) {
|
|
34
|
+
const { userState } = require_AuthProvider.useAuth();
|
|
35
|
+
const url = stageId && userState?.token ? stageUrl(`/${stageId}`) : null;
|
|
36
|
+
const { data, error, isLoading, mutate } = (0, swr.default)(url, () => require_api.default.request(url));
|
|
37
|
+
return {
|
|
38
|
+
data,
|
|
39
|
+
error,
|
|
40
|
+
isLoading,
|
|
41
|
+
mutate
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Approve a staged version, publishing it for real. */
|
|
45
|
+
function approveStagedVersion(stageId) {
|
|
46
|
+
return require_api.default.request(stageUrl(`/${stageId}/approve`), "POST");
|
|
47
|
+
}
|
|
48
|
+
/** Reject a staged version, dropping it and its tarball. */
|
|
49
|
+
function rejectStagedVersion(stageId) {
|
|
50
|
+
return require_api.default.request(stageUrl(`/${stageId}`), "DELETE");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Download the staged tarball.
|
|
54
|
+
*
|
|
55
|
+
* The endpoint is authenticated, so a plain `<a href>` would get a 401: the
|
|
56
|
+
* blob has to be fetched through the API client, which attaches the bearer
|
|
57
|
+
* token, and then handed to the browser.
|
|
58
|
+
*/
|
|
59
|
+
async function downloadStagedTarball(item) {
|
|
60
|
+
const blob = await require_api.default.request(stageUrl(`/${item.id}/tarball`), "GET", { headers: { accept: "application/octet-stream" } });
|
|
61
|
+
const safeName = item.packageName.replace("@", "").replace("/", "-");
|
|
62
|
+
require_url.downloadFile(blob, `${safeName}-${item.version}.tgz`);
|
|
63
|
+
}
|
|
64
|
+
//#endregion
|
|
65
|
+
exports.approveStagedVersion = approveStagedVersion;
|
|
66
|
+
exports.downloadStagedTarball = downloadStagedTarball;
|
|
67
|
+
exports.rejectStagedVersion = rejectStagedVersion;
|
|
68
|
+
exports.useStageItem = useStageItem;
|
|
69
|
+
exports.useStageList = useStageList;
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=useStage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStage.js","names":[],"sources":["../../../src/sections/Stage/useStage.ts"],"sourcesContent":["import useSWR from 'swr';\n\nimport { useAuth } from '../../providers/AuthProvider';\nimport API from '../../store/api';\nimport { getConfiguration } from '../../configuration';\nimport { stripTrailingSlash } from '../../store/utils';\nimport { APIRoute } from '../../utils/routes';\nimport { downloadFile } from '../../utils/url';\nimport type { StagePackageList, StagePackageVersion } from './types';\n\nfunction stageUrl(path = ''): string {\n const basePath = stripTrailingSlash(getConfiguration().base);\n return `${basePath}${APIRoute.STAGE}${path}`;\n}\n\n/**\n * Page through the staged versions the logged in user is allowed to see.\n *\n * The registry filters by permission before paginating, so `total` always\n * matches what this user can actually reach.\n */\nexport function useStageList(page: number, perPage: number) {\n const { userState } = useAuth();\n const url = `${stageUrl()}?page=${page}&perPage=${perPage}`;\n // a null key tells SWR not to fetch: without a session the request can only\n // come back 401\n const { data, error, isLoading, mutate } = useSWR<StagePackageList>(\n userState?.token ? url : null,\n () => API.request<StagePackageList>(url)\n );\n\n return { data, error, isLoading, mutate };\n}\n\n/** A single staged version. */\nexport function useStageItem(stageId?: string) {\n const { userState } = useAuth();\n const url = stageId && userState?.token ? stageUrl(`/${stageId}`) : null;\n const { data, error, isLoading, mutate } = useSWR<StagePackageVersion>(url, () =>\n API.request<StagePackageVersion>(url as string)\n );\n\n return { data, error, isLoading, mutate };\n}\n\n/** Approve a staged version, publishing it for real. */\nexport function approveStagedVersion(stageId: string): Promise<{ message: string }> {\n return API.request<{ message: string }>(stageUrl(`/${stageId}/approve`), 'POST');\n}\n\n/** Reject a staged version, dropping it and its tarball. */\nexport function rejectStagedVersion(stageId: string): Promise<void> {\n return API.request<void>(stageUrl(`/${stageId}`), 'DELETE');\n}\n\n/**\n * Download the staged tarball.\n *\n * The endpoint is authenticated, so a plain `<a href>` would get a 401: the\n * blob has to be fetched through the API client, which attaches the bearer\n * token, and then handed to the browser.\n */\nexport async function downloadStagedTarball(item: StagePackageVersion): Promise<void> {\n const blob = await API.request<Blob>(stageUrl(`/${item.id}/tarball`), 'GET', {\n headers: { accept: 'application/octet-stream' },\n });\n const safeName = item.packageName.replace('@', '').replace('/', '-');\n downloadFile(blob, `${safeName}-${item.version}.tgz`);\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAS,SAAS,OAAO,IAAY;CAEnC,OAAO,GADU,cAAA,mBAAmB,sBAAA,iBAAiB,CAAC,CAAC,IAC7C,IAAW,eAAA,SAAS,QAAQ;AACxC;;;;;;;AAQA,SAAgB,aAAa,MAAc,SAAiB;CAC1D,MAAM,EAAE,cAAc,qBAAA,QAAQ;CAC9B,MAAM,MAAM,GAAG,SAAS,EAAE,QAAQ,KAAK,WAAW;CAGlD,MAAM,EAAE,MAAM,OAAO,WAAW,YAAA,GAAW,IAAA,QAAA,CACzC,WAAW,QAAQ,MAAM,YACnB,YAAA,QAAI,QAA0B,GAAG,CACzC;CAEA,OAAO;EAAE;EAAM;EAAO;EAAW;CAAO;AAC1C;;AAGA,SAAgB,aAAa,SAAkB;CAC7C,MAAM,EAAE,cAAc,qBAAA,QAAQ;CAC9B,MAAM,MAAM,WAAW,WAAW,QAAQ,SAAS,IAAI,SAAS,IAAI;CACpE,MAAM,EAAE,MAAM,OAAO,WAAW,YAAA,GAAW,IAAA,QAAA,CAA4B,WACrE,YAAA,QAAI,QAA6B,GAAa,CAChD;CAEA,OAAO;EAAE;EAAM;EAAO;EAAW;CAAO;AAC1C;;AAGA,SAAgB,qBAAqB,SAA+C;CAClF,OAAO,YAAA,QAAI,QAA6B,SAAS,IAAI,QAAQ,SAAS,GAAG,MAAM;AACjF;;AAGA,SAAgB,oBAAoB,SAAgC;CAClE,OAAO,YAAA,QAAI,QAAc,SAAS,IAAI,SAAS,GAAG,QAAQ;AAC5D;;;;;;;;AASA,eAAsB,sBAAsB,MAA0C;CACpF,MAAM,OAAO,MAAM,YAAA,QAAI,QAAc,SAAS,IAAI,KAAK,GAAG,SAAS,GAAG,OAAO,EAC3E,SAAS,EAAE,QAAQ,2BAA2B,EAChD,CAAC;CACD,MAAM,WAAW,KAAK,YAAY,QAAQ,KAAK,EAAE,CAAC,CAAC,QAAQ,KAAK,GAAG;CACnE,YAAA,aAAa,MAAM,GAAG,SAAS,GAAG,KAAK,QAAQ,KAAK;AACtD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { downloadFile } from "../../utils/url.mjs";
|
|
2
|
+
import { APIRoute } from "../../utils/routes.mjs";
|
|
3
|
+
import api_default from "../../store/api.mjs";
|
|
4
|
+
import { getConfiguration } from "../../configuration.mjs";
|
|
5
|
+
import { stripTrailingSlash } from "../../store/utils.mjs";
|
|
6
|
+
import { useAuth } from "../../providers/AuthProvider/AuthProvider.mjs";
|
|
7
|
+
import "../../providers/AuthProvider/index.mjs";
|
|
8
|
+
import useSWR from "swr";
|
|
9
|
+
//#region src/sections/Stage/useStage.ts
|
|
10
|
+
function stageUrl(path = "") {
|
|
11
|
+
return `${stripTrailingSlash(getConfiguration().base)}${APIRoute.STAGE}${path}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Page through the staged versions the logged in user is allowed to see.
|
|
15
|
+
*
|
|
16
|
+
* The registry filters by permission before paginating, so `total` always
|
|
17
|
+
* matches what this user can actually reach.
|
|
18
|
+
*/
|
|
19
|
+
function useStageList(page, perPage) {
|
|
20
|
+
const { userState } = useAuth();
|
|
21
|
+
const url = `${stageUrl()}?page=${page}&perPage=${perPage}`;
|
|
22
|
+
const { data, error, isLoading, mutate } = useSWR(userState?.token ? url : null, () => api_default.request(url));
|
|
23
|
+
return {
|
|
24
|
+
data,
|
|
25
|
+
error,
|
|
26
|
+
isLoading,
|
|
27
|
+
mutate
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** A single staged version. */
|
|
31
|
+
function useStageItem(stageId) {
|
|
32
|
+
const { userState } = useAuth();
|
|
33
|
+
const url = stageId && userState?.token ? stageUrl(`/${stageId}`) : null;
|
|
34
|
+
const { data, error, isLoading, mutate } = useSWR(url, () => api_default.request(url));
|
|
35
|
+
return {
|
|
36
|
+
data,
|
|
37
|
+
error,
|
|
38
|
+
isLoading,
|
|
39
|
+
mutate
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** Approve a staged version, publishing it for real. */
|
|
43
|
+
function approveStagedVersion(stageId) {
|
|
44
|
+
return api_default.request(stageUrl(`/${stageId}/approve`), "POST");
|
|
45
|
+
}
|
|
46
|
+
/** Reject a staged version, dropping it and its tarball. */
|
|
47
|
+
function rejectStagedVersion(stageId) {
|
|
48
|
+
return api_default.request(stageUrl(`/${stageId}`), "DELETE");
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Download the staged tarball.
|
|
52
|
+
*
|
|
53
|
+
* The endpoint is authenticated, so a plain `<a href>` would get a 401: the
|
|
54
|
+
* blob has to be fetched through the API client, which attaches the bearer
|
|
55
|
+
* token, and then handed to the browser.
|
|
56
|
+
*/
|
|
57
|
+
async function downloadStagedTarball(item) {
|
|
58
|
+
const blob = await api_default.request(stageUrl(`/${item.id}/tarball`), "GET", { headers: { accept: "application/octet-stream" } });
|
|
59
|
+
const safeName = item.packageName.replace("@", "").replace("/", "-");
|
|
60
|
+
downloadFile(blob, `${safeName}-${item.version}.tgz`);
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { approveStagedVersion, downloadStagedTarball, rejectStagedVersion, useStageItem, useStageList };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=useStage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStage.mjs","names":[],"sources":["../../../src/sections/Stage/useStage.ts"],"sourcesContent":["import useSWR from 'swr';\n\nimport { useAuth } from '../../providers/AuthProvider';\nimport API from '../../store/api';\nimport { getConfiguration } from '../../configuration';\nimport { stripTrailingSlash } from '../../store/utils';\nimport { APIRoute } from '../../utils/routes';\nimport { downloadFile } from '../../utils/url';\nimport type { StagePackageList, StagePackageVersion } from './types';\n\nfunction stageUrl(path = ''): string {\n const basePath = stripTrailingSlash(getConfiguration().base);\n return `${basePath}${APIRoute.STAGE}${path}`;\n}\n\n/**\n * Page through the staged versions the logged in user is allowed to see.\n *\n * The registry filters by permission before paginating, so `total` always\n * matches what this user can actually reach.\n */\nexport function useStageList(page: number, perPage: number) {\n const { userState } = useAuth();\n const url = `${stageUrl()}?page=${page}&perPage=${perPage}`;\n // a null key tells SWR not to fetch: without a session the request can only\n // come back 401\n const { data, error, isLoading, mutate } = useSWR<StagePackageList>(\n userState?.token ? url : null,\n () => API.request<StagePackageList>(url)\n );\n\n return { data, error, isLoading, mutate };\n}\n\n/** A single staged version. */\nexport function useStageItem(stageId?: string) {\n const { userState } = useAuth();\n const url = stageId && userState?.token ? stageUrl(`/${stageId}`) : null;\n const { data, error, isLoading, mutate } = useSWR<StagePackageVersion>(url, () =>\n API.request<StagePackageVersion>(url as string)\n );\n\n return { data, error, isLoading, mutate };\n}\n\n/** Approve a staged version, publishing it for real. */\nexport function approveStagedVersion(stageId: string): Promise<{ message: string }> {\n return API.request<{ message: string }>(stageUrl(`/${stageId}/approve`), 'POST');\n}\n\n/** Reject a staged version, dropping it and its tarball. */\nexport function rejectStagedVersion(stageId: string): Promise<void> {\n return API.request<void>(stageUrl(`/${stageId}`), 'DELETE');\n}\n\n/**\n * Download the staged tarball.\n *\n * The endpoint is authenticated, so a plain `<a href>` would get a 401: the\n * blob has to be fetched through the API client, which attaches the bearer\n * token, and then handed to the browser.\n */\nexport async function downloadStagedTarball(item: StagePackageVersion): Promise<void> {\n const blob = await API.request<Blob>(stageUrl(`/${item.id}/tarball`), 'GET', {\n headers: { accept: 'application/octet-stream' },\n });\n const safeName = item.packageName.replace('@', '').replace('/', '-');\n downloadFile(blob, `${safeName}-${item.version}.tgz`);\n}\n"],"mappings":";;;;;;;;;AAUA,SAAS,SAAS,OAAO,IAAY;CAEnC,OAAO,GADU,mBAAmB,iBAAiB,CAAC,CAAC,IAC7C,IAAW,SAAS,QAAQ;AACxC;;;;;;;AAQA,SAAgB,aAAa,MAAc,SAAiB;CAC1D,MAAM,EAAE,cAAc,QAAQ;CAC9B,MAAM,MAAM,GAAG,SAAS,EAAE,QAAQ,KAAK,WAAW;CAGlD,MAAM,EAAE,MAAM,OAAO,WAAW,WAAW,OACzC,WAAW,QAAQ,MAAM,YACnB,YAAI,QAA0B,GAAG,CACzC;CAEA,OAAO;EAAE;EAAM;EAAO;EAAW;CAAO;AAC1C;;AAGA,SAAgB,aAAa,SAAkB;CAC7C,MAAM,EAAE,cAAc,QAAQ;CAC9B,MAAM,MAAM,WAAW,WAAW,QAAQ,SAAS,IAAI,SAAS,IAAI;CACpE,MAAM,EAAE,MAAM,OAAO,WAAW,WAAW,OAA4B,WACrE,YAAI,QAA6B,GAAa,CAChD;CAEA,OAAO;EAAE;EAAM;EAAO;EAAW;CAAO;AAC1C;;AAGA,SAAgB,qBAAqB,SAA+C;CAClF,OAAO,YAAI,QAA6B,SAAS,IAAI,QAAQ,SAAS,GAAG,MAAM;AACjF;;AAGA,SAAgB,oBAAoB,SAAgC;CAClE,OAAO,YAAI,QAAc,SAAS,IAAI,SAAS,GAAG,QAAQ;AAC5D;;;;;;;;AASA,eAAsB,sBAAsB,MAA0C;CACpF,MAAM,OAAO,MAAM,YAAI,QAAc,SAAS,IAAI,KAAK,GAAG,SAAS,GAAG,OAAO,EAC3E,SAAS,EAAE,QAAQ,2BAA2B,EAChD,CAAC;CACD,MAAM,WAAW,KAAK,YAAY,QAAQ,KAAK,EAAE,CAAC,CAAC,QAAQ,KAAK,GAAG;CACnE,aAAa,MAAM,GAAG,SAAS,GAAG,KAAK,QAAQ,KAAK;AACtD"}
|
package/build/store/api.js
CHANGED
|
@@ -21,6 +21,11 @@ function handleResponseType(response) {
|
|
|
21
21
|
response.blob(),
|
|
22
22
|
response.status
|
|
23
23
|
]);
|
|
24
|
+
if (contentType?.includes("application/octet-stream") || contentType?.includes("application/gzip")) return Promise.all([
|
|
25
|
+
response.ok,
|
|
26
|
+
response.blob(),
|
|
27
|
+
response.status
|
|
28
|
+
]);
|
|
24
29
|
if (contentType?.includes("application/json")) return Promise.all([
|
|
25
30
|
response.ok,
|
|
26
31
|
response.json(),
|
|
@@ -48,11 +53,9 @@ var API = class {
|
|
|
48
53
|
request(url, method = "GET", options = { headers: {} }) {
|
|
49
54
|
const token = require_storage.default.getItem("token");
|
|
50
55
|
const headers = new Headers(options.headers);
|
|
51
|
-
if (token && headers.has(AuthHeader) === false) {
|
|
52
|
-
headers.set(AuthHeader, `Bearer ${token}`);
|
|
53
|
-
options.headers = headers;
|
|
54
|
-
}
|
|
56
|
+
if (token && headers.has(AuthHeader) === false) headers.set(AuthHeader, `Bearer ${token}`);
|
|
55
57
|
headers.set("x-client", "verdaccio-ui");
|
|
58
|
+
options.headers = headers;
|
|
56
59
|
return new Promise((resolve, reject) => {
|
|
57
60
|
fetch(url, {
|
|
58
61
|
method,
|
package/build/store/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","names":[],"sources":["../../src/store/api.ts"],"sourcesContent":["import storage from './storage';\n\nexport class CustomError extends Error {\n code: number;\n\n constructor(message: string, code?: number) {\n super(message);\n this.name = 'CustomError';\n this.code = code ?? 500;\n }\n}\n\n/**\n * Handles response according to content type\n * @param {object} response\n * @returns {promise}\n */\nexport function handleResponseType(response: Response): Promise<[boolean, any, number]> {\n if (response.headers) {\n const contentType = response.headers.get('Content-Type');\n if (contentType?.includes('application/pdf')) {\n return Promise.all([response.ok, response.blob(), response.status]);\n }\n if (contentType?.includes('application/json')) {\n return Promise.all([response.ok, response.json(), response.status]);\n }\n // it includes all text types\n if (contentType?.includes('text/')) {\n return Promise.all([response.ok, response.text(), response.status]);\n }\n\n // unfortunately on download files there is no header available\n if (response.url && response.url.endsWith('.tgz') === true) {\n return Promise.all([response.ok, response.blob(), response.status]);\n }\n }\n\n // error handling\n return Promise.all([response.ok, response.text(), response.status]);\n}\n\nconst AuthHeader = 'Authorization';\n\nclass API {\n public request<T>(\n url: string,\n method = 'GET',\n options: RequestInit = { headers: {} }\n ): Promise<T> {\n const token = storage.getItem('token');\n const headers = new Headers(options.headers);\n\n if (token && headers.has(AuthHeader) === false) {\n headers.set(AuthHeader, `Bearer ${token}`);\n
|
|
1
|
+
{"version":3,"file":"api.js","names":[],"sources":["../../src/store/api.ts"],"sourcesContent":["import storage from './storage';\n\nexport class CustomError extends Error {\n code: number;\n\n constructor(message: string, code?: number) {\n super(message);\n this.name = 'CustomError';\n this.code = code ?? 500;\n }\n}\n\n/**\n * Handles response according to content type\n * @param {object} response\n * @returns {promise}\n */\nexport function handleResponseType(response: Response): Promise<[boolean, any, number]> {\n if (response.headers) {\n const contentType = response.headers.get('Content-Type');\n if (contentType?.includes('application/pdf')) {\n return Promise.all([response.ok, response.blob(), response.status]);\n }\n // binary payloads (e.g. staged tarballs, served without a .tgz url) must\n // never be decoded as text: invalid utf-8 bytes become U+FFFD and the\n // downloaded archive is corrupted\n if (\n contentType?.includes('application/octet-stream') ||\n contentType?.includes('application/gzip')\n ) {\n return Promise.all([response.ok, response.blob(), response.status]);\n }\n if (contentType?.includes('application/json')) {\n return Promise.all([response.ok, response.json(), response.status]);\n }\n // it includes all text types\n if (contentType?.includes('text/')) {\n return Promise.all([response.ok, response.text(), response.status]);\n }\n\n // unfortunately on download files there is no header available\n if (response.url && response.url.endsWith('.tgz') === true) {\n return Promise.all([response.ok, response.blob(), response.status]);\n }\n }\n\n // error handling\n return Promise.all([response.ok, response.text(), response.status]);\n}\n\nconst AuthHeader = 'Authorization';\n\nclass API {\n public request<T>(\n url: string,\n method = 'GET',\n options: RequestInit = { headers: {} }\n ): Promise<T> {\n const token = storage.getItem('token');\n const headers = new Headers(options.headers);\n\n if (token && headers.has(AuthHeader) === false) {\n headers.set(AuthHeader, `Bearer ${token}`);\n }\n\n headers.set('x-client', 'verdaccio-ui');\n // assign unconditionally: doing it only inside the token branch dropped\n // the x-client header for anonymous requests\n options.headers = headers;\n\n return new Promise((resolve, reject) => {\n fetch(url, {\n method,\n credentials: 'same-origin',\n signal: options.signal,\n ...options,\n })\n .then(handleResponseType)\n .then((response) => {\n const [ok, data, status] = response;\n if (ok === true) {\n resolve(data);\n } else {\n const message =\n typeof data === 'string' ? data : (data?.error ?? data?.message ?? 'Unknown error');\n reject(new CustomError(message, status));\n }\n })\n .catch((error) => {\n reject(error);\n });\n });\n }\n}\n\nexport default new API();\n"],"mappings":";;AAEA,IAAa,cAAb,cAAiC,MAAM;CACrC;CAEA,YAAY,SAAiB,MAAe;EAC1C,MAAM,OAAO;EACb,KAAK,OAAO;EACZ,KAAK,OAAO,QAAQ;CACtB;AACF;;;;;;AAOA,SAAgB,mBAAmB,UAAqD;CACtF,IAAI,SAAS,SAAS;EACpB,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;EACvD,IAAI,aAAa,SAAS,iBAAiB,GACzC,OAAO,QAAQ,IAAI;GAAC,SAAS;GAAI,SAAS,KAAK;GAAG,SAAS;EAAM,CAAC;EAKpE,IACE,aAAa,SAAS,0BAA0B,KAChD,aAAa,SAAS,kBAAkB,GAExC,OAAO,QAAQ,IAAI;GAAC,SAAS;GAAI,SAAS,KAAK;GAAG,SAAS;EAAM,CAAC;EAEpE,IAAI,aAAa,SAAS,kBAAkB,GAC1C,OAAO,QAAQ,IAAI;GAAC,SAAS;GAAI,SAAS,KAAK;GAAG,SAAS;EAAM,CAAC;EAGpE,IAAI,aAAa,SAAS,OAAO,GAC/B,OAAO,QAAQ,IAAI;GAAC,SAAS;GAAI,SAAS,KAAK;GAAG,SAAS;EAAM,CAAC;EAIpE,IAAI,SAAS,OAAO,SAAS,IAAI,SAAS,MAAM,MAAM,MACpD,OAAO,QAAQ,IAAI;GAAC,SAAS;GAAI,SAAS,KAAK;GAAG,SAAS;EAAM,CAAC;CAEtE;CAGA,OAAO,QAAQ,IAAI;EAAC,SAAS;EAAI,SAAS,KAAK;EAAG,SAAS;CAAM,CAAC;AACpE;AAEA,IAAM,aAAa;AAEnB,IAAM,MAAN,MAAU;CACR,QACE,KACA,SAAS,OACT,UAAuB,EAAE,SAAS,CAAC,EAAE,GACzB;EACZ,MAAM,QAAQ,gBAAA,QAAQ,QAAQ,OAAO;EACrC,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;EAE3C,IAAI,SAAS,QAAQ,IAAI,UAAU,MAAM,OACvC,QAAQ,IAAI,YAAY,UAAU,OAAO;EAG3C,QAAQ,IAAI,YAAY,cAAc;EAGtC,QAAQ,UAAU;EAElB,OAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,KAAK;IACT;IACA,aAAa;IACb,QAAQ,QAAQ;IAChB,GAAG;GACL,CAAC,CAAC,CACC,KAAK,kBAAkB,CAAC,CACxB,MAAM,aAAa;IAClB,MAAM,CAAC,IAAI,MAAM,UAAU;IAC3B,IAAI,OAAO,MACT,QAAQ,IAAI;SAIZ,OAAO,IAAI,YADT,OAAO,SAAS,WAAW,OAAQ,MAAM,SAAS,MAAM,WAAW,iBACrC,MAAM,CAAC;GAE3C,CAAC,CAAC,CACD,OAAO,UAAU;IAChB,OAAO,KAAK;GACd,CAAC;EACL,CAAC;CACH;AACF;AAEA,IAAA,cAAe,IAAI,IAAI"}
|
package/build/store/api.mjs
CHANGED
|
@@ -21,6 +21,11 @@ function handleResponseType(response) {
|
|
|
21
21
|
response.blob(),
|
|
22
22
|
response.status
|
|
23
23
|
]);
|
|
24
|
+
if (contentType?.includes("application/octet-stream") || contentType?.includes("application/gzip")) return Promise.all([
|
|
25
|
+
response.ok,
|
|
26
|
+
response.blob(),
|
|
27
|
+
response.status
|
|
28
|
+
]);
|
|
24
29
|
if (contentType?.includes("application/json")) return Promise.all([
|
|
25
30
|
response.ok,
|
|
26
31
|
response.json(),
|
|
@@ -48,11 +53,9 @@ var API = class {
|
|
|
48
53
|
request(url, method = "GET", options = { headers: {} }) {
|
|
49
54
|
const token = storage_default.getItem("token");
|
|
50
55
|
const headers = new Headers(options.headers);
|
|
51
|
-
if (token && headers.has(AuthHeader) === false) {
|
|
52
|
-
headers.set(AuthHeader, `Bearer ${token}`);
|
|
53
|
-
options.headers = headers;
|
|
54
|
-
}
|
|
56
|
+
if (token && headers.has(AuthHeader) === false) headers.set(AuthHeader, `Bearer ${token}`);
|
|
55
57
|
headers.set("x-client", "verdaccio-ui");
|
|
58
|
+
options.headers = headers;
|
|
56
59
|
return new Promise((resolve, reject) => {
|
|
57
60
|
fetch(url, {
|
|
58
61
|
method,
|