run prettier formatting
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
+1
-3
@@ -1,5 +1,3 @@
|
||||
{
|
||||
"ignoredFiles": [
|
||||
"docs/assets/**/*.svg"
|
||||
]
|
||||
"ignoredFiles": ["docs/assets/**/*.svg"]
|
||||
}
|
||||
|
||||
@@ -244,9 +244,7 @@ export interface OAuthProviderHandlers {
|
||||
req: express.Request,
|
||||
options: Record<string, string>,
|
||||
): Promise<RedirectInfo>;
|
||||
handler(
|
||||
req: express.Request,
|
||||
): Promise<{
|
||||
handler(req: express.Request): Promise<{
|
||||
response: AuthResponse<OAuthProviderInfo>;
|
||||
refreshToken?: string;
|
||||
}>;
|
||||
|
||||
@@ -56,13 +56,11 @@ matching repository is processed.
|
||||
repository.
|
||||
|
||||
```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,
|
||||
|
||||
+4
-4
@@ -104,7 +104,7 @@ describe('CacheManager', () => {
|
||||
manager.forPlugin(plugin2Id).getClient({ defaultTtl: expectedTtl });
|
||||
|
||||
const client = DefaultCacheClient as jest.Mock;
|
||||
const cache = (Keyv as unknown) as jest.Mock;
|
||||
const cache = Keyv as unknown as jest.Mock;
|
||||
expect(cache).toHaveBeenCalledTimes(2);
|
||||
expect(client).toHaveBeenCalledTimes(2);
|
||||
|
||||
@@ -124,7 +124,7 @@ describe('CacheManager', () => {
|
||||
const expectedNamespace = 'test-plugin';
|
||||
manager.forPlugin(expectedNamespace).getClient();
|
||||
|
||||
const cache = (Keyv as unknown) as jest.Mock;
|
||||
const cache = Keyv as unknown as jest.Mock;
|
||||
const mockCalls = cache.mock.calls.splice(-1);
|
||||
const callArgs = mockCalls[0];
|
||||
expect(callArgs[0].store).toBeInstanceOf(NoStore);
|
||||
@@ -138,7 +138,7 @@ describe('CacheManager', () => {
|
||||
.forPlugin(expectedNamespace)
|
||||
.getClient({ defaultTtl: expectedTtl });
|
||||
|
||||
const cache = (Keyv as unknown) as jest.Mock;
|
||||
const cache = Keyv as unknown as jest.Mock;
|
||||
const mockCalls = cache.mock.calls.splice(-1);
|
||||
const callArgs = mockCalls[0];
|
||||
expect(callArgs[0]).toMatchObject({
|
||||
@@ -162,7 +162,7 @@ describe('CacheManager', () => {
|
||||
const expectedTtl = 3600;
|
||||
manager.forPlugin('test').getClient({ defaultTtl: expectedTtl });
|
||||
|
||||
const cache = (Keyv as unknown) as jest.Mock;
|
||||
const cache = Keyv as unknown as jest.Mock;
|
||||
const mockCacheCalls = cache.mock.calls.splice(-1);
|
||||
expect(mockCacheCalls[0][0]).toMatchObject({
|
||||
ttl: expectedTtl,
|
||||
|
||||
@@ -110,9 +110,7 @@ export class DatabaseManager {
|
||||
* @returns Object with client type returned as `client` and boolean representing whether
|
||||
* or not the client was overridden as `overridden`
|
||||
*/
|
||||
private getClientType(
|
||||
pluginId: string,
|
||||
): {
|
||||
private getClientType(pluginId: string): {
|
||||
client: string;
|
||||
overridden: boolean;
|
||||
} {
|
||||
|
||||
@@ -149,7 +149,7 @@ export async function ensureMysqlDatabaseExists(
|
||||
) {
|
||||
const admin = createMysqlDatabaseClient(dbConfig, {
|
||||
connection: {
|
||||
database: (null as unknown) as string,
|
||||
database: null as unknown as string,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -78,21 +78,17 @@ describe('AzureUrlReader', () => {
|
||||
|
||||
it.each([
|
||||
{
|
||||
url:
|
||||
'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
config: createConfig(),
|
||||
response: expect.objectContaining({
|
||||
url:
|
||||
'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml&version=master',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml&version=master',
|
||||
}),
|
||||
},
|
||||
{
|
||||
url:
|
||||
'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
config: createConfig(),
|
||||
response: expect.objectContaining({
|
||||
url:
|
||||
'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml',
|
||||
}),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -129,7 +129,7 @@ export class AzureUrlReader implements UrlReader {
|
||||
}
|
||||
|
||||
return await this.deps.treeResponseFactory.fromZipArchive({
|
||||
stream: (archiveAzureResponse.body as unknown) as Readable,
|
||||
stream: archiveAzureResponse.body as unknown as Readable,
|
||||
etag: commitSha,
|
||||
filter: options?.filter,
|
||||
});
|
||||
|
||||
@@ -60,13 +60,8 @@ export class BitbucketUrlReader implements UrlReader {
|
||||
private readonly integration: BitbucketIntegration,
|
||||
private readonly deps: { treeResponseFactory: ReadTreeResponseFactory },
|
||||
) {
|
||||
const {
|
||||
host,
|
||||
apiBaseUrl,
|
||||
token,
|
||||
username,
|
||||
appPassword,
|
||||
} = integration.config;
|
||||
const { host, apiBaseUrl, token, username, appPassword } =
|
||||
integration.config;
|
||||
|
||||
if (!apiBaseUrl) {
|
||||
throw new Error(
|
||||
@@ -138,7 +133,7 @@ export class BitbucketUrlReader implements UrlReader {
|
||||
}
|
||||
|
||||
return await this.deps.treeResponseFactory.fromTarArchive({
|
||||
stream: (archiveBitbucketResponse.body as unknown) as Readable,
|
||||
stream: archiveBitbucketResponse.body as unknown as Readable,
|
||||
subpath: filepath,
|
||||
etag: lastCommitShortHash,
|
||||
filter: options?.filter,
|
||||
|
||||
@@ -41,9 +41,9 @@ const treeResponseFactory = DefaultReadTreeResponseFactory.create({
|
||||
config: new ConfigReader({}),
|
||||
});
|
||||
|
||||
const mockCredentialsProvider = ({
|
||||
const mockCredentialsProvider = {
|
||||
getCredentials: jest.fn().mockResolvedValue({ headers: {} }),
|
||||
} as unknown) as GithubCredentialsProvider;
|
||||
} as unknown as GithubCredentialsProvider;
|
||||
|
||||
const githubProcessor = new GithubUrlReader(
|
||||
new GitHubIntegration(
|
||||
|
||||
@@ -39,10 +39,14 @@ import {
|
||||
ReadUrlResponse,
|
||||
} from './types';
|
||||
|
||||
export type GhRepoResponse = RestEndpointMethodTypes['repos']['get']['response']['data'];
|
||||
export type GhBranchResponse = RestEndpointMethodTypes['repos']['getBranch']['response']['data'];
|
||||
export type GhTreeResponse = RestEndpointMethodTypes['git']['getTree']['response']['data'];
|
||||
export type GhBlobResponse = RestEndpointMethodTypes['git']['getBlob']['response']['data'];
|
||||
export type GhRepoResponse =
|
||||
RestEndpointMethodTypes['repos']['get']['response']['data'];
|
||||
export type GhBranchResponse =
|
||||
RestEndpointMethodTypes['repos']['getBranch']['response']['data'];
|
||||
export type GhTreeResponse =
|
||||
RestEndpointMethodTypes['git']['getTree']['response']['data'];
|
||||
export type GhBlobResponse =
|
||||
RestEndpointMethodTypes['git']['getBlob']['response']['data'];
|
||||
|
||||
/**
|
||||
* A processor that adds the ability to read files from GitHub v3 APIs, such as
|
||||
@@ -195,7 +199,7 @@ export class GithubUrlReader implements UrlReader {
|
||||
return await this.deps.treeResponseFactory.fromTarArchive({
|
||||
// TODO(Rugvip): Underlying implementation of fetch will be node-fetch, we probably want
|
||||
// to stick to using that in exclusively backend code.
|
||||
stream: (archive.body as unknown) as Readable,
|
||||
stream: archive.body as unknown as Readable,
|
||||
subpath,
|
||||
etag: sha,
|
||||
filter: options?.filter,
|
||||
@@ -258,9 +262,7 @@ export class GithubUrlReader implements UrlReader {
|
||||
}));
|
||||
}
|
||||
|
||||
private async getRepoDetails(
|
||||
url: string,
|
||||
): Promise<{
|
||||
private async getRepoDetails(url: string): Promise<{
|
||||
repo: GhRepoResponse;
|
||||
branch: GhBranchResponse;
|
||||
}> {
|
||||
|
||||
@@ -108,36 +108,30 @@ describe('GitlabUrlReader', () => {
|
||||
it.each([
|
||||
// Project URLs
|
||||
{
|
||||
url:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
|
||||
url: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
|
||||
config: createConfig(),
|
||||
response: expect.objectContaining({
|
||||
url:
|
||||
'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
url: 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
headers: expect.objectContaining({
|
||||
'private-token': '',
|
||||
}),
|
||||
}),
|
||||
},
|
||||
{
|
||||
url:
|
||||
'https://gitlab.example.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
|
||||
url: 'https://gitlab.example.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
|
||||
config: createConfig('0123456789'),
|
||||
response: expect.objectContaining({
|
||||
url:
|
||||
'https://gitlab.example.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
url: 'https://gitlab.example.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
headers: expect.objectContaining({
|
||||
'private-token': '0123456789',
|
||||
}),
|
||||
}),
|
||||
},
|
||||
{
|
||||
url:
|
||||
'https://gitlab.com/groupA/teams/teamA/repoA/-/blob/branch/my/path/to/file.yaml', // Repo not in subgroup
|
||||
url: 'https://gitlab.com/groupA/teams/teamA/repoA/-/blob/branch/my/path/to/file.yaml', // Repo not in subgroup
|
||||
config: createConfig(),
|
||||
response: expect.objectContaining({
|
||||
url:
|
||||
'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
url: 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
}),
|
||||
},
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ export class GitlabUrlReader implements UrlReader {
|
||||
}
|
||||
|
||||
return await this.deps.treeResponseFactory.fromTarArchive({
|
||||
stream: (archiveGitLabResponse.body as unknown) as Readable,
|
||||
stream: archiveGitLabResponse.body as unknown as Readable,
|
||||
subpath: filepath,
|
||||
etag: commitSha,
|
||||
filter: options?.filter,
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
import { stripFirstDirectoryFromPath } from './util';
|
||||
|
||||
// Tar types for `Parse` is not a proper constructor, but it should be
|
||||
const TarParseStream = (Parse as unknown) as { new (): ParseStream };
|
||||
const TarParseStream = Parse as unknown as { new (): ParseStream };
|
||||
|
||||
const pipeline = promisify(pipelineCb);
|
||||
|
||||
|
||||
@@ -123,9 +123,9 @@ describe('Git', () => {
|
||||
|
||||
await git.clone({ url, dir });
|
||||
|
||||
const { onAuth } = ((isomorphic.clone as unknown) as jest.Mock<
|
||||
typeof isomorphic['clone']
|
||||
>).mock.calls[0][0]!;
|
||||
const { onAuth } = (
|
||||
isomorphic.clone as unknown as jest.Mock<typeof isomorphic['clone']>
|
||||
).mock.calls[0][0]!;
|
||||
|
||||
expect(onAuth()).toEqual(auth);
|
||||
});
|
||||
@@ -190,9 +190,9 @@ describe('Git', () => {
|
||||
|
||||
await git.fetch({ remote, dir });
|
||||
|
||||
const { onAuth } = ((isomorphic.fetch as unknown) as jest.Mock<
|
||||
typeof isomorphic['fetch']
|
||||
>).mock.calls[0][0]!;
|
||||
const { onAuth } = (
|
||||
isomorphic.fetch as unknown as jest.Mock<typeof isomorphic['fetch']>
|
||||
).mock.calls[0][0]!;
|
||||
|
||||
expect(onAuth()).toEqual(auth);
|
||||
});
|
||||
@@ -279,9 +279,9 @@ describe('Git', () => {
|
||||
|
||||
await git.push({ remote, dir });
|
||||
|
||||
const { onAuth } = ((isomorphic.push as unknown) as jest.Mock<
|
||||
typeof isomorphic['push']
|
||||
>).mock.calls[0][0]!;
|
||||
const { onAuth } = (
|
||||
isomorphic.push as unknown as jest.Mock<typeof isomorphic['push']>
|
||||
).mock.calls[0][0]!;
|
||||
|
||||
expect(onAuth()).toEqual(auth);
|
||||
});
|
||||
|
||||
@@ -154,14 +154,8 @@ export class ServiceBuilderImpl implements ServiceBuilder {
|
||||
|
||||
async start(): Promise<http.Server> {
|
||||
const app = express();
|
||||
const {
|
||||
port,
|
||||
host,
|
||||
logger,
|
||||
corsOptions,
|
||||
httpsSettings,
|
||||
helmetOptions,
|
||||
} = this.getOptions();
|
||||
const { port, host, logger, corsOptions, httpsSettings, helmetOptions } =
|
||||
this.getOptions();
|
||||
|
||||
app.use(helmet(helmetOptions));
|
||||
if (corsOptions) {
|
||||
|
||||
@@ -92,18 +92,17 @@ export class DockerContainerRunner implements ContainerRunner {
|
||||
Env.push(`${key}=${value}`);
|
||||
}
|
||||
|
||||
const [
|
||||
{ Error: error, StatusCode: statusCode },
|
||||
] = await this.dockerClient.run(imageName, args, logStream, {
|
||||
Volumes,
|
||||
HostConfig: {
|
||||
Binds,
|
||||
},
|
||||
...(workingDir ? { WorkingDir: workingDir } : {}),
|
||||
Entrypoint: command,
|
||||
Env,
|
||||
...userOptions,
|
||||
} as Docker.ContainerCreateOptions);
|
||||
const [{ Error: error, StatusCode: statusCode }] =
|
||||
await this.dockerClient.run(imageName, args, logStream, {
|
||||
Volumes,
|
||||
HostConfig: {
|
||||
Binds,
|
||||
},
|
||||
...(workingDir ? { WorkingDir: workingDir } : {}),
|
||||
Entrypoint: command,
|
||||
Env,
|
||||
...userOptions,
|
||||
} as Docker.ContainerCreateOptions);
|
||||
|
||||
if (error) {
|
||||
throw new Error(
|
||||
|
||||
@@ -38,33 +38,31 @@ export type Instance = {
|
||||
databaseManager: DatabaseManager;
|
||||
connections: Array<Knex>;
|
||||
};
|
||||
export const allDatabases: Record<
|
||||
TestDatabaseId,
|
||||
TestDatabaseProperties
|
||||
> = Object.freeze({
|
||||
POSTGRES_13: {
|
||||
name: 'Postgres 13.x',
|
||||
driver: 'pg',
|
||||
dockerImageName: 'postgres:13',
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING',
|
||||
},
|
||||
POSTGRES_9: {
|
||||
name: 'Postgres 9.x',
|
||||
driver: 'pg',
|
||||
dockerImageName: 'postgres:9',
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING',
|
||||
},
|
||||
MYSQL_8: {
|
||||
name: 'MySQL 8.x',
|
||||
driver: 'mysql2',
|
||||
dockerImageName: 'mysql:8',
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING',
|
||||
},
|
||||
SQLITE_3: {
|
||||
name: 'SQLite 3.x',
|
||||
driver: 'sqlite3',
|
||||
},
|
||||
});
|
||||
export const allDatabases: Record<TestDatabaseId, TestDatabaseProperties> =
|
||||
Object.freeze({
|
||||
POSTGRES_13: {
|
||||
name: 'Postgres 13.x',
|
||||
driver: 'pg',
|
||||
dockerImageName: 'postgres:13',
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_DATABASE_POSTGRES13_CONNECTION_STRING',
|
||||
},
|
||||
POSTGRES_9: {
|
||||
name: 'Postgres 9.x',
|
||||
driver: 'pg',
|
||||
dockerImageName: 'postgres:9',
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_DATABASE_POSTGRES9_CONNECTION_STRING',
|
||||
},
|
||||
MYSQL_8: {
|
||||
name: 'MySQL 8.x',
|
||||
driver: 'mysql2',
|
||||
dockerImageName: 'mysql:8',
|
||||
connectionStringEnvironmentVariableName:
|
||||
'BACKSTAGE_TEST_DATABASE_MYSQL8_CONNECTION_STRING',
|
||||
},
|
||||
SQLITE_3: {
|
||||
name: 'SQLite 3.x',
|
||||
driver: 'sqlite3',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -190,7 +190,7 @@ export type EntityEnvelope = {
|
||||
//
|
||||
// @public
|
||||
export function entityEnvelopeSchemaValidator<
|
||||
T extends EntityEnvelope = EntityEnvelope
|
||||
T extends EntityEnvelope = EntityEnvelope,
|
||||
>(schema?: unknown): (data: unknown) => T;
|
||||
|
||||
// Warning: (tsdoc-param-tag-missing-hyphen) The @param block should be followed by a parameter name and then a hyphen
|
||||
@@ -333,9 +333,7 @@ export function getEntityName(entity: Entity): EntityName;
|
||||
// Warning: (ae-missing-release-tag) "getEntitySourceLocation" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public
|
||||
export function getEntitySourceLocation(
|
||||
entity: Entity,
|
||||
): {
|
||||
export function getEntitySourceLocation(entity: Entity): {
|
||||
type: string;
|
||||
target: string;
|
||||
};
|
||||
@@ -542,9 +540,7 @@ export function parseEntityRef(
|
||||
// Warning: (ae-missing-release-tag) "parseLocationReference" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public
|
||||
export function parseLocationReference(
|
||||
ref: string,
|
||||
): {
|
||||
export function parseLocationReference(ref: string): {
|
||||
type: string;
|
||||
target: string;
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('SchemaValidEntityPolicy', () => {
|
||||
//
|
||||
|
||||
it('rejects wrong root type', async () => {
|
||||
await expect(policy.enforce((7 as unknown) as Entity)).rejects.toThrow(
|
||||
await expect(policy.enforce(7 as unknown as Entity)).rejects.toThrow(
|
||||
/object/,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -18,9 +18,7 @@ import { EntityName, EntityRef } from '../types';
|
||||
import { ENTITY_DEFAULT_NAMESPACE } from './constants';
|
||||
import { Entity } from './Entity';
|
||||
|
||||
function parseRefString(
|
||||
ref: string,
|
||||
): {
|
||||
function parseRefString(ref: string): {
|
||||
kind?: string;
|
||||
namespace?: string;
|
||||
name: string;
|
||||
|
||||
@@ -30,6 +30,5 @@ export interface ApiEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const apiEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const apiEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -33,6 +33,5 @@ export interface ComponentEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const componentEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const componentEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -26,6 +26,5 @@ export interface DomainEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const domainEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const domainEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -34,6 +34,5 @@ export interface GroupEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const groupEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const groupEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -28,6 +28,5 @@ export interface LocationEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const locationEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const locationEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -29,6 +29,5 @@ export interface ResourceEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const resourceEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const resourceEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -27,6 +27,5 @@ export interface SystemEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const systemEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const systemEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -40,6 +40,5 @@ export interface TemplateEntityV1beta2 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const templateEntityV1beta2Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const templateEntityV1beta2Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -31,6 +31,5 @@ export interface UserEntityV1alpha1 extends Entity {
|
||||
};
|
||||
}
|
||||
|
||||
export const userEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator(
|
||||
schema,
|
||||
);
|
||||
export const userEntityV1alpha1Validator =
|
||||
ajvCompiledJsonSchemaValidator(schema);
|
||||
|
||||
@@ -26,9 +26,10 @@ import { LOCATION_ANNOTATION, SOURCE_LOCATION_ANNOTATION } from './annotation';
|
||||
* @param ref A string-form location reference, e.g. 'url:https://host'
|
||||
* @returns A location reference, e.g. { type: 'url', target: 'https://host' }
|
||||
*/
|
||||
export function parseLocationReference(
|
||||
ref: string,
|
||||
): { type: string; target: string } {
|
||||
export function parseLocationReference(ref: string): {
|
||||
type: string;
|
||||
target: string;
|
||||
} {
|
||||
if (typeof ref !== 'string') {
|
||||
throw new TypeError(
|
||||
`Unable to parse location reference '${ref}', unexpected argument ${typeof ref}`,
|
||||
@@ -91,9 +92,10 @@ export function stringifyLocationReference(ref: {
|
||||
* using the UrlReader from @backstage/backend-common. If it is not of type 'url', the caller
|
||||
* needs to have explicit handling of each location type or signal that it is not supported.
|
||||
*/
|
||||
export function getEntitySourceLocation(
|
||||
entity: Entity,
|
||||
): { type: string; target: string } {
|
||||
export function getEntitySourceLocation(entity: Entity): {
|
||||
type: string;
|
||||
target: string;
|
||||
} {
|
||||
const locationRef =
|
||||
entity.metadata?.annotations?.[SOURCE_LOCATION_ANNOTATION] ??
|
||||
entity.metadata?.annotations?.[LOCATION_ANNOTATION];
|
||||
|
||||
@@ -41,7 +41,7 @@ import { compileAjvSchema, throwAjvError } from './ajv';
|
||||
* @see https://github.com/backstage/backstage/tree/master/packages/catalog-model/src/schema
|
||||
*/
|
||||
export function entityEnvelopeSchemaValidator<
|
||||
T extends EntityEnvelope = EntityEnvelope
|
||||
T extends EntityEnvelope = EntityEnvelope,
|
||||
>(schema?: unknown): (data: unknown) => T {
|
||||
const validate = compileAjvSchema(
|
||||
schema ? (schema as Schema) : entityEnvelopeSchema,
|
||||
|
||||
@@ -55,11 +55,9 @@ export default async (cmd: Command) => {
|
||||
lockfile.replaceVersions(result.newVersions);
|
||||
await lockfile.save();
|
||||
} else {
|
||||
const [
|
||||
newVersionsForbidden,
|
||||
newVersionsAllowed,
|
||||
] = partition(result.newVersions, ({ name }) =>
|
||||
forbiddenDuplicatesFilter(name),
|
||||
const [newVersionsForbidden, newVersionsAllowed] = partition(
|
||||
result.newVersions,
|
||||
({ name }) => forbiddenDuplicatesFilter(name),
|
||||
);
|
||||
if (newVersionsForbidden.length && !fix) {
|
||||
success = false;
|
||||
|
||||
@@ -30,9 +30,9 @@ export const optimization = (
|
||||
...(!isParallelDefault(options.parallel)
|
||||
? {
|
||||
minimizer: [
|
||||
(new TerserPlugin({
|
||||
new TerserPlugin({
|
||||
parallel: options.parallel,
|
||||
}) as unknown) as WebpackPluginInstance,
|
||||
}) as unknown as WebpackPluginInstance,
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
|
||||
@@ -137,9 +137,9 @@ export class Lockfile {
|
||||
}
|
||||
|
||||
// Find all versions currently in use
|
||||
const versions = Array.from(
|
||||
new Set(entries.map(e => e.version)),
|
||||
).sort((v1, v2) => semver.rcompare(v1, v2));
|
||||
const versions = Array.from(new Set(entries.map(e => e.version))).sort(
|
||||
(v1, v2) => semver.rcompare(v1, v2),
|
||||
);
|
||||
|
||||
// If we're not using at least 2 different versions we're done
|
||||
if (versions.length < 2) {
|
||||
|
||||
Vendored
+3
-4
@@ -30,9 +30,7 @@ declare module '@svgr/rollup' {
|
||||
|
||||
declare module '@rollup/plugin-yaml';
|
||||
declare module 'react-dev-utils/formatWebpackMessages' {
|
||||
export default function (
|
||||
stats: any,
|
||||
): {
|
||||
export default function (stats: any): {
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
};
|
||||
@@ -46,7 +44,8 @@ declare module 'react-dev-utils/ModuleScopePlugin' {
|
||||
import webpack = require('webpack');
|
||||
|
||||
export default class ModuleScopePlugin
|
||||
implements webpack.WebpackPluginInstance {
|
||||
implements webpack.WebpackPluginInstance
|
||||
{
|
||||
constructor(
|
||||
appSrc: string | ReadonlyArray<string>,
|
||||
allowedFiles?: ReadonlyArray<string>,
|
||||
|
||||
@@ -24,9 +24,11 @@ const substituteMe = '${MY_SUBSTITUTION}';
|
||||
const mySubstitution = 'fooSubstitution';
|
||||
|
||||
const env = jest.fn(async (name: string) => {
|
||||
return ({
|
||||
SECRET: 'my-secret',
|
||||
} as { [name: string]: string })[name];
|
||||
return (
|
||||
{
|
||||
SECRET: 'my-secret',
|
||||
} as { [name: string]: string }
|
||||
)[name];
|
||||
});
|
||||
|
||||
const substitute: TransformFunc = async value => {
|
||||
@@ -44,14 +46,16 @@ const substitute: TransformFunc = async value => {
|
||||
};
|
||||
|
||||
const readFile = jest.fn(async (path: string) => {
|
||||
const content = ({
|
||||
[resolvePath(root, 'my-secret')]: 'secret',
|
||||
[resolvePath(root, 'my-data.json')]: '{"a":{"b":{"c":42}}}',
|
||||
[resolvePath(root, 'my-data.yaml')]: 'some:\n yaml:\n key: 7',
|
||||
[resolvePath(root, 'my-data.yml')]: 'different: { key: hello }',
|
||||
[resolvePath(root, 'invalid.yaml')]: 'foo: [}',
|
||||
[resolvePath(root, `${mySubstitution}/my-data.json`)]: '{"foo":"bar"}',
|
||||
} as { [key: string]: string })[path];
|
||||
const content = (
|
||||
{
|
||||
[resolvePath(root, 'my-secret')]: 'secret',
|
||||
[resolvePath(root, 'my-data.json')]: '{"a":{"b":{"c":42}}}',
|
||||
[resolvePath(root, 'my-data.yaml')]: 'some:\n yaml:\n key: 7',
|
||||
[resolvePath(root, 'my-data.yml')]: 'different: { key: hello }',
|
||||
[resolvePath(root, 'invalid.yaml')]: 'foo: [}',
|
||||
[resolvePath(root, `${mySubstitution}/my-data.json`)]: '{"foo":"bar"}',
|
||||
} as { [key: string]: string }
|
||||
)[path];
|
||||
|
||||
if (!content) {
|
||||
throw new Error('File not found!');
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
import { createSubstitutionTransform } from './substitution';
|
||||
|
||||
const env = jest.fn(async (name: string) => {
|
||||
return ({
|
||||
SECRET: 'my-secret',
|
||||
TOKEN: 'my-token',
|
||||
} as { [name: string]: string })[name];
|
||||
return (
|
||||
{
|
||||
SECRET: 'my-secret',
|
||||
TOKEN: 'my-token',
|
||||
} as { [name: string]: string }
|
||||
)[name];
|
||||
});
|
||||
|
||||
const substituteTransform = createSubstitutionTransform(env);
|
||||
|
||||
@@ -64,9 +64,9 @@ function expectValidValues(config: ConfigReader) {
|
||||
strings: ['string1', 'string2'],
|
||||
});
|
||||
expect(config.getConfig('nested').getString('string')).toBe('string');
|
||||
expect(
|
||||
config.getOptionalConfig('nested')!.getStringArray('strings'),
|
||||
).toEqual(['string1', 'string2']);
|
||||
expect(config.getOptionalConfig('nested')!.getStringArray('strings')).toEqual(
|
||||
['string1', 'string2'],
|
||||
);
|
||||
expect(config.getOptional('missing')).toBe(undefined);
|
||||
expect(config.getOptionalConfig('missing')).toBe(undefined);
|
||||
expect(config.getOptionalConfigArray('missing')).toBe(undefined);
|
||||
@@ -234,9 +234,9 @@ describe('ConfigReader', () => {
|
||||
expect(withLogCollector(() => config.getOptional('a'))).toMatchObject({
|
||||
warn: [],
|
||||
});
|
||||
expect(
|
||||
withLogCollector(() => config.getOptionalString('a')),
|
||||
).toMatchObject({ warn: [] });
|
||||
expect(withLogCollector(() => config.getOptionalString('a'))).toMatchObject(
|
||||
{ warn: [] },
|
||||
);
|
||||
expect(
|
||||
withLogCollector(() => config.getOptionalConfigArray('b')),
|
||||
).toMatchObject({ warn: [] });
|
||||
|
||||
@@ -68,9 +68,7 @@ export class AlertApiForwarder implements AlertApi {
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type ApiFactoryHolder = {
|
||||
get<T>(
|
||||
api: ApiRef<T>,
|
||||
):
|
||||
get<T>(api: ApiRef<T>):
|
||||
| ApiFactory<
|
||||
T,
|
||||
T,
|
||||
@@ -86,9 +84,7 @@ export type ApiFactoryHolder = {
|
||||
// @public
|
||||
export class ApiFactoryRegistry implements ApiFactoryHolder {
|
||||
// (undocumented)
|
||||
get<T>(
|
||||
api: ApiRef<T>,
|
||||
):
|
||||
get<T>(api: ApiRef<T>):
|
||||
| ApiFactory<
|
||||
T,
|
||||
T,
|
||||
@@ -105,7 +101,7 @@ export class ApiFactoryRegistry implements ApiFactoryHolder {
|
||||
Impl extends Api,
|
||||
Deps extends {
|
||||
[name in string]: unknown;
|
||||
}
|
||||
},
|
||||
>(scope: ApiFactoryScope, factory: ApiFactory<Api, Impl, Deps>): boolean;
|
||||
}
|
||||
|
||||
@@ -211,7 +207,7 @@ export type AppOptions = {
|
||||
export type AppRouteBinder = <
|
||||
ExternalRoutes extends {
|
||||
[name: string]: ExternalRouteRef;
|
||||
}
|
||||
},
|
||||
>(
|
||||
externalRoutes: ExternalRoutes,
|
||||
targetRoutes: PartialKeys<
|
||||
@@ -469,7 +465,8 @@ export class OAuth2
|
||||
OpenIdConnectApi,
|
||||
ProfileInfoApi,
|
||||
BackstageIdentityApi,
|
||||
SessionApi {
|
||||
SessionApi
|
||||
{
|
||||
// Warning: (ae-forgotten-export) The symbol "Options" needs to be exported by the entry point index.d.ts
|
||||
constructor(options: Options);
|
||||
// Warning: (ae-forgotten-export) The symbol "CreateOptions" needs to be exported by the entry point index.d.ts
|
||||
@@ -561,7 +558,8 @@ export class OneLoginAuth {
|
||||
//
|
||||
// @public (undocumented)
|
||||
export class SamlAuth
|
||||
implements ProfileInfoApi, BackstageIdentityApi, SessionApi {
|
||||
implements ProfileInfoApi, BackstageIdentityApi, SessionApi
|
||||
{
|
||||
// Warning: (ae-forgotten-export) The symbol "SamlSession" needs to be exported by the entry point index.d.ts
|
||||
constructor(sessionManager: SessionManager<SamlSession>);
|
||||
// Warning: (ae-forgotten-export) The symbol "AuthApiCreateOptions" needs to be exported by the entry point index.d.ts
|
||||
|
||||
+1
-2
@@ -194,8 +194,7 @@ describe('FeatureFlags', () => {
|
||||
it('throws an error if length is greater than 150 characters', () => {
|
||||
expect(() =>
|
||||
featureFlags.registerFlag({
|
||||
name:
|
||||
'loremipsumdolorsitametconsecteturadipiscingelitnuncvitaeportaexaullamcorperturpismaurisutmattisnequemorbisediaculisauguevivamuspulvinarcursuseratblandithendreritquisqueuttinciduntmagnavestibulumblanditaugueat',
|
||||
name: 'loremipsumdolorsitametconsecteturadipiscingelitnuncvitaeportaexaullamcorperturpismaurisutmattisnequemorbisediaculisauguevivamuspulvinarcursuseratblandithendreritquisqueuttinciduntmagnavestibulumblanditaugueat',
|
||||
pluginId: 'plugin-three',
|
||||
}),
|
||||
).toThrow(/not exceed 150 characters/i);
|
||||
|
||||
@@ -65,7 +65,8 @@ class OAuth2
|
||||
OpenIdConnectApi,
|
||||
ProfileInfoApi,
|
||||
BackstageIdentityApi,
|
||||
SessionApi {
|
||||
SessionApi
|
||||
{
|
||||
static create({
|
||||
discoveryApi,
|
||||
environment = 'development',
|
||||
|
||||
@@ -185,9 +185,10 @@ describe('ApiProvider', () => {
|
||||
});
|
||||
|
||||
describe('v1 consumer', () => {
|
||||
const ApiContext = getGlobalSingleton<
|
||||
Context<VersionedValue<{ 1: ApiHolder }>>
|
||||
>('api-context');
|
||||
const ApiContext =
|
||||
getGlobalSingleton<Context<VersionedValue<{ 1: ApiHolder }>>>(
|
||||
'api-context',
|
||||
);
|
||||
|
||||
function useMockApiV1<T>(apiRef: ApiRef<T>): T {
|
||||
const impl = useContext(ApiContext)?.atVersion(1)?.get(apiRef);
|
||||
|
||||
@@ -216,37 +216,33 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
[],
|
||||
);
|
||||
|
||||
const {
|
||||
routePaths,
|
||||
routeParents,
|
||||
routeObjects,
|
||||
featureFlags,
|
||||
} = useMemo(() => {
|
||||
const result = traverseElementTree({
|
||||
root: children,
|
||||
discoverers: [childDiscoverer, routeElementDiscoverer],
|
||||
collectors: {
|
||||
routePaths: routePathCollector,
|
||||
routeParents: routeParentCollector,
|
||||
routeObjects: routeObjectCollector,
|
||||
collectedPlugins: pluginCollector,
|
||||
featureFlags: featureFlagCollector,
|
||||
},
|
||||
});
|
||||
const { routePaths, routeParents, routeObjects, featureFlags } =
|
||||
useMemo(() => {
|
||||
const result = traverseElementTree({
|
||||
root: children,
|
||||
discoverers: [childDiscoverer, routeElementDiscoverer],
|
||||
collectors: {
|
||||
routePaths: routePathCollector,
|
||||
routeParents: routeParentCollector,
|
||||
routeObjects: routeObjectCollector,
|
||||
collectedPlugins: pluginCollector,
|
||||
featureFlags: featureFlagCollector,
|
||||
},
|
||||
});
|
||||
|
||||
validateRoutes(result.routePaths, result.routeParents);
|
||||
validateRoutes(result.routePaths, result.routeParents);
|
||||
|
||||
// TODO(Rugvip): Restructure the public API so that we can get an immediate view of
|
||||
// the app, rather than having to wait for the provider to render.
|
||||
// For now we need to push the additional plugins we find during
|
||||
// collection and then make sure we initialize things afterwards.
|
||||
result.collectedPlugins.forEach(plugin => this.plugins.add(plugin));
|
||||
this.verifyPlugins(this.plugins);
|
||||
// TODO(Rugvip): Restructure the public API so that we can get an immediate view of
|
||||
// the app, rather than having to wait for the provider to render.
|
||||
// For now we need to push the additional plugins we find during
|
||||
// collection and then make sure we initialize things afterwards.
|
||||
result.collectedPlugins.forEach(plugin => this.plugins.add(plugin));
|
||||
this.verifyPlugins(this.plugins);
|
||||
|
||||
// Initialize APIs once all plugins are available
|
||||
this.getApiHolder();
|
||||
return result;
|
||||
}, [children]);
|
||||
// Initialize APIs once all plugins are available
|
||||
this.getApiHolder();
|
||||
return result;
|
||||
}, [children]);
|
||||
|
||||
const loadedConfig = useConfigLoader(
|
||||
this.configLoader,
|
||||
@@ -314,10 +310,8 @@ export class PrivateAppImpl implements BackstageApp {
|
||||
}
|
||||
|
||||
getRouter(): ComponentType<{}> {
|
||||
const {
|
||||
Router: RouterComponent,
|
||||
SignInPage: SignInPageComponent,
|
||||
} = this.components;
|
||||
const { Router: RouterComponent, SignInPage: SignInPageComponent } =
|
||||
this.components;
|
||||
|
||||
// This wraps the sign-in page and waits for sign-in to be completed before rendering the app
|
||||
const SignInPageWrapper = ({
|
||||
|
||||
@@ -22,9 +22,10 @@ import { AppContext as AppContextV1 } from './types';
|
||||
import { AppContextProvider } from './AppContext';
|
||||
|
||||
describe('v1 consumer', () => {
|
||||
const AppContext = getGlobalSingleton<
|
||||
Context<VersionedValue<{ 1: AppContextV1 }>>
|
||||
>('app-context');
|
||||
const AppContext =
|
||||
getGlobalSingleton<Context<VersionedValue<{ 1: AppContextV1 }>>>(
|
||||
'app-context',
|
||||
);
|
||||
|
||||
function useMockAppV1(): AppContextV1 {
|
||||
const impl = useContext(AppContext)?.atVersion(1);
|
||||
|
||||
@@ -60,7 +60,7 @@ export const defaultConfigLoader: AppConfigLoader = async (
|
||||
if (!Array.isArray(appConfig)) {
|
||||
throw new Error('Static configuration has invalid format');
|
||||
}
|
||||
const configs = (appConfig.slice() as unknown) as AppConfig[];
|
||||
const configs = appConfig.slice() as unknown as AppConfig[];
|
||||
|
||||
// Avoiding this string also being replaced at runtime
|
||||
if (
|
||||
|
||||
@@ -105,14 +105,14 @@ type KeysWithType<Obj extends { [key in string]: any }, Type> = {
|
||||
*/
|
||||
type PartialKeys<
|
||||
Map extends { [name in string]: any },
|
||||
Keys extends keyof Map
|
||||
Keys extends keyof Map,
|
||||
> = Partial<Pick<Map, Keys>> & Required<Omit<Map, Keys>>;
|
||||
|
||||
/**
|
||||
* Creates a map of target routes with matching parameters based on a map of external routes.
|
||||
*/
|
||||
type TargetRouteMap<
|
||||
ExternalRoutes extends { [name: string]: ExternalRouteRef }
|
||||
ExternalRoutes extends { [name: string]: ExternalRouteRef },
|
||||
> = {
|
||||
[name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<
|
||||
infer Params,
|
||||
@@ -123,7 +123,7 @@ type TargetRouteMap<
|
||||
};
|
||||
|
||||
export type AppRouteBinder = <
|
||||
ExternalRoutes extends { [name: string]: ExternalRouteRef }
|
||||
ExternalRoutes extends { [name: string]: ExternalRouteRef },
|
||||
>(
|
||||
externalRoutes: ExternalRoutes,
|
||||
targetRoutes: PartialKeys<
|
||||
|
||||
@@ -28,7 +28,7 @@ const ERROR_MESSAGE = 'Import this from @backstage/core-plugin-api';
|
||||
|
||||
/** @deprecated Import from @backstage/core-plugin-api instead */
|
||||
export function createRoutableExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(_options: {
|
||||
component: () => Promise<T>;
|
||||
mountPoint: RouteRef;
|
||||
@@ -38,14 +38,14 @@ export function createRoutableExtension<
|
||||
|
||||
/** @deprecated Import from @backstage/core-plugin-api instead */
|
||||
export function createComponentExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(_options: { component: ComponentLoader<T> }): Extension<T> {
|
||||
throw new Error(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
/** @deprecated Import from @backstage/core-plugin-api instead */
|
||||
export function createReactExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(_options: {
|
||||
component: ComponentLoader<T>;
|
||||
data?: Record<string, unknown>;
|
||||
|
||||
@@ -126,8 +126,7 @@ describe('DefaultAuthConnector', () => {
|
||||
|
||||
expect(popupSpy).toBeCalledTimes(1);
|
||||
expect(popupSpy.mock.calls[0][0]).toMatchObject({
|
||||
url:
|
||||
'http://my-host/api/auth/my-provider/start?scope=a%20b&env=production',
|
||||
url: 'http://my-host/api/auth/my-provider/start?scope=a%20b&env=production',
|
||||
});
|
||||
|
||||
await expect(sessionPromise).resolves.toEqual({
|
||||
@@ -175,8 +174,7 @@ describe('DefaultAuthConnector', () => {
|
||||
|
||||
expect(popupSpy).toBeCalledTimes(1);
|
||||
expect(popupSpy.mock.calls[0][0]).toMatchObject({
|
||||
url:
|
||||
'http://my-host/api/auth/my-provider/start?scope=-ab-&env=production',
|
||||
url: 'http://my-host/api/auth/my-provider/start?scope=-ab-&env=production',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,7 +61,8 @@ function defaultJoinScopes(scopes: Set<string>) {
|
||||
* via the OAuthRequestApi.
|
||||
*/
|
||||
export class DefaultAuthConnector<AuthSession>
|
||||
implements AuthConnector<AuthSession> {
|
||||
implements AuthConnector<AuthSession>
|
||||
{
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly environment: string;
|
||||
private readonly provider: AuthProvider & { id: string };
|
||||
|
||||
@@ -30,8 +30,7 @@ describe('showLoginPopup', () => {
|
||||
const removeEventListenerSpy = jest.spyOn(window, 'removeEventListener');
|
||||
|
||||
const payloadPromise = showLoginPopup({
|
||||
url:
|
||||
'my-origin/api/backend/auth/start?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fa%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fb',
|
||||
url: 'my-origin/api/backend/auth/start?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fa%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fb',
|
||||
name: 'test-popup',
|
||||
origin: 'my-origin',
|
||||
});
|
||||
|
||||
@@ -29,7 +29,8 @@ import ObservableImpl from 'zen-observable';
|
||||
* See http://reactivex.io/documentation/subject.html
|
||||
*/
|
||||
export class PublishSubject<T>
|
||||
implements Observable<T>, ZenObservable.SubscriptionObserver<T> {
|
||||
implements Observable<T>, ZenObservable.SubscriptionObserver<T>
|
||||
{
|
||||
private isClosed = false;
|
||||
private terminatingError?: Error;
|
||||
|
||||
@@ -121,7 +122,8 @@ export class PublishSubject<T>
|
||||
* See http://reactivex.io/documentation/subject.html
|
||||
*/
|
||||
export class BehaviorSubject<T>
|
||||
implements Observable<T>, ZenObservable.SubscriptionObserver<T> {
|
||||
implements Observable<T>, ZenObservable.SubscriptionObserver<T>
|
||||
{
|
||||
private isClosed = false;
|
||||
private currentValue: T;
|
||||
private terminatingError?: Error;
|
||||
|
||||
@@ -29,7 +29,7 @@ export type VersionedValue<Versions extends { [version: number]: any }> = {
|
||||
* Creates a container for a map of versioned values that implements VersionedValue.
|
||||
*/
|
||||
export function createVersionedValueMap<
|
||||
Versions extends { [version: number]: any }
|
||||
Versions extends { [version: number]: any },
|
||||
>(versions: Versions): VersionedValue<Versions> {
|
||||
Object.freeze(versions);
|
||||
return {
|
||||
|
||||
@@ -37,11 +37,11 @@ function makeRouteRenderer(node: ReactNode) {
|
||||
<Wrapper>
|
||||
<AppContextProvider
|
||||
appContext={
|
||||
({
|
||||
{
|
||||
getComponents: () => ({
|
||||
NotFoundErrorPage: () => <>Not Found</>,
|
||||
}),
|
||||
} as unknown) as AppContext
|
||||
} as unknown as AppContext
|
||||
}
|
||||
>
|
||||
<MemoryRouter initialEntries={[path]} children={node} />
|
||||
|
||||
@@ -330,9 +330,10 @@ describe('discovery', () => {
|
||||
});
|
||||
|
||||
describe('v1 consumer', () => {
|
||||
const RoutingContext = getGlobalSingleton<
|
||||
Context<VersionedValue<{ 1: RouteResolver }>>
|
||||
>('routing-context');
|
||||
const RoutingContext =
|
||||
getGlobalSingleton<Context<VersionedValue<{ 1: RouteResolver }>>>(
|
||||
'routing-context',
|
||||
);
|
||||
|
||||
function useMockRouteRefV1(
|
||||
routeRef: AnyRouteRef,
|
||||
|
||||
@@ -75,7 +75,7 @@ export function isSubRouteRef<Params extends AnyParams>(
|
||||
|
||||
export function isExternalRouteRef<
|
||||
Params extends AnyParams,
|
||||
Optional extends boolean
|
||||
Optional extends boolean,
|
||||
>(
|
||||
routeRef:
|
||||
| RouteRef<Params>
|
||||
|
||||
@@ -38,10 +38,8 @@ export function DefaultNode({ node: { id } }: RenderNodeProps) {
|
||||
React.useLayoutEffect(() => {
|
||||
// set the width to the length of the ID
|
||||
if (idRef.current) {
|
||||
let {
|
||||
height: renderedHeight,
|
||||
width: renderedWidth,
|
||||
} = idRef.current.getBBox();
|
||||
let { height: renderedHeight, width: renderedWidth } =
|
||||
idRef.current.getBBox();
|
||||
renderedHeight = Math.round(renderedHeight);
|
||||
renderedWidth = Math.round(renderedWidth);
|
||||
|
||||
|
||||
@@ -132,10 +132,8 @@ export function DependencyGraph({
|
||||
|
||||
container.call(zoom);
|
||||
|
||||
const {
|
||||
width: newContainerWidth,
|
||||
height: newContainerHeight,
|
||||
} = node.getBoundingClientRect();
|
||||
const { width: newContainerWidth, height: newContainerHeight } =
|
||||
node.getBoundingClientRect();
|
||||
if (containerWidth !== newContainerWidth) {
|
||||
setContainerWidth(newContainerWidth);
|
||||
}
|
||||
|
||||
@@ -71,10 +71,8 @@ export function Edge({
|
||||
React.useLayoutEffect(() => {
|
||||
// set the label width to the actual rendered width to properly layout graph
|
||||
if (labelRef.current) {
|
||||
let {
|
||||
height: renderedHeight,
|
||||
width: renderedWidth,
|
||||
} = labelRef.current.getBBox();
|
||||
let { height: renderedHeight, width: renderedWidth } =
|
||||
labelRef.current.getBBox();
|
||||
renderedHeight = Math.round(renderedHeight);
|
||||
renderedWidth = Math.round(renderedWidth);
|
||||
|
||||
|
||||
@@ -46,10 +46,8 @@ export function Node({
|
||||
React.useLayoutEffect(() => {
|
||||
// set the node width to the actual rendered width to properly layout graph
|
||||
if (nodeRef.current) {
|
||||
let {
|
||||
height: renderedHeight,
|
||||
width: renderedWidth,
|
||||
} = nodeRef.current.getBBox();
|
||||
let { height: renderedHeight, width: renderedWidth } =
|
||||
nodeRef.current.getBBox();
|
||||
renderedHeight = Math.round(renderedHeight);
|
||||
renderedWidth = Math.round(renderedWidth);
|
||||
|
||||
|
||||
@@ -38,9 +38,10 @@ function useCalloutStates(): {
|
||||
return { states, setState };
|
||||
}
|
||||
|
||||
function useCalloutHasBeenSeen(
|
||||
featureId: string,
|
||||
): { seen: boolean | undefined; markSeen: () => void } {
|
||||
function useCalloutHasBeenSeen(featureId: string): {
|
||||
seen: boolean | undefined;
|
||||
markSeen: () => void;
|
||||
} {
|
||||
const { states, setState } = useCalloutStates();
|
||||
|
||||
const markSeen = useCallback(() => {
|
||||
@@ -50,9 +51,10 @@ function useCalloutHasBeenSeen(
|
||||
return { seen: states[featureId] === true, markSeen };
|
||||
}
|
||||
|
||||
export function useShowCallout(
|
||||
featureId: string,
|
||||
): { show: boolean; hide: () => void } {
|
||||
export function useShowCallout(featureId: string): {
|
||||
show: boolean;
|
||||
hide: () => void;
|
||||
} {
|
||||
const { seen, markSeen } = useCalloutHasBeenSeen(featureId);
|
||||
return { show: seen === false, hide: markSeen };
|
||||
}
|
||||
|
||||
@@ -96,14 +96,14 @@ interface StyleProps extends WithStyles {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const MetadataList = withStyles(
|
||||
listStyles,
|
||||
)(({ classes, children }: StyleProps) => (
|
||||
<ul className={classes.root}>{children}</ul>
|
||||
));
|
||||
export const MetadataList = withStyles(listStyles)(
|
||||
({ classes, children }: StyleProps) => (
|
||||
<ul className={classes.root}>{children}</ul>
|
||||
),
|
||||
);
|
||||
|
||||
export const MetadataListItem = withStyles(
|
||||
listItemStyles,
|
||||
)(({ classes, children }: StyleProps) => (
|
||||
<li className={classes.root}>{children}</li>
|
||||
));
|
||||
export const MetadataListItem = withStyles(listItemStyles)(
|
||||
({ classes, children }: StyleProps) => (
|
||||
<li className={classes.root}>{children}</li>
|
||||
),
|
||||
);
|
||||
|
||||
+10
-10
@@ -44,16 +44,16 @@ interface StyleProps extends WithStyles {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
// Sub Components
|
||||
const StyledList = withStyles(
|
||||
listStyle,
|
||||
)(({ classes, children }: StyleProps) => (
|
||||
<MetadataList classes={classes}>{children}</MetadataList>
|
||||
));
|
||||
const StyledNestedList = withStyles(
|
||||
nestedListStyle,
|
||||
)(({ classes, children }: StyleProps) => (
|
||||
<MetadataList classes={classes}>{children}</MetadataList>
|
||||
));
|
||||
const StyledList = withStyles(listStyle)(
|
||||
({ classes, children }: StyleProps) => (
|
||||
<MetadataList classes={classes}>{children}</MetadataList>
|
||||
),
|
||||
);
|
||||
const StyledNestedList = withStyles(nestedListStyle)(
|
||||
({ classes, children }: StyleProps) => (
|
||||
<MetadataList classes={classes}>{children}</MetadataList>
|
||||
),
|
||||
);
|
||||
|
||||
function renderList(list: Array<any>, nested?: boolean) {
|
||||
const values = list.map((item: any, index: number) => (
|
||||
|
||||
@@ -20,9 +20,11 @@ import { Content } from '../../layout/Content';
|
||||
import { HeaderTabs } from '../../layout/HeaderTabs';
|
||||
import { SubRoute } from './types';
|
||||
|
||||
export function useSelectedSubRoute(
|
||||
subRoutes: SubRoute[],
|
||||
): { index: number; route: SubRoute; element: JSX.Element } {
|
||||
export function useSelectedSubRoute(subRoutes: SubRoute[]): {
|
||||
index: number;
|
||||
route: SubRoute;
|
||||
element: JSX.Element;
|
||||
} {
|
||||
const params = useParams();
|
||||
|
||||
const routes = subRoutes.map(({ path, children }) => ({
|
||||
|
||||
@@ -285,9 +285,10 @@ export function Table<T extends object = {}>({
|
||||
const [filtersOpen, setFiltersOpen] = useState(
|
||||
calculatedInitialState.filtersOpen,
|
||||
);
|
||||
const toggleFilters = useCallback(() => setFiltersOpen(v => !v), [
|
||||
setFiltersOpen,
|
||||
]);
|
||||
const toggleFilters = useCallback(
|
||||
() => setFiltersOpen(v => !v),
|
||||
[setFiltersOpen],
|
||||
);
|
||||
const [selectedFiltersLength, setSelectedFiltersLength] = useState(0);
|
||||
const [tableData, setTableData] = useState(data as any[]);
|
||||
const [selectedFilters, setSelectedFilters] = useState(
|
||||
|
||||
@@ -42,8 +42,7 @@ const DEFAULT_SUPPORT_CONFIG: SupportConfig = {
|
||||
{
|
||||
// TODO: Update to dedicated support page on backstage.io/docs
|
||||
title: 'Add `app.support` config key',
|
||||
url:
|
||||
'https://github.com/andrewthauer/backstage/blob/master/app-config.yaml',
|
||||
url: 'https://github.com/andrewthauer/backstage/blob/master/app-config.yaml',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -42,18 +42,14 @@ describe('<ErrorBoundary/>', () => {
|
||||
it('should render error boundary with and without error', async () => {
|
||||
const { error } = await withLogCollector(['error'], async () => {
|
||||
const apis = ApiRegistry.with(errorApiRef, new MockErrorApi());
|
||||
const {
|
||||
rerender,
|
||||
queryByRole,
|
||||
getByRole,
|
||||
getByText,
|
||||
} = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ErrorBoundary>
|
||||
<Bomb />
|
||||
</ErrorBoundary>
|
||||
</ApiProvider>,
|
||||
);
|
||||
const { rerender, queryByRole, getByRole, getByText } =
|
||||
await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ErrorBoundary>
|
||||
<Bomb />
|
||||
</ErrorBoundary>
|
||||
</ApiProvider>,
|
||||
);
|
||||
|
||||
expect(queryByRole('alert')).not.toBeInTheDocument();
|
||||
expect(getByText(/working component/i)).toBeInTheDocument();
|
||||
|
||||
@@ -133,10 +133,8 @@ export const SidebarIntro = () => {
|
||||
starredItemsDismissed: false,
|
||||
recentlyViewedItemsDismissed: false,
|
||||
};
|
||||
const [
|
||||
dismissedIntro,
|
||||
setDismissedIntro,
|
||||
] = useLocalStorage<SidebarIntroLocalStorage>(SIDEBAR_INTRO_LOCAL_STORAGE);
|
||||
const [dismissedIntro, setDismissedIntro] =
|
||||
useLocalStorage<SidebarIntroLocalStorage>(SIDEBAR_INTRO_LOCAL_STORAGE);
|
||||
|
||||
const { starredItemsDismissed, recentlyViewedItemsDismissed } =
|
||||
dismissedIntro ?? {};
|
||||
|
||||
@@ -58,7 +58,7 @@ export type ApiFactory<
|
||||
Impl extends Api,
|
||||
Deps extends {
|
||||
[name in string]: unknown;
|
||||
}
|
||||
},
|
||||
> = {
|
||||
api: ApiRef<Api>;
|
||||
deps: TypesToApiRefs<Deps>;
|
||||
@@ -86,7 +86,7 @@ export type ApiRef<T> = {
|
||||
export type ApiRefsToTypes<
|
||||
T extends {
|
||||
[key in string]: ApiRef<unknown>;
|
||||
}
|
||||
},
|
||||
> = {
|
||||
[key in keyof T]: ApiRefType<T[key]>;
|
||||
};
|
||||
@@ -216,7 +216,7 @@ export type BackstageIdentityApi = {
|
||||
// @public (undocumented)
|
||||
export type BackstagePlugin<
|
||||
Routes extends AnyRoutes = {},
|
||||
ExternalRoutes extends AnyExternalRoutes = {}
|
||||
ExternalRoutes extends AnyExternalRoutes = {},
|
||||
> = {
|
||||
getId(): string;
|
||||
output(): PluginOutput[];
|
||||
@@ -253,7 +253,7 @@ export function createApiFactory<
|
||||
Impl extends Api,
|
||||
Deps extends {
|
||||
[name in string]: unknown;
|
||||
}
|
||||
},
|
||||
>(factory: ApiFactory<Api, Impl, Deps>): ApiFactory<Api, Impl, Deps>;
|
||||
|
||||
// @public (undocumented)
|
||||
@@ -272,7 +272,7 @@ export function createApiRef<T>(config: ApiRefConfig): ApiRef<T>;
|
||||
//
|
||||
// @public (undocumented)
|
||||
export function createComponentExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(options: { component: ComponentLoader<T> }): Extension<T>;
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "OptionalParams" needs to be exported by the entry point index.d.ts
|
||||
@@ -284,7 +284,7 @@ export function createExternalRouteRef<
|
||||
[param in ParamKey]: string;
|
||||
},
|
||||
Optional extends boolean = false,
|
||||
ParamKey extends string = never
|
||||
ParamKey extends string = never,
|
||||
>(options: {
|
||||
id: string;
|
||||
params?: ParamKey[];
|
||||
@@ -296,7 +296,7 @@ export function createExternalRouteRef<
|
||||
// @public (undocumented)
|
||||
export function createPlugin<
|
||||
Routes extends AnyRoutes = {},
|
||||
ExternalRoutes extends AnyExternalRoutes = {}
|
||||
ExternalRoutes extends AnyExternalRoutes = {},
|
||||
>(
|
||||
config: PluginConfig<Routes, ExternalRoutes>,
|
||||
): BackstagePlugin<Routes, ExternalRoutes>;
|
||||
@@ -305,7 +305,7 @@ export function createPlugin<
|
||||
//
|
||||
// @public (undocumented)
|
||||
export function createReactExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(options: {
|
||||
component: ComponentLoader<T>;
|
||||
data?: Record<string, unknown>;
|
||||
@@ -315,7 +315,7 @@ export function createReactExtension<
|
||||
//
|
||||
// @public (undocumented)
|
||||
export function createRoutableExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(options: { component: () => Promise<T>; mountPoint: RouteRef }): Extension<T>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "createRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
@@ -325,7 +325,7 @@ export function createRouteRef<
|
||||
Params extends {
|
||||
[param in ParamKey]: string;
|
||||
},
|
||||
ParamKey extends string = never
|
||||
ParamKey extends string = never,
|
||||
>(config: {
|
||||
id?: string;
|
||||
params?: ParamKey[];
|
||||
@@ -342,7 +342,7 @@ export function createRouteRef<
|
||||
// @public (undocumented)
|
||||
export function createSubRouteRef<
|
||||
Path extends string,
|
||||
ParentParams extends AnyParams = never
|
||||
ParentParams extends AnyParams = never,
|
||||
>(config: {
|
||||
id: string;
|
||||
path: Path;
|
||||
@@ -369,7 +369,7 @@ export interface ElementCollection {
|
||||
getElements<
|
||||
Props extends {
|
||||
[name: string]: unknown;
|
||||
}
|
||||
},
|
||||
>(): Array<ReactElement<Props>>;
|
||||
selectByComponentData(query: {
|
||||
key: string;
|
||||
@@ -421,7 +421,7 @@ export type Extension<T> = {
|
||||
// @public (undocumented)
|
||||
export type ExternalRouteRef<
|
||||
Params extends AnyParams = any,
|
||||
Optional extends boolean = any
|
||||
Optional extends boolean = any,
|
||||
> = {
|
||||
readonly [routeRefType]: 'external';
|
||||
params: ParamKeys<Params>;
|
||||
@@ -667,7 +667,7 @@ export type PendingAuthRequest = {
|
||||
// @public (undocumented)
|
||||
export type PluginConfig<
|
||||
Routes extends AnyRoutes,
|
||||
ExternalRoutes extends AnyExternalRoutes
|
||||
ExternalRoutes extends AnyExternalRoutes,
|
||||
> = {
|
||||
id: string;
|
||||
apis?: Iterable<AnyApiFactory>;
|
||||
@@ -885,9 +885,7 @@ export function useRouteRefParams<Params extends AnyParams>(
|
||||
// Warning: (ae-missing-release-tag) "withApis" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export function withApis<T>(
|
||||
apis: TypesToApiRefs<T>,
|
||||
): <P extends T>(
|
||||
export function withApis<T>(apis: TypesToApiRefs<T>): <P extends T>(
|
||||
WrappedComponent: React_2.ComponentType<P>,
|
||||
) => {
|
||||
(props: React_2.PropsWithChildren<Omit<P, keyof T>>): JSX.Element;
|
||||
|
||||
@@ -24,7 +24,7 @@ import { ApiRef, ApiFactory, TypesToApiRefs } from './types';
|
||||
export function createApiFactory<
|
||||
Api,
|
||||
Impl extends Api,
|
||||
Deps extends { [name in string]: unknown }
|
||||
Deps extends { [name in string]: unknown },
|
||||
>(factory: ApiFactory<Api, Impl, Deps>): ApiFactory<Api, Impl, Deps>;
|
||||
export function createApiFactory<Api, Impl extends Api>(
|
||||
api: ApiRef<Api>,
|
||||
@@ -33,7 +33,7 @@ export function createApiFactory<Api, Impl extends Api>(
|
||||
export function createApiFactory<
|
||||
Api,
|
||||
Impl extends Api,
|
||||
Deps extends { [name in string]: unknown }
|
||||
Deps extends { [name in string]: unknown },
|
||||
>(
|
||||
factory: ApiFactory<Api, Impl, Deps> | ApiRef<Api>,
|
||||
instance?: Impl,
|
||||
|
||||
@@ -36,7 +36,7 @@ export type ApiHolder = {
|
||||
export type ApiFactory<
|
||||
Api,
|
||||
Impl extends Api,
|
||||
Deps extends { [name in string]: unknown }
|
||||
Deps extends { [name in string]: unknown },
|
||||
> = {
|
||||
api: ApiRef<Api>;
|
||||
deps: TypesToApiRefs<Deps>;
|
||||
|
||||
@@ -18,9 +18,8 @@ import { useVersionedContext } from '../lib/versionedValues';
|
||||
import { AppContext as AppContextV1 } from './types';
|
||||
|
||||
export const useApp = (): AppContextV1 => {
|
||||
const versionedContext = useVersionedContext<{ 1: AppContextV1 }>(
|
||||
'app-context',
|
||||
);
|
||||
const versionedContext =
|
||||
useVersionedContext<{ 1: AppContextV1 }>('app-context');
|
||||
const appContext = versionedContext.atVersion(1);
|
||||
if (!appContext) {
|
||||
throw new Error('AppContext v1 not available');
|
||||
|
||||
@@ -33,7 +33,7 @@ type ComponentLoader<T> =
|
||||
// ComponentType inserts children as an optional prop whether the inner component accepts it or not,
|
||||
// making it impossible to make the usage of children type safe.
|
||||
export function createRoutableExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(options: {
|
||||
component: () => Promise<T>;
|
||||
mountPoint: RouteRef;
|
||||
@@ -91,7 +91,7 @@ export function createRoutableExtension<
|
||||
// ComponentType inserts children as an optional prop whether the inner component accepts it or not,
|
||||
// making it impossible to make the usage of children type safe.
|
||||
export function createComponentExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(options: { component: ComponentLoader<T> }): Extension<T> {
|
||||
const { component } = options;
|
||||
return createReactExtension({ component });
|
||||
@@ -101,7 +101,7 @@ export function createComponentExtension<
|
||||
// ComponentType inserts children as an optional prop whether the inner component accepts it or not,
|
||||
// making it impossible to make the usage of children type safe.
|
||||
export function createReactExtension<
|
||||
T extends (props: any) => JSX.Element | null
|
||||
T extends (props: any) => JSX.Element | null,
|
||||
>(options: {
|
||||
component: ComponentLoader<T>;
|
||||
data?: Record<string, unknown>;
|
||||
@@ -111,9 +111,9 @@ export function createReactExtension<
|
||||
let Component: T;
|
||||
if ('lazy' in options.component) {
|
||||
const lazyLoader = options.component.lazy;
|
||||
Component = (lazy(() =>
|
||||
Component = lazy(() =>
|
||||
lazyLoader().then(component => ({ default: component })),
|
||||
) as unknown) as T;
|
||||
) as unknown as T;
|
||||
} else {
|
||||
Component = options.component.sync;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export type VersionedValue<Versions extends { [version: number]: any }> = {
|
||||
* Creates a container for a map of versioned values that implements VersionedValue.
|
||||
*/
|
||||
export function createVersionedValueMap<
|
||||
Versions extends { [version: number]: any }
|
||||
Versions extends { [version: number]: any },
|
||||
>(versions: Versions): VersionedValue<Versions> {
|
||||
Object.freeze(versions);
|
||||
return {
|
||||
@@ -43,7 +43,7 @@ export function createVersionedValueMap<
|
||||
}
|
||||
|
||||
export function useVersionedContext<
|
||||
Versions extends { [version in number]: any }
|
||||
Versions extends { [version in number]: any },
|
||||
>(key: string): VersionedValue<Versions> {
|
||||
const versionedValue = useContext(
|
||||
getGlobalSingleton<Context<VersionedValue<Versions>>>(key),
|
||||
|
||||
@@ -26,8 +26,9 @@ import { AnyApiFactory } from '../apis';
|
||||
|
||||
export class PluginImpl<
|
||||
Routes extends AnyRoutes,
|
||||
ExternalRoutes extends AnyExternalRoutes
|
||||
> implements BackstagePlugin<Routes, ExternalRoutes> {
|
||||
ExternalRoutes extends AnyExternalRoutes,
|
||||
> implements BackstagePlugin<Routes, ExternalRoutes>
|
||||
{
|
||||
private storedOutput?: PluginOutput[];
|
||||
|
||||
constructor(private readonly config: PluginConfig<Routes, ExternalRoutes>) {}
|
||||
@@ -81,7 +82,7 @@ export class PluginImpl<
|
||||
|
||||
export function createPlugin<
|
||||
Routes extends AnyRoutes = {},
|
||||
ExternalRoutes extends AnyExternalRoutes = {}
|
||||
ExternalRoutes extends AnyExternalRoutes = {},
|
||||
>(
|
||||
config: PluginConfig<Routes, ExternalRoutes>,
|
||||
): BackstagePlugin<Routes, ExternalRoutes> {
|
||||
|
||||
@@ -42,7 +42,7 @@ export type AnyExternalRoutes = { [name: string]: ExternalRouteRef };
|
||||
|
||||
export type BackstagePlugin<
|
||||
Routes extends AnyRoutes = {},
|
||||
ExternalRoutes extends AnyExternalRoutes = {}
|
||||
ExternalRoutes extends AnyExternalRoutes = {},
|
||||
> = {
|
||||
getId(): string;
|
||||
output(): PluginOutput[];
|
||||
@@ -54,7 +54,7 @@ export type BackstagePlugin<
|
||||
|
||||
export type PluginConfig<
|
||||
Routes extends AnyRoutes,
|
||||
ExternalRoutes extends AnyExternalRoutes
|
||||
ExternalRoutes extends AnyExternalRoutes,
|
||||
> = {
|
||||
id: string;
|
||||
apis?: Iterable<AnyApiFactory>;
|
||||
|
||||
@@ -24,8 +24,9 @@ import {
|
||||
|
||||
export class ExternalRouteRefImpl<
|
||||
Params extends AnyParams,
|
||||
Optional extends boolean
|
||||
> implements ExternalRouteRef<Params, Optional> {
|
||||
Optional extends boolean,
|
||||
> implements ExternalRouteRef<Params, Optional>
|
||||
{
|
||||
readonly [routeRefType] = 'external';
|
||||
|
||||
constructor(
|
||||
@@ -42,7 +43,7 @@ export class ExternalRouteRefImpl<
|
||||
export function createExternalRouteRef<
|
||||
Params extends { [param in ParamKey]: string },
|
||||
Optional extends boolean = false,
|
||||
ParamKey extends string = never
|
||||
ParamKey extends string = never,
|
||||
>(options: {
|
||||
/**
|
||||
* An identifier for this route, used to identify it in error messages
|
||||
|
||||
@@ -32,7 +32,8 @@ export type RouteRefConfig<Params extends AnyParams> = {
|
||||
};
|
||||
|
||||
export class RouteRefImpl<Params extends AnyParams>
|
||||
implements RouteRef<Params> {
|
||||
implements RouteRef<Params>
|
||||
{
|
||||
readonly [routeRefType] = 'absolute';
|
||||
|
||||
constructor(
|
||||
@@ -70,7 +71,7 @@ export function createRouteRef<
|
||||
// ParamKey is here to make sure the Params type properly has its keys narrowed down
|
||||
// to only the elements of params. Defaulting to never makes sure we end up with
|
||||
// Param = {} if the params array is empty.
|
||||
ParamKey extends string = never
|
||||
ParamKey extends string = never,
|
||||
>(config: {
|
||||
/** The id of the route ref, used to identify it when printed */
|
||||
id?: string;
|
||||
|
||||
@@ -27,7 +27,8 @@ import {
|
||||
const PARAM_PATTERN = /^\w+$/;
|
||||
|
||||
export class SubRouteRefImpl<Params extends AnyParams>
|
||||
implements SubRouteRef<Params> {
|
||||
implements SubRouteRef<Params>
|
||||
{
|
||||
readonly [routeRefType] = 'sub';
|
||||
|
||||
constructor(
|
||||
@@ -55,7 +56,7 @@ type PathParams<S extends string> = { [name in ParamNames<S>]: string };
|
||||
*/
|
||||
type MergeParams<
|
||||
P1 extends { [param in string]: string },
|
||||
P2 extends AnyParams
|
||||
P2 extends AnyParams,
|
||||
> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);
|
||||
|
||||
/**
|
||||
@@ -64,14 +65,14 @@ type MergeParams<
|
||||
*/
|
||||
type MakeSubRouteRef<
|
||||
Params extends { [param in string]: string },
|
||||
ParentParams extends AnyParams
|
||||
ParentParams extends AnyParams,
|
||||
> = keyof Params & keyof ParentParams extends never
|
||||
? SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>
|
||||
: never;
|
||||
|
||||
export function createSubRouteRef<
|
||||
Path extends string,
|
||||
ParentParams extends AnyParams = never
|
||||
ParentParams extends AnyParams = never,
|
||||
>(config: {
|
||||
id: string;
|
||||
path: Path;
|
||||
|
||||
@@ -21,9 +21,8 @@ export type AnyParams = { [param in string]: string } | undefined;
|
||||
export type ParamKeys<Params extends AnyParams> = keyof Params extends never
|
||||
? []
|
||||
: (keyof Params)[];
|
||||
export type OptionalParams<
|
||||
Params extends { [param in string]: string }
|
||||
> = Params[keyof Params] extends never ? undefined : Params;
|
||||
export type OptionalParams<Params extends { [param in string]: string }> =
|
||||
Params[keyof Params] extends never ? undefined : Params;
|
||||
|
||||
// The extra TS magic here is to require a single params argument if the RouteRef
|
||||
// had at least one param defined, but require 0 arguments if there are no params defined.
|
||||
@@ -65,7 +64,7 @@ export type SubRouteRef<Params extends AnyParams = any> = {
|
||||
|
||||
export type ExternalRouteRef<
|
||||
Params extends AnyParams = any,
|
||||
Optional extends boolean = any
|
||||
Optional extends boolean = any,
|
||||
> = {
|
||||
readonly [routeRefType]: 'external';
|
||||
|
||||
|
||||
@@ -48,9 +48,8 @@ export function useRouteRef<Params extends AnyParams>(
|
||||
| ExternalRouteRef<Params, any>,
|
||||
): RouteFunc<Params> | undefined {
|
||||
const sourceLocation = useLocation();
|
||||
const versionedContext = useVersionedContext<{ 1: RouteResolver }>(
|
||||
'routing-context',
|
||||
);
|
||||
const versionedContext =
|
||||
useVersionedContext<{ 1: RouteResolver }>('routing-context');
|
||||
const resolver = versionedContext.atVersion(1);
|
||||
const routeFunc = useMemo(
|
||||
() => resolver && resolver.resolve(routeRef, sourceLocation),
|
||||
|
||||
@@ -96,7 +96,7 @@ class DevAppBuilder {
|
||||
registerApi<
|
||||
Api,
|
||||
Impl extends Api,
|
||||
Deps extends { [name in string]: unknown }
|
||||
Deps extends { [name in string]: unknown },
|
||||
>(factory: ApiFactory<Api, Impl, Deps>): DevAppBuilder {
|
||||
this.apis.push(factory);
|
||||
return this;
|
||||
|
||||
@@ -186,8 +186,7 @@ describe('ApiDocGenerator', () => {
|
||||
type: 'method',
|
||||
name: 'z',
|
||||
path: 'MyApiType.z',
|
||||
text:
|
||||
'z(a: Promise<readonly [{k: MySecondSubType}[]]>): Array<MyThirdSubType>',
|
||||
text: 'z(a: Promise<readonly [{k: MySecondSubType}[]]>): Array<MyThirdSubType>',
|
||||
docs: ['Multiple', 'JsDoc', 'Comments'],
|
||||
links: [
|
||||
{
|
||||
|
||||
@@ -127,9 +127,9 @@ export default class ApiDocGenerator {
|
||||
);
|
||||
const docs = this.getNodeDocs(declaration);
|
||||
|
||||
const membersAndTypes = Array.from(
|
||||
interfaceMembers.values(),
|
||||
).flatMap(fieldSymbol => this.getMemberInfo(name, fieldSymbol));
|
||||
const membersAndTypes = Array.from(interfaceMembers.values()).flatMap(
|
||||
fieldSymbol => this.getMemberInfo(name, fieldSymbol),
|
||||
);
|
||||
|
||||
const members = membersAndTypes.map(t => t.member);
|
||||
const dependentTypes = this.flattenTypes(
|
||||
@@ -174,9 +174,8 @@ export default class ApiDocGenerator {
|
||||
): { member: FieldInfo; dependentTypes: TypeInfo[] } {
|
||||
const declaration = symbol.valueDeclaration;
|
||||
|
||||
const { links, infos: dependentTypes } = this.findAllTypeReferences(
|
||||
declaration,
|
||||
);
|
||||
const { links, infos: dependentTypes } =
|
||||
this.findAllTypeReferences(declaration);
|
||||
|
||||
let type: FieldInfo['type'] = 'prop';
|
||||
if (
|
||||
|
||||
@@ -92,9 +92,7 @@ export default class TypeLocator {
|
||||
return result as { [key in T]: ExportedInstance[] };
|
||||
}
|
||||
|
||||
private getExportedConstructorDeclaration(
|
||||
node: ts.Node,
|
||||
):
|
||||
private getExportedConstructorDeclaration(node: ts.Node):
|
||||
| {
|
||||
constructorType: ts.Type;
|
||||
args: ts.Expression[];
|
||||
|
||||
@@ -78,9 +78,10 @@ export default class TypescriptHighlighter implements Highlighter {
|
||||
|
||||
// Order here is important, e.g. comments must be first to avoid string literals inside comments being highlighted
|
||||
return TypescriptHighlighter.highlighters
|
||||
.reduce((parts, highlighter) => parts.flatMap(painter(...highlighter)), [
|
||||
{ text: fullText },
|
||||
])
|
||||
.reduce(
|
||||
(parts, highlighter) => parts.flatMap(painter(...highlighter)),
|
||||
[{ text: fullText }],
|
||||
)
|
||||
.map(({ text }) => text)
|
||||
.join('');
|
||||
}
|
||||
|
||||
@@ -403,14 +403,9 @@ async function testBackendStart(appDir: string, isPostgres: boolean) {
|
||||
if (isPostgres) {
|
||||
print('Dropping old DBs');
|
||||
await Promise.all(
|
||||
[
|
||||
'catalog',
|
||||
'scaffolder',
|
||||
'auth',
|
||||
'identity',
|
||||
'proxy',
|
||||
'techdocs',
|
||||
].map(name => dropDB(`backstage_plugin_${name}`)),
|
||||
['catalog', 'scaffolder', 'auth', 'identity', 'proxy', 'techdocs'].map(
|
||||
name => dropDB(`backstage_plugin_${name}`),
|
||||
),
|
||||
);
|
||||
print('Created DBs');
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ import { promisify } from 'util';
|
||||
|
||||
const execFile = promisify(execFileCb);
|
||||
|
||||
const EXPECTED_LOAD_ERRORS = /ECONNREFUSED|ECONNRESET|did not get to load all resources/;
|
||||
const EXPECTED_LOAD_ERRORS =
|
||||
/ECONNREFUSED|ECONNRESET|did not get to load all resources/;
|
||||
|
||||
export function spawnPiped(cmd: string[], options?: SpawnOptions) {
|
||||
function pipeWithPrefix(stream: NodeJS.WriteStream, prefix = '') {
|
||||
|
||||
@@ -27,9 +27,8 @@ export class ScmIntegrationsApi {
|
||||
}
|
||||
}
|
||||
|
||||
export const scmIntegrationsApiRef: ApiRef<ScmIntegrationRegistry> = createApiRef(
|
||||
{
|
||||
export const scmIntegrationsApiRef: ApiRef<ScmIntegrationRegistry> =
|
||||
createApiRef({
|
||||
id: 'integration.scmintegrations',
|
||||
description: 'All of the registered SCM integrations of your config',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -51,8 +51,7 @@ describe('AzureIntegration', () => {
|
||||
expect(
|
||||
integration.resolveUrl({
|
||||
url: '../a.yaml',
|
||||
base:
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Ffolder%2Fcatalog-info.yaml',
|
||||
base: 'https://dev.azure.com/organization/project/_git/repository?path=%2Ffolder%2Fcatalog-info.yaml',
|
||||
}),
|
||||
).toBe(
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Fa.yaml',
|
||||
@@ -61,8 +60,7 @@ describe('AzureIntegration', () => {
|
||||
expect(
|
||||
integration.resolveUrl({
|
||||
url: '/a.yaml',
|
||||
base:
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Ffolder%2Fcatalog-info.yaml',
|
||||
base: 'https://dev.azure.com/organization/project/_git/repository?path=%2Ffolder%2Fcatalog-info.yaml',
|
||||
lineNumber: 14,
|
||||
}),
|
||||
).toBe(
|
||||
@@ -81,8 +79,7 @@ describe('AzureIntegration', () => {
|
||||
expect(
|
||||
integration.resolveUrl({
|
||||
url: 'https://absolute.com/path',
|
||||
base:
|
||||
'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
base: 'https://dev.azure.com/organization/project/_git/repository?path=%2Fcatalog-info.yaml',
|
||||
}),
|
||||
).toBe('https://absolute.com/path');
|
||||
});
|
||||
|
||||
@@ -43,26 +43,22 @@ describe('azure core', () => {
|
||||
describe('getAzureFileFetchUrl', () => {
|
||||
it.each([
|
||||
{
|
||||
url:
|
||||
'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
result:
|
||||
'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml&version=master',
|
||||
},
|
||||
{
|
||||
url:
|
||||
'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
url: 'https://dev.azure.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
result:
|
||||
'https://dev.azure.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml',
|
||||
},
|
||||
{
|
||||
url:
|
||||
'https://api.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
url: 'https://api.com/org-name/project-name/_git/repo-name?path=my-template.yaml',
|
||||
result:
|
||||
'https://api.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml',
|
||||
},
|
||||
{
|
||||
url:
|
||||
'https://api.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
url: 'https://api.com/org-name/project-name/_git/repo-name?path=my-template.yaml&version=GBmaster',
|
||||
result:
|
||||
'https://api.com/org-name/project-name/_apis/git/repositories/repo-name/items?path=my-template.yaml&version=master',
|
||||
},
|
||||
|
||||
@@ -31,13 +31,8 @@ export function getAzureFileFetchUrl(url: string): string {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
|
||||
const [
|
||||
empty,
|
||||
userOrOrg,
|
||||
project,
|
||||
srcKeyword,
|
||||
repoName,
|
||||
] = parsedUrl.pathname.split('/');
|
||||
const [empty, userOrOrg, project, srcKeyword, repoName] =
|
||||
parsedUrl.pathname.split('/');
|
||||
|
||||
const path = parsedUrl.searchParams.get('path') || '';
|
||||
const ref = parsedUrl.searchParams.get('version')?.substr(2);
|
||||
@@ -117,13 +112,8 @@ export function getAzureCommitsUrl(url: string): string {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
|
||||
const [
|
||||
empty,
|
||||
userOrOrg,
|
||||
project,
|
||||
srcKeyword,
|
||||
repoName,
|
||||
] = parsedUrl.pathname.split('/');
|
||||
const [empty, userOrOrg, project, srcKeyword, repoName] =
|
||||
parsedUrl.pathname.split('/');
|
||||
|
||||
// Remove the "GB" from "GBmain" for example.
|
||||
const ref = parsedUrl.searchParams.get('version')?.substr(2);
|
||||
|
||||
@@ -56,8 +56,7 @@ describe('GitHubIntegration', () => {
|
||||
expect(
|
||||
integration.resolveUrl({
|
||||
url: '../a.yaml',
|
||||
base:
|
||||
'https://github.com/backstage/backstage/blob/master/test/README.md',
|
||||
base: 'https://github.com/backstage/backstage/blob/master/test/README.md',
|
||||
lineNumber: 17,
|
||||
}),
|
||||
).toBe('https://github.com/backstage/backstage/tree/master/a.yaml#L17');
|
||||
@@ -65,8 +64,7 @@ describe('GitHubIntegration', () => {
|
||||
expect(
|
||||
integration.resolveUrl({
|
||||
url: './',
|
||||
base:
|
||||
'https://github.com/backstage/backstage/blob/master/test/README.md',
|
||||
base: 'https://github.com/backstage/backstage/blob/master/test/README.md',
|
||||
}),
|
||||
).toBe('https://github.com/backstage/backstage/tree/master/test/');
|
||||
});
|
||||
|
||||
@@ -232,9 +232,9 @@ describe('GithubCredentialsProvider tests', () => {
|
||||
],
|
||||
token: 'hardcoded_token',
|
||||
});
|
||||
octokit.apps.listInstallations.mockResolvedValue(({
|
||||
octokit.apps.listInstallations.mockResolvedValue({
|
||||
data: [],
|
||||
} as unknown) as RestEndpointMethodTypes['apps']['listInstallations']['response']);
|
||||
} as unknown as RestEndpointMethodTypes['apps']['listInstallations']['response']);
|
||||
|
||||
await expect(
|
||||
githubProvider.getCredentials({
|
||||
|
||||
@@ -85,11 +85,8 @@ class GithubAppManager {
|
||||
owner: string,
|
||||
repo?: string,
|
||||
): Promise<{ accessToken: string }> {
|
||||
const {
|
||||
installationId,
|
||||
suspended,
|
||||
repositorySelection,
|
||||
} = await this.getInstallationData(owner);
|
||||
const { installationId, suspended, repositorySelection } =
|
||||
await this.getInstallationData(owner);
|
||||
if (suspended) {
|
||||
throw new Error(
|
||||
`The GitHub application for ${[owner, repo]
|
||||
|
||||
@@ -52,37 +52,32 @@ describe('gitlab core', () => {
|
||||
// Project URLs
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
|
||||
url: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file.yaml',
|
||||
result:
|
||||
'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
// Works with non URI encoded link
|
||||
url:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file with spaces.yaml',
|
||||
url: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path/to/file with spaces.yaml',
|
||||
result:
|
||||
'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile%20with%20spaces.yaml/raw?ref=branch',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path%20with%20spaces/to/file.yaml',
|
||||
url: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path%20with%20spaces/to/file.yaml',
|
||||
result:
|
||||
'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%20with%20spaces%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
},
|
||||
{
|
||||
config: configWithToken,
|
||||
url:
|
||||
'https://gitlab.example.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path%20with%20spaces/to/file.yaml',
|
||||
url: 'https://gitlab.example.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/my/path%20with%20spaces/to/file.yaml',
|
||||
result:
|
||||
'https://gitlab.example.com/api/v4/projects/12345/repository/files/my%2Fpath%20with%20spaces%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
},
|
||||
{
|
||||
config: configWithNoToken,
|
||||
url:
|
||||
'https://gitlab.com/groupA/teams/teamA/repoA/-/blob/branch/my/path%20with%20spaces/to/file.yaml', // Repo not in subgroup
|
||||
url: 'https://gitlab.com/groupA/teams/teamA/repoA/-/blob/branch/my/path%20with%20spaces/to/file.yaml', // Repo not in subgroup
|
||||
result:
|
||||
'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%20with%20spaces%2Fto%2Ffile.yaml/raw?ref=branch',
|
||||
},
|
||||
|
||||
@@ -68,13 +68,8 @@ export function buildRawUrl(target: string): URL {
|
||||
try {
|
||||
const url = new URL(target);
|
||||
|
||||
const [
|
||||
empty,
|
||||
userOrOrg,
|
||||
repoName,
|
||||
blobKeyword,
|
||||
...restOfPath
|
||||
] = url.pathname.split('/');
|
||||
const [empty, userOrOrg, repoName, blobKeyword, ...restOfPath] =
|
||||
url.pathname.split('/');
|
||||
|
||||
if (
|
||||
empty !== '' ||
|
||||
|
||||
@@ -57,8 +57,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: './b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
}),
|
||||
).toBe(
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/b.yaml',
|
||||
@@ -67,8 +66,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: './b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
}),
|
||||
).toBe(
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/b.yaml?at=master',
|
||||
@@ -77,8 +75,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: 'b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
}),
|
||||
).toBe(
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/b.yaml',
|
||||
@@ -89,8 +86,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: '/other/b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
}),
|
||||
).toBe(
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/other/b.yaml',
|
||||
@@ -99,8 +95,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: '/other/b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
}),
|
||||
).toBe(
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/other/b.yaml?at=master',
|
||||
@@ -111,8 +106,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: './b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
lineNumber: 11,
|
||||
}),
|
||||
).toBe(
|
||||
@@ -122,8 +116,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: 'b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
lineNumber: 12,
|
||||
}),
|
||||
).toBe(
|
||||
@@ -133,8 +126,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: '/other/b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml',
|
||||
lineNumber: 13,
|
||||
}),
|
||||
).toBe(
|
||||
@@ -144,8 +136,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: '/other/b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
lineNumber: 14,
|
||||
}),
|
||||
).toBe(
|
||||
@@ -157,8 +148,7 @@ describe('defaultScmResolveUrl', () => {
|
||||
expect(
|
||||
defaultScmResolveUrl({
|
||||
url: 'https://b.com/b.yaml',
|
||||
base:
|
||||
'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
base: 'https://gitlab.com/groupA/teams/teamA/subgroupA/repoA/-/blob/branch/folder/a.yaml?at=master',
|
||||
}),
|
||||
).toBe('https://b.com/b.yaml');
|
||||
});
|
||||
|
||||
@@ -176,9 +176,8 @@ export class GoogleGCSPublish implements PublisherBase {
|
||||
fileStreamChunks.push(chunk);
|
||||
})
|
||||
.on('end', () => {
|
||||
const techdocsMetadataJson = Buffer.concat(fileStreamChunks).toString(
|
||||
'utf-8',
|
||||
);
|
||||
const techdocsMetadataJson =
|
||||
Buffer.concat(fileStreamChunks).toString('utf-8');
|
||||
resolve(JSON5.parse(techdocsMetadataJson));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -92,7 +92,7 @@ export function wrapInTestApp(
|
||||
apis: mockApis,
|
||||
// Bit of a hack to make sure that the default config loader isn't used
|
||||
// as that would force every single test to wait for config loading.
|
||||
configLoader: (false as unknown) as undefined,
|
||||
configLoader: false as unknown as undefined,
|
||||
components: {
|
||||
Progress,
|
||||
BootErrorPage,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user