@@ -1,70 +0,0 @@
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: Group
|
||||
metadata:
|
||||
name: team-a
|
||||
description: Team A
|
||||
spec:
|
||||
type: team
|
||||
profile:
|
||||
# Intentional no displayName for testing
|
||||
email: team-a@example.com
|
||||
picture: https://avatars.dicebear.com/api/identicon/team-a@example.com.svg?background=%23fff&margin=25
|
||||
parent: backstage
|
||||
children: []
|
||||
---
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: User
|
||||
metadata:
|
||||
name: breanna.davison
|
||||
spec:
|
||||
profile:
|
||||
# Intentional no displayName for testing
|
||||
email: breanna-davison@example.com
|
||||
picture: https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg?background=%23fff
|
||||
memberOf: [team-a]
|
||||
---
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: User
|
||||
metadata:
|
||||
name: janelle.dawe
|
||||
spec:
|
||||
profile:
|
||||
displayName: Janelle Dawe
|
||||
email: janelle-dawe@example.com
|
||||
picture: https://avatars.dicebear.com/api/avataaars/janelle-dawe@example.com.svg?background=%23fff
|
||||
memberOf: [team-a]
|
||||
---
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: User
|
||||
metadata:
|
||||
name: nigel.manning
|
||||
spec:
|
||||
profile:
|
||||
displayName: Nigel Manning
|
||||
email: nigel-manning@example.com
|
||||
picture: https://avatars.dicebear.com/api/avataaars/nigel-manning@example.com.svg?background=%23fff
|
||||
memberOf: [team-a]
|
||||
---
|
||||
# This user is added as an example, to make it more easy for the "Guest"
|
||||
# sign-in option to demonstrate some entities being owned. In a regular org,
|
||||
# a guest user would probably not be registered like this.
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: User
|
||||
metadata:
|
||||
name: guest
|
||||
spec:
|
||||
profile:
|
||||
displayName: Guest User
|
||||
email: guest@example.com
|
||||
picture: https://avatars.dicebear.com/api/avataaars/guest@example.com.svg?background=%23fff
|
||||
memberOf: [team-a]
|
||||
|
||||
---
|
||||
apiVersion: backstage.io/v1alpha1
|
||||
kind: User
|
||||
metadata:
|
||||
name: benjdlambert
|
||||
spec:
|
||||
profile:
|
||||
picture: https://avatars.dicebear.com/api/avataaars/breanna-davison@example.com.svg?background=%23fff
|
||||
memberOf: []
|
||||
@@ -93,7 +93,9 @@ export class DatabaseTaskStore implements TaskStore {
|
||||
this.db = options.database;
|
||||
}
|
||||
|
||||
async list(options: { createdBy?: string }): Promise<SerializedTask[]> {
|
||||
async list(options: {
|
||||
createdBy?: string;
|
||||
}): Promise<{ tasks: SerializedTask[] }> {
|
||||
const queryBuilder = this.db<RawDbTaskRow>('tasks');
|
||||
|
||||
if (options.createdBy) {
|
||||
@@ -104,7 +106,7 @@ export class DatabaseTaskStore implements TaskStore {
|
||||
|
||||
const results = await queryBuilder.orderBy('created_at', 'desc').select();
|
||||
|
||||
return results.map(result => ({
|
||||
const tasks = results.map(result => ({
|
||||
id: result.id,
|
||||
spec: JSON.parse(result.spec),
|
||||
status: result.status,
|
||||
@@ -112,6 +114,8 @@ export class DatabaseTaskStore implements TaskStore {
|
||||
lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),
|
||||
createdAt: parseSqlDateToIsoString(result.created_at),
|
||||
}));
|
||||
|
||||
return { tasks };
|
||||
}
|
||||
|
||||
async getTask(taskId: string): Promise<SerializedTask> {
|
||||
|
||||
@@ -208,13 +208,13 @@ describe('StorageTaskBroker', () => {
|
||||
const { taskId } = await broker.dispatch({ spec: {} as TaskSpec });
|
||||
|
||||
const promise = broker.list();
|
||||
await expect(promise).resolves.toEqual(
|
||||
expect.arrayContaining([
|
||||
await expect(promise).resolves.toEqual({
|
||||
tasks: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: taskId,
|
||||
}),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should list only tasks createdBy a specific user', async () => {
|
||||
@@ -227,6 +227,6 @@ describe('StorageTaskBroker', () => {
|
||||
const task = await storage.getTask(taskId);
|
||||
|
||||
const promise = broker.list({ createdBy: 'user:default/foo' });
|
||||
await expect(promise).resolves.toEqual([task]);
|
||||
await expect(promise).resolves.toEqual({ tasks: [task] });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -151,7 +151,14 @@ export class StorageTaskBroker implements TaskBroker {
|
||||
private readonly logger: Logger,
|
||||
) {}
|
||||
|
||||
async list(options?: { createdBy?: string }): Promise<SerializedTask[]> {
|
||||
async list(options?: {
|
||||
createdBy?: string;
|
||||
}): Promise<{ tasks: SerializedTask[] }> {
|
||||
if (!this.storage.list) {
|
||||
throw new Error(
|
||||
'TaskStore does not implement the list method. Please implement the list method to be able to list tasks',
|
||||
);
|
||||
}
|
||||
return await this.storage.list({ createdBy: options?.createdBy });
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ export interface TaskBroker {
|
||||
after: number | undefined;
|
||||
}): Observable<{ events: SerializedTaskEvent[] }>;
|
||||
get(taskId: string): Promise<SerializedTask>;
|
||||
list(options?: { createdBy?: string }): Promise<SerializedTask[]>;
|
||||
list?(options?: { createdBy?: string }): Promise<{ tasks: SerializedTask[] }>;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +194,7 @@ export interface TaskStore {
|
||||
listStaleTasks(options: { timeoutS: number }): Promise<{
|
||||
tasks: { taskId: string }[];
|
||||
}>;
|
||||
list(options: { createdBy?: string }): Promise<SerializedTask[]>;
|
||||
list?(options: { createdBy?: string }): Promise<{ tasks: SerializedTask[] }>;
|
||||
|
||||
emitLogEvent({ taskId, body }: TaskStoreEmitOptions): Promise<void>;
|
||||
listEvents({
|
||||
|
||||
@@ -292,42 +292,52 @@ describe('createRouter', () => {
|
||||
|
||||
describe('GET /v2/tasks', () => {
|
||||
it('return all tasks', async () => {
|
||||
(taskBroker.list as jest.Mocked<TaskBroker>['list']).mockResolvedValue([
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: '',
|
||||
},
|
||||
]);
|
||||
(
|
||||
taskBroker.list as jest.Mocked<Required<TaskBroker>>['list']
|
||||
).mockResolvedValue({
|
||||
tasks: [
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const response = await request(app).get(`/v2/tasks`);
|
||||
expect(taskBroker.list).toBeCalledWith({
|
||||
createdBy: undefined,
|
||||
});
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.body).toStrictEqual([
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: '',
|
||||
},
|
||||
]);
|
||||
expect(response.body).toStrictEqual({
|
||||
tasks: [
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('return filtered tasks', async () => {
|
||||
(taskBroker.list as jest.Mocked<TaskBroker>['list']).mockResolvedValue([
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: 'user:default/foo',
|
||||
},
|
||||
]);
|
||||
(
|
||||
taskBroker.list as jest.Mocked<Required<TaskBroker>>['list']
|
||||
).mockResolvedValue({
|
||||
tasks: [
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: 'user:default/foo',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const response = await request(app).get(
|
||||
`/v2/tasks?createdBy=user:default/foo`,
|
||||
@@ -337,15 +347,17 @@ describe('createRouter', () => {
|
||||
});
|
||||
|
||||
expect(response.status).toEqual(200);
|
||||
expect(response.body).toStrictEqual([
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: 'user:default/foo',
|
||||
},
|
||||
]);
|
||||
expect(response.body).toStrictEqual({
|
||||
tasks: [
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
createdBy: 'user:default/foo',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -253,7 +253,20 @@ export async function createRouter(
|
||||
res.status(201).json({ id: result.taskId });
|
||||
})
|
||||
.get('/v2/tasks', async (req, res) => {
|
||||
const userEntityRef = req.query.createdBy?.toString();
|
||||
const [userEntityRef] = [req.query.createdBy].flat();
|
||||
|
||||
if (
|
||||
typeof userEntityRef !== 'string' &&
|
||||
typeof userEntityRef !== 'undefined'
|
||||
) {
|
||||
throw new InputError('createdBy query parameter must be a string');
|
||||
}
|
||||
|
||||
if (!taskBroker.list) {
|
||||
throw new Error(
|
||||
'TaskBroker does not support listing tasks, please implement the list method on the TaskBroker.',
|
||||
);
|
||||
}
|
||||
|
||||
const tasks = await taskBroker.list({
|
||||
createdBy: userEntityRef,
|
||||
|
||||
@@ -347,7 +347,7 @@ describe('api', () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const result = await apiClient.listTasks({ createdBy: 'all' });
|
||||
const result = await apiClient.listTasks({ filterByOwnership: 'all' });
|
||||
expect(result).toHaveLength(2);
|
||||
});
|
||||
it('should list task using the current user as owner', async () => {
|
||||
@@ -357,23 +357,27 @@ describe('api', () => {
|
||||
|
||||
if (createdBy) {
|
||||
return res(
|
||||
ctx.json([
|
||||
{
|
||||
createdBy,
|
||||
},
|
||||
]),
|
||||
ctx.json({
|
||||
tasks: [
|
||||
{
|
||||
createdBy,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return res(
|
||||
ctx.json([
|
||||
{
|
||||
createdBy: null,
|
||||
},
|
||||
{
|
||||
createdBy: null,
|
||||
},
|
||||
]),
|
||||
ctx.json({
|
||||
tasks: [
|
||||
{
|
||||
createdBy: null,
|
||||
},
|
||||
{
|
||||
createdBy: null,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
@@ -382,9 +386,9 @@ describe('api', () => {
|
||||
userEntityRef: 'user:default/foo',
|
||||
});
|
||||
|
||||
const result = await apiClient.listTasks({ createdBy: 'owned' });
|
||||
const result = await apiClient.listTasks({ filterByOwnership: 'owned' });
|
||||
expect(identityApi.getBackstageIdentity).toBeCalled();
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result.tasks).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -37,7 +37,6 @@ import {
|
||||
ScaffolderGetIntegrationsListOptions,
|
||||
ScaffolderGetIntegrationsListResponse,
|
||||
ScaffolderTask,
|
||||
TasksOwnerFilterKind,
|
||||
ScaffolderDryRunOptions,
|
||||
ScaffolderDryRunResponse,
|
||||
} from './types';
|
||||
@@ -61,13 +60,13 @@ export class ScaffolderClient implements ScaffolderApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly scmIntegrationsApi: ScmIntegrationRegistry;
|
||||
private readonly fetchApi: FetchApi;
|
||||
private readonly identityApi: IdentityApi;
|
||||
private readonly identityApi?: IdentityApi;
|
||||
private readonly useLongPollingLogs: boolean;
|
||||
|
||||
constructor(options: {
|
||||
discoveryApi: DiscoveryApi;
|
||||
fetchApi: FetchApi;
|
||||
identityApi: IdentityApi;
|
||||
identityApi?: IdentityApi;
|
||||
scmIntegrationsApi: ScmIntegrationRegistry;
|
||||
useLongPollingLogs?: boolean;
|
||||
}) {
|
||||
@@ -79,18 +78,21 @@ export class ScaffolderClient implements ScaffolderApi {
|
||||
}
|
||||
|
||||
async listTasks(options: {
|
||||
createdBy: TasksOwnerFilterKind;
|
||||
}): Promise<ScaffolderTask[]> {
|
||||
filterByOwnership: 'owned' | 'all';
|
||||
}): Promise<{ tasks: ScaffolderTask[] }> {
|
||||
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(
|
||||
options.createdBy === 'owned' ? { createdBy: userEntityRef } : {},
|
||||
options.filterByOwnership === 'owned' ? { createdBy: userEntityRef } : {},
|
||||
);
|
||||
|
||||
const url = `${baseUrl}/v2/tasks?${query}`;
|
||||
|
||||
const response = await this.fetchApi.fetch(url);
|
||||
const response = await this.fetchApi.fetch(`${baseUrl}/v2/tasks?${query}`);
|
||||
if (!response.ok) {
|
||||
throw await ResponseError.fromResponse(response);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ describe('<ListTasksPage />', () => {
|
||||
};
|
||||
catalogApi.getEntityByRef.mockResolvedValue(entity);
|
||||
|
||||
scaffolderApiMock.listTasks.mockResolvedValue([]);
|
||||
scaffolderApiMock.listTasks.mockResolvedValue({ tasks: [] });
|
||||
|
||||
const { getByText } = await renderInTestApp(
|
||||
<TestApiProvider
|
||||
@@ -101,20 +101,22 @@ describe('<ListTasksPage />', () => {
|
||||
},
|
||||
};
|
||||
catalogApi.getEntityByRef.mockResolvedValue(entity);
|
||||
scaffolderApiMock.listTasks.mockResolvedValue([
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {
|
||||
user: { ref: 'user:default/foo' },
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/test',
|
||||
},
|
||||
} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
lastHeartbeatAt: '',
|
||||
},
|
||||
]);
|
||||
scaffolderApiMock.listTasks.mockResolvedValue({
|
||||
tasks: [
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {
|
||||
user: { ref: 'user:default/foo' },
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/test',
|
||||
},
|
||||
} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
lastHeartbeatAt: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
scaffolderApiMock.getTemplateParameterSchema.mockResolvedValue({
|
||||
title: 'One Template',
|
||||
@@ -139,7 +141,9 @@ describe('<ListTasksPage />', () => {
|
||||
},
|
||||
);
|
||||
|
||||
expect(scaffolderApiMock.listTasks).toBeCalledWith({ createdBy: 'owned' });
|
||||
expect(scaffolderApiMock.listTasks).toBeCalledWith({
|
||||
filterByOwnership: 'owned',
|
||||
});
|
||||
expect(getByText('List template tasks')).toBeInTheDocument();
|
||||
expect(getByText('All tasks that have been started')).toBeInTheDocument();
|
||||
expect(getByText('Tasks')).toBeInTheDocument();
|
||||
@@ -173,36 +177,40 @@ describe('<ListTasksPage />', () => {
|
||||
});
|
||||
|
||||
scaffolderApiMock.listTasks
|
||||
.mockResolvedValue([
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {
|
||||
user: { ref: 'user:default/foo' },
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/mock',
|
||||
},
|
||||
} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
lastHeartbeatAt: '',
|
||||
},
|
||||
])
|
||||
.mockResolvedValue([
|
||||
{
|
||||
id: 'b-random-id',
|
||||
spec: {
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/mock',
|
||||
},
|
||||
user: {
|
||||
ref: 'user:default/boo',
|
||||
},
|
||||
} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
lastHeartbeatAt: '',
|
||||
},
|
||||
]);
|
||||
.mockResolvedValue({
|
||||
tasks: [
|
||||
{
|
||||
id: 'a-random-id',
|
||||
spec: {
|
||||
user: { ref: 'user:default/foo' },
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/mock',
|
||||
},
|
||||
} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
lastHeartbeatAt: '',
|
||||
},
|
||||
],
|
||||
})
|
||||
.mockResolvedValue({
|
||||
tasks: [
|
||||
{
|
||||
id: 'b-random-id',
|
||||
spec: {
|
||||
templateInfo: {
|
||||
entityRef: 'template:default/mock',
|
||||
},
|
||||
user: {
|
||||
ref: 'user:default/boo',
|
||||
},
|
||||
} as any,
|
||||
status: 'completed',
|
||||
createdAt: '',
|
||||
lastHeartbeatAt: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
scaffolderApiMock.getTemplateParameterSchema.mockResolvedValue({
|
||||
title: 'One Template',
|
||||
@@ -232,7 +240,9 @@ describe('<ListTasksPage />', () => {
|
||||
fireEvent.click(allButton);
|
||||
});
|
||||
|
||||
expect(scaffolderApiMock.listTasks).toBeCalledWith({ createdBy: 'all' });
|
||||
expect(scaffolderApiMock.listTasks).toBeCalledWith({
|
||||
filterByOwnership: 'all',
|
||||
});
|
||||
expect(await findByText('One Template')).toBeInTheDocument();
|
||||
expect(await findByText('OtherUser')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -31,7 +31,6 @@ import React, { useState } from 'react';
|
||||
import { scaffolderApiRef } from '../../api';
|
||||
import { rootRouteRef } from '../../routes';
|
||||
import { OwnerListPicker } from './OwnerListPicker';
|
||||
import { TasksOwnerFilterKind } from '../../types';
|
||||
import {
|
||||
CreatedAtColumn,
|
||||
OwnerEntityColumn,
|
||||
@@ -40,7 +39,7 @@ import {
|
||||
} from './columns';
|
||||
|
||||
export interface MyTaskPageProps {
|
||||
initiallySelectedFilter?: TasksOwnerFilterKind;
|
||||
initiallySelectedFilter?: 'owned' | 'all';
|
||||
}
|
||||
|
||||
const ListTaskPageContent = (props: MyTaskPageProps) => {
|
||||
@@ -52,14 +51,15 @@ const ListTaskPageContent = (props: MyTaskPageProps) => {
|
||||
const [ownerFilter, setOwnerFilter] = useState(initiallySelectedFilter);
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
if (scaffolderApi.listTasks) {
|
||||
return scaffolderApi.listTasks?.({ createdBy: ownerFilter });
|
||||
return scaffolderApi.listTasks?.({ filterByOwnership: ownerFilter });
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'listTasks is not implemented in the scaffolderApi, please make sure to implement this method.',
|
||||
);
|
||||
return Promise.resolve([]);
|
||||
|
||||
return Promise.resolve({ tasks: [] });
|
||||
}, [scaffolderApi, ownerFilter]);
|
||||
|
||||
if (loading) {
|
||||
@@ -89,7 +89,7 @@ const ListTaskPageContent = (props: MyTaskPageProps) => {
|
||||
</CatalogFilterLayout.Filters>
|
||||
<CatalogFilterLayout.Content>
|
||||
<MaterialTable
|
||||
data={value!}
|
||||
data={value?.tasks ?? []}
|
||||
title="Tasks"
|
||||
columns={[
|
||||
{
|
||||
|
||||
@@ -29,8 +29,6 @@ import React, { Fragment } from 'react';
|
||||
|
||||
import AllIcon from '@material-ui/icons/FontDownload';
|
||||
|
||||
import { TasksOwnerFilterKind } from '../../types';
|
||||
|
||||
const useStyles = makeStyles<Theme>(
|
||||
theme => ({
|
||||
root: {
|
||||
@@ -91,7 +89,7 @@ function getFilterGroups(): ButtonGroup[] {
|
||||
|
||||
export const OwnerListPicker = (props: {
|
||||
filter: string;
|
||||
onSelectOwner: (id: TasksOwnerFilterKind) => void;
|
||||
onSelectOwner: (id: 'owned' | 'all') => void;
|
||||
}) => {
|
||||
const { filter, onSelectOwner } = props;
|
||||
const classes = useStyles();
|
||||
@@ -111,7 +109,7 @@ export const OwnerListPicker = (props: {
|
||||
key={item.id}
|
||||
button
|
||||
divider
|
||||
onClick={() => onSelectOwner(item.id as TasksOwnerFilterKind)}
|
||||
onClick={() => onSelectOwner(item.id as 'owned' | 'all')}
|
||||
selected={item.id === filter}
|
||||
className={classes.menuItem}
|
||||
data-testid={`owner-picker-${item.id}`}
|
||||
|
||||
@@ -37,7 +37,6 @@ export type {
|
||||
ScaffolderTaskOutput,
|
||||
ScaffolderTaskStatus,
|
||||
TemplateParameterSchema,
|
||||
TasksOwnerFilterKind,
|
||||
} from './types';
|
||||
export {
|
||||
createScaffolderFieldExtension,
|
||||
|
||||
@@ -102,13 +102,6 @@ export type LogEvent = {
|
||||
taskId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* The status of each task you can filter from `ScaffolderClient`
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type TasksOwnerFilterKind = 'owned' | 'all';
|
||||
|
||||
/**
|
||||
* The input options to the `scaffold` method of the `ScaffolderClient`.
|
||||
*
|
||||
@@ -200,10 +193,10 @@ export interface ScaffolderApi {
|
||||
getTask(taskId: string): Promise<ScaffolderTask>;
|
||||
|
||||
listTasks?({
|
||||
createdBy,
|
||||
filterByOwnership,
|
||||
}: {
|
||||
createdBy: TasksOwnerFilterKind;
|
||||
}): Promise<ScaffolderTask[]>;
|
||||
filterByOwnership: 'owned' | 'all';
|
||||
}): Promise<{ tasks: ScaffolderTask[] }>;
|
||||
|
||||
getIntegrationsList(
|
||||
options: ScaffolderGetIntegrationsListOptions,
|
||||
|
||||
@@ -4176,6 +4176,14 @@
|
||||
resolved "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.14.1.tgz#155ef21065427901994e765da8a0ba0eaae8b8bd"
|
||||
integrity sha512-6Wci+Tp3CgPt/B9B0a3J4s3yMgLNSku6w5TV6mN+61C71UqsRBv2FUibBf3tPGlNxebgPHMEUzKpb1ggE8KCKw==
|
||||
|
||||
"@mswjs/cookies@^0.1.6":
|
||||
version "0.1.7"
|
||||
resolved "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.1.7.tgz#d334081b2c51057a61c1dd7b76ca3cac02251651"
|
||||
integrity sha512-bDg1ReMBx+PYDB4Pk7y1Q07Zz1iKIEUWQpkEXiA2lEWg9gvOZ8UBmGXilCEUvyYoRFlmr/9iXTRR69TrgSwX/Q==
|
||||
dependencies:
|
||||
"@types/set-cookie-parser" "^2.4.0"
|
||||
set-cookie-parser "^2.4.6"
|
||||
|
||||
"@mswjs/cookies@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.0.tgz#7ef2b5d7e444498bb27cf57720e61f76a4ce9f23"
|
||||
@@ -4184,6 +4192,18 @@
|
||||
"@types/set-cookie-parser" "^2.4.0"
|
||||
set-cookie-parser "^2.4.6"
|
||||
|
||||
"@mswjs/interceptors@^0.12.6":
|
||||
version "0.12.7"
|
||||
resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.12.7.tgz#0d1cd4cd31a0f663e0455993951201faa09d0909"
|
||||
integrity sha512-eGjZ3JRAt0Fzi5FgXiV/P3bJGj0NqsN7vBS0J0FO2AQRQ0jCKQS4lEFm4wvlSgKQNfeuc/Vz6d81VtU3Gkx/zg==
|
||||
dependencies:
|
||||
"@open-draft/until" "^1.0.3"
|
||||
"@xmldom/xmldom" "^0.7.2"
|
||||
debug "^4.3.2"
|
||||
headers-utils "^3.0.2"
|
||||
outvariant "^1.2.0"
|
||||
strict-event-emitter "^0.2.0"
|
||||
|
||||
"@mswjs/interceptors@^0.15.1":
|
||||
version "0.15.3"
|
||||
resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.15.3.tgz#bcd17b5d7558d4f598007a4bb383b42dc9264f8d"
|
||||
@@ -5967,6 +5987,14 @@
|
||||
resolved "https://registry.npmjs.org/@types/humanize-duration/-/humanize-duration-3.27.1.tgz#f14740d1f585a0a8e3f46359b62fda8b0eaa31e7"
|
||||
integrity sha512-K3e+NZlpCKd6Bd/EIdqjFJRFHbrq5TzPPLwREk5Iv/YoIjQrs6ljdAUCo+Lb2xFlGNOjGSE0dqsVD19cZL137w==
|
||||
|
||||
"@types/inquirer@^7.3.3":
|
||||
version "7.3.3"
|
||||
resolved "https://registry.npmjs.org/@types/inquirer/-/inquirer-7.3.3.tgz#92e6676efb67fa6925c69a2ee638f67a822952ac"
|
||||
integrity sha512-HhxyLejTHMfohAuhRun4csWigAMjXTmRyiJTU1Y/I1xmggikFMkOUoMQRlFm+zQcPEGHSs3io/0FAmNZf8EymQ==
|
||||
dependencies:
|
||||
"@types/through" "*"
|
||||
rxjs "^6.4.0"
|
||||
|
||||
"@types/inquirer@^8.1.3":
|
||||
version "8.2.1"
|
||||
resolved "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.1.tgz#28a139be3105a1175e205537e8ac10830e38dbf4"
|
||||
@@ -6043,7 +6071,7 @@
|
||||
resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f"
|
||||
integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw==
|
||||
|
||||
"@types/js-levenshtein@^1.1.1":
|
||||
"@types/js-levenshtein@^1.1.0", "@types/js-levenshtein@^1.1.1":
|
||||
version "1.1.1"
|
||||
resolved "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz#ba05426a43f9e4e30b631941e0aa17bf0c890ed5"
|
||||
integrity sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==
|
||||
@@ -7163,7 +7191,7 @@
|
||||
"@webassemblyjs/ast" "1.11.1"
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@xmldom/xmldom@^0.7.0", "@xmldom/xmldom@^0.7.5":
|
||||
"@xmldom/xmldom@^0.7.0", "@xmldom/xmldom@^0.7.2", "@xmldom/xmldom@^0.7.5":
|
||||
version "0.7.5"
|
||||
resolved "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d"
|
||||
integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==
|
||||
@@ -9827,7 +9855,7 @@ cookie@0.4.1:
|
||||
resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
|
||||
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
|
||||
|
||||
cookie@0.4.2, cookie@^0.4.2, cookie@~0.4.1:
|
||||
cookie@0.4.2, cookie@^0.4.1, cookie@^0.4.2, cookie@~0.4.1:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
|
||||
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
|
||||
@@ -13556,6 +13584,11 @@ graphql-ws@^5.4.1:
|
||||
resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.5.5.tgz#f375486d3f196e2a2527b503644693ae3a8670a9"
|
||||
integrity sha512-hvyIS71vs4Tu/yUYHPvGXsTgo0t3arU820+lT5VjZS2go0ewp2LqyCgxEN56CzOG7Iys52eRhHBiD1gGRdiQtw==
|
||||
|
||||
graphql@^15.5.1:
|
||||
version "15.8.0"
|
||||
resolved "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38"
|
||||
integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==
|
||||
|
||||
graphql@^16.0.0, graphql@^16.3.0:
|
||||
version "16.5.0"
|
||||
resolved "https://registry.npmjs.org/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85"
|
||||
@@ -13782,6 +13815,11 @@ headers-polyfill@^3.0.4:
|
||||
resolved "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.0.7.tgz#725c4f591e6748f46b036197eae102c92b959ff4"
|
||||
integrity sha512-JoLCAdCEab58+2/yEmSnOlficyHFpIl0XJqwu3l+Unkm1gXpFUYsThz6Yha3D6tNhocWkCPfyW0YVIGWFqTi7w==
|
||||
|
||||
headers-utils@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/headers-utils/-/headers-utils-3.0.2.tgz#dfc65feae4b0e34357308aefbcafa99c895e59ef"
|
||||
integrity sha512-xAxZkM1dRyGV2Ou5bzMxBPNLoRCjcX+ya7KSWybQD2KwLphxsapUVK6x/02o7f4VU6GPSXch9vNY2+gkU8tYWQ==
|
||||
|
||||
helmet@^5.0.2:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.npmjs.org/helmet/-/helmet-5.0.2.tgz#3264ec6bab96c82deaf65e3403c369424cb2366c"
|
||||
@@ -14361,7 +14399,7 @@ inquirer@^7.3.3:
|
||||
strip-ansi "^6.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
inquirer@^8.0.0, inquirer@^8.2.0:
|
||||
inquirer@^8.0.0, inquirer@^8.1.1, inquirer@^8.2.0:
|
||||
version "8.2.4"
|
||||
resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4"
|
||||
integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==
|
||||
@@ -18146,6 +18184,32 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
msw@^0.35.0:
|
||||
version "0.35.0"
|
||||
resolved "https://registry.npmjs.org/msw/-/msw-0.35.0.tgz#18a4ceb6c822ef226a30421d434413bc45030d38"
|
||||
integrity sha512-V7A6PqaS31F1k//fPS0OnO7vllfaqBUFsMEu3IpYixyWpiUInfyglodnbXhhtDyytkQikpkPZv8TZi/CvZzv/w==
|
||||
dependencies:
|
||||
"@mswjs/cookies" "^0.1.6"
|
||||
"@mswjs/interceptors" "^0.12.6"
|
||||
"@open-draft/until" "^1.0.3"
|
||||
"@types/cookie" "^0.4.1"
|
||||
"@types/inquirer" "^7.3.3"
|
||||
"@types/js-levenshtein" "^1.1.0"
|
||||
chalk "^4.1.1"
|
||||
chokidar "^3.4.2"
|
||||
cookie "^0.4.1"
|
||||
graphql "^15.5.1"
|
||||
headers-utils "^3.0.2"
|
||||
inquirer "^8.1.1"
|
||||
is-node-process "^1.0.1"
|
||||
js-levenshtein "^1.1.6"
|
||||
node-fetch "^2.6.1"
|
||||
node-match-path "^0.6.3"
|
||||
statuses "^2.0.0"
|
||||
strict-event-emitter "^0.2.0"
|
||||
type-fest "^1.2.2"
|
||||
yargs "^17.0.1"
|
||||
|
||||
msw@^0.39.2:
|
||||
version "0.39.2"
|
||||
resolved "https://registry.npmjs.org/msw/-/msw-0.39.2.tgz#832e9274db62c43cb79854d5a69dce031c700de8"
|
||||
@@ -18490,6 +18554,11 @@ node-libs-browser@^2.2.1:
|
||||
util "^0.11.0"
|
||||
vm-browserify "^1.0.1"
|
||||
|
||||
node-match-path@^0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.npmjs.org/node-match-path/-/node-match-path-0.6.3.tgz#55dd8443d547f066937a0752dce462ea7dc27551"
|
||||
integrity sha512-fB1reOHKLRZCJMAka28hIxCwQLxGmd7WewOCBDYKpyA1KXi68A7vaGgdZAPhY2E6SXoYt3KqYCCvXLJ+O0Fu/Q==
|
||||
|
||||
node-modules-regexp@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40"
|
||||
@@ -19099,7 +19168,7 @@ outdent@^0.5.0:
|
||||
resolved "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff"
|
||||
integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==
|
||||
|
||||
outvariant@^1.2.1, outvariant@^1.3.0:
|
||||
outvariant@^1.2.0, outvariant@^1.2.1, outvariant@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/outvariant/-/outvariant-1.3.0.tgz#c39723b1d2cba729c930b74bf962317a81b9b1c9"
|
||||
integrity sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ==
|
||||
@@ -22133,7 +22202,7 @@ rxjs@7.5.5, rxjs@^7.1.0, rxjs@^7.2.0, rxjs@^7.5.1, rxjs@^7.5.5:
|
||||
dependencies:
|
||||
tslib "^2.1.0"
|
||||
|
||||
rxjs@^6.3.3, rxjs@^6.6.0, rxjs@^6.6.3:
|
||||
rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.3:
|
||||
version "6.6.7"
|
||||
resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
|
||||
integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
|
||||
@@ -25768,7 +25837,7 @@ yargs@^17.0.0, yargs@^17.1.1, yargs@^17.2.1:
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^21.0.0"
|
||||
|
||||
yargs@^17.3.1:
|
||||
yargs@^17.0.1, yargs@^17.3.1:
|
||||
version "17.5.1"
|
||||
resolved "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e"
|
||||
integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==
|
||||
|
||||
Reference in New Issue
Block a user