@backstage/plugin-scaffolder-common 2.3.0-next.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder-common
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 1a705ca: Added `templateDryRunPermission`, which allows permission policies to control who can submit inline Software Template dry runs.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- be0a75a: Exclude internal task data from task responses.
|
|
12
|
+
- ffaca06: Fixed a connection leak in the scaffolder event stream where unsubscribing did not abort the underlying SSE connection. Also changed unexpected server disconnects to signal an error instead of silently completing, enabling consumers to retry.
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @backstage/integration@2.1.2
|
|
15
|
+
- @backstage/catalog-model@1.10.1
|
|
16
|
+
- @backstage/plugin-permission-common@0.9.11
|
|
17
|
+
|
|
18
|
+
## 2.3.0-next.2
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- @backstage/integration@2.1.2-next.1
|
|
24
|
+
- @backstage/plugin-permission-common@0.9.11-next.0
|
|
25
|
+
|
|
3
26
|
## 2.3.0-next.1
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
|
@@ -145,11 +145,16 @@ class ScaffolderClient {
|
|
|
145
145
|
if (after !== void 0) {
|
|
146
146
|
params.set("after", String(Number(after)));
|
|
147
147
|
}
|
|
148
|
+
const ctrl = new AbortController();
|
|
148
149
|
this.discoveryApi.getBaseUrl("scaffolder").then(
|
|
149
150
|
(baseUrl) => {
|
|
151
|
+
if (ctrl.signal.aborted) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const query = params.toString();
|
|
150
155
|
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
|
|
151
156
|
taskId
|
|
152
|
-
)}/eventstream`;
|
|
157
|
+
)}/eventstream${query ? `?${query}` : ""}`;
|
|
153
158
|
const processEvent = (event) => {
|
|
154
159
|
if (event.data) {
|
|
155
160
|
try {
|
|
@@ -159,10 +164,10 @@ class ScaffolderClient {
|
|
|
159
164
|
}
|
|
160
165
|
}
|
|
161
166
|
};
|
|
162
|
-
|
|
163
|
-
void fetchEventSource.fetchEventSource(url, {
|
|
167
|
+
fetchEventSource.fetchEventSource(url, {
|
|
164
168
|
fetch: this.fetchApi.fetch,
|
|
165
169
|
signal: ctrl.signal,
|
|
170
|
+
openWhenHidden: true,
|
|
166
171
|
onmessage(e) {
|
|
167
172
|
if (e.event === "log") {
|
|
168
173
|
processEvent(e);
|
|
@@ -175,15 +180,22 @@ class ScaffolderClient {
|
|
|
175
180
|
}
|
|
176
181
|
processEvent(e);
|
|
177
182
|
},
|
|
183
|
+
onclose() {
|
|
184
|
+
subscriber.error(new Error("SSE connection closed unexpectedly"));
|
|
185
|
+
},
|
|
178
186
|
onerror(err) {
|
|
187
|
+
ctrl.abort();
|
|
179
188
|
subscriber.error(err);
|
|
189
|
+
throw err;
|
|
180
190
|
}
|
|
191
|
+
}).catch(() => {
|
|
181
192
|
});
|
|
182
193
|
},
|
|
183
194
|
(error) => {
|
|
184
195
|
subscriber.error(error);
|
|
185
196
|
}
|
|
186
197
|
);
|
|
198
|
+
return () => ctrl.abort();
|
|
187
199
|
});
|
|
188
200
|
}
|
|
189
201
|
streamLogsPolling({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScaffolderClient.cjs.js","sources":["../src/ScaffolderClient.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { Observable } from '@backstage/types';\nimport {\n EventSourceMessage,\n fetchEventSource,\n} from '@microsoft/fetch-event-source';\nimport ObservableImpl from 'zen-observable';\n\nimport { type TemplateParameterSchema } from './TemplateEntityV1beta3';\nimport {\n ListActionsResponse,\n ListTemplatingExtensionsResponse,\n LogEvent,\n ScaffolderApi,\n ScaffolderDryRunOptions,\n ScaffolderDryRunResponse,\n ScaffolderGetIntegrationsListOptions,\n ScaffolderGetIntegrationsListResponse,\n ScaffolderRequestOptions,\n ScaffolderScaffoldOptions,\n ScaffolderScaffoldResponse,\n ScaffolderStreamLogsOptions,\n ScaffolderTask,\n} from './api';\nimport { DefaultApiClient, TaskStatus, TypedResponse } from './schema/openapi';\n\n/**\n * An API to interact with the scaffolder backend.\n *\n * @public\n */\nexport class ScaffolderClient implements ScaffolderApi {\n private readonly apiClient: DefaultApiClient;\n private readonly discoveryApi: {\n getBaseUrl(pluginId: string): Promise<string>;\n };\n private readonly scmIntegrationsApi: ScmIntegrationRegistry;\n private readonly fetchApi: { fetch: typeof fetch };\n private readonly identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n private readonly useLongPollingLogs: boolean;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi: { fetch: typeof fetch };\n identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n scmIntegrationsApi: ScmIntegrationRegistry;\n useLongPollingLogs?: boolean;\n }) {\n this.apiClient = new DefaultApiClient(options);\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi ?? { fetch };\n this.scmIntegrationsApi = options.scmIntegrationsApi;\n this.useLongPollingLogs = options.useLongPollingLogs ?? false;\n this.identityApi = options.identityApi;\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTasks}\n */\n async listTasks(\n request: {\n filterByOwnership: 'owned' | 'all';\n limit?: number;\n offset?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }> {\n if (!this.identityApi) {\n throw new Error(\n 'IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method',\n );\n }\n\n const { userEntityRef } = await this.identityApi.getBackstageIdentity();\n\n return await this.requestRequired(\n await this.apiClient.listTasks(\n {\n query: {\n createdBy:\n request.filterByOwnership === 'owned'\n ? [userEntityRef]\n : undefined,\n limit: request.limit,\n offset: request.offset,\n },\n },\n options,\n ),\n );\n }\n\n async getIntegrationsList(\n options: ScaffolderGetIntegrationsListOptions,\n ): Promise<ScaffolderGetIntegrationsListResponse> {\n const integrations = [\n ...this.scmIntegrationsApi.azure.list(),\n ...this.scmIntegrationsApi.bitbucketCloud.list(),\n ...this.scmIntegrationsApi.bitbucketServer.list(),\n ...this.scmIntegrationsApi.gerrit.list(),\n ...this.scmIntegrationsApi.gitea.list(),\n ...this.scmIntegrationsApi.github.list(),\n ...this.scmIntegrationsApi.gitlab.list(),\n ]\n .map(c => ({ type: c.type, title: c.title, host: c.config.host }))\n .filter(c => options.allowedHosts.includes(c.host));\n\n return {\n integrations,\n };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTemplateParameterSchema}\n */\n async getTemplateParameterSchema(\n templateRef: string,\n options?: ScaffolderRequestOptions,\n ): Promise<TemplateParameterSchema> {\n return await this.requestRequired(\n await this.apiClient.getTemplateParameterSchema(\n {\n path: parseEntityRef(templateRef, {\n defaultKind: 'template',\n }),\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.scaffold}\n */\n async scaffold(\n request: ScaffolderScaffoldOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderScaffoldResponse> {\n const response = await this.apiClient.scaffold(\n {\n body: request,\n },\n options,\n );\n\n if (response.status !== 201) {\n const status = `${response.status} ${response.statusText}`;\n const body = await response.text();\n throw new Error(`Backend request failed, ${status} ${body.trim()}`);\n }\n\n const { id } = await response.json();\n return { taskId: id };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTask}\n */\n async getTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderTask> {\n return await this.requestRequired(\n await this.apiClient.getTask(\n {\n path: { taskId },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.streamLogs}\n */\n streamLogs(\n request: ScaffolderStreamLogsOptions,\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n if (this.useLongPollingLogs) {\n return this.streamLogsPolling(request, options);\n }\n\n return this.streamLogsEventStream(request);\n }\n\n /**\n * {@inheritdoc ScaffolderApi.dryRun}\n */\n async dryRun(\n request: ScaffolderDryRunOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderDryRunResponse> {\n return await this.requestRequired(\n await this.apiClient.dryRun(\n {\n body: {\n template: request.template,\n values: request.values,\n secrets: request.secrets,\n directoryContents: request.directoryContents,\n },\n },\n options,\n ),\n );\n }\n\n private streamLogsEventStream({\n isTaskRecoverable,\n taskId,\n after,\n }: ScaffolderStreamLogsOptions): Observable<LogEvent> {\n return new ObservableImpl(subscriber => {\n const params = new URLSearchParams();\n if (after !== undefined) {\n params.set('after', String(Number(after)));\n }\n\n this.discoveryApi.getBaseUrl('scaffolder').then(\n baseUrl => {\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/eventstream`;\n\n const processEvent = (event: any) => {\n if (event.data) {\n try {\n subscriber.next(JSON.parse(event.data));\n } catch (ex) {\n subscriber.error(ex);\n }\n }\n };\n\n const ctrl = new AbortController();\n void fetchEventSource(url, {\n fetch: this.fetchApi.fetch,\n signal: ctrl.signal,\n onmessage(e: EventSourceMessage) {\n if (e.event === 'log') {\n processEvent(e);\n return;\n } else if (e.event === 'completion' && !isTaskRecoverable) {\n processEvent(e);\n subscriber.complete();\n ctrl.abort();\n return;\n }\n processEvent(e);\n },\n onerror(err) {\n subscriber.error(err);\n },\n });\n },\n error => {\n subscriber.error(error);\n },\n );\n });\n }\n\n private streamLogsPolling(\n {\n taskId,\n after: inputAfter,\n }: {\n taskId: string;\n after?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n let after = inputAfter;\n\n return new ObservableImpl(subscriber => {\n (async () => {\n while (!subscriber.closed) {\n const response = await this.apiClient.streamLogsPolling(\n {\n path: { taskId },\n query: { after },\n },\n options,\n );\n\n if (!response.ok) {\n // wait for one second to not run into an\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const logs = (await response.json()) as LogEvent[];\n\n for (const event of logs) {\n after = Number(event.id);\n\n subscriber.next(event);\n\n if (event.type === 'completion') {\n subscriber.complete();\n return;\n }\n }\n }\n })();\n });\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listActions}\n */\n async listActions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListActionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listActions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTemplatingExtensions}\n */\n async listTemplatingExtensions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListTemplatingExtensionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listTemplatingExtensions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.cancelTask}\n */\n async cancelTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ status?: TaskStatus }> {\n return await this.requestRequired(\n await this.apiClient.cancelTask({ path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async retry(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ id: string }> {\n return await this.requestRequired(\n await this.apiClient.retry({ body: {}, path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async autocomplete(\n {\n token,\n resource,\n provider,\n context,\n }: {\n token: string;\n provider: string;\n resource: string;\n context: Record<string, string>;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ results: { title?: string; id: string }[] }> {\n return await this.requestRequired(\n await this.apiClient.autocomplete(\n {\n path: { provider, resource },\n body: { token, context },\n },\n options,\n ),\n );\n }\n\n //\n // Private methods\n //\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n}\n"],"names":["DefaultApiClient","parseEntityRef","ObservableImpl","fetchEventSource","ResponseError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScaffolderClient.cjs.js","sources":["../src/ScaffolderClient.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { Observable } from '@backstage/types';\nimport {\n EventSourceMessage,\n fetchEventSource,\n} from '@microsoft/fetch-event-source';\nimport ObservableImpl from 'zen-observable';\n\nimport { type TemplateParameterSchema } from './TemplateEntityV1beta3';\nimport {\n ListActionsResponse,\n ListTemplatingExtensionsResponse,\n LogEvent,\n ScaffolderApi,\n ScaffolderDryRunOptions,\n ScaffolderDryRunResponse,\n ScaffolderGetIntegrationsListOptions,\n ScaffolderGetIntegrationsListResponse,\n ScaffolderRequestOptions,\n ScaffolderScaffoldOptions,\n ScaffolderScaffoldResponse,\n ScaffolderStreamLogsOptions,\n ScaffolderTask,\n} from './api';\nimport { DefaultApiClient, TaskStatus, TypedResponse } from './schema/openapi';\n\n/**\n * An API to interact with the scaffolder backend.\n *\n * @public\n */\nexport class ScaffolderClient implements ScaffolderApi {\n private readonly apiClient: DefaultApiClient;\n private readonly discoveryApi: {\n getBaseUrl(pluginId: string): Promise<string>;\n };\n private readonly scmIntegrationsApi: ScmIntegrationRegistry;\n private readonly fetchApi: { fetch: typeof fetch };\n private readonly identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n private readonly useLongPollingLogs: boolean;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi: { fetch: typeof fetch };\n identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n scmIntegrationsApi: ScmIntegrationRegistry;\n useLongPollingLogs?: boolean;\n }) {\n this.apiClient = new DefaultApiClient(options);\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi ?? { fetch };\n this.scmIntegrationsApi = options.scmIntegrationsApi;\n this.useLongPollingLogs = options.useLongPollingLogs ?? false;\n this.identityApi = options.identityApi;\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTasks}\n */\n async listTasks(\n request: {\n filterByOwnership: 'owned' | 'all';\n limit?: number;\n offset?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }> {\n if (!this.identityApi) {\n throw new Error(\n 'IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method',\n );\n }\n\n const { userEntityRef } = await this.identityApi.getBackstageIdentity();\n\n return await this.requestRequired(\n await this.apiClient.listTasks(\n {\n query: {\n createdBy:\n request.filterByOwnership === 'owned'\n ? [userEntityRef]\n : undefined,\n limit: request.limit,\n offset: request.offset,\n },\n },\n options,\n ),\n );\n }\n\n async getIntegrationsList(\n options: ScaffolderGetIntegrationsListOptions,\n ): Promise<ScaffolderGetIntegrationsListResponse> {\n const integrations = [\n ...this.scmIntegrationsApi.azure.list(),\n ...this.scmIntegrationsApi.bitbucketCloud.list(),\n ...this.scmIntegrationsApi.bitbucketServer.list(),\n ...this.scmIntegrationsApi.gerrit.list(),\n ...this.scmIntegrationsApi.gitea.list(),\n ...this.scmIntegrationsApi.github.list(),\n ...this.scmIntegrationsApi.gitlab.list(),\n ]\n .map(c => ({ type: c.type, title: c.title, host: c.config.host }))\n .filter(c => options.allowedHosts.includes(c.host));\n\n return {\n integrations,\n };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTemplateParameterSchema}\n */\n async getTemplateParameterSchema(\n templateRef: string,\n options?: ScaffolderRequestOptions,\n ): Promise<TemplateParameterSchema> {\n return await this.requestRequired(\n await this.apiClient.getTemplateParameterSchema(\n {\n path: parseEntityRef(templateRef, {\n defaultKind: 'template',\n }),\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.scaffold}\n */\n async scaffold(\n request: ScaffolderScaffoldOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderScaffoldResponse> {\n const response = await this.apiClient.scaffold(\n {\n body: request,\n },\n options,\n );\n\n if (response.status !== 201) {\n const status = `${response.status} ${response.statusText}`;\n const body = await response.text();\n throw new Error(`Backend request failed, ${status} ${body.trim()}`);\n }\n\n const { id } = await response.json();\n return { taskId: id };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTask}\n */\n async getTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderTask> {\n return await this.requestRequired(\n await this.apiClient.getTask(\n {\n path: { taskId },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.streamLogs}\n */\n streamLogs(\n request: ScaffolderStreamLogsOptions,\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n if (this.useLongPollingLogs) {\n return this.streamLogsPolling(request, options);\n }\n\n return this.streamLogsEventStream(request);\n }\n\n /**\n * {@inheritdoc ScaffolderApi.dryRun}\n */\n async dryRun(\n request: ScaffolderDryRunOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderDryRunResponse> {\n return await this.requestRequired(\n await this.apiClient.dryRun(\n {\n body: {\n template: request.template,\n values: request.values,\n secrets: request.secrets,\n directoryContents: request.directoryContents,\n },\n },\n options,\n ),\n );\n }\n\n private streamLogsEventStream({\n isTaskRecoverable,\n taskId,\n after,\n }: ScaffolderStreamLogsOptions): Observable<LogEvent> {\n return new ObservableImpl(subscriber => {\n const params = new URLSearchParams();\n if (after !== undefined) {\n params.set('after', String(Number(after)));\n }\n\n const ctrl = new AbortController();\n\n this.discoveryApi.getBaseUrl('scaffolder').then(\n baseUrl => {\n if (ctrl.signal.aborted) {\n return;\n }\n\n const query = params.toString();\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/eventstream${query ? `?${query}` : ''}`;\n\n const processEvent = (event: any) => {\n if (event.data) {\n try {\n subscriber.next(JSON.parse(event.data));\n } catch (ex) {\n subscriber.error(ex);\n }\n }\n };\n\n fetchEventSource(url, {\n fetch: this.fetchApi.fetch,\n signal: ctrl.signal,\n openWhenHidden: true,\n onmessage(e: EventSourceMessage) {\n if (e.event === 'log') {\n processEvent(e);\n return;\n } else if (e.event === 'completion' && !isTaskRecoverable) {\n processEvent(e);\n subscriber.complete();\n ctrl.abort();\n return;\n }\n processEvent(e);\n },\n onclose() {\n subscriber.error(new Error('SSE connection closed unexpectedly'));\n },\n onerror(err) {\n ctrl.abort();\n subscriber.error(err);\n throw err;\n },\n }).catch(() => {\n // The throw in onerror is the documented way to stop fetchEventSource\n // from retrying, but it also rejects this promise. The error is already\n // forwarded via subscriber.error above, so we consume the rejection here.\n });\n },\n error => {\n subscriber.error(error);\n },\n );\n\n return () => ctrl.abort();\n });\n }\n\n private streamLogsPolling(\n {\n taskId,\n after: inputAfter,\n }: {\n taskId: string;\n after?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n let after = inputAfter;\n\n return new ObservableImpl(subscriber => {\n (async () => {\n while (!subscriber.closed) {\n const response = await this.apiClient.streamLogsPolling(\n {\n path: { taskId },\n query: { after },\n },\n options,\n );\n\n if (!response.ok) {\n // wait for one second to not run into an\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const logs = (await response.json()) as LogEvent[];\n\n for (const event of logs) {\n after = Number(event.id);\n\n subscriber.next(event);\n\n if (event.type === 'completion') {\n subscriber.complete();\n return;\n }\n }\n }\n })();\n });\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listActions}\n */\n async listActions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListActionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listActions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTemplatingExtensions}\n */\n async listTemplatingExtensions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListTemplatingExtensionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listTemplatingExtensions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.cancelTask}\n */\n async cancelTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ status?: TaskStatus }> {\n return await this.requestRequired(\n await this.apiClient.cancelTask({ path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async retry(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ id: string }> {\n return await this.requestRequired(\n await this.apiClient.retry({ body: {}, path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async autocomplete(\n {\n token,\n resource,\n provider,\n context,\n }: {\n token: string;\n provider: string;\n resource: string;\n context: Record<string, string>;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ results: { title?: string; id: string }[] }> {\n return await this.requestRequired(\n await this.apiClient.autocomplete(\n {\n path: { provider, resource },\n body: { token, context },\n },\n options,\n ),\n );\n }\n\n //\n // Private methods\n //\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n}\n"],"names":["DefaultApiClient","parseEntityRef","ObservableImpl","fetchEventSource","ResponseError"],"mappings":"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"}
|
|
@@ -139,11 +139,16 @@ class ScaffolderClient {
|
|
|
139
139
|
if (after !== void 0) {
|
|
140
140
|
params.set("after", String(Number(after)));
|
|
141
141
|
}
|
|
142
|
+
const ctrl = new AbortController();
|
|
142
143
|
this.discoveryApi.getBaseUrl("scaffolder").then(
|
|
143
144
|
(baseUrl) => {
|
|
145
|
+
if (ctrl.signal.aborted) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const query = params.toString();
|
|
144
149
|
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
|
|
145
150
|
taskId
|
|
146
|
-
)}/eventstream`;
|
|
151
|
+
)}/eventstream${query ? `?${query}` : ""}`;
|
|
147
152
|
const processEvent = (event) => {
|
|
148
153
|
if (event.data) {
|
|
149
154
|
try {
|
|
@@ -153,10 +158,10 @@ class ScaffolderClient {
|
|
|
153
158
|
}
|
|
154
159
|
}
|
|
155
160
|
};
|
|
156
|
-
|
|
157
|
-
void fetchEventSource(url, {
|
|
161
|
+
fetchEventSource(url, {
|
|
158
162
|
fetch: this.fetchApi.fetch,
|
|
159
163
|
signal: ctrl.signal,
|
|
164
|
+
openWhenHidden: true,
|
|
160
165
|
onmessage(e) {
|
|
161
166
|
if (e.event === "log") {
|
|
162
167
|
processEvent(e);
|
|
@@ -169,15 +174,22 @@ class ScaffolderClient {
|
|
|
169
174
|
}
|
|
170
175
|
processEvent(e);
|
|
171
176
|
},
|
|
177
|
+
onclose() {
|
|
178
|
+
subscriber.error(new Error("SSE connection closed unexpectedly"));
|
|
179
|
+
},
|
|
172
180
|
onerror(err) {
|
|
181
|
+
ctrl.abort();
|
|
173
182
|
subscriber.error(err);
|
|
183
|
+
throw err;
|
|
174
184
|
}
|
|
185
|
+
}).catch(() => {
|
|
175
186
|
});
|
|
176
187
|
},
|
|
177
188
|
(error) => {
|
|
178
189
|
subscriber.error(error);
|
|
179
190
|
}
|
|
180
191
|
);
|
|
192
|
+
return () => ctrl.abort();
|
|
181
193
|
});
|
|
182
194
|
}
|
|
183
195
|
streamLogsPolling({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScaffolderClient.esm.js","sources":["../src/ScaffolderClient.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { Observable } from '@backstage/types';\nimport {\n EventSourceMessage,\n fetchEventSource,\n} from '@microsoft/fetch-event-source';\nimport ObservableImpl from 'zen-observable';\n\nimport { type TemplateParameterSchema } from './TemplateEntityV1beta3';\nimport {\n ListActionsResponse,\n ListTemplatingExtensionsResponse,\n LogEvent,\n ScaffolderApi,\n ScaffolderDryRunOptions,\n ScaffolderDryRunResponse,\n ScaffolderGetIntegrationsListOptions,\n ScaffolderGetIntegrationsListResponse,\n ScaffolderRequestOptions,\n ScaffolderScaffoldOptions,\n ScaffolderScaffoldResponse,\n ScaffolderStreamLogsOptions,\n ScaffolderTask,\n} from './api';\nimport { DefaultApiClient, TaskStatus, TypedResponse } from './schema/openapi';\n\n/**\n * An API to interact with the scaffolder backend.\n *\n * @public\n */\nexport class ScaffolderClient implements ScaffolderApi {\n private readonly apiClient: DefaultApiClient;\n private readonly discoveryApi: {\n getBaseUrl(pluginId: string): Promise<string>;\n };\n private readonly scmIntegrationsApi: ScmIntegrationRegistry;\n private readonly fetchApi: { fetch: typeof fetch };\n private readonly identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n private readonly useLongPollingLogs: boolean;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi: { fetch: typeof fetch };\n identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n scmIntegrationsApi: ScmIntegrationRegistry;\n useLongPollingLogs?: boolean;\n }) {\n this.apiClient = new DefaultApiClient(options);\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi ?? { fetch };\n this.scmIntegrationsApi = options.scmIntegrationsApi;\n this.useLongPollingLogs = options.useLongPollingLogs ?? false;\n this.identityApi = options.identityApi;\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTasks}\n */\n async listTasks(\n request: {\n filterByOwnership: 'owned' | 'all';\n limit?: number;\n offset?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }> {\n if (!this.identityApi) {\n throw new Error(\n 'IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method',\n );\n }\n\n const { userEntityRef } = await this.identityApi.getBackstageIdentity();\n\n return await this.requestRequired(\n await this.apiClient.listTasks(\n {\n query: {\n createdBy:\n request.filterByOwnership === 'owned'\n ? [userEntityRef]\n : undefined,\n limit: request.limit,\n offset: request.offset,\n },\n },\n options,\n ),\n );\n }\n\n async getIntegrationsList(\n options: ScaffolderGetIntegrationsListOptions,\n ): Promise<ScaffolderGetIntegrationsListResponse> {\n const integrations = [\n ...this.scmIntegrationsApi.azure.list(),\n ...this.scmIntegrationsApi.bitbucketCloud.list(),\n ...this.scmIntegrationsApi.bitbucketServer.list(),\n ...this.scmIntegrationsApi.gerrit.list(),\n ...this.scmIntegrationsApi.gitea.list(),\n ...this.scmIntegrationsApi.github.list(),\n ...this.scmIntegrationsApi.gitlab.list(),\n ]\n .map(c => ({ type: c.type, title: c.title, host: c.config.host }))\n .filter(c => options.allowedHosts.includes(c.host));\n\n return {\n integrations,\n };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTemplateParameterSchema}\n */\n async getTemplateParameterSchema(\n templateRef: string,\n options?: ScaffolderRequestOptions,\n ): Promise<TemplateParameterSchema> {\n return await this.requestRequired(\n await this.apiClient.getTemplateParameterSchema(\n {\n path: parseEntityRef(templateRef, {\n defaultKind: 'template',\n }),\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.scaffold}\n */\n async scaffold(\n request: ScaffolderScaffoldOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderScaffoldResponse> {\n const response = await this.apiClient.scaffold(\n {\n body: request,\n },\n options,\n );\n\n if (response.status !== 201) {\n const status = `${response.status} ${response.statusText}`;\n const body = await response.text();\n throw new Error(`Backend request failed, ${status} ${body.trim()}`);\n }\n\n const { id } = await response.json();\n return { taskId: id };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTask}\n */\n async getTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderTask> {\n return await this.requestRequired(\n await this.apiClient.getTask(\n {\n path: { taskId },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.streamLogs}\n */\n streamLogs(\n request: ScaffolderStreamLogsOptions,\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n if (this.useLongPollingLogs) {\n return this.streamLogsPolling(request, options);\n }\n\n return this.streamLogsEventStream(request);\n }\n\n /**\n * {@inheritdoc ScaffolderApi.dryRun}\n */\n async dryRun(\n request: ScaffolderDryRunOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderDryRunResponse> {\n return await this.requestRequired(\n await this.apiClient.dryRun(\n {\n body: {\n template: request.template,\n values: request.values,\n secrets: request.secrets,\n directoryContents: request.directoryContents,\n },\n },\n options,\n ),\n );\n }\n\n private streamLogsEventStream({\n isTaskRecoverable,\n taskId,\n after,\n }: ScaffolderStreamLogsOptions): Observable<LogEvent> {\n return new ObservableImpl(subscriber => {\n const params = new URLSearchParams();\n if (after !== undefined) {\n params.set('after', String(Number(after)));\n }\n\n this.discoveryApi.getBaseUrl('scaffolder').then(\n baseUrl => {\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/eventstream`;\n\n const processEvent = (event: any) => {\n if (event.data) {\n try {\n subscriber.next(JSON.parse(event.data));\n } catch (ex) {\n subscriber.error(ex);\n }\n }\n };\n\n const ctrl = new AbortController();\n void fetchEventSource(url, {\n fetch: this.fetchApi.fetch,\n signal: ctrl.signal,\n onmessage(e: EventSourceMessage) {\n if (e.event === 'log') {\n processEvent(e);\n return;\n } else if (e.event === 'completion' && !isTaskRecoverable) {\n processEvent(e);\n subscriber.complete();\n ctrl.abort();\n return;\n }\n processEvent(e);\n },\n onerror(err) {\n subscriber.error(err);\n },\n });\n },\n error => {\n subscriber.error(error);\n },\n );\n });\n }\n\n private streamLogsPolling(\n {\n taskId,\n after: inputAfter,\n }: {\n taskId: string;\n after?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n let after = inputAfter;\n\n return new ObservableImpl(subscriber => {\n (async () => {\n while (!subscriber.closed) {\n const response = await this.apiClient.streamLogsPolling(\n {\n path: { taskId },\n query: { after },\n },\n options,\n );\n\n if (!response.ok) {\n // wait for one second to not run into an\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const logs = (await response.json()) as LogEvent[];\n\n for (const event of logs) {\n after = Number(event.id);\n\n subscriber.next(event);\n\n if (event.type === 'completion') {\n subscriber.complete();\n return;\n }\n }\n }\n })();\n });\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listActions}\n */\n async listActions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListActionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listActions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTemplatingExtensions}\n */\n async listTemplatingExtensions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListTemplatingExtensionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listTemplatingExtensions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.cancelTask}\n */\n async cancelTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ status?: TaskStatus }> {\n return await this.requestRequired(\n await this.apiClient.cancelTask({ path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async retry(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ id: string }> {\n return await this.requestRequired(\n await this.apiClient.retry({ body: {}, path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async autocomplete(\n {\n token,\n resource,\n provider,\n context,\n }: {\n token: string;\n provider: string;\n resource: string;\n context: Record<string, string>;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ results: { title?: string; id: string }[] }> {\n return await this.requestRequired(\n await this.apiClient.autocomplete(\n {\n path: { provider, resource },\n body: { token, context },\n },\n options,\n ),\n );\n }\n\n //\n // Private methods\n //\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScaffolderClient.esm.js","sources":["../src/ScaffolderClient.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { ResponseError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { Observable } from '@backstage/types';\nimport {\n EventSourceMessage,\n fetchEventSource,\n} from '@microsoft/fetch-event-source';\nimport ObservableImpl from 'zen-observable';\n\nimport { type TemplateParameterSchema } from './TemplateEntityV1beta3';\nimport {\n ListActionsResponse,\n ListTemplatingExtensionsResponse,\n LogEvent,\n ScaffolderApi,\n ScaffolderDryRunOptions,\n ScaffolderDryRunResponse,\n ScaffolderGetIntegrationsListOptions,\n ScaffolderGetIntegrationsListResponse,\n ScaffolderRequestOptions,\n ScaffolderScaffoldOptions,\n ScaffolderScaffoldResponse,\n ScaffolderStreamLogsOptions,\n ScaffolderTask,\n} from './api';\nimport { DefaultApiClient, TaskStatus, TypedResponse } from './schema/openapi';\n\n/**\n * An API to interact with the scaffolder backend.\n *\n * @public\n */\nexport class ScaffolderClient implements ScaffolderApi {\n private readonly apiClient: DefaultApiClient;\n private readonly discoveryApi: {\n getBaseUrl(pluginId: string): Promise<string>;\n };\n private readonly scmIntegrationsApi: ScmIntegrationRegistry;\n private readonly fetchApi: { fetch: typeof fetch };\n private readonly identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n private readonly useLongPollingLogs: boolean;\n\n constructor(options: {\n discoveryApi: { getBaseUrl(pluginId: string): Promise<string> };\n fetchApi: { fetch: typeof fetch };\n identityApi?: {\n getBackstageIdentity(): Promise<{\n type: 'user';\n userEntityRef: string;\n ownershipEntityRefs: string[];\n }>;\n };\n scmIntegrationsApi: ScmIntegrationRegistry;\n useLongPollingLogs?: boolean;\n }) {\n this.apiClient = new DefaultApiClient(options);\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi ?? { fetch };\n this.scmIntegrationsApi = options.scmIntegrationsApi;\n this.useLongPollingLogs = options.useLongPollingLogs ?? false;\n this.identityApi = options.identityApi;\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTasks}\n */\n async listTasks(\n request: {\n filterByOwnership: 'owned' | 'all';\n limit?: number;\n offset?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ tasks: ScaffolderTask[]; totalTasks?: number }> {\n if (!this.identityApi) {\n throw new Error(\n 'IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method',\n );\n }\n\n const { userEntityRef } = await this.identityApi.getBackstageIdentity();\n\n return await this.requestRequired(\n await this.apiClient.listTasks(\n {\n query: {\n createdBy:\n request.filterByOwnership === 'owned'\n ? [userEntityRef]\n : undefined,\n limit: request.limit,\n offset: request.offset,\n },\n },\n options,\n ),\n );\n }\n\n async getIntegrationsList(\n options: ScaffolderGetIntegrationsListOptions,\n ): Promise<ScaffolderGetIntegrationsListResponse> {\n const integrations = [\n ...this.scmIntegrationsApi.azure.list(),\n ...this.scmIntegrationsApi.bitbucketCloud.list(),\n ...this.scmIntegrationsApi.bitbucketServer.list(),\n ...this.scmIntegrationsApi.gerrit.list(),\n ...this.scmIntegrationsApi.gitea.list(),\n ...this.scmIntegrationsApi.github.list(),\n ...this.scmIntegrationsApi.gitlab.list(),\n ]\n .map(c => ({ type: c.type, title: c.title, host: c.config.host }))\n .filter(c => options.allowedHosts.includes(c.host));\n\n return {\n integrations,\n };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTemplateParameterSchema}\n */\n async getTemplateParameterSchema(\n templateRef: string,\n options?: ScaffolderRequestOptions,\n ): Promise<TemplateParameterSchema> {\n return await this.requestRequired(\n await this.apiClient.getTemplateParameterSchema(\n {\n path: parseEntityRef(templateRef, {\n defaultKind: 'template',\n }),\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.scaffold}\n */\n async scaffold(\n request: ScaffolderScaffoldOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderScaffoldResponse> {\n const response = await this.apiClient.scaffold(\n {\n body: request,\n },\n options,\n );\n\n if (response.status !== 201) {\n const status = `${response.status} ${response.statusText}`;\n const body = await response.text();\n throw new Error(`Backend request failed, ${status} ${body.trim()}`);\n }\n\n const { id } = await response.json();\n return { taskId: id };\n }\n\n /**\n * {@inheritdoc ScaffolderApi.getTask}\n */\n async getTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderTask> {\n return await this.requestRequired(\n await this.apiClient.getTask(\n {\n path: { taskId },\n },\n options,\n ),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.streamLogs}\n */\n streamLogs(\n request: ScaffolderStreamLogsOptions,\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n if (this.useLongPollingLogs) {\n return this.streamLogsPolling(request, options);\n }\n\n return this.streamLogsEventStream(request);\n }\n\n /**\n * {@inheritdoc ScaffolderApi.dryRun}\n */\n async dryRun(\n request: ScaffolderDryRunOptions,\n options?: ScaffolderRequestOptions,\n ): Promise<ScaffolderDryRunResponse> {\n return await this.requestRequired(\n await this.apiClient.dryRun(\n {\n body: {\n template: request.template,\n values: request.values,\n secrets: request.secrets,\n directoryContents: request.directoryContents,\n },\n },\n options,\n ),\n );\n }\n\n private streamLogsEventStream({\n isTaskRecoverable,\n taskId,\n after,\n }: ScaffolderStreamLogsOptions): Observable<LogEvent> {\n return new ObservableImpl(subscriber => {\n const params = new URLSearchParams();\n if (after !== undefined) {\n params.set('after', String(Number(after)));\n }\n\n const ctrl = new AbortController();\n\n this.discoveryApi.getBaseUrl('scaffolder').then(\n baseUrl => {\n if (ctrl.signal.aborted) {\n return;\n }\n\n const query = params.toString();\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/eventstream${query ? `?${query}` : ''}`;\n\n const processEvent = (event: any) => {\n if (event.data) {\n try {\n subscriber.next(JSON.parse(event.data));\n } catch (ex) {\n subscriber.error(ex);\n }\n }\n };\n\n fetchEventSource(url, {\n fetch: this.fetchApi.fetch,\n signal: ctrl.signal,\n openWhenHidden: true,\n onmessage(e: EventSourceMessage) {\n if (e.event === 'log') {\n processEvent(e);\n return;\n } else if (e.event === 'completion' && !isTaskRecoverable) {\n processEvent(e);\n subscriber.complete();\n ctrl.abort();\n return;\n }\n processEvent(e);\n },\n onclose() {\n subscriber.error(new Error('SSE connection closed unexpectedly'));\n },\n onerror(err) {\n ctrl.abort();\n subscriber.error(err);\n throw err;\n },\n }).catch(() => {\n // The throw in onerror is the documented way to stop fetchEventSource\n // from retrying, but it also rejects this promise. The error is already\n // forwarded via subscriber.error above, so we consume the rejection here.\n });\n },\n error => {\n subscriber.error(error);\n },\n );\n\n return () => ctrl.abort();\n });\n }\n\n private streamLogsPolling(\n {\n taskId,\n after: inputAfter,\n }: {\n taskId: string;\n after?: number;\n },\n options?: ScaffolderRequestOptions,\n ): Observable<LogEvent> {\n let after = inputAfter;\n\n return new ObservableImpl(subscriber => {\n (async () => {\n while (!subscriber.closed) {\n const response = await this.apiClient.streamLogsPolling(\n {\n path: { taskId },\n query: { after },\n },\n options,\n );\n\n if (!response.ok) {\n // wait for one second to not run into an\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const logs = (await response.json()) as LogEvent[];\n\n for (const event of logs) {\n after = Number(event.id);\n\n subscriber.next(event);\n\n if (event.type === 'completion') {\n subscriber.complete();\n return;\n }\n }\n }\n })();\n });\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listActions}\n */\n async listActions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListActionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listActions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.listTemplatingExtensions}\n */\n async listTemplatingExtensions(\n options?: ScaffolderRequestOptions,\n ): Promise<ListTemplatingExtensionsResponse> {\n return await this.requestRequired(\n await this.apiClient.listTemplatingExtensions(null as any, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.cancelTask}\n */\n async cancelTask(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ status?: TaskStatus }> {\n return await this.requestRequired(\n await this.apiClient.cancelTask({ path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async retry(\n taskId: string,\n options?: ScaffolderRequestOptions,\n ): Promise<{ id: string }> {\n return await this.requestRequired(\n await this.apiClient.retry({ body: {}, path: { taskId } }, options),\n );\n }\n\n /**\n * {@inheritdoc ScaffolderApi.retry}\n */\n async autocomplete(\n {\n token,\n resource,\n provider,\n context,\n }: {\n token: string;\n provider: string;\n resource: string;\n context: Record<string, string>;\n },\n options?: ScaffolderRequestOptions,\n ): Promise<{ results: { title?: string; id: string }[] }> {\n return await this.requestRequired(\n await this.apiClient.autocomplete(\n {\n path: { provider, resource },\n body: { token, context },\n },\n options,\n ),\n );\n }\n\n //\n // Private methods\n //\n\n private async requestRequired<T>(response: TypedResponse<T>): Promise<T> {\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-scaffolder-common",
|
|
3
|
-
"version": "2.3.0
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Common functionalities for the scaffolder, to be shared between scaffolder and scaffolder-backend plugin",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "common-library",
|
|
@@ -70,11 +70,11 @@
|
|
|
70
70
|
"test": "backstage-cli package test"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@backstage/catalog-model": "1.10.
|
|
74
|
-
"@backstage/errors": "1.3.1",
|
|
75
|
-
"@backstage/integration": "2.1.2
|
|
76
|
-
"@backstage/plugin-permission-common": "0.9.
|
|
77
|
-
"@backstage/types": "1.2.2",
|
|
73
|
+
"@backstage/catalog-model": "^1.10.1",
|
|
74
|
+
"@backstage/errors": "^1.3.1",
|
|
75
|
+
"@backstage/integration": "^2.1.2",
|
|
76
|
+
"@backstage/plugin-permission-common": "^0.9.11",
|
|
77
|
+
"@backstage/types": "^1.2.2",
|
|
78
78
|
"@microsoft/fetch-event-source": "^2.0.1",
|
|
79
79
|
"@types/json-schema": "^7.0.9",
|
|
80
80
|
"cross-fetch": "^4.0.0",
|
|
@@ -82,8 +82,8 @@
|
|
|
82
82
|
"zen-observable": "^0.10.0"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@backstage/cli": "0.36.6
|
|
86
|
-
"@backstage/test-utils": "1.7.22
|
|
85
|
+
"@backstage/cli": "^0.36.6",
|
|
86
|
+
"@backstage/test-utils": "^1.7.22",
|
|
87
87
|
"msw": "^2.0.0"
|
|
88
88
|
},
|
|
89
89
|
"module": "./dist/index.esm.js"
|