Merge branch 'backstage:master' into stack-overflow-search-highlight-fix
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend-module-github': minor
|
||||
---
|
||||
|
||||
Allow to force the creation of a pull request from a forked repository
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Upgrade jest
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-github': patch
|
||||
---
|
||||
|
||||
Decreased number of teams fetched by GraphQL Query responsible for fetching Teams and Members in organization, due to timeouts when running against big organizations
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@techdocs/cli': patch
|
||||
---
|
||||
|
||||
fix: mkdocs parameter casing
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-app-api': patch
|
||||
---
|
||||
|
||||
The default `ComponentsApi` implementation now uses the `ComponentRef` ID as the component key, rather than the reference instance. This fixes a bug where duplicate installations of `@backstage/frontend-plugin-api` would break the app.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/frontend-plugin-api': patch
|
||||
---
|
||||
|
||||
App component extensions are no longer wrapped in an `ExtensionBoundary`, allowing them to inherit the outer context instead.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/integration': minor
|
||||
'@backstage/backend-common': patch
|
||||
---
|
||||
|
||||
Fix rate limit detection by looking for HTTP status code 429 and updating the header `x-ratelimit-remaining` to look for in case of a 403 code is returned
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-backend-module-github': minor
|
||||
---
|
||||
|
||||
Prevent Entity Providers from eliminating Users and Groups from the DB when the synchronisation fails
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/cli': patch
|
||||
---
|
||||
|
||||
Fixed an issue that would cause an invalid `__backstage-autodetected-plugins__.js` to be written when using experimental module discovery.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'@backstage/plugin-scaffolder-backend': patch
|
||||
'@backstage/plugin-scaffolder-node': patch
|
||||
---
|
||||
|
||||
Add option to configure nunjucks with the `trimBlocks` and `lstripBlocks` options in the fetch:template action
|
||||
@@ -21,9 +21,9 @@ To switch a project to React 18, there are generally three changes that need to
|
||||
// highlight-remove-next-line
|
||||
"@types/react": "^17",
|
||||
// highlight-remove-next-line
|
||||
"@types/react": "^17",
|
||||
"@types/react-dom": "^17",
|
||||
// highlight-add-next-line
|
||||
"@types/react-dom": "^18",
|
||||
"@types/react": "^18",
|
||||
// highlight-add-next-line
|
||||
"@types/react-dom": "^18",
|
||||
},
|
||||
|
||||
@@ -277,7 +277,7 @@ module.exports = {
|
||||
to: 'https://developer.spotify.com/',
|
||||
},
|
||||
{
|
||||
label: 'Github',
|
||||
label: 'GitHub',
|
||||
to: 'https://github.com/backstage/',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -36,11 +36,6 @@ const Community = () => {
|
||||
label: 'Community newsletter',
|
||||
link: 'https://info.backstage.spotify.com/newsletter_subscribe',
|
||||
},
|
||||
{
|
||||
content: 'Join the',
|
||||
label: 'Twitter community',
|
||||
link: 'https://twitter.com/i/communities/1494019781716062215',
|
||||
},
|
||||
];
|
||||
|
||||
const officialInitiatives: ICollectionItem[] = [
|
||||
@@ -58,45 +53,11 @@ const Community = () => {
|
||||
link: 'https://info.backstage.spotify.com/newsletter_subscribe',
|
||||
label: 'Subscribe',
|
||||
},
|
||||
{
|
||||
title: 'Contributor Spotlight',
|
||||
content:
|
||||
"A recognition for valuable community work. Nominate contributing members for their efforts! We'll put them in the spotlight ❤️",
|
||||
link: '/nominate',
|
||||
label: 'Nominate now',
|
||||
},
|
||||
];
|
||||
|
||||
const communityInitiatives: ICollectionItem[] = [
|
||||
{
|
||||
title: 'Open Mic Meetup',
|
||||
content: (
|
||||
<>
|
||||
A casual get together of Backstage users sharing their experiences and
|
||||
helping each other. Hosted by{' '}
|
||||
<Link to="https://roadie.io/">Roadie.io</Link> and{' '}
|
||||
<Link to="https://frontside.com/">Frontside Software</Link>.
|
||||
</>
|
||||
),
|
||||
link: 'https://backstage-openmic.com/',
|
||||
label: 'Learn more',
|
||||
},
|
||||
{
|
||||
title: 'Backstage Weekly Newsletter',
|
||||
content: (
|
||||
<>
|
||||
A weekly newsletter with news, updates and things community from your
|
||||
friends at <Link to="https://roadie.io/">Roadie.io</Link>.
|
||||
</>
|
||||
),
|
||||
link: 'https://roadie.io/backstage-weekly/',
|
||||
label: 'Learn more',
|
||||
},
|
||||
];
|
||||
|
||||
const trainingNCertifications: ICollectionItem[] = [
|
||||
{
|
||||
title: 'Open Mic Meetup',
|
||||
title: 'Introduction to Backstage: Developer Portals Made Easy (LFS142x)',
|
||||
content:
|
||||
'This is a course produced and curated by the Linux Foundation. This course introduces you to Backstage and how to get started with the project.',
|
||||
link: 'https://training.linuxfoundation.org/training/introduction-to-backstage-developer-portals-made-easy-lfs142x/',
|
||||
@@ -204,30 +165,6 @@ const Community = () => {
|
||||
</BannerSectionGrid>
|
||||
</BannerSection>
|
||||
|
||||
<BannerSection diagonalBorder greyBackground>
|
||||
<BannerSectionGrid
|
||||
header={<h2 className="text--primary">Community initiatives</h2>}
|
||||
>
|
||||
{communityInitiatives.map(
|
||||
({ title, content, link, label }, index) => (
|
||||
<ContentBlock
|
||||
key={index}
|
||||
title={title}
|
||||
hasBulletLine
|
||||
actionButtons={[
|
||||
{
|
||||
link,
|
||||
label,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<p>{content}</p>
|
||||
</ContentBlock>
|
||||
),
|
||||
)}
|
||||
</BannerSectionGrid>
|
||||
</BannerSection>
|
||||
|
||||
<BannerSection diagonalBorder>
|
||||
<BannerSectionGrid
|
||||
header={
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import nominateStyles from './nominate.module.scss';
|
||||
import Layout from '@theme/Layout';
|
||||
import clsx from 'clsx';
|
||||
import { BannerSection } from '@site/src/components/bannerSection/bannerSection';
|
||||
import { BannerSectionGrid } from '../../components/bannerSection/bannerSectionGrid';
|
||||
import { ContentBlock } from '@site/src/components/contentBlock/contentBlock';
|
||||
|
||||
const Nominate = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<div className={clsx(nominateStyles.nominatePage)}>
|
||||
<BannerSection greyBackground>
|
||||
<ContentBlock title={<h1>Contributor Spotlight nomination</h1>}>
|
||||
<iframe
|
||||
src="https://docs.google.com/forms/d/e/1FAIpQLSdiZ28O7vwHo6NrwirEzGSbuVyBANSv7ItHqRlgVvSz3Z5xqQ/viewform?embedded=true"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</ContentBlock>
|
||||
</BannerSection>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Nominate;
|
||||
@@ -1,32 +0,0 @@
|
||||
.nominatePage {
|
||||
font-size: 1.25rem;
|
||||
|
||||
&,
|
||||
& > section,
|
||||
& > section > div {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
& > section > div > div {
|
||||
flex: 1;
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 54px;
|
||||
line-height: 56px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
@@ -333,10 +333,7 @@ export class GithubUrlReader implements UrlReader {
|
||||
// GitHub returns a 403 response with a couple of headers indicating rate
|
||||
// limit status. See more in the GitHub docs:
|
||||
// https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting
|
||||
if (
|
||||
response.status === 403 &&
|
||||
response.headers.get('X-RateLimit-Remaining') === '0'
|
||||
) {
|
||||
if (this.integration.parseRateLimitInfo(response).isRateLimited) {
|
||||
message += ' (rate limit exceeded)';
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
"@swc/core": "^1.3.46",
|
||||
"@swc/helpers": "^0.5.0",
|
||||
"@swc/jest": "^0.2.22",
|
||||
"@types/jest": "^29.0.0",
|
||||
"@types/jest": "^29.5.11",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.7.2",
|
||||
@@ -100,7 +100,7 @@
|
||||
"handlebars": "^4.7.3",
|
||||
"html-webpack-plugin": "^5.3.1",
|
||||
"inquirer": "^8.2.0",
|
||||
"jest": "^29.0.2",
|
||||
"jest": "^29.7.0",
|
||||
"jest-css-modules": "^2.1.0",
|
||||
"jest-environment-jsdom": "^29.0.2",
|
||||
"jest-runtime": "^29.0.2",
|
||||
@@ -112,6 +112,7 @@
|
||||
"node-libs-browser": "^2.2.1",
|
||||
"npm-packlist": "^5.0.0",
|
||||
"ora": "^5.3.0",
|
||||
"p-queue": "^6.6.2",
|
||||
"postcss": "^8.1.0",
|
||||
"process": "^0.11.10",
|
||||
"react-dev-utils": "^12.0.0-next.60",
|
||||
|
||||
@@ -18,6 +18,7 @@ import { BackstagePackageJson } from '@backstage/cli-node';
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
import chokidar from 'chokidar';
|
||||
import fs from 'fs-extra';
|
||||
import PQueue from 'p-queue';
|
||||
import { join as joinPath, resolve as resolvePath } from 'path';
|
||||
import { paths as cliPaths } from '../paths';
|
||||
|
||||
@@ -104,6 +105,9 @@ async function detectPackages(
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure we're not issuing multiple writes at the same time, which can cause partial overwrites
|
||||
const writeQueue = new PQueue({ concurrency: 1 });
|
||||
|
||||
async function writeDetectedPackagesModule(
|
||||
pkgs: { name: string; export?: string; import: string }[],
|
||||
) {
|
||||
@@ -116,13 +120,15 @@ async function writeDetectedPackagesModule(
|
||||
)
|
||||
.join(',');
|
||||
|
||||
await fs.writeFile(
|
||||
joinPath(
|
||||
cliPaths.targetRoot,
|
||||
'node_modules',
|
||||
`${DETECTED_MODULES_MODULE_NAME}.js`,
|
||||
await writeQueue.add(() =>
|
||||
fs.writeFile(
|
||||
joinPath(
|
||||
cliPaths.targetRoot,
|
||||
'node_modules',
|
||||
`${DETECTED_MODULES_MODULE_NAME}.js`,
|
||||
),
|
||||
`window['__@backstage/discovered__'] = { modules: [${requirePackageScript}] };`,
|
||||
),
|
||||
`window['__@backstage/discovered__'] = { modules: [${requirePackageScript}] };`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,11 @@ const ERR = (name: string, path: string) => ({
|
||||
message: `${name} does not export ${path}`,
|
||||
});
|
||||
|
||||
// cwd must be restored
|
||||
const origDir = process.cwd();
|
||||
afterAll(() => {
|
||||
process.chdir(origDir);
|
||||
});
|
||||
process.chdir(FIXTURE);
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
|
||||
@@ -28,6 +28,11 @@ const ERR_FORBIDDEN = (newImp: string) => ({
|
||||
message: `Relative imports of monorepo packages are forbidden, use '${newImp}' instead`,
|
||||
});
|
||||
|
||||
// cwd must be restored
|
||||
const origDir = process.cwd();
|
||||
afterAll(() => {
|
||||
process.chdir(origDir);
|
||||
});
|
||||
process.chdir(FIXTURE);
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
|
||||
@@ -53,6 +53,11 @@ const ERR_SWITCH_BACK = () => ({
|
||||
message: 'Switch back to import declaration',
|
||||
});
|
||||
|
||||
// cwd must be restored
|
||||
const origDir = process.cwd();
|
||||
afterAll(() => {
|
||||
process.chdir(origDir);
|
||||
});
|
||||
process.chdir(FIXTURE);
|
||||
|
||||
const ruleTester = new RuleTester({
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2023 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 {
|
||||
coreExtensionData,
|
||||
createComponentExtension,
|
||||
createComponentRef,
|
||||
createExtension,
|
||||
createExtensionOverrides,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { resolveAppNodeSpecs } from '../../../tree/resolveAppNodeSpecs';
|
||||
import { resolveAppTree } from '../../../tree/resolveAppTree';
|
||||
import { App } from '../../../extensions/App';
|
||||
import { DefaultComponentsApi } from './DefaultComponentsApi';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { instantiateAppNodeTree } from '../../../tree/instantiateAppNodeTree';
|
||||
|
||||
const testRefA = createComponentRef({ id: 'test.a' });
|
||||
const testRefB1 = createComponentRef({ id: 'test.b' });
|
||||
const testRefB2 = createComponentRef({ id: 'test.b' });
|
||||
|
||||
const baseOverrides = createExtensionOverrides({
|
||||
extensions: [
|
||||
App,
|
||||
createExtension({
|
||||
namespace: 'app',
|
||||
name: 'root',
|
||||
attachTo: { id: 'app', input: 'root' },
|
||||
output: {
|
||||
element: coreExtensionData.reactElement,
|
||||
},
|
||||
factory() {
|
||||
return {
|
||||
element: <div>root</div>,
|
||||
};
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
describe('DefaultComponentsApi', () => {
|
||||
it('should provide components', () => {
|
||||
const tree = resolveAppTree(
|
||||
'app',
|
||||
resolveAppNodeSpecs({
|
||||
features: [
|
||||
baseOverrides,
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
createComponentExtension({
|
||||
ref: testRefA,
|
||||
loader: { sync: () => () => <div>test.a</div> },
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
instantiateAppNodeTree(tree.root);
|
||||
const api = DefaultComponentsApi.fromTree(tree);
|
||||
|
||||
const ComponentA = api.getComponent(testRefA);
|
||||
render(<ComponentA />);
|
||||
|
||||
expect(screen.getByText('test.a')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should key extension refs by ID', () => {
|
||||
const tree = resolveAppTree(
|
||||
'app',
|
||||
resolveAppNodeSpecs({
|
||||
features: [
|
||||
baseOverrides,
|
||||
createExtensionOverrides({
|
||||
extensions: [
|
||||
createComponentExtension({
|
||||
ref: testRefB1,
|
||||
loader: { sync: () => () => <div>test.b</div> },
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
);
|
||||
instantiateAppNodeTree(tree.root);
|
||||
const api = DefaultComponentsApi.fromTree(tree);
|
||||
|
||||
const ComponentB1 = api.getComponent(testRefB1);
|
||||
const ComponentB2 = api.getComponent(testRefB2);
|
||||
|
||||
expect(ComponentB1).toBe(ComponentB2);
|
||||
|
||||
render(<ComponentB2 />);
|
||||
|
||||
expect(screen.getByText('test.b')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
+24
-4
@@ -15,7 +15,12 @@
|
||||
*/
|
||||
|
||||
import { ComponentType } from 'react';
|
||||
import { ComponentRef, ComponentsApi } from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
AppTree,
|
||||
ComponentRef,
|
||||
ComponentsApi,
|
||||
createComponentExtension,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
/**
|
||||
* Implementation for the {@linkComponentApi}
|
||||
@@ -23,14 +28,29 @@ import { ComponentRef, ComponentsApi } from '@backstage/frontend-plugin-api';
|
||||
* @internal
|
||||
*/
|
||||
export class DefaultComponentsApi implements ComponentsApi {
|
||||
#components: Map<ComponentRef<any>, ComponentType<any>>;
|
||||
#components: Map<string, ComponentType<any>>;
|
||||
|
||||
constructor(components: Map<ComponentRef<any>, any>) {
|
||||
static fromTree(tree: AppTree) {
|
||||
const componentEntries = tree.root.edges.attachments
|
||||
.get('components')
|
||||
?.reduce((map, e) => {
|
||||
const data = e.instance?.getData(
|
||||
createComponentExtension.componentDataRef,
|
||||
);
|
||||
if (data) {
|
||||
map.set(data.ref.id, data.impl);
|
||||
}
|
||||
return map;
|
||||
}, new Map<string, ComponentType>());
|
||||
return new DefaultComponentsApi(componentEntries ?? new Map());
|
||||
}
|
||||
|
||||
constructor(components: Map<string, any>) {
|
||||
this.#components = components;
|
||||
}
|
||||
|
||||
getComponent<T extends {}>(ref: ComponentRef<T>): ComponentType<T> {
|
||||
const impl = this.#components.get(ref);
|
||||
const impl = this.#components.get(ref.id);
|
||||
if (!impl) {
|
||||
throw new Error(`No implementation found for component ref ${ref}`);
|
||||
}
|
||||
@@ -14,4 +14,4 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { DefaultComponentsApi } from './ComponentsApi';
|
||||
export { DefaultComponentsApi } from './DefaultComponentsApi';
|
||||
|
||||
@@ -31,17 +31,22 @@ import { toInternalExtension } from '../../../frontend-plugin-api/src/wiring/res
|
||||
|
||||
/** @internal */
|
||||
export function resolveAppNodeSpecs(options: {
|
||||
features: FrontendFeature[];
|
||||
builtinExtensions: Extension<unknown>[];
|
||||
parameters: Array<ExtensionParameters>;
|
||||
features?: FrontendFeature[];
|
||||
builtinExtensions?: Extension<unknown>[];
|
||||
parameters?: Array<ExtensionParameters>;
|
||||
forbidden?: Set<string>;
|
||||
}): AppNodeSpec[] {
|
||||
const { builtinExtensions, parameters, forbidden = new Set() } = options;
|
||||
const {
|
||||
builtinExtensions = [],
|
||||
parameters = [],
|
||||
forbidden = new Set(),
|
||||
features = [],
|
||||
} = options;
|
||||
|
||||
const plugins = options.features.filter(
|
||||
const plugins = features.filter(
|
||||
(f): f is BackstagePlugin => f.$$type === '@backstage/BackstagePlugin',
|
||||
);
|
||||
const overrides = options.features.filter(
|
||||
const overrides = features.filter(
|
||||
(f): f is ExtensionOverrides =>
|
||||
f.$$type === '@backstage/ExtensionOverrides',
|
||||
);
|
||||
|
||||
@@ -19,11 +19,9 @@ import { ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
AppTree,
|
||||
appTreeApiRef,
|
||||
ComponentRef,
|
||||
componentsApiRef,
|
||||
coreExtensionData,
|
||||
createApiExtension,
|
||||
createComponentExtension,
|
||||
createThemeExtension,
|
||||
createTranslationExtension,
|
||||
FrontendFeature,
|
||||
@@ -373,22 +371,10 @@ function createApiHolder(
|
||||
factory: () => routeResolutionApi,
|
||||
});
|
||||
|
||||
const componentsExtensions =
|
||||
tree.root.edges.attachments
|
||||
.get('components')
|
||||
?.map(e => e.instance?.getData(createComponentExtension.componentDataRef))
|
||||
.filter(x => !!x) ?? [];
|
||||
|
||||
const componentsMap = componentsExtensions.reduce(
|
||||
(components, component) =>
|
||||
component ? components.set(component.ref, component?.impl) : components,
|
||||
new Map<ComponentRef<any>, any>(),
|
||||
);
|
||||
|
||||
factoryRegistry.register('static', {
|
||||
api: componentsApiRef,
|
||||
deps: {},
|
||||
factory: () => new DefaultComponentsApi(componentsMap),
|
||||
factory: () => DefaultComponentsApi.fromTree(tree),
|
||||
});
|
||||
|
||||
factoryRegistry.register('static', {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { lazy, ComponentType } from 'react';
|
||||
import { lazy, ComponentType } from 'react';
|
||||
import {
|
||||
AnyExtensionInputMap,
|
||||
ResolvedExtensionInputs,
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
} from '../wiring';
|
||||
import { Expand } from '../types';
|
||||
import { PortableSchema } from '../schema';
|
||||
import { ExtensionBoundary, ComponentRef } from '../components';
|
||||
import { ComponentRef } from '../components';
|
||||
|
||||
/** @public */
|
||||
export function createComponentExtension<
|
||||
@@ -61,28 +61,26 @@ export function createComponentExtension<
|
||||
output: {
|
||||
component: createComponentExtension.componentDataRef,
|
||||
},
|
||||
factory({ config, inputs, node }) {
|
||||
let ExtensionComponent: ComponentType<TProps>;
|
||||
|
||||
factory({ config, inputs }) {
|
||||
if ('sync' in options.loader) {
|
||||
ExtensionComponent = options.loader.sync({ config, inputs });
|
||||
} else {
|
||||
const lazyLoader = options.loader.lazy;
|
||||
ExtensionComponent = lazy(() =>
|
||||
lazyLoader({ config, inputs }).then(Component => ({
|
||||
default: Component,
|
||||
})),
|
||||
) as unknown as ComponentType<TProps>;
|
||||
return {
|
||||
component: {
|
||||
ref: options.ref,
|
||||
impl: options.loader.sync({ config, inputs }) as ComponentType,
|
||||
},
|
||||
};
|
||||
}
|
||||
const lazyLoader = options.loader.lazy;
|
||||
const ExtensionComponent = lazy(() =>
|
||||
lazyLoader({ config, inputs }).then(Component => ({
|
||||
default: Component,
|
||||
})),
|
||||
) as unknown as ComponentType;
|
||||
|
||||
return {
|
||||
component: {
|
||||
ref: options.ref,
|
||||
impl: props => (
|
||||
<ExtensionBoundary node={node}>
|
||||
<ExtensionComponent {...(props as TProps)} />
|
||||
</ExtensionBoundary>
|
||||
),
|
||||
impl: ExtensionComponent,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
```ts
|
||||
import { Config } from '@backstage/config';
|
||||
import { ConsumedResponse } from '@backstage/errors';
|
||||
import { RestEndpointMethodTypes } from '@octokit/rest';
|
||||
|
||||
// @public
|
||||
@@ -567,6 +568,8 @@ export class GithubIntegration implements ScmIntegration {
|
||||
// (undocumented)
|
||||
static factory: ScmIntegrationsFactory<GithubIntegration>;
|
||||
// (undocumented)
|
||||
parseRateLimitInfo(response: ConsumedResponse): RateLimitInfo;
|
||||
// (undocumented)
|
||||
resolveEditUrl(url: string): string;
|
||||
// (undocumented)
|
||||
resolveUrl(options: {
|
||||
@@ -694,6 +697,12 @@ export type PersonalAccessTokenCredential = AzureCredentialBase & {
|
||||
personalAccessToken: string;
|
||||
};
|
||||
|
||||
// @public
|
||||
export interface RateLimitInfo {
|
||||
// (undocumented)
|
||||
isRateLimited: boolean;
|
||||
}
|
||||
|
||||
// @public
|
||||
export function readAwsS3IntegrationConfig(
|
||||
config: Config,
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"dependencies": {
|
||||
"@azure/identity": "^4.0.0",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@octokit/auth-app": "^4.0.0",
|
||||
"@octokit/rest": "^19.0.3",
|
||||
"cross-fetch": "^4.0.0",
|
||||
|
||||
@@ -78,6 +78,33 @@ describe('GithubIntegration', () => {
|
||||
),
|
||||
).toBe('https://github.com/backstage/backstage/edit/master/README.md');
|
||||
});
|
||||
|
||||
describe('isRateLimited', () => {
|
||||
const integration = new GithubIntegration({ host: 'h.com' });
|
||||
|
||||
it.each`
|
||||
status | ratelimitRemaining | expected
|
||||
${404} | ${100} | ${false}
|
||||
${429} | ${undefined} | ${true}
|
||||
${429} | ${100} | ${true}
|
||||
${403} | ${100} | ${false}
|
||||
${403} | ${0} | ${true}
|
||||
`(
|
||||
'(statusCode: $status, header: $ratelimitRemaining) === $expected',
|
||||
({ status, ratelimitRemaining, expected }) => {
|
||||
const headers = new Headers({
|
||||
'x-ratelimit-remaining': ratelimitRemaining,
|
||||
});
|
||||
const result = integration.parseRateLimitInfo({
|
||||
status,
|
||||
headers,
|
||||
} as Response);
|
||||
expect(result).toMatchObject({
|
||||
isRateLimited: expected,
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('replaceGithubUrlType', () => {
|
||||
|
||||
@@ -15,11 +15,16 @@
|
||||
*/
|
||||
|
||||
import { basicIntegrations, defaultScmResolveUrl } from '../helpers';
|
||||
import { ScmIntegration, ScmIntegrationsFactory } from '../types';
|
||||
import {
|
||||
RateLimitInfo,
|
||||
ScmIntegration,
|
||||
ScmIntegrationsFactory,
|
||||
} from '../types';
|
||||
import {
|
||||
GithubIntegrationConfig,
|
||||
readGithubIntegrationConfigs,
|
||||
} from './config';
|
||||
import { ConsumedResponse } from '@backstage/errors';
|
||||
|
||||
/**
|
||||
* A GitHub based integration.
|
||||
@@ -65,6 +70,15 @@ export class GithubIntegration implements ScmIntegration {
|
||||
resolveEditUrl(url: string): string {
|
||||
return replaceGithubUrlType(url, 'edit');
|
||||
}
|
||||
|
||||
parseRateLimitInfo(response: ConsumedResponse): RateLimitInfo {
|
||||
return {
|
||||
isRateLimited:
|
||||
response.status === 429 ||
|
||||
(response.status === 403 &&
|
||||
response.headers.get('x-ratelimit-remaining') === '0'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -37,5 +37,6 @@ export type {
|
||||
ScmIntegration,
|
||||
ScmIntegrationsFactory,
|
||||
ScmIntegrationsGroup,
|
||||
RateLimitInfo,
|
||||
} from './types';
|
||||
export type { ScmIntegrationRegistry } from './registry';
|
||||
|
||||
@@ -108,3 +108,12 @@ export interface ScmIntegrationsGroup<T extends ScmIntegration> {
|
||||
export type ScmIntegrationsFactory<T extends ScmIntegration> = (options: {
|
||||
config: Config;
|
||||
}) => ScmIntegrationsGroup<T>;
|
||||
|
||||
/**
|
||||
* Encapsulates information about the RateLimit state
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface RateLimitInfo {
|
||||
isRateLimited: boolean;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ export default async function serve(opts: OptionValues) {
|
||||
stderrLogFunc: mkdocsLogFunc,
|
||||
mkdocsConfigFileName: mkdocsYmlPath,
|
||||
mkdocsParameterClean: opts.mkdocsParameterClean,
|
||||
mkdocsParameterDirtyReload: opts.mkdocsParameterDirtyReload,
|
||||
mkdocsParameterDirtyReload: opts.mkdocsParameterDirtyreload,
|
||||
mkdocsParameterStrict: opts.mkdocsParameterStrict,
|
||||
});
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ export async function getOrganizationTeams(
|
||||
const query = `
|
||||
query teams($org: String!, $cursor: String) {
|
||||
organization(login: $org) {
|
||||
teams(first: 100, after: $cursor) {
|
||||
teams(first: 50, after: $cursor) {
|
||||
pageInfo { hasNextPage, endCursor }
|
||||
nodes {
|
||||
slug
|
||||
|
||||
+54
-54
@@ -17,10 +17,7 @@
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import {
|
||||
GithubCredentialsProvider,
|
||||
GithubIntegrationConfig,
|
||||
} from '@backstage/integration';
|
||||
import { GithubCredentialsProvider } from '@backstage/integration';
|
||||
import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
|
||||
import { EventSubscriber } from '@backstage/plugin-events-node';
|
||||
import { graphql } from '@octokit/graphql';
|
||||
@@ -28,6 +25,7 @@ import {
|
||||
GithubMultiOrgEntityProvider,
|
||||
withLocations,
|
||||
} from './GithubMultiOrgEntityProvider';
|
||||
import { Logger } from 'winston';
|
||||
|
||||
jest.mock('@octokit/graphql');
|
||||
|
||||
@@ -43,11 +41,50 @@ jest.mock('@backstage/integration', () => ({
|
||||
|
||||
describe('GithubMultiOrgEntityProvider', () => {
|
||||
describe('read', () => {
|
||||
let mockClient: jest.Mock<any, any, any>;
|
||||
let entityProviderConnection: EntityProviderConnection;
|
||||
let logger: Logger;
|
||||
let gitHubConfig: { host: string };
|
||||
let mockGetCredentials: jest.Mock<any, any, any>;
|
||||
let entityProvider: GithubMultiOrgEntityProvider;
|
||||
|
||||
beforeEach(() => {
|
||||
mockClient = jest.fn();
|
||||
(graphql.defaults as jest.Mock).mockReturnValue(mockClient);
|
||||
|
||||
entityProviderConnection = {
|
||||
applyMutation: jest.fn(),
|
||||
refresh: jest.fn(),
|
||||
};
|
||||
|
||||
logger = getVoidLogger();
|
||||
|
||||
gitHubConfig = { host: 'github.com' };
|
||||
|
||||
mockGetCredentials = jest.fn().mockReturnValue({
|
||||
headers: { token: 'blah' },
|
||||
type: 'app',
|
||||
});
|
||||
|
||||
const githubCredentialsProvider: GithubCredentialsProvider = {
|
||||
getCredentials: mockGetCredentials,
|
||||
};
|
||||
|
||||
entityProvider = new GithubMultiOrgEntityProvider({
|
||||
id: 'my-id',
|
||||
gitHubConfig,
|
||||
githubCredentialsProvider,
|
||||
githubUrl: 'https://github.com',
|
||||
logger,
|
||||
orgs: ['orgA', 'orgB'], // only include for tests that require it
|
||||
});
|
||||
|
||||
entityProvider.connect(entityProviderConnection);
|
||||
});
|
||||
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
|
||||
it('should read specified orgs', async () => {
|
||||
const mockClient = jest.fn();
|
||||
|
||||
mockClient
|
||||
.mockResolvedValueOnce({
|
||||
organization: {
|
||||
@@ -155,36 +192,6 @@ describe('GithubMultiOrgEntityProvider', () => {
|
||||
|
||||
(graphql.defaults as jest.Mock).mockReturnValue(mockClient);
|
||||
|
||||
const entityProviderConnection: EntityProviderConnection = {
|
||||
applyMutation: jest.fn(),
|
||||
refresh: jest.fn(),
|
||||
};
|
||||
|
||||
const logger = getVoidLogger();
|
||||
const gitHubConfig: GithubIntegrationConfig = {
|
||||
host: 'github.com',
|
||||
};
|
||||
|
||||
const mockGetCredentials = jest.fn().mockReturnValue({
|
||||
headers: { token: 'blah' },
|
||||
type: 'app',
|
||||
});
|
||||
|
||||
const githubCredentialsProvider: GithubCredentialsProvider = {
|
||||
getCredentials: mockGetCredentials,
|
||||
};
|
||||
|
||||
const entityProvider = new GithubMultiOrgEntityProvider({
|
||||
id: 'my-id',
|
||||
gitHubConfig,
|
||||
githubCredentialsProvider,
|
||||
githubUrl: 'https://github.com',
|
||||
logger,
|
||||
orgs: ['orgA', 'orgB'],
|
||||
});
|
||||
|
||||
entityProvider.connect(entityProviderConnection);
|
||||
|
||||
await entityProvider.read();
|
||||
|
||||
expect(mockGetCredentials).toHaveBeenCalledWith({
|
||||
@@ -353,8 +360,6 @@ describe('GithubMultiOrgEntityProvider', () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const mockClient = jest.fn();
|
||||
|
||||
mockClient
|
||||
.mockResolvedValueOnce({
|
||||
organization: {
|
||||
@@ -462,26 +467,11 @@ describe('GithubMultiOrgEntityProvider', () => {
|
||||
|
||||
(graphql.defaults as jest.Mock).mockReturnValue(mockClient);
|
||||
|
||||
const entityProviderConnection: EntityProviderConnection = {
|
||||
applyMutation: jest.fn(),
|
||||
refresh: jest.fn(),
|
||||
};
|
||||
|
||||
const logger = getVoidLogger();
|
||||
const gitHubConfig: GithubIntegrationConfig = {
|
||||
host: 'github.com',
|
||||
};
|
||||
|
||||
const mockGetCredentials = jest.fn().mockReturnValue({
|
||||
headers: { token: 'blah' },
|
||||
type: 'app',
|
||||
});
|
||||
|
||||
const githubCredentialsProvider: GithubCredentialsProvider = {
|
||||
getCredentials: mockGetCredentials,
|
||||
};
|
||||
|
||||
const entityProvider = new GithubMultiOrgEntityProvider({
|
||||
entityProvider = new GithubMultiOrgEntityProvider({
|
||||
id: 'my-id',
|
||||
gitHubConfig,
|
||||
githubCredentialsProvider,
|
||||
@@ -642,6 +632,16 @@ describe('GithubMultiOrgEntityProvider', () => {
|
||||
type: 'full',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not call applyMutation if an error is thrown', async () => {
|
||||
mockClient.mockImplementationOnce(() => {
|
||||
throw new Error('Network Error');
|
||||
});
|
||||
|
||||
await expect(entityProvider.read()).rejects.toThrow('Network Error');
|
||||
|
||||
expect(entityProviderConnection.applyMutation).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('withLocations', () => {
|
||||
|
||||
+35
-39
@@ -248,53 +248,49 @@ export class GithubMultiOrgEntityProvider implements EntityProvider {
|
||||
: await this.getAllOrgs(this.options.gitHubConfig);
|
||||
|
||||
for (const org of orgsToProcess) {
|
||||
try {
|
||||
const { headers, type: tokenType } =
|
||||
await this.options.githubCredentialsProvider.getCredentials({
|
||||
url: `${this.options.githubUrl}/${org}`,
|
||||
});
|
||||
const client = graphql.defaults({
|
||||
baseUrl: this.options.gitHubConfig.apiBaseUrl,
|
||||
headers,
|
||||
const { headers, type: tokenType } =
|
||||
await this.options.githubCredentialsProvider.getCredentials({
|
||||
url: `${this.options.githubUrl}/${org}`,
|
||||
});
|
||||
const client = graphql.defaults({
|
||||
baseUrl: this.options.gitHubConfig.apiBaseUrl,
|
||||
headers,
|
||||
});
|
||||
|
||||
logger.info(`Reading GitHub users and teams for org: ${org}`);
|
||||
logger.info(`Reading GitHub users and teams for org: ${org}`);
|
||||
|
||||
const { users } = await getOrganizationUsers(
|
||||
client,
|
||||
org,
|
||||
tokenType,
|
||||
this.options.userTransformer,
|
||||
);
|
||||
const { users } = await getOrganizationUsers(
|
||||
client,
|
||||
org,
|
||||
tokenType,
|
||||
this.options.userTransformer,
|
||||
);
|
||||
|
||||
const { teams } = await getOrganizationTeams(
|
||||
client,
|
||||
org,
|
||||
this.defaultMultiOrgTeamTransformer.bind(this),
|
||||
);
|
||||
const { teams } = await getOrganizationTeams(
|
||||
client,
|
||||
org,
|
||||
this.defaultMultiOrgTeamTransformer.bind(this),
|
||||
);
|
||||
|
||||
// Grab current users from `allUsersMap` if they already exist in our
|
||||
// pending users so we can append to their group membership relations
|
||||
const pendingUsers = users.map(u => {
|
||||
const userRef = stringifyEntityRef(u);
|
||||
if (!allUsersMap.has(userRef)) {
|
||||
allUsersMap.set(userRef, u);
|
||||
}
|
||||
|
||||
return allUsersMap.get(userRef);
|
||||
});
|
||||
|
||||
if (areGroupEntities(teams)) {
|
||||
buildOrgHierarchy(teams);
|
||||
if (areUserEntities(pendingUsers)) {
|
||||
assignGroupsToUsers(pendingUsers, teams);
|
||||
}
|
||||
// Grab current users from `allUsersMap` if they already exist in our
|
||||
// pending users so we can append to their group membership relations
|
||||
const pendingUsers = users.map(u => {
|
||||
const userRef = stringifyEntityRef(u);
|
||||
if (!allUsersMap.has(userRef)) {
|
||||
allUsersMap.set(userRef, u);
|
||||
}
|
||||
|
||||
allTeams.push(...teams);
|
||||
} catch (e) {
|
||||
logger.error(`Failed to read GitHub org data for ${org}: ${e}`);
|
||||
return allUsersMap.get(userRef);
|
||||
});
|
||||
|
||||
if (areGroupEntities(teams)) {
|
||||
buildOrgHierarchy(teams);
|
||||
if (areUserEntities(pendingUsers)) {
|
||||
assignGroupsToUsers(pendingUsers, teams);
|
||||
}
|
||||
}
|
||||
|
||||
allTeams.push(...teams);
|
||||
}
|
||||
|
||||
const allUsers = Array.from(allUsersMap.values());
|
||||
|
||||
+52
-40
@@ -30,13 +30,51 @@ jest.mock('@octokit/graphql');
|
||||
|
||||
describe('GithubOrgEntityProvider', () => {
|
||||
describe('read', () => {
|
||||
let mockClient;
|
||||
let entityProviderConnection: EntityProviderConnection;
|
||||
let entityProvider: GithubOrgEntityProvider;
|
||||
|
||||
const setupMocks = (response: ((...args: any) => any) | undefined) => {
|
||||
mockClient = jest.fn().mockImplementation(response);
|
||||
(graphql.defaults as jest.Mock).mockReturnValue(mockClient);
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
entityProviderConnection = {
|
||||
applyMutation: jest.fn(),
|
||||
refresh: jest.fn(),
|
||||
};
|
||||
|
||||
const logger = getVoidLogger();
|
||||
const gitHubConfig = {
|
||||
host: 'https://github.com',
|
||||
};
|
||||
|
||||
const mockGetCredentials = jest.fn().mockReturnValue({
|
||||
headers: { token: 'blah' },
|
||||
type: 'app',
|
||||
});
|
||||
|
||||
const githubCredentialsProvider = {
|
||||
getCredentials: mockGetCredentials,
|
||||
};
|
||||
|
||||
entityProvider = new GithubOrgEntityProvider({
|
||||
id: 'my-id',
|
||||
githubCredentialsProvider,
|
||||
orgUrl: 'https://github.com/backstage',
|
||||
gitHubConfig,
|
||||
logger,
|
||||
});
|
||||
|
||||
entityProvider.connect(entityProviderConnection);
|
||||
});
|
||||
|
||||
afterEach(() => jest.resetAllMocks());
|
||||
|
||||
it('should read org data and apply mutation', async () => {
|
||||
const mockClient = jest.fn();
|
||||
|
||||
mockClient
|
||||
.mockResolvedValueOnce({
|
||||
setupMocks(() =>
|
||||
Promise.resolve({
|
||||
organization: {
|
||||
membersWithRole: {
|
||||
pageInfo: { hasNextPage: false },
|
||||
@@ -50,10 +88,6 @@ describe('GithubOrgEntityProvider', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
organization: {
|
||||
teams: {
|
||||
pageInfo: { hasNextPage: false },
|
||||
nodes: [
|
||||
@@ -76,38 +110,8 @@ describe('GithubOrgEntityProvider', () => {
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
(graphql.defaults as jest.Mock).mockReturnValue(mockClient);
|
||||
|
||||
const entityProviderConnection: EntityProviderConnection = {
|
||||
applyMutation: jest.fn(),
|
||||
refresh: jest.fn(),
|
||||
};
|
||||
|
||||
const logger = getVoidLogger();
|
||||
const gitHubConfig: GithubIntegrationConfig = {
|
||||
host: 'https://github.com',
|
||||
};
|
||||
|
||||
const mockGetCredentials = jest.fn().mockReturnValue({
|
||||
headers: { token: 'blah' },
|
||||
type: 'app',
|
||||
});
|
||||
|
||||
const githubCredentialsProvider: GithubCredentialsProvider = {
|
||||
getCredentials: mockGetCredentials,
|
||||
};
|
||||
|
||||
const entityProvider = new GithubOrgEntityProvider({
|
||||
id: 'my-id',
|
||||
githubCredentialsProvider,
|
||||
orgUrl: 'https://github.com/backstage',
|
||||
gitHubConfig,
|
||||
logger,
|
||||
});
|
||||
|
||||
entityProvider.connect(entityProviderConnection);
|
||||
}),
|
||||
);
|
||||
|
||||
await entityProvider.read();
|
||||
|
||||
@@ -171,6 +175,14 @@ describe('GithubOrgEntityProvider', () => {
|
||||
type: 'full',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not apply mutation if a request fails', async () => {
|
||||
setupMocks(() => Promise.reject(new Error('Network error')));
|
||||
|
||||
await expect(entityProvider.read()).rejects.toThrow('Network error');
|
||||
|
||||
expect(entityProviderConnection.applyMutation).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('withLocations', () => {
|
||||
|
||||
@@ -375,6 +375,7 @@ export const createPublishGithubPullRequestAction: (
|
||||
teamReviewers?: string[] | undefined;
|
||||
commitMessage?: string | undefined;
|
||||
update?: boolean | undefined;
|
||||
forceFork?: boolean | undefined;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -687,4 +687,57 @@ describe('createPublishGithubPullRequestAction', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with force fork', () => {
|
||||
let input: GithubPullRequestActionInput;
|
||||
let ctx: ActionContext<GithubPullRequestActionInput>;
|
||||
|
||||
beforeEach(() => {
|
||||
input = {
|
||||
repoUrl: 'github.com?owner=myorg&repo=myrepo',
|
||||
title: 'Create my new app',
|
||||
branchName: 'new-app',
|
||||
description: 'This PR is really good',
|
||||
forceFork: true,
|
||||
};
|
||||
|
||||
mockDir.setContent({
|
||||
[workspacePath]: { 'file.txt': 'Hello there!' },
|
||||
});
|
||||
|
||||
ctx = {
|
||||
createTemporaryDirectory: jest.fn(),
|
||||
output: jest.fn(),
|
||||
logger: getRootLogger(),
|
||||
logStream: new Writable(),
|
||||
input,
|
||||
workspacePath,
|
||||
};
|
||||
});
|
||||
|
||||
it('creates a pull request', async () => {
|
||||
await instance.handler(ctx);
|
||||
|
||||
expect(fakeClient.createPullRequest).toHaveBeenCalledWith({
|
||||
owner: 'myorg',
|
||||
repo: 'myrepo',
|
||||
title: 'Create my new app',
|
||||
head: 'new-app',
|
||||
body: 'This PR is really good',
|
||||
changes: [
|
||||
{
|
||||
commit: 'Create my new app',
|
||||
files: {
|
||||
'file.txt': {
|
||||
content: Buffer.from('Hello there!').toString('base64'),
|
||||
encoding: 'base64',
|
||||
mode: '100644',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
forceFork: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -135,6 +135,7 @@ export const createPublishGithubPullRequestAction = (
|
||||
teamReviewers?: string[];
|
||||
commitMessage?: string;
|
||||
update?: boolean;
|
||||
forceFork?: boolean;
|
||||
}>({
|
||||
id: 'publish:github:pull-request',
|
||||
examples,
|
||||
@@ -217,6 +218,11 @@ export const createPublishGithubPullRequestAction = (
|
||||
title: 'Update',
|
||||
description: 'Update pull request if already exists',
|
||||
},
|
||||
forceFork: {
|
||||
type: 'boolean',
|
||||
title: 'Force Fork',
|
||||
description: 'Create pull request from a fork',
|
||||
},
|
||||
},
|
||||
},
|
||||
output: {
|
||||
@@ -255,6 +261,7 @@ export const createPublishGithubPullRequestAction = (
|
||||
teamReviewers,
|
||||
commitMessage,
|
||||
update,
|
||||
forceFork,
|
||||
} = ctx.input;
|
||||
|
||||
const { owner, repo, host } = parseRepoUrl(repoUrl, integrations);
|
||||
@@ -327,6 +334,7 @@ export const createPublishGithubPullRequestAction = (
|
||||
head: branchName,
|
||||
draft,
|
||||
update,
|
||||
forceFork,
|
||||
};
|
||||
if (targetBranchName) {
|
||||
createOptions.base = targetBranchName;
|
||||
|
||||
@@ -177,6 +177,8 @@ export function createFetchTemplateAction(options: {
|
||||
copyWithoutTemplating?: string[] | undefined;
|
||||
cookiecutterCompat?: boolean | undefined;
|
||||
replace?: boolean | undefined;
|
||||
trimBlocks?: boolean | undefined;
|
||||
lstripBlocks?: boolean | undefined;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
@@ -268,6 +270,7 @@ export const createPublishGithubPullRequestAction: (
|
||||
teamReviewers?: string[] | undefined;
|
||||
commitMessage?: string | undefined;
|
||||
update?: boolean | undefined;
|
||||
forceFork?: boolean | undefined;
|
||||
},
|
||||
JsonObject
|
||||
>;
|
||||
|
||||
@@ -34,6 +34,7 @@ const { render, renderCompat } = (() => {
|
||||
|
||||
const env = module.exports.configure({
|
||||
autoescape: false,
|
||||
...JSON.parse(nunjucksConfigs),
|
||||
tags: {
|
||||
variableStart: '\${{',
|
||||
variableEnd: '}}',
|
||||
@@ -42,6 +43,7 @@ const { render, renderCompat } = (() => {
|
||||
|
||||
const compatEnv = module.exports.configure({
|
||||
autoescape: false,
|
||||
...JSON.parse(nunjucksConfigs),
|
||||
tags: {
|
||||
variableStart: '{{',
|
||||
variableEnd: '}}',
|
||||
@@ -102,13 +104,14 @@ export type TemplateFilter = _TemplateFilter;
|
||||
*/
|
||||
export type TemplateGlobal = _TemplateGlobal;
|
||||
|
||||
export interface SecureTemplaterOptions {
|
||||
interface SecureTemplaterOptions {
|
||||
/* Enables jinja compatibility and the "jsonify" filter */
|
||||
cookiecutterCompat?: boolean;
|
||||
/* Extra user-provided nunjucks filters */
|
||||
templateFilters?: Record<string, TemplateFilter>;
|
||||
/* Extra user-provided nunjucks globals */
|
||||
templateGlobals?: Record<string, TemplateGlobal>;
|
||||
nunjucksConfigs?: { trimBlocks?: boolean; lstripBlocks?: boolean };
|
||||
}
|
||||
|
||||
export type SecureTemplateRenderer = (
|
||||
@@ -122,6 +125,7 @@ export class SecureTemplater {
|
||||
cookiecutterCompat,
|
||||
templateFilters = {},
|
||||
templateGlobals = {},
|
||||
nunjucksConfigs = {},
|
||||
} = options;
|
||||
|
||||
const isolate = new Isolate({ memoryLimit: 128 });
|
||||
@@ -140,6 +144,8 @@ export class SecureTemplater {
|
||||
mkScript(nunjucksSource),
|
||||
);
|
||||
|
||||
await contextGlobal.set('nunjucksConfigs', JSON.stringify(nunjucksConfigs));
|
||||
|
||||
const availableFilters = Object.keys(templateFilters);
|
||||
|
||||
await contextGlobal.set(
|
||||
|
||||
@@ -69,6 +69,8 @@ export function createFetchTemplateAction(options: {
|
||||
copyWithoutTemplating?: string[];
|
||||
cookiecutterCompat?: boolean;
|
||||
replace?: boolean;
|
||||
trimBlocks?: boolean;
|
||||
lstripBlocks?: boolean;
|
||||
}>({
|
||||
id: 'fetch:template',
|
||||
description:
|
||||
@@ -237,6 +239,10 @@ export function createFetchTemplateAction(options: {
|
||||
...additionalTemplateFilters,
|
||||
},
|
||||
templateGlobals: additionalTemplateGlobals,
|
||||
nunjucksConfigs: {
|
||||
trimBlocks: ctx.input.trimBlocks,
|
||||
lstripBlocks: ctx.input.lstripBlocks,
|
||||
},
|
||||
});
|
||||
|
||||
for (const location of allEntriesInTemplate) {
|
||||
|
||||
@@ -1547,15 +1547,15 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@azure/identity@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@azure/identity@npm:4.0.0"
|
||||
version: 4.0.1
|
||||
resolution: "@azure/identity@npm:4.0.1"
|
||||
dependencies:
|
||||
"@azure/abort-controller": ^1.0.0
|
||||
"@azure/core-auth": ^1.5.0
|
||||
"@azure/core-client": ^1.4.0
|
||||
"@azure/core-rest-pipeline": ^1.1.0
|
||||
"@azure/core-tracing": ^1.0.0
|
||||
"@azure/core-util": ^1.0.0
|
||||
"@azure/core-util": ^1.3.0
|
||||
"@azure/logger": ^1.0.0
|
||||
"@azure/msal-browser": ^3.5.0
|
||||
"@azure/msal-node": ^2.5.1
|
||||
@@ -1564,7 +1564,7 @@ __metadata:
|
||||
open: ^8.0.0
|
||||
stoppable: ^1.1.0
|
||||
tslib: ^2.2.0
|
||||
checksum: 534a62afe4715d18e221e021f8088873b1efad34344bd4c6c4685572c89517f15a646e246e9233e8db7942b0a5c73f1961ea63e3baf39c28edde1ba51da4423d
|
||||
checksum: 2c975ca70b274dc185022c2b19f1774079fd5cfb08c78ec3500e4baf973911b2958031d5fa36369d3c9acdeb25db457cc497991e7393b383103c058e097703e5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3586,7 +3586,7 @@ __metadata:
|
||||
"@types/fs-extra": ^9.0.1
|
||||
"@types/http-proxy": ^1.17.4
|
||||
"@types/inquirer": ^8.1.3
|
||||
"@types/jest": ^29.0.0
|
||||
"@types/jest": ^29.5.11
|
||||
"@types/minimatch": ^5.0.0
|
||||
"@types/node": ^18.17.8
|
||||
"@types/npm-packlist": ^3.0.0
|
||||
@@ -3635,7 +3635,7 @@ __metadata:
|
||||
handlebars: ^4.7.3
|
||||
html-webpack-plugin: ^5.3.1
|
||||
inquirer: ^8.2.0
|
||||
jest: ^29.0.2
|
||||
jest: ^29.7.0
|
||||
jest-css-modules: ^2.1.0
|
||||
jest-environment-jsdom: ^29.0.2
|
||||
jest-runtime: ^29.0.2
|
||||
@@ -3649,6 +3649,7 @@ __metadata:
|
||||
nodemon: ^3.0.1
|
||||
npm-packlist: ^5.0.0
|
||||
ora: ^5.3.0
|
||||
p-queue: ^6.6.2
|
||||
postcss: ^8.1.0
|
||||
process: ^0.11.10
|
||||
react-dev-utils: ^12.0.0-next.60
|
||||
@@ -4147,6 +4148,7 @@ __metadata:
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/config-loader": "workspace:^"
|
||||
"@backstage/errors": "workspace:^"
|
||||
"@octokit/auth-app": ^4.0.0
|
||||
"@octokit/rest": ^19.0.3
|
||||
"@types/luxon": ^3.0.0
|
||||
@@ -10178,13 +10180,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.23.0":
|
||||
version: 6.23.0
|
||||
resolution: "@codemirror/view@npm:6.23.0"
|
||||
version: 6.23.1
|
||||
resolution: "@codemirror/view@npm:6.23.1"
|
||||
dependencies:
|
||||
"@codemirror/state": ^6.4.0
|
||||
style-mod: ^4.1.0
|
||||
w3c-keyname: ^2.2.4
|
||||
checksum: 6e5f2314a3da2c724dc6a525654d949d3f2fcf7009f4d85f980d52ddc885c8969717e903ca1d9132afbe7c524af5d19bff8285fd394106282a965ae83aa47db4
|
||||
checksum: 5ea3ba5761c574e1f6e1f1058cb452189c890982a77991606d0ae40da3c6fff77f7c7fc3c43fa78d62677ccdfa65dbc56175706b793e34ad4ec7a63b21e8c18e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10469,9 +10471,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/aix-ppc64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/aix-ppc64@npm:0.19.11"
|
||||
"@esbuild/aix-ppc64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/aix-ppc64@npm:0.19.12"
|
||||
conditions: os=aix & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10490,9 +10492,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/android-arm64@npm:0.19.11"
|
||||
"@esbuild/android-arm64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/android-arm64@npm:0.19.12"
|
||||
conditions: os=android & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10511,9 +10513,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-arm@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/android-arm@npm:0.19.11"
|
||||
"@esbuild/android-arm@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/android-arm@npm:0.19.12"
|
||||
conditions: os=android & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10532,9 +10534,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/android-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/android-x64@npm:0.19.11"
|
||||
"@esbuild/android-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/android-x64@npm:0.19.12"
|
||||
conditions: os=android & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10553,9 +10555,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-arm64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/darwin-arm64@npm:0.19.11"
|
||||
"@esbuild/darwin-arm64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/darwin-arm64@npm:0.19.12"
|
||||
conditions: os=darwin & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10574,9 +10576,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/darwin-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/darwin-x64@npm:0.19.11"
|
||||
"@esbuild/darwin-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/darwin-x64@npm:0.19.12"
|
||||
conditions: os=darwin & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10595,9 +10597,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-arm64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/freebsd-arm64@npm:0.19.11"
|
||||
"@esbuild/freebsd-arm64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/freebsd-arm64@npm:0.19.12"
|
||||
conditions: os=freebsd & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10616,9 +10618,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/freebsd-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/freebsd-x64@npm:0.19.11"
|
||||
"@esbuild/freebsd-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/freebsd-x64@npm:0.19.12"
|
||||
conditions: os=freebsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10637,9 +10639,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-arm64@npm:0.19.11"
|
||||
"@esbuild/linux-arm64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-arm64@npm:0.19.12"
|
||||
conditions: os=linux & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10658,9 +10660,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-arm@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-arm@npm:0.19.11"
|
||||
"@esbuild/linux-arm@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-arm@npm:0.19.12"
|
||||
conditions: os=linux & cpu=arm
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10679,9 +10681,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ia32@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-ia32@npm:0.19.11"
|
||||
"@esbuild/linux-ia32@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-ia32@npm:0.19.12"
|
||||
conditions: os=linux & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10700,9 +10702,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-loong64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-loong64@npm:0.19.11"
|
||||
"@esbuild/linux-loong64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-loong64@npm:0.19.12"
|
||||
conditions: os=linux & cpu=loong64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10721,9 +10723,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-mips64el@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-mips64el@npm:0.19.11"
|
||||
"@esbuild/linux-mips64el@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-mips64el@npm:0.19.12"
|
||||
conditions: os=linux & cpu=mips64el
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10742,9 +10744,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-ppc64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-ppc64@npm:0.19.11"
|
||||
"@esbuild/linux-ppc64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-ppc64@npm:0.19.12"
|
||||
conditions: os=linux & cpu=ppc64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10763,9 +10765,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-riscv64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-riscv64@npm:0.19.11"
|
||||
"@esbuild/linux-riscv64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-riscv64@npm:0.19.12"
|
||||
conditions: os=linux & cpu=riscv64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10784,9 +10786,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-s390x@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-s390x@npm:0.19.11"
|
||||
"@esbuild/linux-s390x@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-s390x@npm:0.19.12"
|
||||
conditions: os=linux & cpu=s390x
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10805,9 +10807,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/linux-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/linux-x64@npm:0.19.11"
|
||||
"@esbuild/linux-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/linux-x64@npm:0.19.12"
|
||||
conditions: os=linux & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10826,9 +10828,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/netbsd-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/netbsd-x64@npm:0.19.11"
|
||||
"@esbuild/netbsd-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/netbsd-x64@npm:0.19.12"
|
||||
conditions: os=netbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10847,9 +10849,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/openbsd-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/openbsd-x64@npm:0.19.11"
|
||||
"@esbuild/openbsd-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/openbsd-x64@npm:0.19.12"
|
||||
conditions: os=openbsd & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10868,9 +10870,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/sunos-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/sunos-x64@npm:0.19.11"
|
||||
"@esbuild/sunos-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/sunos-x64@npm:0.19.12"
|
||||
conditions: os=sunos & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10889,9 +10891,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-arm64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/win32-arm64@npm:0.19.11"
|
||||
"@esbuild/win32-arm64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/win32-arm64@npm:0.19.12"
|
||||
conditions: os=win32 & cpu=arm64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10910,9 +10912,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-ia32@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/win32-ia32@npm:0.19.11"
|
||||
"@esbuild/win32-ia32@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/win32-ia32@npm:0.19.12"
|
||||
conditions: os=win32 & cpu=ia32
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -10931,9 +10933,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@esbuild/win32-x64@npm:0.19.11":
|
||||
version: 0.19.11
|
||||
resolution: "@esbuild/win32-x64@npm:0.19.11"
|
||||
"@esbuild/win32-x64@npm:0.19.12":
|
||||
version: 0.19.12
|
||||
resolution: "@esbuild/win32-x64@npm:0.19.12"
|
||||
conditions: os=win32 & cpu=x64
|
||||
languageName: node
|
||||
linkType: hard
|
||||
@@ -12836,9 +12838,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mswjs/interceptors@npm:^0.25.14":
|
||||
version: 0.25.14
|
||||
resolution: "@mswjs/interceptors@npm:0.25.14"
|
||||
"@mswjs/interceptors@npm:^0.25.15":
|
||||
version: 0.25.15
|
||||
resolution: "@mswjs/interceptors@npm:0.25.15"
|
||||
dependencies:
|
||||
"@open-draft/deferred-promise": ^2.2.0
|
||||
"@open-draft/logger": ^0.3.0
|
||||
@@ -12846,7 +12848,7 @@ __metadata:
|
||||
is-node-process: ^1.2.0
|
||||
outvariant: ^1.2.1
|
||||
strict-event-emitter: ^0.5.1
|
||||
checksum: caf9513cf6848ff0c3f1402abf881d3c1333f68fae54076cfd3fd919b7edb709769342bd3afd2a60ef4ae698ef47776b6203e0ea6a5d8e788e97eda7ed9dbbd4
|
||||
checksum: dbe43f2df398bbe48ee5ea4ecf055144c9c5689218e5955b01378ea084044dab992d1b434d3533e75df044030a976402e53ec65d743c2619e024defd75ffc076
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -18212,7 +18214,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/jest@npm:*, @types/jest@npm:^29.0.0":
|
||||
"@types/jest@npm:*, @types/jest@npm:^29.0.0, @types/jest@npm:^29.5.11":
|
||||
version: 29.5.11
|
||||
resolution: "@types/jest@npm:29.5.11"
|
||||
dependencies:
|
||||
@@ -19353,14 +19355,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/eslint-plugin@npm:^6.12.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:6.19.0"
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1"
|
||||
dependencies:
|
||||
"@eslint-community/regexpp": ^4.5.1
|
||||
"@typescript-eslint/scope-manager": 6.19.0
|
||||
"@typescript-eslint/type-utils": 6.19.0
|
||||
"@typescript-eslint/utils": 6.19.0
|
||||
"@typescript-eslint/visitor-keys": 6.19.0
|
||||
"@typescript-eslint/scope-manager": 6.19.1
|
||||
"@typescript-eslint/type-utils": 6.19.1
|
||||
"@typescript-eslint/utils": 6.19.1
|
||||
"@typescript-eslint/visitor-keys": 6.19.1
|
||||
debug: ^4.3.4
|
||||
graphemer: ^1.4.0
|
||||
ignore: ^5.2.4
|
||||
@@ -19373,25 +19375,25 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 9880567d52d4e6559e2343caeed68f856d593b42816b8f705cd98d5a5b46cc620e3bebaaf08bbc982061bba18e5be94d6c539c0c816e8772ddabba0ad4e9363e
|
||||
checksum: ad04000cd6c15d864ff92655baa3aec99bb0ccf4714fedd145fedde60a27590a5feafe480beb2f0f3864b416098bde1e9431bada7480eb7ca4efad891e1d2f6f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/parser@npm:^6.7.2":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/parser@npm:6.19.0"
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/parser@npm:6.19.1"
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager": 6.19.0
|
||||
"@typescript-eslint/types": 6.19.0
|
||||
"@typescript-eslint/typescript-estree": 6.19.0
|
||||
"@typescript-eslint/visitor-keys": 6.19.0
|
||||
"@typescript-eslint/scope-manager": 6.19.1
|
||||
"@typescript-eslint/types": 6.19.1
|
||||
"@typescript-eslint/typescript-estree": 6.19.1
|
||||
"@typescript-eslint/visitor-keys": 6.19.1
|
||||
debug: ^4.3.4
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 0ac91ff83fdf693de4494b45be79f25803ea6ca3ee717e4f96785b7ffc1da0180adb0426b61bc6eff5666c8ef9ea58c50efbd4351ef9018c0050116cbd74a62b
|
||||
checksum: cd29619da08a2d9b7123ba4d8240989c747f8e0d5672179d8b147e413ee1334d1fa48570b0c37cf0ae4e26a275fd2d268cbe702c6fed639d3331abbb3292570a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19405,22 +19407,22 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/scope-manager@npm:6.19.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/scope-manager@npm:6.19.0"
|
||||
"@typescript-eslint/scope-manager@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/scope-manager@npm:6.19.1"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 6.19.0
|
||||
"@typescript-eslint/visitor-keys": 6.19.0
|
||||
checksum: 47d9d1b70cd64f9d1bb717090850e0ff1a34e453c28b43fd0cecaea4db05cacebd60f5da55b35c4b3cc01491f02e9de358f82a0822b27c00e80e3d1a27de32d1
|
||||
"@typescript-eslint/types": 6.19.1
|
||||
"@typescript-eslint/visitor-keys": 6.19.1
|
||||
checksum: 848cdebc16a3803e8a6d6035a7067605309a652bb2425f475f755b5ace4d80d2c17c8c8901f0f4759556da8d0a5b71024d472b85c3f3c70d0e6dcfe2a972ef35
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/type-utils@npm:6.19.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/type-utils@npm:6.19.0"
|
||||
"@typescript-eslint/type-utils@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/type-utils@npm:6.19.1"
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree": 6.19.0
|
||||
"@typescript-eslint/utils": 6.19.0
|
||||
"@typescript-eslint/typescript-estree": 6.19.1
|
||||
"@typescript-eslint/utils": 6.19.1
|
||||
debug: ^4.3.4
|
||||
ts-api-utils: ^1.0.1
|
||||
peerDependencies:
|
||||
@@ -19428,7 +19430,7 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: a88f022617be636f43429a7c7c5cd2e0e29955e96d4a9fed7d03467dc4a432b1240a71009d62213604ddb3522be9694e6b78882ee805687cda107021d1ddb203
|
||||
checksum: eab1a30f8d85f7c6e2545de5963fbec2f3bb91913d59623069b4b0db372a671ab048c7018376fc853c3af06ea39417f3e7b27dd665027dd812347a5e64cecd77
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19439,10 +19441,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:6.19.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/types@npm:6.19.0"
|
||||
checksum: 1371b5ba41c1d2879b3c2823ab01a30cf034e476ef53ff2a7f9e9a4a0056dfbbfecd3143031b05430aa6c749233cacbd01b72cea38a9ece1c6cf95a5cd43da6a
|
||||
"@typescript-eslint/types@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/types@npm:6.19.1"
|
||||
checksum: 598ce222b59c20432d06f60703d0c2dd16d9b2151569c192852136c57b8188e3ef6ef9fddaa2c136c9a756fcc7d873c0e29ec41cfd340564842287ef7b4571cd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19464,12 +19466,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:6.19.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:6.19.0"
|
||||
"@typescript-eslint/typescript-estree@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:6.19.1"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 6.19.0
|
||||
"@typescript-eslint/visitor-keys": 6.19.0
|
||||
"@typescript-eslint/types": 6.19.1
|
||||
"@typescript-eslint/visitor-keys": 6.19.1
|
||||
debug: ^4.3.4
|
||||
globby: ^11.1.0
|
||||
is-glob: ^4.0.3
|
||||
@@ -19479,24 +19481,24 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 919f9588840cdab7e0ef6471f4c35d602523b142b2cffeabe9171d6ce65eb7f41614d0cb17e008e0d8e796374821ab053ced35b84642c3b1d491987362f2fdb5
|
||||
checksum: fb71a14aeee0468780219c5b8d39075f85d360b04ccd0ee88f4f0a615d2c232a6d3016e36d8c6eda2d9dfda86b4f4cc2c3d7582940fb29d33c7cf305e124d4e2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/utils@npm:6.19.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/utils@npm:6.19.0"
|
||||
"@typescript-eslint/utils@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/utils@npm:6.19.1"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": ^4.4.0
|
||||
"@types/json-schema": ^7.0.12
|
||||
"@types/semver": ^7.5.0
|
||||
"@typescript-eslint/scope-manager": 6.19.0
|
||||
"@typescript-eslint/types": 6.19.0
|
||||
"@typescript-eslint/typescript-estree": 6.19.0
|
||||
"@typescript-eslint/scope-manager": 6.19.1
|
||||
"@typescript-eslint/types": 6.19.1
|
||||
"@typescript-eslint/typescript-estree": 6.19.1
|
||||
semver: ^7.5.4
|
||||
peerDependencies:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
checksum: 05a26251a526232b08850b6c3327637213ef989453e353f3a8255433b74893a70d5c38369c528b762e853b7586d7830d728b372494e65f37770ecb05a88112d4
|
||||
checksum: fe72e75c3ea17a85772b83f148555ea94ff5d55d13586f3fc038833197a74f8071e14c2bbf1781c40eec20005f052f4be2513a725eea82a15da3cb9af3046c70
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19528,13 +19530,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:6.19.0":
|
||||
version: 6.19.0
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:6.19.0"
|
||||
"@typescript-eslint/visitor-keys@npm:6.19.1":
|
||||
version: 6.19.1
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:6.19.1"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 6.19.0
|
||||
"@typescript-eslint/types": 6.19.1
|
||||
eslint-visitor-keys: ^3.4.1
|
||||
checksum: 35b11143e1b55ecf01e0f513085df2cc83d0781f4a8354dc10f6ec3356f66b91a1ed8abadb6fb66af1c1746f9c874eabc8b5636882466e229cda5d6a39aada08
|
||||
checksum: bdf057a42e776970a89cdd568e493e3ea7ec085544d8f318d33084da63c3395ad2c0fb9cef9f61ceeca41f5dab54ab064b7078fe596889005e412ec74d2d1ae4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -25766,32 +25768,32 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"esbuild@npm:^0.19.0, esbuild@npm:~0.19.10":
|
||||
version: 0.19.11
|
||||
resolution: "esbuild@npm:0.19.11"
|
||||
version: 0.19.12
|
||||
resolution: "esbuild@npm:0.19.12"
|
||||
dependencies:
|
||||
"@esbuild/aix-ppc64": 0.19.11
|
||||
"@esbuild/android-arm": 0.19.11
|
||||
"@esbuild/android-arm64": 0.19.11
|
||||
"@esbuild/android-x64": 0.19.11
|
||||
"@esbuild/darwin-arm64": 0.19.11
|
||||
"@esbuild/darwin-x64": 0.19.11
|
||||
"@esbuild/freebsd-arm64": 0.19.11
|
||||
"@esbuild/freebsd-x64": 0.19.11
|
||||
"@esbuild/linux-arm": 0.19.11
|
||||
"@esbuild/linux-arm64": 0.19.11
|
||||
"@esbuild/linux-ia32": 0.19.11
|
||||
"@esbuild/linux-loong64": 0.19.11
|
||||
"@esbuild/linux-mips64el": 0.19.11
|
||||
"@esbuild/linux-ppc64": 0.19.11
|
||||
"@esbuild/linux-riscv64": 0.19.11
|
||||
"@esbuild/linux-s390x": 0.19.11
|
||||
"@esbuild/linux-x64": 0.19.11
|
||||
"@esbuild/netbsd-x64": 0.19.11
|
||||
"@esbuild/openbsd-x64": 0.19.11
|
||||
"@esbuild/sunos-x64": 0.19.11
|
||||
"@esbuild/win32-arm64": 0.19.11
|
||||
"@esbuild/win32-ia32": 0.19.11
|
||||
"@esbuild/win32-x64": 0.19.11
|
||||
"@esbuild/aix-ppc64": 0.19.12
|
||||
"@esbuild/android-arm": 0.19.12
|
||||
"@esbuild/android-arm64": 0.19.12
|
||||
"@esbuild/android-x64": 0.19.12
|
||||
"@esbuild/darwin-arm64": 0.19.12
|
||||
"@esbuild/darwin-x64": 0.19.12
|
||||
"@esbuild/freebsd-arm64": 0.19.12
|
||||
"@esbuild/freebsd-x64": 0.19.12
|
||||
"@esbuild/linux-arm": 0.19.12
|
||||
"@esbuild/linux-arm64": 0.19.12
|
||||
"@esbuild/linux-ia32": 0.19.12
|
||||
"@esbuild/linux-loong64": 0.19.12
|
||||
"@esbuild/linux-mips64el": 0.19.12
|
||||
"@esbuild/linux-ppc64": 0.19.12
|
||||
"@esbuild/linux-riscv64": 0.19.12
|
||||
"@esbuild/linux-s390x": 0.19.12
|
||||
"@esbuild/linux-x64": 0.19.12
|
||||
"@esbuild/netbsd-x64": 0.19.12
|
||||
"@esbuild/openbsd-x64": 0.19.12
|
||||
"@esbuild/sunos-x64": 0.19.12
|
||||
"@esbuild/win32-arm64": 0.19.12
|
||||
"@esbuild/win32-ia32": 0.19.12
|
||||
"@esbuild/win32-x64": 0.19.12
|
||||
dependenciesMeta:
|
||||
"@esbuild/aix-ppc64":
|
||||
optional: true
|
||||
@@ -25841,7 +25843,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
esbuild: bin/esbuild
|
||||
checksum: ae949a796d1d06b55275ae7491ce137857468f69a93d8cc9c0943d2a701ac54e14dbb250a2ba56f2ad98283669578f1ec3bd85a4681910a5ff29a2470c3bd62c
|
||||
checksum: 2936e29107b43e65a775b78b7bc66ddd7d76febd73840ac7e825fb22b65029422ff51038a08d19b05154f543584bd3afe7d1ef1c63900429475b17fbe61cb61f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -31346,7 +31348,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jest@npm:^29.0.2":
|
||||
"jest@npm:^29.7.0":
|
||||
version: 29.7.0
|
||||
resolution: "jest@npm:29.7.0"
|
||||
dependencies:
|
||||
@@ -34632,13 +34634,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"msw@npm:^2.0.0, msw@npm:^2.0.8":
|
||||
version: 2.1.4
|
||||
resolution: "msw@npm:2.1.4"
|
||||
version: 2.1.5
|
||||
resolution: "msw@npm:2.1.5"
|
||||
dependencies:
|
||||
"@bundled-es-modules/cookie": ^2.0.0
|
||||
"@bundled-es-modules/statuses": ^1.0.1
|
||||
"@mswjs/cookies": ^1.1.0
|
||||
"@mswjs/interceptors": ^0.25.14
|
||||
"@mswjs/interceptors": ^0.25.15
|
||||
"@open-draft/until": ^2.1.0
|
||||
"@types/cookie": ^0.6.0
|
||||
"@types/statuses": ^2.0.4
|
||||
@@ -34660,7 +34662,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
msw: cli/index.js
|
||||
checksum: da8aaf9682ac48a635966beef9add9493297de797b266066bcd8ae0c2708488b81558251412e41489511a63deda1774b42e28197e9b73ddf14d9ecf8bb916e7a
|
||||
checksum: 19a54a25baa584d1bafa219e1c2245073688eeed6ea5330f27c868a2f279390ee4fbd8a13d64cf0a056149d7e2faa300f901959bab8854e010f29368524d7c4f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user