@@ -69,16 +69,19 @@ export class ResponseBodyParser
|
||||
const jsonContentType = Object.keys(contentTypes).find(contentType =>
|
||||
contentType.split(';').includes('application/json'),
|
||||
);
|
||||
if (!jsonContentType) {
|
||||
throw new OperationError(
|
||||
this.operation,
|
||||
`No application/json content type found in response for status code ${statusCode}`,
|
||||
);
|
||||
} else if ('$ref' in contentTypes[jsonContentType].schema) {
|
||||
const eventStreamContentType = Object.keys(contentTypes).find(
|
||||
contentType => contentType.split(';').includes('text/event-stream'),
|
||||
);
|
||||
if (jsonContentType && '$ref' in contentTypes[jsonContentType].schema) {
|
||||
throw new OperationError(
|
||||
this.operation,
|
||||
'Reference objects are not supported',
|
||||
);
|
||||
} else if (!jsonContentType && !eventStreamContentType) {
|
||||
throw new OperationError(
|
||||
this.operation,
|
||||
`No valid content type found in response for status code ${statusCode}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,14 +116,20 @@ export class ResponseBodyParser
|
||||
const jsonContentType = Object.keys(contentTypes ?? {}).find(contentType =>
|
||||
contentType.split(';').includes('application/json'),
|
||||
);
|
||||
if (!jsonContentType) {
|
||||
const eventStreamContentType = Object.keys(contentTypes ?? {}).find(
|
||||
contentType => contentType.split(';').includes('text/event-stream'),
|
||||
);
|
||||
if (!jsonContentType && !eventStreamContentType) {
|
||||
throw new OperationResponseError(
|
||||
this.operation,
|
||||
response,
|
||||
'No application/json content type found in response',
|
||||
'No valid content type found in response',
|
||||
);
|
||||
}
|
||||
const schema = responseSchema.content![jsonContentType].schema;
|
||||
const schema =
|
||||
(jsonContentType && responseSchema.content![jsonContentType].schema) ||
|
||||
(eventStreamContentType &&
|
||||
responseSchema.content![eventStreamContentType].schema);
|
||||
// This is a bit of type laziness. Ideally, this would be a type-narrowing function, but I wasn't able to get the types to work.
|
||||
if (!schema) {
|
||||
throw new OperationError(this.operation, 'No schema found in response');
|
||||
@@ -145,6 +154,28 @@ export class ResponseBodyParser
|
||||
}
|
||||
|
||||
const validate = this.ajv.compile(schema);
|
||||
|
||||
if (eventStreamContentType) {
|
||||
const eventStreamBody = await response.text();
|
||||
|
||||
const jsonMatches = [...eventStreamBody.matchAll(/data:\s*(\{.*?\})/g)];
|
||||
const jsonObjects = jsonMatches.map(match => {
|
||||
return match[1] as any as JsonObject;
|
||||
});
|
||||
|
||||
const invalid = jsonObjects.some(jsonObject => !validate(jsonObject));
|
||||
if (invalid) {
|
||||
throw new OperationParsingResponseError(
|
||||
this.operation,
|
||||
response,
|
||||
'Response body',
|
||||
validate.errors!,
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const jsonBody = (await response.json()) as JsonObject;
|
||||
const valid = validate(jsonBody);
|
||||
if (!valid) {
|
||||
|
||||
@@ -44,10 +44,8 @@ components:
|
||||
required: false
|
||||
allowReserved: true
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
minimum: 0
|
||||
type: integer
|
||||
minimum: 0
|
||||
namespace:
|
||||
name: namespace
|
||||
in: path
|
||||
@@ -69,10 +67,8 @@ components:
|
||||
required: false
|
||||
allowReserved: true
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
minimum: 0
|
||||
type: integer
|
||||
minimum: 0
|
||||
order:
|
||||
name: order
|
||||
in: query
|
||||
@@ -534,7 +530,7 @@ components:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
format: byte
|
||||
# format: byte
|
||||
executable:
|
||||
type: boolean
|
||||
symlink:
|
||||
@@ -869,9 +865,11 @@ components:
|
||||
type: object
|
||||
properties:
|
||||
title:
|
||||
$ref: '#/components/schemas/JsonValue'
|
||||
type: string
|
||||
# $ref: '#/components/schemas/JsonValue'
|
||||
description:
|
||||
$ref: '#/components/schemas/JsonValue'
|
||||
type: string
|
||||
# $ref: '#/components/schemas/JsonValue'
|
||||
schema:
|
||||
type: object
|
||||
# additionalProperties: {}
|
||||
@@ -971,7 +969,11 @@ components:
|
||||
name:
|
||||
type: string
|
||||
argument:
|
||||
type: object
|
||||
oneOf:
|
||||
- type: boolean
|
||||
- type: number
|
||||
- type: object
|
||||
- type: string
|
||||
stack:
|
||||
type: string
|
||||
required:
|
||||
@@ -1324,6 +1326,17 @@ paths:
|
||||
- id
|
||||
required:
|
||||
- results
|
||||
'400':
|
||||
description: Unsupported provider.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
parameters:
|
||||
- in: path
|
||||
name: provider
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
// ******************************************************************
|
||||
import { Action } from '../models/Action.model';
|
||||
import { Autocomplete200Response } from '../models/Autocomplete200Response.model';
|
||||
import { Autocomplete400Response } from '../models/Autocomplete400Response.model';
|
||||
import { AutocompleteRequest } from '../models/AutocompleteRequest.model';
|
||||
import { CancelTask200Response } from '../models/CancelTask200Response.model';
|
||||
import { DryRun200Response } from '../models/DryRun200Response.model';
|
||||
@@ -43,7 +44,7 @@ export type Autocomplete = {
|
||||
resource: string;
|
||||
};
|
||||
body: AutocompleteRequest;
|
||||
response: Autocomplete200Response;
|
||||
response: Autocomplete200Response | Autocomplete400Response;
|
||||
};
|
||||
/**
|
||||
* @public
|
||||
@@ -93,8 +94,8 @@ export type ListActions = {
|
||||
export type ListTasks = {
|
||||
query: {
|
||||
createdBy?: Array<string>;
|
||||
limit?: Array<number>;
|
||||
offset?: Array<number>;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order?: Array<string>;
|
||||
status?: Array<string>;
|
||||
};
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Autocomplete400Response {
|
||||
message?: string;
|
||||
name?: string;
|
||||
}
|
||||
+2
-3
@@ -17,13 +17,12 @@
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
import { JsonValue } from '../models/JsonValue.model';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TemplateParameterSchemaStepsInner {
|
||||
title: JsonValue;
|
||||
description?: JsonValue;
|
||||
title: string;
|
||||
description?: string;
|
||||
schema: any;
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
import { ValidationErrorArgument } from '../models/ValidationErrorArgument.model';
|
||||
import { ValidationErrorPathInner } from '../models/ValidationErrorPathInner.model';
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,6 @@ export interface ValidationError {
|
||||
message: string;
|
||||
instance: any;
|
||||
name: string;
|
||||
argument: any;
|
||||
argument: ValidationErrorArgument;
|
||||
stack: string;
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ValidationErrorArgument = any | boolean | number | string;
|
||||
@@ -19,6 +19,7 @@ export * from '../models/ActionExample.model';
|
||||
export * from '../models/ActionSchema.model';
|
||||
export * from '../models/Autocomplete200Response.model';
|
||||
export * from '../models/Autocomplete200ResponseResultsInner.model';
|
||||
export * from '../models/Autocomplete400Response.model';
|
||||
export * from '../models/AutocompleteRequest.model';
|
||||
export * from '../models/CancelTask200Response.model';
|
||||
export * from '../models/DryRun200Response.model';
|
||||
@@ -61,4 +62,5 @@ export * from '../models/TemplateInfoEntity.model';
|
||||
export * from '../models/TemplateParameterSchema.model';
|
||||
export * from '../models/TemplateParameterSchemaStepsInner.model';
|
||||
export * from '../models/ValidationError.model';
|
||||
export * from '../models/ValidationErrorArgument.model';
|
||||
export * from '../models/ValidationErrorPathInner.model';
|
||||
|
||||
@@ -80,11 +80,8 @@ export const spec = {
|
||||
required: false,
|
||||
allowReserved: true,
|
||||
schema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
},
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
namespace: {
|
||||
@@ -112,11 +109,8 @@ export const spec = {
|
||||
required: false,
|
||||
allowReserved: true,
|
||||
schema: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
},
|
||||
type: 'integer',
|
||||
minimum: 0,
|
||||
},
|
||||
},
|
||||
order: {
|
||||
@@ -545,7 +539,6 @@ export const spec = {
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
format: 'byte',
|
||||
},
|
||||
executable: {
|
||||
type: 'boolean',
|
||||
@@ -758,10 +751,10 @@ export const spec = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
$ref: '#/components/schemas/JsonValue',
|
||||
type: 'string',
|
||||
},
|
||||
description: {
|
||||
$ref: '#/components/schemas/JsonValue',
|
||||
type: 'string',
|
||||
},
|
||||
schema: {
|
||||
type: 'object',
|
||||
@@ -805,7 +798,20 @@ export const spec = {
|
||||
type: 'string',
|
||||
},
|
||||
argument: {
|
||||
type: 'object',
|
||||
oneOf: [
|
||||
{
|
||||
type: 'boolean',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
type: 'object',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
},
|
||||
],
|
||||
},
|
||||
stack: {
|
||||
type: 'string',
|
||||
@@ -1352,6 +1358,24 @@ export const spec = {
|
||||
},
|
||||
},
|
||||
},
|
||||
'400': {
|
||||
description: 'Unsupported provider.',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
message: {
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
parameters: [
|
||||
{
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import { DatabaseManager } from '@backstage/backend-defaults/database';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import express from 'express';
|
||||
import request from 'supertest';
|
||||
import ObservableImpl from 'zen-observable';
|
||||
|
||||
@@ -65,6 +66,24 @@ import {
|
||||
import { createDefaultFilters } from '../lib/templating/filters/createDefaultFilters';
|
||||
import { createRouter } from './router';
|
||||
import { DatabaseTaskStore } from '../scaffolder/tasks/DatabaseTaskStore';
|
||||
import { Server } from 'http';
|
||||
import { wrapServer } from '@backstage/backend-openapi-utils/testUtils';
|
||||
|
||||
const mockAccess = jest.fn();
|
||||
|
||||
jest.mock('fs-extra', () => ({
|
||||
...jest.requireActual('fs-extra'),
|
||||
access: (...args: any[]) => mockAccess(...args),
|
||||
promises: {
|
||||
access: (...args: any[]) => mockAccess(...args),
|
||||
},
|
||||
constants: {
|
||||
F_OK: 0,
|
||||
W_OK: 1,
|
||||
},
|
||||
mkdir: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
}));
|
||||
|
||||
function createDatabase(): DatabaseService {
|
||||
return DatabaseManager.fromConfig(
|
||||
@@ -245,7 +264,8 @@ const createTestRouter = async (
|
||||
});
|
||||
|
||||
router.use(mockErrorHandler());
|
||||
return { router, logger, taskBroker, permissions, catalog };
|
||||
const app = await wrapServer(express().use(router));
|
||||
return { router: app, logger, taskBroker, permissions, catalog };
|
||||
};
|
||||
|
||||
describe('scaffolder router', () => {
|
||||
|
||||
@@ -102,7 +102,6 @@ import {
|
||||
findTemplate,
|
||||
getEntityBaseUrl,
|
||||
getWorkingDirectory,
|
||||
parseNumberParam,
|
||||
parseStringsParam,
|
||||
} from './helpers';
|
||||
|
||||
@@ -404,8 +403,10 @@ export async function createRouter(
|
||||
description: template.metadata.description,
|
||||
'ui:options': template.metadata['ui:options'],
|
||||
steps: parameters.map(schema => ({
|
||||
title: schema.title ?? 'Please enter the following information',
|
||||
description: schema.description,
|
||||
title:
|
||||
(schema.title as string) ??
|
||||
'Please enter the following information',
|
||||
description: schema.description as string,
|
||||
schema,
|
||||
})),
|
||||
EXPERIMENTAL_formDecorators:
|
||||
@@ -587,8 +588,7 @@ export async function createRouter(
|
||||
};
|
||||
});
|
||||
|
||||
const limit = parseNumberParam(req.query.limit, 'limit');
|
||||
const offset = parseNumberParam(req.query.offset, 'offset');
|
||||
const { limit, offset } = req.query;
|
||||
|
||||
const taskPermissionFilters = await getAuthorizeConditions({
|
||||
credentials: credentials,
|
||||
@@ -604,8 +604,8 @@ export async function createRouter(
|
||||
},
|
||||
order,
|
||||
pagination: {
|
||||
limit: limit ? limit[0] : undefined,
|
||||
offset: offset ? offset[0] : undefined,
|
||||
limit,
|
||||
offset,
|
||||
},
|
||||
permissionFilters: taskPermissionFilters,
|
||||
});
|
||||
|
||||
@@ -105,8 +105,8 @@ export type ListActions = {};
|
||||
export type ListTasks = {
|
||||
query: {
|
||||
createdBy?: Array<string>;
|
||||
limit?: Array<number>;
|
||||
offset?: Array<number>;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order?: Array<string>;
|
||||
status?: Array<string>;
|
||||
};
|
||||
@@ -339,7 +339,7 @@ export class DefaultApiClient {
|
||||
): Promise<TypedResponse<ListTasksResponse>> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl(pluginId);
|
||||
|
||||
const uriTemplate = `/v2/tasks{?createdBy*,limit*,offset*,order*,status*}`;
|
||||
const uriTemplate = `/v2/tasks{?createdBy*,limit,offset,order*,status*}`;
|
||||
|
||||
const uri = parser.parse(uriTemplate).expand({
|
||||
...request.query,
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Autocomplete400Response {
|
||||
message?: string;
|
||||
name?: string;
|
||||
}
|
||||
+2
-3
@@ -17,13 +17,12 @@
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
import { JsonValue } from '../models/JsonValue.model';
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TemplateParameterSchemaStepsInner {
|
||||
title: JsonValue;
|
||||
description?: JsonValue;
|
||||
title: string;
|
||||
description?: string;
|
||||
schema: any;
|
||||
}
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
import { ValidationErrorArgument } from '../models/ValidationErrorArgument.model';
|
||||
import { ValidationErrorPathInner } from '../models/ValidationErrorPathInner.model';
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,6 @@ export interface ValidationError {
|
||||
message: string;
|
||||
instance: any;
|
||||
name: string;
|
||||
argument: any;
|
||||
argument: ValidationErrorArgument;
|
||||
stack: string;
|
||||
}
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2024 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// ******************************************************************
|
||||
// * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. *
|
||||
// ******************************************************************
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ValidationErrorArgument = any | boolean | number | string;
|
||||
@@ -19,6 +19,7 @@ export * from '../models/ActionExample.model';
|
||||
export * from '../models/ActionSchema.model';
|
||||
export * from '../models/Autocomplete200Response.model';
|
||||
export * from '../models/Autocomplete200ResponseResultsInner.model';
|
||||
export * from '../models/Autocomplete400Response.model';
|
||||
export * from '../models/AutocompleteRequest.model';
|
||||
export * from '../models/CancelTask200Response.model';
|
||||
export * from '../models/DryRun200Response.model';
|
||||
@@ -61,4 +62,5 @@ export * from '../models/TemplateInfoEntity.model';
|
||||
export * from '../models/TemplateParameterSchema.model';
|
||||
export * from '../models/TemplateParameterSchemaStepsInner.model';
|
||||
export * from '../models/ValidationError.model';
|
||||
export * from '../models/ValidationErrorArgument.model';
|
||||
export * from '../models/ValidationErrorPathInner.model';
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "workspace:^",
|
||||
"@backstage/core-plugin-api": "workspace:^",
|
||||
"@backstage/errors": "workspace:^",
|
||||
"@backstage/integration": "workspace:^",
|
||||
"@backstage/plugin-permission-common": "workspace:^",
|
||||
@@ -73,7 +72,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/test-utils": "workspace:^",
|
||||
"cross-fetch": "^4.0.0",
|
||||
"msw": "^1.0.0",
|
||||
"uri-template": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
+18
-12
@@ -14,12 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ConfigReader } from '@backstage/core-app-api';
|
||||
import { ScmIntegrations } from '@backstage/integration';
|
||||
import { MockFetchApi, registerMswTestHooks } from '@backstage/test-utils';
|
||||
import {
|
||||
MockFetchApi,
|
||||
mockApis,
|
||||
registerMswTestHooks,
|
||||
} from '@backstage/test-utils';
|
||||
import { rest } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { ScaffolderClient } from './api';
|
||||
import { ScaffolderClient } from './ScaffolderClient';
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
||||
|
||||
jest.mock('@microsoft/fetch-event-source');
|
||||
@@ -31,6 +34,17 @@ const server = setupServer();
|
||||
|
||||
describe('api', () => {
|
||||
registerMswTestHooks(server);
|
||||
const githubIntegrationConfig = mockApis.config({
|
||||
data: {
|
||||
integrations: {
|
||||
github: [
|
||||
{
|
||||
host: 'hello.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
const mockBaseUrl = 'http://backstage/api';
|
||||
|
||||
const discoveryApi = { getBaseUrl: async () => mockBaseUrl };
|
||||
@@ -43,15 +57,7 @@ describe('api', () => {
|
||||
};
|
||||
|
||||
const scmIntegrationsApi = ScmIntegrations.fromConfig(
|
||||
new ConfigReader({
|
||||
integrations: {
|
||||
github: [
|
||||
{
|
||||
host: 'hello.com',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
githubIntegrationConfig,
|
||||
);
|
||||
|
||||
let apiClient: ScaffolderClient;
|
||||
@@ -15,11 +15,6 @@
|
||||
*/
|
||||
|
||||
import { parseEntityRef } from '@backstage/catalog-model';
|
||||
import {
|
||||
DiscoveryApi,
|
||||
FetchApi,
|
||||
IdentityApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { ResponseError } from '@backstage/errors';
|
||||
import { ScmIntegrationRegistry } from '@backstage/integration';
|
||||
import { Observable } from '@backstage/types';
|
||||
@@ -50,6 +45,9 @@ import {
|
||||
TaskStatus,
|
||||
TypedResponse,
|
||||
} from '../client/src/schema/openapi';
|
||||
import { DiscoveryApi } from '../client/src/schema/openapi/generated/types/discovery';
|
||||
import { FetchApi } from '../client/src/schema/openapi/generated/types/fetch';
|
||||
import { IdentityApi } from './types/IdentityApi';
|
||||
|
||||
/**
|
||||
* An API to interact with the scaffolder backend.
|
||||
@@ -106,8 +104,8 @@ export class ScaffolderClient implements ScaffolderApi {
|
||||
request.filterByOwnership === 'owned'
|
||||
? [userEntityRef]
|
||||
: undefined,
|
||||
limit: request.limit ? [request.limit] : undefined,
|
||||
offset: request.offset ? [request.offset] : undefined,
|
||||
limit: request.limit,
|
||||
offset: request.offset,
|
||||
},
|
||||
},
|
||||
options,
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a copy of the BackstageUserIdentity, to avoid importing core-plugin-api.
|
||||
*/
|
||||
type BackstageUserIdentity = {
|
||||
/**
|
||||
* The type of identity that this structure represents. In the frontend app
|
||||
* this will currently always be 'user'.
|
||||
*/
|
||||
type: 'user';
|
||||
|
||||
/**
|
||||
* The entityRef of the user in the catalog.
|
||||
* For example User:default/sandra
|
||||
*/
|
||||
userEntityRef: string;
|
||||
|
||||
/**
|
||||
* The user and group entities that the user claims ownership through
|
||||
*/
|
||||
ownershipEntityRefs: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a partial copy of the IdentityApi, to avoid importing core-plugin-api.
|
||||
*/
|
||||
export type IdentityApi = {
|
||||
/**
|
||||
* User identity information within Backstage.
|
||||
*/
|
||||
getBackstageIdentity(): Promise<BackstageUserIdentity>;
|
||||
};
|
||||
@@ -87,10 +87,12 @@
|
||||
"git-url-parse": "^15.0.0",
|
||||
"humanize-duration": "^3.25.1",
|
||||
"idb-keyval": "5.1.5",
|
||||
"json-schema": "^0.4.0",
|
||||
"json-schema-library": "^9.0.0",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash": "^4.17.21",
|
||||
"luxon": "^3.0.0",
|
||||
"qs": "^6.9.4",
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-use": "^17.2.4",
|
||||
"react-window": "^1.8.10",
|
||||
|
||||
@@ -7394,8 +7394,18 @@ __metadata:
|
||||
dependencies:
|
||||
"@backstage/catalog-model": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/errors": "workspace:^"
|
||||
"@backstage/integration": "workspace:^"
|
||||
"@backstage/plugin-permission-common": "workspace:^"
|
||||
"@backstage/test-utils": "workspace:^"
|
||||
"@backstage/types": "workspace:^"
|
||||
"@microsoft/fetch-event-source": "npm:^2.0.1"
|
||||
cross-fetch: "npm:^4.0.0"
|
||||
json-schema: "npm:^0.4.0"
|
||||
msw: "npm:^1.0.0"
|
||||
qs: "npm:^6.9.4"
|
||||
uri-template: "npm:^2.0.0"
|
||||
zen-observable: "npm:^0.10.0"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -7536,9 +7546,7 @@ __metadata:
|
||||
"@backstage/core-components": "workspace:^"
|
||||
"@backstage/core-plugin-api": "workspace:^"
|
||||
"@backstage/dev-utils": "workspace:^"
|
||||
"@backstage/errors": "workspace:^"
|
||||
"@backstage/frontend-plugin-api": "workspace:^"
|
||||
"@backstage/integration": "workspace:^"
|
||||
"@backstage/integration-react": "workspace:^"
|
||||
"@backstage/plugin-catalog": "workspace:^"
|
||||
"@backstage/plugin-catalog-common": "workspace:^"
|
||||
@@ -7555,7 +7563,6 @@ __metadata:
|
||||
"@material-ui/core": "npm:^4.12.2"
|
||||
"@material-ui/icons": "npm:^4.9.1"
|
||||
"@material-ui/lab": "npm:4.0.0-alpha.61"
|
||||
"@microsoft/fetch-event-source": "npm:^2.0.1"
|
||||
"@react-hookz/web": "npm:^24.0.0"
|
||||
"@rjsf/core": "npm:5.23.2"
|
||||
"@rjsf/material-ui": "npm:5.23.2"
|
||||
@@ -7590,7 +7597,6 @@ __metadata:
|
||||
react-window: "npm:^1.8.10"
|
||||
swr: "npm:^2.0.0"
|
||||
yaml: "npm:^2.0.0"
|
||||
zen-observable: "npm:^0.10.0"
|
||||
zod: "npm:^3.22.4"
|
||||
zod-to-json-schema: "npm:^3.20.4"
|
||||
peerDependencies:
|
||||
|
||||
Reference in New Issue
Block a user