diff --git a/.changeset/breezy-dolphins-lay.md b/.changeset/breezy-dolphins-lay.md deleted file mode 100644 index 0197979531..0000000000 --- a/.changeset/breezy-dolphins-lay.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@backstage/plugin-auth-backend': patch ---- - -AWS-ALB: update provider to the latest changes described [here](https://backstage.io/docs/auth/identity-resolver). - -This removes the `ExperimentalIdentityResolver` type in favor of `SignInResolver` and `AuthHandler`. -The AWS ALB provider can now be configured in the same way as the Google provider in the example. diff --git a/.changeset/cool-deers-cough.md b/.changeset/cool-deers-cough.md deleted file mode 100644 index 4f4921db8d..0000000000 --- a/.changeset/cool-deers-cough.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'@backstage/plugin-catalog-react': minor -'@backstage/plugin-catalog': patch ---- - -Introduce a new `StarredEntitiesApi` that is used in the `useStarredEntities` hook. -The `@backstage/plugin-catalog` installs a default implementation that is backed by the `StorageApi`, but one can also override the `starredEntitiesApiRef`. - -This change also updates the storage format from a custom string to an entity reference and moves the location in the local storage. -A migration will convert the previously starred entities to the location on the first load of Backstage. diff --git a/.changeset/dirty-balloons-develop.md b/.changeset/dirty-balloons-develop.md deleted file mode 100644 index 6dd9005cca..0000000000 --- a/.changeset/dirty-balloons-develop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-api-docs': patch ---- - -Bump `swagger-ui-react` to `^4.0.0-rc.3`. diff --git a/.changeset/flat-camels-scream.md b/.changeset/flat-camels-scream.md deleted file mode 100644 index 2c49af5010..0000000000 --- a/.changeset/flat-camels-scream.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/integration': patch ---- - -By replacing `\n` with a newline for GitHub Apps private keys, this allows users to store the private key as an environment variable and reference it in the YAML. diff --git a/.changeset/funny-dolls-draw.md b/.changeset/funny-dolls-draw.md deleted file mode 100644 index f194b30750..0000000000 --- a/.changeset/funny-dolls-draw.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@backstage/create-app': patch ---- - -The scaffolder plugin has just released the beta 3 version of software templates, which replaces the handlebars templating syntax. As part of this change, the template entity schema is no longer included in the core catalog-model as with previous versions. The decoupling of the template entities version will allow us to more easily make updates in the future. - -In order to use the new beta 3 templates, the following changes are **required** for any existing installation, inside `packages/backend/src/plugins/catalog.ts`: - -```diff -+import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; - -... - - const builder = await CatalogBuilder.create(env); -+ builder.addProcessor(new ScaffolderEntitiesProcessor()); - const { processingEngine, router } = await builder.build(); -``` - -If you're interested in learning more about creating custom kinds, please check out the [extending the model](https://backstage.io/docs/features/software-catalog/extending-the-model) documentation. diff --git a/.changeset/gorgeous-laws-report.md b/.changeset/gorgeous-laws-report.md deleted file mode 100644 index 47e5aa301f..0000000000 --- a/.changeset/gorgeous-laws-report.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/plugin-catalog-react': patch -'@backstage/plugin-scaffolder': patch ---- - -Introduce a `useStarredEntity` hook to check if a single entity is starred. -It provides a more efficient implementation compared to the `useStarredEntities` hook, because the rendering is only triggered if the selected entity is starred, not if _any_ entity is starred. diff --git a/.changeset/happy-hotels-explain.md b/.changeset/happy-hotels-explain.md deleted file mode 100644 index ede18c3187..0000000000 --- a/.changeset/happy-hotels-explain.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@backstage/core-app-api': patch -'@backstage/core-components': patch -'@backstage/theme': patch ---- - -Internal refactor to avoid importing all of `@material-ui/core`. diff --git a/.changeset/hip-suns-fix.md b/.changeset/hip-suns-fix.md deleted file mode 100644 index 4555c7b179..0000000000 --- a/.changeset/hip-suns-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -update the null check to use the optional chaining operator in case of non-null assertion operator is not working in function extractInitials(values: string) diff --git a/.changeset/honest-drinks-eat.md b/.changeset/honest-drinks-eat.md deleted file mode 100644 index b6cb168e00..0000000000 --- a/.changeset/honest-drinks-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-graphiql': patch ---- - -Add experimental `experimentalInstallationRecipe` to `package.json`. diff --git a/.changeset/hungry-bugs-drop.md b/.changeset/hungry-bugs-drop.md deleted file mode 100644 index d13e21d446..0000000000 --- a/.changeset/hungry-bugs-drop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/core-components': patch ---- - -Resolve a warning in ` + + + ); +}; diff --git a/plugins/bazaar/src/components/DeleteProjectDialog/index.ts b/plugins/bazaar/src/components/DeleteProjectDialog/index.ts new file mode 100644 index 0000000000..fdd488aeb9 --- /dev/null +++ b/plugins/bazaar/src/components/DeleteProjectDialog/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { DeleteProjectDialog } from './DeleteProjectDialog'; diff --git a/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx b/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx new file mode 100644 index 0000000000..172bdf548d --- /dev/null +++ b/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx @@ -0,0 +1,82 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useState, useEffect } from 'react'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { useApi } from '@backstage/core-plugin-api'; +import { ProjectDialog } from '../ProjectDialog'; +import { BazaarProject, FormValues } from '../../types'; +import { bazaarApiRef } from '../../api'; + +type Props = { + entity: Entity; + bazaarProject: BazaarProject; + fetchBazaarProject: () => Promise; + open: boolean; + handleClose: () => void; + isAddForm: boolean; +}; + +export const EditProjectDialog = ({ + entity, + bazaarProject, + fetchBazaarProject, + open, + handleClose, +}: Props) => { + const [defaultValues, setDefaultValues] = useState({ + announcement: bazaarProject.announcement, + community: bazaarProject.community, + status: bazaarProject.status, + }); + + const bazaarApi = useApi(bazaarApiRef); + + useEffect(() => { + setDefaultValues({ + announcement: bazaarProject.announcement, + community: bazaarProject.community, + status: bazaarProject.status, + }); + }, [bazaarProject]); + + const handleSave: any = async (getValues: any, _: any) => { + const formValues = getValues(); + + const updateResponse = await bazaarApi.updateMetadata({ + name: entity.metadata.name, + entityRef: stringifyEntityRef(entity), + announcement: formValues.announcement, + status: formValues.status, + community: formValues.community, + membersCount: bazaarProject.membersCount, + }); + + if (updateResponse.status === 'ok') fetchBazaarProject(); + handleClose(); + }; + + return ( + + ); +}; diff --git a/plugins/bazaar/src/components/EditProjectDialog/index.ts b/plugins/bazaar/src/components/EditProjectDialog/index.ts new file mode 100644 index 0000000000..4c48c375ce --- /dev/null +++ b/plugins/bazaar/src/components/EditProjectDialog/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { EditProjectDialog } from './EditProjectDialog'; diff --git a/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx b/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx new file mode 100644 index 0000000000..6bf844d592 --- /dev/null +++ b/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx @@ -0,0 +1,324 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useState, useEffect } from 'react'; +import { + Grid, + makeStyles, + Card, + CardContent, + CardHeader, + Typography, + Divider, + IconButton, + Popover, + MenuList, + MenuItem, + ListItemText, + Link, +} from '@material-ui/core'; +import { + Progress, + HeaderIconLinkRow, + IconLinkVerticalProps, + Avatar, +} from '@backstage/core-components'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { AboutField } from '@backstage/plugin-catalog'; +import { StatusTag } from '../StatusTag'; +import EditIcon from '@material-ui/icons/Edit'; +import ChatIcon from '@material-ui/icons/Chat'; +import PersonAddIcon from '@material-ui/icons/PersonAdd'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; +import DeleteIcon from '@material-ui/icons/Delete'; +import { EditProjectDialog } from '../EditProjectDialog'; +import { DeleteProjectDialog } from '../DeleteProjectDialog'; +import ExitToAppIcon from '@material-ui/icons/ExitToApp'; +import { useApi, identityApiRef } from '@backstage/core-plugin-api'; +import { Member, BazaarProject } from '../../types'; +import { bazaarApiRef } from '../../api'; +import { Alert } from '@material-ui/lab'; +import { useAsyncFn } from 'react-use'; + +const useStyles = makeStyles({ + description: { + wordBreak: 'break-word', + }, + icon: { + marginRight: '1.75rem', + }, + link: { + color: '#9cc9ff', + '&:hover': { + textDecoration: 'underline', + }, + }, + memberLink: { + display: 'block', + marginBottom: '0.3rem', + }, +}); + +const sortMembers = (m1: Member, m2: Member) => { + return new Date(m2.joinDate!).getTime() - new Date(m1.joinDate!).getTime(); +}; + +export const EntityBazaarInfoCard = () => { + const { entity } = useEntity(); + const classes = useStyles(); + const bazaarApi = useApi(bazaarApiRef); + const identity = useApi(identityApiRef); + const [anchorEl, setAnchorEl] = useState(); + const [open, setOpen] = useState(false); + const [popoverOpen, setPopoverOpen] = useState(false); + const [openDelete, setOpenDelete] = useState(false); + const [isMember, setIsMember] = useState(false); + const [isBazaar, setIsBazaar] = useState(false); + const [members, fetchMembers] = useAsyncFn(async () => { + const response = await bazaarApi.getMembers(entity); + + const dbMembers = response.data.map((obj: any) => { + const member: Member = { + userId: obj.user_id, + entityRef: obj.entity_ref, + joinDate: obj.join_date, + picture: obj.picture, + }; + + return member; + }); + + dbMembers.sort(sortMembers); + + return dbMembers; + }); + + const [bazaarProject, fetchBazaarProject] = useAsyncFn(async () => { + const response = await bazaarApi.getMetadata(entity); + + if (response) { + const metadata = await response.json().then((resp: any) => resp.data[0]); + + if (metadata) { + return { + entityRef: metadata.entity_ref, + name: metadata.name, + community: metadata.community, + announcement: metadata.announcement, + status: metadata.status, + updatedAt: metadata.updated_at, + membersCount: metadata.members_count, + } as BazaarProject; + } + } + return null; + }); + + useEffect(() => { + fetchMembers(); + fetchBazaarProject(); + }, [fetchMembers, fetchBazaarProject]); + + useEffect(() => { + const isBazaarMember = + members?.value + ?.map((member: Member) => member.userId) + .indexOf(identity.getUserId()) >= 0; + const isBazaarProject = bazaarProject.value !== null; + + setIsMember(isBazaarMember); + setIsBazaar(isBazaarProject); + }, [bazaarProject, members, identity]); + + const onOpen = (event: React.SyntheticEvent) => { + setAnchorEl(event.currentTarget); + setPopoverOpen(true); + }; + + const closeEdit = () => { + setOpen(false); + }; + + const closeDelete = () => { + setOpenDelete(false); + }; + + const popoverCloseHandler = () => { + setPopoverOpen(false); + }; + + const handleMembersClick = async () => { + if (!isMember) { + await bazaarApi.addMember(entity); + } else { + await bazaarApi.deleteMember(entity); + } + + fetchMembers(); + fetchBazaarProject(); + }; + + const links: IconLinkVerticalProps[] = [ + { + label: isMember ? 'Leave' : 'Join', + icon: isMember ? : , + href: '', + onClick: async () => { + handleMembersClick(); + }, + }, + { + label: 'Community', + icon: , + href: bazaarProject?.value?.community, + disabled: !bazaarProject?.value?.community || !isMember, + }, + ]; + + if (!isBazaar) { + return null; + } else if (bazaarProject.loading || members.loading) { + return ; + } else if (bazaarProject.error) { + return {bazaarProject?.error?.message}; + } else if (members.error) { + return {members?.error?.message}; + } + return ( + + {bazaarProject?.value && ( + + )} + + {bazaarProject?.value && ( + + )} + + + + } + subheader={} + /> + + + + + { + setOpen(true); + setPopoverOpen(false); + }} + > + + + + + { + setOpenDelete(true); + setPopoverOpen(false); + }} + > + + + + + + + + + {bazaarProject?.value?.announcement + ? bazaarProject?.value?.announcement + .split('\n') + .map((str: string, i: number) => ( + + {str} + + )) + : 'No announcement'} + + + + + + + + + + + {' '} + + {members?.value?.length ? ( + members.value.slice(0, 3).map((member: Member) => { + return ( +
+ + + {member?.userId} + +
+ ); + }) + ) : ( +
+ )} + + + + + + ); +}; diff --git a/plugins/bazaar/src/components/EntityBazaarInfoCard/index.ts b/plugins/bazaar/src/components/EntityBazaarInfoCard/index.ts new file mode 100644 index 0000000000..89eee92f11 --- /dev/null +++ b/plugins/bazaar/src/components/EntityBazaarInfoCard/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { EntityBazaarInfoCard } from './EntityBazaarInfoCard'; diff --git a/plugins/bazaar/src/components/HomePage/HomePage.tsx b/plugins/bazaar/src/components/HomePage/HomePage.tsx new file mode 100644 index 0000000000..32a16291fc --- /dev/null +++ b/plugins/bazaar/src/components/HomePage/HomePage.tsx @@ -0,0 +1,47 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Header, RoutedTabs } from '@backstage/core-components'; +import { Route } from 'react-router-dom'; +import { SortView } from '../SortView'; +import { About } from '../About'; + +export const HomePage = () => { + const tabContent = [ + { + path: '/', + title: 'Home', + children: } />, + }, + { + path: '/about', + title: 'About', + children: } />, + }, + ]; + + return ( +
+
+ +
+ ); +}; diff --git a/plugins/bazaar/src/components/HomePage/index.ts b/plugins/bazaar/src/components/HomePage/index.ts new file mode 100644 index 0000000000..41d7bc5d03 --- /dev/null +++ b/plugins/bazaar/src/components/HomePage/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { HomePage } from './HomePage'; diff --git a/plugins/bazaar/src/components/InputField/InputField.tsx b/plugins/bazaar/src/components/InputField/InputField.tsx new file mode 100644 index 0000000000..4d284ff82c --- /dev/null +++ b/plugins/bazaar/src/components/InputField/InputField.tsx @@ -0,0 +1,63 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Controller, Control, FieldError } from 'react-hook-form'; +import { TextField } from '@material-ui/core'; +import { FormValues } from '../../types'; + +type Props = { + inputType: 'announcement' | 'community'; + error?: FieldError | undefined; + control: Control; + helperText?: string; + placeholder?: string; + rules?: Object; +}; + +export const InputField = ({ + inputType, + error, + control, + helperText, + placeholder, + rules, +}: Props) => { + const label = + inputType.charAt(0).toLocaleUpperCase('en-US') + inputType.slice(1); + + return ( + ( + + )} + /> + ); +}; diff --git a/plugins/bazaar/src/components/InputField/index.ts b/plugins/bazaar/src/components/InputField/index.ts new file mode 100644 index 0000000000..d8c82eecbd --- /dev/null +++ b/plugins/bazaar/src/components/InputField/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { InputField } from './InputField'; diff --git a/plugins/bazaar/src/components/InputSelector/InputSelector.tsx b/plugins/bazaar/src/components/InputSelector/InputSelector.tsx new file mode 100644 index 0000000000..a41cedfcf3 --- /dev/null +++ b/plugins/bazaar/src/components/InputSelector/InputSelector.tsx @@ -0,0 +1,75 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import InputLabel from '@material-ui/core/InputLabel'; +import MenuItem from '@material-ui/core/MenuItem'; +import FormControl from '@material-ui/core/FormControl'; +import Select from '@material-ui/core/Select'; +import { Controller, Control, FieldError } from 'react-hook-form'; +import { FormValues } from '../../types'; + +type Props = { + options: string[]; + control: Control; + name: 'announcement' | 'status'; + error?: FieldError | undefined; +}; + +export const InputSelector = ({ name, options, control, error }: Props) => { + const label = name.charAt(0).toLocaleUpperCase('en-US') + name.slice(1); + + return ( + ( + + + {label} + + + + )} + /> + ); +}; diff --git a/plugins/bazaar/src/components/InputSelector/index.ts b/plugins/bazaar/src/components/InputSelector/index.ts new file mode 100644 index 0000000000..a4327991b0 --- /dev/null +++ b/plugins/bazaar/src/components/InputSelector/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { InputSelector } from './InputSelector'; diff --git a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx new file mode 100644 index 0000000000..b3c8b3e2e7 --- /dev/null +++ b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx @@ -0,0 +1,98 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { ItemCardHeader } from '@backstage/core-components'; +import { + Card, + CardActionArea, + CardContent, + makeStyles, + Typography, +} from '@material-ui/core'; +import { StatusTag } from '../StatusTag/StatusTag'; +import { Link as RouterLink } from 'react-router-dom'; +import { catalogRouteRef } from '@backstage/plugin-catalog-react'; +import { useRouteRef } from '@backstage/core-plugin-api'; +import { BazaarProject } from '../../types'; +import { parseEntityName } from '@backstage/catalog-model'; +import { DateTime } from 'luxon'; + +const useStyles = makeStyles({ + statusTag: { + display: 'inline-block', + whiteSpace: 'nowrap', + marginBottom: '0.5rem', + }, + announcement: { + display: '-webkit-box', + WebkitLineClamp: 5, + WebkitBoxOrient: 'vertical', + marginBottom: '0.8rem', + overflow: 'hidden', + }, + memberCount: { + float: 'right', + }, +}); + +type Props = { + bazaarProject: BazaarProject; +}; + +export const ProjectCard = ({ bazaarProject }: Props) => { + const classes = useStyles(); + const { entityRef, name, status, updatedAt, announcement, membersCount } = + bazaarProject; + const catalogLink = useRouteRef(catalogRouteRef); + const { namespace, kind } = parseEntityName(entityRef); + + return ( + + + + + + + {membersCount === 1 + ? `${membersCount} member` + : `${membersCount} members`} + +
+ + {announcement} + +
+
+
+
+ ); +}; diff --git a/plugins/bazaar/src/components/ProjectCard/index.ts b/plugins/bazaar/src/components/ProjectCard/index.ts new file mode 100644 index 0000000000..00e62bebba --- /dev/null +++ b/plugins/bazaar/src/components/ProjectCard/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ProjectCard } from './ProjectCard'; diff --git a/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx b/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx new file mode 100644 index 0000000000..cb76984f44 --- /dev/null +++ b/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx @@ -0,0 +1,186 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { + createStyles, + Theme, + withStyles, + WithStyles, +} from '@material-ui/core/styles'; +import MuiDialogTitle from '@material-ui/core/DialogTitle'; +import MuiDialogContent from '@material-ui/core/DialogContent'; +import MuiDialogActions from '@material-ui/core/DialogActions'; +import CloseIcon from '@material-ui/icons/Close'; +import { Button, Dialog, Typography, IconButton } from '@material-ui/core'; +import { useForm, SubmitHandler } from 'react-hook-form'; +import { InputField } from '../InputField/InputField'; +import { InputSelector } from '../InputSelector/InputSelector'; +import { FormValues } from '../../types'; + +const styles = (theme: Theme) => + createStyles({ + root: { + margin: 0, + padding: theme.spacing(2), + }, + closeButton: { + position: 'absolute', + right: theme.spacing(1), + top: theme.spacing(1), + color: theme.palette.grey[500], + }, + }); + +/* + DialogTitleProps, DialogTitle, DialogContent and DialogActions + are copied from the git-release plugin +*/ +export interface DialogTitleProps extends WithStyles { + id: string; + children: React.ReactNode; + onClose: () => void; +} + +const DialogTitle = withStyles(styles)((props: DialogTitleProps) => { + const { children, classes, onClose, ...other } = props; + return ( + + {children} + {onClose ? ( + + + + ) : null} + + ); +}); + +const DialogContent = withStyles((theme: Theme) => ({ + root: { + padding: theme.spacing(2), + }, +}))(MuiDialogContent); + +const DialogActions = withStyles((theme: Theme) => ({ + root: { + margin: 0, + padding: theme.spacing(1), + }, +}))(MuiDialogActions); + +type Props = { + handleSave: (getValues: any, reset: any) => SubmitHandler; + isAddForm: boolean; + title: string; + defaultValues: FormValues; + open: boolean; + projectSelector?: JSX.Element; + handleClose: () => void; +}; + +export const ProjectDialog = ({ + handleSave, + isAddForm, + title, + defaultValues, + open, + projectSelector, + handleClose, +}: Props) => { + const { + handleSubmit, + reset, + control, + getValues, + formState: { errors }, + } = useForm({ + mode: 'onChange', + defaultValues: defaultValues, + }); + + const handleCloseAndClear = () => { + handleClose(); + reset(defaultValues); + }; + + const handleSaveProject = () => { + handleSave(getValues, reset); + }; + + return ( +
+ + + {title} + + + + {isAddForm && projectSelector} + + + + + + + + + + + + +
+ ); +}; diff --git a/plugins/bazaar/src/components/ProjectDialog/index.ts b/plugins/bazaar/src/components/ProjectDialog/index.ts new file mode 100644 index 0000000000..bd85b6576b --- /dev/null +++ b/plugins/bazaar/src/components/ProjectDialog/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ProjectDialog } from './ProjectDialog'; diff --git a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx new file mode 100644 index 0000000000..0b01b86088 --- /dev/null +++ b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx @@ -0,0 +1,109 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useState } from 'react'; +import { Content } from '@backstage/core-components'; +import { ProjectCard } from '../ProjectCard/ProjectCard'; +import { makeStyles, Grid } from '@material-ui/core'; +import Pagination from '@material-ui/lab/Pagination'; +import { BazaarProject } from '../../types'; + +type Props = { + bazaarProjects: BazaarProject[]; + sortingMethod: (arg0: BazaarProject, arg1: BazaarProject) => number; +}; + +const useStyles = makeStyles({ + content: { + width: '100%', + display: 'flex', + flexWrap: 'wrap', + alignItems: 'center', + }, + item: { + minWidth: '20.5rem', + maxWidth: '20.5rem', + width: '20%', + }, +}); + +export const ProjectPreview = ({ bazaarProjects, sortingMethod }: Props) => { + const classes = useStyles(); + const [currentPage, setCurrentPage] = useState(1); + const pageSize = 10; + const pageCount = Math.ceil(bazaarProjects.length / pageSize); + + const handlePageClick = (_: any, pageIndex: number) => { + setCurrentPage(pageIndex); + }; + + if (!bazaarProjects.length) { + return ( +
+ Please add projects to the Bazaar. +
+ ); + } + + bazaarProjects.sort(sortingMethod); + + return ( + + + {bazaarProjects + .slice(pageSize * (currentPage - 1), pageSize * currentPage) + .map((bazaarProject: BazaarProject) => { + const entityRef = bazaarProject.entityRef; + + return ( + + + + ); + })} + + + + ); +}; diff --git a/plugins/bazaar/src/components/ProjectPreview/index.ts b/plugins/bazaar/src/components/ProjectPreview/index.ts new file mode 100644 index 0000000000..74a954c595 --- /dev/null +++ b/plugins/bazaar/src/components/ProjectPreview/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ProjectPreview } from './ProjectPreview'; diff --git a/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx b/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx new file mode 100644 index 0000000000..1c2718d403 --- /dev/null +++ b/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx @@ -0,0 +1,54 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { Autocomplete } from '@material-ui/lab'; +import { TextField } from '@material-ui/core'; + +type Props = { + entities: Entity[]; + value: string; + onChange: (entity: Entity) => void; + isFormInvalid: boolean; +}; + +export const ProjectSelector = ({ + entities, + value, + onChange, + isFormInvalid, +}: Props) => { + return ( + option?.metadata?.name} + renderOption={option => {option?.metadata?.name}} + renderInput={params => ( + + )} + onChange={(_, data) => onChange(data!)} + /> + ); +}; diff --git a/plugins/bazaar/src/components/ProjectSelector/index.ts b/plugins/bazaar/src/components/ProjectSelector/index.ts new file mode 100644 index 0000000000..e81b825dbf --- /dev/null +++ b/plugins/bazaar/src/components/ProjectSelector/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { ProjectSelector } from './ProjectSelector'; diff --git a/plugins/bazaar/src/components/SortView/SortView.tsx b/plugins/bazaar/src/components/SortView/SortView.tsx new file mode 100644 index 0000000000..99d3f84ac3 --- /dev/null +++ b/plugins/bazaar/src/components/SortView/SortView.tsx @@ -0,0 +1,183 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React, { useEffect, useState } from 'react'; +import { + Content, + ContentHeader, + SupportButton, + Progress, +} from '@backstage/core-components'; +import { AddProjectDialog } from '../AddProjectDialog'; +import { AlertBanner } from '../AlertBanner'; +import { ProjectPreview } from '../ProjectPreview/ProjectPreview'; +import { Button, makeStyles, Link } from '@material-ui/core'; +import { useAsyncFn } from 'react-use'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { useApi } from '@backstage/core-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import { BazaarProject } from '../../types'; +import { bazaarApiRef } from '../../api'; +import { Alert } from '@material-ui/lab'; + +const useStyles = makeStyles({ + container: { + marginTop: '2rem', + }, +}); + +const filterCatalogEntities = ( + bazaarProjects: BazaarProject[], + catalogEntities: Entity[], +) => { + const bazaarProjectRefs = bazaarProjects.map( + (project: BazaarProject) => project.entityRef, + ); + + const filtered = catalogEntities.filter((entity: Entity) => { + return !bazaarProjectRefs?.includes(stringifyEntityRef(entity)); + }); + + return filtered; +}; + +export const SortView = () => { + const classes = useStyles(); + const [openAdd, setOpenAdd] = useState(false); + const [openNoProjects, setOpenNoProjects] = useState(false); + const bazaarApi = useApi(bazaarApiRef); + const catalogApi = useApi(catalogApiRef); + const [filteredCatalogEntites, setFilteredCatalogEntities] = + useState(); + + const compareProjectsByDate = ( + a: BazaarProject, + b: BazaarProject, + ): number => { + const dateA = new Date(a.updatedAt!).getTime(); + const dateB = new Date(b.updatedAt!).getTime(); + return dateB - dateA; + }; + + const handleCloseNoProjects = () => { + setOpenNoProjects(false); + }; + + const [catalogEntities, fetchCatalogEntities] = useAsyncFn(async () => { + const entities = await catalogApi.getEntities({ + filter: { + kind: ['Component', 'Resource'], + }, + fields: ['kind', 'metadata.name', 'metadata.namespace'], + }); + + return entities.items; + }); + + const [bazaarProjects, fetchBazaarProjects] = useAsyncFn(async () => { + const response = await bazaarApi.getEntities(); + const dbProjects: BazaarProject[] = []; + + response.data.forEach((project: any) => { + dbProjects.push({ + entityRef: project.entity_ref, + name: project.name, + status: project.status, + announcement: project.announcement, + community: project.community, + updatedAt: project.updated_at, + membersCount: project.members_count, + }); + }); + + return dbProjects; + }); + + useEffect(() => { + fetchCatalogEntities(); + fetchBazaarProjects(); + }, [fetchBazaarProjects, fetchCatalogEntities]); + + useEffect(() => { + const filteredCatalogEntities = filterCatalogEntities( + bazaarProjects.value || [], + catalogEntities.value || [], + ); + + if (filteredCatalogEntities) { + setFilteredCatalogEntities(filteredCatalogEntities); + } + }, [bazaarProjects, catalogEntities]); + + if (catalogEntities.loading || bazaarProjects.loading) return ; + + if (catalogEntities.error) + return {catalogEntities.error.message}; + + if (bazaarProjects.error) + return {bazaarProjects.error.message}; + + return ( + + + No project available. Please{' '} + + create a project + {' '} + from a template first. +
+ } + handleClose={handleCloseNoProjects} + /> + + + { + setOpenAdd(false); + }} + open={openAdd} + fetchBazaarProjects={fetchBazaarProjects} + fetchCatalogEntities={fetchCatalogEntities} + /> + + + + + + ); +}; diff --git a/plugins/bazaar/src/components/SortView/index.ts b/plugins/bazaar/src/components/SortView/index.ts new file mode 100644 index 0000000000..086c7c29d1 --- /dev/null +++ b/plugins/bazaar/src/components/SortView/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { SortView } from './SortView'; diff --git a/plugins/bazaar/src/components/StatusTag/StatusTag.tsx b/plugins/bazaar/src/components/StatusTag/StatusTag.tsx new file mode 100644 index 0000000000..eb01ea5350 --- /dev/null +++ b/plugins/bazaar/src/components/StatusTag/StatusTag.tsx @@ -0,0 +1,37 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { StatusOK, StatusWarning } from '@backstage/core-components'; +import { Status } from '../../types'; + +interface StatusComponent { + [key: string]: JSX.Element | undefined; +} + +const statuses: StatusComponent = { + proposed: proposed, + ongoing: ongoing, +}; + +type Props = { + status: Status; + styles?: string; +}; + +export const StatusTag = ({ status, styles }: Props) => { + return
{statuses[status]}
; +}; diff --git a/plugins/bazaar/src/components/StatusTag/index.ts b/plugins/bazaar/src/components/StatusTag/index.ts new file mode 100644 index 0000000000..33886382f8 --- /dev/null +++ b/plugins/bazaar/src/components/StatusTag/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { StatusTag } from './StatusTag'; diff --git a/plugins/bazaar/src/index.ts b/plugins/bazaar/src/index.ts new file mode 100644 index 0000000000..e9b388d736 --- /dev/null +++ b/plugins/bazaar/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { bazaarPlugin, BazaarPage } from './plugin'; +export { EntityBazaarInfoCard } from './components/EntityBazaarInfoCard'; diff --git a/plugins/welcome/src/plugin.test.ts b/plugins/bazaar/src/plugin.test.ts similarity index 80% rename from plugins/welcome/src/plugin.test.ts rename to plugins/bazaar/src/plugin.test.ts index 8b429f0526..4d9964d1dd 100644 --- a/plugins/welcome/src/plugin.test.ts +++ b/plugins/bazaar/src/plugin.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,10 @@ * limitations under the License. */ -import { welcomePlugin } from './plugin'; +import { bazaarPlugin } from './plugin'; -describe('welcome', () => { +describe('bazaar', () => { it('should export plugin', () => { - expect(welcomePlugin).toBeDefined(); + expect(bazaarPlugin).toBeDefined(); }); }); diff --git a/plugins/bazaar/src/plugin.ts b/plugins/bazaar/src/plugin.ts new file mode 100644 index 0000000000..f96eaf522d --- /dev/null +++ b/plugins/bazaar/src/plugin.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { rootRouteRef } from './routes'; +import { + createApiFactory, + createPlugin, + createRoutableExtension, + identityApiRef, + discoveryApiRef, +} from '@backstage/core-plugin-api'; +import { bazaarApiRef, BazaarClient } from './api'; + +export const bazaarPlugin = createPlugin({ + id: 'bazaar', + routes: { + root: rootRouteRef, + }, + apis: [ + createApiFactory({ + api: bazaarApiRef, + deps: { + identityApi: identityApiRef, + discoveryApi: discoveryApiRef, + }, + factory: ({ identityApi, discoveryApi }) => + new BazaarClient({ identityApi, discoveryApi }), + }), + ], +}); + +export const BazaarPage = bazaarPlugin.provide( + createRoutableExtension({ + component: () => import('./components/HomePage').then(m => m.HomePage), + mountPoint: rootRouteRef, + }), +); diff --git a/plugins/bazaar/src/routes.ts b/plugins/bazaar/src/routes.ts new file mode 100644 index 0000000000..a3cc88d86f --- /dev/null +++ b/plugins/bazaar/src/routes.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + title: 'bazaar', +}); diff --git a/plugins/bazaar/src/setupTests.ts b/plugins/bazaar/src/setupTests.ts new file mode 100644 index 0000000000..427556fe26 --- /dev/null +++ b/plugins/bazaar/src/setupTests.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '@testing-library/jest-dom'; +import 'cross-fetch/polyfill'; diff --git a/plugins/bazaar/src/types.ts b/plugins/bazaar/src/types.ts new file mode 100644 index 0000000000..4050c6a2ee --- /dev/null +++ b/plugins/bazaar/src/types.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { EntityRef } from '@backstage/catalog-model'; + +export type Member = { + entityRef: EntityRef; + userId: string; + joinDate?: string; + picture?: string; +}; + +export type Status = 'ongoing' | 'proposed'; + +export type BazaarProject = { + name: string; + entityRef: EntityRef; + community: string; + status: Status; + announcement: string; + updatedAt?: string; + membersCount: number; +}; + +export type FormValues = { + announcement: string; + community: string; + status: string; +}; diff --git a/plugins/bitrise/CHANGELOG.md b/plugins/bitrise/CHANGELOG.md index 802e0a4abc..7e364ca294 100644 --- a/plugins/bitrise/CHANGELOG.md +++ b/plugins/bitrise/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-bitrise +## 0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.15 ### Patch Changes diff --git a/plugins/bitrise/package.json b/plugins/bitrise/package.json index c581071c1a..9123188947 100644 --- a/plugins/bitrise/package.json +++ b/plugins/bitrise/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-bitrise", "description": "A Backstage plugin that integrates towards Bitrise", - "version": "0.1.15", + "version": "0.1.16", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +39,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 6e1a819d78..6bac00a7a3 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,22 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.3.5 + +### Patch Changes + +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/plugin-catalog-backend@0.17.1 + - @backstage/errors@0.1.3 + - @backstage/catalog-model@0.9.5 + +## 0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@0.17.0 + ## 0.3.3 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index bc71ca4688..7236e780c4 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", "description": "A Backstage catalog backend modules that helps integrate towards LDAP", - "version": "0.3.3", + "version": "0.3.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -29,16 +29,17 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/plugin-catalog-backend": "^0.16.0", + "@backstage/errors": "^0.1.3", + "@backstage/plugin-catalog-backend": "^0.17.1", "@types/ldapjs": "^2.2.0", "ldapjs": "^2.2.0", "lodash": "^4.17.21", "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.7.15", + "@backstage/cli": "^0.8.0", "@types/lodash": "^4.14.151" }, "files": [ diff --git a/plugins/catalog-backend-module-ldap/src/ldap/client.ts b/plugins/catalog-backend-module-ldap/src/ldap/client.ts index 048aa40dc1..553081f4b0 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/client.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/client.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { ForwardedError } from '@backstage/errors'; import ldap, { Client, SearchEntry, SearchOptions } from 'ldapjs'; import { Logger } from 'winston'; import { BindConfig } from './config'; @@ -120,7 +121,7 @@ export class LdapClient { clearInterval(logInterval); }); } catch (e) { - throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); + throw new ForwardedError(`LDAP search at DN "${dn}" failed`, e); } } @@ -167,7 +168,7 @@ export class LdapClient { }); }); } catch (e) { - throw new Error(`LDAP search at DN "${dn}" failed, ${e.message}`); + throw new ForwardedError(`LDAP search at DN "${dn}" failed`, e); } } diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 0fa13b2018..7f3b8657f9 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,21 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.2.8 + +### Patch Changes + +- 406dcf06e5: Add `MicrosoftGraphOrgEntityProvider` as an alternative to `MicrosoftGraphOrgReaderProcessor` that automatically handles user and group deletions. +- Updated dependencies + - @backstage/plugin-catalog-backend@0.17.1 + - @backstage/catalog-model@0.9.5 + +## 0.2.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@0.17.0 + ## 0.2.6 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/README.md b/plugins/catalog-backend-module-msgraph/README.md index 4c41d42915..0e088d3a4e 100644 --- a/plugins/catalog-backend-module-msgraph/README.md +++ b/plugins/catalog-backend-module-msgraph/README.md @@ -1,41 +1,24 @@ # Catalog Backend Module for Microsoft Graph This is an extension module to the `plugin-catalog-backend` plugin, providing a -`MicrosoftGraphOrgReaderProcessor` that can be used to ingest organization data -from the Microsoft Graph API. This processor is useful if you want to import -users and groups from Azure Active Directory or Office 365. +`MicrosoftGraphOrgReaderProcessor` and a `MicrosoftGraphOrgEntityProvider` that +can be used to ingest organization data from the Microsoft Graph API. This +processor is useful if you want to import users and groups from Azure Active +Directory or Office 365. ## Getting Started -1. The processor is not installed by default, therefore you have to add a - dependency to `@backstage/plugin-catalog-backend-module-msgraph` to your - backend package. +First you need to decide whether you want to use an [entity provider or a processor](https://backstage.io/docs/features/software-catalog/life-of-an-entity#stitching) to ingest the organization data. +If you want groups and users deleted from the source to be automatically deleted +from Backstage, choose the entity provider. -```bash -# From your Backstage root directory -cd packages/backend -yarn add @backstage/plugin-catalog-backend-module-msgraph -``` - -2. The `MicrosoftGraphOrgReaderProcessor` is not registered by default, so you - have to register it in the catalog plugin: - -```typescript -// packages/backend/src/plugins/catalog.ts -builder.addProcessor( - MicrosoftGraphOrgReaderProcessor.fromConfig(config, { - logger, - }), -); -``` - -3. Create or use an existing App registration in the [Microsoft Azure Portal](https://portal.azure.com/). +1. Create or use an existing App registration in the [Microsoft Azure Portal](https://portal.azure.com/). The App registration requires at least the API permissions `Group.Read.All`, `GroupMember.Read.All`, `User.Read` and `User.Read.All` for Microsoft Graph (if you still run into errors about insufficient privileges, add `Team.ReadBasic.All` and `TeamMember.Read.All` too). -4. Configure the processor: +2. Configure the processor or entity provider: ```yaml # app-config.yaml @@ -69,6 +52,56 @@ catalog: By default, all users are loaded. If you want to filter users based on their attributes, use `userFilter`. `userGroupMemberFilter` can be used if you want to load users based on their group membership. +3. The package is not installed by default, therefore you have to add a + dependency to `@backstage/plugin-catalog-backend-module-msgraph` to your + backend package. + +```bash +# From your Backstage root directory +cd packages/backend +yarn add @backstage/plugin-catalog-backend-module-msgraph +``` + +### Using the Entity Provider + +4. The `MicrosoftGraphOrgEntityProvider` is not registered by default, so you + have to register it in the catalog plugin. Pass the target to reference a + provider from the configuration. As entity providers are not part of the + entity refresh loop, you have to run them manually. + +```typescript +// packages/backend/src/plugins/catalog.ts +const msGraphOrgEntityProvider = MicrosoftGraphOrgEntityProvider.fromConfig( + env.config, + { + id: 'https://graph.microsoft.com/v1.0', + target: 'https://graph.microsoft.com/v1.0', + logger: env.logger, + }, +); +builder.addEntityProvider(msGraphOrgEntityProvider); + +// Trigger a read every 5 minutes +useHotCleanup( + module, + runPeriodically(() => msGraphOrgEntityProvider.read(), 5 * 60 * 1000), +); +``` + +### Using the Processor + +4. The `MicrosoftGraphOrgReaderProcessor` is not registered by default, so you + have to register it in the catalog plugin: + +```typescript +// packages/backend/src/plugins/catalog.ts +builder.addProcessor( + MicrosoftGraphOrgReaderProcessor.fromConfig(config, { + logger, + }), +); +``` + 5. Add a location that ingests from Microsoft Graph: ```yaml @@ -84,10 +117,11 @@ catalog: โ€ฆ ``` -## Customize the Processor +## Customize the Processor or Entity Provider -In case you want to customize the ingested entities, the `MicrosoftGraphOrgReaderProcessor` -allows to pass transformers for users, groups and the organization. +In case you want to customize the ingested entities, both the `MicrosoftGraphOrgReaderProcessor` +and the `MicrosoftGraphOrgEntityProvider` allows to pass transformers for users, +groups and the organization. 1. Create a transformer: diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index d290fcf9b6..1357659739 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -6,6 +6,8 @@ import { CatalogProcessor } from '@backstage/plugin-catalog-backend'; import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; +import { EntityProvider } from '@backstage/plugin-catalog-backend'; +import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; import { GroupEntity } from '@backstage/catalog-model'; import { LocationSpec } from '@backstage/catalog-model'; import { Logger as Logger_2 } from 'winston'; @@ -93,6 +95,38 @@ export class MicrosoftGraphClient { requestRaw(url: string): Promise; } +// Warning: (ae-missing-release-tag) "MicrosoftGraphOrgEntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public +export class MicrosoftGraphOrgEntityProvider implements EntityProvider { + constructor(options: { + id: string; + provider: MicrosoftGraphProviderConfig; + logger: Logger_2; + userTransformer?: UserTransformer; + groupTransformer?: GroupTransformer; + organizationTransformer?: OrganizationTransformer; + }); + // (undocumented) + connect(connection: EntityProviderConnection): Promise; + // (undocumented) + static fromConfig( + config: Config, + options: { + id: string; + target: string; + logger: Logger_2; + userTransformer?: UserTransformer; + groupTransformer?: GroupTransformer; + organizationTransformer?: OrganizationTransformer; + }, + ): MicrosoftGraphOrgEntityProvider; + // (undocumented) + getProviderName(): string; + // (undocumented) + read(): Promise; +} + // Warning: (ae-missing-release-tag) "MicrosoftGraphOrgReaderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index febaabe219..d0f664f428 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", "description": "A Backstage catalog backend modules that helps integrate towards Microsoft Graph", - "version": "0.2.6", + "version": "0.2.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,9 +30,9 @@ }, "dependencies": { "@azure/msal-node": "^1.1.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/plugin-catalog-backend": "^0.16.0", + "@backstage/plugin-catalog-backend": "^0.17.1", "@microsoft/microsoft-graph-types": "^2.6.0", "cross-fetch": "^3.0.6", "lodash": "^4.17.21", @@ -41,9 +41,9 @@ "qs": "^6.9.4" }, "devDependencies": { - "@backstage/backend-common": "^0.9.6", - "@backstage/cli": "^0.7.15", - "@backstage/test-utils": "^0.1.18", + "@backstage/backend-common": "^0.9.7", + "@backstage/cli": "^0.8.0", + "@backstage/test-utils": "^0.1.19", "@types/lodash": "^4.14.151", "msw": "^0.29.0" }, diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts index 5164439448..efbbca1f5c 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts @@ -72,4 +72,21 @@ describe('readMicrosoftGraphConfig', () => { ]; expect(actual).toEqual(expected); }); + + it('should fail if both userFilter and userGroupMemberFilter are set', () => { + const config = { + providers: [ + { + target: 'target', + tenantId: 'tenantId', + clientId: 'clientId', + clientSecret: 'clientSecret', + authority: 'https://login.example.com/', + userFilter: 'accountEnabled eq true', + userGroupMemberFilter: 'any', + }, + ], + }; + expect(() => readMicrosoftGraphConfig(new ConfigReader(config))).toThrow(); + }); }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts index fe0678372a..91a6d49b57 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.ts @@ -87,6 +87,12 @@ export function readMicrosoftGraphConfig( ); const groupFilter = providerConfig.getOptionalString('groupFilter'); + if (userFilter && userGroupMemberFilter) { + throw new Error( + `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`, + ); + } + providers.push({ target, authority, diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts new file mode 100644 index 0000000000..eab2d93526 --- /dev/null +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.test.ts @@ -0,0 +1,174 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { getVoidLogger } from '@backstage/backend-common'; +import { + GroupEntity, + LOCATION_ANNOTATION, + ORIGIN_LOCATION_ANNOTATION, + UserEntity, +} from '@backstage/catalog-model'; +import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; +import { + MicrosoftGraphClient, + MICROSOFT_GRAPH_USER_ID_ANNOTATION, + readMicrosoftGraphOrg, +} from '../microsoftGraph'; +import { + MicrosoftGraphOrgEntityProvider, + withLocations, +} from './MicrosoftGraphOrgEntityProvider'; + +jest.mock('../microsoftGraph', () => { + return { + ...jest.requireActual('../microsoftGraph'), + readMicrosoftGraphOrg: jest.fn(), + }; +}); + +const readMicrosoftGraphOrgMocked = readMicrosoftGraphOrg as jest.Mock< + Promise<{ users: UserEntity[]; groups: GroupEntity[] }> +>; + +describe('MicrosoftGraphOrgEntityProvider', () => { + afterEach(() => jest.resetAllMocks()); + + it('should apply mutation', async () => { + jest + .spyOn(MicrosoftGraphClient, 'create') + .mockReturnValue({} as unknown as MicrosoftGraphClient); + + readMicrosoftGraphOrgMocked.mockResolvedValue({ + users: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'u1', + }, + spec: { + memberOf: [], + }, + }, + ], + groups: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'g1', + }, + spec: { + type: 'team', + children: [], + }, + }, + ], + }); + + const entityProviderConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + }; + const provider = new MicrosoftGraphOrgEntityProvider({ + id: 'test', + logger: getVoidLogger(), + provider: { + target: 'https://example.com', + tenantId: 'tenant', + clientId: 'clientid', + clientSecret: 'clientsecret', + }, + }); + + provider.connect(entityProviderConnection); + + await provider.read(); + + expect(entityProviderConnection.applyMutation).toBeCalledWith({ + entities: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': 'msgraph:test/u1', + 'backstage.io/managed-by-origin-location': 'msgraph:test/u1', + }, + name: 'u1', + }, + spec: { + memberOf: [], + }, + }, + locationKey: 'msgraph-org-provider:test', + }, + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/managed-by-location': 'msgraph:test/g1', + 'backstage.io/managed-by-origin-location': 'msgraph:test/g1', + }, + name: 'g1', + }, + spec: { + children: [], + type: 'team', + }, + }, + locationKey: 'msgraph-org-provider:test', + }, + ], + type: 'full', + }); + }); +}); + +describe('withLocations', () => { + it('should set location annotations', () => { + expect( + withLocations('test', { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'u1', + annotations: { + [MICROSOFT_GRAPH_USER_ID_ANNOTATION]: 'uid', + }, + }, + spec: { + memberOf: [], + }, + }), + ).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'u1', + annotations: { + [MICROSOFT_GRAPH_USER_ID_ANNOTATION]: 'uid', + [LOCATION_ANNOTATION]: 'msgraph:test/uid', + [ORIGIN_LOCATION_ANNOTATION]: 'msgraph:test/uid', + }, + }, + spec: { + memberOf: [], + }, + }); + }); +}); diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts new file mode 100644 index 0000000000..ea396162dd --- /dev/null +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgEntityProvider.ts @@ -0,0 +1,181 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + Entity, + LOCATION_ANNOTATION, + ORIGIN_LOCATION_ANNOTATION, +} from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { + EntityProvider, + EntityProviderConnection, +} from '@backstage/plugin-catalog-backend'; +import { merge } from 'lodash'; +import { Logger } from 'winston'; +import { + GroupTransformer, + MicrosoftGraphClient, + MicrosoftGraphProviderConfig, + MICROSOFT_GRAPH_GROUP_ID_ANNOTATION, + MICROSOFT_GRAPH_TENANT_ID_ANNOTATION, + MICROSOFT_GRAPH_USER_ID_ANNOTATION, + OrganizationTransformer, + readMicrosoftGraphConfig, + readMicrosoftGraphOrg, + UserTransformer, +} from '../microsoftGraph'; + +/** + * Reads user and group entries out of Microsoft Graph, and provides them as + * User and Group entities for the catalog. + */ +export class MicrosoftGraphOrgEntityProvider implements EntityProvider { + private connection?: EntityProviderConnection; + + static fromConfig( + config: Config, + options: { + id: string; + target: string; + logger: Logger; + userTransformer?: UserTransformer; + groupTransformer?: GroupTransformer; + organizationTransformer?: OrganizationTransformer; + }, + ) { + const c = config.getOptionalConfig('catalog.processors.microsoftGraphOrg'); + const providers = c ? readMicrosoftGraphConfig(c) : []; + const provider = providers.find(p => options.target.startsWith(p.target)); + + if (!provider) { + throw new Error( + `There is no Microsoft Graph Org provider that matches ${options.target}. Please add a configuration entry for it under catalog.processors.microsoftGraphOrg.providers.`, + ); + } + + const logger = options.logger.child({ + target: options.target, + }); + + return new MicrosoftGraphOrgEntityProvider({ + id: options.id, + userTransformer: options.userTransformer, + groupTransformer: options.groupTransformer, + organizationTransformer: options.organizationTransformer, + logger, + provider, + }); + } + + constructor( + private options: { + id: string; + provider: MicrosoftGraphProviderConfig; + logger: Logger; + userTransformer?: UserTransformer; + groupTransformer?: GroupTransformer; + organizationTransformer?: OrganizationTransformer; + }, + ) {} + + getProviderName() { + return `MicrosoftGraphOrgEntityProvider:${this.options.id}`; + } + + async connect(connection: EntityProviderConnection) { + this.connection = connection; + } + + async read() { + if (!this.connection) { + throw new Error('Not initialized'); + } + + const provider = this.options.provider; + const { markReadComplete } = trackProgress(this.options.logger); + const client = MicrosoftGraphClient.create(this.options.provider); + + const { users, groups } = await readMicrosoftGraphOrg( + client, + provider.tenantId, + { + userFilter: provider.userFilter, + userGroupMemberFilter: provider.userGroupMemberFilter, + groupFilter: provider.groupFilter, + groupTransformer: this.options.groupTransformer, + userTransformer: this.options.userTransformer, + organizationTransformer: this.options.organizationTransformer, + logger: this.options.logger, + }, + ); + + const { markCommitComplete } = markReadComplete({ users, groups }); + + await this.connection.applyMutation({ + type: 'full', + entities: [...users, ...groups].map(entity => ({ + locationKey: `msgraph-org-provider:${this.options.id}`, + entity: withLocations(this.options.id, entity), + })), + }); + + markCommitComplete(); + } +} + +// Helps wrap the timing and logging behaviors +function trackProgress(logger: Logger) { + let timestamp = Date.now(); + let summary: string; + + logger.info('Reading msgraph users and groups'); + + function markReadComplete(read: { users: unknown[]; groups: unknown[] }) { + summary = `${read.users.length} msgraph users and ${read.groups.length} msgraph groups`; + const readDuration = ((Date.now() - timestamp) / 1000).toFixed(1); + timestamp = Date.now(); + logger.info(`Read ${summary} in ${readDuration} seconds. Committing...`); + return { markCommitComplete }; + } + + function markCommitComplete() { + const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1); + logger.info(`Committed ${summary} in ${commitDuration} seconds.`); + } + + return { markReadComplete }; +} + +// Makes sure that emitted entities have a proper location based on their uuid +export function withLocations(providerId: string, entity: Entity): Entity { + const uuid = + entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] || + entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] || + entity.metadata.annotations?.[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION] || + entity.metadata.name; + const location = `msgraph:${providerId}/${encodeURIComponent(uuid)}`; + return merge( + { + metadata: { + annotations: { + [LOCATION_ANNOTATION]: location, + [ORIGIN_LOCATION_ANNOTATION]: location, + }, + }, + }, + entity, + ) as Entity; +} diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts new file mode 100644 index 0000000000..8236dc52e1 --- /dev/null +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.test.ts @@ -0,0 +1,143 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { GroupEntity, UserEntity } from '@backstage/catalog-model'; +import { MicrosoftGraphClient, readMicrosoftGraphOrg } from '../microsoftGraph'; +import { MicrosoftGraphOrgReaderProcessor } from './MicrosoftGraphOrgReaderProcessor'; + +jest.mock('../microsoftGraph', () => { + return { + ...jest.requireActual('../microsoftGraph'), + readMicrosoftGraphOrg: jest.fn(), + }; +}); + +const readMicrosoftGraphOrgMocked = readMicrosoftGraphOrg as jest.Mock< + Promise<{ users: UserEntity[]; groups: GroupEntity[] }> +>; + +describe('MicrosoftGraphOrgReaderProcessor', () => { + const emit = jest.fn(); + let processor: MicrosoftGraphOrgReaderProcessor; + + beforeEach(() => { + processor = new MicrosoftGraphOrgReaderProcessor({ + providers: [ + { + target: 'https://example.com', + tenantId: 'tenant', + clientId: 'clientid', + clientSecret: 'clientsecret', + }, + ], + logger: getVoidLogger(), + }); + + jest + .spyOn(MicrosoftGraphClient, 'create') + .mockReturnValue({} as unknown as MicrosoftGraphClient); + }); + + afterEach(() => jest.resetAllMocks()); + + it('should process microsoft-graph-org locations', async () => { + const location = { + type: 'microsoft-graph-org', + target: 'https://example.com', + }; + + readMicrosoftGraphOrgMocked.mockResolvedValue({ + users: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'u1', + }, + spec: { + memberOf: [], + }, + }, + ], + groups: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'g1', + }, + spec: { + type: 'team', + children: [], + }, + }, + ], + }); + + const processed = await processor.readLocation(location, false, emit); + + expect(processed).toBe(true); + expect(emit).toBeCalledTimes(2); + expect(emit).toBeCalledWith({ + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'g1', + }, + spec: { + children: [], + type: 'team', + }, + }, + location: { + target: 'https://example.com', + type: 'microsoft-graph-org', + }, + type: 'entity', + }); + expect(emit).toBeCalledWith({ + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'u1', + }, + spec: { + memberOf: [], + }, + }, + location: { + target: 'https://example.com', + type: 'microsoft-graph-org', + }, + type: 'entity', + }); + }); + + it('should ignore other locations', async () => { + const location = { + type: 'url', + target: 'https://example.com', + }; + + const processed = await processor.readLocation(location, false, emit); + + expect(processed).toBe(false); + expect(emit).toBeCalledTimes(0); + }); +}); diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts index 7f4e55c0cc..cb7729e04a 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts @@ -90,12 +90,6 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { ); } - if (provider.userFilter && provider.userGroupMemberFilter) { - throw new Error( - `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`, - ); - } - // Read out all of the raw data const startTimestamp = Date.now(); this.logger.info('Reading Microsoft Graph users and groups'); diff --git a/plugins/catalog-backend-module-msgraph/src/processors/index.ts b/plugins/catalog-backend-module-msgraph/src/processors/index.ts index f5dc101563..7f70bde994 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/index.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ +export { MicrosoftGraphOrgEntityProvider } from './MicrosoftGraphOrgEntityProvider'; export { MicrosoftGraphOrgReaderProcessor } from './MicrosoftGraphOrgReaderProcessor'; diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index 846fba5d01..b098270431 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,36 @@ # @backstage/plugin-catalog-backend +## 0.17.1 + +### Patch Changes + +- 3adaf88db2: Take CatalogParser in account when processing file locations. +- 1f62d1cbe9: Minor rearrangement of `Stitcher` to clarify the scope of one stitch round +- 3ba87f514e: Add a `GitHubOrgEntityProvider` that can be used instead of the `GithubOrgReaderProcessor`. +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- 177401b571: Use entity title (if defined) as title of documents indexed by `DefaultCatalogCollator` +- Updated dependencies + - @backstage/backend-common@0.9.7 + - @backstage/errors@0.1.3 + - @backstage/catalog-model@0.9.5 + +## 0.17.0 + +### Minor Changes + +- 9fb9256e50: This continues the deprecation of classes used by the legacy catalog engine. New deprecations can be viewed in this [PR](https://github.com/backstage/backstage/pull/7500) or in the API reference documentation. + + The `batchAddOrUpdateEntities` method of the `EntitiesCatalog` interface has been marked as optional and is being deprecated. It is still implemented and required to be implemented by the legacy catalog classes, but was never implemented in the new catalog. + + This change is only relevant if you are consuming the `EntitiesCatalog` interface directly, in which case you will get a type error that you need to resolve. It can otherwise be ignored. + +### Patch Changes + +- 3b59bb915e: Fixes a bug in the catalog where entities were not being marked as orphaned. +- 55ff928d50: This change refactors the internal package structure to remove the `next` catalog folder that was used during the implementation and testing phase of the new catalog engine. The implementation is now the default and is therefore restructured to no longer be packaged under `next/`. This refactor does not change catalog imports from other parts of the project. +- Updated dependencies + - @backstage/integration@0.6.8 + ## 0.16.0 ### Minor Changes diff --git a/plugins/catalog-backend/api-report.md b/plugins/catalog-backend/api-report.md index 6b7d966b28..d3c73afc91 100644 --- a/plugins/catalog-backend/api-report.md +++ b/plugins/catalog-backend/api-report.md @@ -16,6 +16,7 @@ import { EntityName } from '@backstage/catalog-model'; import { EntityPolicy } from '@backstage/catalog-model'; import { EntityRelationSpec } from '@backstage/catalog-model'; import express from 'express'; +import { GitHubIntegrationConfig } from '@backstage/integration'; import { IndexableDocument } from '@backstage/search-common'; import { JsonObject } from '@backstage/config'; import { JsonValue } from '@backstage/config'; @@ -966,6 +967,7 @@ export class FileReaderProcessor implements CatalogProcessor { location: LocationSpec, optional: boolean, emit: CatalogProcessorEmit, + parser: CatalogProcessorParser, ): Promise; } @@ -1019,6 +1021,33 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { ): Promise; } +// Warning: (ae-missing-release-tag) "GitHubOrgEntityProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export class GitHubOrgEntityProvider implements EntityProvider { + constructor(options: { + id: string; + orgUrl: string; + gitHubConfig: GitHubIntegrationConfig; + logger: Logger_2; + }); + // (undocumented) + connect(connection: EntityProviderConnection): Promise; + // (undocumented) + static fromConfig( + config: Config, + options: { + id: string; + orgUrl: string; + logger: Logger_2; + }, + ): GitHubOrgEntityProvider; + // (undocumented) + getProviderName(): string; + // (undocumented) + read(): Promise; +} + // Warning: (ae-missing-release-tag) "GithubOrgReaderProcessor" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 8a3e6dc432..896bbde592 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-backend", "description": "The Backstage backend plugin that provides the Backstage catalog", - "version": "0.16.0", + "version": "0.17.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,12 +30,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.2", - "@backstage/integration": "^0.6.7", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", "@backstage/search-common": "^0.2.0", "@octokit/graphql": "^4.5.8", "@types/express": "^4.17.6", @@ -61,9 +61,9 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.7", - "@backstage/cli": "^0.7.15", - "@backstage/test-utils": "^0.1.18", + "@backstage/backend-test-utils": "^0.1.8", + "@backstage/cli": "^0.8.0", + "@backstage/test-utils": "^0.1.19", "@types/core-js": "^2.5.4", "@types/git-url-parse": "^9.0.0", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts index 0b9d3653a0..f2f478c481 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts @@ -15,7 +15,7 @@ */ import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; -import { ConflictError, NotFoundError } from '@backstage/errors'; +import { ConflictError, isError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; import lodash from 'lodash'; import { v4 as uuid } from 'uuid'; @@ -550,7 +550,10 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { return result.rowCount === 1 || result.length === 1; } catch (error) { // SQLite reached this rather than the rowCount check above - if (error.message.includes('UNIQUE constraint failed')) { + if ( + isError(error) && + error.message.includes('UNIQUE constraint failed') + ) { return false; } throw error; diff --git a/plugins/catalog-backend/src/ingestion/index.ts b/plugins/catalog-backend/src/ingestion/index.ts index 33c81c56cc..fcb634914b 100644 --- a/plugins/catalog-backend/src/ingestion/index.ts +++ b/plugins/catalog-backend/src/ingestion/index.ts @@ -14,14 +14,15 @@ * limitations under the License. */ -export type { CatalogRule, CatalogRulesEnforcer } from './CatalogRules'; export { DefaultCatalogRulesEnforcer } from './CatalogRules'; +export type { CatalogRule, CatalogRulesEnforcer } from './CatalogRules'; +export * from './processors'; +export * from './providers'; export type { - AnalyzeLocationRequest, - AnalyzeLocationResponse, - LocationAnalyzer, AnalyzeLocationEntityField, AnalyzeLocationExistingEntity, AnalyzeLocationGenerateEntity, + AnalyzeLocationRequest, + AnalyzeLocationResponse, + LocationAnalyzer, } from './types'; -export * from './processors'; diff --git a/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts index c394e9b047..63bc45726d 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.ts @@ -16,6 +16,7 @@ import { UrlReader } from '@backstage/backend-common'; import { LocationSpec } from '@backstage/catalog-model'; +import { isError } from '@backstage/errors'; import limiterFactory from 'p-limit'; import * as result from './results'; import { @@ -50,7 +51,7 @@ export class AwsS3DiscoveryProcessor implements CatalogProcessor { } catch (error) { const message = `Unable to read ${location.type}, ${error}`; - if (error.name === 'NotFoundError') { + if (isError(error) && error.name === 'NotFoundError') { if (!optional) { emit(result.notFoundError(location, message)); } diff --git a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts index 8a5f202e5e..c2cce66bc6 100644 --- a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts @@ -21,6 +21,7 @@ import { CatalogProcessorResult, } from './types'; import path from 'path'; +import { defaultEntityDataParser } from './util/parse'; describe('FileReaderProcessor', () => { const fixturesRoot = path.join(__dirname, '__fixtures__/fileReaderProcessor'); @@ -33,7 +34,7 @@ describe('FileReaderProcessor', () => { }; const generated = (await new Promise(emit => - processor.readLocation(spec, false, emit), + processor.readLocation(spec, false, emit, defaultEntityDataParser), )) as CatalogProcessorEntityResult; expect(generated.type).toBe('entity'); @@ -49,7 +50,7 @@ describe('FileReaderProcessor', () => { }; const generated = (await new Promise(emit => - processor.readLocation(spec, false, emit), + processor.readLocation(spec, false, emit, defaultEntityDataParser), )) as CatalogProcessorErrorResult; expect(generated.type).toBe('error'); @@ -69,6 +70,7 @@ describe('FileReaderProcessor', () => { { type: 'file', target: `${path.join(fixturesRoot, '**', '*.yaml')}` }, false, emit, + defaultEntityDataParser, ); expect(emit).toBeCalledTimes(2); diff --git a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts index 5f6e739bdd..9ff3f52ba0 100644 --- a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.ts @@ -20,8 +20,11 @@ import g from 'glob'; import path from 'path'; import { promisify } from 'util'; import * as result from './results'; -import { CatalogProcessor, CatalogProcessorEmit } from './types'; -import { parseEntityYaml } from './util/parse'; +import { + CatalogProcessor, + CatalogProcessorEmit, + CatalogProcessorParser, +} from './types'; const glob = promisify(g); @@ -30,6 +33,7 @@ export class FileReaderProcessor implements CatalogProcessor { location: LocationSpec, optional: boolean, emit: CatalogProcessorEmit, + parser: CatalogProcessorParser, ): Promise { if (location.type !== 'file') { return false; @@ -44,9 +48,12 @@ export class FileReaderProcessor implements CatalogProcessor { // The normalize converts to native slashes; the glob library returns // forward slashes even on windows - for (const parseResult of parseEntityYaml(data, { - type: 'file', - target: path.normalize(fileMatch), + for await (const parseResult of parser({ + data: data, + location: { + type: 'file', + target: path.normalize(fileMatch), + }, })) { emit(parseResult); } diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts index 8894482484..87a910ee06 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.test.ts @@ -13,27 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('@octokit/graphql'); import { getVoidLogger } from '@backstage/backend-common'; import { LocationSpec } from '@backstage/catalog-model'; -import { - ScmIntegrations, - GithubCredentialsProvider, -} from '@backstage/integration'; -import { GithubOrgReaderProcessor, parseUrl } from './GithubOrgReaderProcessor'; -import { graphql } from '@octokit/graphql'; import { ConfigReader } from '@backstage/config'; +import { + GithubCredentialsProvider, + ScmIntegrations, +} from '@backstage/integration'; +import { graphql } from '@octokit/graphql'; +import { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor'; + +jest.mock('@octokit/graphql'); describe('GithubOrgReaderProcessor', () => { - describe('parseUrl', () => { - it('only supports clean org urls, and decodes them', () => { - expect(() => parseUrl('https://github.com')).toThrow(); - expect(() => parseUrl('https://github.com/org/foo')).toThrow(); - expect(() => parseUrl('https://github.com/org/foo/teams')).toThrow(); - expect(parseUrl('https://github.com/foo%32')).toEqual({ org: 'foo2' }); - }); - }); - describe('implementation', () => { const logger = getVoidLogger(); const integrations = ScmIntegrations.fromConfig( diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts index 3a82ff6516..244dbd8104 100644 --- a/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/GithubOrgReaderProcessor.ts @@ -23,10 +23,14 @@ import { } from '@backstage/integration'; import { graphql } from '@octokit/graphql'; import { Logger } from 'winston'; -import { getOrganizationTeams, getOrganizationUsers } from './github'; +import { + getOrganizationTeams, + getOrganizationUsers, + parseGitHubOrgUrl, +} from './github'; import * as results from './results'; import { CatalogProcessor, CatalogProcessorEmit } from './types'; -import { buildOrgHierarchy } from './util/org'; +import { assignGroupsToUsers, buildOrgHierarchy } from './util/org'; type GraphQL = typeof graphql; @@ -61,7 +65,7 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { } const { client, tokenType } = await this.createClient(location.target); - const { org } = parseUrl(location.target); + const { org } = parseGitHubOrgUrl(location.target); // Read out all of the raw data const startTimestamp = Date.now(); @@ -78,16 +82,7 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { `Read ${users.length} GitHub users and ${groups.length} GitHub groups in ${duration} seconds`, ); - // Fill out the hierarchy - const usersByName = new Map(users.map(u => [u.metadata.name, u])); - for (const [groupName, userNames] of groupMemberUsers.entries()) { - for (const userName of userNames) { - const user = usersByName.get(userName); - if (user && !user.spec.memberOf.includes(groupName)) { - user.spec.memberOf.push(groupName); - } - } - } + assignGroupsToUsers(users, groupMemberUsers); buildOrgHierarchy(groups); // Done! @@ -126,18 +121,3 @@ export class GithubOrgReaderProcessor implements CatalogProcessor { return { client, tokenType }; } } - -/* - * Helpers - */ - -export function parseUrl(urlString: string): { org: string } { - const path = new URL(urlString).pathname.substr(1).split('/'); - - // /backstage - if (path.length === 1 && path[0].length) { - return { org: decodeURIComponent(path[0]) }; - } - - throw new Error(`Expected a URL pointing to /`); -} diff --git a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts index cf889eb577..6a85cc07c7 100644 --- a/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts @@ -16,6 +16,7 @@ import { UrlReader } from '@backstage/backend-common'; import { Entity, LocationSpec } from '@backstage/catalog-model'; +import { assertError } from '@backstage/errors'; import parseGitUrl from 'git-url-parse'; import limiterFactory from 'p-limit'; import { Logger } from 'winston'; @@ -91,6 +92,7 @@ export class UrlReaderProcessor implements CatalogProcessor { }); } } catch (error) { + assertError(error); const message = `Unable to read ${location.type}, ${error}`; if (error.name === 'NotModifiedError' && cacheItem) { for (const parseResult of cacheItem.value) { diff --git a/plugins/catalog-backend/src/ingestion/processors/github/index.ts b/plugins/catalog-backend/src/ingestion/processors/github/index.ts index 7c14e21108..3d9e881ddd 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/index.ts @@ -17,7 +17,8 @@ export { readGithubConfig, readGithubMultiOrgConfig } from './config'; export type { GithubMultiOrgConfig, ProviderConfig } from './config'; export { + getOrganizationRepositories, getOrganizationTeams, getOrganizationUsers, - getOrganizationRepositories, } from './github'; +export { parseGitHubOrgUrl } from './util'; diff --git a/packages/techdocs-common/__mocks__/types.d.ts b/plugins/catalog-backend/src/ingestion/processors/github/util.test.ts similarity index 51% rename from packages/techdocs-common/__mocks__/types.d.ts rename to plugins/catalog-backend/src/ingestion/processors/github/util.test.ts index e085b95851..02f54e0675 100644 --- a/packages/techdocs-common/__mocks__/types.d.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/util.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { parseGitHubOrgUrl } from './util'; -interface IStorageFilesMock { - emptyFiles(): void; - fileExists(targetPath: string): boolean; - readFile(targetPath: string): Buffer; - writeFile(targetPath: string, sourcePath: string): void; - writeFile(targetPath: string, sourceBuffer: Buffer): void; - writeFile(targetPath: string, source: string | Buffer): void; -} +describe('parseGitHubOrgUrl', () => { + it('only supports clean org urls, and decodes them', () => { + expect(() => parseGitHubOrgUrl('https://github.com')).toThrow(); + expect(() => parseGitHubOrgUrl('https://github.com/org/foo')).toThrow(); + expect(() => + parseGitHubOrgUrl('https://github.com/org/foo/teams'), + ).toThrow(); + expect(parseGitHubOrgUrl('https://github.com/foo%32')).toEqual({ + org: 'foo2', + }); + }); +}); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/util.ts b/plugins/catalog-backend/src/ingestion/processors/github/util.ts new file mode 100644 index 0000000000..d8df376038 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/github/util.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export function parseGitHubOrgUrl(urlString: string): { org: string } { + const path = new URL(urlString).pathname.substr(1).split('/'); + + // /backstage + if (path.length === 1 && path[0].length) { + return { org: decodeURIComponent(path[0]) }; + } + + throw new Error(`Expected a URL pointing to /`); +} diff --git a/plugins/catalog-backend/src/ingestion/processors/util/org.test.ts b/plugins/catalog-backend/src/ingestion/processors/util/org.test.ts index 254f511c4f..8a8f47642a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/util/org.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/util/org.test.ts @@ -15,7 +15,16 @@ */ import { GroupEntity, UserEntity } from '@backstage/catalog-model'; -import { buildMemberOf, buildOrgHierarchy } from './org'; +import { assignGroupsToUsers, buildMemberOf, buildOrgHierarchy } from './org'; + +function u(name: string, memberOf: string[] = []): UserEntity { + return { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { name }, + spec: { memberOf }, + }; +} function g( name: string, @@ -56,22 +65,33 @@ describe('buildOrgHierarchy', () => { }); }); +describe('assignGroupsToUsers', () => { + it('should assign groups to users', () => { + const users: UserEntity[] = [u('u1'), u('u2')]; + const groupMemberUsers = new Map([ + ['g1', ['u1', 'u2']], + ['g2', ['u2']], + ['g3', ['u3']], + ]); + + assignGroupsToUsers(users, groupMemberUsers); + + expect(users[0].spec.memberOf).toEqual(['g1']); + expect(users[1].spec.memberOf).toEqual(['g1', 'g2']); + }); +}); + describe('buildMemberOf', () => { it('fills indirect member of groups', () => { const a = g('a', undefined, []); const b = g('b', 'a', []); const c = g('c', 'b', []); - const u: UserEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'User', - metadata: { name: 'n' }, - spec: { profile: {}, memberOf: ['c'] }, - }; + const user = u('n', ['c']); const groups = [a, b, c]; buildOrgHierarchy(groups); - buildMemberOf(groups, [u]); - expect(u.spec.memberOf).toEqual(expect.arrayContaining(['a', 'b', 'c'])); + buildMemberOf(groups, [user]); + expect(user.spec.memberOf).toEqual(expect.arrayContaining(['a', 'b', 'c'])); }); it('takes group spec.members into account', () => { @@ -79,16 +99,11 @@ describe('buildMemberOf', () => { const b = g('b', 'a', []); const c = g('c', 'b', []); c.spec.members = ['n']; - const u: UserEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'User', - metadata: { name: 'n' }, - spec: { profile: {}, memberOf: [] }, - }; + const user = u('n'); const groups = [a, b, c]; buildOrgHierarchy(groups); - buildMemberOf(groups, [u]); - expect(u.spec.memberOf).toEqual(expect.arrayContaining(['a', 'b', 'c'])); + buildMemberOf(groups, [user]); + expect(user.spec.memberOf).toEqual(expect.arrayContaining(['a', 'b', 'c'])); }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/util/org.ts b/plugins/catalog-backend/src/ingestion/processors/util/org.ts index bc90362233..3c71f350e6 100644 --- a/plugins/catalog-backend/src/ingestion/processors/util/org.ts +++ b/plugins/catalog-backend/src/ingestion/processors/util/org.ts @@ -49,6 +49,22 @@ export function buildOrgHierarchy(groups: GroupEntity[]) { } } +// Ensure that users have their direct group memberships. +export function assignGroupsToUsers( + users: UserEntity[], + groupMemberUsers: Map, +) { + const usersByName = new Map(users.map(u => [u.metadata.name, u])); + for (const [groupName, userNames] of groupMemberUsers.entries()) { + for (const userName of userNames) { + const user = usersByName.get(userName); + if (user && !user.spec.memberOf.includes(groupName)) { + user.spec.memberOf.push(groupName); + } + } + } +} + // Ensure that users have their transitive group memberships. Requires that // the groups were previously processed with buildOrgHierarchy() export function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) { diff --git a/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.test.ts b/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.test.ts new file mode 100644 index 0000000000..75edea6909 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.test.ts @@ -0,0 +1,235 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getVoidLogger } from '@backstage/backend-common'; +import { GroupEntity, UserEntity } from '@backstage/catalog-model'; +import { + GithubCredentialsProvider, + GitHubIntegrationConfig, +} from '@backstage/integration'; +import { GitHubOrgEntityProvider } from '.'; +import { EntityProviderConnection } from '../../providers'; +import { withLocations } from './GitHubOrgEntityProvider'; +import { graphql } from '@octokit/graphql'; + +jest.mock('@octokit/graphql'); + +describe('GitHubOrgEntityProvider', () => { + describe('read', () => { + afterEach(() => jest.resetAllMocks()); + + it('should read org data and apply mutation', async () => { + const mockClient = jest.fn(); + + mockClient + .mockResolvedValueOnce({ + organization: { + membersWithRole: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + login: 'a', + name: 'b', + bio: 'c', + email: 'd', + avatarUrl: 'e', + }, + ], + }, + }, + }) + .mockResolvedValueOnce({ + organization: { + teams: { + pageInfo: { hasNextPage: false }, + nodes: [ + { + slug: 'team', + combinedSlug: 'blah/team', + name: 'Team', + description: 'The one and only team', + avatarUrl: 'http://example.com/team.jpeg', + parentTeam: { + slug: 'parent', + combinedSlug: '', + members: { pageInfo: { hasNextPage: false }, nodes: [] }, + }, + members: { + pageInfo: { hasNextPage: false }, + nodes: [{ login: 'a' }], + }, + }, + ], + }, + }, + }); + + (graphql.defaults as jest.Mock).mockReturnValue(mockClient); + + const entityProviderConnection: EntityProviderConnection = { + applyMutation: jest.fn(), + }; + + const logger = getVoidLogger(); + const gitHubConfig: GitHubIntegrationConfig = { + host: 'https://github.com', + }; + + const mockGetCredentials = jest.fn().mockReturnValue({ + headers: { token: 'blah' }, + type: 'app', + }); + + jest.spyOn(GithubCredentialsProvider, 'create').mockReturnValue({ + getCredentials: mockGetCredentials, + } as any); + + const entityProvider = new GitHubOrgEntityProvider({ + id: 'my-id', + orgUrl: 'https://github.com/backstage', + gitHubConfig, + logger, + }); + + entityProvider.connect(entityProviderConnection); + + await entityProvider.read(); + + expect(entityProviderConnection.applyMutation).toBeCalledWith({ + entities: [ + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://https://github.com/a', + 'backstage.io/managed-by-origin-location': + 'url:https://https://github.com/a', + 'github.com/user-login': 'a', + }, + description: 'c', + name: 'a', + }, + spec: { + memberOf: ['team'], + profile: { + displayName: 'b', + email: 'd', + picture: 'e', + }, + }, + }, + locationKey: 'github-org-provider:my-id', + }, + { + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + annotations: { + 'backstage.io/managed-by-location': + 'url:https://https://github.com/orgs/backstage/teams/team', + 'backstage.io/managed-by-origin-location': + 'url:https://https://github.com/orgs/backstage/teams/team', + 'github.com/team-slug': 'blah/team', + }, + name: 'team', + description: 'The one and only team', + }, + spec: { + children: [], + parent: 'parent', + profile: { + displayName: 'Team', + picture: 'http://example.com/team.jpeg', + }, + type: 'team', + }, + }, + locationKey: 'github-org-provider:my-id', + }, + ], + type: 'full', + }); + }); + }); + + describe('withLocations', () => { + it('should set location for user', () => { + const entity: UserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'githubuser', + }, + spec: { + memberOf: [], + }, + }; + + expect(withLocations('https://github.com', 'backstage', entity)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: 'githubuser', + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/githubuser', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/githubuser', + }, + }, + spec: { + memberOf: [], + }, + }); + }); + + it('should set location for group', () => { + const entity: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'mygroup', + }, + spec: { + type: 'team', + children: [], + }, + }; + + expect(withLocations('https://github.com', 'backstage', entity)).toEqual({ + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: 'mygroup', + annotations: { + 'backstage.io/managed-by-location': + 'url:https://github.com/orgs/backstage/teams/mygroup', + 'backstage.io/managed-by-origin-location': + 'url:https://github.com/orgs/backstage/teams/mygroup', + }, + }, + spec: { + type: 'team', + children: [], + }, + }); + }); + }); +}); diff --git a/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts b/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts new file mode 100644 index 0000000000..ecd0d153d1 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/providers/GitHubOrgEntityProvider.ts @@ -0,0 +1,180 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + Entity, + LOCATION_ANNOTATION, + ORIGIN_LOCATION_ANNOTATION, +} from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { + GithubCredentialsProvider, + GitHubIntegrationConfig, + ScmIntegrations, +} from '@backstage/integration'; +import { graphql } from '@octokit/graphql'; +import { merge } from 'lodash'; +import { Logger } from 'winston'; +import { + EntityProvider, + EntityProviderConnection, +} from '../../providers/types'; +import { + getOrganizationTeams, + getOrganizationUsers, + parseGitHubOrgUrl, +} from '../processors/github'; +import { assignGroupsToUsers, buildOrgHierarchy } from '../processors/util/org'; + +// TODO: Consider supporting an (optional) webhook that reacts on org changes + +export class GitHubOrgEntityProvider implements EntityProvider { + private connection?: EntityProviderConnection; + private readonly credentialsProvider: GithubCredentialsProvider; + + static fromConfig( + config: Config, + options: { id: string; orgUrl: string; logger: Logger }, + ) { + const integrations = ScmIntegrations.fromConfig(config); + const gitHubConfig = integrations.github.byUrl(options.orgUrl)?.config; + + if (!gitHubConfig) { + throw new Error( + `There is no GitHub Org provider that matches ${options.orgUrl}. Please add a configuration for an integration.`, + ); + } + + const logger = options.logger.child({ + target: options.orgUrl, + }); + + return new GitHubOrgEntityProvider({ + id: options.id, + orgUrl: options.orgUrl, + logger, + gitHubConfig, + }); + } + + constructor( + private options: { + id: string; + orgUrl: string; + gitHubConfig: GitHubIntegrationConfig; + logger: Logger; + }, + ) { + this.credentialsProvider = GithubCredentialsProvider.create( + options.gitHubConfig, + ); + } + + getProviderName() { + return `GitHubOrgEntityProvider:${this.options.id}`; + } + + async connect(connection: EntityProviderConnection) { + this.connection = connection; + } + + async read() { + if (!this.connection) { + throw new Error('Not initialized'); + } + + const { markReadComplete } = trackProgress(this.options.logger); + + const { headers, type: tokenType } = + await this.credentialsProvider.getCredentials({ + url: this.options.orgUrl, + }); + const client = graphql.defaults({ + baseUrl: this.options.gitHubConfig.apiBaseUrl, + headers, + }); + + const { org } = parseGitHubOrgUrl(this.options.orgUrl); + const { users } = await getOrganizationUsers(client, org, tokenType); + const { groups, groupMemberUsers } = await getOrganizationTeams( + client, + org, + ); + assignGroupsToUsers(users, groupMemberUsers); + buildOrgHierarchy(groups); + + const { markCommitComplete } = markReadComplete({ users, groups }); + + await this.connection.applyMutation({ + type: 'full', + entities: [...users, ...groups].map(entity => ({ + locationKey: `github-org-provider:${this.options.id}`, + entity: withLocations( + `https://${this.options.gitHubConfig.host}`, + org, + entity, + ), + })), + }); + + markCommitComplete(); + } +} + +// Helps wrap the timing and logging behaviors +function trackProgress(logger: Logger) { + let timestamp = Date.now(); + let summary: string; + + logger.info('Reading GitHub users and groups'); + + function markReadComplete(read: { users: unknown[]; groups: unknown[] }) { + summary = `${read.users.length} GitHub users and ${read.groups.length} GitHub groups`; + const readDuration = ((Date.now() - timestamp) / 1000).toFixed(1); + timestamp = Date.now(); + logger.info(`Read ${summary} in ${readDuration} seconds. Committing...`); + return { markCommitComplete }; + } + + function markCommitComplete() { + const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1); + logger.info(`Committed ${summary} in ${commitDuration} seconds.`); + } + + return { markReadComplete }; +} + +// Makes sure that emitted entities have a proper location +export function withLocations( + baseUrl: string, + org: string, + entity: Entity, +): Entity { + const location = + entity.kind === 'Group' + ? `url:${baseUrl}/orgs/${org}/teams/${entity.metadata.name}` + : `url:${baseUrl}/${entity.metadata.name}`; + return merge( + { + metadata: { + annotations: { + [LOCATION_ANNOTATION]: location, + [ORIGIN_LOCATION_ANNOTATION]: location, + }, + }, + }, + entity, + ) as Entity; +} diff --git a/plugins/catalog-backend/src/ingestion/providers/index.ts b/plugins/catalog-backend/src/ingestion/providers/index.ts new file mode 100644 index 0000000000..cd1bc5cb36 --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/providers/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { GitHubOrgEntityProvider } from './GitHubOrgEntityProvider'; diff --git a/plugins/catalog-backend/src/legacy/ingestion/LocationReaders.ts b/plugins/catalog-backend/src/legacy/ingestion/LocationReaders.ts index 91902ce5be..04347615e5 100644 --- a/plugins/catalog-backend/src/legacy/ingestion/LocationReaders.ts +++ b/plugins/catalog-backend/src/legacy/ingestion/LocationReaders.ts @@ -255,7 +255,7 @@ export class LocationReaders implements LocationReader { const message = `Policy check failed while analyzing entity ${kind}:${namespace}/${name} at ${stringifyLocationReference( item.location, )}, ${e}`; - emit(result.inputError(item.location, e.message)); + emit(result.inputError(item.location, message)); logger.warn(message); return undefined; } diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 59cd4d94ae..1ce32a01e1 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -19,7 +19,7 @@ import { entityEnvelopeSchemaValidator, stringifyEntityRef, } from '@backstage/catalog-model'; -import { serializeError } from '@backstage/errors'; +import { assertError, serializeError } from '@backstage/errors'; import { Hash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; import { Logger } from 'winston'; @@ -257,6 +257,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { track.markSuccessfulWithChanges(setOfThingsToStitch.size); } catch (error) { + assertError(error); track.markFailed(error); } }, diff --git a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts index e973dcbf0c..d3ec162216 100644 --- a/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts @@ -23,7 +23,12 @@ import { stringifyEntityRef, stringifyLocationReference, } from '@backstage/catalog-model'; -import { ConflictError, InputError, NotAllowedError } from '@backstage/errors'; +import { + assertError, + ConflictError, + InputError, + NotAllowedError, +} from '@backstage/errors'; import { JsonValue } from '@backstage/config'; import { ScmIntegrationRegistry } from '@backstage/integration'; import path from 'path'; @@ -160,6 +165,7 @@ export class DefaultCatalogProcessingOrchestrator ok: collectorResults.errors.length === 0, }; } catch (error) { + assertError(error); return { ok: false, errors: collector.results().errors.concat(error), diff --git a/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts index dfaa25418b..436038db66 100644 --- a/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts +++ b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts @@ -21,6 +21,7 @@ import { ORIGIN_LOCATION_ANNOTATION, stringifyLocationReference, } from '@backstage/catalog-model'; +import { assertError } from '@backstage/errors'; import { Logger } from 'winston'; import { CatalogProcessorResult } from '../ingestion'; import { locationSpecToLocationEntity } from '../util/conversion'; @@ -73,6 +74,7 @@ export class ProcessorOutputCollector { try { entity = validateEntityEnvelope(i.entity); } catch (e) { + assertError(e); this.logger.debug(`Envelope validation failed at ${i.location}, ${e}`); this.errors.push(e); return; diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts index bb556fc49f..20e141b921 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.test.ts @@ -37,6 +37,20 @@ const expectedEntities: Entity[] = [ owner: 'someone', }, }, + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + title: 'Test Entity', + name: 'test-entity-2', + description: 'The expected description 2', + }, + spec: { + type: 'some-type', + lifecycle: 'experimental', + owner: 'someone', + }, + }, ]; describe('DefaultCatalogCollator', () => { @@ -89,6 +103,15 @@ describe('DefaultCatalogCollator', () => { lifecycle: expectedEntities[0]!.spec!.lifecycle, owner: expectedEntities[0]!.spec!.owner, }); + expect(documents[1]).toMatchObject({ + title: expectedEntities[1].metadata.title, + location: '/catalog/default/component/test-entity-2', + text: expectedEntities[1].metadata.description, + namespace: 'default', + componentType: expectedEntities[1]!.spec!.type, + lifecycle: expectedEntities[1]!.spec!.lifecycle, + owner: expectedEntities[1]!.spec!.owner, + }); }); it('maps a returned entity with a custom locationTemplate', async () => { diff --git a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts index 6292b2a833..a28a7645c4 100644 --- a/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts +++ b/plugins/catalog-backend/src/search/DefaultCatalogCollator.ts @@ -87,7 +87,7 @@ export class DefaultCatalogCollator implements DocumentCollator { }); return response.items.map((entity: Entity): CatalogEntityDocument => { return { - title: entity.metadata.name, + title: entity.metadata.title ?? entity.metadata.name, location: this.applyArgsToFormat(this.locationTemplate, { namespace: entity.metadata.namespace || 'default', kind: entity.kind, diff --git a/plugins/catalog-backend/src/stitching/Stitcher.ts b/plugins/catalog-backend/src/stitching/Stitcher.ts index 0aa39f5ac8..507f3aa53e 100644 --- a/plugins/catalog-backend/src/stitching/Stitcher.ts +++ b/plugins/catalog-backend/src/stitching/Stitcher.ts @@ -20,7 +20,7 @@ import { parseEntityRef, UNSTABLE_EntityStatusItem, } from '@backstage/catalog-model'; -import { SerializedError } from '@backstage/errors'; +import { SerializedError, stringifyError } from '@backstage/errors'; import { Knex } from 'knex'; import { uniqBy } from 'lodash'; import { v4 as uuid } from 'uuid'; @@ -47,194 +47,198 @@ export class Stitcher { async stitch(entityRefs: Set) { for (const entityRef of entityRefs) { try { - const entityResult = await this.database( - 'refresh_state', - ) - .where({ entity_ref: entityRef }) - .limit(1) - .select('entity_id'); - if (!entityResult.length) { - // Entity does no exist in refresh state table, no stitching required. - continue; - } - - // Insert stitching ticket that will be compared before inserting the final entity. - const ticket = uuid(); - await this.database('final_entities') - .insert({ - entity_id: entityResult[0].entity_id, - hash: '', - stitch_ticket: ticket, - }) - .onConflict('entity_id') - .merge(['stitch_ticket']); - - // Selecting from refresh_state and final_entities should yield exactly - // one row (except in abnormal cases where the stitch was invoked for - // something that didn't exist at all, in which case it's zero rows). - // The join with the temporary incoming_references still gives one row. - // The only result set "expanding" join is the one with relations, so - // the output should be at least one row (if zero or one relations were - // found), or at most the same number of rows as relations. - const result: Array<{ - entityId: string; - processedEntity?: string; - errors: string; - incomingReferenceCount: string | number; - previousHash?: string; - relationType?: string; - relationTarget?: string; - }> = await this.database - .with('incoming_references', function incomingReferences(builder) { - return builder - .from('refresh_state_references') - .where({ target_entity_ref: entityRef }) - .count({ count: '*' }); - }) - .select({ - entityId: 'refresh_state.entity_id', - processedEntity: 'refresh_state.processed_entity', - errors: 'refresh_state.errors', - incomingReferenceCount: 'incoming_references.count', - previousHash: 'final_entities.hash', - relationType: 'relations.type', - relationTarget: 'relations.target_entity_ref', - }) - .from('refresh_state') - .where({ 'refresh_state.entity_ref': entityRef }) - .crossJoin(this.database.raw('incoming_references')) - .leftOuterJoin('final_entities', { - 'final_entities.entity_id': 'refresh_state.entity_id', - }) - .leftOuterJoin('relations', { - 'relations.source_entity_ref': 'refresh_state.entity_ref', - }) - .orderBy('relationType', 'asc') - .orderBy('relationTarget', 'asc'); - - // If there were no rows returned, it would mean that there was no - // matching row even in the refresh_state. This can happen for example - // if we emit a relation to something that hasn't been ingested yet. - // It's safe to ignore this stitch attempt in that case. - if (!result.length) { - this.logger.error( - `Unable to stitch ${entityRef}, item does not exist in refresh state table`, - ); - continue; - } - - const { - entityId, - processedEntity, - errors, - incomingReferenceCount, - previousHash, - } = result[0]; - - // If there was no processed entity in place, the target hasn't been - // through the processing steps yet. It's safe to ignore this stitch - // attempt in that case, since another stitch will be triggered when - // that processing has finished. - if (!processedEntity) { - this.logger.debug( - `Unable to stitch ${entityRef}, the entity has not yet been processed`, - ); - continue; - } - - // Grab the processed entity and stitch all of the relevant data into - // it - const entity = JSON.parse(processedEntity) as Entity; - const isOrphan = Number(incomingReferenceCount) === 0; - let statusItems: UNSTABLE_EntityStatusItem[] = []; - - if (isOrphan) { - this.logger.debug(`${entityRef} is an orphan`); - entity.metadata.annotations = { - ...entity.metadata.annotations, - ['backstage.io/orphan']: 'true', - }; - } - if (errors) { - const parsedErrors = JSON.parse(errors) as SerializedError[]; - if (Array.isArray(parsedErrors) && parsedErrors.length) { - statusItems = parsedErrors.map(e => ({ - type: ENTITY_STATUS_CATALOG_PROCESSING_TYPE, - level: 'error', - message: `${e.name}: ${e.message}`, - error: e, - })); - } - } - - // TODO: entityRef is lower case and should be uppercase in the final - // result - const uniqueRelationRows = uniqBy( - result, - r => `${r.relationType}:${r.relationTarget}`, - ); - entity.relations = uniqueRelationRows - .filter(row => row.relationType /* exclude null row, if relevant */) - .map(row => ({ - type: row.relationType!, - target: parseEntityRef(row.relationTarget!), - })); - if (statusItems.length) { - entity.status = { - ...entity.status, - items: [...(entity.status?.items ?? []), ...statusItems], - }; - } - - // If the output entity was actually not changed, just abort - const hash = generateStableHash(entity); - if (hash === previousHash) { - this.logger.debug(`Skipped stitching of ${entityRef}, no changes`); - continue; - } - - entity.metadata.uid = entityId; - entity.metadata.generation = 1; - if (!entity.metadata.etag) { - // If the original data source did not have its own etag handling, - // use the hash as a good-quality etag - entity.metadata.etag = hash; - } - - const rowsChanged = await this.database( - 'final_entities', - ) - .update({ - final_entity: JSON.stringify(entity), - hash, - }) - .where('entity_id', entityId) - .where('stitch_ticket', ticket) - .onConflict('entity_id') - .merge(['final_entity', 'hash']); - - if (rowsChanged.length === 0) { - this.logger.debug( - `Entity ${entityRef} is already processed, skipping write.`, - ); - continue; - } - - // TODO(freben): Search will probably need a similar safeguard against - // race conditions like the final_entities ticket handling above. - // Otherwise, it can be the case that: - // A writes the entity -> - // B writes the entity -> - // B writes search -> - // A writes search - const searchEntries = buildEntitySearch(entityId, entity); - await this.database('search') - .where({ entity_id: entityId }) - .delete(); - await this.database.batchInsert('search', searchEntries, BATCH_SIZE); + await this.stitchOne(entityRef); } catch (error) { - this.logger.error(`Failed to stitch ${entityRef}, ${error}`); + this.logger.error( + `Failed to stitch ${entityRef}, ${stringifyError(error)}`, + ); } } } + + private async stitchOne(entityRef: string): Promise { + const entityResult = await this.database('refresh_state') + .where({ entity_ref: entityRef }) + .limit(1) + .select('entity_id'); + if (!entityResult.length) { + // Entity does no exist in refresh state table, no stitching required. + return; + } + + // Insert stitching ticket that will be compared before inserting the final entity. + const ticket = uuid(); + await this.database('final_entities') + .insert({ + entity_id: entityResult[0].entity_id, + hash: '', + stitch_ticket: ticket, + }) + .onConflict('entity_id') + .merge(['stitch_ticket']); + + // Selecting from refresh_state and final_entities should yield exactly + // one row (except in abnormal cases where the stitch was invoked for + // something that didn't exist at all, in which case it's zero rows). + // The join with the temporary incoming_references still gives one row. + // The only result set "expanding" join is the one with relations, so + // the output should be at least one row (if zero or one relations were + // found), or at most the same number of rows as relations. + const result: Array<{ + entityId: string; + processedEntity?: string; + errors: string; + incomingReferenceCount: string | number; + previousHash?: string; + relationType?: string; + relationTarget?: string; + }> = await this.database + .with('incoming_references', function incomingReferences(builder) { + return builder + .from('refresh_state_references') + .where({ target_entity_ref: entityRef }) + .count({ count: '*' }); + }) + .select({ + entityId: 'refresh_state.entity_id', + processedEntity: 'refresh_state.processed_entity', + errors: 'refresh_state.errors', + incomingReferenceCount: 'incoming_references.count', + previousHash: 'final_entities.hash', + relationType: 'relations.type', + relationTarget: 'relations.target_entity_ref', + }) + .from('refresh_state') + .where({ 'refresh_state.entity_ref': entityRef }) + .crossJoin(this.database.raw('incoming_references')) + .leftOuterJoin('final_entities', { + 'final_entities.entity_id': 'refresh_state.entity_id', + }) + .leftOuterJoin('relations', { + 'relations.source_entity_ref': 'refresh_state.entity_ref', + }) + .orderBy('relationType', 'asc') + .orderBy('relationTarget', 'asc'); + + // If there were no rows returned, it would mean that there was no + // matching row even in the refresh_state. This can happen for example + // if we emit a relation to something that hasn't been ingested yet. + // It's safe to ignore this stitch attempt in that case. + if (!result.length) { + this.logger.error( + `Unable to stitch ${entityRef}, item does not exist in refresh state table`, + ); + return; + } + + const { + entityId, + processedEntity, + errors, + incomingReferenceCount, + previousHash, + } = result[0]; + + // If there was no processed entity in place, the target hasn't been + // through the processing steps yet. It's safe to ignore this stitch + // attempt in that case, since another stitch will be triggered when + // that processing has finished. + if (!processedEntity) { + this.logger.debug( + `Unable to stitch ${entityRef}, the entity has not yet been processed`, + ); + return; + } + + // Grab the processed entity and stitch all of the relevant data into + // it + const entity = JSON.parse(processedEntity) as Entity; + const isOrphan = Number(incomingReferenceCount) === 0; + let statusItems: UNSTABLE_EntityStatusItem[] = []; + + if (isOrphan) { + this.logger.debug(`${entityRef} is an orphan`); + entity.metadata.annotations = { + ...entity.metadata.annotations, + ['backstage.io/orphan']: 'true', + }; + } + if (errors) { + const parsedErrors = JSON.parse(errors) as SerializedError[]; + if (Array.isArray(parsedErrors) && parsedErrors.length) { + statusItems = parsedErrors.map(e => ({ + type: ENTITY_STATUS_CATALOG_PROCESSING_TYPE, + level: 'error', + message: `${e.name}: ${e.message}`, + error: e, + })); + } + } + + // TODO: entityRef is lower case and should be uppercase in the final + // result + const uniqueRelationRows = uniqBy( + result, + r => `${r.relationType}:${r.relationTarget}`, + ); + entity.relations = uniqueRelationRows + .filter(row => row.relationType /* exclude null row, if relevant */) + .map(row => ({ + type: row.relationType!, + target: parseEntityRef(row.relationTarget!), + })); + if (statusItems.length) { + entity.status = { + ...entity.status, + items: [...(entity.status?.items ?? []), ...statusItems], + }; + } + + // If the output entity was actually not changed, just abort + const hash = generateStableHash(entity); + if (hash === previousHash) { + this.logger.debug(`Skipped stitching of ${entityRef}, no changes`); + return; + } + + entity.metadata.uid = entityId; + entity.metadata.generation = 1; + if (!entity.metadata.etag) { + // If the original data source did not have its own etag handling, + // use the hash as a good-quality etag + entity.metadata.etag = hash; + } + + const rowsChanged = await this.database( + 'final_entities', + ) + .update({ + final_entity: JSON.stringify(entity), + hash, + }) + .where('entity_id', entityId) + .where('stitch_ticket', ticket) + .onConflict('entity_id') + .merge(['final_entity', 'hash']); + + if (rowsChanged.length === 0) { + this.logger.debug( + `Entity ${entityRef} is already processed, skipping write.`, + ); + return; + } + + // TODO(freben): Search will probably need a similar safeguard against + // race conditions like the final_entities ticket handling above. + // Otherwise, it can be the case that: + // A writes the entity -> + // B writes the entity -> + // B writes search -> + // A writes search + const searchEntries = buildEntitySearch(entityId, entity); + await this.database('search') + .where({ entity_id: entityId }) + .delete(); + await this.database.batchInsert('search', searchEntries, BATCH_SIZE); + } } diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index 20eb85af21..a156be8fe0 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,29 @@ # @backstage/plugin-catalog-graph +## 0.2.1 + +### Patch Changes + +- ce0aef1841: Capture analytics events for clicks in the graph. +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.2.0 + +### Minor Changes + +- 5c42360577: Add documentation and more type safety around DependencyGraph + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.3 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index e2de70e510..b0dca011ca 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.1.3", + "version": "0.2.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,11 +22,11 @@ }, "dependencies": { "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -41,10 +41,10 @@ "p-limit": "^3.1.0" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", - "@backstage/core-app-api": "^0.1.16", + "@backstage/cli": "^0.8.0", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", + "@backstage/core-app-api": "^0.1.18", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx index 7e3149fef7..9fe482a30b 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.test.tsx @@ -15,12 +15,14 @@ */ import { Entity } from '@backstage/catalog-model'; import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { analyticsApiRef } from '@backstage/core-plugin-api'; import { CatalogApi, catalogApiRef, EntityProvider, } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { MockAnalyticsApi, renderInTestApp } from '@backstage/test-utils'; +import userEvent from '@testing-library/user-event'; import React from 'react'; import { catalogEntityRouteRef, catalogGraphRouteRef } from '../../routes'; import { CatalogGraphCard } from './CatalogGraphCard'; @@ -117,4 +119,30 @@ describe('', () => { '/catalog-graph?rootEntityRefs%5B%5D=b%3Ad%2Fc', ); }); + + test('captures analytics event on click', async () => { + const analyticsSpy = new MockAnalyticsApi(); + const { findByText } = await renderInTestApp( + + {wrapper} + , + { + mountedRoutes: { + '/entity/{kind}/{namespace}/{name}': catalogEntityRouteRef, + '/catalog-graph': catalogGraphRouteRef, + }, + }, + ); + + expect(await findByText('b:d/c')).toBeInTheDocument(); + userEvent.click(await findByText('b:d/c')); + + expect(analyticsSpy.getEvents()[0]).toMatchObject({ + action: 'click', + subject: 'b:d/c', + attributes: { + to: '/entity/{kind}/{namespace}/{name}', + }, + }); + }); }); diff --git a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx index 5ac8a89539..42e85a75ba 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphCard/CatalogGraphCard.tsx @@ -19,8 +19,11 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { InfoCard, InfoCardVariants } from '@backstage/core-components'; -import { useRouteRef } from '@backstage/core-plugin-api'; -import { useEntity } from '@backstage/plugin-catalog-react'; +import { useAnalytics, useRouteRef } from '@backstage/core-plugin-api'; +import { + formatEntityRefTitle, + useEntity, +} from '@backstage/plugin-catalog-react'; import { makeStyles, Theme } from '@material-ui/core'; import qs from 'qs'; import React, { MouseEvent, useCallback } from 'react'; @@ -78,6 +81,7 @@ export const CatalogGraphCard = ({ const catalogGraphRoute = useRouteRef(catalogGraphRouteRef); const navigate = useNavigate(); const classes = useStyles({ height }); + const analytics = useAnalytics(); const onNodeClick = useCallback( (node: EntityNode, _: MouseEvent) => { @@ -87,9 +91,14 @@ export const CatalogGraphCard = ({ namespace: nodeEntityName.namespace.toLocaleLowerCase('en-US'), name: nodeEntityName.name, }); + analytics.captureEvent( + 'click', + node.title ?? formatEntityRefTitle(nodeEntityName), + { attributes: { to: path } }, + ); navigate(path); }, - [catalogEntityRoute, navigate], + [catalogEntityRoute, navigate, analytics], ); const catalogGraphParams = qs.stringify( diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx index 8b467a017e..b992d0c976 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.test.tsx @@ -15,8 +15,9 @@ */ import { RELATION_HAS_PART, RELATION_PART_OF } from '@backstage/catalog-model'; import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { analyticsApiRef } from '@backstage/core-plugin-api'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; -import { renderInTestApp } from '@backstage/test-utils'; +import { MockAnalyticsApi, renderInTestApp } from '@backstage/test-utils'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { catalogEntityRouteRef } from '../../routes'; @@ -167,4 +168,53 @@ describe('', () => { expect(navigate).toBeCalledWith('/entity/{kind}/{namespace}/{name}'); }); + + test('should capture analytics event when selecting other entity', async () => { + const analyticsSpy = new MockAnalyticsApi(); + const { getByText, findAllByTestId } = await renderInTestApp( + + {wrapper} + , + { + mountedRoutes: { + '/entity/{kind}/{namespace}/{name}': catalogEntityRouteRef, + }, + }, + ); + + expect(await findAllByTestId('node')).toHaveLength(2); + + userEvent.click(getByText('b:d/e')); + + expect(analyticsSpy.getEvents()[0]).toMatchObject({ + action: 'click', + subject: 'b:d/e', + }); + }); + + test('should capture analytics event when navigating to entity', async () => { + const analyticsSpy = new MockAnalyticsApi(); + const { getByText, findAllByTestId } = await renderInTestApp( + + {wrapper} + , + { + mountedRoutes: { + '/entity/{kind}/{namespace}/{name}': catalogEntityRouteRef, + }, + }, + ); + + expect(await findAllByTestId('node')).toHaveLength(2); + + userEvent.click(getByText('b:d/e'), { shiftKey: true }); + + expect(analyticsSpy.getEvents()[0]).toMatchObject({ + action: 'click', + subject: 'b:d/e', + attributes: { + to: '/entity/{kind}/{namespace}/{name}', + }, + }); + }); }); diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx index f5f1ced541..fdcb71d3ad 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/CatalogGraphPage.tsx @@ -21,7 +21,7 @@ import { Page, SupportButton, } from '@backstage/core-components'; -import { useRouteRef } from '@backstage/core-plugin-api'; +import { useAnalytics, useRouteRef } from '@backstage/core-plugin-api'; import { formatEntityRefTitle } from '@backstage/plugin-catalog-react'; import { Grid, makeStyles, Paper, Typography } from '@material-ui/core'; import FilterListIcon from '@material-ui/icons/FilterList'; @@ -31,11 +31,11 @@ import React, { MouseEvent, useCallback } from 'react'; import { useNavigate } from 'react-router'; import { catalogEntityRouteRef } from '../../routes'; import { + ALL_RELATION_PAIRS, Direction, EntityNode, EntityRelationsGraph, RelationPairs, - ALL_RELATION_PAIRS, } from '../EntityRelationsGraph'; import { DirectionFilter } from './DirectionFilter'; import { MaxDepthFilter } from './MaxDepthFilter'; @@ -133,6 +133,7 @@ export const CatalogGraphPage = ({ showFilters, toggleShowFilters, } = useCatalogGraphPage({ initialState }); + const analytics = useAnalytics(); const onNodeClick = useCallback( (node: EntityNode, event: MouseEvent) => { const nodeEntityName = parseEntityRef(node.id); @@ -143,12 +144,22 @@ export const CatalogGraphPage = ({ namespace: nodeEntityName.namespace.toLocaleLowerCase('en-US'), name: nodeEntityName.name, }); + + analytics.captureEvent( + 'click', + node.title ?? formatEntityRefTitle(nodeEntityName), + { attributes: { to: path } }, + ); navigate(path); } else { + analytics.captureEvent( + 'click', + node.title ?? formatEntityRefTitle(nodeEntityName), + ); setRootEntityNames([nodeEntityName]); } }, - [catalogEntityRoute, navigate, setRootEntityNames], + [catalogEntityRoute, navigate, setRootEntityNames, analytics], ); return ( diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index f0c8b3a9a8..80ad7f9a16 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.0", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.8", "@graphql-modules/core": "^0.7.17", "apollo-server": "^2.16.1", @@ -42,7 +42,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.7.0", + "@backstage/cli": "^0.8.0", "@backstage/test-utils": "^0.1.11", "@graphql-codegen/cli": "^1.21.3", "@graphql-codegen/typescript": "^1.17.7", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 9b13184018..d06f38698b 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,27 @@ # @backstage/plugin-catalog-import +## 0.7.3 + +### Patch Changes + +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/errors@0.1.3 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.7.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/integration@0.6.8 + - @backstage/core-components@0.7.0 + - @backstage/integration-react@0.1.12 + ## 0.7.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index f571b5df31..fe453ca45d 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-import", "description": "A Backstage plugin the helps you import entities into your catalog", - "version": "0.7.1", + "version": "0.7.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,13 @@ }, "dependencies": { "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/integration": "^0.6.7", - "@backstage/integration-react": "^0.1.11", - "@backstage/plugin-catalog-react": "^0.5.2", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", + "@backstage/integration-react": "^0.1.12", + "@backstage/plugin-catalog-react": "^0.6.1", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -54,10 +55,10 @@ "lodash": "^4.17.21" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx index 75910db5a2..7784aa7284 100644 --- a/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx +++ b/plugins/catalog-import/src/components/StepInitAnalyzeUrl/StepInitAnalyzeUrl.tsx @@ -113,8 +113,8 @@ export const StepInitAnalyzeUrl = ({ break; } } - } catch (e) { - setError(e.data?.error?.message ?? e.message); + } catch (e: any) { + setError(e?.data?.error?.message ?? e.message); setSubmitted(false); } }, diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx index ea3ea3e96f..fe5e76c968 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx @@ -45,7 +45,7 @@ const entities: Entity[] = [ ]; describe('', () => { - it('renders without exploding', async () => { + it('renders without exploding', () => { render( ', () => { const repositoryUrl = screen.getByText( 'http://my-repository/a/catalog-info.yaml', ); - const kindText = await screen.findByText('Kind_2'); + const kindText = screen.getByText(/Kind_2/); expect(repositoryUrl).toBeInTheDocument(); expect(repositoryUrl).toBeVisible(); expect(kindText).toBeInTheDocument(); expect(kindText).toBeVisible(); }); - it('renders card with custom styles', async () => { + it('renders card with custom styles', () => { const { result } = renderHook(() => useStyles()); render( @@ -77,14 +77,14 @@ describe('', () => { const repositoryUrl = screen.getByText( 'http://my-repository/a/catalog-info.yaml', ); - const kindText = await screen.findByText('Kind_2'); + const kindText = screen.getByText(/Kind_2/); expect(repositoryUrl).toBeInTheDocument(); expect(repositoryUrl).not.toBeVisible(); expect(kindText).toBeInTheDocument(); expect(kindText).not.toBeVisible(); }); - it('renders with custom styles', async () => { + it('renders with custom styles', () => { const { result } = renderHook(() => useStyles()); render( @@ -98,7 +98,7 @@ describe('', () => { const repositoryUrl = screen.getByText( 'http://my-repository/a/catalog-info.yaml', ); - const kindText = await screen.findByText('Kind_2'); + const kindText = screen.getByText(/Kind_2/); expect(repositoryUrl).toBeInTheDocument(); expect(repositoryUrl).toBeVisible(); expect(kindText).toBeInTheDocument(); diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx index 6cabc52ddb..f441554119 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/StepPrepareCreatePullRequest.tsx @@ -16,6 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { assertError } from '@backstage/errors'; import { catalogApiRef, formatEntityRefTitle, @@ -174,6 +175,7 @@ export const StepPrepareCreatePullRequest = ({ { notRepeatable: true }, ); } catch (e) { + assertError(e); setError(e.message); setSubmitted(false); } diff --git a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx index 99dc972678..5c4f9b9594 100644 --- a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx +++ b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx @@ -25,6 +25,7 @@ import { PrepareResult, ReviewResult } from '../useImportState'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Link } from '@backstage/core-components'; import { stringifyEntityRef } from '@backstage/catalog-model'; +import { assertError } from '@backstage/errors'; type Props = { prepareResult: PrepareResult; @@ -88,6 +89,7 @@ export const StepReviewLocation = ({ locations, }); } catch (e) { + assertError(e); // TODO: this error should be handled differently. We add it as 'optional' and // it is not uncommon that a PR has not been merged yet. if ( diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index ef2dd15f93..26999f9e35 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,38 @@ # @backstage/plugin-catalog-react +## 0.6.1 + +### Patch Changes + +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/errors@0.1.3 + - @backstage/core-app-api@0.1.18 + - @backstage/core-plugin-api@0.1.11 + - @backstage/catalog-model@0.9.5 + +## 0.6.0 + +### Minor Changes + +- 82fbda923e: Introduce a new `StarredEntitiesApi` that is used in the `useStarredEntities` hook. + The `@backstage/plugin-catalog` installs a default implementation that is backed by the `StorageApi`, but one can also override the `starredEntitiesApiRef`. + + This change also updates the storage format from a custom string to an entity reference and moves the location in the local storage. + A migration will convert the previously starred entities to the location on the first load of Backstage. + +### Patch Changes + +- 0366c9b667: Introduce a `useStarredEntity` hook to check if a single entity is starred. + It provides a more efficient implementation compared to the `useStarredEntities` hook, because the rendering is only triggered if the selected entity is starred, not if _any_ entity is starred. +- 4aca84f86b: Support `material-ui` overrides in plugin-catalog-react components +- b03b9f19e0: added sorting in entity `Name` column by `metadata.title` if present +- Updated dependencies + - @backstage/integration@0.6.8 + - @backstage/core-app-api@0.1.17 + - @backstage/core-components@0.7.0 + ## 0.5.2 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 9ddee679c3..3373641d16 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog-react", "description": "A frontend library that helps other Backstage plugins interact with the catalog", - "version": "0.5.2", + "version": "0.6.1", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,11 +30,12 @@ }, "dependencies": { "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-app-api": "^0.1.16", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/integration": "^0.6.7", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-app-api": "^0.1.18", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", "@backstage/version-bridge": "^0.1.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -49,8 +50,8 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx index 4dce00e7b7..5c267916ea 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/UnregisterEntityDialog.tsx @@ -33,6 +33,7 @@ import { useUnregisterEntityDialogState } from './useUnregisterEntityDialogState import { alertApiRef, configApiRef, useApi } from '@backstage/core-plugin-api'; import { Progress, ResponseErrorPanel } from '@backstage/core-components'; +import { assertError } from '@backstage/errors'; const useStyles = makeStyles({ advancedButton: { @@ -70,6 +71,7 @@ const Contents = ({ await state.unregisterLocation(); onConfirm(); } catch (err) { + assertError(err); alertApi.post({ message: err.message }); } finally { setBusy(false); @@ -87,6 +89,7 @@ const Contents = ({ await state.deleteEntity(); onConfirm(); } catch (err) { + assertError(err); alertApi.post({ message: err.message }); } finally { setBusy(false); diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 0e00949dcd..0030f702ec 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-catalog +## 0.7.2 + +### Patch Changes + +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/errors@0.1.3 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.7.1 + +### Patch Changes + +- 82fbda923e: Introduce a new `StarredEntitiesApi` that is used in the `useStarredEntities` hook. + The `@backstage/plugin-catalog` installs a default implementation that is backed by the `StorageApi`, but one can also override the `starredEntitiesApiRef`. + + This change also updates the storage format from a custom string to an entity reference and moves the location in the local storage. + A migration will convert the previously starred entities to the location on the first load of Backstage. + +- 93a13dfb42: Support `material-ui` overrides in SystemDiagramCard and EmptityLinksEmptyState components +- b03b9f19e0: added sorting in entity `Name` column by `metadata.title` if present +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + - @backstage/integration-react@0.1.12 + ## 0.7.0 ### Minor Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 3de20d7f95..0557a047e6 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-catalog", "description": "The Backstage plugin for browsing the Backstage catalog", - "version": "0.7.0", + "version": "0.7.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,13 +32,13 @@ }, "dependencies": { "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/integration-react": "^0.1.11", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/errors": "^0.1.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/integration-react": "^0.1.12", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/errors": "^0.1.3", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -51,10 +51,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx index cb5ea98031..20aa673ea3 100644 --- a/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx +++ b/plugins/catalog/src/components/EntityOrphanWarning/DeleteEntityDialog.tsx @@ -19,6 +19,7 @@ import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { Button, Dialog, DialogActions, DialogTitle } from '@material-ui/core'; import React, { useState } from 'react'; import { alertApiRef, useApi } from '@backstage/core-plugin-api'; +import { assertError } from '@backstage/errors'; type Props = { open: boolean; @@ -44,6 +45,7 @@ export const DeleteEntityDialog = ({ await catalogApi.removeEntityByUid(uid!); onConfirm(); } catch (err) { + assertError(err); alertApi.post({ message: err.message }); } finally { setBusy(false); diff --git a/plugins/circleci/CHANGELOG.md b/plugins/circleci/CHANGELOG.md index 3607e9430d..a501d77ff3 100644 --- a/plugins/circleci/CHANGELOG.md +++ b/plugins/circleci/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-circleci +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.26 ### Patch Changes diff --git a/plugins/circleci/package.json b/plugins/circleci/package.json index edd11711ae..8f49c4ac56 100644 --- a/plugins/circleci/package.json +++ b/plugins/circleci/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-circleci", "description": "A Backstage plugin that integrates towards Circle CI", - "version": "0.2.26", + "version": "0.2.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -52,10 +52,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cloudbuild/CHANGELOG.md b/plugins/cloudbuild/CHANGELOG.md index ac9bda48e8..dfd17e9908 100644 --- a/plugins/cloudbuild/CHANGELOG.md +++ b/plugins/cloudbuild/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-cloudbuild +## 0.2.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.26 ### Patch Changes diff --git a/plugins/cloudbuild/package.json b/plugins/cloudbuild/package.json index 37e36df83b..6699fc1e00 100644 --- a/plugins/cloudbuild/package.json +++ b/plugins/cloudbuild/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cloudbuild", "description": "A Backstage plugin that integrates towards Google Cloud Build", - "version": "0.2.26", + "version": "0.2.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/code-coverage-backend/CHANGELOG.md b/plugins/code-coverage-backend/CHANGELOG.md index 33bdd55346..8e8f9ceac8 100644 --- a/plugins/code-coverage-backend/CHANGELOG.md +++ b/plugins/code-coverage-backend/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-code-coverage-backend +## 0.1.14 + +### Patch Changes + +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/backend-common@0.9.7 + - @backstage/errors@0.1.3 + - @backstage/catalog-model@0.9.5 + +## 0.1.13 + +### Patch Changes + +- da9241530a: check for existence of lines property in files +- Updated dependencies + - @backstage/integration@0.6.8 + ## 0.1.12 ### Patch Changes diff --git a/plugins/code-coverage-backend/package.json b/plugins/code-coverage-backend/package.json index 4feb1e037f..56be697bac 100644 --- a/plugins/code-coverage-backend/package.json +++ b/plugins/code-coverage-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage-backend", "description": "A Backstage backend plugin that helps you keep track of your code coverage", - "version": "0.1.12", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -20,12 +20,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.6.7", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "express": "^4.17.1", @@ -37,7 +37,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.15", + "@backstage/cli": "^0.8.0", "@types/express-xml-bodyparser": "^0.3.2", "@types/supertest": "^2.0.8", "msw": "^0.29.0", diff --git a/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts b/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts index b666e042de..97a99c10b2 100644 --- a/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts +++ b/plugins/code-coverage-backend/src/service/CoverageUtils.test.ts @@ -208,7 +208,7 @@ describe('CodeCoverageUtils', () => { }; // @ts-ignore utils.validateRequestBody(mockRequest as Request); - } catch (error) { + } catch (error: any) { err = error; } expect(err?.message).toEqual('Content-Type missing'); @@ -226,7 +226,7 @@ describe('CodeCoverageUtils', () => { // @ts-ignore utils.validateRequestBody(mockRequest as Request); - } catch (error) { + } catch (error: any) { err = error; } expect(err?.message).toEqual('Illegal Content-Type'); diff --git a/plugins/code-coverage/CHANGELOG.md b/plugins/code-coverage/CHANGELOG.md index 8e3312b169..4bf3c6ea49 100644 --- a/plugins/code-coverage/CHANGELOG.md +++ b/plugins/code-coverage/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-code-coverage +## 0.1.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.14 ### Patch Changes diff --git a/plugins/code-coverage/package.json b/plugins/code-coverage/package.json index 0f1708e912..2d74ddd055 100644 --- a/plugins/code-coverage/package.json +++ b/plugins/code-coverage/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-code-coverage", "description": "A Backstage plugin that helps you keep track of your code coverage", - "version": "0.1.14", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,13 +21,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -41,10 +41,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/config-schema/CHANGELOG.md b/plugins/config-schema/CHANGELOG.md index c16d6c1230..9e6e82c0c3 100644 --- a/plugins/config-schema/CHANGELOG.md +++ b/plugins/config-schema/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-config-schema +## 0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.10 ### Patch Changes diff --git a/plugins/config-schema/package.json b/plugins/config-schema/package.json index 272313d064..1b2214de8b 100644 --- a/plugins/config-schema/package.json +++ b/plugins/config-schema/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-config-schema", "description": "A Backstage plugin that lets you browse the configuration schema of your app", - "version": "0.1.10", + "version": "0.1.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ }, "dependencies": { "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -36,10 +36,10 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/cost-insights/CHANGELOG.md b/plugins/cost-insights/CHANGELOG.md index dbd0c578cf..8a7b07af3b 100644 --- a/plugins/cost-insights/CHANGELOG.md +++ b/plugins/cost-insights/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-cost-insights +## 0.11.10 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.11.9 ### Patch Changes diff --git a/plugins/cost-insights/package.json b/plugins/cost-insights/package.json index d1e8fb4c3a..7eedd9a5bc 100644 --- a/plugins/cost-insights/package.json +++ b/plugins/cost-insights/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-cost-insights", "description": "A Backstage plugin that helps you keep track of your cloud spend", - "version": "0.11.9", + "version": "0.11.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ }, "dependencies": { "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -55,10 +55,10 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/explore-react/package.json b/plugins/explore-react/package.json index 08eb02683c..263137e93f 100644 --- a/plugins/explore-react/package.json +++ b/plugins/explore-react/package.json @@ -29,10 +29,10 @@ "postpack": "backstage-cli postpack" }, "dependencies": { - "@backstage/core-plugin-api": "^0.1.3" + "@backstage/core-plugin-api": "^0.1.11" }, "devDependencies": { - "@backstage/cli": "^0.7.2", + "@backstage/cli": "^0.8.0", "@backstage/dev-utils": "^0.2.0", "@backstage/test-utils": "^0.1.14", "@testing-library/jest-dom": "^5.10.1", diff --git a/plugins/explore/CHANGELOG.md b/plugins/explore/CHANGELOG.md index 7d4de81c65..f051691dc5 100644 --- a/plugins/explore/CHANGELOG.md +++ b/plugins/explore/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-explore +## 0.3.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.19 ### Patch Changes diff --git a/plugins/explore/package.json b/plugins/explore/package.json index 400ddc42ac..281d1727e8 100644 --- a/plugins/explore/package.json +++ b/plugins/explore/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-explore", "description": "A Backstage plugin for building an exploration page of your software ecosystem", - "version": "0.3.19", + "version": "0.3.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,12 +31,12 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", "@backstage/plugin-explore-react": "^0.0.6", - "@backstage/theme": "^0.2.10", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/firehydrant/CHANGELOG.md b/plugins/firehydrant/CHANGELOG.md index 0fc18c58f9..2343eb1c2e 100644 --- a/plugins/firehydrant/CHANGELOG.md +++ b/plugins/firehydrant/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-firehydrant +## 0.1.7 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.6 ### Patch Changes diff --git a/plugins/firehydrant/package.json b/plugins/firehydrant/package.json index 557aa6ea9d..e72bdfda51 100644 --- a/plugins/firehydrant/package.json +++ b/plugins/firehydrant/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-firehydrant", "description": "A Backstage plugin that integrates towards FireHydrant", - "version": "0.1.6", + "version": "0.1.7", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -22,10 +22,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,10 +35,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/fossa/CHANGELOG.md b/plugins/fossa/CHANGELOG.md index b4ba20ad10..f422dfbe41 100644 --- a/plugins/fossa/CHANGELOG.md +++ b/plugins/fossa/CHANGELOG.md @@ -1,5 +1,26 @@ # @backstage/plugin-fossa +## 0.2.21 + +### Patch Changes + +- 09c106b96c: Add `entitiesFilter` option to `FossaPage` to filter entities displayed in the table. +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/errors@0.1.3 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.2.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.19 ### Patch Changes diff --git a/plugins/fossa/api-report.md b/plugins/fossa/api-report.md index 50e382d3d4..d6e229d3d6 100644 --- a/plugins/fossa/api-report.md +++ b/plugins/fossa/api-report.md @@ -21,7 +21,17 @@ export const EntityFossaCard: ({ // Warning: (ae-missing-release-tag) "FossaPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const FossaPage: () => JSX.Element; +export const FossaPage: ({ entitiesFilter }: FossaPageProps) => JSX.Element; + +// Warning: (ae-missing-release-tag) "FossaPageProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type FossaPageProps = { + entitiesFilter?: + | Record[] + | Record + | undefined; +}; // Warning: (ae-missing-release-tag) "fossaPlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/fossa/package.json b/plugins/fossa/package.json index 7d6e9bcf19..c33e5f64ac 100644 --- a/plugins/fossa/package.json +++ b/plugins/fossa/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-fossa", "description": "A Backstage plugin that integrates towards FOSSA", - "version": "0.2.19", + "version": "0.2.21", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx index 78c8b7bb40..778f5ee9c6 100644 --- a/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx +++ b/plugins/fossa/src/components/FossaPage/FossaPage.test.tsx @@ -142,4 +142,38 @@ describe('', () => { expect(getByText(/0 Issues/i)).toBeInTheDocument(); expect(getByText(/10 Issues/i)).toBeInTheDocument(); }); + + it('has configurable entity filter', async () => { + const entity: Entity = { + apiVersion: 'v1', + kind: 'API', + metadata: { + name: 'my-name-0', + annotations: { + 'fossa.io/project-name': 'my-name-0', + }, + }, + }; + + fossaApi.getFindingSummaries.mockResolvedValue(new Map()); + catalogApi.getEntities.mockResolvedValue({ items: [entity] }); + + const { getByText } = await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + }, + }, + ); + + expect(catalogApi.getEntities).toBeCalledWith( + expect.objectContaining({ + filter: { kind: 'API' }, + }), + ); + expect(getByText(/my-name-0/i)).toBeInTheDocument(); + }); }); diff --git a/plugins/fossa/src/components/FossaPage/FossaPage.tsx b/plugins/fossa/src/components/FossaPage/FossaPage.tsx index 3e16085968..fbdaf85717 100644 --- a/plugins/fossa/src/components/FossaPage/FossaPage.tsx +++ b/plugins/fossa/src/components/FossaPage/FossaPage.tsx @@ -30,8 +30,8 @@ import { Tooltip } from '@material-ui/core'; import { Skeleton } from '@material-ui/lab'; import { DateTime } from 'luxon'; import * as React from 'react'; -import { useMemo } from 'react'; -import { useAsync } from 'react-use'; +import { useMemo, useState } from 'react'; +import { useAsync, useDeepCompareEffect } from 'react-use'; import { FindingSummary, fossaApiRef } from '../../api'; import { getProjectName } from '../getProjectName'; @@ -166,14 +166,25 @@ const filters: TableFilter[] = [ { column: 'Branch', type: 'select' }, ]; -export const FossaPage = () => { +export type FossaPageProps = { + entitiesFilter?: + | Record[] + | Record + | undefined; +}; + +export const FossaPage = ({ + entitiesFilter = { kind: 'Component' }, +}: FossaPageProps) => { const catalogApi = useApi(catalogApiRef); const fossaApi = useApi(fossaApiRef); + const [filter, setFilter] = useState(entitiesFilter); + useDeepCompareEffect(() => setFilter(entitiesFilter), [entitiesFilter]); // Get a list of all relevant entities const { value: entities, loading: entitiesLoading } = useAsync(() => { return catalogApi.getEntities({ - filter: { kind: 'Component' }, + filter, fields: [ 'kind', 'metadata.namespace', @@ -182,7 +193,7 @@ export const FossaPage = () => { 'relations', ], }); - }); + }, [filter]); // get the project names of all entities. the idx of both lists match. const projectNames = useMemo( diff --git a/plugins/fossa/src/components/FossaPage/index.ts b/plugins/fossa/src/components/FossaPage/index.ts index 7be77be441..13dd680a95 100644 --- a/plugins/fossa/src/components/FossaPage/index.ts +++ b/plugins/fossa/src/components/FossaPage/index.ts @@ -15,3 +15,4 @@ */ export { FossaPage } from './FossaPage'; +export type { FossaPageProps } from './FossaPage'; diff --git a/plugins/fossa/src/components/index.ts b/plugins/fossa/src/components/index.ts index 12632d4fff..f108626e88 100644 --- a/plugins/fossa/src/components/index.ts +++ b/plugins/fossa/src/components/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export * from './FossaCard'; +export type { FossaPageProps } from './FossaPage'; diff --git a/plugins/fossa/src/index.ts b/plugins/fossa/src/index.ts index 200b977f3b..7f75fad178 100644 --- a/plugins/fossa/src/index.ts +++ b/plugins/fossa/src/index.ts @@ -20,5 +20,6 @@ * @packageDocumentation */ -export { fossaPlugin } from './plugin'; +export * from './components'; export { EntityFossaCard, FossaPage } from './extensions'; +export { fossaPlugin } from './plugin'; diff --git a/plugins/gcp-projects/CHANGELOG.md b/plugins/gcp-projects/CHANGELOG.md index e0b2a84aff..28c40f6221 100644 --- a/plugins/gcp-projects/CHANGELOG.md +++ b/plugins/gcp-projects/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-gcp-projects +## 0.3.8 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.7 ### Patch Changes diff --git a/plugins/gcp-projects/package.json b/plugins/gcp-projects/package.json index 5f71ffe4b6..0a3f70486e 100644 --- a/plugins/gcp-projects/package.json +++ b/plugins/gcp-projects/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gcp-projects", "description": "A Backstage plugin that helps you manage projects in GCP", - "version": "0.3.7", + "version": "0.3.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,10 +43,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/git-release-manager/CHANGELOG.md b/plugins/git-release-manager/CHANGELOG.md index e60f641007..72bcf87b2a 100644 --- a/plugins/git-release-manager/CHANGELOG.md +++ b/plugins/git-release-manager/CHANGELOG.md @@ -1,5 +1,23 @@ # @backstage/plugin-git-release-manager +## 0.3.2 + +### Patch Changes + +- 82ea1f2bed: Minor internal type improvement +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/core-plugin-api@0.1.11 + +## 0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@0.6.8 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.0 ### Minor Changes diff --git a/plugins/git-release-manager/package.json b/plugins/git-release-manager/package.json index 74487bf0cc..a63f491f48 100644 --- a/plugins/git-release-manager/package.json +++ b/plugins/git-release-manager/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-git-release-manager", "description": "A Backstage plugin that helps you manage releases in git", - "version": "0.3.0", + "version": "0.3.2", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/integration": "^0.6.7", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/integration": "^0.6.8", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +39,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/git-release-manager/src/features/Patch/hooks/usePatchDryRun.tsx b/plugins/git-release-manager/src/features/Patch/hooks/usePatchDryRun.tsx index de3a67e874..3bd69b1028 100644 --- a/plugins/git-release-manager/src/features/Patch/hooks/usePatchDryRun.tsx +++ b/plugins/git-release-manager/src/features/Patch/hooks/usePatchDryRun.tsx @@ -391,6 +391,6 @@ export function usePatchDryRun({ asyncCatcher, abortIfError, selectedPatchCommit: latestCommitOnReleaseBranchRes.value - ?.selectedPatchCommit as any, + ?.selectedPatchCommit as GetRecentCommitsResultSingle, }; } diff --git a/plugins/github-actions/CHANGELOG.md b/plugins/github-actions/CHANGELOG.md index ec59cc10a6..222bc4c851 100644 --- a/plugins/github-actions/CHANGELOG.md +++ b/plugins/github-actions/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-github-actions +## 0.4.22 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/integration@0.6.8 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.4.21 ### Patch Changes diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index b473f9b675..7958a97cb8 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-actions", "description": "A Backstage plugin that integrates towards GitHub Actions", - "version": "0.4.21", + "version": "0.4.22", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,12 +33,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/integration": "^0.6.7", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/integration": "^0.6.8", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -52,10 +52,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/github-deployments/CHANGELOG.md b/plugins/github-deployments/CHANGELOG.md index 3cebaad3ce..5259ea11b2 100644 --- a/plugins/github-deployments/CHANGELOG.md +++ b/plugins/github-deployments/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-github-deployments +## 0.1.20 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/integration@0.6.8 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + - @backstage/integration-react@0.1.12 + ## 0.1.19 ### Patch Changes diff --git a/plugins/github-deployments/package.json b/plugins/github-deployments/package.json index 7cd079edbd..ba226037ff 100644 --- a/plugins/github-deployments/package.json +++ b/plugins/github-deployments/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-github-deployments", "description": "A Backstage plugin that integrates towards GitHub Deployments", - "version": "0.1.19", + "version": "0.1.20", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,14 +21,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.6.7", - "@backstage/integration-react": "^0.1.11", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", + "@backstage/integration-react": "^0.1.12", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -39,10 +39,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/gitops-profiles/CHANGELOG.md b/plugins/gitops-profiles/CHANGELOG.md index d9959c7729..08f256cdb5 100644 --- a/plugins/gitops-profiles/CHANGELOG.md +++ b/plugins/gitops-profiles/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-gitops-profiles +## 0.3.8 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.7 ### Patch Changes diff --git a/plugins/gitops-profiles/package.json b/plugins/gitops-profiles/package.json index d728929b1d..9088c79fd9 100644 --- a/plugins/gitops-profiles/package.json +++ b/plugins/gitops-profiles/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-gitops-profiles", "description": "A Backstage plugin that helps you manage GitOps profiles", - "version": "0.3.7", + "version": "0.3.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -44,10 +44,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/graphiql/CHANGELOG.md b/plugins/graphiql/CHANGELOG.md index 760c63e5d2..aa58dbd332 100644 --- a/plugins/graphiql/CHANGELOG.md +++ b/plugins/graphiql/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-graphiql +## 0.2.20 + +### Patch Changes + +- c8215e1fe6: Add experimental `experimentalInstallationRecipe` to `package.json`. +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.19 ### Patch Changes diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 3e179c75a3..1c5ebe17f6 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-graphiql", "description": "Backstage plugin for browsing GraphQL APIs", - "version": "0.2.19", + "version": "0.2.20", "private": false, "publishConfig": { "access": "public", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -44,10 +44,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/graphql-backend/package.json b/plugins/graphql-backend/package.json index e87bd52934..6f1f0000ea 100644 --- a/plugins/graphql-backend/package.json +++ b/plugins/graphql-backend/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.0", + "@backstage/backend-common": "^0.9.7", "@backstage/config": "^0.1.8", "@backstage/plugin-catalog-graphql": "^0.2.12", "@graphql-modules/core": "^0.7.17", @@ -47,7 +47,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.0", + "@backstage/cli": "^0.8.0", "@types/supertest": "^2.0.8", "eslint-plugin-graphql": "^4.0.0", "msw": "^0.29.0", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index a14e6e01e3..aa35cdf968 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,60 @@ # @backstage/plugin-home +## 0.4.4 + +### Patch Changes + +- ef5bf4235a: Adds a `` component that shows a playful greeting on the home page. + To use it, pass it to the home page header: + + ```typescript + +
} pageTitleOverride="Home"> + +
+ โ€ฆ +
+ ``` + +- 87b2d5ad88: Fix `` to display only the selected tab, not the other way around. +- 2435d7a49b: Added HeaderWorldClock to the Home plugin which is a copy of the HomepageTimer from core-components that has been updated to use props over static config from app-config.yaml. To use HeaderWorldClock you'll need to create an array of ClockConfig like this: + + ```ts + const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, + ]; + ``` + + Then you can pass `clockConfigs` into the HeaderWorldClock like this: + + ```ts + +
+ +
+ ... +
+ ``` + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.4.3 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index dc7e130235..28b9fa9e66 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-home", "description": "A Backstage plugin that helps you build a home page", - "version": "0.4.3", + "version": "0.4.4", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,10 +35,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/ilert/CHANGELOG.md b/plugins/ilert/CHANGELOG.md index 406b846162..efa2d5d8f6 100644 --- a/plugins/ilert/CHANGELOG.md +++ b/plugins/ilert/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-ilert +## 0.1.15 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.14 ### Patch Changes diff --git a/plugins/ilert/package.json b/plugins/ilert/package.json index 697f3ca790..34db6580fe 100644 --- a/plugins/ilert/package.json +++ b/plugins/ilert/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-ilert", "description": "A Backstage plugin that integrates towards iLert", - "version": "0.1.14", + "version": "0.1.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,12 +21,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@date-io/luxon": "2.x", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -39,10 +39,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/jenkins-backend/package.json b/plugins/jenkins-backend/package.json index b741cc3d11..bdae720c0e 100644 --- a/plugins/jenkins-backend/package.json +++ b/plugins/jenkins-backend/package.json @@ -22,9 +22,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", @@ -35,7 +35,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.15", + "@backstage/cli": "^0.8.0", "@types/jenkins": "^0.23.1", "@types/supertest": "^2.0.8", "msw": "^0.29.0", diff --git a/plugins/jenkins/CHANGELOG.md b/plugins/jenkins/CHANGELOG.md index 04cb19ab9c..84db4728bc 100644 --- a/plugins/jenkins/CHANGELOG.md +++ b/plugins/jenkins/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-jenkins +## 0.5.11 + +### Patch Changes + +- 3c756657b8: Sort Jenkins build by timestamp in `CITable` +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.5.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.5.9 ### Patch Changes diff --git a/plugins/jenkins/package.json b/plugins/jenkins/package.json index 5048f4c3eb..fa6a5e6d52 100644 --- a/plugins/jenkins/package.json +++ b/plugins/jenkins/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-jenkins", "description": "A Backstage plugin that integrates towards Jenkins", - "version": "0.5.9", + "version": "0.5.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,10 +48,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx index 0519ed3816..ee17df8533 100644 --- a/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/jenkins/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -80,6 +80,12 @@ const FailSkippedWidget = ({ }; const generatedColumns: TableColumn[] = [ + { + title: 'Timestamp', + defaultSort: 'desc', + hidden: true, + field: 'lastBuild.timestamp', + }, { title: 'Build', field: 'fullName', diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 25b9e32679..e271decc8b 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -32,10 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.4", - "@backstage/catalog-model": "^0.9.3", + "@backstage/backend-common": "^0.9.7", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.1", + "@backstage/errors": "^0.1.3", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", @@ -44,7 +44,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.7.13", + "@backstage/cli": "^0.8.0", "@types/jest-when": "^2.7.2", "@types/lodash": "^4.14.151", "jest-when": "^3.1.0", diff --git a/plugins/kafka/CHANGELOG.md b/plugins/kafka/CHANGELOG.md index 5cc277aa7e..3697f8de28 100644 --- a/plugins/kafka/CHANGELOG.md +++ b/plugins/kafka/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-kafka +## 0.2.19 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.18 ### Patch Changes diff --git a/plugins/kafka/package.json b/plugins/kafka/package.json index d7c18cac65..6b91797359 100644 --- a/plugins/kafka/package.json +++ b/plugins/kafka/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kafka", "description": "A Backstage plugin that integrates towards Kafka", - "version": "0.2.18", + "version": "0.2.19", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -35,10 +35,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 004476d8c1..d506571a3f 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,44 @@ # @backstage/plugin-kubernetes-backend +## 0.3.18 + +### Patch Changes + +- b61c50a12f: Fix Kubernetes plugin custom objects lookup regression +- c57b075d18: add caData support for kubernetes client config +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/backend-common@0.9.7 + - @backstage/errors@0.1.3 + - @backstage/catalog-model@0.9.5 + +## 0.3.17 + +### Patch Changes + +- 89bcf90b66: Refactor kubernetes fetcher to reduce boilerplate code +- a982e166c5: Enable customization of services used by the kubernetes backend plugin + + The createRouter function has been deprecated in favor of a KubernetesBuilder object. + Here's how you should upgrade your projects when configuring the Kubernetes backend plugin. + in your `packages/backend/src/plugins/kubernetes.ts` file for instance: + + ```typescript + import { KubernetesBuilder } from '@backstage/plugin-kubernetes-backend'; + import { PluginEnvironment } from '../types'; + + export default async function createPlugin({ + logger, + config, + }: PluginEnvironment) { + const { router } = await KubernetesBuilder.createBuilder({ + logger, + config, + }).build(); + return router; + } + ``` + ## 0.3.16 ### Patch Changes diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index c8211a5323..f34815f328 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -27,6 +27,8 @@ export interface AWSClusterDetails extends ClusterDetails { export interface ClusterDetails { // (undocumented) authProvider: string; + // (undocumented) + caData?: string | undefined; dashboardApp?: string; dashboardUrl?: string; name: string; diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index f588771294..be2903dff5 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes-backend", "description": "A Backstage backend plugin that integrates towards Kubernetes", - "version": "0.3.16", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.4", - "@backstage/catalog-model": "^0.9.3", + "@backstage/backend-common": "^0.9.7", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", + "@backstage/errors": "^0.1.3", "@backstage/plugin-kubernetes-common": "^0.1.4", "@google-cloud/container": "^2.2.0", "@kubernetes/client-node": "^0.15.0", @@ -54,7 +55,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.13", + "@backstage/cli": "^0.8.0", "@types/aws4": "^1.5.1", "supertest": "^6.1.3", "aws-sdk-mock": "^5.2.1", diff --git a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts index 6d1506c4c7..62346ac6c3 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts @@ -53,6 +53,7 @@ describe('ConfigClusterLocator', () => { url: 'http://localhost:8080', authProvider: 'serviceAccount', skipTLSVerify: false, + caData: undefined, }, ]); }); @@ -89,6 +90,7 @@ describe('ConfigClusterLocator', () => { url: 'http://localhost:8080', authProvider: 'serviceAccount', skipTLSVerify: false, + caData: undefined, }, { name: 'cluster2', @@ -96,6 +98,7 @@ describe('ConfigClusterLocator', () => { url: 'http://localhost:8081', authProvider: 'google', skipTLSVerify: true, + caData: undefined, }, ]); }); @@ -141,6 +144,7 @@ describe('ConfigClusterLocator', () => { url: 'http://localhost:8080', authProvider: 'aws', skipTLSVerify: false, + caData: undefined, }, { assumeRole: 'SomeRole', @@ -150,6 +154,7 @@ describe('ConfigClusterLocator', () => { url: 'http://localhost:8081', authProvider: 'aws', skipTLSVerify: true, + caData: undefined, }, { assumeRole: 'SomeRole', @@ -159,6 +164,7 @@ describe('ConfigClusterLocator', () => { serviceAccountToken: undefined, authProvider: 'aws', skipTLSVerify: true, + caData: undefined, }, ]); }); diff --git a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts index 53d3a1d025..bb9dbfe13f 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts @@ -35,6 +35,7 @@ export class ConfigClusterLocator implements KubernetesClustersSupplier { url: c.getString('url'), serviceAccountToken: c.getOptionalString('serviceAccountToken'), skipTLSVerify: c.getOptionalBoolean('skipTLSVerify') ?? false, + caData: c.getOptionalString('caData'), authProvider: authProvider, }; const dashboardUrl = c.getOptionalString('dashboardUrl'); diff --git a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts index 7b2dfbf8de..545f839907 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.test.ts @@ -213,7 +213,7 @@ describe('GkeClusterLocator', () => { } as any); await expect(sut.getClusters()).rejects.toThrow( - 'There was an error retrieving clusters from GKE for projectId=some-project region=some-region : [some error]', + 'There was an error retrieving clusters from GKE for projectId=some-project region=some-region; caused by Error: some error', ); expect(mockedListClusters).toBeCalledTimes(1); diff --git a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts index 3cc6c216ae..3aa4a3e941 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/GkeClusterLocator.ts @@ -15,6 +15,7 @@ */ import { Config } from '@backstage/config'; +import { ForwardedError } from '@backstage/errors'; import * as container from '@google-cloud/container'; import { GKEClusterDetails, KubernetesClustersSupplier } from '../types/types'; @@ -49,6 +50,7 @@ export class GkeClusterLocator implements KubernetesClustersSupplier { ); } + // TODO pass caData into the object async getClusters(): Promise { const { projectId, region, skipTLSVerify } = this.options; const request = { @@ -65,8 +67,9 @@ export class GkeClusterLocator implements KubernetesClustersSupplier { skipTLSVerify, })); } catch (e) { - throw new Error( - `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region} : [${e.message}]`, + throw new ForwardedError( + `There was an error retrieving clusters from GKE for projectId=${projectId} region=${region}`, + e, ); } } diff --git a/plugins/kubernetes-backend/src/cluster-locator/index.test.ts b/plugins/kubernetes-backend/src/cluster-locator/index.test.ts index 95be99a8a5..dde4dc1d93 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/index.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/index.test.ts @@ -54,6 +54,7 @@ describe('getCombinedClusterDetails', () => { url: 'http://localhost:8080', authProvider: 'serviceAccount', skipTLSVerify: false, + caData: undefined, }, { name: 'cluster2', @@ -61,6 +62,7 @@ describe('getCombinedClusterDetails', () => { url: 'http://localhost:8081', authProvider: 'google', skipTLSVerify: false, + caData: undefined, }, ]); }); diff --git a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts index bde538bf55..11cca4917f 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesBuilder.ts @@ -124,6 +124,7 @@ export class KubernetesBuilder { group: c.getString('group'), apiVersion: c.getString('apiVersion'), plural: c.getString('plural'), + objectType: 'customresources', } as CustomResource), ); diff --git a/plugins/kubernetes-backend/src/service/KubernetesClientProvider.ts b/plugins/kubernetes-backend/src/service/KubernetesClientProvider.ts index 61b19854c2..4b2848508e 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesClientProvider.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesClientProvider.ts @@ -31,6 +31,7 @@ export class KubernetesClientProvider { name: clusterDetails.name, server: clusterDetails.url, skipTLSVerify: clusterDetails.skipTLSVerify, + caData: clusterDetails.caData, }; // TODO configure diff --git a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts index a08f339a20..308b7a10be 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesFetcher.ts @@ -148,7 +148,10 @@ export class KubernetesClientBasedFetcher implements KubernetesFetcher { labelSelector, ) .then(r => { - return { type: objectType, resources: (r.body as any).items }; + return { + type: objectType, + resources: (r.body as any).items, + }; }); } } diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 30a8d2756c..90485fcaee 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -91,6 +91,7 @@ export interface ClusterDetails { authProvider: string; serviceAccountToken?: string | undefined; skipTLSVerify?: boolean; + caData?: string | undefined; /** * Specifies the link to the Kubernetes dashboard managing this cluster. * @remarks diff --git a/plugins/kubernetes-common/package.json b/plugins/kubernetes-common/package.json index ec3fec1c56..28dfc94c49 100644 --- a/plugins/kubernetes-common/package.json +++ b/plugins/kubernetes-common/package.json @@ -35,11 +35,11 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@kubernetes/client-node": "^0.15.0" }, "devDependencies": { - "@backstage/cli": "^0.7.15" + "@backstage/cli": "^0.8.0" }, "jest": { "roots": [ diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 6994729a3b..a0a4ef2a51 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-kubernetes +## 0.4.17 + +### Patch Changes + +- 89bcf90b66: Refactor kubernetes fetcher to reduce boilerplate code +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.4.16 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index a8e271e85d..22db871ccd 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-kubernetes", "description": "A Backstage plugin that integrates towards Kubernetes", - "version": "0.4.16", + "version": "0.4.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,13 +31,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", "@backstage/plugin-kubernetes-common": "^0.1.5", - "@backstage/theme": "^0.2.10", + "@backstage/theme": "^0.2.11", "@kubernetes/client-node": "^0.15.0", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", @@ -51,10 +51,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/lighthouse/CHANGELOG.md b/plugins/lighthouse/CHANGELOG.md index fad1da1e6e..4ff76d4f1b 100644 --- a/plugins/lighthouse/CHANGELOG.md +++ b/plugins/lighthouse/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-lighthouse +## 0.2.29 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.28 ### Patch Changes diff --git a/plugins/lighthouse/package.json b/plugins/lighthouse/package.json index 14facb2439..8d9cf70bad 100644 --- a/plugins/lighthouse/package.json +++ b/plugins/lighthouse/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-lighthouse", "description": "A Backstage plugin that integrates towards Lighthouse", - "version": "0.2.28", + "version": "0.2.29", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,12 +32,12 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -47,10 +47,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/newrelic/CHANGELOG.md b/plugins/newrelic/CHANGELOG.md index 3b8b004fc0..7ffd4b06d1 100644 --- a/plugins/newrelic/CHANGELOG.md +++ b/plugins/newrelic/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-newrelic +## 0.3.8 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.7 ### Patch Changes diff --git a/plugins/newrelic/package.json b/plugins/newrelic/package.json index 8b50f26077..c44608e2ef 100644 --- a/plugins/newrelic/package.json +++ b/plugins/newrelic/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-newrelic", "description": "A Backstage plugin that integrates towards New Relic", - "version": "0.3.7", + "version": "0.3.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,9 +32,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,10 +43,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index a9dab3d9e2..6e1cc7064f 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-org +## 0.3.27 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.26 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index d391bf8081..4e89865f44 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-org", "description": "A Backstage plugin that helps you create entity pages for your organization", - "version": "0.3.26", + "version": "0.3.27", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,11 +21,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -37,10 +37,10 @@ "qs": "^6.10.1" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/pagerduty/CHANGELOG.md b/plugins/pagerduty/CHANGELOG.md index 626b7e9afd..11ae548db8 100644 --- a/plugins/pagerduty/CHANGELOG.md +++ b/plugins/pagerduty/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-pagerduty +## 0.3.17 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.16 ### Patch Changes diff --git a/plugins/pagerduty/package.json b/plugins/pagerduty/package.json index fc213e0576..35a240b5de 100644 --- a/plugins/pagerduty/package.json +++ b/plugins/pagerduty/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-pagerduty", "description": "A Backstage plugin that integrates towards PagerDuty", - "version": "0.3.16", + "version": "0.3.17", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,10 +48,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/proxy-backend/package.json b/plugins/proxy-backend/package.json index e7510450b0..c43ea8b31a 100644 --- a/plugins/proxy-backend/package.json +++ b/plugins/proxy-backend/package.json @@ -29,7 +29,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/config": "^0.1.8", "@types/express": "^4.17.6", "express": "^4.17.1", @@ -43,7 +43,7 @@ "yup": "^0.32.9" }, "devDependencies": { - "@backstage/cli": "^0.7.15", + "@backstage/cli": "^0.8.0", "@types/http-proxy-middleware": "^0.19.3", "@types/supertest": "^2.0.8", "@types/uuid": "^8.0.0", diff --git a/plugins/rollbar-backend/package.json b/plugins/rollbar-backend/package.json index 7c872cc704..1d7be09b85 100644 --- a/plugins/rollbar-backend/package.json +++ b/plugins/rollbar-backend/package.json @@ -31,7 +31,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.4", + "@backstage/backend-common": "^0.9.7", "@backstage/config": "^0.1.10", "@types/express": "^4.17.6", "axios": "^0.21.1", @@ -48,7 +48,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.13", + "@backstage/cli": "^0.8.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/rollbar/CHANGELOG.md b/plugins/rollbar/CHANGELOG.md index 76ea278858..4f7f3c9a16 100644 --- a/plugins/rollbar/CHANGELOG.md +++ b/plugins/rollbar/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-rollbar +## 0.3.18 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.17 ### Patch Changes diff --git a/plugins/rollbar/package.json b/plugins/rollbar/package.json index 62486e915d..f35852fe74 100644 --- a/plugins/rollbar/package.json +++ b/plugins/rollbar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-rollbar", "description": "A Backstage plugin that integrates towards Rollbar", - "version": "0.3.17", + "version": "0.3.18", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/scaffolder-backend-module-cookiecutter/package.json b/plugins/scaffolder-backend-module-cookiecutter/package.json index 88eef336a3..7db57dbe6b 100644 --- a/plugins/scaffolder-backend-module-cookiecutter/package.json +++ b/plugins/scaffolder-backend-module-cookiecutter/package.json @@ -20,10 +20,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.0", - "@backstage/errors": "^0.1.1", + "@backstage/backend-common": "^0.9.7", + "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.2", - "@backstage/plugin-scaffolder-backend": "^0.15.2", + "@backstage/plugin-scaffolder-backend": "^0.15.10", "@backstage/config": "^0.1.8", "command-exists": "^1.2.9", "fs-extra": "10.0.0", @@ -32,7 +32,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.8", + "@backstage/cli": "^0.8.0", "@types/fs-extra": "^9.0.1", "@types/mock-fs": "^4.13.0", "@types/jest": "^26.0.7", diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index f0cd953a5c..c88e6d0f9f 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -21,16 +21,16 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.0", - "@backstage/plugin-scaffolder-backend": "^0.15.2", + "@backstage/backend-common": "^0.9.7", + "@backstage/plugin-scaffolder-backend": "^0.15.10", "@backstage/config": "^0.1.8", - "@backstage/errors": "^0.1.1", + "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.2", "command-exists": "^1.2.9", "fs-extra": "^9.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.8", + "@backstage/cli": "^0.8.0", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", "@types/command-exists": "^1.2.0", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 25ae32c5d9..d027ec52e7 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,34 @@ # @backstage/plugin-scaffolder-backend +## 0.15.10 + +### Patch Changes + +- b149e94290: Allow `catalog:register` action to register optional locations +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/plugin-catalog-backend@0.17.1 + - @backstage/backend-common@0.9.7 + - @backstage/errors@0.1.3 + - @backstage/catalog-model@0.9.5 + +## 0.15.9 + +### Patch Changes + +- 0f99f1170e: Make sure `sourcePath` of `publish:github:pull-request` can only be used to + retrieve files from the workspace. + +## 0.15.8 + +### Patch Changes + +- 42c618abf6: Use `resolveSafeChildPath` in the `fetchContents` function to forbid reading files outside the base directory when a template is registered from a `file:` location. +- 18083d1821: Introduce the new `scaffolder.backstage.io/v1beta3` template kind with nunjucks support ๐Ÿฅ‹ +- Updated dependencies + - @backstage/integration@0.6.8 + - @backstage/plugin-catalog-backend@0.17.0 + ## 0.15.7 ### Patch Changes diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index deb2657c59..a52c57bb2a 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -15,8 +15,10 @@ import { createPullRequest } from 'octokit-plugin-create-pull-request'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; import { JsonObject } from '@backstage/config'; +import { JsonObject as JsonObject_2 } from '@backstage/types'; import { JsonValue } from '@backstage/config'; import { Knex } from 'knex'; +import { JsonValue as JsonValue_2 } from '@backstage/types'; import { LocationSpec } from '@backstage/catalog-model'; import { Logger as Logger_2 } from 'winston'; import { Octokit } from '@octokit/rest'; @@ -187,7 +189,7 @@ export function createRouter(options: RouterOptions): Promise; // @public (undocumented) export const createTemplateAction: < Input extends Partial<{ - [name: string]: JsonValue | Partial | undefined; + [name: string]: JsonValue_2 | Partial | undefined; }>, >( templateAction: TemplateAction, diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 98fd053771..ea29866485 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-backend", "description": "The Backstage backend plugin that helps you create new things", - "version": "0.15.7", + "version": "0.15.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,13 +30,13 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.2", - "@backstage/integration": "^0.6.7", - "@backstage/plugin-catalog-backend": "^0.16.0", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", + "@backstage/plugin-catalog-backend": "^0.17.1", "@backstage/plugin-scaffolder-common": "^0.1.0", "@backstage/plugin-scaffolder-backend-module-cookiecutter": "^0.1.2", "@gitbeaker/core": "^30.2.0", @@ -70,8 +70,8 @@ "yaml": "^1.10.0" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/test-utils": "^0.1.19", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", "@types/git-url-parse": "^9.0.0", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts index eb704c729e..e1f8823487 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.test.ts @@ -174,4 +174,42 @@ describe('catalog:register', () => { 'http://foo/var', ); }); + + it('should ignore failures when dry running the location in the catalog if `optional` is set', async () => { + addLocation + .mockResolvedValueOnce({ + entities: [], + }) + .mockRejectedValueOnce(new Error('Not found')); + await action.handler({ + ...mockContext, + input: { + catalogInfoUrl: 'http://foo/var', + optional: true, + }, + }); + + expect(addLocation).toHaveBeenNthCalledWith( + 1, + { + type: 'url', + target: 'http://foo/var', + }, + {}, + ); + expect(addLocation).toHaveBeenNthCalledWith( + 2, + { + dryRun: true, + type: 'url', + target: 'http://foo/var', + }, + {}, + ); + + expect(mockContext.output).toBeCalledWith( + 'catalogInfoUrl', + 'http://foo/var', + ); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts index 9d4961bfd9..0c08131925 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts @@ -27,8 +27,8 @@ export function createCatalogRegisterAction(options: { const { catalogClient, integrations } = options; return createTemplateAction< - | { catalogInfoUrl: string } - | { repoContentsUrl: string; catalogInfoPath?: string } + | { catalogInfoUrl: string; optional?: boolean } + | { repoContentsUrl: string; catalogInfoPath?: string; optional?: boolean } >({ id: 'catalog:register', description: @@ -46,6 +46,12 @@ export function createCatalogRegisterAction(options: { 'An absolute URL pointing to the catalog info file location', type: 'string', }, + optional: { + title: 'Optional', + description: + 'Permit the registered location to optionally exist. Default: false', + type: 'boolean', + }, }, }, { @@ -64,6 +70,12 @@ export function createCatalogRegisterAction(options: { 'A relative path from the repo root pointing to the catalog info file, defaults to /catalog-info.yaml', type: 'string', }, + optional: { + title: 'Optional', + description: + 'Permit the registered location to optionally exist. Default: false', + type: 'boolean', + }, }, }, ], @@ -100,22 +112,30 @@ export function createCatalogRegisterAction(options: { }, ctx.token ? { token: ctx.token } : {}, ); - const result = await catalogClient.addLocation( - { - dryRun: true, - type: 'url', - target: catalogInfoUrl, - }, - ctx.token ? { token: ctx.token } : {}, - ); - if (result.entities.length > 0) { - const { entities } = result; - const entity = - entities.find(e => !e.metadata.name.startsWith('generated-')) ?? - entities[0]; - ctx.output('entityRef', stringifyEntityRef(entity)); + try { + const result = await catalogClient.addLocation( + { + dryRun: true, + type: 'url', + target: catalogInfoUrl, + }, + ctx.token ? { token: ctx.token } : {}, + ); + + if (result.entities.length > 0) { + const { entities } = result; + const entity = + entities.find(e => !e.metadata.name.startsWith('generated-')) ?? + entities[0]; + ctx.output('entityRef', stringifyEntityRef(entity)); + } + } catch (e) { + if (!input.optional) { + throw e; + } } + ctx.output('catalogInfoUrl', catalogInfoUrl); }, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts index 6d8324768e..0761f65f09 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/github/githubWebhook.ts @@ -17,6 +17,7 @@ import { ScmIntegrationRegistry } from '@backstage/integration'; import { createTemplateAction } from '../../createTemplateAction'; import { OctokitProvider } from './OctokitProvider'; import { emitterEventNames } from '@octokit/webhooks'; +import { assertError } from '@backstage/errors'; type ContentType = 'form' | 'json'; @@ -130,6 +131,7 @@ export function createGithubWebhookAction(options: { }); ctx.logger.info(`Webhook '${webhookUrl}' created successfully`); } catch (e) { + assertError(e); ctx.logger.warn( `Failed: create webhook '${webhookUrl}' on repo: '${repo}', ${e.message}`, ); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index 3907bc1d4e..eff65e329f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -19,6 +19,7 @@ import { PassThrough, Writable } from 'stream'; import { Logger } from 'winston'; import { Git } from '@backstage/backend-common'; import { Octokit } from '@octokit/rest'; +import { assertError } from '@backstage/errors'; export type RunCommandOptions = { command: string; @@ -152,6 +153,7 @@ export const enableBranchProtectionOnDefaultRepoBranch = async ({ }, }); } catch (e) { + assertError(e); if ( e.message.includes( 'Upgrade to GitHub Pro or make this repository public to enable this feature', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index b32f9b5b3f..ad6a4a7857 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -22,6 +22,7 @@ import { getRepoSourceDirectory } from './util'; import { createTemplateAction } from '../../createTemplateAction'; import { Config } from '@backstage/config'; import { OctokitProvider } from '../github/OctokitProvider'; +import { assertError } from '@backstage/errors'; type Permission = 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; type Collaborator = { access: Permission; username: string }; @@ -198,6 +199,7 @@ export function createPublishGithubAction(options: { permission, }); } catch (e) { + assertError(e); ctx.logger.warn( `Skipping ${permission} access for ${team_slug}, ${e.message}`, ); @@ -213,6 +215,7 @@ export function createPublishGithubAction(options: { names: topics.map(t => t.toLowerCase()), }); } catch (e) { + assertError(e); ctx.logger.warn(`Skipping topics ${topics.join(' ')}, ${e.message}`); } } @@ -250,6 +253,7 @@ export function createPublishGithubAction(options: { requireCodeOwnerReviews, }); } catch (e) { + assertError(e); ctx.logger.warn( `Skipping: default branch protection on '${newRepo.name}', ${e.message}`, ); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts index 2ba30bb3db..ed72b14a65 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.test.ts @@ -14,21 +14,20 @@ * limitations under the License. */ +import { getRootLogger } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; import mockFs from 'mock-fs'; -import { Writable } from 'stream'; import os from 'os'; import { resolve as resolvePath } from 'path'; -import { - PullRequestCreator, - GithubPullRequestActionInput, - createPublishGithubPullRequestAction, - ClientFactoryInput, -} from './githubPullRequest'; +import { Writable } from 'stream'; import { ActionContext, TemplateAction } from '../../types'; -import { getRootLogger } from '@backstage/backend-common'; - -import { ScmIntegrations } from '@backstage/integration'; -import { ConfigReader } from '@backstage/config'; +import { + ClientFactoryInput, + createPublishGithubPullRequestAction, + GithubPullRequestActionInput, + PullRequestCreator, +} from './githubPullRequest'; const root = os.platform() === 'win32' ? 'C:\\root' : '/root'; const workspacePath = resolvePath(root, 'my-workspace'); @@ -174,6 +173,14 @@ describe('createPublishGithubPullRequestAction', () => { ], }); }); + + it('should not allow to use files outside of the workspace', async () => { + input.sourcePath = '../../test'; + + await expect(instance.handler(ctx)).rejects.toThrow( + 'Relative path is not allowed to refer to a directory outside its parent', + ); + }); }); describe('with repoUrl', () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts index e21ffc5cd0..253fd72b38 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/githubPullRequest.ts @@ -28,6 +28,7 @@ import { Octokit } from '@octokit/rest'; import { InputError, CustomErrorBase } from '@backstage/errors'; import { createPullRequest } from 'octokit-plugin-create-pull-request'; import globby from 'globby'; +import { resolveSafeChildPath } from '@backstage/backend-common'; class GithubResponseError extends CustomErrorBase {} @@ -183,7 +184,7 @@ export const createPublishGithubPullRequestAction = ({ const client = await clientFactory({ integrations, host, owner, repo }); const fileRoot = sourcePath - ? path.resolve(ctx.workspacePath, sourcePath) + ? resolveSafeChildPath(ctx.workspacePath, sourcePath) : ctx.workspacePath; const localFilePaths = await globby(['./**', './**/.*', '!.git'], { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts new file mode 100644 index 0000000000..f179289624 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import path from 'path'; +import { getRepoSourceDirectory } from './util'; + +describe('getRepoSourceDirectory', () => { + it('should return workspace root if no sub folder is given', () => { + expect( + getRepoSourceDirectory(path.join('/', 'var', 'workspace'), undefined), + ).toEqual(path.join('/', 'var', 'workspace')); + }); + + it('should return path in workspace if sub folder is given', () => { + expect( + getRepoSourceDirectory( + path.join('/', 'var', 'workspace'), + path.join('path', 'of', 'subfolder'), + ), + ).toEqual(path.join('/', 'var', 'workspace', 'path', 'of', 'subfolder')); + }); + + it('should not allow traversal outside the workspace root', () => { + // We have to construct the path manually here, as path.join would mitigate the path traversal + expect( + getRepoSourceDirectory( + path.join('/', 'var', 'workspace'), + `..${path.sep}secret`, + ), + ).toEqual(path.join('/', 'var', 'workspace', 'secret')); + expect( + getRepoSourceDirectory( + path.join('/', 'var', 'workspace'), + `.${path.sep}path${path.sep}..${path.sep}..${path.sep}secret`, + ), + ).toEqual(path.join('/', 'var', 'workspace', 'secret')); + expect( + getRepoSourceDirectory( + path.join('/', 'var', 'workspace'), + path.join('/', 'absolute', 'secret'), + ), + ).toEqual(path.join('/', 'var', 'workspace', 'absolute', 'secret')); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts index dea180dc04..58ba5bfdd1 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/util.ts @@ -15,6 +15,7 @@ */ import { InputError } from '@backstage/errors'; +import { isChildPath } from '@backstage/backend-common'; import { join as joinPath, normalize as normalizePath } from 'path'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -27,7 +28,11 @@ export const getRepoSourceDirectory = ( /^(\.\.(\/|\\|$))+/, '', ); - return joinPath(workspacePath, safeSuffix); + const path = joinPath(workspacePath, safeSuffix); + if (!isChildPath(workspacePath, path)) { + throw new Error('Invalid source path'); + } + return path; } return workspacePath; }; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DefaultWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DefaultWorkflowRunner.test.ts index 3ecdd6dcd8..d6d1b0cfd2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DefaultWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DefaultWorkflowRunner.test.ts @@ -13,7 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import os from 'os'; + +import mockFs from 'mock-fs'; +import * as winston from 'winston'; + import { getVoidLogger } from '@backstage/backend-common'; import { DefaultWorkflowRunner } from './DefaultWorkflowRunner'; import { TemplateActionRegistry } from '../actions'; @@ -22,7 +25,6 @@ import { ConfigReader } from '@backstage/config'; import { Task, TaskSpec } from './types'; describe('DefaultWorkflowRunner', () => { - const workingDirectory = os.tmpdir(); const logger = getVoidLogger(); let actionRegistry = new TemplateActionRegistry(); let runner: DefaultWorkflowRunner; @@ -45,6 +47,11 @@ describe('DefaultWorkflowRunner', () => { }); beforeEach(() => { + winston.format.simple(); // put logform the require cache before mocking fs + mockFs({ + '/tmp': mockFs.directory(), + }); + jest.resetAllMocks(); actionRegistry = new TemplateActionRegistry(); fakeActionHandler = jest.fn(); @@ -84,11 +91,15 @@ describe('DefaultWorkflowRunner', () => { runner = new DefaultWorkflowRunner({ actionRegistry, integrations, - workingDirectory, + workingDirectory: '/tmp', logger, }); }); + afterEach(() => { + mockFs.restore(); + }); + it('should throw an error if the action does not exist', async () => { const task = createMockTaskWithSpec({ apiVersion: 'scaffolder.backstage.io/v1beta3', diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/LegacyWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/LegacyWorkflowRunner.test.ts index a82f6b25fa..2714f1b80c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/LegacyWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/LegacyWorkflowRunner.test.ts @@ -13,18 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import mockFs from 'mock-fs'; +import * as winston from 'winston'; import { createTemplateAction, TemplateActionRegistry } from '../actions'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { LegacyWorkflowRunner } from './LegacyWorkflowRunner'; -import os from 'os'; import { Task, TaskSpec } from './types'; import { RepoSpec } from '../actions/builtin/publish/util'; describe('LegacyWorkflowRunner', () => { let runner: LegacyWorkflowRunner; - const workingDirectory = os.tmpdir(); const logger = getVoidLogger(); let actionRegistry = new TemplateActionRegistry(); @@ -45,6 +46,11 @@ describe('LegacyWorkflowRunner', () => { }); beforeEach(() => { + winston.format.simple(); // put logform the require cache before mocking fs + mockFs({ + '/tmp': mockFs.directory(), + }); + actionRegistry = new TemplateActionRegistry(); actionRegistry.register({ id: 'test-action', @@ -57,11 +63,15 @@ describe('LegacyWorkflowRunner', () => { runner = new LegacyWorkflowRunner({ actionRegistry, integrations, - workingDirectory, + workingDirectory: '/tmp', logger, }); }); + afterEach(() => { + mockFs.restore(); + }); + it('should fail when the action does not exist', async () => { const task = createMockTaskWithSpec({ apiVersion: 'backstage.io/v1beta2', diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts index af1f3752e1..529cfed95e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/StorageTaskBroker.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/config'; +import { assertError } from '@backstage/errors'; import { Logger } from 'winston'; import { CompletedTaskState, @@ -195,6 +196,7 @@ export class StorageTaskBroker implements TaskBroker { try { callback(undefined, result); } catch (error) { + assertError(error); callback(error, { events: [] }); } } diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index 65ba71e9fe..6e70ea06a6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -20,6 +20,7 @@ import { DefaultWorkflowRunner } from './DefaultWorkflowRunner'; import { Logger } from 'winston'; import { TemplateActionRegistry } from '../actions'; import { ScmIntegrations } from '@backstage/integration'; +import { assertError } from '@backstage/errors'; /** * TaskWorkerOptions @@ -102,6 +103,7 @@ export class TaskWorker { await task.complete('completed', { output }); } catch (error) { + assertError(error); await task.complete('failed', { error: { name: error.name, message: error.message }, }); diff --git a/plugins/scaffolder-backend/src/service/helpers.ts b/plugins/scaffolder-backend/src/service/helpers.ts index 7125e9df93..6741ab3379 100644 --- a/plugins/scaffolder-backend/src/service/helpers.ts +++ b/plugins/scaffolder-backend/src/service/helpers.ts @@ -21,6 +21,7 @@ import { SOURCE_LOCATION_ANNOTATION, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; +import { assertError } from '@backstage/errors'; import fs from 'fs-extra'; import os from 'os'; import { Logger } from 'winston'; @@ -39,6 +40,7 @@ export async function getWorkingDirectory( await fs.access(workingDirectory, fs.constants.F_OK | fs.constants.W_OK); logger.info(`using working directory: ${workingDirectory}`); } catch (err) { + assertError(err); logger.error( `working directory ${workingDirectory} ${ err.code === 'ENOENT' ? 'does not exist' : 'is not writable' diff --git a/plugins/scaffolder-common/package.json b/plugins/scaffolder-common/package.json index 7f79dab541..b0c8de30c7 100644 --- a/plugins/scaffolder-common/package.json +++ b/plugins/scaffolder-common/package.json @@ -36,10 +36,10 @@ "url": "https://github.com/backstage/backstage/issues" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10" }, "devDependencies": { - "@backstage/cli": "^0.7.15" + "@backstage/cli": "^0.8.0" } } diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 1d5510f704..119ed36685 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder +## 0.11.8 + +### Patch Changes + +- 0366c9b667: Introduce a `useStarredEntity` hook to check if a single entity is starred. + It provides a more efficient implementation compared to the `useStarredEntities` hook, because the rendering is only triggered if the selected entity is starred, not if _any_ entity is starred. +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/integration@0.6.8 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + - @backstage/integration-react@0.1.12 + ## 0.11.7 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 7acfe55692..10483f4807 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder", "description": "The Backstage plugin that helps you create new things", - "version": "0.11.7", + "version": "0.11.8", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,15 +32,15 @@ }, "dependencies": { "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.2", - "@backstage/integration": "^0.6.7", - "@backstage/integration-react": "^0.1.11", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", + "@backstage/integration-react": "^0.1.12", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -64,10 +64,10 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/search-backend-module-elasticsearch/package.json b/plugins/search-backend-module-elasticsearch/package.json index 35d4a47277..87688e455f 100644 --- a/plugins/search-backend-module-elasticsearch/package.json +++ b/plugins/search-backend-module-elasticsearch/package.json @@ -30,8 +30,8 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/backend-common": "^0.9.3", - "@backstage/cli": "^0.7.12", + "@backstage/backend-common": "^0.9.7", + "@backstage/cli": "^0.8.0", "@elastic/elasticsearch-mock": "^0.3.0" }, "files": [ diff --git a/plugins/search-backend-module-pg/package.json b/plugins/search-backend-module-pg/package.json index a7196bc283..a31d908ac4 100644 --- a/plugins/search-backend-module-pg/package.json +++ b/plugins/search-backend-module-pg/package.json @@ -20,15 +20,15 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.4", + "@backstage/backend-common": "^0.9.7", "@backstage/search-common": "^0.2.0", "@backstage/plugin-search-backend-node": "^0.4.2", "lodash": "^4.17.21", "knex": "^0.95.1" }, "devDependencies": { - "@backstage/backend-test-utils": "^0.1.6", - "@backstage/cli": "^0.7.13" + "@backstage/backend-test-utils": "^0.1.8", + "@backstage/cli": "^0.8.0" }, "files": [ "dist", diff --git a/plugins/search-backend-node/package.json b/plugins/search-backend-node/package.json index b2f835d16d..6681d31819 100644 --- a/plugins/search-backend-node/package.json +++ b/plugins/search-backend-node/package.json @@ -26,8 +26,8 @@ "@types/lunr": "^2.3.3" }, "devDependencies": { - "@backstage/backend-common": "^0.9.1", - "@backstage/cli": "^0.7.10" + "@backstage/backend-common": "^0.9.7", + "@backstage/cli": "^0.8.0" }, "files": [ "dist" diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts index a2cbb4ecc3..cbe48ef5a7 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.test.ts @@ -192,6 +192,37 @@ describe('LunrSearchEngine', () => { }); }); + it('should handle single-item array filter as scalar value', async () => { + const inspectableSearchEngine = new LunrSearchEngineForTranslatorTests({ + logger: getVoidLogger(), + }); + const translatorUnderTest = inspectableSearchEngine.getTranslator(); + + const actualTranslatedQuery = translatorUnderTest({ + term: 'testTerm', + filters: { kind: ['testKind'] }, + }) as ConcreteLunrQuery; + + expect(actualTranslatedQuery).toMatchObject({ + documentTypes: undefined, + lunrQueryBuilder: expect.any(Function), + }); + + const query: jest.Mocked = { + allFields: ['kind'], + clauses: [], + term: jest.fn(), + clause: jest.fn(), + }; + + actualTranslatedQuery.lunrQueryBuilder.bind(query)(query); + + expect(query.term).toBeCalledWith(lunr.tokenizer('testKind'), { + fields: ['kind'], + presence: lunr.Query.presence.REQUIRED, + }); + }); + it('should return translated query with multiple filters', async () => { const inspectableSearchEngine = new LunrSearchEngineForTranslatorTests({ logger: getVoidLogger(), diff --git a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts index f22762cb9f..ea51ffe8e1 100644 --- a/plugins/search-backend-node/src/engines/LunrSearchEngine.ts +++ b/plugins/search-backend-node/src/engines/LunrSearchEngine.ts @@ -80,11 +80,17 @@ export class LunrSearchEngine implements SearchEngine { }); if (filters) { - Object.entries(filters).forEach(([field, value]) => { + Object.entries(filters).forEach(([field, fieldValue]) => { if (!q.allFields.includes(field)) { // Throw for unknown field, as this will be a non match throw new Error(`unrecognised field ${field}`); } + // Arrays are poorly supported, but we can make it better for single-item arrays, + // which should be a common case + const value = + Array.isArray(fieldValue) && fieldValue.length === 1 + ? fieldValue[0] + : fieldValue; // Require that the given field has the given value if (['string', 'number', 'boolean'].includes(typeof value)) { diff --git a/plugins/search-backend/package.json b/plugins/search-backend/package.json index 7d1f4d1cab..18d4484451 100644 --- a/plugins/search-backend/package.json +++ b/plugins/search-backend/package.json @@ -20,7 +20,7 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.1", + "@backstage/backend-common": "^0.9.7", "@backstage/search-common": "^0.2.0", "@backstage/plugin-search-backend-node": "^0.4.2", "@types/express": "^4.17.6", @@ -30,7 +30,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.10", + "@backstage/cli": "^0.8.0", "@types/supertest": "^2.0.8", "supertest": "^6.1.3" }, diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 89e33f9784..f92a021e5c 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-search +## 0.4.15 + +### Patch Changes + +- 56bd537256: SearchBar component to accept optional placeholder prop +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.4.14 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index d763d06774..9830d26e5c 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-search", "description": "The Backstage plugin that provides your backstage app with search", - "version": "0.4.14", + "version": "0.4.15", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -30,14 +30,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.5.2", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.1", "@backstage/search-common": "^0.2.0", - "@backstage/theme": "^0.2.10", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -50,10 +50,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/sentry/CHANGELOG.md b/plugins/sentry/CHANGELOG.md index 1d1a5028f3..cfaab7754c 100644 --- a/plugins/sentry/CHANGELOG.md +++ b/plugins/sentry/CHANGELOG.md @@ -1,5 +1,25 @@ # @backstage/plugin-sentry +## 0.3.26 + +### Patch Changes + +- f93e4349e5: fix: parameter name on call to sentry api +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.3.25 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.24 ### Patch Changes diff --git a/plugins/sentry/package.json b/plugins/sentry/package.json index 366a609b06..ae3aad815f 100644 --- a/plugins/sentry/package.json +++ b/plugins/sentry/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sentry", "description": "A Backstage plugin that integrates towards Sentry", - "version": "0.3.24", + "version": "0.3.26", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,11 +32,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -48,10 +48,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/sentry/src/api/production-api.ts b/plugins/sentry/src/api/production-api.ts index 0e7f5b784d..e634650f96 100644 --- a/plugins/sentry/src/api/production-api.ts +++ b/plugins/sentry/src/api/production-api.ts @@ -32,7 +32,7 @@ export class ProductionSentryApi implements SentryApi { const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/sentry/api`; const response = await fetch( - `${apiUrl}/0/projects/${this.organization}/${project}/issues/?statsFor=${statsFor}`, + `${apiUrl}/0/projects/${this.organization}/${project}/issues/?statsPeriod=${statsFor}`, ); if (response.status >= 400 && response.status < 600) { diff --git a/plugins/shortcuts/CHANGELOG.md b/plugins/shortcuts/CHANGELOG.md index a5a53a45dc..8e454f53e3 100644 --- a/plugins/shortcuts/CHANGELOG.md +++ b/plugins/shortcuts/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-shortcuts +## 0.1.12 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.11 ### Patch Changes diff --git a/plugins/shortcuts/package.json b/plugins/shortcuts/package.json index 0ae27eec9e..c9afe49c5a 100644 --- a/plugins/shortcuts/package.json +++ b/plugins/shortcuts/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-shortcuts", "description": "A Backstage plugin that provides a shortcuts feature to the sidebar", - "version": "0.1.11", + "version": "0.1.12", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,9 +21,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -37,10 +37,10 @@ "zen-observable": "^0.8.15" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/sonarqube/CHANGELOG.md b/plugins/sonarqube/CHANGELOG.md index 917a2ec0e2..8886ca3645 100644 --- a/plugins/sonarqube/CHANGELOG.md +++ b/plugins/sonarqube/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-sonarqube +## 0.2.6 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.5 ### Patch Changes diff --git a/plugins/sonarqube/package.json b/plugins/sonarqube/package.json index 4d835045fa..971eb1e8cb 100644 --- a/plugins/sonarqube/package.json +++ b/plugins/sonarqube/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-sonarqube", "description": "", - "version": "0.2.5", + "version": "0.2.6", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -33,11 +33,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -49,10 +49,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/splunk-on-call/CHANGELOG.md b/plugins/splunk-on-call/CHANGELOG.md index f78686838c..4bd0b9e9bc 100644 --- a/plugins/splunk-on-call/CHANGELOG.md +++ b/plugins/splunk-on-call/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-splunk-on-call +## 0.3.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.13 ### Patch Changes diff --git a/plugins/splunk-on-call/package.json b/plugins/splunk-on-call/package.json index 7841d99ee1..007707a735 100644 --- a/plugins/splunk-on-call/package.json +++ b/plugins/splunk-on-call/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-splunk-on-call", "description": "A Backstage plugin that integrates towards Splunk On-Call", - "version": "0.3.13", + "version": "0.3.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,11 +31,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -47,10 +47,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/tech-radar/CHANGELOG.md b/plugins/tech-radar/CHANGELOG.md index b5ab486b79..8e7b5875a9 100644 --- a/plugins/tech-radar/CHANGELOG.md +++ b/plugins/tech-radar/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-tech-radar +## 0.4.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.4.10 ### Patch Changes diff --git a/plugins/tech-radar/package.json b/plugins/tech-radar/package.json index 7ad89495e6..bf146c4c2a 100644 --- a/plugins/tech-radar/package.json +++ b/plugins/tech-radar/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-tech-radar", "description": "A Backstage plugin that lets you display a Tech Radar for your organization", - "version": "0.4.10", + "version": "0.4.11", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "start": "backstage-cli plugin:serve" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -45,10 +45,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/tech-radar/src/sample.ts b/plugins/tech-radar/src/sample.ts index 9c89a1e73a..2b674f35c8 100644 --- a/plugins/tech-radar/src/sample.ts +++ b/plugins/tech-radar/src/sample.ts @@ -51,7 +51,7 @@ entries.push({ title: 'JavaScript', quadrant: 'languages', description: - 'Excepteur **sint** occaecat *cupidatat* non proident, sunt in culpa qui officia deserunt mollit anim id est laborum', + 'Excepteur **sint** occaecat *cupidatat* non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n```ts\nconst x = "3";\n```\n', }); entries.push({ timeline: [ diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 7b88ae0c41..221a681203 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs-backend +## 0.10.5 + +### Patch Changes + +- 177401b571: Display entity title (if defined) in titles of TechDocs search results +- 36e67d2f24: Internal updates to apply more strict checks to throw errors. +- Updated dependencies + - @backstage/techdocs-common@0.10.4 + - @backstage/backend-common@0.9.7 + - @backstage/errors@0.1.3 + - @backstage/catalog-model@0.9.5 + ## 0.10.4 ### Patch Changes diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index cac7dcf422..c4fec93c10 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs-backend", "description": "The Backstage backend plugin that renders technical documentation for your components", - "version": "0.10.4", + "version": "0.10.5", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,14 +31,14 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.1", + "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.7", "@backstage/search-common": "^0.2.0", - "@backstage/techdocs-common": "^0.10.3", + "@backstage/techdocs-common": "^0.10.4", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", "dockerode": "^3.2.1", @@ -51,7 +51,7 @@ "winston": "^3.2.1" }, "devDependencies": { - "@backstage/cli": "^0.7.15", + "@backstage/cli": "^0.8.0", "@backstage/test-utils": "^0.1.18", "@types/dockerode": "^3.2.1", "msw": "^0.29.0", diff --git a/plugins/techdocs-backend/src/DocsBuilder/builder.ts b/plugins/techdocs-backend/src/DocsBuilder/builder.ts index 5327062233..821b3478a0 100644 --- a/plugins/techdocs-backend/src/DocsBuilder/builder.ts +++ b/plugins/techdocs-backend/src/DocsBuilder/builder.ts @@ -19,7 +19,7 @@ import { stringifyEntityRef, } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { NotModifiedError } from '@backstage/errors'; +import { assertError, isError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { GeneratorBase, @@ -131,7 +131,7 @@ export class DocsBuilder { preparedDir = preparerResponse.preparedDir; newEtag = preparerResponse.etag; } catch (err) { - if (err instanceof NotModifiedError) { + if (isError(err) && err.name === 'NotModifiedError') { // No need to prepare anymore since cache is valid. // Set last check happened to now new BuildMetadataStorage(this.entity.metadata.uid).setLastUpdated(); @@ -142,7 +142,7 @@ export class DocsBuilder { ); return false; } - throw new Error(err.message); + throw err; } this.logger.info( @@ -195,6 +195,7 @@ export class DocsBuilder { // Not a blocker hence no need to await this. fs.remove(preparedDir); } catch (error) { + assertError(error); this.logger.debug(`Error removing prepared directory ${error.message}`); } } @@ -221,6 +222,7 @@ export class DocsBuilder { `Removing generated directory ${outputDir} since the site has been published`, ); } catch (error) { + assertError(error); this.logger.debug(`Error removing generated directory ${error.message}`); } diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts index 0df22bee53..006cfdd073 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.test.ts @@ -58,6 +58,7 @@ const expectedEntities: Entity[] = [ apiVersion: 'backstage.io/v1alpha1', kind: 'Component', metadata: { + title: 'Test Entity with Docs!', name: 'test-entity-with-docs', description: 'Documented description', annotations: { @@ -133,6 +134,7 @@ describe('DefaultTechDocsCollator with legacyPathCasing configuration', () => { location: `/docs/default/Component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`, text: mockSearchDocIndex.docs[idx].text, namespace: 'default', + entityTitle: entity!.metadata.title, componentType: entity!.spec!.type, lifecycle: entity!.spec!.lifecycle, owner: '', @@ -177,6 +179,7 @@ describe('DefaultTechDocsCollator', () => { location: `/docs/default/component/${entity.metadata.name}/${mockSearchDocIndex.docs[idx].location}`, text: mockSearchDocIndex.docs[idx].text, namespace: 'default', + entityTitle: entity!.metadata.title, componentType: entity!.spec!.type, lifecycle: entity!.spec!.lifecycle, owner: '', diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts index cb7d40206b..c0a96b7862 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollator.ts @@ -93,6 +93,7 @@ export class DefaultTechDocsCollator implements DocumentCollator { 'namespace', 'metadata.annotations', 'metadata.name', + 'metadata.title', 'metadata.namespace', 'spec.type', 'spec.lifecycle', @@ -130,6 +131,7 @@ export class DefaultTechDocsCollator implements DocumentCollator { }), path: doc.location, ...entityInfo, + entityTitle: entity.metadata.title, componentType: entity.spec?.type?.toString() || 'other', lifecycle: (entity.spec?.lifecycle as string) || '', owner: diff --git a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts index 463b895564..6f977dcb47 100644 --- a/plugins/techdocs-backend/src/service/DocsSynchronizer.ts +++ b/plugins/techdocs-backend/src/service/DocsSynchronizer.ts @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; -import { NotFoundError } from '@backstage/errors'; +import { assertError, NotFoundError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { GeneratorBuilder, @@ -113,6 +113,7 @@ export class DocsSynchronizer { return; } } catch (e) { + assertError(e); const msg = `Failed to build the docs page: ${e.message}`; taskLogger.error(msg); this.logger.error(msg, e); diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index 4eb78f8c26..f3b94c8579 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,39 @@ # @backstage/plugin-techdocs +## 0.12.3 + +### Patch Changes + +- ba5b75ed2f: Add `` as an alternative to `` that + shows a grid of card instead of table. + + Extend `` to display the entity title of the entity instead of the + name if available. + +- 177401b571: Display entity title (if defined) in titles of TechDocs search results +- cdf8ca6111: Only replace the shadow dom if the content is changed to avoid a flickering UI. +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/errors@0.1.3 + - @backstage/core-plugin-api@0.1.11 + - @backstage/plugin-catalog@0.7.2 + - @backstage/plugin-catalog-react@0.6.1 + - @backstage/catalog-model@0.9.5 + +## 0.12.2 + +### Patch Changes + +- 76fef740fe: Refactored `` component internals to support future extensibility. +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/plugin-catalog@0.7.1 + - @backstage/integration@0.6.8 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + - @backstage/plugin-search@0.4.15 + - @backstage/integration-react@0.1.12 + ## 0.12.1 ### Patch Changes diff --git a/plugins/techdocs/api-report.md b/plugins/techdocs/api-report.md index b091d37743..c6b16be0b3 100644 --- a/plugins/techdocs/api-report.md +++ b/plugins/techdocs/api-report.md @@ -145,6 +145,11 @@ export type DocsTableRow = { // @public (undocumented) export const EmbeddedDocsRouter: (_props: Props_2) => JSX.Element; +// Warning: (ae-missing-release-tag) "EntityListDocsGrid" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const EntityListDocsGrid: () => JSX.Element; + // Warning: (ae-missing-release-tag) "EntityListDocsTable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 7a61144192..0aecd7d17c 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-techdocs", "description": "The Backstage plugin that renders technical documentation for your components", - "version": "0.12.1", + "version": "0.12.3", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -32,17 +32,17 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/integration": "^0.6.7", - "@backstage/integration-react": "^0.1.11", - "@backstage/plugin-catalog": "^0.7.0", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/plugin-search": "^0.4.14", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/integration": "^0.6.8", + "@backstage/integration-react": "^0.1.12", + "@backstage/plugin-catalog": "^0.7.2", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/plugin-search": "^0.4.15", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -61,10 +61,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/react-hooks": "^7.0.2", diff --git a/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.test.tsx b/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.test.tsx index 22dc86f440..807914c5ad 100644 --- a/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.test.tsx +++ b/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.test.tsx @@ -33,6 +33,17 @@ const validResult = { lifecycle: 'production', }; +const validResultWithTitle = { + location: 'https://backstage.io/docs', + title: 'Documentation', + text: 'Backstage is an open-source developer portal that puts the developer experience first.', + kind: 'library', + namespace: '', + name: 'Backstage', + entityTitle: 'Backstage App', + lifecycle: 'production', +}; + describe('DocsResultListItem test', () => { it('should render search doc passed in', async () => { const { findByText } = render(); @@ -59,4 +70,14 @@ describe('DocsResultListItem test', () => { ), ).toBeInTheDocument(); }); + + it('should use entity title if defined', async () => { + const { findByText } = render( + , + ); + + expect( + await findByText('Documentation | Backstage App docs'), + ).toBeInTheDocument(); + }); }); diff --git a/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.tsx b/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.tsx index 54e6110b88..03cf011c32 100644 --- a/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.tsx +++ b/plugins/techdocs/src/components/DocsResultListItem/DocsResultListItem.tsx @@ -47,7 +47,11 @@ export const DocsResultListItem = ({ { '/techdocs/SomeNamespace/TestKind/testName', ); }); + + it('should render entity title if available', async () => { + const { findByText } = render( + wrapInTestApp( + , + { + mountedRoutes: { + '/docs/:namespace/:kind/:name/*': rootDocsRouteRef, + }, + }, + ), + ); + expect(await findByText('TestTitle')).toBeInTheDocument(); + }); }); diff --git a/plugins/techdocs/src/home/components/DocsCardGrid.tsx b/plugins/techdocs/src/home/components/DocsCardGrid.tsx index badc338b1b..e84454ae54 100644 --- a/plugins/techdocs/src/home/components/DocsCardGrid.tsx +++ b/plugins/techdocs/src/home/components/DocsCardGrid.tsx @@ -49,7 +49,9 @@ export const DocsCardGrid = ({ : entities.map((entity, index: number) => ( - + {entity.metadata.description} diff --git a/plugins/techdocs/src/home/components/EntityListDocsGrid.tsx b/plugins/techdocs/src/home/components/EntityListDocsGrid.tsx new file mode 100644 index 0000000000..8c04a29f66 --- /dev/null +++ b/plugins/techdocs/src/home/components/EntityListDocsGrid.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { + CodeSnippet, + Progress, + WarningPanel, +} from '@backstage/core-components'; +import { useEntityListProvider } from '@backstage/plugin-catalog-react'; +import React from 'react'; +import { DocsCardGrid } from './DocsCardGrid'; + +export const EntityListDocsGrid = () => { + const { loading, error, entities } = useEntityListProvider(); + + if (error) { + return ( + + + + ); + } + + if (loading || !entities) { + return ; + } + + entities.sort((a, b) => + (a.metadata.title ?? a.metadata.name).localeCompare( + b.metadata.title ?? b.metadata.name, + ), + ); + + return ; +}; diff --git a/plugins/techdocs/src/home/components/index.ts b/plugins/techdocs/src/home/components/index.ts index 53dd0fd909..d9d627cf8d 100644 --- a/plugins/techdocs/src/home/components/index.ts +++ b/plugins/techdocs/src/home/components/index.ts @@ -14,9 +14,10 @@ * limitations under the License. */ -export { EntityListDocsTable } from './EntityListDocsTable'; export { DefaultTechDocsHome } from './DefaultTechDocsHome'; +export { EntityListDocsGrid } from './EntityListDocsGrid'; +export { EntityListDocsTable } from './EntityListDocsTable'; +export type { PanelType } from './TechDocsCustomHome'; export { TechDocsPageWrapper } from './TechDocsPageWrapper'; export { TechDocsPicker } from './TechDocsPicker'; -export type { PanelType } from './TechDocsCustomHome'; export type { DocsTableRow } from './types'; diff --git a/plugins/techdocs/src/index.ts b/plugins/techdocs/src/index.ts index 50e25c5582..a6a95e9264 100644 --- a/plugins/techdocs/src/index.ts +++ b/plugins/techdocs/src/index.ts @@ -24,14 +24,15 @@ export * from './api'; export { techdocsApiRef, techdocsStorageApiRef } from './api'; export type { TechDocsApi, TechDocsStorageApi } from './api'; export { TechDocsClient, TechDocsStorageClient } from './client'; -export type { DocsTableRow, PanelType } from './home/components'; +export * from './components/DocsResultListItem'; export { - EntityListDocsTable, DefaultTechDocsHome, + EntityListDocsGrid, + EntityListDocsTable, TechDocsPageWrapper, TechDocsPicker, } from './home/components'; -export * from './components/DocsResultListItem'; +export type { DocsTableRow, PanelType } from './home/components'; export { DocsCardGrid, DocsTable, @@ -44,4 +45,4 @@ export { TechDocsReaderPage, } from './plugin'; export * from './reader'; -export { EmbeddedDocsRouter, Router, isTechDocsAvailable } from './Router'; +export { EmbeddedDocsRouter, isTechDocsAvailable, Router } from './Router'; diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 0cb6c039d0..7307961772 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -397,6 +397,11 @@ const TheReader = ({ const dom = useTechDocsReaderDom(); const shadowDomRef = useRef(null); + const onReadyRef = useRef<() => void>(onReady); + useEffect(() => { + onReadyRef.current = onReady; + }, [onReady]); + useEffect(() => { if (!dom || !shadowDomRef.current) return; const shadowDiv = shadowDomRef.current; @@ -406,8 +411,10 @@ const TheReader = ({ shadowRoot.removeChild(child), ); shadowRoot.appendChild(dom); - onReady(); - }, [dom, onReady]); + onReadyRef.current(); + + // this hook must ONLY be triggered by a changed dom + }, [dom]); return ( <> diff --git a/plugins/todo-backend/package.json b/plugins/todo-backend/package.json index 2e945487a4..67c990cf13 100644 --- a/plugins/todo-backend/package.json +++ b/plugins/todo-backend/package.json @@ -25,11 +25,11 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/backend-common": "^0.9.6", + "@backstage/backend-common": "^0.9.7", "@backstage/catalog-client": "^0.5.0", - "@backstage/catalog-model": "^0.9.4", + "@backstage/catalog-model": "^0.9.5", "@backstage/config": "^0.1.10", - "@backstage/errors": "^0.1.1", + "@backstage/errors": "^0.1.3", "@backstage/integration": "^0.6.7", "@types/express": "^4.17.6", "cross-fetch": "^3.0.6", @@ -40,7 +40,7 @@ "yn": "^4.0.0" }, "devDependencies": { - "@backstage/cli": "^0.7.15", + "@backstage/cli": "^0.8.0", "@types/supertest": "^2.0.8", "msw": "^0.29.0", "supertest": "^6.1.3" diff --git a/plugins/todo/CHANGELOG.md b/plugins/todo/CHANGELOG.md index 880df42ca1..99c33c425e 100644 --- a/plugins/todo/CHANGELOG.md +++ b/plugins/todo/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-todo +## 0.1.14 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@0.6.0 + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.1.13 ### Patch Changes diff --git a/plugins/todo/package.json b/plugins/todo/package.json index 03a955fda3..d20ff43470 100644 --- a/plugins/todo/package.json +++ b/plugins/todo/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-todo", "description": "A Backstage plugin that lets you browse TODO comments in your source code", - "version": "0.1.13", + "version": "0.1.14", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -27,12 +27,12 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/catalog-model": "^0.9.4", - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.2", - "@backstage/plugin-catalog-react": "^0.5.2", - "@backstage/theme": "^0.2.10", + "@backstage/catalog-model": "^0.9.5", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/plugin-catalog-react": "^0.6.1", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -41,10 +41,10 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index b16e327f02..ae3bc1c72d 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/plugin-user-settings +## 0.3.10 + +### Patch Changes + +- 63602a1753: Align grid height +- 202f322927: Atlassian auth provider + + - AtlassianAuth added to core-app-api + - Atlassian provider added to plugin-auth-backend + - Updated user-settings with Atlassian connection + +- Updated dependencies + - @backstage/core-components@0.7.1 + - @backstage/core-plugin-api@0.1.11 + +## 0.3.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.3.8 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index c8f105080a..bc836a7251 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-user-settings", "description": "A Backstage plugin that provides a settings page", - "version": "0.3.8", + "version": "0.3.10", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -31,9 +31,9 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -43,11 +43,11 @@ "react-use": "^17.2.4" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx index 4b9cf9c783..8cfb3a7257 100644 --- a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx +++ b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx @@ -25,6 +25,7 @@ import { oktaAuthApiRef, microsoftAuthApiRef, bitbucketAuthApiRef, + atlassianAuthApiRef, } from '@backstage/core-plugin-api'; type Props = { @@ -89,6 +90,14 @@ export const DefaultProviderSettings = ({ configuredProviders }: Props) => ( icon={Star} /> )} + {configuredProviders.includes('atlassian') && ( + + )} {configuredProviders.includes('oauth2') && ( ( - + diff --git a/plugins/user-settings/src/components/General/UserSettingsProfileCard.tsx b/plugins/user-settings/src/components/General/UserSettingsProfileCard.tsx index f79b1084c5..93bb32c5db 100644 --- a/plugins/user-settings/src/components/General/UserSettingsProfileCard.tsx +++ b/plugins/user-settings/src/components/General/UserSettingsProfileCard.tsx @@ -24,7 +24,7 @@ export const UserSettingsProfileCard = () => { const { profile, displayName } = useUserProfile(); return ( - + diff --git a/plugins/welcome/CHANGELOG.md b/plugins/welcome/CHANGELOG.md deleted file mode 100644 index d6952c886a..0000000000 --- a/plugins/welcome/CHANGELOG.md +++ /dev/null @@ -1,204 +0,0 @@ -# @backstage/plugin-welcome - -## 0.3.7 - -### Patch Changes - -- 81a41ec249: Added a `name` key to all extensions in order to improve Analytics API metadata. -- Updated dependencies - - @backstage/core-components@0.6.1 - - @backstage/core-plugin-api@0.1.10 - -## 0.3.6 - -### Patch Changes - -- Updated dependencies - - @backstage/core-plugin-api@0.1.9 - - @backstage/core-components@0.6.0 - -## 0.3.5 - -### Patch Changes - -- Updated dependencies - - @backstage/core-components@0.5.0 - -## 0.3.4 - -### Patch Changes - -- 9f1362dcc1: Upgrade `@material-ui/lab` to `4.0.0-alpha.57`. -- Updated dependencies - - @backstage/core-components@0.4.2 - - @backstage/core-plugin-api@0.1.8 - -## 0.3.3 - -### Patch Changes - -- Updated dependencies - - @backstage/core-components@0.4.0 - -## 0.3.2 - -### Patch Changes - -- Updated dependencies - - @backstage/core-components@0.3.0 - - @backstage/core-plugin-api@0.1.5 - -## 0.3.1 - -### Patch Changes - -- 9d40fcb1e: - Bumping `material-ui/core` version to at least `4.12.2` as they made some breaking changes in later versions which broke `Pagination` of the `Table`. - - Switching out `material-table` to `@material-table/core` for support for the later versions of `material-ui/core` - - This causes a minor API change to `@backstage/core-components` as the interface for `Table` re-exports the `prop` from the underlying `Table` components. - - `onChangeRowsPerPage` has been renamed to `onRowsPerPageChange` - - `onChangePage` has been renamed to `onPageChange` - - Migration guide is here: https://material-table-core.com/docs/breaking-changes -- Updated dependencies - - @backstage/core-components@0.2.0 - - @backstage/core-plugin-api@0.1.4 - - @backstage/theme@0.2.9 - -## 0.3.0 - -### Minor Changes - -- d719926d2: **BREAKING CHANGE** Remove deprecated route registrations, meaning that it is no longer enough to only import the plugin in the app and the exported page extension must be used instead. - -### Patch Changes - -- 48c9fcd33: Migrated to use the new `@backstage/core-*` packages rather than `@backstage/core`. -- Updated dependencies - - @backstage/core-plugin-api@0.1.3 - -## 0.2.8 - -### Patch Changes - -- 062bbf90f: chore: bump `@testing-library/user-event` from 12.8.3 to 13.1.8 -- 675a569a9: chore: bump `react-use` dependency in all packages -- Updated dependencies [062bbf90f] -- Updated dependencies [889d89b6e] -- Updated dependencies [3f988cb63] -- Updated dependencies [675a569a9] - - @backstage/core@0.7.9 - -## 0.2.7 - -### Patch Changes - -- f85851837: Australian Greeting -- Updated dependencies [94da20976] -- Updated dependencies [d8cc7e67a] -- Updated dependencies [99fbef232] -- Updated dependencies [ab07d77f6] -- Updated dependencies [931b21a12] -- Updated dependencies [937ed39ce] -- Updated dependencies [9a9e7a42f] -- Updated dependencies [50ce875a0] - - @backstage/core@0.7.6 - - @backstage/theme@0.2.6 - -## 0.2.6 - -### Patch Changes - -- Updated dependencies [40c0fdbaa] -- Updated dependencies [2a271d89e] -- Updated dependencies [bece09057] -- Updated dependencies [169f48deb] -- Updated dependencies [8a1566719] -- Updated dependencies [4c049a1a1] - - @backstage/core@0.7.0 - -## 0.2.5 - -### Patch Changes - -- 8dfdec613: Migrated to new composability API, exporting the plugin as `welcomePlugin` and the page as `WelcomePage`. -- Updated dependencies [12ece98cd] -- Updated dependencies [d82246867] -- Updated dependencies [c810082ae] -- Updated dependencies [5fa3bdb55] -- Updated dependencies [21e624ba9] -- Updated dependencies [da9f53c60] -- Updated dependencies [32c95605f] -- Updated dependencies [54c7d02f7] - - @backstage/core@0.6.0 - - @backstage/theme@0.2.3 - -## 0.2.4 - -### Patch Changes - -- Updated dependencies [efd6ef753] -- Updated dependencies [a187b8ad0] - - @backstage/core@0.5.0 - -## 0.2.3 - -### Patch Changes - -- Updated dependencies [2527628e1] -- Updated dependencies [1c69d4716] -- Updated dependencies [1665ae8bb] -- Updated dependencies [04f26f88d] -- Updated dependencies [ff243ce96] - - @backstage/core@0.4.0 - - @backstage/theme@0.2.2 - -## 0.2.2 - -### Patch Changes - -- 303c5ea17: Refactor route registration to remove deprecating code - -## 0.2.1 - -### Patch Changes - -- Updated dependencies [7b37d65fd] -- Updated dependencies [4aca74e08] -- Updated dependencies [e8f69ba93] -- Updated dependencies [0c0798f08] -- Updated dependencies [0c0798f08] -- Updated dependencies [199237d2f] -- Updated dependencies [6627b626f] -- Updated dependencies [4577e377b] - - @backstage/core@0.3.0 - - @backstage/theme@0.2.1 - -## 0.2.0 - -### Minor Changes - -- 28edd7d29: Create backend plugin through CLI - -### Patch Changes - -- Updated dependencies [819a70229] -- Updated dependencies [ae5983387] -- Updated dependencies [0d4459c08] -- Updated dependencies [482b6313d] -- Updated dependencies [1c60f716e] -- Updated dependencies [144c66d50] -- Updated dependencies [b79017fd3] -- Updated dependencies [6d97d2d6f] -- Updated dependencies [93a3fa3ae] -- Updated dependencies [782f3b354] -- Updated dependencies [2713f28f4] -- Updated dependencies [406015b0d] -- Updated dependencies [82759d3e4] -- Updated dependencies [ac8d5d5c7] -- Updated dependencies [ebca83d48] -- Updated dependencies [aca79334f] -- Updated dependencies [c0d5242a0] -- Updated dependencies [3beb5c9fc] -- Updated dependencies [754e31db5] -- Updated dependencies [1611c6dbc] - - @backstage/core@0.2.0 - - @backstage/theme@0.2.0 diff --git a/plugins/welcome/README.md b/plugins/welcome/README.md deleted file mode 100644 index c40a760c7c..0000000000 --- a/plugins/welcome/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Title - -> This plugin formerly provided the "homepage" of early alpha versions of Backstage. -> It is no longer in active use and in most cases can be removed from your instance. - -Welcome to the welcome plugin! - -## Sub-section 1 - -## Sub-section 2 diff --git a/plugins/welcome/api-report.md b/plugins/welcome/api-report.md deleted file mode 100644 index 02a46615f3..0000000000 --- a/plugins/welcome/api-report.md +++ /dev/null @@ -1,21 +0,0 @@ -## API Report File for "@backstage/plugin-welcome" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -/// - -import { BackstagePlugin } from '@backstage/core-plugin-api'; - -// Warning: (ae-missing-release-tag) "WelcomePage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const WelcomePage: () => JSX.Element; - -// Warning: (ae-missing-release-tag) "welcomePlugin" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -const welcomePlugin: BackstagePlugin<{}, {}>; -export { welcomePlugin as plugin }; -export { welcomePlugin }; -``` diff --git a/plugins/welcome/package.json b/plugins/welcome/package.json deleted file mode 100644 index e0f6684dbc..0000000000 --- a/plugins/welcome/package.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "@backstage/plugin-welcome", - "description": "An old Backstage plugin that provides a welcome page", - "version": "0.3.7", - "main": "src/index.ts", - "types": "src/index.ts", - "private": false, - "license": "Apache-2.0", - "publishConfig": { - "access": "public", - "main": "dist/index.esm.js", - "types": "dist/index.d.ts" - }, - "homepage": "https://backstage.io", - "repository": { - "type": "git", - "url": "https://github.com/backstage/backstage", - "directory": "plugins/welcome" - }, - "keywords": [ - "backstage" - ], - "scripts": { - "build": "backstage-cli plugin:build", - "lint": "backstage-cli lint", - "test": "backstage-cli test", - "diff": "backstage-cli plugin:diff", - "prepack": "backstage-cli prepack", - "postpack": "backstage-cli postpack", - "clean": "backstage-cli clean", - "start": "backstage-cli plugin:serve" - }, - "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/theme": "^0.2.10", - "@material-ui/core": "^4.12.2", - "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "4.0.0-alpha.57", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "react-router-dom": "6.0.0-beta.0", - "react-use": "^17.2.4" - }, - "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", - "@testing-library/jest-dom": "^5.10.1", - "@testing-library/react": "^11.2.5", - "@testing-library/user-event": "^13.1.8", - "@types/jest": "^26.0.7", - "@types/node": "^14.14.32", - "cross-fetch": "^3.0.6", - "msw": "^0.29.0" - }, - "files": [ - "dist" - ] -} diff --git a/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx b/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx deleted file mode 100644 index 22be84a4bf..0000000000 --- a/plugins/welcome/src/components/WelcomePage/WelcomePage.test.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { renderInTestApp } from '@backstage/test-utils'; -import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core'; -import React from 'react'; -import WelcomePage from './WelcomePage'; - -import { - ApiProvider, - ApiRegistry, - ConfigReader, -} from '@backstage/core-app-api'; -import { configApiRef, errorApiRef } from '@backstage/core-plugin-api'; - -describe('WelcomePage', () => { - it('should render', async () => { - const { baseElement } = await renderInTestApp( - - - - - , - ); - expect(baseElement).toBeInTheDocument(); - }); -}); diff --git a/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx b/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx deleted file mode 100644 index ce45b1b031..0000000000 --- a/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from 'react'; -import { Link as RouterLink } from 'react-router-dom'; -import { - Typography, - Grid, - List, - ListItem, - ListItemText, - Link, -} from '@material-ui/core'; - -import { - Content, - InfoCard, - Header, - HomepageTimer, - Page, - ContentHeader, - SupportButton, - WarningPanel, -} from '@backstage/core-components'; - -import { useApi, configApiRef } from '@backstage/core-plugin-api'; - -const WelcomePage = () => { - const appTitle = - useApi(configApiRef).getOptionalString('app.title') ?? 'Backstage'; - const profile = { givenName: '' }; - - return ( - -
- -
- - - - - - - - - We created Backstage about 4 years ago. While Spotify's - internal version of Backstage has had the benefit of time to - mature and evolve, the first iteration of our open source - version is still nascent. We are envisioning three phases of - the project and we have already begun work on various aspects - of these phases. The best way to keep track of the progress is - through the  - - Milestones - - . - - } - /> - - - - - You now have a running instance of Backstage!  - - ๐ŸŽ‰ - -  Let's make sure you get the most out of this platform by - walking you through the basics. - - - The Setup - - - Backstage is put together from three base concepts: the core, - the app and the plugins. - - - - - - - - - - - - - - Build Your Plugins - - - We suggest you either check out the documentation for{' '} - - creating a plugin - {' '} - or have a look in the code for the{' '} - - existing plugins - {' '} - in the directory{' '} - - plugins/ - - . - - - - - - - - backstage.io - - - - Create a plugin - - - - Plugin gallery - - - - - - -
- ); -}; - -export default WelcomePage; diff --git a/plugins/xcmetrics/CHANGELOG.md b/plugins/xcmetrics/CHANGELOG.md index ce8dae1168..a7d2d480b7 100644 --- a/plugins/xcmetrics/CHANGELOG.md +++ b/plugins/xcmetrics/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-xcmetrics +## 0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.7.0 + - @backstage/theme@0.2.11 + ## 0.2.8 ### Patch Changes diff --git a/plugins/xcmetrics/package.json b/plugins/xcmetrics/package.json index e6ef2c2631..c012c8e059 100644 --- a/plugins/xcmetrics/package.json +++ b/plugins/xcmetrics/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-xcmetrics", "description": "A Backstage plugin that shows XCode build metrics for your components", - "version": "0.2.8", + "version": "0.2.9", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", @@ -21,10 +21,10 @@ "clean": "backstage-cli clean" }, "dependencies": { - "@backstage/core-components": "^0.6.1", - "@backstage/core-plugin-api": "^0.1.10", - "@backstage/errors": "^0.1.1", - "@backstage/theme": "^0.2.10", + "@backstage/core-components": "^0.7.1", + "@backstage/core-plugin-api": "^0.1.11", + "@backstage/errors": "^0.1.3", + "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", @@ -36,10 +36,10 @@ "recharts": "^1.8.5" }, "devDependencies": { - "@backstage/cli": "^0.7.15", - "@backstage/core-app-api": "^0.1.16", - "@backstage/dev-utils": "^0.2.11", - "@backstage/test-utils": "^0.1.18", + "@backstage/cli": "^0.8.0", + "@backstage/core-app-api": "^0.1.18", + "@backstage/dev-utils": "^0.2.12", + "@backstage/test-utils": "^0.1.19", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^11.2.5", "@testing-library/user-event": "^13.1.8", diff --git a/scripts/api-extractor.ts b/scripts/api-extractor.ts index 3d74882b6c..c8f35508fa 100644 --- a/scripts/api-extractor.ts +++ b/scripts/api-extractor.ts @@ -134,6 +134,23 @@ async function findPackageDirs() { return packageDirs; } +function logApiReportInstructions() { + console.log(''); + console.log( + '*************************************************************************************', + ); + console.log( + '* You have uncommitted changes to the public API of a package. *', + ); + console.log( + '* To solve this, run `yarn build:api-reports` and commit all api-report.md changes. *', + ); + console.log( + '*************************************************************************************', + ); + console.log(''); +} + interface ApiExtractionOptions { packageDirs: string[]; outputDir: string; @@ -267,20 +284,7 @@ async function runApiExtraction({ if (!extractorResult.succeeded) { if (shouldLogInstructions) { - console.log(''); - console.log( - '*************************************************************************************', - ); - console.log( - '* You have uncommitted changes to the public API of a package. *', - ); - console.log( - '* To solve this, run `yarn build:api-reports` and commit all api-report.md changes. *', - ); - console.log( - '*************************************************************************************', - ); - console.log(''); + logApiReportInstructions(); if (conflictingFile) { console.log(''); @@ -294,7 +298,8 @@ async function runApiExtraction({ const content = await fs.readFile(conflictingFile, 'utf8'); console.log(content); - console.log(''); + + logApiReportInstructions(); } } diff --git a/yarn.lock b/yarn.lock index c0329e7a4e..c905fbea6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -375,7 +375,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.4.4", "@babel/core@^7.7.5": +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.16", "@babel/core@^7.7.5": version "7.14.8" resolved "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz#20cdf7c84b5d86d83fac8710a8bc605a7ba3f010" integrity sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q== @@ -414,7 +414,7 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13": +"@babel/helper-annotate-as-pure@^7.12.13": version "7.12.13" resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab" integrity sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw== @@ -1536,7 +1536,7 @@ "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.14.0", "@babel/plugin-transform-modules-commonjs@^7.14.5", "@babel/plugin-transform-modules-commonjs@^7.4.4": +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.13.8", "@babel/plugin-transform-modules-commonjs@^7.14.0", "@babel/plugin-transform-modules-commonjs@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz#7aaee0ea98283de94da98b28f8c35701429dad97" integrity sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A== @@ -1663,7 +1663,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.13.0" -"@babel/plugin-transform-react-display-name@^7.0.0", "@babel/plugin-transform-react-display-name@^7.12.13": +"@babel/plugin-transform-react-display-name@^7.0.0": version "7.14.2" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.14.2.tgz#2e854544d42ab3bb9c21f84e153d62e800fbd593" integrity sha512-zCubvP+jjahpnFJvPaHPiGVfuVUjXHhFvJKQdNnsmSsiU9kR/rCZ41jHc++tERD2zV+p7Hr6is+t5b6iWTCqSw== @@ -1677,13 +1677,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-react-jsx-development@^7.12.17": - version "7.12.17" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.17.tgz#f510c0fa7cd7234153539f9a362ced41a5ca1447" - integrity sha512-BPjYV86SVuOaudFhsJR1zjgxxOhJDt6JHNoD48DxWEIxUCAMjV1ys6DYw4SDYZh0b1QsS2vfIA9t/ZsQGsDOUQ== - dependencies: - "@babel/plugin-transform-react-jsx" "^7.12.17" - "@babel/plugin-transform-react-jsx-development@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.14.5.tgz#1a6c73e2f7ed2c42eebc3d2ad60b0c7494fcb9af" @@ -1691,7 +1684,7 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.14.5" -"@babel/plugin-transform-react-jsx@^7.0.0", "@babel/plugin-transform-react-jsx@^7.12.17", "@babel/plugin-transform-react-jsx@^7.13.12": +"@babel/plugin-transform-react-jsx@^7.0.0": version "7.14.3" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.3.tgz#0e26597805cf0862da735f264550933c38babb66" integrity sha512-uuxuoUNVhdgYzERiHHFkE4dWoJx+UFVyuAl0aqN8P2/AKFHwqgUC5w2+4/PjpKXJsFgBlYAFXlUmDQ3k3DUkXw== @@ -1713,14 +1706,6 @@ "@babel/plugin-syntax-jsx" "^7.14.5" "@babel/types" "^7.14.9" -"@babel/plugin-transform-react-pure-annotations@^7.12.1": - version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" - integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-transform-react-pure-annotations@^7.14.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.14.5.tgz#18de612b84021e3a9802cbc212c9d9f46d0d11fc" @@ -2046,7 +2031,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.10": +"@babel/preset-react@^7.12.10", "@babel/preset-react@^7.12.5": version "7.14.5" resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.14.5.tgz#0fbb769513f899c2c56f3a882fa79673c2d4ab3c" integrity sha512-XFxBkjyObLvBaAvkx1Ie95Iaq4S/GUEIrejyrntQ/VCMKUYvKLoyKxOBzJ2kjA3b6rC9/KL6KXfDC2GqvLiNqQ== @@ -2058,18 +2043,6 @@ "@babel/plugin-transform-react-jsx-development" "^7.14.5" "@babel/plugin-transform-react-pure-annotations" "^7.14.5" -"@babel/preset-react@^7.12.5": - version "7.13.13" - resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.13.13.tgz#fa6895a96c50763fe693f9148568458d5a839761" - integrity sha512-gx+tDLIE06sRjKJkVtpZ/t3mzCDOnPG+ggHZG9lffUbX8+wC739x20YQc9V35Do6ZAxaUc/HhVHIiOzz5MvDmA== - dependencies: - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/helper-validator-option" "^7.12.17" - "@babel/plugin-transform-react-display-name" "^7.12.13" - "@babel/plugin-transform-react-jsx" "^7.13.12" - "@babel/plugin-transform-react-jsx-development" "^7.12.17" - "@babel/plugin-transform-react-pure-annotations" "^7.12.1" - "@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.13.0": version "7.14.5" resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.14.5.tgz#aa98de119cf9852b79511f19e7f44a2d379bcce0" @@ -2098,14 +2071,7 @@ core-js-pure "^3.16.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.14.8" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz#7119a56f421018852694290b9f9148097391b446" - integrity sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.0", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.0", "@babel/runtime@^7.14.8", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.15.4" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== @@ -2362,6 +2328,49 @@ remark-gfm "^1.0.0" zen-observable "^0.8.15" +"@backstage/core-components@^0.6.1": + version "0.6.1" + resolved "https://registry.npmjs.org/@backstage/core-components/-/core-components-0.6.1.tgz#65cfc704828f76c48ad5115404779206bb6fe1bb" + integrity sha512-gQRRcYEv98BFLpVW5nu2MhuzgjoMVEhPMyUSRc9NYa58GA1D8Q7zV7xYdbfCanMOlKDmi+rQ3Cp2u6C60+uhNg== + dependencies: + "@backstage/config" "^0.1.10" + "@backstage/core-plugin-api" "^0.1.10" + "@backstage/errors" "^0.1.2" + "@backstage/theme" "^0.2.10" + "@material-table/core" "^3.1.0" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + "@types/dagre" "^0.7.44" + "@types/react" "*" + "@types/react-sparklines" "^1.7.0" + "@types/react-text-truncate" "^0.14.0" + classnames "^2.2.6" + clsx "^1.1.0" + d3-selection "^2.0.0" + d3-shape "^2.0.0" + d3-zoom "^2.0.0" + dagre "^0.8.5" + immer "^9.0.1" + lodash "^4.17.21" + pluralize "^8.0.0" + prop-types "^15.7.2" + qs "^6.9.4" + rc-progress "^3.0.0" + react "^16.12.0" + react-dom "^16.12.0" + react-helmet "6.1.0" + react-hook-form "^7.12.2" + react-markdown "^5.0.2" + react-router "6.0.0-beta.0" + react-router-dom "6.0.0-beta.0" + react-sparklines "^1.7.0" + react-syntax-highlighter "^15.4.3" + react-text-truncate "^0.16.0" + react-use "^17.2.4" + remark-gfm "^1.0.0" + zen-observable "^0.8.15" + "@backstage/core@*": version "0.7.14" resolved "https://registry.npmjs.org/@backstage/core/-/core-0.7.14.tgz#863844fe40bb6a29bcc2d297e42055633b0e886f" @@ -2432,6 +2441,29 @@ react-router-dom "6.0.0-beta.0" react-use "^17.2.4" +"@backstage/plugin-catalog-react@^0.5.0": + version "0.5.2" + resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-0.5.2.tgz#7d1af3b0aa2397e4c62847fe78b8fe5afd90ee07" + integrity sha512-eoVGSrFyPWgMNZY9rMwEm0QS7B+FRLR2L+nRUlFjK4YnGQCYMXMZroJqSMRdBqBKlPiMgZO2AzZiFROcpSPwmA== + dependencies: + "@backstage/catalog-client" "^0.5.0" + "@backstage/catalog-model" "^0.9.4" + "@backstage/core-app-api" "^0.1.16" + "@backstage/core-components" "^0.6.1" + "@backstage/core-plugin-api" "^0.1.10" + "@backstage/integration" "^0.6.7" + "@backstage/version-bridge" "^0.1.0" + "@material-ui/core" "^4.12.2" + "@material-ui/icons" "^4.9.1" + "@material-ui/lab" "4.0.0-alpha.57" + "@types/react" "*" + jwt-decode "^3.1.0" + lodash "^4.17.21" + qs "^6.9.4" + react "^16.13.1" + react-router "6.0.0-beta.0" + react-use "^17.2.4" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -2442,16 +2474,16 @@ resolved "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-5.0.2.tgz#b23080fa35520e993a8a37a0f5bca26aa4650a48" integrity sha512-NBEJlHWrhQucLhZGHtSxM2loSaNUMajC7KOYJLyfcdW/6goVoff2HoYI3bz8YCDN0wKGbxtUL0gx2dvHpvnWlw== -"@changesets/apply-release-plan@^5.0.0": - version "5.0.0" - resolved "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-5.0.0.tgz#11bf168acecbf4cfa2b0e6425160bac5ceeec1c3" - integrity sha512-SE+5nPNSKUyUociPnAvnjYSVF+diciEhX9ZHSqKWMlydswCDjiaq9gz67qwWCmwgEgEOz0TS7VrQBoOlzbitvA== +"@changesets/apply-release-plan@^5.0.1": + version "5.0.1" + resolved "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-5.0.1.tgz#ed3e30550f787ef1b72f0a51e29a54d244123109" + integrity sha512-ltYLM/PPoL1Un9hnNCbUac25FWonJvIZ/9C3O4UyZ/k4rir9FGvH6KLtMOiPEAJWnXmaHeRDr06MzohuXOnmvw== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/config" "^1.6.0" + "@changesets/config" "^1.6.1" "@changesets/get-version-range-type" "^0.3.2" - "@changesets/git" "^1.1.1" - "@changesets/types" "^4.0.0" + "@changesets/git" "^1.1.2" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" detect-indent "^6.0.0" fs-extra "^7.0.1" @@ -2461,36 +2493,36 @@ resolve-from "^5.0.0" semver "^5.4.1" -"@changesets/assemble-release-plan@^5.0.0": - version "5.0.0" - resolved "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.0.0.tgz#3e57405e5c375e2d933f62e74d1874915e60cd61" - integrity sha512-LElDXTCBUkPSmdXlCisoUWw2paX48snatBmw/hKnGiSvnyZqdTIylLojAGQWG0/vOO9v3s/DvJ4hdagIquxJjg== +"@changesets/assemble-release-plan@^5.0.1": + version "5.0.1" + resolved "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.0.1.tgz#80e9b750705677eb2d6356c581ed9c2e97fd68e7" + integrity sha512-KQqafvScTFQ/4Q2LpLmDYhU47LWvIGcgVS8tzKU8fBvRdKuLGQXe42VYbwVM0cHIkFd/b6YFn+H2QMdKC2MjIQ== dependencies: "@babel/runtime" "^7.10.4" "@changesets/errors" "^0.1.4" - "@changesets/get-dependents-graph" "^1.2.1" - "@changesets/types" "^4.0.0" + "@changesets/get-dependents-graph" "^1.2.2" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" semver "^5.4.1" "@changesets/cli@^2.14.0": - version "2.16.0" - resolved "https://registry.npmjs.org/@changesets/cli/-/cli-2.16.0.tgz#9f794005d0503efba5e348b929821a1732fd0f0d" - integrity sha512-VFkXSyyk/WRjjUoBI7g7cDy09qBjPbBQOloPMEshTzMo/NY9muWHl2yB/FSSkV/6PxGimPtJ7aEJPYfk8HCfXw== + version "2.17.0" + resolved "https://registry.npmjs.org/@changesets/cli/-/cli-2.17.0.tgz#cc7ff4f64d029ddd6d87020a012c8cf8c7adde58" + integrity sha512-UyraYwYst1lTjef+8i80XQ6SqsLaGwi4Sgn9YuDf2xdHA9m+5qQXshHvHVjaTdPTA09rqMBk9yeO7vmAqF4+vQ== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/apply-release-plan" "^5.0.0" - "@changesets/assemble-release-plan" "^5.0.0" - "@changesets/config" "^1.6.0" + "@changesets/apply-release-plan" "^5.0.1" + "@changesets/assemble-release-plan" "^5.0.1" + "@changesets/config" "^1.6.1" "@changesets/errors" "^0.1.4" - "@changesets/get-dependents-graph" "^1.2.1" - "@changesets/get-release-plan" "^3.0.0" - "@changesets/git" "^1.1.1" + "@changesets/get-dependents-graph" "^1.2.2" + "@changesets/get-release-plan" "^3.0.1" + "@changesets/git" "^1.1.2" "@changesets/logger" "^0.0.5" - "@changesets/pre" "^1.0.6" - "@changesets/read" "^0.4.7" - "@changesets/types" "^4.0.0" - "@changesets/write" "^0.1.4" + "@changesets/pre" "^1.0.7" + "@changesets/read" "^0.5.0" + "@changesets/types" "^4.0.1" + "@changesets/write" "^0.1.5" "@manypkg/get-packages" "^1.0.1" "@types/semver" "^6.0.0" boxen "^1.3.0" @@ -2509,15 +2541,15 @@ term-size "^2.1.0" tty-table "^2.8.10" -"@changesets/config@^1.6.0": - version "1.6.0" - resolved "https://registry.npmjs.org/@changesets/config/-/config-1.6.0.tgz#2cd9426b9d4212534d2b31c51de43280b76d3df4" - integrity sha512-vMY/OpMFSDC2crDKb5Nq2kMX9hozcXL4dY5Rr+a1JQ044Rz+jqjJPpdTP2yQ+j7qmeGcUTvwjJoEMeekYwfqhg== +"@changesets/config@^1.6.1": + version "1.6.1" + resolved "https://registry.npmjs.org/@changesets/config/-/config-1.6.1.tgz#e9b1636fd56a74411c493c924e6ffa07d7d26091" + integrity sha512-aQTo6ODvhsvnSFszMP1YbJyAi1DtE1Pes9rL+G+KYJiAOA6k5RzbiKOarjo+ZkKXpX0G3CBAbOO8jXOX4xG7cQ== dependencies: "@changesets/errors" "^0.1.4" - "@changesets/get-dependents-graph" "^1.2.1" + "@changesets/get-dependents-graph" "^1.2.2" "@changesets/logger" "^0.0.5" - "@changesets/types" "^4.0.0" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" fs-extra "^7.0.1" micromatch "^4.0.2" @@ -2529,28 +2561,28 @@ dependencies: extendable-error "^0.1.5" -"@changesets/get-dependents-graph@^1.2.1": - version "1.2.1" - resolved "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.2.1.tgz#462908693dc3a354622e43f85a764b74b5bb53af" - integrity sha512-vJOibo9SkqhVbgfq5AHIlQ7tzkYQIXh3tPAnlNLy2bPZsU+SByd74GaxHYWt1zOBlncU25WKrIM6J7XBB+GVUg== +"@changesets/get-dependents-graph@^1.2.2": + version "1.2.2" + resolved "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.2.2.tgz#7a2238f3d1a023de83d37b727a0da15826e88d73" + integrity sha512-3zJRw6TcexmOrmIZNOXpIRsZtqtrdmlzbqp4+V0VgnBvTxz16rqCS9VBsBqFYeJDWFj3soOlHUMeTwLghr18DA== dependencies: - "@changesets/types" "^4.0.0" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" chalk "^2.1.0" fs-extra "^7.0.1" semver "^5.4.1" -"@changesets/get-release-plan@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.0.tgz#55efc01db2e24bd7a88e703956eb2f6c4a79054f" - integrity sha512-7VLiqpcWZyjwIXYgkubBC/9cdwqUJEhLMRT9/Y9+ctHqrpsXmJg15QQPTOh3HT9yGN5fJPL1WwuZkc1HXUhK0g== +"@changesets/get-release-plan@^3.0.1": + version "3.0.1" + resolved "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.1.tgz#c98a34321eac9e4187098893ff8dadb6f90ad89c" + integrity sha512-HTZeEPvLlcWMWKxLrzQNLQWKDDN1lUKvaOV+hl/yBhgtyJECljJJzd3IRaKqCSWMrYKNaaEcmunTtZ4oaeoK9w== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/assemble-release-plan" "^5.0.0" - "@changesets/config" "^1.6.0" - "@changesets/pre" "^1.0.6" - "@changesets/read" "^0.4.7" - "@changesets/types" "^4.0.0" + "@changesets/assemble-release-plan" "^5.0.1" + "@changesets/config" "^1.6.1" + "@changesets/pre" "^1.0.7" + "@changesets/read" "^0.5.0" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" "@changesets/get-version-range-type@^0.3.2": @@ -2558,14 +2590,14 @@ resolved "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.3.2.tgz#8131a99035edd11aa7a44c341cbb05e668618c67" integrity sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg== -"@changesets/git@^1.1.1": - version "1.1.1" - resolved "https://registry.npmjs.org/@changesets/git/-/git-1.1.1.tgz#f444d3ff3604acb6949560656c9ef330485a5fa3" - integrity sha512-Z12TcKwgU33YE3r76cyU+X81RchOXljDZ5s3G2u0Zd+ODyrwlDb91IO55+6R0Ha6ouPz8ioont0gA70c1RFngg== +"@changesets/git@^1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@changesets/git/-/git-1.1.2.tgz#248d4418bcb2d4f198852409cfcbd06a1fcb0424" + integrity sha512-dfza8elsIwcYVa4fFzLaPs4+AkoCFiW3sfzkkC7WR+rG9j+zZh7CelzVpnoiAbEI2QOzeCbZKMoLSvBPgHhB1g== dependencies: "@babel/runtime" "^7.10.4" "@changesets/errors" "^0.1.4" - "@changesets/types" "^4.0.0" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" is-subdir "^1.1.1" spawndamnit "^2.0.0" @@ -2577,51 +2609,51 @@ dependencies: chalk "^2.1.0" -"@changesets/parse@^0.3.8": - version "0.3.8" - resolved "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.8.tgz#0bb244eccb35cb301168f85684bb03389c59341d" - integrity sha512-0S7Dc7XbMOKamBtd48vVuWL2aFZyaglw6lJsXNddn9forFf8oMKMmdyJ/HQPyeEChDDOhDF1/ya7m/zpt4Dk4w== +"@changesets/parse@^0.3.9": + version "0.3.9" + resolved "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.9.tgz#c518792b05f15ab418d58dc1cea81601556e845e" + integrity sha512-XoTEkMpvRRVxSlhvOaK4YSFM+RZhYFTksxRh7ieNkb6pMxkpq8MOYSi/07BuqkODn4dJEMOoSy3RzL99P6FyqA== dependencies: - "@changesets/types" "^4.0.0" + "@changesets/types" "^4.0.1" js-yaml "^3.13.1" -"@changesets/pre@^1.0.6": - version "1.0.6" - resolved "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.6.tgz#45700cf18274b35b2296000befe7fe4df8ff046f" - integrity sha512-ZwFFQLjhTmA4hj8+Cf9pm6nD9Tp+AiBz1wJLaGum4Ae1fPXMwDnJfHknFUTytqZBlC0gHkiGSj6QkUuetWvckg== +"@changesets/pre@^1.0.7": + version "1.0.7" + resolved "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.7.tgz#caf6430c90b8ac6d58c9cd90a19558ab06b19b88" + integrity sha512-oUU6EL4z0AIyCv/EscQFxxJsQfc9/AcSpqAGbdZrLXwshUWTXsJHMWlE3/+iSIyQ+I+/xtxbBxnqDUpUU3TOOg== dependencies: "@babel/runtime" "^7.10.4" "@changesets/errors" "^0.1.4" - "@changesets/types" "^4.0.0" + "@changesets/types" "^4.0.1" "@manypkg/get-packages" "^1.0.1" fs-extra "^7.0.1" -"@changesets/read@^0.4.7": - version "0.4.7" - resolved "https://registry.npmjs.org/@changesets/read/-/read-0.4.7.tgz#5a32ae7092330fba31eaec4c83321bb936605766" - integrity sha512-E70QrYQpSCMF0nC0dlPU7i6A9zht+8zkQczrKMbOUwDVrfidcvgojxfuJSQbzptYSb9OKYh8GOLd+bsq9+uO9Q== +"@changesets/read@^0.5.0": + version "0.5.0" + resolved "https://registry.npmjs.org/@changesets/read/-/read-0.5.0.tgz#52f7a10f6baebf97172e62035ee8345652c5a1c0" + integrity sha512-A2OJ+vgfvbUaLx2yKyHH+tapa+DUd2NtpFpVuxjUqv0zirjqju20z1bziqaqpIQSf/rXPuoc09vp5w4VakraHg== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/git" "^1.1.1" + "@changesets/git" "^1.1.2" "@changesets/logger" "^0.0.5" - "@changesets/parse" "^0.3.8" - "@changesets/types" "^4.0.0" + "@changesets/parse" "^0.3.9" + "@changesets/types" "^4.0.1" chalk "^2.1.0" fs-extra "^7.0.1" p-filter "^2.1.0" -"@changesets/types@^4.0.0": - version "4.0.0" - resolved "https://registry.npmjs.org/@changesets/types/-/types-4.0.0.tgz#635f804546b0a96ecc0ca3f26403a6782a3dc938" - integrity sha512-whLmPx2wgJRoOtxVZop+DJ71z1gTSkij7osiHgN+pe//FiE6bb4ffvBBb0rACs2cUPfAkWxgSPzqkECgKS1jvQ== +"@changesets/types@^4.0.1": + version "4.0.1" + resolved "https://registry.npmjs.org/@changesets/types/-/types-4.0.1.tgz#85cf3cc32baff0691112d9d15fc21fbe022c9f0a" + integrity sha512-zVfv752D8K2tjyFmxU/vnntQ+dPu+9NupOSguA/2Zuym4tVxRh0ylArgKZ1bOAi2eXfGlZMxJU/kj7uCSI15RQ== -"@changesets/write@^0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@changesets/write/-/write-0.1.4.tgz#5828ecc70c48d0e8696c5f13fe06b730cdfde6f2" - integrity sha512-uco+vS3mo2JqflLciIU707har+6AEFOeP8pgu3vVC1M2WcKukQgR1KylHFqZJxKQWahf8mQnuUSbgR4yJQuhmA== +"@changesets/write@^0.1.5": + version "0.1.5" + resolved "https://registry.npmjs.org/@changesets/write/-/write-0.1.5.tgz#97574d95c8e48c3bbb1173802672f9a64d1b7fef" + integrity sha512-AYVSCH7on/Cyzo/8lVfqlsXmyKl3JhbNu9yHApdLPhHAzv5wqoHiZlMDkmd+AA67SRqzK2lDs4BcIojK+uWeIA== dependencies: "@babel/runtime" "^7.10.4" - "@changesets/types" "^4.0.0" + "@changesets/types" "^4.0.1" fs-extra "^7.0.1" human-id "^1.0.2" prettier "^1.19.1" @@ -2723,6 +2755,11 @@ dependencies: "@date-io/core" "^2.10.11" +"@discoveryjs/json-ext@^0.5.3": + version "0.5.5" + resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz#9283c9ce5b289a3c4f61c12757469e59377f81f3" + integrity sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA== + "@elastic/elasticsearch-mock@^0.3.0": version "0.3.0" resolved "https://registry.npmjs.org/@elastic/elasticsearch-mock/-/elasticsearch-mock-0.3.0.tgz#6b1d8448aad3ca20f760fa01c0206b733c9c1e54" @@ -2934,6 +2971,16 @@ dependencies: google-gax "^2.12.0" +"@google-cloud/firestore@^4.15.1": + version "4.15.1" + resolved "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-4.15.1.tgz#ed764fc76823ce120e68fe8c27ef1edd0650cd93" + integrity sha512-2PWsCkEF1W02QbghSeRsNdYKN1qavrHBP3m72gPDMHQSYrGULOaTi7fSJquQmAtc4iPVB2/x6h80rdLHTATQtA== + dependencies: + fast-deep-equal "^3.1.1" + functional-red-black-tree "^1.0.1" + google-gax "^2.24.1" + protobufjs "^6.8.6" + "@google-cloud/paginator@^3.0.0": version "3.0.5" resolved "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.5.tgz#9d6b96c421a89bd560c1bc2c197c7611ef21db6c" @@ -5028,19 +5075,19 @@ resolved "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-2.0.0.tgz#1108b9ea661ca6c81e4a8bfa63a09eb27d5bc2db" integrity sha512-35cfQ4YWlnZnmZKmIxlGPUPLtbkF8lr/A/1Sk1eC0ddLMwQN06dOuLc+dI3YLQS+T+MoNt3DIQ0NynwgKPilig== -"@octokit/webhooks-types@4.7.0": - version "4.7.0" - resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-4.7.0.tgz#0d86cb32a6502da41d2a33b243102f96012bddbb" - integrity sha512-LWTPedtJtcdA1+k+iERtCr7UnO/d+Cr00/vRPhjASTHz2G/ZtSAnDNjDv5c7X2R7OJsPE6eFUMT7frwjjuAbZA== +"@octokit/webhooks-types@4.12.0": + version "4.12.0" + resolved "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-4.12.0.tgz#add8b98d60ab42e965c4ba31040097f810e222de" + integrity sha512-G0k7CoS9bK+OI7kPHgqi1KqK4WhrjDQSjy0wJI+0OTx/xvbHUIZDeqatY60ceeRINP/1ExEk6kTARboP0xavEw== "@octokit/webhooks@^9.14.1": - version "9.15.0" - resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.15.0.tgz#ed43660c1911755747b5c1b2847081eb96d8e0a0" - integrity sha512-IFHXmTT4rVz8TbH5oH8qmJkM9UJLo75mmaMydKdn0j/ffLuTQ/+j6+Jl5dyboUo6AtUwaklFacszViVCKHME6A== + version "9.17.0" + resolved "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-9.17.0.tgz#81140b2e127157aa9817d085cd8758545e4a72e4" + integrity sha512-/+9WSLuDuoqNWnMY4w6ePioILBqsUOiUt0ygQzugYzd112WB+yPIjmUQjAbNXImDsAa1myLpBICAMQDZlULyAA== dependencies: "@octokit/request-error" "^2.0.2" "@octokit/webhooks-methods" "^2.0.0" - "@octokit/webhooks-types" "4.7.0" + "@octokit/webhooks-types" "4.12.0" aggregate-error "^3.1.0" "@open-draft/until@^1.0.3": @@ -5546,7 +5593,22 @@ react-syntax-highlighter "^13.5.3" regenerator-runtime "^0.13.7" -"@storybook/addons@6.3.7", "@storybook/addons@^6.1.11": +"@storybook/addons@6.3.11", "@storybook/addons@^6.1.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.3.11.tgz#4b5e88793bcce7ef823340e9010a96e35e3284cc" + integrity sha512-2Y03lOwzWDRB/glISa/4luBMM5uyYhkIBixbZF9miIb2SCWRlNmom5NCnKsR18Wu6g7zI7os3aAMfKr24aSofQ== + dependencies: + "@storybook/api" "6.3.11" + "@storybook/channels" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/core-events" "6.3.11" + "@storybook/router" "6.3.11" + "@storybook/theming" "6.3.11" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + +"@storybook/addons@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/addons/-/addons-6.3.7.tgz#7c6b8d11b65f67b1884f6140437fe996dc39537a" integrity sha512-9stVjTcc52bqqh7YQex/LpSjJ4e2Czm4/ZYDjIiNy0p4OZEx+yLhL5mZzMWh2NQd6vv+pHASBSxf2IeaR5511A== @@ -5561,6 +5623,32 @@ global "^4.4.0" regenerator-runtime "^0.13.7" +"@storybook/api@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/api/-/api-6.3.11.tgz#ea3806a0570da65bfb5b39e4edb90289b5ba701e" + integrity sha512-QmgXM613zy/DPrJLVRJnALT5Rh4VWgvxrHbdLxRWGDrMHNYlm3N1KA+a6ZtIM5Zl94B3y5o0SPCSleSbnA3viA== + dependencies: + "@reach/router" "^1.3.4" + "@storybook/channels" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/core-events" "6.3.11" + "@storybook/csf" "0.0.1" + "@storybook/router" "6.3.11" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.3.11" + "@types/reach__router" "^1.3.7" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.20" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + telejson "^5.3.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/api@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/api/-/api-6.3.7.tgz#88b8a51422cd0739c91bde0b1d65fb6d8a8485d0" @@ -5587,10 +5675,10 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/builder-webpack4@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.3.7.tgz#1cc1a1184043be3f6ef840d0b43ba91a803105e2" - integrity sha512-M5envblMzAUrNqP1+ouKiL8iSIW/90+kBRU2QeWlZoZl1ib+fiFoKk06cgbaC70Bx1lU8nOnI/VBvB5pLhXLaw== +"@storybook/builder-webpack4@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.3.11.tgz#b1b62a41b2fbd951733e86aaa4730dc2541b4221" + integrity sha512-FkLfbe8GneSALj9Dgh0i+mZR8EVoM5T96HDM0DxhNbWzO3lDrcKxFdlRjYRohZaJn3gYUU09IU9xrfFKgYoYew== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -5613,20 +5701,20 @@ "@babel/preset-env" "^7.12.11" "@babel/preset-react" "^7.12.10" "@babel/preset-typescript" "^7.12.7" - "@storybook/addons" "6.3.7" - "@storybook/api" "6.3.7" - "@storybook/channel-postmessage" "6.3.7" - "@storybook/channels" "6.3.7" - "@storybook/client-api" "6.3.7" - "@storybook/client-logger" "6.3.7" - "@storybook/components" "6.3.7" - "@storybook/core-common" "6.3.7" - "@storybook/core-events" "6.3.7" - "@storybook/node-logger" "6.3.7" - "@storybook/router" "6.3.7" + "@storybook/addons" "6.3.11" + "@storybook/api" "6.3.11" + "@storybook/channel-postmessage" "6.3.11" + "@storybook/channels" "6.3.11" + "@storybook/client-api" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/components" "6.3.11" + "@storybook/core-common" "6.3.11" + "@storybook/core-events" "6.3.11" + "@storybook/node-logger" "6.3.11" + "@storybook/router" "6.3.11" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.3.7" - "@storybook/ui" "6.3.7" + "@storybook/theming" "6.3.11" + "@storybook/ui" "6.3.11" "@types/node" "^14.0.10" "@types/webpack" "^4.41.26" autoprefixer "^9.8.6" @@ -5663,6 +5751,19 @@ webpack-hot-middleware "^2.25.0" webpack-virtual-modules "^0.2.2" +"@storybook/channel-postmessage@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.3.11.tgz#b03748affc8775ce241ded0eabd50d17bb065117" + integrity sha512-cXmDqs91CLrqPugLLVdmE6iPH0eWJ0LsO3uoYXGDIAkv+C1HJBn5VdO1/gBm/B+lpkZ++DYiZ0tRUOMKsuw8IQ== + dependencies: + "@storybook/channels" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/core-events" "6.3.11" + core-js "^3.8.2" + global "^4.4.0" + qs "^6.10.0" + telejson "^5.3.2" + "@storybook/channel-postmessage@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.3.7.tgz#bd4edf84a29aa2cd4a22d26115c60194d289a840" @@ -5676,6 +5777,15 @@ qs "^6.10.0" telejson "^5.3.2" +"@storybook/channels@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.3.11.tgz#a14ce233367a9072bd1cffef3825f125c27bb0ae" + integrity sha512-slY3B1zRJaABrkFj2r89O0D6axQjeh6oyuJFrRZ7SoTK26ODi839LD+LwSpk40c4FoQAgT3pcJmjiFyUbBdtRg== + dependencies: + core-js "^3.8.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/channels@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/channels/-/channels-6.3.7.tgz#85ed5925522b802d959810f78d37aacde7fea66e" @@ -5685,6 +5795,30 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/client-api@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.3.11.tgz#3e6548bf6e83a2958db701cf59740a2519eea771" + integrity sha512-YUiVZzQYaGqYCTp1Jcf7zviJSWq3no93wT8uCj2HLW7n56fa5Iwx1O29dY2lhBEGmJ3JjTPNeSrSrzoHb1AZRg== + dependencies: + "@storybook/addons" "6.3.11" + "@storybook/channel-postmessage" "6.3.11" + "@storybook/channels" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/core-events" "6.3.11" + "@storybook/csf" "0.0.1" + "@types/qs" "^6.9.5" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + global "^4.4.0" + lodash "^4.17.20" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + stable "^0.1.8" + store2 "^2.12.0" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/client-api@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.3.7.tgz#cb1dca05467d777bd09aadbbdd1dd22ca537ce14" @@ -5709,6 +5843,14 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" +"@storybook/client-logger@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.3.11.tgz#d2e0e17f35ed4c5ee282d818b6db3a015ce6b833" + integrity sha512-U06IuAGZFOJYgtXH02dbNe5lHLcwsSo6JBdFLjcUP3C0WqtskoUGLA2XLUCYasl7OMB0mcLHy4GaZL4wtrW6+Q== + dependencies: + core-js "^3.8.2" + global "^4.4.0" + "@storybook/client-logger@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.3.7.tgz#ff17b7494e7e9e23089b0d5c5364c371c726bdd1" @@ -5717,6 +5859,36 @@ core-js "^3.8.2" global "^4.4.0" +"@storybook/components@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/components/-/components-6.3.11.tgz#a7d015fc9808d0200d033d8f694db79277770030" + integrity sha512-/iajr+kMXQLgXa6hr/nupcHFzdppZ4S/vdDgoyXW/L1jDeKzy5Bxzf4JjjoR/tY6jgiFRja1C1mUGFqceyb9ow== + dependencies: + "@popperjs/core" "^2.6.0" + "@storybook/client-logger" "6.3.11" + "@storybook/csf" "0.0.1" + "@storybook/theming" "6.3.11" + "@types/color-convert" "^2.0.0" + "@types/overlayscrollbars" "^1.12.0" + "@types/react-syntax-highlighter" "11.0.5" + color-convert "^2.0.1" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.20" + markdown-to-jsx "^7.1.3" + memoizerific "^1.11.3" + overlayscrollbars "^1.13.1" + polished "^4.0.5" + prop-types "^15.7.2" + react-colorful "^5.1.2" + react-popper-tooltip "^3.1.1" + react-syntax-highlighter "^13.5.3" + react-textarea-autosize "^8.3.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + "@storybook/components@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/components/-/components-6.3.7.tgz#42b1ca6d24e388e02eab82aa9ed3365db2266ecc" @@ -5747,18 +5919,18 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/core-client@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.3.7.tgz#cfb75952e0e1d32f2aca92bca2786334ab589c40" - integrity sha512-M/4A65yV+Y4lsCQXX4BtQO/i3BcMPrU5FkDG8qJd3dkcx2fUlFvGWqQPkcTZE+MPVvMEGl/AsEZSADzah9+dAg== +"@storybook/core-client@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.3.11.tgz#beede8dfb0b0d86945f0b15ef574c6ed8af37576" + integrity sha512-GSVxt6ZnZPboZ0nRJ0b4+r8yL43l0uImgg6tsCwctxj/qvx4O9thh3zVfgu1i6BqG9auJoNby2dTZDaGkPLaIg== dependencies: - "@storybook/addons" "6.3.7" - "@storybook/channel-postmessage" "6.3.7" - "@storybook/client-api" "6.3.7" - "@storybook/client-logger" "6.3.7" - "@storybook/core-events" "6.3.7" + "@storybook/addons" "6.3.11" + "@storybook/channel-postmessage" "6.3.11" + "@storybook/client-api" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/core-events" "6.3.11" "@storybook/csf" "0.0.1" - "@storybook/ui" "6.3.7" + "@storybook/ui" "6.3.11" airbnb-js-shims "^2.2.1" ansi-to-html "^0.6.11" core-js "^3.8.2" @@ -5770,10 +5942,10 @@ unfetch "^4.2.0" util-deprecate "^1.0.2" -"@storybook/core-common@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.3.7.tgz#9eedf3ff16aff870950e3372ab71ef846fa3ac52" - integrity sha512-exLoqRPPsAefwyjbsQBLNFrlPCcv69Q/pclqmIm7FqAPR7f3CKP1rqsHY0PnemizTL/+cLX5S7mY90gI6wpNug== +"@storybook/core-common@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.3.11.tgz#e21cd087435c4f17d099ea3a27d34300d5f201db" + integrity sha512-PR/TndBaItPjItoOMEYCE4rPZGF7dfuqh+SbL0pmk6yLqO5MTSPEVpLEutbKh3uYlt1mgb8cXLuTQ3ybkG5O+Q== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -5796,7 +5968,7 @@ "@babel/preset-react" "^7.12.10" "@babel/preset-typescript" "^7.12.7" "@babel/register" "^7.12.1" - "@storybook/node-logger" "6.3.7" + "@storybook/node-logger" "6.3.11" "@storybook/semver" "^7.3.2" "@types/glob-base" "^0.3.0" "@types/micromatch" "^4.0.1" @@ -5824,6 +5996,13 @@ util-deprecate "^1.0.2" webpack "4" +"@storybook/core-events@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.3.11.tgz#76c1701c9cb3f50d6a1fe2344d396df2dd76f8a3" + integrity sha512-wuWZsw2VB2qSuac+40SaeaZ40/4sQhYSnLSN+l944G1kkjZwZcVc1nBTaYBt9H7uH+INkmGblDbGNnme71KCjg== + dependencies: + core-js "^3.8.2" + "@storybook/core-events@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.3.7.tgz#c5bc7cae7dc295de73b6b9f671ecbe582582e9bd" @@ -5831,17 +6010,18 @@ dependencies: core-js "^3.8.2" -"@storybook/core-server@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.3.7.tgz#6f29ad720aafe4a97247b5e306eac4174d0931f2" - integrity sha512-m5OPD/rmZA7KFewkXzXD46/i1ngUoFO4LWOiAY/wR6RQGjYXGMhSa5UYFF6MNwSbiGS5YieHkR5crB1HP47AhQ== +"@storybook/core-server@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.3.11.tgz#e6cfdab8de72254007de50473186734c26bbcbc7" + integrity sha512-pQiLtvoa4PkQ0I/i/nA+GSa7XsJeu83BQHirNba8kI+bsRLFWAY6BPM3nIs3n7fa3OlkAVxnYRgmZJXodGFIng== dependencies: - "@storybook/builder-webpack4" "6.3.7" - "@storybook/core-client" "6.3.7" - "@storybook/core-common" "6.3.7" - "@storybook/csf-tools" "6.3.7" - "@storybook/manager-webpack4" "6.3.7" - "@storybook/node-logger" "6.3.7" + "@discoveryjs/json-ext" "^0.5.3" + "@storybook/builder-webpack4" "6.3.11" + "@storybook/core-client" "6.3.11" + "@storybook/core-common" "6.3.11" + "@storybook/csf-tools" "6.3.11" + "@storybook/manager-webpack4" "6.3.11" + "@storybook/node-logger" "6.3.11" "@storybook/semver" "^7.3.2" "@types/node" "^14.0.10" "@types/node-fetch" "^2.5.7" @@ -5870,18 +6050,18 @@ util-deprecate "^1.0.2" webpack "4" -"@storybook/core@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/core/-/core-6.3.7.tgz#482228a270abc3e23fed10c7bc4df674da22ca19" - integrity sha512-YTVLPXqgyBg7TALNxQ+cd+GtCm/NFjxr/qQ1mss1T9GCMR0IjE0d0trgOVHHLAO8jCVlK8DeuqZCCgZFTXulRw== +"@storybook/core@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/core/-/core-6.3.11.tgz#7ded63649e8096339eca445e8de1f550a621179d" + integrity sha512-WhDA98hTI01L/R9l7ZCDXqhZ73Esf7VmngxcF8sVZVnM1ZwO3jq0BPYnTPUR65sVZ4XLUx1zuFQ2pAipsM8y1g== dependencies: - "@storybook/core-client" "6.3.7" - "@storybook/core-server" "6.3.7" + "@storybook/core-client" "6.3.11" + "@storybook/core-server" "6.3.11" -"@storybook/csf-tools@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.3.7.tgz#505514d211f8698c47ddb15662442098b4b00156" - integrity sha512-A7yGsrYwh+vwVpmG8dHpEimX021RbZd9VzoREcILH56u8atssdh/rseljyWlRes3Sr4QgtLvDB7ggoJ+XDZH7w== +"@storybook/csf-tools@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.3.11.tgz#53e40158032902cdedf6fbbdee9953e92f4a9973" + integrity sha512-XI9E1nhoD3ALRmHPL6NTVxap6ryh64pJDQyYbji7zRblL+QyCywv6AwUUs00iwjWrLeuthusJ434aX/imATQSA== dependencies: "@babel/generator" "^7.12.11" "@babel/parser" "^7.12.11" @@ -5905,20 +6085,20 @@ dependencies: lodash "^4.17.15" -"@storybook/manager-webpack4@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.3.7.tgz#9ca604dea38d3c47eb38bf485ca6107861280aa8" - integrity sha512-cwUdO3oklEtx6y+ZOl2zHvflICK85emiXBQGgRcCsnwWQRBZOMh+tCgOSZj4jmISVpT52RtT9woG4jKe15KBig== +"@storybook/manager-webpack4@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.3.11.tgz#477a796da09a771b2d3e1adfe217a79de37057af" + integrity sha512-EY/mhxAbOznZn4ql6/UW738ezd2dIWCgC3DAzhd/1crIbp7LqzNcXOW3QWYtfLLEOhsmI3TO1U7ExyN1t3n48g== dependencies: "@babel/core" "^7.12.10" "@babel/plugin-transform-template-literals" "^7.12.1" "@babel/preset-react" "^7.12.10" - "@storybook/addons" "6.3.7" - "@storybook/core-client" "6.3.7" - "@storybook/core-common" "6.3.7" - "@storybook/node-logger" "6.3.7" - "@storybook/theming" "6.3.7" - "@storybook/ui" "6.3.7" + "@storybook/addons" "6.3.11" + "@storybook/core-client" "6.3.11" + "@storybook/core-common" "6.3.11" + "@storybook/node-logger" "6.3.11" + "@storybook/theming" "6.3.11" + "@storybook/ui" "6.3.11" "@types/node" "^14.0.10" "@types/webpack" "^4.41.26" babel-loader "^8.2.2" @@ -5948,10 +6128,10 @@ webpack-dev-middleware "^3.7.3" webpack-virtual-modules "^0.2.2" -"@storybook/node-logger@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.3.7.tgz#492469ea4749de8d984af144976961589a1ac382" - integrity sha512-YXHCblruRe6HcNefDOpuXJoaybHnnSryIVP9Z+gDv6OgLAMkyxccTIaQL9dbc/eI4ywgzAz4kD8t1RfVwXNVXw== +"@storybook/node-logger@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.3.11.tgz#b17c48b8b8083ed9d06d01266af0736b13101dd4" + integrity sha512-c6nsOk/AIux89/AVIydLA2ToqHWq4XoUKFkYJ/eOPJTLv3bdl7fV/5Vlx7EqRHqlXYCGbvTaDrMs+0tVHmp2vg== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.1.0" @@ -5973,17 +6153,17 @@ tslib "^2.0.0" "@storybook/react@^6.3.6": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/react/-/react-6.3.7.tgz#b15259aeb4cdeef99cc7f09d21db42e3ecd7a01a" - integrity sha512-4S0iCQIzgi6PdAtV2sYw4uL57yIwbMInNFSux9CxPnVdlxOxCJ+U8IgTxD4tjkTvR4boYSEvEle46ns/bwg5iQ== + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/react/-/react-6.3.11.tgz#f6270fcebc072e6adbb1e08e4a4abb0f9b518744" + integrity sha512-nW04cvjGRW92gD2ibiDyRtSi0GW3RjZzZkFSiwzA7SbAw9HxvIP1nCYOroIX1x/xGMMiypgFPavgaFcaYbyE/Q== dependencies: "@babel/preset-flow" "^7.12.1" "@babel/preset-react" "^7.12.10" "@pmmmwh/react-refresh-webpack-plugin" "^0.4.3" - "@storybook/addons" "6.3.7" - "@storybook/core" "6.3.7" - "@storybook/core-common" "6.3.7" - "@storybook/node-logger" "6.3.7" + "@storybook/addons" "6.3.11" + "@storybook/core" "6.3.11" + "@storybook/core-common" "6.3.11" + "@storybook/node-logger" "6.3.11" "@storybook/react-docgen-typescript-plugin" "1.0.2-canary.253f8c1.0" "@storybook/semver" "^7.3.2" "@types/webpack-env" "^1.16.0" @@ -6001,6 +6181,22 @@ ts-dedent "^2.0.0" webpack "4" +"@storybook/router@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/router/-/router-6.3.11.tgz#7b43d4704f2bced12109e16906e100ff9fa3eae9" + integrity sha512-R9Den9xCGhU5CLx4wi79uHbJqKqpZO7QDpENZGL7bT/IDid7szqFldztrzvmC5LE1TBpU6VQjEGaITWMrG2tsw== + dependencies: + "@reach/router" "^1.3.4" + "@storybook/client-logger" "6.3.11" + "@types/reach__router" "^1.3.7" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.20" + memoizerific "^1.11.3" + qs "^6.10.0" + ts-dedent "^2.0.0" + "@storybook/router@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/router/-/router-6.3.7.tgz#1714a99a58a7b9f08b6fcfe2b678dad6ca896736" @@ -6041,6 +6237,24 @@ prettier "~2.2.1" regenerator-runtime "^0.13.7" +"@storybook/theming@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.3.11.tgz#0fb4e42b43b5937647a3e4f17422c3cf45d046fb" + integrity sha512-MbEaGYP9nqu/Sv/FBK/7jRRHGe34TZ7tmZj6ZWE0KZih4Ey39LjPY6XcJ1rMDZclrXmT98p3+KClzdwKD0/Tdw== + dependencies: + "@emotion/core" "^10.1.1" + "@emotion/is-prop-valid" "^0.8.6" + "@emotion/styled" "^10.0.27" + "@storybook/client-logger" "6.3.11" + core-js "^3.8.2" + deep-object-diff "^1.1.0" + emotion-theming "^10.0.27" + global "^4.4.0" + memoizerific "^1.11.3" + polished "^4.0.5" + resolve-from "^5.0.0" + ts-dedent "^2.0.0" + "@storybook/theming@6.3.7": version "6.3.7" resolved "https://registry.npmjs.org/@storybook/theming/-/theming-6.3.7.tgz#6daf9a21b26ed607f3c28a82acd90c0248e76d8b" @@ -6059,21 +6273,21 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/ui@6.3.7": - version "6.3.7" - resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.3.7.tgz#d0caea50640670da3189bbbb67c43da30c90455a" - integrity sha512-PBeRO8qtwAbtHvxUgNtz/ChUR6qnN+R37dMaIs3Y96jbks1fS2K9Mt7W5s1HnUbWbg2KsZMv9D4VYPBasY+Isw== +"@storybook/ui@6.3.11": + version "6.3.11" + resolved "https://registry.npmjs.org/@storybook/ui/-/ui-6.3.11.tgz#fc04d6ab50b78dc5f3d8fdc1eade0c78e4c4a4e9" + integrity sha512-Jy6J7GRCgcnCp6jOpGcGcjHfzMVqFJ8gnLzrvTPR6EQBl9sJlJMVvYyj/52fDTnrRj+mjs8+cnkQwUHg+U/yrA== dependencies: "@emotion/core" "^10.1.1" - "@storybook/addons" "6.3.7" - "@storybook/api" "6.3.7" - "@storybook/channels" "6.3.7" - "@storybook/client-logger" "6.3.7" - "@storybook/components" "6.3.7" - "@storybook/core-events" "6.3.7" - "@storybook/router" "6.3.7" + "@storybook/addons" "6.3.11" + "@storybook/api" "6.3.11" + "@storybook/channels" "6.3.11" + "@storybook/client-logger" "6.3.11" + "@storybook/components" "6.3.11" + "@storybook/core-events" "6.3.11" + "@storybook/router" "6.3.11" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.3.7" + "@storybook/theming" "6.3.11" "@types/markdown-to-jsx" "^6.11.3" copy-to-clipboard "^3.3.1" core-js "^3.8.2" @@ -6642,6 +6856,13 @@ resolved "https://registry.npmjs.org/@types/dagre/-/dagre-0.7.44.tgz#8f4b796b118ca29c132da7068fbc0d0351ee5851" integrity sha512-N6HD+79w77ZVAaVO7JJDW5yJ9LAxM62FpgNGO9xEde+KVYjDRyhIMzfiErXpr1g0JPon9kwlBzoBK6s4fOww9Q== +"@types/debug@^4.0.0": + version "4.1.7" + resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" + integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + dependencies: + "@types/ms" "*" + "@types/diff@^5.0.0": version "5.0.0" resolved "https://registry.npmjs.org/@types/diff/-/diff-5.0.0.tgz#eb71e94feae62548282c4889308a3dfb57e36020" @@ -6716,9 +6937,9 @@ "@types/range-parser" "*" "@types/express-session@^1.17.2": - version "1.17.3" - resolved "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.3.tgz#4a37c5c4428b8f922ac8ac1cb4bd9190a4d2b097" - integrity sha512-57DnyxiqClXOIjoCgeKCUYfKxBPOlOY/k+l1TPK+7bSwyiPTrS5FIk1Ycql7twk4wO7P5lfOVy6akDGiaMSLfw== + version "1.17.4" + resolved "https://registry.npmjs.org/@types/express-session/-/express-session-1.17.4.tgz#97a30a35e853a61bdd26e727453b8ed314d6166b" + integrity sha512-7cNlSI8+oOBUHTfPXMwDxF/Lchx5aJ3ho7+p9jJZYVg9dVDJFh3qdMXmJtRsysnvS+C6x46k9DRYmrmCkE+MVg== dependencies: "@types/express" "*" @@ -6785,9 +7006,9 @@ "@types/node" "*" "@types/hast@^2.0.0": - version "2.3.1" - resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.1.tgz#b16872f2a6144c7025f296fb9636a667ebb79cd9" - integrity sha512-viwwrB+6xGzw+G1eWpF9geV3fnsDgXqHG+cqgiHrvQfDUW5hzhCyV7Sy3UJxhfRFBsgky2SSW33qi/YrIkjX5Q== + version "2.3.4" + resolved "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== dependencies: "@types/unist" "*" @@ -7075,6 +7296,11 @@ dependencies: "@types/unist" "*" +"@types/mdurl@^1.0.0": + version "1.0.2" + resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" + integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== + "@types/micromatch@^4.0.1": version "4.0.1" resolved "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.1.tgz#9381449dd659fc3823fd2a4190ceacc985083bc7" @@ -7123,6 +7349,11 @@ dependencies: "@types/node" "*" +"@types/ms@*": + version "0.7.31" + resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" + integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + "@types/node-fetch@^2.5.0", "@types/node-fetch@^2.5.7": version "2.5.8" resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" @@ -7374,9 +7605,9 @@ "@types/react" "*" "@types/react@*", "@types/react@>=16.9.0", "@types/react@^16.9": - version "16.14.15" - resolved "https://registry.npmjs.org/@types/react/-/react-16.14.15.tgz#95d8fa3148050e94bcdc5751447921adbe19f9e6" - integrity sha512-jOxlBV9RGZhphdeqJTCv35VZOkjY+XIEY2owwSk84BNDdDv2xS6Csj6fhi+B/q30SR9Tz8lDNt/F2Z5RF3TrRg== + version "16.14.18" + resolved "https://registry.npmjs.org/@types/react/-/react-16.14.18.tgz#b2bcea05ee244fde92d409f91bd888ca8e54b20f" + integrity sha512-eeyqd1mqoG43mI0TvNKy9QNf1Tjz3DEOsRP3rlPo35OeMIt05I+v9RR8ZvL2GuYZeF2WAcLXJZMzu6zdz3VbtQ== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -7642,9 +7873,9 @@ integrity sha512-vX1NPekXhrLquFWskH2thcvFAha187F/lM6xYOoEMZWwJ/6alSk0/ttmGP/YRqcqtCv0TMbZjYAdZyHAEcuU4g== "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.3" - resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" - integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== + version "2.0.6" + resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== "@types/unzipper@^0.10.3": version "0.10.3" @@ -8155,10 +8386,10 @@ dependencies: tslib "^1.9.3" -"@xmldom/xmldom@^0.7.0", "@xmldom/xmldom@^0.7.2": - version "0.7.3" - resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.3.tgz#55de695f77afd3cc0e5bee0aa900040bc63c0f63" - integrity sha512-8XmJdPut2XGtfFcsNsqEsvMUmAwk7xLq7m+E/GcsU9b5qyFFIsiX4Fvnb5UoQ4wo12Wlm07YFJERoyWUYdbIpw== +"@xmldom/xmldom@^0.7.0", "@xmldom/xmldom@^0.7.5": + version "0.7.5" + resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" + integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== "@xobotyi/scrollbar-width@^1.9.5": version "1.9.5" @@ -9465,6 +9696,11 @@ bail@^1.0.0: resolved "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== +bail@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/bail/-/bail-2.0.1.tgz#d676736373a374058a935aec81b94c12ba815771" + integrity sha512-d5FoTAr2S5DSUPKl85WNm2yUwsINN8eidIdIwsOge2t33DaOfOdSmmsI11jMN3GmALCXaw+Y6HMVHDzePshFAA== + balanced-match@^0.4.2: version "0.4.2" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" @@ -10245,9 +10481,9 @@ canvas@^2.6.1: simple-get "^3.0.3" canvg@^3.0.6: - version "3.0.8" - resolved "https://registry.npmjs.org/canvg/-/canvg-3.0.8.tgz#9125a4b7033d2f237402241b192587385f4589e6" - integrity sha512-9De5heHfVRgCkln3CGEeSJMviN5U2RyxL4uutYoe8HxI60BjH2XnT2ZUHIp+ZaAZNTUd5Asqfut8WEEdANqfAg== + version "3.0.9" + resolved "https://registry.npmjs.org/canvg/-/canvg-3.0.9.tgz#9ba095f158b94b97ca2c9c1c40785b11dc08df6d" + integrity sha512-rDXcnRPuz4QHoCilMeoTxql+fvGqNAxp+qV/KHD8rOiJSAfVjFclbdUNHD2Uqfthr+VMg17bD2bVuk6F07oLGw== dependencies: "@babel/runtime" "^7.12.5" "@types/raf" "^3.4.0" @@ -10256,7 +10492,7 @@ canvg@^3.0.6: regenerator-runtime "^0.13.7" rgbcolor "^1.0.1" stackblur-canvas "^2.0.0" - svg-pathdata "^5.0.5" + svg-pathdata "^6.0.3" capital-case@^1.0.4: version "1.0.4" @@ -10289,6 +10525,11 @@ ccount@^1.0.0: resolved "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== +ccount@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ccount/-/ccount-2.0.0.tgz#3d6fb55803832766a24c6f339abc507297eb5d25" + integrity sha512-VOR0NWFYX65n9gELQdcpqsie5L5ihBXuZGAgaPEp/U7IOSjnPMEH6geE+2f6lcekaNEfWzAHS45mPvSo5bqsUA== + chainsaw@~0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" @@ -10383,16 +10624,31 @@ character-entities-legacy@^1.0.0: resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== +character-entities-legacy@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-2.0.0.tgz#57f4d00974c696e8f74e9f493e7fcb75b44d7ee7" + integrity sha512-YwaEtEvWLpFa6Wh3uVLrvirA/ahr9fki/NUd/Bd4OR6EdJ8D22hovYQEOUCBfQfcqnC4IAMGMsHXY1eXgL4ZZA== + character-entities@^1.0.0: version "1.2.4" resolved "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== +character-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/character-entities/-/character-entities-2.0.0.tgz#508355fcc8c73893e0909efc1a44d28da2b6fdf3" + integrity sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA== + character-reference-invalid@^1.0.0: version "1.1.4" resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== +character-reference-invalid@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.0.tgz#a0bdeb89c051fe7ed5d3158b2f06af06984f2813" + integrity sha512-pE3Z15lLRxDzWJy7bBHBopRwfI20sbrMVLQTC7xsPglCHf4Wv1e167OgYAFP78co2XlhojDyAqA+IAJse27//g== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -10879,6 +11135,11 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== +comma-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" + integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + command-exists@^1.2.9: version "1.2.9" resolved "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" @@ -11289,12 +11550,7 @@ core-js-pure@^3.8.2: resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.0.tgz#218e07add3f1844e53fab195c47871fc5ba18de8" integrity sha512-wzlhZNepF/QA9yvx3ePDgNGudU5KDB8lu/TRPKelYA/QtSnkS/cLl2W+TIdEX1FAFcBr0YpY7tPDlcmXJ7AyiQ== -core-js@^2.4.0, core-js@^2.6.10: - version "2.6.11" - resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - -core-js@^2.5.0: +core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.10: version "2.6.12" resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== @@ -11305,9 +11561,9 @@ core-js@^3.0.4, core-js@^3.6.5, core-js@^3.8.2: integrity sha512-GUbtPllXMYRzIgHNZ4dTYTcUemls2cni83Q4Q/TrFONHfhcg9oEGOtaGHfb0cpzec60P96UKPvMkjX1jET8rUw== core-js@^3.6.0, core-js@^3.8.3: - version "3.18.1" - resolved "https://registry.npmjs.org/core-js/-/core-js-3.18.1.tgz#289d4be2ce0085d40fc1244c0b1a54c00454622f" - integrity sha512-vJlUi/7YdlCZeL6fXvWNaLUPh/id12WXj3MbkMw5uOyF0PfWPBNOCNbs53YqgrvtujLNlt9JQpruyIKkUZ+PKA== + version "3.18.3" + resolved "https://registry.npmjs.org/core-js/-/core-js-3.18.3.tgz#86a0bba2d8ec3df860fefcc07a8d119779f01509" + integrity sha512-tReEhtMReZaPFVw7dajMx0vlsz3oOb8ajgPoHVYGxr8ErnZ6PcYEvvmjGmXlfpnxpkYSdOQttjB+MvVbCGfvLw== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -12140,7 +12396,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.2, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1: +debug@4, debug@4.3.2, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.0, debug@^4.3.1, debug@^4.3.2: version "4.3.2" resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== @@ -13158,6 +13414,11 @@ escape-string-regexp@^4.0.0: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + escodegen@^1.14.1, escodegen@^1.9.1: version "1.14.3" resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" @@ -14987,6 +15248,21 @@ google-auth-library@^7.0.0, google-auth-library@^7.0.2: jws "^4.0.0" lru-cache "^6.0.0" +google-auth-library@^7.6.1: + version "7.10.0" + resolved "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.10.0.tgz#6ab852f8e1abbe425aec695ac6501f80bd5eba56" + integrity sha512-ICsqaU+lxMHVlDUzMrfVIEqnARw2AwBiZ/2KnNM6BcTf9Nott+Af87DTIzmlnW865p3REUP2MVL0xkPC3a61aQ== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^4.0.0" + gcp-metadata "^4.2.0" + gtoken "^5.0.4" + jws "^4.0.0" + lru-cache "^6.0.0" + google-gax@^2.12.0: version "2.14.1" resolved "https://registry.npmjs.org/google-gax/-/google-gax-2.14.1.tgz#74885c5d9f01db412917fc49bbf20c4884828d36" @@ -15005,6 +15281,25 @@ google-gax@^2.12.0: protobufjs "^6.10.2" retry-request "^4.0.0" +google-gax@^2.24.1: + version "2.27.0" + resolved "https://registry.npmjs.org/google-gax/-/google-gax-2.27.0.tgz#78ba655ae7707cb92ba37c35932381b5970c1772" + integrity sha512-xcLCeNKCqNm/w0At7/vdZHV/zol/iRS+PSAZTu7i6xNGBra/kWI3cfn4M6ZLQXeUEGbTVLJ4zGm53TVc4lvbDA== + dependencies: + "@grpc/grpc-js" "~1.3.0" + "@grpc/proto-loader" "^0.6.1" + "@types/long" "^4.0.0" + abort-controller "^3.0.0" + duplexify "^4.0.0" + fast-text-encoding "^1.0.3" + google-auth-library "^7.6.1" + is-stream-ended "^0.1.4" + node-fetch "^2.6.1" + object-hash "^2.1.1" + proto3-json-serializer "^0.1.1" + protobufjs "6.11.2" + retry-request "^4.0.0" + google-p12-pem@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e" @@ -15497,9 +15792,9 @@ highlight.js@~10.7.0: integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== history@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/history/-/history-5.0.0.tgz#0cabbb6c4bbf835addb874f8259f6d25101efd08" - integrity sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg== + version "5.0.1" + resolved "https://registry.npmjs.org/history/-/history-5.0.1.tgz#de35025ed08bce0db62364b47ebbf9d97b5eb06a" + integrity sha512-5qC/tFUKfVci5kzgRxZxN5Mf1CV8NmJx9ByaPX0YTLx5Vz3Svh7NYp6eA4CpDq4iA9D0C1t8BNIfvQIrUI3mVw== dependencies: "@babel/runtime" "^7.7.6" @@ -16282,6 +16577,11 @@ is-alphabetical@1.0.4, is-alphabetical@^1.0.0: resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== +is-alphabetical@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.0.tgz#ef6e2caea57c63450fffc7abb6cbdafc5eb96e96" + integrity sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w== + is-alphanumerical@^1.0.0: version "1.0.4" resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" @@ -16290,6 +16590,14 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" +is-alphanumerical@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.0.tgz#0fbfeb6a72d21d91143b3d182bf6cf5909ee66f6" + integrity sha512-t+2GlJ+hO9yagJ+jU3+HSh80VKvz/3cG2cxbGGm4S0hjKuhWQXgPVUVOZz3tqZzMjhmphZ+1TIJTlRZRoe6GCQ== + dependencies: + is-alphabetical "^2.0.0" + is-decimal "^2.0.0" + is-arguments@^1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" @@ -16403,6 +16711,11 @@ is-decimal@^1.0.0: resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== +is-decimal@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.0.tgz#db1140337809fd043a056ae40a9bd1cdc563034c" + integrity sha512-QfrfjQV0LjoWQ1K1XSoEZkTAzSa14RKVMa5zg3SdAfzEmQzRM4+tbSFWb78creCeA9rNBzaZal92opi1TwPWZw== + is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" @@ -16524,6 +16837,11 @@ is-hexadecimal@^1.0.0: resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== +is-hexadecimal@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.0.tgz#8e1ec9f48fe3eabd90161109856a23e0907a65d5" + integrity sha512-vGOtYkiaxwIiR0+Ng/zNId+ZZehGfINwTzdrDqc6iubbnQWhnPuYymOzOKUDqa2cSl59yHnEh2h6MvRLQsyNug== + is-in-browser@^1.0.2, is-in-browser@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835" @@ -16658,6 +16976,11 @@ is-plain-obj@^3.0.0: resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== +is-plain-obj@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.0.0.tgz#06c0999fd7574edf5a906ba5644ad0feb3a84d22" + integrity sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw== + is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -18828,6 +19151,11 @@ longest-streak@^2.0.0: resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== +longest-streak@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/longest-streak/-/longest-streak-3.0.0.tgz#f127e2bded83caa6a35ac5f7a2f2b2f94b36f3dc" + integrity sha512-XhUjWR5CFaQ03JOP+iSDS9koy8T5jfoImCZ4XprElw3BXsSk4MpVYOLw/6LTDKZhO13PlAXnB5gS4MHQTpkSOw== + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -19086,6 +19414,11 @@ markdown-table@^2.0.0: dependencies: repeat-string "^1.0.0" +markdown-table@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.1.tgz#88c48957aaf2a8014ccb2ba026776a1d736fe3dc" + integrity sha512-CBbaYXKSGnE1uLRpKA1SWgIRb2PQrpkllNWpZtZe6VojOJ4ysqiq7/2glYcmKsOYN09QgH/HEBX5hIshAeiK6A== + markdown-to-jsx@^6.11.4: version "6.11.4" resolved "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-6.11.4.tgz#b4528b1ab668aef7fe61c1535c27e837819392c5" @@ -19152,6 +19485,24 @@ mdast-util-definitions@^4.0.0: dependencies: unist-util-visit "^2.0.0" +mdast-util-definitions@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.0.tgz#b6d10ef00a3c4cf191e8d9a5fa58d7f4a366f817" + integrity sha512-5hcR7FL2EuZ4q6lLMUK5w4lHT2H3vqL9quPvYZ/Ku5iifrirfMHiGdhxdXMUbUkDmz5I+TYMd7nbaxUhbQkfpQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + unist-util-visit "^3.0.0" + +mdast-util-find-and-replace@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.1.0.tgz#69728acd250749f8aac6e150e07d1fd15619e829" + integrity sha512-1w1jbqAd13oU78QPBf5223+xB+37ecNtQ1JElq2feWols5oEYAl+SgNDnOZipe7NfLemoEt362yUS15/wip4mw== + dependencies: + escape-string-regexp "^5.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^4.0.0" + mdast-util-from-markdown@^0.8.0: version "0.8.1" resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.1.tgz#781371d493cac11212947226190270c15dc97116" @@ -19162,11 +19513,38 @@ mdast-util-from-markdown@^0.8.0: micromark "~2.10.0" parse-entities "^2.0.0" +mdast-util-from-markdown@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.0.2.tgz#7c793bb96b053d12f032e37382ae989efb70ee66" + integrity sha512-gXaxv/5fGdrr9TqSMlQK7FmshK8yR9DvW3+NapMBDm44inORxIZVJa1D3yjrUT9ISu8tB/jjblEkUzyzclquNg== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + parse-entities "^3.0.0" + unist-util-stringify-position "^3.0.0" + mdast-util-gfm-autolink-literal@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.1.tgz#94675074d725ed7254b3172fa7e7c3252960de39" integrity sha512-gJ2xSpqKCetSr22GEWpZH3f5ffb4pPn/72m4piY0v7T/S+O7n7rw+sfoPLhb2b4O7WdnERoYdALRcmD68FMtlw== +mdast-util-gfm-autolink-literal@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz#4032dcbaddaef7d4f2f3768ed830475bb22d3970" + integrity sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg== + dependencies: + "@types/mdast" "^3.0.0" + ccount "^2.0.0" + mdast-util-find-and-replace "^2.0.0" + micromark-util-character "^1.0.0" + mdast-util-gfm-strikethrough@^0.2.0: version "0.2.2" resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.2.tgz#6e9ddd33ce41b06a60463e817f6ef4cf7bfa0655" @@ -19174,6 +19552,14 @@ mdast-util-gfm-strikethrough@^0.2.0: dependencies: mdast-util-to-markdown "^0.5.0" +mdast-util-gfm-strikethrough@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.0.tgz#6cc72ef5d9539f4cee76af3f15dd0daa9e3af40f" + integrity sha512-gM9ipBUdRxYa6Yq1Hd8Otg6jEn/dRxFZ1F9ZX4QHosHOexLGqNZO2dh0A+YFbUEd10RcKjnjb4jOfJJzoXXUew== + dependencies: + "@types/mdast" "^3.0.3" + mdast-util-to-markdown "^1.0.0" + mdast-util-gfm-table@^0.1.0: version "0.1.4" resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.4.tgz#5b3d71d16294c6fae1c2c424d3a081ffc7407b83" @@ -19182,6 +19568,14 @@ mdast-util-gfm-table@^0.1.0: markdown-table "^2.0.0" mdast-util-to-markdown "^0.5.0" +mdast-util-gfm-table@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.1.tgz#07c269a219d66ec2deb6de38aed0ba1d1f9442df" + integrity sha512-NByKuaSg5+M6r9DZBPXFUmhMHGFf9u+WE76EeStN01ghi8hpnydiWBXr+qj0XCRWI7SAMNtEjGvip6zci9axQA== + dependencies: + markdown-table "^3.0.0" + mdast-util-to-markdown "^1.0.0" + mdast-util-gfm-task-list-item@^0.1.0: version "0.1.4" resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.4.tgz#5899b1320d1b826f7658ac3171babf4ae1e626a2" @@ -19189,6 +19583,14 @@ mdast-util-gfm-task-list-item@^0.1.0: dependencies: mdast-util-to-markdown "^0.5.0" +mdast-util-gfm-task-list-item@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.0.tgz#a0aa2a00c893f9f006d13ba096cbc64608559c7f" + integrity sha512-dwkzOTjQe8JCCHVE3Cb0pLHTYLudf7t9WCAnb20jI8/dW+VHjgWhjtIUVA3oigNkssgjEwX+i+3XesUdCnXGyA== + dependencies: + "@types/mdast" "^3.0.3" + mdast-util-to-markdown "^1.0.0" + mdast-util-gfm@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-0.1.0.tgz#bac0efe703670d1b40474e6be13dbdd887273a04" @@ -19199,6 +19601,16 @@ mdast-util-gfm@^0.1.0: mdast-util-gfm-table "^0.1.0" mdast-util-gfm-task-list-item "^0.1.0" +mdast-util-gfm@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-1.0.0.tgz#5cbedeabae72be2c3dff1ec958394e2f9553ec43" + integrity sha512-JY4qImsTqivQ0Gl3qvdaizCpomFaNrHnjEhNjNNKeNEA5jZHAJDYu1+yO4V9jn4/ti8GrKdAScaT4F71knoxsA== + dependencies: + mdast-util-gfm-autolink-literal "^1.0.0" + mdast-util-gfm-strikethrough "^1.0.0" + mdast-util-gfm-table "^1.0.0" + mdast-util-gfm-task-list-item "^1.0.0" + mdast-util-to-hast@10.0.1: version "10.0.1" resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" @@ -19213,6 +19625,21 @@ mdast-util-to-hast@10.0.1: unist-util-position "^3.0.0" unist-util-visit "^2.0.0" +mdast-util-to-hast@^11.0.0: + version "11.3.0" + resolved "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-11.3.0.tgz#ea9220617a710e80aa5cc3ac7cc9d4bb0440ae7a" + integrity sha512-4o3Cli3hXPmm1LhB+6rqhfsIUBjnKFlIUZvudaermXB+4/KONdd/W4saWWkC+LBLbPMqhFSSTSRgafHsT5fVJw== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + "@types/mdurl" "^1.0.0" + mdast-util-definitions "^5.0.0" + mdurl "^1.0.0" + unist-builder "^3.0.0" + unist-util-generated "^2.0.0" + unist-util-position "^4.0.0" + unist-util-visit "^4.0.0" + mdast-util-to-markdown@^0.5.0: version "0.5.3" resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.5.3.tgz#e05c54a3ccd239bab63c48a1e5b5747f0dcd5aca" @@ -19225,11 +19652,29 @@ mdast-util-to-markdown@^0.5.0: repeat-string "^1.0.0" zwitch "^1.0.0" +mdast-util-to-markdown@^1.0.0: + version "1.2.3" + resolved "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.2.3.tgz#2b3af92bf0e29080927eb59a8a10cd0a7398e093" + integrity sha512-040jJYtjOUdbvYAXCfPrpLJRdvMOmR33KRqlhT4r+fEbVM+jao1RMbA8RmGeRmw8RAj3vQ+HvhIaJPijvnOwCg== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + longest-streak "^3.0.0" + mdast-util-to-string "^3.0.0" + micromark-util-decode-string "^1.0.0" + unist-util-visit "^4.0.0" + zwitch "^2.0.0" + mdast-util-to-string@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz#27055500103f51637bd07d01da01eb1967a43527" integrity sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A== +mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" + integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -19437,6 +19882,37 @@ microevent.ts@~0.1.1: resolved "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== +micromark-core-commonmark@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-1.0.1.tgz#a64987cafe872e8b80bc8f2352a5d988586ac4f1" + integrity sha512-vEOw8hcQ3nwHkKKNIyP9wBi8M50zjNajtmI+cCUWcVfJS+v5/3WCh4PLKf7PPRZFUutjzl4ZjlHwBWUKfb/SkA== + dependencies: + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + parse-entities "^3.0.0" + +micromark-extension-gfm-autolink-literal@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.0.tgz#1a49a62bfcb00f9dff87ab39f3b21a108612dc24" + integrity sha512-t+K0aPK32mXypVTEKV+WRfoT/Rb7MERDgHZVRr56NXpyQQhgMk72QnK4NljYUlrgbuesH+MxiPQwThzqRDIwvA== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-extension-gfm-autolink-literal@~0.5.0: version "0.5.1" resolved "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.1.tgz#5326fc86f3ae0fbba57bb0bfc2f158c9456528ce" @@ -19444,6 +19920,17 @@ micromark-extension-gfm-autolink-literal@~0.5.0: dependencies: micromark "~2.10.0" +micromark-extension-gfm-strikethrough@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.1.tgz#9f53ab4f5dc8c0525a889850bae615f074a98a27" + integrity sha512-fzGYXWz9HPWH1uHqYwdyR8XpEtuoYVHUjTdPQTnl3ETVZOQe1NXMwE3RA7AMqeON52hG+kO9g1/P1+pLONBSMQ== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-extension-gfm-strikethrough@~0.6.0: version "0.6.2" resolved "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.2.tgz#754788bdd13046e7f69edaa0d3f3d555d23128d6" @@ -19451,6 +19938,16 @@ micromark-extension-gfm-strikethrough@~0.6.0: dependencies: micromark "~2.10.0" +micromark-extension-gfm-table@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.0.tgz#f0d35dbf008b6182311049f9137323d34a54c7a0" + integrity sha512-OATRuHDgEAT/aaJJRSdU12V+s01kNSnJ0jumdfLq5mPy0F5DkR3zbTSFLH4tjVYM0/kEG6umxIhHY62mFe4z5Q== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-extension-gfm-table@~0.4.0: version "0.4.1" resolved "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.1.tgz#79cc37da82d6ae0cc3901c1c6264b97a72372fbd" @@ -19458,11 +19955,28 @@ micromark-extension-gfm-table@~0.4.0: dependencies: micromark "~2.10.0" +micromark-extension-gfm-tagfilter@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.0.tgz#a38c7c462c2007b534fcb485e9310165879654a7" + integrity sha512-GGUZhzQrOdHR8RHU2ru6K+4LMlj+pBdNuXRtw5prOflDOk2hHqDB0xEgej1AHJ2VETeycX7tzQh2EmaTUOmSKg== + dependencies: + micromark-util-types "^1.0.0" + micromark-extension-gfm-tagfilter@~0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz#d9f26a65adee984c9ccdd7e182220493562841ad" integrity sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q== +micromark-extension-gfm-task-list-item@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.0.tgz#ab38b2b4ead4e746189d6323c32cacab2c63599d" + integrity sha512-3tkHCq1NNwijtwpjYba9+rl1yvQ4xYg8iQpUAfTJRyq8MtIEsBUF/vW6B9Gh8Qwy1hE2FmpyHhP4jnFAt61zLg== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + micromark-extension-gfm-task-list-item@~0.3.0: version "0.3.1" resolved "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.1.tgz#24b7f54936a609179595f87a0e5279d1c6cf346c" @@ -19480,6 +19994,187 @@ micromark-extension-gfm@^0.3.0: micromark-extension-gfm-tagfilter "~0.3.0" micromark-extension-gfm-task-list-item "~0.3.0" +micromark-extension-gfm@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-1.0.0.tgz#7a1cee0df200e3f2ab14cb63d7a5ea6820a82f1d" + integrity sha512-OjqbQPL1Vec/4l5hnC8WnMNmWwgrT9JvzR2udqIGrGKecZsdwY9GAWZ5482CuD12SXuHNj8aS8epni6ip0Pwog== + dependencies: + micromark-extension-gfm-autolink-literal "^1.0.0" + micromark-extension-gfm-strikethrough "^1.0.0" + micromark-extension-gfm-table "^1.0.0" + micromark-extension-gfm-tagfilter "^1.0.0" + micromark-extension-gfm-task-list-item "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-destination@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" + integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-label@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-1.0.0.tgz#b316ec479b474232973ff13b49b576f84a6f2cbb" + integrity sha512-XWEucVZb+qBCe2jmlOnWr6sWSY6NHx+wtpgYFsm4G+dufOf6tTQRRo0bdO7XSlGPu5fyjpJenth6Ksnc5Mwfww== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-space@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" + integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-title@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-1.0.0.tgz#708f7a8044f34a898c0efdb4f55e4da66b537273" + integrity sha512-flvC7Gx0dWVWorXuBl09Cr3wB5FTuYec8pMGVySIp2ZlqTcIjN/lFohZcP0EG//krTptm34kozHk7aK/CleCfA== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" + integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-character@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" + integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-chunked@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" + integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-classify-character@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" + integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-combine-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" + integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" + integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-decode-string@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-1.0.0.tgz#f97946825231d9c97df767875064401774578a6e" + integrity sha512-4g5UJ8P/J8wuRKUXCcB7udQuOBXpLyvBQSLSuznfBLCG+thKG6UTwFnXfHkrr/1wddprkUbPatCzxDjrJ+5zDg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + parse-entities "^3.0.0" + +micromark-util-encode@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-1.0.0.tgz#c409ecf751a28aa9564b599db35640fccec4c068" + integrity sha512-cJpFVM768h6zkd8qJ1LNRrITfY4gwFt+tziPcIf71Ui8yFzY9wG3snZQqiWVq93PG4Sw6YOtcNiKJfVIs9qfGg== + +micromark-util-html-tag-name@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.0.0.tgz#75737e92fef50af0c6212bd309bc5cb8dbd489ed" + integrity sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g== + +micromark-util-normalize-identifier@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" + integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-resolve-all@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" + integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== + dependencies: + micromark-util-types "^1.0.0" + +micromark-util-sanitize-uri@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz#27dc875397cd15102274c6c6da5585d34d4f12b2" + integrity sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-subtokenize@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.0.tgz#6f006fa719af92776c75a264daaede0fb3943c6a" + integrity sha512-EsnG2qscmcN5XhkqQBZni/4oQbLFjz9yk3ZM/P8a3YUjwV6+6On2wehr1ALx0MxK3+XXXLTzuBKHDFeDFYRdgQ== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-symbol@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.0.0.tgz#91cdbcc9b2a827c0129a177d36241bcd3ccaa34d" + integrity sha512-NZA01jHRNCt4KlOROn8/bGi6vvpEmlXld7EHcRH+aYWUfL3Wc8JLUNNlqUMKa0hhz6GrpUWsHtzPmKof57v0gQ== + +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.0.1.tgz#8bb8a092d93d326bd29fe29602799f2d0d922fd4" + integrity sha512-UT0ylWEEy80RFYzK9pEaugTqaxoD/j0Y9WhHpSyitxd99zjoQz7JJ+iKuhPAgOW2MiPSUAx+c09dcqokeyaROA== + +micromark@^3.0.0: + version "3.0.5" + resolved "https://registry.npmjs.org/micromark/-/micromark-3.0.5.tgz#d24792c8a06f201d5608c106dbfadef34c299684" + integrity sha512-QfjERBnPw0G9mxhOCkkbRP0n8SX8lIBLrEKeEVceviUukqVMv3hWE4AgNTOK/W6GWqtPvvIHg2Apl3j1Dxm6aQ== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + parse-entities "^3.0.0" + micromark@~2.10.0: version "2.10.1" resolved "https://registry.npmjs.org/micromark/-/micromark-2.10.1.tgz#cd73f54e0656f10e633073db26b663a221a442a7" @@ -19656,6 +20351,7 @@ minipass-fetch@^1.3.0, minipass-fetch@^1.3.2: resolved "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz#34c7cea038c817a8658461bf35174551dce17a0a" integrity sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ== dependencies: + encoding "^0.1.12" minipass "^3.1.0" minipass-sized "^1.0.3" minizlib "^2.0.0" @@ -21148,6 +21844,18 @@ parse-entities@^2.0.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" +parse-entities@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/parse-entities/-/parse-entities-3.0.0.tgz#9ed6d6569b6cfc95ade058d683ddef239dad60dc" + integrity sha512-AJlcIFDNPEP33KyJLguv0xJc83BNvjxwpuUIcetyXUsLpVXAUCePJ5kIoYtEN2R1ac0cYaRu/vk9dVFkewHQhQ== + dependencies: + character-entities "^2.0.0" + character-entities-legacy "^2.0.0" + character-reference-invalid "^2.0.0" + is-alphanumerical "^2.0.0" + is-decimal "^2.0.0" + is-hexadecimal "^2.0.0" + parse-filepath@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" @@ -21336,12 +22044,12 @@ passport-onelogin-oauth@^0.0.1: uid2 "0.0.3" passport-saml@^3.1.2: - version "3.1.2" - resolved "https://registry.npmjs.org/passport-saml/-/passport-saml-3.1.2.tgz#34a0c2c423d729ce102e69fea9c22040910e6d43" - integrity sha512-EhD3/ofiz1vu7R72i4RskXk/dQG9GyDmXPdHJf5LYB+93B5kvKv5p+5lpZgO3z+Wf3eN0h/tGdGd6noyYdjY6g== + version "3.2.0" + resolved "https://registry.npmjs.org/passport-saml/-/passport-saml-3.2.0.tgz#72ec8203df6dd872a205b8d5f578859a4e723e42" + integrity sha512-EUzL+Wk8ZVdvOYhCBTkUrR1fwuMwF9za1FinFabP5Tl9qeJktsJWfoiBz7Fk6jQvpLwfnfryGdvwcOlGVct41A== dependencies: - "@xmldom/xmldom" "^0.7.2" - debug "^4.3.1" + "@xmldom/xmldom" "^0.7.5" + debug "^4.3.2" passport-strategy "^1.0.0" xml-crypto "^2.1.3" xml-encryption "^1.3.0" @@ -22241,17 +22949,7 @@ precond@0.2: resolved "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= -preferred-pm@^3.0.0: - version "3.0.2" - resolved "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.0.2.tgz#bbdbef1014e34a7490349bf70d6d244b8d57a5e1" - integrity sha512-yGIxyBkK/OWOppgCXfOeOXOeNrddyK1DzqS6XpOokRZb2ogXTpHRhKDTO7d0pjF/2p2sV9pEkKL4e0tNZI1y2A== - dependencies: - find-up "^5.0.0" - find-yarn-workspace-root2 "1.2.16" - path-exists "^4.0.0" - which-pm "2.0.0" - -preferred-pm@^3.0.3: +preferred-pm@^3.0.0, preferred-pm@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.0.3.tgz#1b6338000371e3edbce52ef2e4f65eb2e73586d6" integrity sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ== @@ -22485,12 +23183,22 @@ property-information@^5.3.0: dependencies: xtend "^4.0.0" +property-information@^6.0.0: + version "6.0.1" + resolved "https://registry.npmjs.org/property-information/-/property-information-6.0.1.tgz#7c668d9f2b9cb63bc3e105d8b8dfee7221a17800" + integrity sha512-F4WUUAF7fMeF4/JUFHNBWDaKDXi2jbvqBW/y6o5wsf3j19wTZ7S60TmtB5HoBhtgw7NKQRMWuz5vk2PR0CygUg== + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -protobufjs@^6.10.0, protobufjs@^6.10.2: +proto3-json-serializer@^0.1.1: + version "0.1.4" + resolved "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-0.1.4.tgz#aa2dc4c9c9b7ea05631354b2c2e52c227539a7f0" + integrity sha512-bFzdsKU/zaTobWrRxRniMZIzzcgKYlmBWL1gAcTXZ2M7TQTGPI0JoYYs6bN7tpWj59ZCfwg7Ii/A2e8BbQGYnQ== + +protobufjs@6.11.2, protobufjs@^6.10.0, protobufjs@^6.10.2, protobufjs@^6.8.6: version "6.11.2" resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw== @@ -22951,6 +23659,11 @@ react-hook-form@^7.12.2: resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.16.1.tgz#669046df378a71949e5cf8a2398cbe20d5cb27bc" integrity sha512-kcLDmSmlyLUFx2UU5bG/o4+3NeK753fhKodJa8gkplXohGkpAq0/p+TR24OWjZmkEc3ES7ppC5v5d6KUk+fJTA== +react-hook-form@^7.13.0: + version "7.17.4" + resolved "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.17.4.tgz#232b6aaccddb91eb4a228ac20b154abd90866fdb" + integrity sha512-7XhbCr7d9fDC1TgcK/BUbt7D3q0VJMu7jPErfsa0JrxVjv/nni41xWdJcy0Zb7R+Np8OsCkQ2lMyloAtE3DLiQ== + react-hot-loader@^4.12.21: version "4.13.0" resolved "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-4.13.0.tgz#c27e9408581c2a678f5316e69c061b226dc6a202" @@ -22991,7 +23704,7 @@ react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-i resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2: +"react-is@^16.8.0 || ^17.0.0", react-is@^17.0.0, react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== @@ -23032,6 +23745,25 @@ react-markdown@^5.0.2: unist-util-visit "^2.0.0" xtend "^4.0.1" +react-markdown@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/react-markdown/-/react-markdown-7.0.1.tgz#c7365fcd7d1813b3ae68f2200e8f92d47d865627" + integrity sha512-pthNPaoiwg0q7hukoE04F2ENwSzijIlWHJ4UMs/96LUe/G/P3FnbP4qHzx3FoNqae+2SqDG8vzniTLnJDeWneg== + dependencies: + "@types/hast" "^2.0.0" + "@types/unist" "^2.0.0" + comma-separated-tokens "^2.0.0" + prop-types "^15.0.0" + property-information "^6.0.0" + react-is "^17.0.0" + remark-parse "^10.0.0" + remark-rehype "^9.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.3.0" + unified "^10.0.0" + unist-util-visit "^4.0.0" + vfile "^5.0.0" + react-popper-tooltip@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac" @@ -23735,6 +24467,16 @@ remark-gfm@^1.0.0: mdast-util-gfm "^0.1.0" micromark-extension-gfm "^0.3.0" +remark-gfm@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/remark-gfm/-/remark-gfm-2.0.0.tgz#4fef4d7b35afa2bd3cd0410d313d32169634051c" + integrity sha512-waIv4Tjcd2CTUDxKRYzuPyIHw1FoX4H2GjXAzXV9PxQWb+dU4fJivd/FZ+nxyzPARrqTjMIkwIwPoWNbpBhjcQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-gfm "^1.0.0" + micromark-extension-gfm "^1.0.0" + unified "^10.0.0" + remark-mdx@1.6.22: version "1.6.22" resolved "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" @@ -23771,6 +24513,15 @@ remark-parse@8.0.3: vfile-location "^3.0.0" xtend "^4.0.1" +remark-parse@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.0.tgz#65e2b2b34d8581d36b97f12a2926bb2126961cb4" + integrity sha512-07ei47p2Xl7Bqbn9H2VYQYirnAFJPwdMuypdozWsSbnmrkgA2e2sZLZdnDNrrsxR4onmIzH/J6KXqKxCuqHtPQ== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + unified "^10.0.0" + remark-parse@^9.0.0: version "9.0.0" resolved "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" @@ -23778,6 +24529,16 @@ remark-parse@^9.0.0: dependencies: mdast-util-from-markdown "^0.8.0" +remark-rehype@^9.0.0: + version "9.1.0" + resolved "https://registry.npmjs.org/remark-rehype/-/remark-rehype-9.1.0.tgz#e4b5b6e19c125b3780343eb66c3e9b99b0f06a81" + integrity sha512-oLa6YmgAYg19zb0ZrBACh40hpBLteYROaPLhBXzLgjqyHQrN+gVP9N/FJvfzuNNuzCutktkroXEZBrxAxKhh7Q== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-to-hast "^11.0.0" + unified "^10.0.0" + remark-squeeze-paragraphs@4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" @@ -24413,20 +25174,13 @@ select-hose@^2.0.0: resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -selfsigned@^1.10.11: +selfsigned@^1.10.11, selfsigned@^1.10.7: version "1.10.11" resolved "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== dependencies: node-forge "^0.10.0" -selfsigned@^1.10.7: - version "1.10.8" - resolved "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz#0d17208b7d12c33f8eac85c41835f27fc3d81a30" - integrity sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w== - dependencies: - node-forge "^0.10.0" - semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -24999,6 +25753,11 @@ space-separated-tokens@^1.0.0: resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== +space-separated-tokens@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" + integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== + spawn-command@^0.0.2-1: version "0.0.2-1" resolved "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" @@ -25793,10 +26552,10 @@ svg-parser@^2.0.2: resolved "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svg-pathdata@^5.0.5: - version "5.0.5" - resolved "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-5.0.5.tgz#65e8d765642ba15fe15434444087d082bc526b29" - integrity sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow== +svg-pathdata@^6.0.3: + version "6.0.3" + resolved "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz#80b0e0283b652ccbafb69ad4f8f73e8d3fbf2cac" + integrity sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw== svgo@^1.0.0, svgo@^1.2.2: version "1.3.2" @@ -26515,6 +27274,11 @@ trough@^1.0.0: resolved "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +trough@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/trough/-/trough-2.0.2.tgz#94a3aa9d5ce379fc561f6244905b3f36b7458d96" + integrity sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w== + tryer@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -26918,6 +27682,19 @@ unified@9.2.0, unified@^9.0.0: trough "^1.0.0" vfile "^4.0.0" +unified@^10.0.0: + version "10.1.0" + resolved "https://registry.npmjs.org/unified/-/unified-10.1.0.tgz#4e65eb38fc2448b1c5ee573a472340f52b9346fe" + integrity sha512-4U3ru/BRXYYhKbwXV6lU6bufLikoAavTwev89H5UxY8enDFaAT2VXmIXYNm6hb5oHPng/EXr77PVyDFcptbk5g== + dependencies: + "@types/unist" "^2.0.0" + bail "^2.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^4.0.0" + trough "^2.0.0" + vfile "^5.0.0" + union-value@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -26964,21 +27741,43 @@ unist-builder@2.0.3, unist-builder@^2.0.0: resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== +unist-builder@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" + integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-generated@^1.0.0: version "1.1.6" resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== +unist-util-generated@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" + integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== + unist-util-is@^4.0.0: version "4.0.3" resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.3.tgz#e8b44db55fc20c43752b3346c116344d45d7c91d" integrity sha512-bTofCFVx0iQM8Jqb1TBDVRIQW03YkD3p66JOd/aCWuqzlLyUtx1ZAGw/u+Zw+SttKvSVcvTiKYbfrtLoLefykw== +unist-util-is@^5.0.0: + version "5.1.1" + resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" + integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== + unist-util-position@^3.0.0: version "3.1.0" resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== +unist-util-position@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.1.tgz#f8484b2da19a897a0180556d160c28633070dbb9" + integrity sha512-mgy/zI9fQ2HlbOtTdr2w9lhVaiFUHWQnZrFF2EUoVOqtAUdzqMtNiD99qA5a1IcjWVR8O6aVYE9u7Z2z1v0SQA== + unist-util-remove-position@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" @@ -27000,6 +27799,13 @@ unist-util-stringify-position@^2.0.0: dependencies: "@types/unist" "^2.0.2" +unist-util-stringify-position@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.0.tgz#d517d2883d74d0daa0b565adc3d10a02b4a8cde9" + integrity sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-visit-parents@1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06" @@ -27013,6 +27819,22 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" +unist-util-visit-parents@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2" + integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + +unist-util-visit-parents@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.0.tgz#44bbc5d25f2411e7dfc5cecff12de43296aa8521" + integrity sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit@2.0.3, unist-util-visit@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" @@ -27022,6 +27844,24 @@ unist-util-visit@2.0.3, unist-util-visit@^2.0.0: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" +unist-util-visit@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b" + integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^4.0.0" + +unist-util-visit@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.0.tgz#f41e407a9e94da31594e6b1c9811c51ab0b3d8f5" + integrity sha512-n7lyhFKJfVZ9MnKtqbsqkQEk5P1KShj0+//V7mAcoI6bpbUjh3C/OG8HVD+pBihfh6Ovl01m8dkcv9HNqYajmQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.0.0" + universal-github-app-jwt@^1.0.1: version "1.1.0" resolved "https://registry.npmjs.org/universal-github-app-jwt/-/universal-github-app-jwt-1.1.0.tgz#0abaa876101cdf1d3e4c546be2768841c0c1b514" @@ -27448,6 +28288,14 @@ vfile-message@^2.0.0: "@types/unist" "^2.0.0" unist-util-stringify-position "^2.0.0" +vfile-message@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/vfile-message/-/vfile-message-3.0.2.tgz#db7eaebe7fecb853010f2ef1664427f52baf8f74" + integrity sha512-UUjZYIOg9lDRwwiBAuezLIsu9KlXntdxwG+nXnjuQAHvBpcX3x0eN8h+I7TkY5nkCXj+cWVp4ZqebtGBvok8ww== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile@^4.0.0: version "4.2.0" resolved "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz#26c78ac92eb70816b01d4565e003b7e65a2a0e01" @@ -27459,6 +28307,16 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" +vfile@^5.0.0: + version "5.1.0" + resolved "https://registry.npmjs.org/vfile/-/vfile-5.1.0.tgz#18e78016f0f71e98d737d40f0fca921dc264a600" + integrity sha512-4o7/DJjEaFPYSh0ckv5kcYkJTHQgCKdL8ozMM1jLAxO9ox95IzveDPXCZp08HamdWq8JXTkClDvfAKaeLQeKtg== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + vinyl-file@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz#b104d9e4409ffa325faadd520642d0a3b488b365" @@ -28482,3 +29340,8 @@ zwitch@^1.0.0: version "1.0.5" resolved "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== + +zwitch@^2.0.0: + version "2.0.2" + resolved "https://registry.npmjs.org/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1" + integrity sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==