diff --git a/.changeset/brown-tips-battle.md b/.changeset/brown-tips-battle.md new file mode 100644 index 0000000000..86a1185cfe --- /dev/null +++ b/.changeset/brown-tips-battle.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Added `@types/minimist` to `devDependencies` diff --git a/.changeset/dirty-coins-invite.md b/.changeset/dirty-coins-invite.md new file mode 100644 index 0000000000..3e35c4a6ca --- /dev/null +++ b/.changeset/dirty-coins-invite.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Remove unused dependencies diff --git a/.changeset/fair-oranges-leave.md b/.changeset/fair-oranges-leave.md new file mode 100644 index 0000000000..43fd97f925 --- /dev/null +++ b/.changeset/fair-oranges-leave.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': minor +--- + +We added a new IconButton component with fixed sizes showcasing a single icon. diff --git a/.changeset/thick-zoos-matter.md b/.changeset/thick-zoos-matter.md new file mode 100644 index 0000000000..641eb30dfe --- /dev/null +++ b/.changeset/thick-zoos-matter.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Remove unused dependencies diff --git a/.changeset/true-papers-visit.md b/.changeset/true-papers-visit.md new file mode 100644 index 0000000000..81b45c632a --- /dev/null +++ b/.changeset/true-papers-visit.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-permission-node': patch +--- + +Deprecated `createPermissionIntegrationRouter` and related types, which has been replaced by `PermissionRegistryService`. For more information, including how to migrate existing plugins, see the [service docs](https://backstage.io/docs/backend-system/core-services/permissions-registry). diff --git a/.changeset/warm-heads-walk.md b/.changeset/warm-heads-walk.md new file mode 100644 index 0000000000..39bd86d0ee --- /dev/null +++ b/.changeset/warm-heads-walk.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': minor +--- + +Added a new ScrollArea component for Canon. diff --git a/canon-docs/src/app/(docs)/components/icon-button/page.mdx b/canon-docs/src/app/(docs)/components/icon-button/page.mdx new file mode 100644 index 0000000000..591ee321eb --- /dev/null +++ b/canon-docs/src/app/(docs)/components/icon-button/page.mdx @@ -0,0 +1,111 @@ +import { PropsTable } from '@/components/PropsTable'; +import { Snippet } from '@/components/Snippet'; +import { Tabs } from '@/components/Tabs'; +import { CodeBlock } from '@/components/CodeBlock'; +import { + IconButtonPreview, + IconButtonSizes, + IconButtonDisabled, + IconButtonResponsive, +} from '@/snippets/icon-button'; +import { iconButtonVariants } from '@/snippets/_snippets'; +import { iconButtonPropDefs } from '../../../../../../packages/canon/src/components/IconButton/IconButton.props'; + +# Icon Button + +A button component with a single icon that can be used to trigger actions. + +} + code={` + + +`} +/> + + + + Usage + Theming + + + +`} + /> + + + We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with + your brand. For additional flexibility, you can use the provided class names for each element listed below. + `} + /> + + + + +## API reference + + + +## Examples + +### Variants + +Here's a view when buttons have different variants. + +} + code={iconButtonVariants} +/> + +### Sizes + +Here's a view when buttons have different sizes. + +} + code={` + + +`} +/> + +### Disabled + +Here's a view when buttons are disabled. + +} + code={``} +/> + +### Responsive + +Here's a view when buttons are responsive. + +} + code={``} +/> diff --git a/canon-docs/src/components/PropsTable/PropsTable.tsx b/canon-docs/src/components/PropsTable/PropsTable.tsx index aa6b9f296e..62917eaeed 100644 --- a/canon-docs/src/components/PropsTable/PropsTable.tsx +++ b/canon-docs/src/components/PropsTable/PropsTable.tsx @@ -19,10 +19,6 @@ export const PropsTable = >({ }) => { const completeData = { ...data, - children: { - values: 'ReactNode', - responsive: false, - }, className: { values: 'string', responsive: false, diff --git a/canon-docs/src/snippets/_snippets.ts b/canon-docs/src/snippets/_snippets.ts index 75ff5056f4..00a9c1462d 100644 --- a/canon-docs/src/snippets/_snippets.ts +++ b/canon-docs/src/snippets/_snippets.ts @@ -38,7 +38,7 @@ export const grid = `import { Grid } from '@backstage/canon'; `; -export const buttonVariants = ` +export const buttonVariants = ` @@ -48,7 +48,13 @@ export const buttonVariants = ` - + +`; + +export const iconButtonVariants = ` + + + `; export const flexFAQ1 = ` diff --git a/canon-docs/src/snippets/icon-button.tsx b/canon-docs/src/snippets/icon-button.tsx new file mode 100644 index 0000000000..2079041456 --- /dev/null +++ b/canon-docs/src/snippets/icon-button.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { IconButton, Flex, ButtonProps, Text } from '../../../packages/canon'; + +export const IconButtonPreview = () => { + return ( + + + + + ); +}; + +export const IconButtonSizes = () => { + return ( + + + + + ); +}; + +export const IconButtonDisabled = () => { + return ; +}; + +export const IconButtonResponsive = () => { + return ( + + ); +}; + +export const IconButtonPlayground = () => { + const variants: string[] = ['primary', 'secondary']; + + return ( + + {variants.map(variant => ( + + {variant} + {['small', 'medium'].map(size => ( + + + + ))} + + ))} + + ); +}; diff --git a/canon-docs/src/utils/data.ts b/canon-docs/src/utils/data.ts index c454b76d71..6aa487d93a 100644 --- a/canon-docs/src/utils/data.ts +++ b/canon-docs/src/utils/data.ts @@ -87,6 +87,11 @@ export const components: Page[] = [ slug: 'icon', status: 'alpha', }, + { + title: 'IconButton', + slug: 'icon-button', + status: 'alpha', + }, { title: 'Input', slug: 'input', diff --git a/docs/backend-system/core-services/permissionsRegistry.md b/docs/backend-system/core-services/permissionsRegistry.md index 4b0b87b894..79d8274986 100644 --- a/docs/backend-system/core-services/permissionsRegistry.md +++ b/docs/backend-system/core-services/permissionsRegistry.md @@ -1,5 +1,5 @@ --- -id: permissions +id: permissions-registry title: Permissions Registry Service sidebar_label: Permissions Registry description: Documentation for the Permissions Registry service diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index 0fe4447ca9..bf97009772 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -450,6 +450,7 @@ export default { 'backend-system/core-services/lifecycle', 'backend-system/core-services/logger', 'backend-system/core-services/permissions', + 'backend-system/core-services/permissions-registry', 'backend-system/core-services/plugin-metadata', 'backend-system/core-services/root-config', 'backend-system/core-services/root-health', diff --git a/packages/backend-app-api/knip-report.md b/packages/backend-app-api/knip-report.md index 5180cb33c8..13b4ec495e 100644 --- a/packages/backend-app-api/knip-report.md +++ b/packages/backend-app-api/knip-report.md @@ -1,49 +1,8 @@ # Knip report -## Unused dependencies (27) - -| Name | Location | Severity | -| :-------------------------------- | :----------- | :------- | -| @backstage/plugin-permission-node | package.json | error | -| @backstage/plugin-auth-node | package.json | error | -| @backstage/config-loader | package.json | error | -| @backstage/cli-common | package.json | error | -| @manypkg/get-packages | package.json | error | -| @backstage/config | package.json | error | -| winston-transport | package.json | error | -| @backstage/types | package.json | error | -| path-to-regexp | package.json | error | -| compression | package.json | error | -| triple-beam | package.json | error | -| node-forge | package.json | error | -| selfsigned | package.json | error | -| minimatch | package.json | error | -| stoppable | package.json | error | -| minimist | package.json | error | -| logform | package.json | error | -| winston | package.json | error | -| cookie | package.json | error | -| helmet | package.json | error | -| lodash | package.json | error | -| morgan | package.json | error | -| luxon | package.json | error | -| cors | package.json | error | -| jose | package.json | error | -| knex | package.json | error | -| uuid | package.json | error | - -## Unused devDependencies (10) +## Unused devDependencies (1) | Name | Location | Severity | | :-------------------------- | :----------- | :------- | | @backstage/backend-defaults | package.json | error | -| @types/compression | package.json | error | -| @types/http-errors | package.json | error | -| @types/node-forge | package.json | error | -| @types/stoppable | package.json | error | -| @types/minimist | package.json | error | -| @types/morgan | package.json | error | -| http-errors | package.json | error | -| supertest | package.json | error | -| msw | package.json | error | diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index c50e9155a7..5390261b9a 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -47,48 +47,12 @@ }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", - "@backstage/cli-common": "workspace:^", - "@backstage/config": "workspace:^", - "@backstage/config-loader": "workspace:^", - "@backstage/errors": "workspace:^", - "@backstage/plugin-auth-node": "workspace:^", - "@backstage/plugin-permission-node": "workspace:^", - "@backstage/types": "workspace:^", - "@manypkg/get-packages": "^1.1.3", - "compression": "^1.7.4", - "cookie": "^0.7.0", - "cors": "^2.8.5", - "helmet": "^6.0.0", - "jose": "^5.0.0", - "knex": "^3.0.0", - "lodash": "^4.17.21", - "logform": "^2.3.2", - "luxon": "^3.0.0", - "minimatch": "^9.0.0", - "minimist": "^1.2.5", - "morgan": "^1.10.0", - "node-forge": "^1.3.1", - "path-to-regexp": "^8.0.0", - "selfsigned": "^2.0.0", - "stoppable": "^1.1.0", - "triple-beam": "^1.4.1", - "uuid": "^11.0.0", - "winston": "^3.2.1", - "winston-transport": "^4.5.0" + "@backstage/errors": "workspace:^" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", "@backstage/backend-test-utils": "workspace:^", - "@backstage/cli": "workspace:^", - "@types/compression": "^1.7.0", - "@types/http-errors": "^2.0.0", - "@types/minimist": "^1.2.0", - "@types/morgan": "^1.9.0", - "@types/node-forge": "^1.3.0", - "@types/stoppable": "^1.1.0", - "http-errors": "^2.0.0", - "msw": "^1.0.0", - "supertest": "^7.0.0" + "@backstage/cli": "workspace:^" }, "configSchema": "config.d.ts" } diff --git a/packages/backend-defaults/knip-report.md b/packages/backend-defaults/knip-report.md index 22105d3219..169963316a 100644 --- a/packages/backend-defaults/knip-report.md +++ b/packages/backend-defaults/knip-report.md @@ -1,21 +1,11 @@ # Knip report -## Unused dependencies (6) +## Unused dependencies (2) -| Name | Location | Severity | -| :-------------------- | :----------- | :------- | -| @backstage/cli-common | package.json | error | -| @azure/identity | package.json | error | -| better-sqlite3 | package.json | error | -| isomorphic-git | package.json | error | -| minimist | package.json | error | -| mysql2 | package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :--------------- | :----------- | :------- | -| @types/stoppable | package.json | error | +| Name | Location | Severity | +| :------------- | :----------- | :------- | +| better-sqlite3 | package.json | error | +| mysql2 | package.json | error | ## Referenced optional peerDependencies (1) diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 3531b033bc..3a256f5985 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -127,12 +127,10 @@ "@aws-sdk/client-s3": "^3.350.0", "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/types": "^3.347.0", - "@azure/identity": "^4.0.0", "@azure/storage-blob": "^12.5.0", "@backstage/backend-app-api": "workspace:^", "@backstage/backend-dev-utils": "workspace:^", "@backstage/backend-plugin-api": "workspace:^", - "@backstage/cli-common": "workspace:^", "@backstage/cli-node": "workspace:^", "@backstage/config": "workspace:^", "@backstage/config-loader": "workspace:^", @@ -164,7 +162,6 @@ "fs-extra": "^11.2.0", "git-url-parse": "^15.0.0", "helmet": "^6.0.0", - "isomorphic-git": "^1.23.0", "jose": "^5.0.0", "keyv": "^5.2.1", "knex": "^3.0.0", @@ -172,7 +169,6 @@ "logform": "^2.3.2", "luxon": "^3.0.0", "minimatch": "^9.0.0", - "minimist": "^1.2.5", "mysql2": "^3.0.0", "node-fetch": "^2.7.0", "node-forge": "^1.3.1", @@ -201,11 +197,11 @@ "@google-cloud/cloud-sql-connector": "^1.4.0", "@types/archiver": "^6.0.0", "@types/base64-stream": "^1.0.2", + "@types/compression": "^1.7.5", "@types/concat-stream": "^2.0.0", "@types/http-errors": "^2.0.0", "@types/node-forge": "^1.3.0", "@types/pg-format": "^1.0.5", - "@types/stoppable": "^1.1.0", "@types/yauzl": "^2.10.0", "aws-sdk-client-mock": "^4.0.0", "http-errors": "^2.0.0", diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.test.ts index 0c545b898c..0adbc3381f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GiteaUrlReader.test.ts @@ -35,14 +35,6 @@ const treeResponseFactory = DefaultReadTreeResponseFactory.create({ config: new ConfigReader({}), }); -jest.mock('./git', () => ({ - Git: { - fromAuth: () => ({ - clone: jest.fn(() => Promise.resolve({})), - }), - }, -})); - const giteaProcessor = new GiteaUrlReader( new GiteaIntegration( readGiteaConfig( diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.test.ts index c5cdaa9928..37dab25883 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/HarnessUrlReader.test.ts @@ -35,14 +35,6 @@ const treeResponseFactory = DefaultReadTreeResponseFactory.create({ config: new ConfigReader({}), }); -jest.mock('./git', () => ({ - Git: { - fromAuth: () => ({ - clone: jest.fn(() => Promise.resolve({})), - }), - }, -})); - const harnessProcessor = new HarnessUrlReader( new HarnessIntegration( readHarnessConfig( diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/git.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/git.ts deleted file mode 100644 index 119d4f64bd..0000000000 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/git.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2024 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 fs from 'fs-extra'; -import isomorphicGit, { ProgressCallback, AuthCallback } from 'isomorphic-git'; -import http from 'isomorphic-git/http/node'; -import { LoggerService } from '@backstage/backend-plugin-api'; - -/** - * Configure static credential for authentication - * - * @public - */ -export type StaticAuthOptions = { - username?: string; - password?: string; - token?: string; - logger?: LoggerService; -}; - -/** - * Configure an authentication callback that can provide credentials on demand - * - * @public - */ -export type AuthCallbackOptions = { - onAuth: AuthCallback; - logger?: LoggerService; -}; - -function isAuthCallbackOptions( - options: StaticAuthOptions | AuthCallbackOptions, -): options is AuthCallbackOptions { - return 'onAuth' in options; -} - -/* -provider username password -Azure 'notempty' token -Bitbucket Cloud 'x-token-auth' token -Bitbucket Server username password or token -GitHub 'x-access-token' token -GitLab 'oauth2' token - -From : https://isomorphic-git.org/docs/en/onAuth with fix for GitHub - -Or token provided as `token` for Bearer auth header -instead of Basic Auth (e.g., Bitbucket Server). -*/ -/** - * A convenience wrapper around the `isomorphic-git` library. - * - * @public - */ -export class Git { - private readonly headers: { - [x: string]: string; - }; - - private constructor( - private readonly config: { - onAuth: AuthCallback; - token?: string; - logger?: LoggerService; - }, - ) { - this.onAuth = config.onAuth; - - this.headers = { - 'user-agent': 'git/@isomorphic-git', - ...(config.token ? { Authorization: `Bearer ${config.token}` } : {}), - }; - } - - /** https://isomorphic-git.org/docs/en/clone */ - async clone(options: { - url: string; - dir: string; - ref?: string; - depth?: number; - noCheckout?: boolean; - }): Promise { - const { url, dir, ref, depth, noCheckout } = options; - this.config.logger?.info(`Cloning repo {dir=${dir},url=${url}}`); - - try { - return await isomorphicGit.clone({ - fs, - http, - url, - dir, - ref, - singleBranch: true, - depth: depth ?? 1, - noCheckout, - onProgress: this.onProgressHandler(), - headers: this.headers, - onAuth: this.onAuth, - }); - } catch (ex) { - this.config.logger?.error(`Failed to clone repo {dir=${dir},url=${url}}`); - if (ex.data) { - throw new Error(`${ex.message} {data=${JSON.stringify(ex.data)}}`); - } - throw ex; - } - } - - private onAuth: AuthCallback; - - private onProgressHandler = (): ProgressCallback => { - let currentPhase = ''; - - return event => { - if (currentPhase !== event.phase) { - currentPhase = event.phase; - this.config.logger?.info(event.phase); - } - const total = event.total - ? `${Math.round((event.loaded / event.total) * 100)}%` - : event.loaded; - this.config.logger?.debug(`status={${event.phase},total={${total}}}`); - }; - }; - - static fromAuth = (options: StaticAuthOptions | AuthCallbackOptions) => { - if (isAuthCallbackOptions(options)) { - const { onAuth, logger } = options; - return new Git({ onAuth, logger }); - } - - const { username, password, token, logger } = options; - return new Git({ onAuth: () => ({ username, password }), token, logger }); - }; -} diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index e9527d4c35..1881d84e3c 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -12,6 +12,7 @@ import { default as React_2 } from 'react'; import * as React_3 from 'react'; import { ReactNode } from 'react'; import { RefAttributes } from 'react'; +import { ScrollArea as ScrollArea_2 } from '@base-ui-components/react/scroll-area'; import { Tooltip as Tooltip_2 } from '@base-ui-components/react/tooltip'; // @public (undocumented) @@ -590,6 +591,40 @@ export type HeightProps = GetPropDefTypes; // @public (undocumented) export const Icon: (props: IconProps) => React_2.JSX.Element; +// @public (undocumented) +export const IconButton: React_2.ForwardRefExoticComponent< + IconButtonProps & React_2.RefAttributes +>; + +// @public (undocumented) +export type IconButtonOwnProps = GetPropDefTypes; + +// @public (undocumented) +export const iconButtonPropDefs: { + variant: { + type: 'enum'; + values: ('primary' | 'secondary')[]; + className: string; + default: 'primary'; + responsive: true; + }; + size: { + type: 'enum'; + values: ('small' | 'medium')[]; + className: string; + default: 'medium'; + responsive: true; + }; +}; + +// @public +export interface IconButtonProps + extends Omit, 'children'> { + icon: IconNames; + size?: IconButtonOwnProps['size']; + variant?: IconButtonOwnProps['variant']; +} + // @public (undocumented) export const IconContext: Context; @@ -828,6 +863,38 @@ export type ResponsivePropDef = RegularPropDef & { responsive: true; }; +// @public (undocumented) +export const ScrollArea: { + Root: React_2.ForwardRefExoticComponent< + Omit< + ScrollArea_2.Root.Props & React_2.RefAttributes, + 'ref' + > & + React_2.RefAttributes + >; + Viewport: React_2.ForwardRefExoticComponent< + Omit< + ScrollArea_2.Viewport.Props & React_2.RefAttributes, + 'ref' + > & + React_2.RefAttributes + >; + Scrollbar: React_2.ForwardRefExoticComponent< + Omit< + ScrollArea_2.Scrollbar.Props & React_2.RefAttributes, + 'ref' + > & + React_2.RefAttributes + >; + Thumb: React_2.ForwardRefExoticComponent< + Omit< + ScrollArea_2.Thumb.Props & React_2.RefAttributes, + 'ref' + > & + React_2.RefAttributes + >; +}; + // @public (undocumented) export type Space = | '0.5' diff --git a/packages/canon/src/components/IconButton/IconButton.props.ts b/packages/canon/src/components/IconButton/IconButton.props.ts new file mode 100644 index 0000000000..e584997ef5 --- /dev/null +++ b/packages/canon/src/components/IconButton/IconButton.props.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2025 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 type { PropDef, GetPropDefTypes } from '../../props/prop-def'; + +/** @public */ +export const iconButtonPropDefs = { + variant: { + type: 'enum', + values: ['primary', 'secondary'], + className: 'canon-Button--variant', + default: 'primary', + responsive: true, + }, + size: { + type: 'enum', + values: ['small', 'medium'], + className: 'canon-Button--size', + default: 'medium', + responsive: true, + }, +} satisfies { + variant: PropDef<'primary' | 'secondary'>; + size: PropDef<'small' | 'medium'>; +}; + +/** @public */ +export type IconButtonOwnProps = GetPropDefTypes; diff --git a/packages/canon/src/components/IconButton/IconButton.stories.tsx b/packages/canon/src/components/IconButton/IconButton.stories.tsx new file mode 100644 index 0000000000..74e058430c --- /dev/null +++ b/packages/canon/src/components/IconButton/IconButton.stories.tsx @@ -0,0 +1,140 @@ +/* + * Copyright 2024 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 type { Meta, StoryObj } from '@storybook/react'; +import { IconButton } from './IconButton'; +import { Flex } from '../Flex'; +import { Text } from '../Text'; +import { IconButtonProps } from './types'; + +const meta = { + title: 'Components/IconButton', + component: IconButton, + argTypes: { + size: { + control: 'select', + options: ['small', 'medium'], + }, + variant: { + control: 'select', + options: ['primary', 'secondary'], + }, + }, + args: { + size: 'medium', + variant: 'primary', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Variants: Story = { + args: { + icon: 'cloud', + }, + parameters: { + argTypes: { + variant: { + control: false, + }, + }, + }, + render: args => ( + + + + + ), +}; + +export const Sizes: Story = { + args: { + icon: 'cloud', + }, + render: args => ( + + + + + ), +}; + +export const Disabled: Story = { + args: { + icon: 'cloud', + disabled: true, + }, + render: args => ( + + + + + ), +}; + +export const Responsive: Story = { + args: { + icon: 'cloud', + variant: { + initial: 'primary', + sm: 'secondary', + }, + size: { + xs: 'small', + sm: 'medium', + }, + }, +}; + +const variants: string[] = ['primary', 'secondary']; + +export const Playground: Story = { + args: { + icon: 'cloud', + }, + render: args => ( + + {variants.map(variant => ( + + {variant} + {['small', 'medium'].map(size => ( + + + + + + ))} + + ))} + + ), +}; diff --git a/packages/canon/src/components/IconButton/IconButton.tsx b/packages/canon/src/components/IconButton/IconButton.tsx new file mode 100644 index 0000000000..0f28ed963f --- /dev/null +++ b/packages/canon/src/components/IconButton/IconButton.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2024 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, { forwardRef } from 'react'; +import { Icon } from '../Icon'; +import clsx from 'clsx'; +import { useResponsiveValue } from '../../hooks/useResponsiveValue'; + +import type { IconButtonProps } from './types'; + +/** @public */ +export const IconButton = forwardRef( + (props: IconButtonProps, ref) => { + const { + size = 'medium', + variant = 'primary', + icon, + className, + style, + ...rest + } = props; + + const responsiveSize = useResponsiveValue(size); + const responsiveVariant = useResponsiveValue(variant); + + return ( + + ); + }, +); + +export default IconButton; diff --git a/packages/canon/src/components/IconButton/index.tsx b/packages/canon/src/components/IconButton/index.tsx new file mode 100644 index 0000000000..5f9943557e --- /dev/null +++ b/packages/canon/src/components/IconButton/index.tsx @@ -0,0 +1,20 @@ +/* + * Copyright 2024 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 { IconButton } from './IconButton'; +export type { IconButtonProps } from './types'; +export { iconButtonPropDefs } from './IconButton.props'; +export type { IconButtonOwnProps } from './IconButton.props'; diff --git a/packages/canon/src/components/IconButton/styles.css b/packages/canon/src/components/IconButton/styles.css new file mode 100644 index 0000000000..aa4c2d0523 --- /dev/null +++ b/packages/canon/src/components/IconButton/styles.css @@ -0,0 +1,105 @@ +/* + * Copyright 2024 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. + */ + +.canon-IconButton { + border: none; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; + font-family: var(--canon-font-regular); + font-weight: var(--canon-font-weight-bold); + padding: 0; + cursor: pointer; + border-radius: var(--canon-radius-2); + gap: var(--canon-space-1_5); + + &:disabled { + cursor: not-allowed; + } +} + +.canon-IconButton--variant-primary { + background-color: var(--canon-bg-solid); + color: var(--canon-fg-solid); + transition: background-color 150ms ease, box-shadow 150ms ease; + + &:hover { + background-color: var(--canon-bg-solid-hover); + } + + &:active { + background-color: var(--canon-bg-solid-pressed); + } + + &:focus-visible { + outline: 2px solid var(--canon-ring); + outline-offset: 2px; + } + + &:disabled { + background-color: var(--canon-bg-solid-disabled); + color: var(--canon-fg-solid-disabled); + } +} + +.canon-IconButton--variant-secondary { + background-color: var(--canon-bg-surface-1); + box-shadow: inset 0 0 0 1px var(--canon-border); + color: var(--canon-fg-primary); + transition: box-shadow 150ms ease; + + &:hover { + box-shadow: inset 0 0 0 1px var(--canon-border-hover); + } + + &:active { + box-shadow: inset 0 0 0 1px var(--canon-border-pressed); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--canon-ring); + } + + &:disabled { + box-shadow: inset 0 0 0 1px var(--canon-border-disabled); + color: var(--canon-fg-disabled); + } +} + +.canon-IconButton--size-medium { + font-size: var(--canon-font-size-4); + height: 40px; + width: 40px; +} + +.canon-IconButton--size-small { + font-size: var(--canon-font-size-3); + height: 32px; + width: 32px; +} + +.canon-IconButton--size-small .canon-IconButton--icon { + width: 1rem; + height: 1rem; +} + +.canon-IconButton--size-medium .canon-IconButton--icon { + width: 1.5rem; + height: 1.5rem; +} diff --git a/packages/canon/src/components/IconButton/types.ts b/packages/canon/src/components/IconButton/types.ts new file mode 100644 index 0000000000..90505d3352 --- /dev/null +++ b/packages/canon/src/components/IconButton/types.ts @@ -0,0 +1,42 @@ +/* + * Copyright 2024 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 { IconNames } from '../Icon'; +import type { IconButtonOwnProps } from './IconButton.props'; + +/** + * Properties for {@link IconButton} + * + * @public + */ +export interface IconButtonProps + extends Omit, 'children'> { + /** + * The size of the button + * @defaultValue 'medium' + */ + size?: IconButtonOwnProps['size']; + + /** + * The visual variant of the button + * @defaultValue 'primary' + */ + variant?: IconButtonOwnProps['variant']; + + /** + * Icon to display at the start of the button + */ + icon: IconNames; +} diff --git a/packages/canon/src/components/ScrollArea/ScrollArea.stories.tsx b/packages/canon/src/components/ScrollArea/ScrollArea.stories.tsx new file mode 100644 index 0000000000..3caf39a29e --- /dev/null +++ b/packages/canon/src/components/ScrollArea/ScrollArea.stories.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2024 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 type { Meta, StoryObj } from '@storybook/react'; +import { ScrollArea } from './ScrollArea'; +import { Text } from '../Text/Text'; + +const meta = { + title: 'Components/ScrollArea', + component: ScrollArea.Root, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => ( + + +
+ + Vernacular architecture is building done outside any academic + tradition, and without professional guidance. It is not a particular + architectural movement or style, but rather a broad category, + encompassing a wide range and variety of building types, with + differing methods of construction, from around the world, both + historical and extant and classical and modern. Vernacular + architecture constitutes 95% of the world's built environment, as + estimated in 1995 by Amos Rapoport, as measured against the small + percentage of new buildings every year designed by architects and + built by engineers. + + + This type of architecture usually serves immediate, local needs, is + constrained by the materials available in its particular region and + reflects local traditions and cultural practices. The study of + vernacular architecture does not examine formally schooled + architects, but instead that of the design skills and tradition of + local builders, who were rarely given any attribution for the work. + More recently, vernacular architecture has been examined by + designers and the building industry in an effort to be more energy + conscious with contemporary design and construction—part of a + broader interest in sustainable design. + +
+
+ + + +
+ ), +}; diff --git a/packages/canon/src/components/ScrollArea/ScrollArea.styles.css b/packages/canon/src/components/ScrollArea/ScrollArea.styles.css new file mode 100644 index 0000000000..1d1c25e9d0 --- /dev/null +++ b/packages/canon/src/components/ScrollArea/ScrollArea.styles.css @@ -0,0 +1,67 @@ +/* + * Copyright 2024 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. + */ + +.canon-ScrollAreaRoot { + box-sizing: border-box; + width: 24rem; + height: 8.5rem; + max-width: calc(100vw - 8rem); +} + +.canon-ScrollAreaViewport { + height: 100%; + overscroll-behavior: contain; +} + +.canon-ScrollAreaContent { + display: flex; + flex-direction: column; + gap: 1rem; + padding-block: 0.75rem; + padding-left: 1rem; + padding-right: 1.5rem; +} + +.canon-ScrollAreaScrollbar { + display: flex; + justify-content: center; + background-color: var(--canon-scrollbar); + width: 0.25rem; + border-radius: 0.375rem; + margin: 0.5rem; + opacity: 0; + transition: opacity 150ms 300ms; + + &[data-hovering], + &[data-scrolling] { + opacity: 1; + transition-duration: 75ms; + transition-delay: 0ms; + } + + &::before { + content: ''; + position: absolute; + width: 1.25rem; + height: 100%; + } +} + +.canon-ScrollAreaThumb { + width: 100%; + border-radius: inherit; + background-color: var(--canon-scrollbar-thumb); +} diff --git a/packages/canon/src/components/ScrollArea/ScrollArea.tsx b/packages/canon/src/components/ScrollArea/ScrollArea.tsx new file mode 100644 index 0000000000..1c0036d005 --- /dev/null +++ b/packages/canon/src/components/ScrollArea/ScrollArea.tsx @@ -0,0 +1,75 @@ +/* + * Copyright 2024 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 { ScrollArea as ScrollAreaPrimitive } from '@base-ui-components/react/scroll-area'; +import clsx from 'clsx'; + +const ScrollAreaRoot = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ScrollAreaRoot.displayName = ScrollAreaPrimitive.Root.displayName; + +const ScrollAreaViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ScrollAreaViewport.displayName = ScrollAreaPrimitive.Viewport.displayName; + +const ScrollAreaScrollbar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ScrollAreaScrollbar.displayName = ScrollAreaPrimitive.Scrollbar.displayName; + +const ScrollAreaThumb = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +ScrollAreaThumb.displayName = ScrollAreaPrimitive.Thumb.displayName; + +/** @public */ +export const ScrollArea = { + Root: ScrollAreaRoot, + Viewport: ScrollAreaViewport, + Scrollbar: ScrollAreaScrollbar, + Thumb: ScrollAreaThumb, +}; diff --git a/packages/canon/src/components/ScrollArea/index.ts b/packages/canon/src/components/ScrollArea/index.ts new file mode 100644 index 0000000000..20dab2d8ec --- /dev/null +++ b/packages/canon/src/components/ScrollArea/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2024 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 * from './ScrollArea'; diff --git a/packages/canon/src/css/components.css b/packages/canon/src/css/components.css index c515762716..b4a466abeb 100644 --- a/packages/canon/src/css/components.css +++ b/packages/canon/src/css/components.css @@ -24,7 +24,9 @@ @import '../components/Table/styles.css'; @import '../components/Text/styles.css'; @import '../components/Heading/styles.css'; +@import '../components/IconButton/styles.css'; @import '../components/Input/Input.styles.css'; @import '../components/Field/Field.styles.css'; @import '../components/Link/styles.css'; @import '../components/Tooltip/Tooltip.styles.css'; +@import '../components/ScrollArea/ScrollArea.styles.css'; diff --git a/packages/canon/src/css/core.css b/packages/canon/src/css/core.css index 8c7863953a..8efb066b70 100644 --- a/packages/canon/src/css/core.css +++ b/packages/canon/src/css/core.css @@ -109,8 +109,10 @@ --canon-border-warning: #e36d05; --canon-border-success: #53db83; - /* Ring Colors */ + /* Special Colors */ --canon-ring: #1f5493; + --canon-scrollbar: #a0a0a03b; + --canon-scrollbar-thumb: #a0a0a0; } /* Dark theme tokens */ @@ -153,4 +155,9 @@ --canon-border-danger: #f87a7a; --canon-border-warning: #e36d05; --canon-border-success: #53db83; + + /* Special Colors */ + --canon-ring: #1f5493; + --canon-scrollbar: #3636363a; + --canon-scrollbar-thumb: #575757; } diff --git a/packages/canon/src/index.ts b/packages/canon/src/index.ts index 0fae261531..ff60e9b22c 100644 --- a/packages/canon/src/index.ts +++ b/packages/canon/src/index.ts @@ -34,11 +34,13 @@ export * from './components/Heading'; // UI components export * from './components/Button'; export * from './components/Icon'; +export * from './components/IconButton'; export * from './components/Checkbox'; export * from './components/Table'; export * from './components/Input'; export * from './components/Field'; export * from './components/Tooltip'; +export * from './components/ScrollArea'; // Types export * from './types'; diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index 37d4e94e44..1e2ebf401f 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -56,6 +56,7 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/json-schema-merge-allof": "^0.6.0", + "@types/minimist": "^1.2.5", "msw": "^1.0.0", "zen-observable": "^0.10.0" } diff --git a/plugins/permission-node/report.api.md b/plugins/permission-node/report.api.md index fca13ce5f0..8c743a0f6c 100644 --- a/plugins/permission-node/report.api.md +++ b/plugins/permission-node/report.api.md @@ -138,7 +138,7 @@ export function createConditionTransformer< TRules extends PermissionRule[], >(permissionRules: [...TRules]): ConditionTransformer; -// @public +// @public @deprecated export function createPermissionIntegrationRouter< TResourceType1 extends string, TResource1, @@ -177,7 +177,7 @@ export function createPermissionIntegrationRouter< ): PermissionRuleset; }; -// @public +// @public @deprecated export type CreatePermissionIntegrationRouterResourceOptions< TResourceType extends string, TResource, @@ -266,7 +266,7 @@ export type MetadataResponse = MetadataResponse_2; // @public @deprecated export type MetadataResponseSerializedRule = MetadataResponseSerializedRule_2; -// @public +// @public @deprecated export type PermissionIntegrationRouterOptions< TResourceType1 extends string = string, TResource1 = any, diff --git a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts index b215044ed8..cf68af3a3e 100644 --- a/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts +++ b/plugins/permission-node/src/integration/createPermissionIntegrationRouter.ts @@ -201,6 +201,7 @@ export function createConditionAuthorizer( * for a particular resource type. * * @public + * @deprecated {@link createPermissionIntegrationRouter} is deprecated */ export type CreatePermissionIntegrationRouterResourceOptions< TResourceType extends string, @@ -223,6 +224,7 @@ export type CreatePermissionIntegrationRouterResourceOptions< * permissions and rules from multiple resource types. * * @public + * @deprecated {@link createPermissionIntegrationRouter} is deprecated */ export type PermissionIntegrationRouterOptions< TResourceType1 extends string = string, @@ -410,6 +412,7 @@ class PermissionIntegrationMetadataStore { * need to be evaluated. * * @public + * @deprecated use `PermissionRegistryService` instead, see {@link https://backstage.io/docs/backend-system/core-services/permissions-registry#migrating-from-createpermissionintegrationrouter | the migration section in the service docs} for more details. */ export function createPermissionIntegrationRouter< TResourceType1 extends string, diff --git a/yarn.lock b/yarn.lock index 30ce7647b2..27ce79aa3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3464,43 +3464,7 @@ __metadata: "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" - "@backstage/cli-common": "workspace:^" - "@backstage/config": "workspace:^" - "@backstage/config-loader": "workspace:^" "@backstage/errors": "workspace:^" - "@backstage/plugin-auth-node": "workspace:^" - "@backstage/plugin-permission-node": "workspace:^" - "@backstage/types": "workspace:^" - "@manypkg/get-packages": ^1.1.3 - "@types/compression": ^1.7.0 - "@types/http-errors": ^2.0.0 - "@types/minimist": ^1.2.0 - "@types/morgan": ^1.9.0 - "@types/node-forge": ^1.3.0 - "@types/stoppable": ^1.1.0 - compression: ^1.7.4 - cookie: ^0.7.0 - cors: ^2.8.5 - helmet: ^6.0.0 - http-errors: ^2.0.0 - jose: ^5.0.0 - knex: ^3.0.0 - lodash: ^4.17.21 - logform: ^2.3.2 - luxon: ^3.0.0 - minimatch: ^9.0.0 - minimist: ^1.2.5 - morgan: ^1.10.0 - msw: ^1.0.0 - node-forge: ^1.3.1 - path-to-regexp: ^8.0.0 - selfsigned: ^2.0.0 - stoppable: ^1.1.0 - supertest: ^7.0.0 - triple-beam: ^1.4.1 - uuid: ^11.0.0 - winston: ^3.2.1 - winston-transport: ^4.5.0 languageName: unknown linkType: soft @@ -3591,14 +3555,12 @@ __metadata: "@aws-sdk/credential-providers": ^3.350.0 "@aws-sdk/types": ^3.347.0 "@aws-sdk/util-stream-node": ^3.350.0 - "@azure/identity": ^4.0.0 "@azure/storage-blob": ^12.5.0 "@backstage/backend-app-api": "workspace:^" "@backstage/backend-dev-utils": "workspace:^" "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" - "@backstage/cli-common": "workspace:^" "@backstage/cli-node": "workspace:^" "@backstage/config": "workspace:^" "@backstage/config-loader": "workspace:^" @@ -3618,13 +3580,13 @@ __metadata: "@opentelemetry/api": ^1.9.0 "@types/archiver": ^6.0.0 "@types/base64-stream": ^1.0.2 + "@types/compression": ^1.7.5 "@types/concat-stream": ^2.0.0 "@types/cors": ^2.8.6 "@types/express": ^4.17.6 "@types/http-errors": ^2.0.0 "@types/node-forge": ^1.3.0 "@types/pg-format": ^1.0.5 - "@types/stoppable": ^1.1.0 "@types/yauzl": ^2.10.0 archiver: ^7.0.0 aws-sdk-client-mock: ^4.0.0 @@ -3641,7 +3603,6 @@ __metadata: git-url-parse: ^15.0.0 helmet: ^6.0.0 http-errors: ^2.0.0 - isomorphic-git: ^1.23.0 jose: ^5.0.0 keyv: ^5.2.1 knex: ^3.0.0 @@ -3649,7 +3610,6 @@ __metadata: logform: ^2.3.2 luxon: ^3.0.0 minimatch: ^9.0.0 - minimist: ^1.2.5 msw: ^1.0.0 mysql2: ^3.0.0 node-fetch: ^2.7.0 @@ -4150,6 +4110,7 @@ __metadata: "@backstage/types": "workspace:^" "@types/json-schema": ^7.0.6 "@types/json-schema-merge-allof": ^0.6.0 + "@types/minimist": ^1.2.5 ajv: ^8.10.0 chokidar: ^3.5.2 fs-extra: ^11.2.0 @@ -19535,7 +19496,7 @@ __metadata: languageName: node linkType: hard -"@types/compression@npm:^1.7.0": +"@types/compression@npm:^1.7.5": version: 1.7.5 resolution: "@types/compression@npm:1.7.5" dependencies: @@ -20253,22 +20214,13 @@ __metadata: languageName: node linkType: hard -"@types/minimist@npm:^1.2.0": +"@types/minimist@npm:^1.2.5": version: 1.2.5 resolution: "@types/minimist@npm:1.2.5" checksum: 477047b606005058ab0263c4f58097136268007f320003c348794f74adedc3166ffc47c80ec3e94687787f2ab7f4e72c468223946e79892cf0fd9e25e9970a90 languageName: node linkType: hard -"@types/morgan@npm:^1.9.0": - version: 1.9.9 - resolution: "@types/morgan@npm:1.9.9" - dependencies: - "@types/node": "*" - checksum: 54bcb432f6ddb82b94bc1970204bedb3465a9afdcced6c2c6b481cf5f276266663ba3edc2b728b0118aa9720bfe5d8561c0259daaad6b027017e35936b107db0 - languageName: node - linkType: hard - "@types/ms@npm:*": version: 0.7.31 resolution: "@types/ms@npm:0.7.31" @@ -20920,15 +20872,6 @@ __metadata: languageName: node linkType: hard -"@types/stoppable@npm:^1.1.0": - version: 1.1.3 - resolution: "@types/stoppable@npm:1.1.3" - dependencies: - "@types/node": "*" - checksum: 53cbe08da33d2babb4ee98fe123c1e08bc5a26f547a2eaeac7c279743bbee5f9b49c0772db6a106471a07092916deb9bb7e0632fd502585d45d9c398f036938d - languageName: node - linkType: hard - "@types/stream-buffers@npm:^3.0.3": version: 3.0.7 resolution: "@types/stream-buffers@npm:3.0.7"