Deprecate and re-export

Signed-off-by: solimant <solimant@users.noreply.github.com>
This commit is contained in:
solimant
2024-12-27 07:22:58 +00:00
parent e2fa65af59
commit d2da49c568
103 changed files with 1619 additions and 3018 deletions
@@ -118,7 +118,7 @@ async function downloadDirectoryContents(
directoryContents: {
path: string;
base64Content: string;
executable: boolean;
executable?: boolean;
}[],
name: string,
) {
+3 -380
View File
@@ -14,389 +14,12 @@
* limitations under the License.
*/
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 {
ListActionsResponse,
ListTemplatingExtensionsResponse,
LogEvent,
ScaffolderApi,
ScaffolderDryRunOptions,
ScaffolderDryRunResponse,
ScaffolderGetIntegrationsListOptions,
ScaffolderGetIntegrationsListResponse,
ScaffolderScaffoldOptions,
ScaffolderScaffoldResponse,
ScaffolderStreamLogsOptions,
ScaffolderTask,
TemplateParameterSchema,
} from '@backstage/plugin-scaffolder-react';
import { Observable } from '@backstage/types';
import {
EventSourceMessage,
fetchEventSource,
} from '@microsoft/fetch-event-source';
import { default as qs, default as queryString } from 'qs';
import ObservableImpl from 'zen-observable';
import { ScaffolderClient as _ScaffolderClient } from '@backstage/plugin-scaffolder-common';
/**
* An API to interact with the scaffolder backend.
*
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderClient} instead as this has now been moved.
*/
export class ScaffolderClient implements ScaffolderApi {
private readonly discoveryApi: DiscoveryApi;
private readonly scmIntegrationsApi: ScmIntegrationRegistry;
private readonly fetchApi: FetchApi;
private readonly identityApi?: IdentityApi;
private readonly useLongPollingLogs: boolean;
constructor(options: {
discoveryApi: DiscoveryApi;
fetchApi: FetchApi;
identityApi?: IdentityApi;
scmIntegrationsApi: ScmIntegrationRegistry;
useLongPollingLogs?: boolean;
}) {
this.discoveryApi = options.discoveryApi;
this.fetchApi = options.fetchApi ?? { fetch };
this.scmIntegrationsApi = options.scmIntegrationsApi;
this.useLongPollingLogs = options.useLongPollingLogs ?? false;
this.identityApi = options.identityApi;
}
async listTasks(options: {
filterByOwnership: 'owned' | 'all';
limit?: number;
offset?: number;
}): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }> {
if (!this.identityApi) {
throw new Error(
'IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method',
);
}
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const { userEntityRef } = await this.identityApi.getBackstageIdentity();
const query = queryString.stringify({
createdBy:
options.filterByOwnership === 'owned' ? userEntityRef : undefined,
limit: options.limit,
offset: options.offset,
});
const response = await this.fetchApi.fetch(`${baseUrl}/v2/tasks?${query}`);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
async getIntegrationsList(
options: ScaffolderGetIntegrationsListOptions,
): Promise<ScaffolderGetIntegrationsListResponse> {
const integrations = [
...this.scmIntegrationsApi.azure.list(),
...this.scmIntegrationsApi.bitbucket
.list()
.filter(
item =>
!this.scmIntegrationsApi.bitbucketCloud.byHost(item.config.host) &&
!this.scmIntegrationsApi.bitbucketServer.byHost(item.config.host),
),
...this.scmIntegrationsApi.bitbucketCloud.list(),
...this.scmIntegrationsApi.bitbucketServer.list(),
...this.scmIntegrationsApi.gerrit.list(),
...this.scmIntegrationsApi.gitea.list(),
...this.scmIntegrationsApi.github.list(),
...this.scmIntegrationsApi.gitlab.list(),
]
.map(c => ({ type: c.type, title: c.title, host: c.config.host }))
.filter(c => options.allowedHosts.includes(c.host));
return {
integrations,
};
}
async getTemplateParameterSchema(
templateRef: string,
): Promise<TemplateParameterSchema> {
const { namespace, kind, name } = parseEntityRef(templateRef, {
defaultKind: 'template',
});
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const templatePath = [namespace, kind, name]
.map(s => encodeURIComponent(s))
.join('/');
const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;
const response = await this.fetchApi.fetch(url);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
const schema: TemplateParameterSchema = await response.json();
return schema;
}
async scaffold(
options: ScaffolderScaffoldOptions,
): Promise<ScaffolderScaffoldResponse> {
const { templateRef, values, secrets = {} } = options;
const url = `${await this.discoveryApi.getBaseUrl('scaffolder')}/v2/tasks`;
const response = await this.fetchApi.fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateRef,
values: { ...values },
secrets,
}),
});
if (response.status !== 201) {
const status = `${response.status} ${response.statusText}`;
const body = await response.text();
throw new Error(`Backend request failed, ${status} ${body.trim()}`);
}
const { id } = (await response.json()) as { id: string };
return { taskId: id };
}
async getTask(taskId: string): Promise<ScaffolderTask> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}`;
const response = await this.fetchApi.fetch(url);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
streamLogs(options: ScaffolderStreamLogsOptions): Observable<LogEvent> {
if (this.useLongPollingLogs) {
return this.streamLogsPolling(options);
}
return this.streamLogsEventStream(options);
}
async dryRun(
options: ScaffolderDryRunOptions,
): Promise<ScaffolderDryRunResponse> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const response = await this.fetchApi.fetch(`${baseUrl}/v2/dry-run`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
template: options.template,
values: options.values,
secrets: options.secrets,
directoryContents: options.directoryContents,
}),
});
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return response.json();
}
private streamLogsEventStream({
isTaskRecoverable,
taskId,
after,
}: ScaffolderStreamLogsOptions): Observable<LogEvent> {
return new ObservableImpl(subscriber => {
const params = new URLSearchParams();
if (after !== undefined) {
params.set('after', String(Number(after)));
}
this.discoveryApi.getBaseUrl('scaffolder').then(
baseUrl => {
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
taskId,
)}/eventstream`;
const processEvent = (event: any) => {
if (event.data) {
try {
subscriber.next(JSON.parse(event.data));
} catch (ex) {
subscriber.error(ex);
}
}
};
const ctrl = new AbortController();
void fetchEventSource(url, {
fetch: this.fetchApi.fetch,
signal: ctrl.signal,
onmessage(e: EventSourceMessage) {
if (e.event === 'log') {
processEvent(e);
return;
} else if (e.event === 'completion' && !isTaskRecoverable) {
processEvent(e);
subscriber.complete();
ctrl.abort();
return;
}
processEvent(e);
},
onerror(err) {
subscriber.error(err);
},
});
},
error => {
subscriber.error(error);
},
);
});
}
private streamLogsPolling({
taskId,
after: inputAfter,
}: {
taskId: string;
after?: number;
}): Observable<LogEvent> {
let after = inputAfter;
return new ObservableImpl(subscriber => {
this.discoveryApi.getBaseUrl('scaffolder').then(async baseUrl => {
while (!subscriber.closed) {
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
taskId,
)}/events?${qs.stringify({ after })}`;
const response = await this.fetchApi.fetch(url);
if (!response.ok) {
// wait for one second to not run into an
await new Promise(resolve => setTimeout(resolve, 1000));
continue;
}
const logs = (await response.json()) as LogEvent[];
for (const event of logs) {
after = Number(event.id);
subscriber.next(event);
if (event.type === 'completion') {
subscriber.complete();
return;
}
}
}
});
});
}
async listActions(): Promise<ListActionsResponse> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const response = await this.fetchApi.fetch(`${baseUrl}/v2/actions`);
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
async listTemplatingExtensions(): Promise<ListTemplatingExtensionsResponse> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const response = await this.fetchApi.fetch(
`${baseUrl}/v2/templating-extensions`,
);
if (!response.ok) {
throw ResponseError.fromResponse(response);
}
return response.json();
}
async cancelTask(taskId: string): Promise<void> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}/cancel`;
const response = await this.fetchApi.fetch(url, {
method: 'POST',
});
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
async retry?(taskId: string): Promise<void> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}/retry`;
const response = await this.fetchApi.fetch(url, {
method: 'POST',
});
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
return await response.json();
}
async autocomplete({
token,
resource,
provider,
context,
}: {
token: string;
provider: string;
resource: string;
context?: Record<string, string>;
}): Promise<{ results: { title?: string; id: string }[] }> {
const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');
const url = `${baseUrl}/v2/autocomplete/${provider}/${resource}`;
const response = await this.fetchApi.fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
token,
context: context ?? {},
}),
});
if (!response.ok) {
throw await ResponseError.fromResponse(response);
}
const { results } = await response.json();
return { results };
}
}
export class ScaffolderClient extends _ScaffolderClient {}
@@ -223,7 +223,7 @@ function OngoingTaskContent(props: {
const [, { execute: triggerRetry }] = useAsync(async () => {
if (taskId) {
analytics.captureEvent('retried', 'Template has been retried');
await scaffolderApi.retry?.(taskId);
await scaffolderApi.retry?.({ taskId });
}
});
@@ -85,6 +85,7 @@ export const BitbucketRepoPicker = (
scaffolderApi
.autocomplete({
context: {},
token: accessToken,
resource: 'workspaces',
provider: 'bitbucket-cloud',
+32 -29
View File
@@ -21,22 +21,8 @@
*/
import {
createScaffolderFieldExtension as createScaffolderFieldExtensionTemp,
ScaffolderFieldExtensions as ScaffolderFieldExtensionsTemp,
useTemplateSecrets as useTemplateSecretsTemp,
scaffolderApiRef as scaffolderApiRefTemp,
createScaffolderLayout as createScaffolderLayoutTemp,
ScaffolderLayouts as ScaffolderLayoutsTemp,
type LayoutOptions as LayoutOptionsTemp,
type LayoutTemplate as LayoutTemplateTemp,
type ScaffolderApi as ScaffolderApiTemp,
type ScaffolderUseTemplateSecrets as ScaffolderUseTemplateSecretsTemp,
type TemplateParameterSchema as TemplateParameterSchemaTemp,
type CustomFieldExtensionSchema as CustomFieldExtensionSchemaTemp,
type CustomFieldValidator as CustomFieldValidatorTemp,
type FieldExtensionOptions as FieldExtensionOptionsTemp,
type FieldExtensionComponentProps as FieldExtensionComponentPropsTemp,
type FieldExtensionComponent as FieldExtensionComponentTemp,
type ListActionsResponse as ListActionsResponseTemp,
type LogEvent as LogEventTemp,
type ScaffolderDryRunOptions as ScaffolderDryRunOptionsTemp,
@@ -50,6 +36,23 @@ import {
type ScaffolderTask as ScaffolderTaskTemp,
type ScaffolderTaskOutput as ScaffolderTaskOutputTemp,
type ScaffolderTaskStatus as ScaffolderTaskStatusTemp,
} from '@backstage/plugin-scaffolder-common';
import {
createScaffolderFieldExtension as createScaffolderFieldExtensionTemp,
ScaffolderFieldExtensions as ScaffolderFieldExtensionsTemp,
useTemplateSecrets as useTemplateSecretsTemp,
scaffolderApiRef as scaffolderApiRefTemp,
createScaffolderLayout as createScaffolderLayoutTemp,
ScaffolderLayouts as ScaffolderLayoutsTemp,
type LayoutOptions as LayoutOptionsTemp,
type LayoutTemplate as LayoutTemplateTemp,
type ScaffolderUseTemplateSecrets as ScaffolderUseTemplateSecretsTemp,
type CustomFieldExtensionSchema as CustomFieldExtensionSchemaTemp,
type CustomFieldValidator as CustomFieldValidatorTemp,
type FieldExtensionOptions as FieldExtensionOptionsTemp,
type FieldExtensionComponentProps as FieldExtensionComponentPropsTemp,
type FieldExtensionComponent as FieldExtensionComponentTemp,
} from '@backstage/plugin-scaffolder-react';
import { rootRouteRef as rootRouteRefTemp } from './routes';
@@ -82,7 +85,7 @@ export const useTemplateSecrets = useTemplateSecretsTemp;
export const scaffolderApiRef = scaffolderApiRefTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderApi} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderApi} instead as this has now been moved.
*/
export type ScaffolderApi = ScaffolderApiTemp;
/**
@@ -92,7 +95,7 @@ export type ScaffolderApi = ScaffolderApiTemp;
export type ScaffolderUseTemplateSecrets = ScaffolderUseTemplateSecretsTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#TemplateParameterSchema} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#TemplateParameterSchema} instead as this has now been moved.
*/
export type TemplateParameterSchema = TemplateParameterSchemaTemp;
/**
@@ -127,69 +130,69 @@ export type FieldExtensionComponent<_TReturnValue, _TInputProps> =
FieldExtensionComponentTemp<_TReturnValue, _TInputProps>;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ListActionsResponse} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ListActionsResponse} instead as this has now been moved.
*/
export type ListActionsResponse = ListActionsResponseTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#LogEvent} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#LogEvent} instead as this has now been moved.
*/
export type LogEvent = LogEventTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderDryRunOptions} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderDryRunOptions} instead as this has now been moved.
*/
export type ScaffolderDryRunOptions = ScaffolderDryRunOptionsTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderDryRunResponse} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderDryRunResponse} instead as this has now been moved.
*/
export type ScaffolderDryRunResponse = ScaffolderDryRunResponseTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderGetIntegrationsListOptions} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderGetIntegrationsListOptions} instead as this has now been moved.
*/
export type ScaffolderGetIntegrationsListOptions =
ScaffolderGetIntegrationsListOptionsTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderGetIntegrationsListResponse} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderGetIntegrationsListResponse} instead as this has now been moved.
*/
export type ScaffolderGetIntegrationsListResponse =
ScaffolderGetIntegrationsListResponseTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderOutputlink} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderOutputlink} instead as this has now been moved.
*/
export type ScaffolderOutputlink = ScaffolderOutputLinkTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderScaffoldOptions} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderScaffoldOptions} instead as this has now been moved.
*/
export type ScaffolderScaffoldOptions = ScaffolderScaffoldOptionsTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderScaffoldResponse} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderScaffoldResponse} instead as this has now been moved.
*/
export type ScaffolderScaffoldResponse = ScaffolderScaffoldResponseTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderStreamLogsOptions} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderStreamLogsOptions} instead as this has now been moved.
*/
export type ScaffolderStreamLogsOptions = ScaffolderStreamLogsOptionsTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderTask} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderTask} instead as this has now been moved.
*/
export type ScaffolderTask = ScaffolderTaskTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderTaskOutput} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderTaskOutput} instead as this has now been moved.
*/
export type ScaffolderTaskOutput = ScaffolderTaskOutputTemp;
/**
* @public
* @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderTaskStatus} instead as this has now been moved.
* @deprecated use import from {@link @backstage/plugin-scaffolder-common#ScaffolderTaskStatus} instead as this has now been moved.
*/
export type ScaffolderTaskStatus = ScaffolderTaskStatusTemp;
/**