Merge pull request #6756 from backstage/dependabot/npm_and_yarn/prettier-2.3.2

chore(deps-dev): bump prettier from 2.2.1 to 2.3.2
This commit is contained in:
Fredrik Adelöw
2021-08-09 14:04:37 +02:00
committed by GitHub
312 changed files with 1455 additions and 1668 deletions
+8 -8
View File
@@ -30,19 +30,19 @@ import openapiApiEntity from './openapi-example-api.yaml';
import otherApiEntity from './other-example-api.yaml';
import { Content, Header, Page } from '@backstage/core-components';
const mockEntities = ([
const mockEntities = [
openapiApiEntity,
asyncapiApiEntity,
graphqlApiEntity,
otherApiEntity,
] as unknown) as Entity[];
] as unknown as Entity[];
createDevApp()
.registerApi({
api: catalogApiRef,
deps: {},
factory: () =>
(({
({
async getEntities() {
return {
items: mockEntities.slice(),
@@ -51,7 +51,7 @@ createDevApp()
async getEntityByName(name: string) {
return mockEntities.find(e => e.metadata.name === name);
},
} as unknown) as typeof catalogApiRef.T),
} as unknown as typeof catalogApiRef.T),
})
.registerApi({
api: apiDocsConfigRef,
@@ -72,7 +72,7 @@ createDevApp()
<Page themeId="home">
<Header title="OpenAPI" />
<Content>
<EntityProvider entity={(openapiApiEntity as any) as Entity}>
<EntityProvider entity={openapiApiEntity as any as Entity}>
<EntityApiDefinitionCard />
</EntityProvider>
</Content>
@@ -85,7 +85,7 @@ createDevApp()
<Page themeId="home">
<Header title="AsyncAPI" />
<Content>
<EntityProvider entity={(asyncapiApiEntity as any) as Entity}>
<EntityProvider entity={asyncapiApiEntity as any as Entity}>
<EntityApiDefinitionCard />
</EntityProvider>
</Content>
@@ -98,7 +98,7 @@ createDevApp()
<Page themeId="home">
<Header title="GraphQL" />
<Content>
<EntityProvider entity={(graphqlApiEntity as any) as Entity}>
<EntityProvider entity={graphqlApiEntity as any as Entity}>
<EntityApiDefinitionCard />
</EntityProvider>
</Content>
@@ -111,7 +111,7 @@ createDevApp()
<Page themeId="home">
<Header title="Other" />
<Content>
<EntityProvider entity={(otherApiEntity as any) as Entity}>
<EntityProvider entity={otherApiEntity as any as Entity}>
<EntityApiDefinitionCard />
</EntityProvider>
</Content>
@@ -88,13 +88,15 @@ const useStyles = makeStyles(theme => ({
'& .asyncapi__enum': {
color: theme.palette.secondary.main,
},
'& .asyncapi__info, .asyncapi__channel, .asyncapi__channels > div, .asyncapi__schema, .asyncapi__channel-operations-list .asyncapi__messages-list-item .asyncapi__message, .asyncapi__message, .asyncapi__server, .asyncapi__servers > div, .asyncapi__messages > div, .asyncapi__schemas > div': {
'background-color': 'inherit',
},
'& .asyncapi__channel-parameters-header, .asyncapi__channel-operations-header, .asyncapi__channel-operation-oneOf-subscribe-header, .asyncapi__channel-operation-oneOf-publish-header, .asyncapi__channel-operation-message-header, .asyncapi__message-header, .asyncapi__message-header-title, .asyncapi__message-header-title > h3, .asyncapi__bindings, .asyncapi__bindings-header, .asyncapi__bindings-header > h4': {
'background-color': 'inherit',
color: theme.palette.text.primary,
},
'& .asyncapi__info, .asyncapi__channel, .asyncapi__channels > div, .asyncapi__schema, .asyncapi__channel-operations-list .asyncapi__messages-list-item .asyncapi__message, .asyncapi__message, .asyncapi__server, .asyncapi__servers > div, .asyncapi__messages > div, .asyncapi__schemas > div':
{
'background-color': 'inherit',
},
'& .asyncapi__channel-parameters-header, .asyncapi__channel-operations-header, .asyncapi__channel-operation-oneOf-subscribe-header, .asyncapi__channel-operation-oneOf-publish-header, .asyncapi__channel-operation-message-header, .asyncapi__message-header, .asyncapi__message-header-title, .asyncapi__message-header-title > h3, .asyncapi__bindings, .asyncapi__bindings-header, .asyncapi__bindings-header > h4':
{
'background-color': 'inherit',
color: theme.palette.text.primary,
},
'& .asyncapi__additional-properties-notice': {
color: theme.palette.text.hint,
},
@@ -104,10 +106,11 @@ const useStyles = makeStyles(theme => ({
'& .asyncapi__schema-example-header-title': {
color: theme.palette.text.secondary,
},
'& .asyncapi__message-headers-header, .asyncapi__message-payload-header, .asyncapi__server-variables-header, .asyncapi__server-security-header': {
'background-color': 'inherit',
color: theme.palette.text.secondary,
},
'& .asyncapi__message-headers-header, .asyncapi__message-payload-header, .asyncapi__server-variables-header, .asyncapi__server-security-header':
{
'background-color': 'inherit',
color: theme.palette.text.secondary,
},
'& .asyncapi__table-header': {
background: theme.palette.background.default,
},
@@ -30,22 +30,26 @@ const useStyles = makeStyles(theme => ({
'& .scheme-container': {
'background-color': theme.palette.background.default,
},
'& .opblock-tag, .opblock-tag small, table thead tr td, table thead tr th': {
color: theme.palette.text.primary,
'border-color': theme.palette.divider,
},
'& .opblock-tag, .opblock-tag small, table thead tr td, table thead tr th':
{
color: theme.palette.text.primary,
'border-color': theme.palette.divider,
},
'& section.models, section.models.is-open h4': {
'border-color': theme.palette.divider,
},
'& .opblock .opblock-summary-description, .parameter__type, table.headers td, .model-title, .model .property.primitive, section h3': {
color: theme.palette.text.secondary,
},
'& .opblock .opblock-summary-operation-id, .opblock .opblock-summary-path, .opblock .opblock-summary-path__deprecated, .opblock .opblock-section-header h4, .parameter__name, .response-col_status, .response-col_links, .responses-inner h4, .swagger-ui .responses-inner h5, .opblock-section-header .btn, .tab li, .info li, .info p, .info table, section.models h4, .info .title, table.model tr.description, .property-row': {
color: theme.palette.text.primary,
},
'& .opblock .opblock-section-header, .model-box, section.models .model-container': {
background: theme.palette.background.default,
},
'& .opblock .opblock-summary-description, .parameter__type, table.headers td, .model-title, .model .property.primitive, section h3':
{
color: theme.palette.text.secondary,
},
'& .opblock .opblock-summary-operation-id, .opblock .opblock-summary-path, .opblock .opblock-summary-path__deprecated, .opblock .opblock-section-header h4, .parameter__name, .response-col_status, .response-col_links, .responses-inner h4, .swagger-ui .responses-inner h5, .opblock-section-header .btn, .tab li, .info li, .info p, .info table, section.models h4, .info .title, table.model tr.description, .property-row':
{
color: theme.palette.text.primary,
},
'& .opblock .opblock-section-header, .model-box, section.models .model-container':
{
background: theme.palette.background.default,
},
'& .prop-format, .parameter__in': {
color: theme.palette.text.disabled,
},
@@ -53,9 +57,10 @@ const useStyles = makeStyles(theme => ({
color: theme.palette.text.primary,
'border-color': theme.palette.divider,
},
'& .opblock-description-wrapper p, .opblock-external-docs-wrapper p, .opblock-title_normal p, .response-control-media-type__accept-message, .opblock .opblock-section-header>label, .scheme-container .schemes>label, .info .base-url, .model': {
color: theme.palette.text.hint,
},
'& .opblock-description-wrapper p, .opblock-external-docs-wrapper p, .opblock-title_normal p, .response-control-media-type__accept-message, .opblock .opblock-section-header>label, .scheme-container .schemes>label, .info .base-url, .model':
{
color: theme.palette.text.hint,
},
'& .parameter__name.required:after': {
color: theme.palette.warning.dark,
},
+1 -1
View File
@@ -22,7 +22,7 @@ import { injectConfig } from './config';
jest.mock('fs-extra');
const fsMock = fs as jest.Mocked<typeof fs>;
const readFileMock = (fsMock.readFile as unknown) as jest.MockedFunction<
const readFileMock = fsMock.readFile as unknown as jest.MockedFunction<
(name: string) => Promise<string>
>;
+1 -2
View File
@@ -104,8 +104,7 @@ export async function createRouter(
// The Cache-Control header instructs the browser to not cache html files since it might
// link to static assets from recently deployed versions.
if (
((express.static.mime as unknown) as Mime).lookup(path) ===
'text/html'
(express.static.mime as unknown as Mime).lookup(path) === 'text/html'
) {
res.setHeader('Cache-Control', 'no-store, max-age=0');
}
+1 -3
View File
@@ -223,9 +223,7 @@ export class OAuthEnvironmentHandler implements AuthProviderRouteHandlers {
export interface OAuthHandlers {
// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
// Warning: (tsdoc-param-tag-with-invalid-type) The @param block should not include a JSDoc-style '{type}'
handler(
req: express.Request,
): Promise<{
handler(req: express.Request): Promise<{
response: AuthResponse<OAuthProviderInfo>;
refreshToken?: string;
}>;
@@ -150,7 +150,7 @@ export class TokenFactory implements TokenIssuer {
// the new one. This also needs to be implemented cross-service though, meaning new services
// that boot up need to be able to grab an existing key to use for signing.
this.logger.info(`Created new signing key ${key.kid}`);
await this.keyStore.addKey((key.toJWK(false) as unknown) as AnyJWK);
await this.keyStore.addKey(key.toJWK(false) as unknown as AnyJWK);
// At this point we are allowed to start using the new key
return key as JSONWebKey;
@@ -32,10 +32,10 @@ describe('oauth helpers', () => {
describe('postMessageResponse', () => {
const appOrigin = 'http://localhost:3000';
it('should post a message back with payload success', () => {
const mockResponse = ({
const mockResponse = {
end: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
const data: WebMessageResponse = {
type: 'authorization_response',
@@ -64,10 +64,10 @@ describe('oauth helpers', () => {
});
it('should post a message back with payload error', () => {
const mockResponse = ({
const mockResponse = {
end: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
const data: WebMessageResponse = {
type: 'authorization_response',
@@ -84,13 +84,13 @@ describe('oauth helpers', () => {
it('should call postMessage twice but only one of them with target *', () => {
let responseBody = '';
const mockResponse = ({
const mockResponse = {
end: jest.fn(body => {
responseBody = body;
return this;
}),
setHeader: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
const data: WebMessageResponse = {
type: 'authorization_response',
@@ -128,10 +128,10 @@ describe('oauth helpers', () => {
});
it('handles single quotes and unicode chars safely', () => {
const mockResponse = ({
const mockResponse = {
end: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
const data: WebMessageResponse = {
type: 'authorization_response',
@@ -164,23 +164,23 @@ describe('oauth helpers', () => {
describe('ensuresXRequestedWith', () => {
it('should return false if no header present', () => {
const mockRequest = ({
const mockRequest = {
header: () => jest.fn(),
} as unknown) as express.Request;
} as unknown as express.Request;
expect(ensuresXRequestedWith(mockRequest)).toBe(false);
});
it('should return false if header present with incorrect value', () => {
const mockRequest = ({
const mockRequest = {
header: () => 'INVALID',
} as unknown) as express.Request;
} as unknown as express.Request;
expect(ensuresXRequestedWith(mockRequest)).toBe(false);
});
it('should return true if header present with correct value', () => {
const mockRequest = ({
const mockRequest = {
header: () => 'XMLHttpRequest',
} as unknown) as express.Request;
} as unknown as express.Request;
expect(ensuresXRequestedWith(mockRequest)).toBe(true);
});
});
@@ -71,19 +71,19 @@ describe('OAuthAdapter', () => {
providerInstance,
oAuthProviderOptions,
);
const mockRequest = ({
const mockRequest = {
query: {
scope: 'user',
env: 'development',
},
} as unknown) as express.Request;
} as unknown as express.Request;
const mockResponse = ({
const mockResponse = {
cookie: jest.fn().mockReturnThis(),
end: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
statusCode: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
await oauthProvider.start(mockRequest, mockResponse);
// nonce cookie checks
@@ -108,20 +108,20 @@ describe('OAuthAdapter', () => {
});
const state = { nonce: 'nonce', env: 'development' };
const mockRequest = ({
const mockRequest = {
cookies: {
'test-provider-nonce': 'nonce',
},
query: {
state: encodeState(state),
},
} as unknown) as express.Request;
} as unknown as express.Request;
const mockResponse = ({
const mockResponse = {
cookie: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
end: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
await oauthProvider.frameHandler(mockRequest, mockResponse);
expect(mockResponse.cookie).toHaveBeenCalledTimes(1);
@@ -141,20 +141,20 @@ describe('OAuthAdapter', () => {
disableRefresh: true,
});
const mockRequest = ({
const mockRequest = {
cookies: {
'test-provider-nonce': 'nonce',
},
query: {
state: 'nonce',
},
} as unknown) as express.Request;
} as unknown as express.Request;
const mockResponse = ({
const mockResponse = {
cookie: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
end: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
await oauthProvider.frameHandler(mockRequest, mockResponse);
expect(mockResponse.cookie).toHaveBeenCalledTimes(0);
@@ -166,15 +166,15 @@ describe('OAuthAdapter', () => {
disableRefresh: false,
});
const mockRequest = ({
const mockRequest = {
header: () => 'XMLHttpRequest',
} as unknown) as express.Request;
} as unknown as express.Request;
const mockResponse = ({
const mockResponse = {
cookie: jest.fn().mockReturnThis(),
send: jest.fn().mockReturnThis(),
status: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
await oauthProvider.logout(mockRequest, mockResponse);
expect(mockResponse.cookie).toHaveBeenCalledTimes(1);
@@ -192,18 +192,18 @@ describe('OAuthAdapter', () => {
disableRefresh: false,
});
const mockRequest = ({
const mockRequest = {
header: () => 'XMLHttpRequest',
cookies: {
'test-provider-refresh-token': 'token',
},
query: {},
} as unknown) as express.Request;
} as unknown as express.Request;
const mockResponse = ({
const mockResponse = {
json: jest.fn().mockReturnThis(),
status: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
await oauthProvider.refresh(mockRequest, mockResponse);
expect(mockResponse.json).toHaveBeenCalledTimes(1);
@@ -222,18 +222,18 @@ describe('OAuthAdapter', () => {
disableRefresh: true,
});
const mockRequest = ({
const mockRequest = {
header: () => 'XMLHttpRequest',
cookies: {
'test-provider-refresh-token': 'token',
},
query: {},
} as unknown) as express.Request;
} as unknown as express.Request;
const mockResponse = ({
const mockResponse = {
send: jest.fn().mockReturnThis(),
status: jest.fn().mockReturnThis(),
} as unknown) as express.Response;
} as unknown as express.Response;
await oauthProvider.refresh(mockRequest, mockResponse);
expect(mockResponse.send).toHaveBeenCalledTimes(1);
@@ -21,24 +21,24 @@ describe('OAuthProvider Utils', () => {
describe('verifyNonce', () => {
it('should throw error if cookie nonce missing', () => {
const state = { nonce: 'NONCE', env: 'development' };
const mockRequest = ({
const mockRequest = {
cookies: {},
query: {
state: encodeState(state),
},
} as unknown) as express.Request;
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).toThrowError('Auth response is missing cookie nonce');
});
it('should throw error if state nonce missing', () => {
const mockRequest = ({
const mockRequest = {
cookies: {
'providera-nonce': 'NONCE',
},
query: {},
} as unknown) as express.Request;
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).toThrowError('Invalid state passed via request');
@@ -46,14 +46,14 @@ describe('OAuthProvider Utils', () => {
it('should throw error if nonce mismatch', () => {
const state = { nonce: 'NONCEB', env: 'development' };
const mockRequest = ({
const mockRequest = {
cookies: {
'providera-nonce': 'NONCEA',
},
query: {
state: encodeState(state),
},
} as unknown) as express.Request;
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).toThrowError('Invalid nonce');
@@ -61,14 +61,14 @@ describe('OAuthProvider Utils', () => {
it('should not throw any error if nonce matches', () => {
const state = { nonce: 'NONCE', env: 'development' };
const mockRequest = ({
const mockRequest = {
cookies: {
'providera-nonce': 'NONCE',
},
query: {
state: encodeState(state),
},
} as unknown) as express.Request;
} as unknown as express.Request;
expect(() => {
verifyNonce(mockRequest, 'providera');
}).not.toThrow();
+1 -3
View File
@@ -106,9 +106,7 @@ export interface OAuthHandlers {
* Handles the redirect from the auth provider when the user has signed in.
* @param {express.Request} req
*/
handler(
req: express.Request,
): Promise<{
handler(req: express.Request): Promise<{
response: AuthResponse<OAuthProviderInfo>;
refreshToken?: string;
}>;
@@ -23,7 +23,7 @@ import {
executeRefreshTokenStrategy,
} from './PassportStrategyHelper';
const mockRequest = ({} as unknown) as express.Request;
const mockRequest = {} as unknown as express.Request;
describe('PassportStrategyHelper', () => {
class MyCustomRedirectStrategy extends passport.Strategy {
@@ -195,7 +195,7 @@ export const executeFetchUserProfileStrategy = async (
accessToken: string,
): Promise<passport.Profile> => {
return new Promise((resolve, reject) => {
const anyStrategy = (providerStrategy as unknown) as ProviderStrategy;
const anyStrategy = providerStrategy as unknown as ProviderStrategy;
anyStrategy.userProfile(
accessToken,
(error: Error, rawProfile: passport.Profile) => {
@@ -79,22 +79,22 @@ describe('AwsALBAuthProvider', () => {
getEntityByName: jest.fn(),
};
const mockRequest = ({
const mockRequest = {
header: jest.fn(() => {
return 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZvbyIsImlzcyI6ImZvbyJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.T2BNS4G-6RoiFnXc8Q8TiwdWzTpNitY8jcsGM3N3-Yo';
}),
} as unknown) as express.Request;
const mockRequestWithoutJwt = ({
} as unknown as express.Request;
const mockRequestWithoutJwt = {
header: jest.fn(() => {
return undefined;
}),
} as unknown) as express.Request;
const mockResponse = ({
} as unknown as express.Request;
const mockResponse = {
end: jest.fn(),
header: () => jest.fn(),
json: jest.fn().mockReturnThis(),
status: jest.fn(),
} as unknown) as express.Response;
} as unknown as express.Response;
describe('should transform to type OAuthResponse', () => {
it('when JWT is valid and identity is resolved successfully', async () => {
@@ -19,10 +19,10 @@ import { GithubAuthProvider } from './provider';
import * as helpers from '../../lib/passport/PassportStrategyHelper';
import { OAuthResult } from '../../lib/oauth';
const mockFrameHandler = (jest.spyOn(
const mockFrameHandler = jest.spyOn(
helpers,
'executeFrameHandlerStrategy',
) as unknown) as jest.MockedFunction<
) as unknown as jest.MockedFunction<
() => Promise<{
result: Omit<OAuthResult, 'params'> & { params: { scope: string } };
}>
@@ -87,7 +87,7 @@ describe('GithubAuthProvider', () => {
it('when "email" is missing, it should be able to create the profile without it', async () => {
const accessToken = '19xasczxcm9n7gacn9jdgm19me';
const fullProfile = ({
const fullProfile = {
id: 'uid-123',
username: 'jimmymarkum',
provider: 'github',
@@ -99,7 +99,7 @@ describe('GithubAuthProvider', () => {
'https://a1cf74336522e87f135f-2f21ace9a6cf0052456644b80fa06d4f.ssl.cf2.rackcdn.com/images/characters_opt/p-mystic-river-sean-penn.jpg',
},
],
} as unknown) as PassportProfile;
} as unknown as PassportProfile;
const params = {
scope: 'read:scope',
@@ -131,7 +131,7 @@ describe('GithubAuthProvider', () => {
it('when "displayName" is missing, it should be able to create the profile and map "displayName" with "username"', async () => {
const accessToken = '19xasczxcm9n7gacn9jdgm19me';
const fullProfile = ({
const fullProfile = {
id: 'uid-123',
username: 'jimmymarkum',
provider: 'github',
@@ -143,7 +143,7 @@ describe('GithubAuthProvider', () => {
'https://a1cf74336522e87f135f-2f21ace9a6cf0052456644b80fa06d4f.ssl.cf2.rackcdn.com/images/characters_opt/p-mystic-river-sean-penn.jpg',
},
],
} as unknown) as PassportProfile;
} as unknown as PassportProfile;
const params = {
scope: 'read:scope',
@@ -18,10 +18,10 @@ import { GitlabAuthProvider } from './provider';
import * as helpers from '../../lib/passport/PassportStrategyHelper';
import { OAuthResult } from '../../lib/oauth';
const mockFrameHandler = (jest.spyOn(
const mockFrameHandler = jest.spyOn(
helpers,
'executeFrameHandlerStrategy',
) as unknown) as jest.MockedFunction<() => Promise<{ result: OAuthResult }>>;
) as unknown as jest.MockedFunction<() => Promise<{ result: OAuthResult }>>;
describe('GitlabAuthProvider', () => {
it('should transform to type OAuthResponse', async () => {
@@ -21,10 +21,10 @@ import { getVoidLogger } from '@backstage/backend-common';
import { TokenIssuer } from '../../identity/types';
import { CatalogIdentityClient } from '../../lib/catalog';
const mockFrameHandler = (jest.spyOn(
const mockFrameHandler = jest.spyOn(
helpers,
'executeFrameHandlerStrategy',
) as unknown) as jest.MockedFunction<
) as unknown as jest.MockedFunction<
() => Promise<{ result: OAuthResult; privateInfo: any }>
>;
@@ -40,8 +40,9 @@ describe('createGoogleProvider', () => {
const provider = new GoogleAuthProvider({
logger: getVoidLogger(),
catalogIdentityClient: (catalogIdentityClient as unknown) as CatalogIdentityClient,
tokenIssuer: (tokenIssuer as unknown) as TokenIssuer,
catalogIdentityClient:
catalogIdentityClient as unknown as CatalogIdentityClient,
tokenIssuer: tokenIssuer as unknown as TokenIssuer,
authHandler: async ({ fullProfile }) => ({
profile: {
email: fullProfile.emails![0]!.value,
@@ -21,10 +21,10 @@ import { getVoidLogger } from '@backstage/backend-common';
import { TokenIssuer } from '../../identity/types';
import { CatalogIdentityClient } from '../../lib/catalog';
const mockFrameHandler = (jest.spyOn(
const mockFrameHandler = jest.spyOn(
helpers,
'executeFrameHandlerStrategy',
) as unknown) as jest.MockedFunction<
) as unknown as jest.MockedFunction<
() => Promise<{ result: OAuthResult; privateInfo: any }>
>;
@@ -40,8 +40,9 @@ describe('createMicrosoftProvider', () => {
const provider = new MicrosoftAuthProvider({
logger: getVoidLogger(),
catalogIdentityClient: (catalogIdentityClient as unknown) as CatalogIdentityClient,
tokenIssuer: (tokenIssuer as unknown) as TokenIssuer,
catalogIdentityClient:
catalogIdentityClient as unknown as CatalogIdentityClient,
tokenIssuer: tokenIssuer as unknown as TokenIssuer,
authHandler: async ({ fullProfile }) => ({
profile: {
email: fullProfile.emails![0]!.value,
@@ -220,24 +220,22 @@ export const microsoftEmailSignInResolver: SignInResolver<OAuthResult> = async (
return { id: entity.metadata.name, entity, token };
};
export const microsoftDefaultSignInResolver: SignInResolver<OAuthResult> = async (
info,
ctx,
) => {
const { profile } = info;
export const microsoftDefaultSignInResolver: SignInResolver<OAuthResult> =
async (info, ctx) => {
const { profile } = info;
if (!profile.email) {
throw new Error('Profile contained no email');
}
if (!profile.email) {
throw new Error('Profile contained no email');
}
const userId = profile.email.split('@')[0];
const userId = profile.email.split('@')[0];
const token = await ctx.tokenIssuer.issueToken({
claims: { sub: userId, ent: [`user:default/${userId}`] },
});
const token = await ctx.tokenIssuer.issueToken({
claims: { sub: userId, ent: [`user:default/${userId}`] },
});
return { id: userId, token };
};
return { id: userId, token };
};
export type MicrosoftProviderOptions = {
/**
@@ -70,7 +70,7 @@ describe('OidcAuthProvider', () => {
rest.get('https://oidc.test/.well-known/openid-configuration', handler),
);
const provider = new OidcAuthProvider(clientMetadata);
const { strategy } = ((await (provider as any).implementation) as any) as {
const { strategy } = (await (provider as any).implementation) as any as {
strategy: {
_client: ClientMetadata;
_issuer: IssuerMetadata;
@@ -138,7 +138,7 @@ describe('OidcAuthProvider', () => {
const req = {
method: 'GET',
url: 'https://oidc.test/?code=test2',
session: ({ 'oidc:oidc.test': 'test' } as any) as Session,
session: { 'oidc:oidc.test': 'test' } as any as Session,
} as express.Request;
await provider.handler(req);
expect(requestSequence).toEqual([0, 1, 2].map(i => requests[i].url));
@@ -42,7 +42,7 @@ describe('DefaultBadgeBuilder', () => {
createBadge: () => badge,
},
failbadge: {
createBadge: () => (undefined as unknown) as Badge, // force a bad return value..
createBadge: () => undefined as unknown as Badge, // force a bad return value..
},
invalidbadge: {
createBadge: () => ({ style: 'wrong' as BadgeStyle, ...badge }),
@@ -48,7 +48,11 @@ export const EntityBadgesDialog = ({ open, onClose }: Props) => {
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const badgesApi = useApi(badgesApiRef);
const { value: badges, loading, error } = useAsync(async () => {
const {
value: badges,
loading,
error,
} = useAsync(async () => {
if (open && entity) {
return await badgesApi.getEntityBadgeSpecs(entity);
}
@@ -140,21 +140,7 @@ describe('readLdapUsers', () => {
distinguishedName: ['dn-value'],
objectGUID: [
Buffer.from([
68,
2,
125,
190,
209,
0,
94,
73,
133,
33,
230,
174,
234,
195,
160,
68, 2, 125, 190, 209, 0, 94, 73, 133, 33, 230, 174, 234, 195, 160,
152,
]),
],
@@ -286,21 +272,7 @@ describe('readLdapGroups', () => {
distinguishedName: ['dn-value'],
objectGUID: [
Buffer.from([
68,
2,
125,
190,
209,
0,
94,
73,
133,
33,
230,
174,
234,
195,
160,
68, 2, 125, 190, 209, 0, 94, 73, 133, 33, 230, 174, 234, 195, 160,
152,
]),
],
@@ -89,9 +89,11 @@ export async function myGroupTransformer(
groupPhoto?: string,
): Promise<GroupEntity | undefined> {
if (
((group as unknown) as {
creationOptions: string[];
}).creationOptions.includes('ProvisionGroupHomepage')
(
group as unknown as {
creationOptions: string[];
}
).creationOptions.includes('ProvisionGroupHomepage')
) {
return undefined;
}
@@ -21,9 +21,10 @@ import { setupServer } from 'msw/node';
import { MicrosoftGraphClient } from './client';
describe('MicrosoftGraphClient', () => {
const confidentialClientApplication: jest.Mocked<msal.ConfidentialClientApplication> = {
acquireTokenByClientCredential: jest.fn(),
} as any;
const confidentialClientApplication: jest.Mocked<msal.ConfidentialClientApplication> =
{
acquireTokenByClientCredential: jest.fn(),
} as any;
let client: MicrosoftGraphClient;
const worker = setupServer();
@@ -202,14 +202,10 @@ describe('read microsoft graph', () => {
'data:image/jpeg;base64,...',
);
const {
groups,
groupMember,
groupMemberOf,
rootGroup,
} = await readMicrosoftGraphGroups(client, 'tenantid', {
groupFilter: 'securityEnabled eq false',
});
const { groups, groupMember, groupMemberOf, rootGroup } =
await readMicrosoftGraphGroups(client, 'tenantid', {
groupFilter: 'securityEnabled eq false',
});
const expectedRootGroup = group({
metadata: {
@@ -318,14 +318,12 @@ export function resolveRelations(
// Make sure every group (except root) has at least one parent. If the parent is missing, add the root.
if (rootGroup) {
const tenantId = rootGroup.metadata.annotations![
MICROSOFT_GRAPH_TENANT_ID_ANNOTATION
];
const tenantId =
rootGroup.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];
groups.forEach(group => {
const groupId = group.metadata.annotations![
MICROSOFT_GRAPH_GROUP_ID_ANNOTATION
];
const groupId =
group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION];
if (!groupId) {
return;
@@ -392,15 +390,11 @@ export async function readMicrosoftGraphOrg(
userFilter: options.userFilter,
logger: options.logger,
});
const {
groups,
rootGroup,
groupMember,
groupMemberOf,
} = await readMicrosoftGraphGroups(client, tenantId, {
groupFilter: options?.groupFilter,
transformer: options?.groupTransformer,
});
const { groups, rootGroup, groupMember, groupMemberOf } =
await readMicrosoftGraphGroups(client, tenantId, {
groupFilter: options?.groupFilter,
transformer: options?.groupTransformer,
});
resolveRelations(rootGroup, groups, users, groupMember, groupMemberOf);
users.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));
+5 -8
View File
@@ -442,13 +442,11 @@
and lets the other processors take care of further processing.
```typescript
const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({
client,
repository,
}) {
// Custom logic for interpret the matching repository.
// See defaultRepositoryParser for an example
};
const customRepositoryParser: BitbucketRepositoryParser =
async function* customRepositoryParser({ client, repository }) {
// Custom logic for interpret the matching repository.
// See defaultRepositoryParser for an example
};
const processor = BitbucketDiscoveryProcessor.fromConfig(env.config, {
parser: customRepositoryParser,
@@ -920,7 +918,6 @@
spec:
type: website
---
```
This behaves now the same way as Kubernetes handles multiple documents in a single YAML file.
+3 -4
View File
@@ -88,9 +88,7 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor {
logger: Logger_2;
});
// (undocumented)
extractInformationFromArn(
arn: string,
): {
extractInformationFromArn(arn: string): {
accountId: string;
organizationId: string;
};
@@ -596,7 +594,8 @@ export class DefaultCatalogCollator implements DocumentCollator {
//
// @public (undocumented)
export class DefaultCatalogProcessingOrchestrator
implements CatalogProcessingOrchestrator {
implements CatalogProcessingOrchestrator
{
constructor(options: {
processors: CatalogProcessor[];
integrations: ScmIntegrationRegistry;
@@ -52,12 +52,8 @@ export class DatabaseLocationsCatalog implements LocationsCatalog {
}
async location(id: string): Promise<LocationResponse> {
const {
message,
status,
timestamp,
...data
} = await this.database.location(id);
const { message, status, timestamp, ...data } =
await this.database.location(id);
return {
currentStatus: {
message,
@@ -556,9 +556,10 @@ export class CommonDatabase implements Database {
}
}
function parsePagination(
input?: EntityPagination,
): { limit?: number; offset?: number } {
function parsePagination(input?: EntityPagination): {
limit?: number;
offset?: number;
} {
if (!input) {
return {};
}
@@ -71,9 +71,8 @@ export class AnnotateLocationEntityProcessor implements CatalogProcessor {
annotations: pickBy(
{
[LOCATION_ANNOTATION]: stringifyLocationReference(location),
[ORIGIN_LOCATION_ANNOTATION]: stringifyLocationReference(
originLocation,
),
[ORIGIN_LOCATION_ANNOTATION]:
stringifyLocationReference(originLocation),
[VIEW_URL_ANNOTATION]: viewUrl,
[EDIT_URL_ANNOTATION]: editUrl,
[SOURCE_LOCATION_ANNOTATION]: sourceLocation,
@@ -37,8 +37,7 @@ describe('AwsOrganizationCloudAccountProcessor', () => {
return {
Accounts: [
{
Arn:
'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395',
Arn: 'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395',
Name: 'testaccount',
},
],
@@ -83,13 +82,11 @@ describe('AwsOrganizationCloudAccountProcessor', () => {
return {
Accounts: [
{
Arn:
'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395',
Arn: 'arn:aws:organizations::192594491037:account/o-1vl18kc5a3/957140518395',
Name: 'testaccount',
},
{
Arn:
'arn:aws:organizations::192594491037:account/o-zzzzzzzzz/957140518395',
Arn: 'arn:aws:organizations::192594491037:account/o-zzzzzzzzz/957140518395',
Name: 'testaccount2',
},
],
@@ -89,9 +89,10 @@ export class AwsOrganizationCloudAccountProcessor implements CatalogProcessor {
.replace(/[^a-zA-Z0-9\-]/g, '-');
}
extractInformationFromArn(
arn: string,
): { accountId: string; organizationId: string } {
extractInformationFromArn(arn: string): {
accountId: string;
organizationId: string;
} {
const parts = arn.split('/');
return {
@@ -256,15 +256,16 @@ describe('BitbucketDiscoveryProcessor', () => {
});
describe('Custom repository parser', () => {
const customRepositoryParser: BitbucketRepositoryParser = async function* customRepositoryParser({}) {
yield results.location(
{
type: 'custom-location-type',
target: 'custom-target',
},
true,
);
};
const customRepositoryParser: BitbucketRepositoryParser =
async function* customRepositoryParser({}) {
yield results.location(
{
type: 'custom-location-type',
target: 'custom-target',
},
true,
);
};
const processor = BitbucketDiscoveryProcessor.fromConfig(
new ConfigReader({
@@ -136,9 +136,11 @@ export async function readBitbucketOrg(
return result;
}
function parseUrl(
urlString: string,
): { projectSearchPath: RegExp; repoSearchPath: RegExp; catalogPath: string } {
function parseUrl(urlString: string): {
projectSearchPath: RegExp;
repoSearchPath: RegExp;
catalogPath: string;
} {
const url = new URL(urlString);
const path = url.pathname.substr(1).split('/');
@@ -21,9 +21,10 @@ import { getOrganizationRepositories } from './github';
import { ConfigReader } from '@backstage/config';
jest.mock('./github');
const mockGetOrganizationRepositories = getOrganizationRepositories as jest.MockedFunction<
typeof getOrganizationRepositories
>;
const mockGetOrganizationRepositories =
getOrganizationRepositories as jest.MockedFunction<
typeof getOrganizationRepositories
>;
describe('GithubDiscoveryProcessor', () => {
describe('parseUrl', () => {
@@ -56,8 +56,9 @@ export class GithubDiscoveryProcessor implements CatalogProcessor {
return false;
}
const gitHubConfig = this.integrations.github.byUrl(location.target)
?.config;
const gitHubConfig = this.integrations.github.byUrl(
location.target,
)?.config;
if (!gitHubConfig) {
throw new Error(
`There is no GitHub integration that matches ${location.target}. Please add a configuration entry for it under integrations.github`,
@@ -110,9 +111,11 @@ export class GithubDiscoveryProcessor implements CatalogProcessor {
* Helpers
*/
export function parseUrl(
urlString: string,
): { org: string; repoSearchPath: RegExp; catalogPath: string } {
export function parseUrl(urlString: string): {
org: string;
repoSearchPath: RegExp;
catalogPath: string;
} {
const url = new URL(urlString);
const path = url.pathname.substr(1).split('/');
@@ -75,8 +75,9 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor {
return false;
}
const gitHubConfig = this.integrations.github.byUrl(location.target)
?.config;
const gitHubConfig = this.integrations.github.byUrl(
location.target,
)?.config;
if (!gitHubConfig) {
throw new Error(
`There is no GitHub integration that matches ${location.target}. Please add a configuration entry for it under integrations.github`,
@@ -93,12 +94,10 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor {
for (const orgConfig of orgsToProcess) {
try {
const {
headers,
type: tokenType,
} = await credentialsProvider.getCredentials({
url: `${baseUrl}/${orgConfig.name}`,
});
const { headers, type: tokenType } =
await credentialsProvider.getCredentials({
url: `${baseUrl}/${orgConfig.name}`,
});
const client = graphql.defaults({
baseUrl: gitHubConfig.apiBaseUrl,
headers,
@@ -113,12 +113,10 @@ export class GithubOrgReaderProcessor implements CatalogProcessor {
}
const credentialsProvider = GithubCredentialsProvider.create(gitHubConfig);
const {
headers,
type: tokenType,
} = await credentialsProvider.getCredentials({
url: orgUrl,
});
const { headers, type: tokenType } =
await credentialsProvider.getCredentials({
url: orgUrl,
});
const client = graphql.defaults({
baseUrl: gitHubConfig.apiBaseUrl,
@@ -26,7 +26,7 @@ import { toAbsoluteUrl } from './LocationEntityProcessor';
describe('LocationEntityProcessor', () => {
describe('toAbsoluteUrl', () => {
it('handles files', () => {
const integrations = ({} as unknown) as ScmIntegrationRegistry;
const integrations = {} as unknown as ScmIntegrationRegistry;
const base: LocationSpec = {
type: 'file',
target: `some${path.sep}path${path.sep}catalog-info.yaml`,
@@ -24,17 +24,16 @@ export type BitbucketRepositoryParser = (options: {
logger: Logger;
}) => AsyncIterable<CatalogProcessorResult>;
export const defaultRepositoryParser: BitbucketRepositoryParser = async function* defaultRepositoryParser({
target,
}) {
yield results.location(
{
type: 'url',
target: target,
},
// Not all locations may actually exist, since the user defined them as a wildcard pattern.
// Thus, we emit them as optional and let the downstream processor find them while not outputting
// an error if it couldn't.
true,
);
};
export const defaultRepositoryParser: BitbucketRepositoryParser =
async function* defaultRepositoryParser({ target }) {
yield results.location(
{
type: 'url',
target: target,
},
// Not all locations may actually exist, since the user defined them as a wildcard pattern.
// Thus, we emit them as optional and let the downstream processor find them while not outputting
// an error if it couldn't.
true,
);
};
@@ -330,7 +330,7 @@ export async function queryWithPaging<
GraphqlType,
OutputType,
Variables extends {},
Response = QueryResponse
Response = QueryResponse,
>(
client: typeof graphql,
query: string,
@@ -58,11 +58,9 @@ export function* parseEntityYaml(
}
}
export const defaultEntityDataParser: CatalogProcessorParser = async function* defaultEntityDataParser({
data,
location,
}) {
for (const e of parseEntityYaml(data, location)) {
yield e;
}
};
export const defaultEntityDataParser: CatalogProcessorParser =
async function* defaultEntityDataParser({ data, location }) {
for (const e of parseEntityYaml(data, location)) {
yield e;
}
};
@@ -31,9 +31,9 @@ describe('ConfigLocationEntityProvider', () => {
},
});
const mockConnection = ({
const mockConnection = {
applyMutation: jest.fn(),
} as unknown) as EntityProviderConnection;
} as unknown as EntityProviderConnection;
const locationProvider = new ConfigLocationEntityProvider(mockConfig);
await locationProvider.connect(mockConnection);
@@ -22,17 +22,17 @@ import { CatalogProcessingOrchestrator } from './processing/types';
import { Stitcher } from './stitching/Stitcher';
describe('DefaultCatalogProcessingEngine', () => {
const db = ({
const db = {
transaction: jest.fn(),
getProcessableEntities: jest.fn(),
updateProcessedEntity: jest.fn(),
} as unknown) as jest.Mocked<DefaultProcessingDatabase>;
} as unknown as jest.Mocked<DefaultProcessingDatabase>;
const orchestrator: jest.Mocked<CatalogProcessingOrchestrator> = {
process: jest.fn(),
};
const stitcher = ({
const stitcher = {
stitch: jest.fn(),
} as unknown) as jest.Mocked<Stitcher>;
} as unknown as jest.Mocked<Stitcher>;
beforeEach(() => {
jest.resetAllMocks();
@@ -28,9 +28,10 @@ import {
DbSearchRow,
} from './database/tables';
function parsePagination(
input?: EntityPagination,
): { limit?: number; offset?: number } {
function parsePagination(input?: EntityPagination): {
limit?: number;
offset?: number;
} {
if (!input) {
return {};
}
@@ -47,13 +47,8 @@ export interface RouterOptions {
export async function createNextRouter(
options: RouterOptions,
): Promise<express.Router> {
const {
entitiesCatalog,
locationAnalyzer,
locationService,
config,
logger,
} = options;
const { entitiesCatalog, locationAnalyzer, locationService, config, logger } =
options;
const router = Router();
router.use(express.json());
@@ -79,10 +79,10 @@ describe('Default Processing Database', () => {
'updates refresh state with varying location keys, %p',
async databaseId => {
const mockWarn = jest.fn();
const { db } = await createDatabase(databaseId, ({
const { db } = await createDatabase(databaseId, {
debug: jest.fn(),
warn: mockWarn,
} as unknown) as Logger);
} as unknown as Logger);
await db.transaction(async tx => {
const knexTx = tx as Knex.Transaction;
@@ -54,7 +54,8 @@ type Context = {
};
export class DefaultCatalogProcessingOrchestrator
implements CatalogProcessingOrchestrator {
implements CatalogProcessingOrchestrator
{
constructor(
private readonly options: {
processors: CatalogProcessor[];
@@ -59,23 +59,21 @@ export class DefaultCatalogCollator implements DocumentCollator {
const baseUrl = await this.discovery.getBaseUrl('catalog');
const res = await fetch(`${baseUrl}/entities`);
const entities: Entity[] = await res.json();
return entities.map(
(entity: Entity): CatalogEntityDocument => {
return {
title: entity.metadata.name,
location: this.applyArgsToFormat(this.locationTemplate, {
namespace: entity.metadata.namespace || 'default',
kind: entity.kind,
name: entity.metadata.name,
}),
text: entity.metadata.description || '',
componentType: entity.spec?.type?.toString() || 'other',
return entities.map((entity: Entity): CatalogEntityDocument => {
return {
title: entity.metadata.name,
location: this.applyArgsToFormat(this.locationTemplate, {
namespace: entity.metadata.namespace || 'default',
kind: entity.kind,
lifecycle: (entity.spec?.lifecycle as string) || '',
owner: (entity.spec?.owner as string) || '',
};
},
);
name: entity.metadata.name,
}),
text: entity.metadata.description || '',
componentType: entity.spec?.type?.toString() || 'other',
namespace: entity.metadata.namespace || 'default',
kind: entity.kind,
lifecycle: (entity.spec?.lifecycle as string) || '',
owner: (entity.spec?.owner as string) || '',
};
});
}
}
@@ -60,8 +60,8 @@ describe('parseEntityTransformParams', () => {
expect(
parseEntityTransformParams({ fields: 'kind,metadata.name' })!(entity),
).toEqual({ kind: 'k', metadata: { name: 'n' } });
expect(
parseEntityTransformParams({ fields: 'metadata' })!(entity),
).toEqual({ metadata: { name: 'n', tags: ['t1', 't2'] } });
expect(parseEntityTransformParams({ fields: 'metadata' })!(entity)).toEqual(
{ metadata: { name: 'n', tags: ['t1', 't2'] } },
);
});
});
@@ -291,10 +291,10 @@ describe('createRouter readonly disabled', () => {
describe('POST /locations', () => {
it('rejects malformed locations', async () => {
const spec = ({
const spec = {
typez: 'b',
target: 'c',
} as unknown) as LocationSpec;
} as unknown as LocationSpec;
const response = await request(app).post('/locations').send(spec);
@@ -49,11 +49,8 @@ export async function startStandaloneServer(
config,
reader,
});
const {
entitiesCatalog,
locationsCatalog,
higherOrderOperation,
} = await builder.build();
const { entitiesCatalog, locationsCatalog, higherOrderOperation } =
await builder.build();
logger.debug('Starting application server...');
const router = await createRouter({
+1 -1
View File
@@ -52,7 +52,7 @@ export async function validateRequestBody<T>(
throw new InputError(`Malformed request: ${e}`);
}
return (body as unknown) as T;
return body as unknown as T;
}
export function disallowReadonlyMode(readonly: boolean) {
+16 -16
View File
@@ -219,7 +219,7 @@ export interface SubscriptionSubscriberObject<
TKey extends string,
TParent,
TContext,
TArgs
TArgs,
> {
subscribe: SubscriptionSubscribeFn<
{ [key in TKey]: TResult },
@@ -245,7 +245,7 @@ export type SubscriptionObject<
TKey extends string,
TParent,
TContext,
TArgs
TArgs,
> =
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
@@ -255,7 +255,7 @@ export type SubscriptionResolver<
TKey extends string,
TParent = {},
TContext = {},
TArgs = {}
TArgs = {},
> =
| ((
...args: any[]
@@ -279,7 +279,7 @@ export type DirectiveResolverFn<
TResult = {},
TParent = {},
TContext = {},
TArgs = {}
TArgs = {},
> = (
next: NextResolverFn<TResult>,
parent: TParent,
@@ -364,7 +364,7 @@ export interface JsonObjectScalarConfig
export type EntityMetadataResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['EntityMetadata']
ParentType = ResolversParentTypes['EntityMetadata'],
> = ResolversObject<{
__resolveType: TypeResolveFn<
'DefaultEntityMetadata' | 'ComponentMetadata' | 'TemplateMetadata',
@@ -393,7 +393,7 @@ export type EntityMetadataResolvers<
export type DefaultEntityMetadataResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['DefaultEntityMetadata']
ParentType = ResolversParentTypes['DefaultEntityMetadata'],
> = ResolversObject<{
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
annotations?: Resolver<ResolversTypes['JSONObject'], ParentType, ContextType>;
@@ -418,7 +418,7 @@ export type DefaultEntityMetadataResolvers<
export type ComponentMetadataResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['ComponentMetadata']
ParentType = ResolversParentTypes['ComponentMetadata'],
> = ResolversObject<{
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
annotations?: Resolver<ResolversTypes['JSONObject'], ParentType, ContextType>;
@@ -448,7 +448,7 @@ export type ComponentMetadataResolvers<
export type TemplateMetadataResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['TemplateMetadata']
ParentType = ResolversParentTypes['TemplateMetadata'],
> = ResolversObject<{
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
annotations?: Resolver<ResolversTypes['JSONObject'], ParentType, ContextType>;
@@ -478,7 +478,7 @@ export type TemplateMetadataResolvers<
export type TemplateEntitySpecResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['TemplateEntitySpec']
ParentType = ResolversParentTypes['TemplateEntitySpec'],
> = ResolversObject<{
type?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
path?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
@@ -489,7 +489,7 @@ export type TemplateEntitySpecResolvers<
export type ComponentEntitySpecResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['ComponentEntitySpec']
ParentType = ResolversParentTypes['ComponentEntitySpec'],
> = ResolversObject<{
title?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
lifecycle?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
@@ -499,7 +499,7 @@ export type ComponentEntitySpecResolvers<
export type LocationEntitySpecResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['LocationEntitySpec']
ParentType = ResolversParentTypes['LocationEntitySpec'],
> = ResolversObject<{
type?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
target?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
@@ -509,7 +509,7 @@ export type LocationEntitySpecResolvers<
export type DefaultEntitySpecResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['DefaultEntitySpec']
ParentType = ResolversParentTypes['DefaultEntitySpec'],
> = ResolversObject<{
raw?: Resolver<Maybe<ResolversTypes['JSONObject']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType>;
@@ -517,7 +517,7 @@ export type DefaultEntitySpecResolvers<
export type EntitySpecResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['EntitySpec']
ParentType = ResolversParentTypes['EntitySpec'],
> = ResolversObject<{
__resolveType: TypeResolveFn<
| 'DefaultEntitySpec'
@@ -531,7 +531,7 @@ export type EntitySpecResolvers<
export type CatalogEntityResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['CatalogEntity']
ParentType = ResolversParentTypes['CatalogEntity'],
> = ResolversObject<{
apiVersion?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
kind?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
@@ -546,7 +546,7 @@ export type CatalogEntityResolvers<
export type CatalogQueryResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['CatalogQuery']
ParentType = ResolversParentTypes['CatalogQuery'],
> = ResolversObject<{
list?: Resolver<
Array<ResolversTypes['CatalogEntity']>,
@@ -558,7 +558,7 @@ export type CatalogQueryResolvers<
export type QueryResolvers<
ContextType = ModuleContext,
ParentType = ResolversParentTypes['Query']
ParentType = ResolversParentTypes['Query'],
> = ResolversObject<{
catalog?: Resolver<ResolversTypes['CatalogQuery'], ParentType, ContextType>;
}>;
+1 -1
View File
@@ -178,7 +178,7 @@ export const ImportStepper: ({
//
// @public
export const PreparePullRequestForm: <
TFieldValues extends Record<string, any>
TFieldValues extends Record<string, any>,
>({
defaultValues,
onSubmit,
@@ -192,7 +192,7 @@ describe('CatalogImportClient', () => {
});
it('should find locations from github', async () => {
((new Octokit().search.code as any) as jest.Mock).mockResolvedValueOnce({
(new Octokit().search.code as any as jest.Mock).mockResolvedValueOnce({
data: {
total_count: 2,
items: [
@@ -248,7 +248,7 @@ describe('CatalogImportClient', () => {
});
it('should find repository from github', async () => {
((new Octokit().search.code as any) as jest.Mock).mockResolvedValueOnce({
(new Octokit().search.code as any as jest.Mock).mockResolvedValueOnce({
data: { total_count: 0, items: [] },
});
@@ -312,7 +312,7 @@ describe('CatalogImportClient', () => {
});
expect(
((new Octokit().git.createRef as any) as jest.Mock).mock.calls[0][0],
(new Octokit().git.createRef as any as jest.Mock).mock.calls[0][0],
).toEqual({
owner: 'backstage',
repo: 'backstage',
@@ -320,7 +320,7 @@ describe('CatalogImportClient', () => {
sha: 'any',
});
expect(
((new Octokit().repos.createOrUpdateFileContents as any) as jest.Mock)
(new Octokit().repos.createOrUpdateFileContents as any as jest.Mock)
.mock.calls[0][0],
).toEqual({
owner: 'backstage',
@@ -331,7 +331,7 @@ describe('CatalogImportClient', () => {
branch: 'backstage-integration',
});
expect(
((new Octokit().pulls.create as any) as jest.Mock).mock.calls[0][0],
(new Octokit().pulls.create as any as jest.Mock).mock.calls[0][0],
).toEqual({
owner: 'backstage',
repo: 'backstage',
@@ -53,8 +53,7 @@ export const ImportComponentPage = (opts: StepperProviderOpts) => {
title="Register an existing component"
deepLink={{
title: 'Learn more about the Software Catalog',
link:
'https://backstage.io/docs/features/software-catalog/software-catalog-overview',
link: 'https://backstage.io/docs/features/software-catalog/software-catalog-overview',
}}
>
<Typography variant="body2" paragraph>
@@ -39,9 +39,10 @@ import { ConfigApi } from '@backstage/core-plugin-api';
export type StepperProviderOpts = {
pullRequest?: {
disable?: boolean;
preparePullRequest?: (
apis: StepperApis,
) => { title?: string; body?: string };
preparePullRequest?: (apis: StepperApis) => {
title?: string;
body?: string;
};
};
};
@@ -382,7 +382,7 @@ describe('<StepInitAnalyzeUrl />', () => {
);
catalogImportApi.analyzeUrl.mockReturnValueOnce(
Promise.resolve(({ type: 'unknown' } as any) as AnalyzeResult),
Promise.resolve({ type: 'unknown' } as any as AnalyzeResult),
);
await act(async () => {
@@ -49,19 +49,14 @@ type Props<TFieldValues extends Record<string, any>> = Pick<
* @param render render the form elements
*/
export const PreparePullRequestForm = <
TFieldValues extends Record<string, any>
TFieldValues extends Record<string, any>,
>({
defaultValues,
onSubmit,
render,
}: Props<TFieldValues>) => {
const {
handleSubmit,
watch,
control,
register,
errors,
} = useForm<TFieldValues>({ mode: 'onTouched', defaultValues });
const { handleSubmit, watch, control, register, errors } =
useForm<TFieldValues>({ mode: 'onTouched', defaultValues });
return (
<form onSubmit={handleSubmit(onSubmit)}>
+2 -4
View File
@@ -516,9 +516,7 @@ export const entityRoute: RouteRef<{
// Warning: (ae-missing-release-tag) "entityRouteParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function entityRouteParams(
entity: Entity,
): {
export function entityRouteParams(entity: Entity): {
readonly kind: string;
readonly namespace: string;
readonly name: string;
@@ -721,7 +719,7 @@ export const useEntityFromUrl: () => EntityLoadingStatus;
//
// @public (undocumented)
export function useEntityListProvider<
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,
>(): EntityListContextProps<EntityFilters>;
// Warning: (ae-missing-release-tag) "useEntityOwnership" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@@ -34,12 +34,8 @@ const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export const EntityLifecyclePicker = () => {
const {
updateFilters,
backendEntities,
filters,
queryParameters,
} = useEntityListProvider();
const { updateFilters, backendEntities, filters, queryParameters } =
useEntityListProvider();
const queryParamLifecycles = [queryParameters.lifecycles]
.flat()
@@ -36,12 +36,8 @@ const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export const EntityOwnerPicker = () => {
const {
updateFilters,
backendEntities,
filters,
queryParameters,
} = useEntityListProvider();
const { updateFilters, backendEntities, filters, queryParameters } =
useEntityListProvider();
const queryParamOwners = [queryParameters.owners]
.flat()
@@ -134,7 +134,7 @@ export function createSystemColumn<T extends Entity>(): TableColumn<T> {
}
export function createMetadataDescriptionColumn<
T extends Entity
T extends Entity,
>(): TableColumn<T> {
return {
title: 'Description',
@@ -34,12 +34,8 @@ const icon = <CheckBoxOutlineBlankIcon fontSize="small" />;
const checkedIcon = <CheckBoxIcon fontSize="small" />;
export const EntityTagPicker = () => {
const {
updateFilters,
backendEntities,
filters,
queryParameters,
} = useEntityListProvider();
const { updateFilters, backendEntities, filters, queryParameters } =
useEntityListProvider();
const queryParamTags = [queryParameters.tags]
.flat()
@@ -63,17 +63,17 @@ const entities: Entity[] = [
const apis = ApiRegistry.from([
[
catalogApiRef,
({
{
getEntities: jest
.fn()
.mockImplementation(() => Promise.resolve({ items: entities })),
} as unknown) as CatalogApi,
} as unknown as CatalogApi,
],
[
alertApiRef,
({
{
post: jest.fn(),
} as unknown) as AlertApi,
} as unknown as AlertApi,
],
]);
@@ -24,12 +24,8 @@ import { Select } from '@backstage/core-components';
export const EntityTypePicker = () => {
const alertApi = useApi(alertApiRef);
const {
error,
availableTypes,
selectedTypes,
setSelectedTypes,
} = useEntityTypeFilter();
const { error, availableTypes, selectedTypes, setSelectedTypes } =
useEntityTypeFilter();
useEffect(() => {
if (error) {
@@ -129,12 +129,8 @@ export const UserListPicker = ({
}))
.filter(({ items }) => !!items.length);
const {
filters,
updateFilters,
backendEntities,
queryParameters,
} = useEntityListProvider();
const { filters, updateFilters, backendEntities, queryParameters } =
useEntityListProvider();
const { isStarredEntity } = useStarredEntities();
const { isOwnedEntity } = useEntityOwnership();
@@ -166,9 +162,8 @@ export const UserListPicker = ({
// To show proper counts for each section, apply all other frontend filters _except_ the user
// filter that's controlled by this picker.
const [entitiesWithoutUserFilter, setEntitiesWithoutUserFilter] = useState(
backendEntities,
);
const [entitiesWithoutUserFilter, setEntitiesWithoutUserFilter] =
useState(backendEntities);
useEffect(() => {
const filterFn = reduceEntityFilters(
compact(Object.values({ ...filters, user: undefined })),
+6 -1
View File
@@ -41,7 +41,12 @@ export const useEntityFromUrl = (): EntityLoadingStatus => {
const errorApi = useApi(errorApiRef);
const catalogApi = useApi(catalogApiRef);
const { value: entity, error, loading, retry: refresh } = useAsyncRetry(
const {
value: entity,
error,
loading,
retry: refresh,
} = useAsyncRetry(
() => catalogApi.getEntityByName({ kind, namespace, name }),
[catalogApi, kind, namespace, name],
);
@@ -51,7 +51,7 @@ export type DefaultEntityFilters = {
};
export type EntityListContextProps<
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,
> = {
/**
* The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension
@@ -215,7 +215,7 @@ export const EntityListProvider = <EntityFilters extends DefaultEntityFilters>({
};
export function useEntityListProvider<
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters
EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,
>(): EntityListContextProps<EntityFilters> {
const context = useContext(EntityListContext);
if (!context)
@@ -46,8 +46,8 @@ describe('useEntityOwnership', () => {
getEntityByName: jest.fn(),
};
const identityApi = (mockIdentityApi as unknown) as IdentityApi;
const catalogApi = (mockCatalogApi as unknown) as CatalogApi;
const identityApi = mockIdentityApi as unknown as IdentityApi;
const catalogApi = mockCatalogApi as unknown as CatalogApi;
const Wrapper = ({ children }: { children?: React.ReactNode }) => (
<ApiProvider
@@ -131,9 +131,10 @@ export function useEntityOwnership(): {
const isOwnedEntity = useMemo(() => {
const myOwnerRefs = new Set(refs ?? []);
return (entity: Entity | EntityName) => {
const entityOwnerRefs = ('metadata' in entity
? getEntityRelations(entity, RELATION_OWNED_BY)
: [entity]
const entityOwnerRefs = (
'metadata' in entity
? getEntityRelations(entity, RELATION_OWNED_BY)
: [entity]
).map(stringifyEntityRef);
for (const ref of entityOwnerRefs) {
if (myOwnerRefs.has(ref)) {
@@ -53,7 +53,11 @@ export function useEntityTypeFilter(): EntityTypeReturn {
// Load all valid spec.type values straight from the catalogApi, paying attention to only the
// kind filter for a complete list.
const { error, loading, value: entities } = useAsync(async () => {
const {
error,
loading,
value: entities,
} = useAsync(async () => {
if (kind) {
const items = await catalogApi
.getEntities({
@@ -30,7 +30,11 @@ export function useRelatedEntities(
error: Error | undefined;
} {
const catalogApi = useApi(catalogApiRef);
const { loading, value: entities, error } = useAsync(async () => {
const {
loading,
value: entities,
error,
} = useAsync(async () => {
const relations =
entity.relations &&
entity.relations.filter(
@@ -158,7 +158,11 @@ export function SystemDiagramCard() {
const systemEdges = new Array<{ from: string; to: string; label: string }>();
const catalogApi = useApi(catalogApiRef);
const { loading, error, value: catalogResponse } = useAsync(() => {
const {
loading,
error,
value: catalogResponse,
} = useAsync(() => {
return catalogApi.getEntities({
filter: {
kind: ['Component', 'API', 'Resource', 'System', 'Domain'],
@@ -47,7 +47,7 @@ describe('useUnregisterEntityDialogState', () => {
removeLocationById: jest.fn(),
removeEntityByUid: jest.fn(),
};
const catalogApi = (catalogApiMock as Partial<CatalogApi>) as CatalogApi;
const catalogApi = catalogApiMock as Partial<CatalogApi> as CatalogApi;
const Wrapper = ({ children }: { children?: React.ReactNode }) => (
<ApiProvider apis={ApiRegistry.with(catalogApiRef, catalogApi)}>
@@ -35,7 +35,7 @@ import {
Link,
} from '@backstage/core-components';
const IconLink = (IconButton as any) as typeof MaterialLink;
const IconLink = IconButton as any as typeof MaterialLink;
const BuildName = ({ build }: { build?: BuildWithSteps }) => (
<Box display="flex" alignItems="center">
@@ -62,9 +62,10 @@ export function useBuildWithSteps(buildId: number) {
}
};
const { loading, value, retry } = useAsyncRetry(() => getBuildWithSteps(), [
getBuildWithSteps,
]);
const { loading, value, retry } = useAsyncRetry(
() => getBuildWithSteps(),
[getBuildWithSteps],
);
const { startPolling, stopPolling } = useAsyncPolling(
getBuildWithSteps,
+17 -15
View File
@@ -26,21 +26,23 @@ import { errorApiRef, useApi } from '@backstage/core-plugin-api';
const makeReadableStatus = (status: string | undefined) => {
if (!status) return '';
return ({
retried: 'Retried',
canceled: 'Canceled',
infrastructure_fail: 'Infra fail',
timedout: 'Timedout',
not_run: 'Not run',
running: 'Running',
failed: 'Failed',
queued: 'Queued',
scheduled: 'Scheduled',
not_running: 'Not running',
no_tests: 'No tests',
fixed: 'Fixed',
success: 'Success',
} as Record<string, string>)[status];
return (
{
retried: 'Retried',
canceled: 'Canceled',
infrastructure_fail: 'Infra fail',
timedout: 'Timedout',
not_run: 'Not run',
running: 'Running',
failed: 'Failed',
queued: 'Queued',
scheduled: 'Scheduled',
not_running: 'Not running',
no_tests: 'No tests',
fixed: 'Fixed',
success: 'Success',
} as Record<string, string>
)[status];
};
const mapWorkflowDetails = (buildData: BuildSummary) => {
@@ -60,7 +60,8 @@ export class CloudbuildClient implements CloudbuildApi {
},
);
const builds: ActionsListWorkflowRunsForRepoResponseData = await workflowRuns.json();
const builds: ActionsListWorkflowRunsForRepoResponseData =
await workflowRuns.json();
return builds;
}
@@ -17,15 +17,16 @@ import { useAsync } from 'react-use';
import { ActionsListWorkflowRunsForRepoResponseData } from '../../api/types';
export const useWorkflowRunJobs = (jobsUrl?: string) => {
const jobs = useAsync(async (): Promise<ActionsListWorkflowRunsForRepoResponseData> => {
if (jobsUrl === undefined) {
return {
builds: [],
};
}
const jobs =
useAsync(async (): Promise<ActionsListWorkflowRunsForRepoResponseData> => {
if (jobsUrl === undefined) {
return {
builds: [],
};
}
const data = await fetch(jobsUrl).then(d => d.json());
return data;
}, [jobsUrl]);
const data = await fetch(jobsUrl).then(d => d.json());
return data;
}, [jobsUrl]);
return jobs;
};
@@ -41,9 +41,12 @@ export function useWorkflowRuns({ projectId }: { projectId: string }) {
const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(5);
const { loading, value: runs, retry, error } = useAsyncRetry<
WorkflowRun[]
>(async () => {
const {
loading,
value: runs,
retry,
error,
} = useAsyncRetry<WorkflowRun[]>(async () => {
return api
.listWorkflowRuns({
projectId,
@@ -117,8 +117,8 @@ export class Cobertura implements Converter {
const lines = [classLines, methodLines].flat().filter(Boolean);
const lineHits = lines.map(l => {
return {
number: parseInt((l.$.number as unknown) as string, 10),
hits: parseInt((l.$.hits as unknown) as string, 10),
number: parseInt(l.$.number as unknown as string, 10),
hits: parseInt(l.$.hits as unknown as string, 10),
'condition-coverage': l.$['condition-coverage'],
branch: l.$.branch,
};
@@ -189,12 +189,8 @@ export const makeRouter = async (
throw new InputError(`Unsupported coverage type '${coverageType}`);
}
const {
sourceLocation,
vcs,
scmFiles,
body,
} = await utils.processCoveragePayload(entityLookup, req);
const { sourceLocation, vcs, scmFiles, body } =
await utils.processCoveragePayload(entityLookup, req);
const files = converter.convert(body, scmFiles);
if (!files || files.length === 0) {
+1 -1
View File
@@ -31,7 +31,7 @@ createDevApp()
factory: () => ({
schema$: () =>
new Observable<ConfigSchemaResult>(sub =>
sub.next({ schema: (exampleSchema as unknown) as Schema }),
sub.next({ schema: exampleSchema as unknown as Schema }),
),
}),
})
+1 -1
View File
@@ -100,7 +100,7 @@ export enum AlertDismissReason {
// @public (undocumented)
export type AlertForm<
A extends Alert = any,
Data = any
Data = any,
> = ForwardRefExoticComponent<
AlertFormProps<A, Data> & RefAttributes<HTMLFormElement>
>;
@@ -41,10 +41,10 @@ import { ScrollAnchor } from '../../utils/scroll';
type MapLoadingtoAlerts = (isLoading: boolean) => void;
const mapLoadingToAlerts: MapLoadingToProps<MapLoadingtoAlerts> = ({
dispatch,
}) => (isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsAlerts]: isLoading });
const mapLoadingToAlerts: MapLoadingToProps<MapLoadingtoAlerts> =
({ dispatch }) =>
(isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsAlerts]: isLoading });
type AlertInsightsProps = {
group: string;
@@ -30,12 +30,12 @@ export const BarChartSteps = ({
onClick,
}: BarChartStepsProps) => {
const classes = useStyles();
const handleOnClick = (index: number) => (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>,
) => {
event.preventDefault();
onClick(index);
};
const handleOnClick =
(index: number) =>
(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
event.preventDefault();
onClick(index);
};
return (
<div className={classes.steps}>
@@ -31,21 +31,18 @@ type CostInsightsPageLoadingProps = {
dispatchReset: (loadingActions: string[]) => void;
};
export const mapLoadingToProps: MapLoadingToProps<CostInsightsPageLoadingProps> = ({
state,
actions,
dispatch,
}) => ({
loadingActions: actions,
loadingGroups: state[DefaultLoadingAction.UserGroups],
loadingBillingDate: state[DefaultLoadingAction.LastCompleteBillingDate],
loadingInitial: state[DefaultLoadingAction.CostInsightsInitial],
dispatchInitial: (isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsInitial]: isLoading }),
dispatchInsights: (isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsPage]: isLoading }),
dispatchNone: (loadingActions: string[]) =>
dispatch(getResetState(loadingActions)),
dispatchReset: (loadingActions: string[]) =>
dispatch(getResetStateWithoutInitial(loadingActions)),
});
export const mapLoadingToProps: MapLoadingToProps<CostInsightsPageLoadingProps> =
({ state, actions, dispatch }) => ({
loadingActions: actions,
loadingGroups: state[DefaultLoadingAction.UserGroups],
loadingBillingDate: state[DefaultLoadingAction.LastCompleteBillingDate],
loadingInitial: state[DefaultLoadingAction.CostInsightsInitial],
dispatchInitial: (isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsInitial]: isLoading }),
dispatchInsights: (isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsPage]: isLoading }),
dispatchNone: (loadingActions: string[]) =>
dispatch(getResetState(loadingActions)),
dispatchReset: (loadingActions: string[]) =>
dispatch(getResetStateWithoutInitial(loadingActions)),
});
@@ -28,24 +28,20 @@ type CostInsightsTabsLoadingProps = {
dispatchReset: (loadingActions: string[]) => void;
};
export const mapFiltersToProps: MapFiltersToProps<CostInsightsTabsFilterProps> = ({
pageFilters,
setPageFilters,
}) => ({
...pageFilters,
setGroup: (group: Group) =>
setPageFilters({
...pageFilters,
group: group.id,
project: null,
}),
});
export const mapFiltersToProps: MapFiltersToProps<CostInsightsTabsFilterProps> =
({ pageFilters, setPageFilters }) => ({
...pageFilters,
setGroup: (group: Group) =>
setPageFilters({
...pageFilters,
group: group.id,
project: null,
}),
});
export const mapLoadingToProps: MapLoadingToProps<CostInsightsTabsLoadingProps> = ({
actions,
dispatch,
}) => ({
loadingActions: actions,
dispatchReset: (loadingActions: string[]) =>
dispatch(getResetStateWithoutInitial(loadingActions)),
});
export const mapLoadingToProps: MapLoadingToProps<CostInsightsTabsLoadingProps> =
({ actions, dispatch }) => ({
loadingActions: actions,
dispatchReset: (loadingActions: string[]) =>
dispatch(getResetStateWithoutInitial(loadingActions)),
});
@@ -51,9 +51,8 @@ export const CostOverviewCard = ({
const styles = useOverviewTabsStyles(theme);
const config = useConfig();
const [tabIndex, setTabIndex] = useState(0);
const { setDuration, setProject, setMetric, ...filters } = useFilters(
mapFiltersToProps,
);
const { setDuration, setProject, setMetric, ...filters } =
useFilters(mapFiltersToProps);
// Reset tabIndex if breakdowns available change
useEffect(() => {
@@ -170,7 +170,8 @@ describe('<ProductInsights />', () => {
}
it('should render each product panel', async () => {
const noComputeEngineCostsRgx = /There are no Compute Engine costs within this time frame for your team's projects./;
const noComputeEngineCostsRgx =
/There are no Compute Engine costs within this time frame for your team's projects./;
const { getByText } = await renderInContext(
<ProductInsights
onLoaded={jest.fn()}
@@ -37,9 +37,10 @@ import { useApi } from '@backstage/core-plugin-api';
type LoadingProps = (isLoading: boolean) => void;
const mapLoadingToProps: MapLoadingToProps<LoadingProps> = ({ dispatch }) => (
isLoading: boolean,
) => dispatch({ [DefaultLoadingAction.CostInsightsProducts]: isLoading });
const mapLoadingToProps: MapLoadingToProps<LoadingProps> =
({ dispatch }) =>
(isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsProducts]: isLoading });
type ProductInsightsProps = {
group: string;
@@ -49,9 +49,10 @@ export type ProductInsightsCardProps = {
onSelectAsync: (product: Product, duration: Duration) => Promise<Entity>;
};
const mapLoadingToProps: MapLoadingToProps<LoadingProps> = ({ dispatch }) => (
isLoading: boolean,
) => dispatch({ [DefaultLoadingAction.CostInsightsProducts]: isLoading });
const mapLoadingToProps: MapLoadingToProps<LoadingProps> =
({ dispatch }) =>
(isLoading: boolean) =>
dispatch({ [DefaultLoadingAction.CostInsightsProducts]: isLoading });
export const ProductInsightsCard = ({
initialState,
@@ -29,29 +29,22 @@ type ProductInsightsCardLoadingProps = {
dispatchLoading: (isLoading: boolean) => void;
};
export const mapFiltersToProps = (
product: string,
): MapFiltersToProps<ProductInsightsCardFilterProps> => ({
pageFilters,
productFilters,
setProductFilters,
}) => ({
...pageFilters,
product: findAlways(productFilters, p => p.productType === product),
setProduct: (duration: Duration) =>
setProductFilters(
productFilters.map(period =>
period.productType === product ? { ...period, duration } : period,
export const mapFiltersToProps =
(product: string): MapFiltersToProps<ProductInsightsCardFilterProps> =>
({ pageFilters, productFilters, setProductFilters }) => ({
...pageFilters,
product: findAlways(productFilters, p => p.productType === product),
setProduct: (duration: Duration) =>
setProductFilters(
productFilters.map(period =>
period.productType === product ? { ...period, duration } : period,
),
),
),
});
});
export const mapLoadingToProps = (
product: string,
): MapLoadingToProps<ProductInsightsCardLoadingProps> => ({
state,
dispatch,
}) => ({
loadingProduct: state[product],
dispatchLoading: (isLoading: boolean) => dispatch({ [product]: isLoading }),
});
export const mapLoadingToProps =
(product: string): MapLoadingToProps<ProductInsightsCardLoadingProps> =>
({ state, dispatch }) => ({
loadingProduct: state[product],
dispatchLoading: (isLoading: boolean) => dispatch({ [product]: isLoading }),
});
@@ -22,14 +22,13 @@ import {
} from '../../testUtils';
import { renderInTestApp } from '@backstage/test-utils';
const MockUnlabeledDataflowAlertMultipleProjects = createMockUnlabeledDataflowData(
data => ({
const MockUnlabeledDataflowAlertMultipleProjects =
createMockUnlabeledDataflowData(data => ({
...data,
projects: [...Array(10)].map(() =>
createMockUnlabeledDataflowAlertProject(),
),
}),
);
}));
const MockUnlabeledDataflowAlertSingleProject = createMockUnlabeledDataflowData(
data => ({
@@ -54,9 +54,8 @@ export const FilterProvider = ({ children }: PropsWithChildren<{}>) => {
const groups = useGroups();
const [error, setError] = useState<Maybe<Error>>(null);
const [pageFilters, setPageFilters] = useState<Maybe<PageFilters>>(null);
const [productFilters, setProductFilters] = useState<Maybe<ProductFilters>>(
null,
);
const [productFilters, setProductFilters] =
useState<Maybe<ProductFilters>>(null);
useEffect(() => {
async function setPageFiltersFromLocation() {
@@ -59,9 +59,8 @@ export const BillingDateProvider = ({ children }: PropsWithChildren<{}>) => {
const [error, setError] = useState<Maybe<Error>>(null);
const { dispatchLoadingBillingDate } = useLoading(mapLoadingToProps);
const [lastCompleteBillingDate, setLastCompeteBillingDate] = useState<
Maybe<string>
>(null);
const [lastCompleteBillingDate, setLastCompeteBillingDate] =
useState<Maybe<string>>(null);
useEffect(() => {
dispatchLoadingBillingDate(true);

Some files were not shown because too many files have changed in this diff Show More