@backstage/plugin-scaffolder 0.11.16 → 0.12.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-8b5d21c1.esm.js","sources":["../../src/api.ts","../../src/components/fields/EntityPicker/EntityPicker.tsx","../../src/components/fields/TextValuePicker/TextValuePicker.tsx","../../src/components/fields/EntityNamePicker/EntityNamePicker.tsx","../../src/components/fields/EntityNamePicker/validation.ts","../../src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx","../../src/components/fields/OwnerPicker/OwnerPicker.tsx","../../src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx","../../src/components/fields/RepoUrlPicker/GitlabRepoPicker.tsx","../../src/components/fields/RepoUrlPicker/AzureRepoPicker.tsx","../../src/components/fields/RepoUrlPicker/BitbucketRepoPicker.tsx","../../src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx","../../src/components/fields/RepoUrlPicker/utils.ts","../../src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx","../../src/components/fields/RepoUrlPicker/validation.ts","../../src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx","../../src/extensions/index.tsx","../../src/routes.ts","../../src/plugin.ts","../../src/components/FavouriteTemplate/FavouriteTemplate.tsx","../../src/components/TemplateCard/TemplateCard.tsx","../../src/components/TemplateList/TemplateList.tsx","../../src/components/TemplateTypePicker/TemplateTypePicker.tsx"],"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 { EntityName } from '@backstage/catalog-model';\nimport {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { JsonObject, JsonValue, Observable } from '@backstage/types';\nimport { Field, FieldValidation } from '@rjsf/core';\nimport qs from 'qs';\nimport ObservableImpl from 'zen-observable';\nimport { ListActionsResponse, ScaffolderTask, Status } from './types';\n\n/**\n * Utility API reference for the {@link ScaffolderApi}.\n *\n * @public\n */\nexport const scaffolderApiRef = createApiRef<ScaffolderApi>({\n id: 'plugin.scaffolder.service',\n});\n\ntype TemplateParameterSchema = {\n title: string;\n steps: Array<{\n title: string;\n schema: JsonObject;\n }>;\n};\n\nexport type LogEvent = {\n type: 'log' | 'completion';\n body: {\n message: string;\n stepId?: string;\n status?: Status;\n };\n createdAt: string;\n id: string;\n taskId: string;\n};\n\nexport type CustomField = {\n name: string;\n component: Field;\n validation: (data: JsonValue, field: FieldValidation) => void;\n};\n\n/**\n * An API to interact with the scaffolder backend.\n *\n * @public\n */\nexport interface ScaffolderApi {\n getTemplateParameterSchema(\n templateName: EntityName,\n ): Promise<TemplateParameterSchema>;\n\n /**\n * Executes the scaffolding of a component, given a template and its\n * parameter values.\n *\n * @param templateName - Name of the Template entity for the scaffolder to use. New project is going to be created out of this template.\n * @param values - Parameters for the template, e.g. name, description\n * @param secrets - Optional secrets to pass to as the secrets parameter to the template.\n */\n scaffold(\n templateName: string,\n values: Record<string, any>,\n secrets?: Record<string, string>,\n ): Promise<string>;\n\n getTask(taskId: string): Promise<ScaffolderTask>;\n\n getIntegrationsList(options: {\n allowedHosts: string[];\n }): Promise<{ type: string; title: string; host: string }[]>;\n\n /**\n * Returns a list of all installed actions.\n */\n listActions(): Promise<ListActionsResponse>;\n\n streamLogs(options: { taskId: string; after?: number }): Observable<LogEvent>;\n}\n\n/**\n * An API to interact with the scaffolder backend.\n *\n * @public\n */\nexport class ScaffolderClient implements ScaffolderApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly scmIntegrationsApi: ScmIntegrationRegistry;\n private readonly fetchApi: FetchApi;\n private readonly useLongPollingLogs: boolean;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n scmIntegrationsApi: ScmIntegrationRegistry;\n useLongPollingLogs?: boolean;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi ?? { fetch };\n this.scmIntegrationsApi = options.scmIntegrationsApi;\n this.useLongPollingLogs = options.useLongPollingLogs ?? false;\n }\n\n async getIntegrationsList(options: { allowedHosts: string[] }) {\n return [\n ...this.scmIntegrationsApi.azure.list(),\n ...this.scmIntegrationsApi.bitbucket.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\n async getTemplateParameterSchema(\n templateName: EntityName,\n ): Promise<TemplateParameterSchema> {\n const { namespace, kind, name } = templateName;\n\n const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');\n const templatePath = [namespace, kind, name]\n .map(s => encodeURIComponent(s))\n .join('/');\n const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;\n\n const response = await this.fetchApi.fetch(url);\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const schema: TemplateParameterSchema = await response.json();\n return schema;\n }\n\n /**\n * Executes the scaffolding of a component, given a template and its\n * parameter values.\n *\n * @param templateName - Template name for the scaffolder to use. New project is going to be created out of this template.\n * @param values - Parameters for the template, e.g. name, description\n * @param secrets - Optional secrets to pass to as the secrets parameter to the template.\n */\n async scaffold(\n templateName: string,\n values: Record<string, any>,\n secrets: Record<string, string> = {},\n ): Promise<string> {\n const url = `${await this.discoveryApi.getBaseUrl('scaffolder')}/v2/tasks`;\n const response = await this.fetchApi.fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n templateName,\n values: { ...values },\n secrets,\n }),\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()) as { id: string };\n return id;\n }\n\n async getTask(taskId: string) {\n const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}`;\n\n const response = await this.fetchApi.fetch(url);\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n streamLogs(options: {\n taskId: string;\n after?: number;\n }): Observable<LogEvent> {\n if (this.useLongPollingLogs) {\n return this.streamLogsPolling(options);\n }\n\n return this.streamLogsEventStream(options);\n }\n\n private streamLogsEventStream({\n taskId,\n after,\n }: {\n taskId: string;\n after?: number;\n }): 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 const eventSource = new EventSource(url, { withCredentials: true });\n eventSource.addEventListener('log', (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 eventSource.addEventListener('completion', (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 eventSource.close();\n subscriber.complete();\n });\n eventSource.addEventListener('error', event => {\n subscriber.error(event);\n });\n },\n error => {\n subscriber.error(error);\n },\n );\n });\n }\n\n private streamLogsPolling({\n taskId,\n after: inputAfter,\n }: {\n taskId: string;\n after?: number;\n }): Observable<LogEvent> {\n let after = inputAfter;\n\n return new ObservableImpl(subscriber => {\n this.discoveryApi.getBaseUrl('scaffolder').then(async baseUrl => {\n while (!subscriber.closed) {\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/events?${qs.stringify({ after })}`;\n const response = await this.fetchApi.fetch(url);\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 async listActions(): Promise<ListActionsResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');\n const response = await this.fetchApi.fetch(`${baseUrl}/v2/actions`);\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n}\n","/*\n * Copyright 2021 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 */\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n catalogApiRef,\n formatEntityRefTitle,\n} from '@backstage/plugin-catalog-react';\nimport { TextField } from '@material-ui/core';\nimport FormControl from '@material-ui/core/FormControl';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { FieldProps, UiSchema } from '@rjsf/core';\nimport React, { useCallback, useEffect } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\n\nexport const allowArbitraryValues = (uiSchema: UiSchema): boolean =>\n (uiSchema['ui:options']?.allowArbitraryValues as boolean) ?? true;\n\nexport const EntityPicker = ({\n onChange,\n schema: { title = 'Entity', description = 'An entity from the catalog' },\n required,\n uiSchema,\n rawErrors,\n formData,\n idSchema,\n}: FieldProps<string>) => {\n const allowedKinds = uiSchema['ui:options']?.allowedKinds as string[];\n const defaultKind = uiSchema['ui:options']?.defaultKind as string | undefined;\n const catalogApi = useApi(catalogApiRef);\n\n const { value: entities, loading } = useAsync(() =>\n catalogApi.getEntities(\n allowedKinds ? { filter: { kind: allowedKinds } } : undefined,\n ),\n );\n\n const entityRefs = entities?.items.map(e =>\n formatEntityRefTitle(e, { defaultKind }),\n );\n\n const onSelect = useCallback(\n (_: any, value: string | null) => {\n onChange(value || '');\n },\n [onChange],\n );\n\n useEffect(() => {\n if (entityRefs?.length === 1) {\n onChange(entityRefs[0]);\n }\n }, [entityRefs, onChange]);\n\n return (\n <FormControl\n margin=\"normal\"\n required={required}\n error={rawErrors?.length > 0 && !formData}\n >\n <Autocomplete\n disabled={entityRefs?.length === 1}\n id={idSchema?.$id}\n value={(formData as string) || ''}\n loading={loading}\n onChange={onSelect}\n options={entityRefs || []}\n autoSelect\n freeSolo={allowArbitraryValues(uiSchema)}\n renderInput={params => (\n <TextField\n {...params}\n label={title}\n margin=\"normal\"\n helperText={description}\n variant=\"outlined\"\n required={required}\n InputProps={params.InputProps}\n />\n )}\n />\n </FormControl>\n );\n};\n","/*\n * Copyright 2021 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 */\nimport { TextField } from '@material-ui/core';\nimport { FieldProps } from '@rjsf/core';\nimport React from 'react';\n\nexport const TextValuePicker = ({\n onChange,\n required,\n schema: { title, description },\n rawErrors,\n formData,\n uiSchema: { 'ui:autofocus': autoFocus },\n idSchema,\n placeholder,\n}: FieldProps<string>) => (\n <TextField\n id={idSchema?.$id}\n label={title}\n placeholder={placeholder}\n helperText={description}\n required={required}\n value={formData ?? ''}\n onChange={({ target: { value } }) => onChange(value)}\n margin=\"normal\"\n error={rawErrors?.length > 0 && !formData}\n inputProps={{ autoFocus }}\n />\n);\n","/*\n * Copyright 2021 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 */\nimport React from 'react';\nimport { FieldProps } from '@rjsf/core';\nimport { TextValuePicker } from '../TextValuePicker';\n\nexport const EntityNamePicker = ({\n schema: { title = 'Name', description = 'Unique name of the component' },\n ...props\n}: FieldProps<string>) => (\n <TextValuePicker schema={{ title, description }} {...props} />\n);\n","/*\n * Copyright 2021 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 { FieldValidation } from '@rjsf/core';\nimport { KubernetesValidatorFunctions } from '@backstage/catalog-model';\n\nexport const entityNamePickerValidation = (\n value: string,\n validation: FieldValidation,\n) => {\n if (!KubernetesValidatorFunctions.isValidObjectName(value)) {\n validation.addError(\n 'must start and end with an alphanumeric character, and contain only alphanumeric characters, hyphens, underscores, and periods. Maximum length is 63 characters.',\n );\n }\n};\n","/*\n * Copyright 2021 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 */\nimport React, { useState } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport useEffectOnce from 'react-use/lib/useEffectOnce';\nimport { CatalogEntitiesRequest } from '@backstage/catalog-client';\nimport { Entity, makeValidator } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { FormControl, TextField } from '@material-ui/core';\nimport { Autocomplete } from '@material-ui/lab';\nimport { FieldProps } from '@rjsf/core';\n\n/**\n * EntityTagsPicker\n * @public\n */\nexport const EntityTagsPicker = ({\n formData,\n onChange,\n uiSchema,\n}: FieldProps<string[]>) => {\n const catalogApi = useApi(catalogApiRef);\n const [inputValue, setInputValue] = useState('');\n const [inputError, setInputError] = useState(false);\n const tagValidator = makeValidator().isValidTag;\n const kinds = uiSchema['ui:options']?.kinds as string[];\n\n const { loading, value: existingTags } = useAsync(async () => {\n const tagsRequest: CatalogEntitiesRequest = { fields: ['metadata.tags'] };\n if (kinds) {\n tagsRequest.filter = { kind: kinds };\n }\n\n const entities = await catalogApi.getEntities(tagsRequest);\n\n return [\n ...new Set(\n entities.items\n .flatMap((e: Entity) => e.metadata?.tags)\n .filter(Boolean) as string[],\n ),\n ].sort();\n });\n\n const setTags = (_: React.ChangeEvent<{}>, values: string[] | null) => {\n // Reset error state in case all tags were removed\n let hasError = false;\n let addDuplicate = false;\n const currentTags = formData || [];\n\n // If adding a new tag\n if (values?.length && currentTags.length < values.length) {\n const newTag = (values[values.length - 1] = values[values.length - 1]\n .toLocaleLowerCase('en-US')\n .trim());\n hasError = !tagValidator(newTag);\n addDuplicate = currentTags.indexOf(newTag) !== -1;\n }\n\n setInputError(hasError);\n setInputValue(!hasError ? '' : inputValue);\n if (!hasError && !addDuplicate) {\n onChange(values || []);\n }\n };\n\n // Initialize field to always return an array\n useEffectOnce(() => onChange(formData || []));\n\n return (\n <FormControl margin=\"normal\">\n <Autocomplete\n multiple\n freeSolo\n filterSelectedOptions\n onChange={setTags}\n value={formData || []}\n inputValue={inputValue}\n loading={loading}\n options={existingTags || []}\n ChipProps={{ size: 'small' }}\n renderInput={params => (\n <TextField\n {...params}\n label=\"Tags\"\n onChange={e => setInputValue(e.target.value)}\n error={inputError}\n helperText=\"Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters\"\n />\n )}\n />\n </FormControl>\n );\n};\n","/*\n * Copyright 2021 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 */\nimport { FieldProps } from '@rjsf/core';\nimport React from 'react';\nimport { EntityPicker } from '../EntityPicker';\n\nexport const OwnerPicker = ({\n schema: { title = 'Owner', description = 'The owner of the component' },\n uiSchema,\n ...props\n}: FieldProps<string>) => {\n const ownerUiSchema = {\n ...uiSchema,\n 'ui:options': {\n allowedKinds: (uiSchema['ui:options']?.allowedKinds || [\n 'Group',\n 'User',\n ]) as string[],\n defaultKind: 'Group',\n },\n };\n\n return (\n <EntityPicker\n {...props}\n schema={{ title, description }}\n uiSchema={ownerUiSchema}\n />\n );\n};\n","/*\n * Copyright 2021 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 */\nimport React from 'react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Input from '@material-ui/core/Input';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { Select, SelectItem } from '@backstage/core-components';\nimport { RepoUrlPickerState } from './types';\n\nexport const GithubRepoPicker = (props: {\n allowedOwners?: string[];\n rawErrors: string[];\n state: RepoUrlPickerState;\n onChange: (state: RepoUrlPickerState) => void;\n}) => {\n const { allowedOwners = [], rawErrors, state, onChange } = props;\n const ownerItems: SelectItem[] = allowedOwners\n ? allowedOwners.map(i => ({ label: i, value: i }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n const { owner, repoName } = state;\n\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n {allowedOwners?.length ? (\n <Select\n native\n label=\"Owner Available\"\n onChange={s =>\n onChange({ owner: String(Array.isArray(s) ? s[0] : s) })\n }\n disabled={allowedOwners.length === 1}\n selected={owner}\n items={ownerItems}\n />\n ) : (\n <>\n <InputLabel htmlFor=\"ownerInput\">Owner</InputLabel>\n <Input\n id=\"ownerInput\"\n onChange={e => onChange({ owner: e.target.value })}\n value={owner}\n />\n </>\n )}\n <FormHelperText>\n The organization, user or project that this repo will belong to\n </FormHelperText>\n </FormControl>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !repoName}\n >\n <InputLabel htmlFor=\"repoNameInput\">Repository</InputLabel>\n <Input\n id=\"repoNameInput\"\n onChange={e => onChange({ repoName: e.target.value })}\n value={repoName}\n />\n <FormHelperText>The name of the repository</FormHelperText>\n </FormControl>\n </>\n );\n};\n","/*\n * Copyright 2021 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 */\nimport React from 'react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Input from '@material-ui/core/Input';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { Select, SelectItem } from '@backstage/core-components';\nimport { RepoUrlPickerState } from './types';\n\nexport const GitlabRepoPicker = (props: {\n allowedOwners?: string[];\n state: RepoUrlPickerState;\n onChange: (state: RepoUrlPickerState) => void;\n rawErrors: string[];\n}) => {\n const { allowedOwners = [], rawErrors, state, onChange } = props;\n const ownerItems: SelectItem[] = allowedOwners\n ? allowedOwners.map(i => ({ label: i, value: i }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n const { owner, repoName } = state;\n\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n {allowedOwners?.length ? (\n <Select\n native\n label=\"Owner Available\"\n onChange={selected =>\n onChange({\n owner: String(Array.isArray(selected) ? selected[0] : selected),\n })\n }\n disabled={allowedOwners.length === 1}\n selected={owner}\n items={ownerItems}\n />\n ) : (\n <>\n <InputLabel htmlFor=\"ownerInput\">Owner</InputLabel>\n <Input\n id=\"ownerInput\"\n onChange={e => onChange({ owner: e.target.value })}\n value={owner}\n />\n </>\n )}\n <FormHelperText>\n The organization, user or project that this repo will belong to\n </FormHelperText>\n </FormControl>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !repoName}\n >\n <InputLabel htmlFor=\"repoNameInput\">Repository</InputLabel>\n <Input\n id=\"repoNameInput\"\n onChange={e => onChange({ repoName: e.target.value })}\n value={repoName}\n />\n <FormHelperText>The name of the repository</FormHelperText>\n </FormControl>\n </>\n );\n};\n","/*\n * Copyright 2022 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 React from 'react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Input from '@material-ui/core/Input';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { RepoUrlPickerState } from './types';\n\nexport const AzureRepoPicker = (props: {\n state: RepoUrlPickerState;\n onChange: (state: RepoUrlPickerState) => void;\n rawErrors: string[];\n}) => {\n const { rawErrors, state, onChange } = props;\n const { organization, repoName, owner } = state;\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !organization}\n >\n <InputLabel htmlFor=\"orgInput\">Organization</InputLabel>\n <Input\n id=\"orgInput\"\n onChange={e => onChange({ organization: e.target.value })}\n value={organization}\n />\n <FormHelperText>\n The organization that this repo will belong to\n </FormHelperText>\n </FormControl>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n <InputLabel htmlFor=\"ownerInput\">Owner</InputLabel>\n <Input\n id=\"ownerInput\"\n onChange={e => onChange({ owner: e.target.value })}\n value={owner}\n />\n <FormHelperText>The Owner that this repo will belong to</FormHelperText>\n </FormControl>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !repoName}\n >\n <InputLabel htmlFor=\"repoNameInput\">Repository</InputLabel>\n <Input\n id=\"repoNameInput\"\n onChange={e => onChange({ repoName: e.target.value })}\n value={repoName}\n />\n <FormHelperText>The name of the repository</FormHelperText>\n </FormControl>\n </>\n );\n};\n","/*\n * Copyright 2021 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 */\nimport React from 'react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Input from '@material-ui/core/Input';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { RepoUrlPickerState } from './types';\n\nexport const BitbucketRepoPicker = (props: {\n onChange: (state: RepoUrlPickerState) => void;\n state: RepoUrlPickerState;\n rawErrors: string[];\n}) => {\n const { onChange, rawErrors, state } = props;\n const { host, workspace, project, repoName } = state;\n return (\n <>\n {host === 'bitbucket.org' && (\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !workspace}\n >\n <InputLabel htmlFor=\"workspaceInput\">Workspace</InputLabel>\n <Input\n id=\"workspaceInput\"\n onChange={e => onChange({ workspace: e.target.value })}\n value={workspace}\n />\n <FormHelperText>\n The Organization that this repo will belong to\n </FormHelperText>\n </FormControl>\n )}\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !project}\n >\n <InputLabel htmlFor=\"projectInput\">Project</InputLabel>\n <Input\n id=\"projectInput\"\n onChange={e => onChange({ project: e.target.value })}\n value={project}\n />\n <FormHelperText>\n The Project that this repo will belong to\n </FormHelperText>\n </FormControl>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !repoName}\n >\n <InputLabel htmlFor=\"repoNameInput\">Repository</InputLabel>\n <Input\n id=\"repoNameInput\"\n onChange={e => onChange({ repoName: e.target.value })}\n value={repoName}\n />\n <FormHelperText>The name of the repository</FormHelperText>\n </FormControl>\n </>\n );\n};\n","/*\n * Copyright 2021 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 */\nimport React, { useEffect } from 'react';\nimport { Progress, Select, SelectItem } from '@backstage/core-components';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { scaffolderApiRef } from '../../../api';\nimport useAsync from 'react-use/lib/useAsync';\n\nexport const RepoUrlPickerHost = (props: {\n host?: string;\n hosts?: string[];\n onChange: (host: string) => void;\n rawErrors: string[];\n}) => {\n const { host, hosts, onChange, rawErrors } = props;\n const scaffolderApi = useApi(scaffolderApiRef);\n\n const { value: integrations, loading } = useAsync(async () => {\n return await scaffolderApi.getIntegrationsList({\n allowedHosts: hosts ?? [],\n });\n });\n\n useEffect(() => {\n if (hosts && !host) {\n // This is only hear to set the default as the first one in the hosts array\n // if the host is not set yet and there is a list of hosts.\n onChange(hosts[0]);\n }\n }, [hosts, host, onChange]);\n\n const hostsOptions: SelectItem[] = integrations\n ? integrations\n .filter(i => hosts?.includes(i.host))\n .map(i => ({ label: i.title, value: i.host }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n if (loading) {\n return <Progress />;\n }\n\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !host}\n >\n <Select\n native\n disabled={hosts?.length === 1 ?? false}\n label=\"Host\"\n onChange={s => onChange(String(Array.isArray(s) ? s[0] : s))}\n selected={host}\n items={hostsOptions}\n data-testid=\"host-select\"\n />\n\n <FormHelperText>\n The host where the repository will be created\n </FormHelperText>\n </FormControl>\n </>\n );\n};\n","/*\n * Copyright 2021 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 { RepoUrlPickerState } from './types';\n\nexport function serializeRepoPickerUrl(data: RepoUrlPickerState) {\n if (!data.host) {\n return undefined;\n }\n\n const params = new URLSearchParams();\n if (data.owner) {\n params.set('owner', data.owner);\n }\n if (data.repoName) {\n params.set('repo', data.repoName);\n }\n if (data.organization) {\n params.set('organization', data.organization);\n }\n if (data.workspace) {\n params.set('workspace', data.workspace);\n }\n if (data.project) {\n params.set('project', data.project);\n }\n\n return `${data.host}?${params.toString()}`;\n}\n\nexport function parseRepoPickerUrl(\n url: string | undefined,\n): RepoUrlPickerState {\n let host = undefined;\n let owner = undefined;\n let repoName = undefined;\n let organization = undefined;\n let workspace = undefined;\n let project = undefined;\n\n try {\n if (url) {\n const parsed = new URL(`https://${url}`);\n host = parsed.host;\n owner = parsed.searchParams.get('owner') || undefined;\n repoName = parsed.searchParams.get('repo') || undefined;\n organization = parsed.searchParams.get('organization') || undefined;\n workspace = parsed.searchParams.get('workspace') || undefined;\n project = parsed.searchParams.get('project') || undefined;\n }\n } catch {\n /* ok */\n }\n\n return { host, owner, repoName, organization, workspace, project };\n}\n","/*\n * Copyright 2021 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 */\nimport { useApi } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\nimport React, { useEffect, useState, useMemo, useCallback } from 'react';\nimport { GithubRepoPicker } from './GithubRepoPicker';\nimport { GitlabRepoPicker } from './GitlabRepoPicker';\nimport { AzureRepoPicker } from './AzureRepoPicker';\nimport { BitbucketRepoPicker } from './BitbucketRepoPicker';\nimport { FieldExtensionComponentProps } from '../../../extensions';\nimport { RepoUrlPickerHost } from './RepoUrlPickerHost';\nimport { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils';\nimport { RepoUrlPickerState } from './types';\n\nexport interface RepoUrlPickerUiOptions {\n allowedHosts?: string[];\n allowedOwners?: string[];\n}\n\nexport const RepoUrlPicker = (\n props: FieldExtensionComponentProps<string, RepoUrlPickerUiOptions>,\n) => {\n const { uiSchema, onChange, rawErrors, formData } = props;\n const [state, setState] = useState<RepoUrlPickerState>(\n parseRepoPickerUrl(formData),\n );\n const integrationApi = useApi(scmIntegrationsApiRef);\n\n const allowedHosts = useMemo(\n () => uiSchema?.['ui:options']?.allowedHosts ?? [],\n [uiSchema],\n );\n const allowedOwners = useMemo(\n () => uiSchema?.['ui:options']?.allowedOwners ?? [],\n [uiSchema],\n );\n\n useEffect(() => {\n onChange(serializeRepoPickerUrl(state));\n }, [state, onChange]);\n\n /* we deal with calling the repo setting here instead of in each components for ease */\n useEffect(() => {\n if (allowedOwners.length === 1) {\n setState(prevState => ({ ...prevState, owner: allowedOwners[0] }));\n }\n }, [setState, allowedOwners]);\n\n const updateLocalState = useCallback(\n (newState: RepoUrlPickerState) => {\n setState(prevState => ({ ...prevState, ...newState }));\n },\n [setState],\n );\n\n const hostType =\n (state.host && integrationApi.byHost(state.host)?.type) ?? null;\n\n return (\n <>\n <RepoUrlPickerHost\n host={state.host}\n hosts={allowedHosts}\n onChange={host => setState(prevState => ({ ...prevState, host }))}\n rawErrors={rawErrors}\n />\n {hostType === 'github' && (\n <GithubRepoPicker\n allowedOwners={allowedOwners}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'gitlab' && (\n <GitlabRepoPicker\n allowedOwners={allowedOwners}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'bitbucket' && (\n <BitbucketRepoPicker\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'azure' && (\n <AzureRepoPicker\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n </>\n );\n};\n","/*\n * Copyright 2021 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 { FieldValidation } from '@rjsf/core';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\n\nexport const repoPickerValidation = (\n value: string,\n validation: FieldValidation,\n context: { apiHolder: ApiHolder },\n) => {\n try {\n const { host, searchParams } = new URL(`https://${value}`);\n\n const integrationApi = context.apiHolder.get(scmIntegrationsApiRef);\n\n if (!host) {\n validation.addError(\n 'Incomplete repository location provided, host not provided',\n );\n } else {\n if (integrationApi?.byHost(host)?.type === 'bitbucket') {\n // workspace is only applicable for bitbucket cloud\n if (host === 'bitbucket.org' && !searchParams.get('workspace')) {\n validation.addError(\n 'Incomplete repository location provided, workspace not provided',\n );\n }\n\n if (!searchParams.get('project')) {\n validation.addError(\n 'Incomplete repository location provided, project not provided',\n );\n }\n }\n // For anything other than bitbucket\n else {\n if (!searchParams.get('owner')) {\n validation.addError(\n 'Incomplete repository location provided, owner not provided',\n );\n }\n }\n\n // Do this for all hosts\n if (!searchParams.get('repo')) {\n validation.addError(\n 'Incomplete repository location provided, repo not provided',\n );\n }\n }\n } catch {\n validation.addError('Unable to parse the Repository URL');\n }\n};\n","/*\n * Copyright 2021 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 */\nimport {\n formatEntityRefTitle,\n useOwnedEntities,\n} from '@backstage/plugin-catalog-react';\nimport { TextField } from '@material-ui/core';\nimport FormControl from '@material-ui/core/FormControl';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { FieldProps } from '@rjsf/core';\nimport React from 'react';\n\nexport const OwnedEntityPicker = ({\n onChange,\n schema: { title = 'Entity', description = 'An entity from the catalog' },\n required,\n uiSchema,\n rawErrors,\n formData,\n idSchema,\n}: FieldProps<string>) => {\n const allowedKinds = uiSchema['ui:options']?.allowedKinds as string[];\n const defaultKind = uiSchema['ui:options']?.defaultKind as string | undefined;\n const { ownedEntities, loading } = useOwnedEntities(allowedKinds);\n\n const entityRefs = ownedEntities?.items\n .map(e => formatEntityRefTitle(e, { defaultKind }))\n .filter(n => n);\n\n const onSelect = (_: any, value: string | null) => {\n onChange(value || '');\n };\n\n return (\n <FormControl\n margin=\"normal\"\n required={required}\n error={rawErrors?.length > 0 && !formData}\n >\n <Autocomplete\n id={idSchema?.$id}\n value={(formData as string) || ''}\n loading={loading}\n onChange={onSelect}\n options={entityRefs || []}\n autoSelect\n freeSolo\n renderInput={params => (\n <TextField\n {...params}\n label={title}\n margin=\"normal\"\n helperText={description}\n variant=\"outlined\"\n required={required}\n InputProps={params.InputProps}\n />\n )}\n />\n </FormControl>\n );\n};\n","/*\n * Copyright 2021 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 React from 'react';\nimport {\n CustomFieldValidator,\n FieldExtensionOptions,\n FieldExtensionComponentProps,\n} from './types';\nimport { Extension, attachComponentData } from '@backstage/core-plugin-api';\n\nexport const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1';\nexport const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1';\n\nexport function createScaffolderFieldExtension<T = any>(\n options: FieldExtensionOptions<T>,\n): Extension<() => null> {\n return {\n expose() {\n const FieldExtensionDataHolder: any = () => null;\n\n attachComponentData(\n FieldExtensionDataHolder,\n FIELD_EXTENSION_KEY,\n options,\n );\n\n return FieldExtensionDataHolder;\n },\n };\n}\n\nexport const ScaffolderFieldExtensions: React.ComponentType = () => null;\nattachComponentData(\n ScaffolderFieldExtensions,\n FIELD_EXTENSION_WRAPPER_KEY,\n true,\n);\n\nexport type {\n CustomFieldValidator,\n FieldExtensionOptions,\n FieldExtensionComponentProps,\n};\n\nexport { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default';\n","/*\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 */\nimport {\n createExternalRouteRef,\n createRouteRef,\n} from '@backstage/core-plugin-api';\n\nexport const registerComponentRouteRef = createExternalRouteRef({\n id: 'register-component',\n optional: true,\n});\n\nexport const rootRouteRef = createRouteRef({\n id: 'scaffolder',\n});\n","/*\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 { scmIntegrationsApiRef } from '@backstage/integration-react';\nimport { scaffolderApiRef, ScaffolderClient } from './api';\nimport { EntityPicker } from './components/fields/EntityPicker';\nimport {\n entityNamePickerValidation,\n EntityNamePicker,\n} from './components/fields/EntityNamePicker';\nimport { OwnerPicker } from './components/fields/OwnerPicker';\nimport {\n repoPickerValidation,\n RepoUrlPicker,\n} from './components/fields/RepoUrlPicker';\nimport { createScaffolderFieldExtension } from './extensions';\nimport { registerComponentRouteRef, rootRouteRef } from './routes';\nimport {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport { OwnedEntityPicker } from './components/fields/OwnedEntityPicker';\nimport { EntityTagsPicker } from './components/fields/EntityTagsPicker';\n\nexport const scaffolderPlugin = createPlugin({\n id: 'scaffolder',\n apis: [\n createApiFactory({\n api: scaffolderApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n scmIntegrationsApi: scmIntegrationsApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, scmIntegrationsApi, fetchApi }) =>\n new ScaffolderClient({\n discoveryApi,\n scmIntegrationsApi,\n fetchApi,\n }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n externalRoutes: {\n registerComponent: registerComponentRouteRef,\n },\n});\n\nexport const EntityPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: EntityPicker,\n name: 'EntityPicker',\n }),\n);\n\nexport const EntityNamePickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: EntityNamePicker,\n name: 'EntityNamePicker',\n validation: entityNamePickerValidation,\n }),\n);\n\nexport const RepoUrlPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: RepoUrlPicker,\n name: 'RepoUrlPicker',\n validation: repoPickerValidation,\n }),\n);\n\nexport const OwnerPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: OwnerPicker,\n name: 'OwnerPicker',\n }),\n);\n\nexport const ScaffolderPage = scaffolderPlugin.provide(\n createRoutableExtension({\n name: 'ScaffolderPage',\n component: () => import('./components/Router').then(m => m.Router),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: OwnedEntityPicker,\n name: 'OwnedEntityPicker',\n }),\n);\n\n/**\n * EntityTagsPickerFieldExtension\n * @public\n */\nexport const EntityTagsPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: EntityTagsPicker,\n name: 'EntityTagsPicker',\n }),\n);\n","/*\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 { Entity } from '@backstage/catalog-model';\nimport { useStarredEntity } from '@backstage/plugin-catalog-react';\nimport { IconButton, makeStyles, Tooltip, withStyles } from '@material-ui/core';\nimport Star from '@material-ui/icons/Star';\nimport StarBorder from '@material-ui/icons/StarBorder';\nimport React, { ComponentProps } from 'react';\n\ntype Props = ComponentProps<typeof IconButton> & { entity: Entity };\n\nconst YellowStar = withStyles({\n root: {\n color: '#f3ba37',\n },\n})(Star);\n\nconst WhiteBorderStar = withStyles({\n root: {\n color: '#ffffff',\n },\n})(StarBorder);\n\nconst useStyles = makeStyles(theme => ({\n starButton: {\n position: 'absolute',\n top: theme.spacing(0.5),\n right: theme.spacing(0.5),\n padding: '0.25rem',\n },\n}));\n\nexport const favouriteTemplateTooltip = (isStarred: boolean) =>\n isStarred ? 'Remove from favorites' : 'Add to favorites';\n\nexport const favouriteTemplateIcon = (isStarred: boolean) =>\n isStarred ? <YellowStar /> : <WhiteBorderStar />;\n\n/**\n * IconButton for showing if a current entity is starred and adding/removing it from the favourite entities\n * @param props - MaterialUI IconButton props extended by required `entity` prop\n */\nexport const FavouriteTemplate = (props: Props) => {\n const classes = useStyles();\n const { toggleStarredEntity, isStarredEntity } = useStarredEntity(\n props.entity,\n );\n return (\n <IconButton\n color=\"inherit\"\n className={classes.starButton}\n {...props}\n onClick={() => toggleStarredEntity()}\n >\n <Tooltip title={favouriteTemplateTooltip(isStarredEntity)}>\n {favouriteTemplateIcon(isStarredEntity)}\n </Tooltip>\n </IconButton>\n );\n};\n","/*\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 */\nimport {\n Entity,\n RELATION_OWNED_BY,\n TemplateEntityV1beta2,\n} from '@backstage/catalog-model';\nimport {\n ScmIntegrationIcon,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport {\n EntityRefLinks,\n getEntityRelations,\n getEntitySourceLocation,\n} from '@backstage/plugin-catalog-react';\nimport { BackstageTheme } from '@backstage/theme';\nimport {\n Box,\n Card,\n CardActions,\n CardContent,\n CardMedia,\n Chip,\n IconButton,\n Link,\n makeStyles,\n Tooltip,\n Typography,\n useTheme,\n} from '@material-ui/core';\nimport WarningIcon from '@material-ui/icons/Warning';\nimport React from 'react';\nimport { generatePath } from 'react-router';\nimport { rootRouteRef } from '../../routes';\nimport { FavouriteTemplate } from '../FavouriteTemplate/FavouriteTemplate';\n\nimport { Button, ItemCardHeader } from '@backstage/core-components';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\n\nconst useStyles = makeStyles(theme => ({\n cardHeader: {\n position: 'relative',\n },\n title: {\n backgroundImage: ({ backgroundImage }: any) => backgroundImage,\n },\n box: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n '-webkit-line-clamp': 10,\n '-webkit-box-orient': 'vertical',\n paddingBottom: '0.8em',\n },\n label: {\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n fontSize: '0.65rem',\n fontWeight: 'bold',\n letterSpacing: 0.5,\n lineHeight: 1,\n paddingBottom: '0.2rem',\n },\n leftButton: {\n marginRight: 'auto',\n },\n}));\n\nconst useDeprecationStyles = makeStyles(theme => ({\n deprecationIcon: {\n position: 'absolute',\n top: theme.spacing(0.5),\n right: theme.spacing(3.5),\n padding: '0.25rem',\n },\n link: {\n color: theme.palette.warning.light,\n },\n}));\n\nexport type TemplateCardProps = {\n template: TemplateEntityV1beta2;\n deprecated?: boolean;\n};\n\ntype TemplateProps = {\n description: string;\n tags: string[];\n title: string;\n type: string;\n name: string;\n};\n\nconst getTemplateCardProps = (\n template: TemplateEntityV1beta2,\n): TemplateProps & { key: string } => {\n return {\n key: template.metadata.uid!,\n name: template.metadata.name,\n title: `${(template.metadata.title || template.metadata.name) ?? ''}`,\n type: template.spec.type ?? '',\n description: template.metadata.description ?? '-',\n tags: (template.metadata?.tags as string[]) ?? [],\n };\n};\n\nconst DeprecationWarning = () => {\n const styles = useDeprecationStyles();\n\n const Title = (\n <Typography style={{ padding: 10, maxWidth: 300 }}>\n This template syntax is deprecated. Click for more info.\n </Typography>\n );\n\n return (\n <div className={styles.deprecationIcon}>\n <Tooltip title={Title}>\n <Link\n href=\"https://backstage.io/docs/features/software-templates/migrating-from-v1alpha1-to-v1beta2\"\n className={styles.link}\n >\n <WarningIcon />\n </Link>\n </Tooltip>\n </div>\n );\n};\n\nexport const TemplateCard = ({ template, deprecated }: TemplateCardProps) => {\n const backstageTheme = useTheme<BackstageTheme>();\n const rootLink = useRouteRef(rootRouteRef);\n const templateProps = getTemplateCardProps(template);\n const ownedByRelations = getEntityRelations(\n template as Entity,\n RELATION_OWNED_BY,\n );\n const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type })\n ? templateProps.type\n : 'other';\n const theme = backstageTheme.getPageTheme({ themeId });\n const classes = useStyles({ backgroundImage: theme.backgroundImage });\n const href = generatePath(`${rootLink()}/templates/:templateName`, {\n templateName: templateProps.name,\n });\n\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n const sourceLocation = getEntitySourceLocation(template, scmIntegrationsApi);\n\n return (\n <Card>\n <CardMedia className={classes.cardHeader}>\n <FavouriteTemplate entity={template} />\n {deprecated && <DeprecationWarning />}\n <ItemCardHeader\n title={templateProps.title}\n subtitle={templateProps.type}\n classes={{ root: classes.title }}\n />\n </CardMedia>\n <CardContent style={{ display: 'grid' }}>\n <Box className={classes.box}>\n <Typography variant=\"body2\" className={classes.label}>\n Description\n </Typography>\n {templateProps.description}\n </Box>\n <Box className={classes.box}>\n <Typography variant=\"body2\" className={classes.label}>\n Owner\n </Typography>\n <EntityRefLinks entityRefs={ownedByRelations} defaultKind=\"Group\" />\n </Box>\n <Box>\n <Typography variant=\"body2\" className={classes.label}>\n Tags\n </Typography>\n {templateProps.tags?.map(tag => (\n <Chip size=\"small\" label={tag} key={tag} />\n ))}\n </Box>\n </CardContent>\n <CardActions>\n {sourceLocation && (\n <IconButton\n className={classes.leftButton}\n href={sourceLocation.locationTargetUrl}\n >\n <ScmIntegrationIcon type={sourceLocation.integrationType} />\n </IconButton>\n )}\n <Button\n color=\"primary\"\n to={href}\n aria-label={`Choose ${templateProps.title}`}\n >\n Choose\n </Button>\n </CardActions>\n </Card>\n );\n};\n","/*\n * Copyright 2021 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 React, { ComponentType } from 'react';\nimport {\n Entity,\n stringifyEntityRef,\n TemplateEntityV1beta2,\n} from '@backstage/catalog-model';\nimport {\n Content,\n ContentHeader,\n ItemCardGrid,\n Link,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport { useEntityListProvider } from '@backstage/plugin-catalog-react';\nimport { Typography } from '@material-ui/core';\nimport { TemplateCard } from '../TemplateCard';\n\nexport type TemplateListProps = {\n TemplateCardComponent?:\n | ComponentType<{ template: TemplateEntityV1beta2 }>\n | undefined;\n group?: {\n title?: string;\n titleComponent?: React.ReactNode;\n filter: (entity: Entity) => boolean;\n };\n};\n\nexport const TemplateList = ({\n TemplateCardComponent,\n group,\n}: TemplateListProps) => {\n const { loading, error, entities } = useEntityListProvider();\n const Card = TemplateCardComponent || TemplateCard;\n const maybeFilteredEntities = group\n ? entities.filter(e => group.filter(e))\n : entities;\n const title = group ? (\n group.titleComponent || <ContentHeader title={group.title} />\n ) : (\n <ContentHeader title=\"Other Templates\" />\n );\n\n if (group && maybeFilteredEntities.length === 0) {\n return null;\n }\n return (\n <>\n {loading && <Progress />}\n\n {error && (\n <WarningPanel title=\"Oops! Something went wrong loading the templates\">\n {error.message}\n </WarningPanel>\n )}\n\n {!error && !loading && !entities.length && (\n <Typography variant=\"body2\">\n No templates found that match your filter. Learn more about{' '}\n <Link to=\"https://backstage.io/docs/features/software-templates/adding-templates\">\n adding templates\n </Link>\n .\n </Typography>\n )}\n\n <Content>\n {title}\n <ItemCardGrid>\n {maybeFilteredEntities &&\n maybeFilteredEntities?.length > 0 &&\n maybeFilteredEntities.map((template: Entity) => (\n <Card\n key={stringifyEntityRef(template)}\n template={template as TemplateEntityV1beta2}\n />\n ))}\n </ItemCardGrid>\n </Content>\n </>\n );\n};\n","/*\n * Copyright 2021 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 React from 'react';\nimport capitalize from 'lodash/capitalize';\nimport { Progress } from '@backstage/core-components';\nimport {\n Box,\n Checkbox,\n FormControlLabel,\n TextField,\n Typography,\n} from '@material-ui/core';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { Autocomplete } from '@material-ui/lab';\nimport { useEntityTypeFilter } from '@backstage/plugin-catalog-react';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nexport const TemplateTypePicker = () => {\n const alertApi = useApi(alertApiRef);\n const { error, loading, availableTypes, selectedTypes, setSelectedTypes } =\n useEntityTypeFilter();\n\n if (loading) return <Progress />;\n\n if (!availableTypes) return null;\n\n if (error) {\n alertApi.post({\n message: `Failed to load entity types`,\n severity: 'error',\n });\n return null;\n }\n\n return (\n <Box pb={1} pt={1}>\n <Typography variant=\"button\">Categories</Typography>\n <Autocomplete\n multiple\n aria-label=\"Categories\"\n options={availableTypes}\n value={selectedTypes}\n onChange={(_: object, value: string[]) => setSelectedTypes(value)}\n renderOption={(option, { selected }) => (\n <FormControlLabel\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={selected}\n />\n }\n label={capitalize(option)}\n />\n )}\n size=\"small\"\n popupIcon={<ExpandMoreIcon data-testid=\"categories-picker-expand\" />}\n renderInput={params => <TextField {...params} variant=\"outlined\" />}\n />\n </Box>\n );\n};\n"],"names":["FormControl","Autocomplete","useStyles","Link"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
3
- import { DiscoveryApi, IdentityApi, ApiHolder, Extension } from '@backstage/core-plugin-api';
3
+ import { DiscoveryApi, FetchApi, ApiHolder, Extension } from '@backstage/core-plugin-api';
4
4
  import * as _backstage_catalog_model from '@backstage/catalog-model';
5
5
  import { JSONSchema, EntityName, Entity, TemplateEntityV1beta2 } from '@backstage/catalog-model';
6
6
  import { ScmIntegrationRegistry } from '@backstage/integration';
@@ -28,6 +28,11 @@ declare type ListActionsResponse = Array<{
28
28
  };
29
29
  }>;
30
30
 
31
+ /**
32
+ * Utility API reference for the {@link ScaffolderApi}.
33
+ *
34
+ * @public
35
+ */
31
36
  declare const scaffolderApiRef: _backstage_core_plugin_api.ApiRef<ScaffolderApi>;
32
37
  declare type TemplateParameterSchema = {
33
38
  title: string;
@@ -47,16 +52,22 @@ declare type LogEvent = {
47
52
  id: string;
48
53
  taskId: string;
49
54
  };
55
+ /**
56
+ * An API to interact with the scaffolder backend.
57
+ *
58
+ * @public
59
+ */
50
60
  interface ScaffolderApi {
51
61
  getTemplateParameterSchema(templateName: EntityName): Promise<TemplateParameterSchema>;
52
62
  /**
53
63
  * Executes the scaffolding of a component, given a template and its
54
64
  * parameter values.
55
65
  *
56
- * @param templateName Name of the Template entity for the scaffolder to use. New project is going to be created out of this template.
57
- * @param values Parameters for the template, e.g. name, description
66
+ * @param templateName - Name of the Template entity for the scaffolder to use. New project is going to be created out of this template.
67
+ * @param values - Parameters for the template, e.g. name, description
68
+ * @param secrets - Optional secrets to pass to as the secrets parameter to the template.
58
69
  */
59
- scaffold(templateName: string, values: Record<string, any>): Promise<string>;
70
+ scaffold(templateName: string, values: Record<string, any>, secrets?: Record<string, string>): Promise<string>;
60
71
  getTask(taskId: string): Promise<ScaffolderTask>;
61
72
  getIntegrationsList(options: {
62
73
  allowedHosts: string[];
@@ -65,20 +76,28 @@ interface ScaffolderApi {
65
76
  title: string;
66
77
  host: string;
67
78
  }[]>;
79
+ /**
80
+ * Returns a list of all installed actions.
81
+ */
68
82
  listActions(): Promise<ListActionsResponse>;
69
- streamLogs({ taskId, after, }: {
83
+ streamLogs(options: {
70
84
  taskId: string;
71
85
  after?: number;
72
86
  }): Observable<LogEvent>;
73
87
  }
88
+ /**
89
+ * An API to interact with the scaffolder backend.
90
+ *
91
+ * @public
92
+ */
74
93
  declare class ScaffolderClient implements ScaffolderApi {
75
94
  private readonly discoveryApi;
76
- private readonly identityApi;
77
95
  private readonly scmIntegrationsApi;
96
+ private readonly fetchApi;
78
97
  private readonly useLongPollingLogs;
79
98
  constructor(options: {
80
99
  discoveryApi: DiscoveryApi;
81
- identityApi: IdentityApi;
100
+ fetchApi: FetchApi;
82
101
  scmIntegrationsApi: ScmIntegrationRegistry;
83
102
  useLongPollingLogs?: boolean;
84
103
  });
@@ -94,31 +113,51 @@ declare class ScaffolderClient implements ScaffolderApi {
94
113
  * Executes the scaffolding of a component, given a template and its
95
114
  * parameter values.
96
115
  *
97
- * @param templateName Template name for the scaffolder to use. New project is going to be created out of this template.
98
- * @param values Parameters for the template, e.g. name, description
116
+ * @param templateName - Template name for the scaffolder to use. New project is going to be created out of this template.
117
+ * @param values - Parameters for the template, e.g. name, description
118
+ * @param secrets - Optional secrets to pass to as the secrets parameter to the template.
99
119
  */
100
- scaffold(templateName: string, values: Record<string, any>): Promise<string>;
120
+ scaffold(templateName: string, values: Record<string, any>, secrets?: Record<string, string>): Promise<string>;
101
121
  getTask(taskId: string): Promise<any>;
102
- streamLogs(opts: {
122
+ streamLogs(options: {
103
123
  taskId: string;
104
124
  after?: number;
105
125
  }): Observable<LogEvent>;
106
126
  private streamLogsEventStream;
107
127
  private streamLogsPolling;
108
- /**
109
- * @returns ListActionsResponse containing all registered actions.
110
- */
111
128
  listActions(): Promise<ListActionsResponse>;
112
129
  }
113
130
 
131
+ /**
132
+ * Field validation type for Custom Field Extensions.
133
+ *
134
+ * @public
135
+ */
114
136
  declare type CustomFieldValidator<T> = ((data: T, field: FieldValidation) => void) | ((data: T, field: FieldValidation, context: {
115
137
  apiHolder: ApiHolder;
116
138
  }) => void);
139
+ /**
140
+ * Type for the Custom Field Extension with the
141
+ * name and components and validation function.
142
+ *
143
+ * @public
144
+ */
117
145
  declare type FieldExtensionOptions<T = any> = {
118
146
  name: string;
119
147
  component: (props: FieldProps<T>) => JSX.Element | null;
120
148
  validation?: CustomFieldValidator<T>;
121
149
  };
150
+ /**
151
+ * Type for field extensions and being able to type
152
+ * incoming props easier.
153
+ *
154
+ * @public
155
+ */
156
+ interface FieldExtensionComponentProps<ReturnValue, UiOptions extends {} = {}> extends FieldProps<ReturnValue> {
157
+ uiSchema: {
158
+ 'ui:options'?: UiOptions;
159
+ };
160
+ }
122
161
 
123
162
  declare function createScaffolderFieldExtension<T = any>(options: FieldExtensionOptions<T>): Extension<() => null>;
124
163
  declare const ScaffolderFieldExtensions: react__default.ComponentType;
@@ -155,7 +194,11 @@ declare const EntityPicker: ({ onChange, schema: { title, description }, require
155
194
 
156
195
  declare const OwnerPicker: ({ schema: { title, description }, uiSchema, ...props }: FieldProps<string>) => JSX.Element;
157
196
 
158
- declare const RepoUrlPicker: ({ onChange, uiSchema, rawErrors, formData, }: FieldProps<string>) => JSX.Element;
197
+ interface RepoUrlPickerUiOptions {
198
+ allowedHosts?: string[];
199
+ allowedOwners?: string[];
200
+ }
201
+ declare const RepoUrlPicker: (props: FieldExtensionComponentProps<string, RepoUrlPickerUiOptions>) => JSX.Element;
159
202
 
160
203
  declare const TextValuePicker: ({ onChange, required, schema: { title, description }, rawErrors, formData, uiSchema: { "ui:autofocus": autoFocus }, idSchema, placeholder, }: FieldProps<string>) => JSX.Element;
161
204
 
@@ -172,7 +215,7 @@ declare type Props = ComponentProps<typeof IconButton> & {
172
215
  };
173
216
  /**
174
217
  * IconButton for showing if a current entity is starred and adding/removing it from the favourite entities
175
- * @param props MaterialUI IconButton props extended by required `entity` prop
218
+ * @param props - MaterialUI IconButton props extended by required `entity` prop
176
219
  */
177
220
  declare const FavouriteTemplate: (props: Props) => JSX.Element;
178
221
 
@@ -190,4 +233,4 @@ declare const TemplateList: ({ TemplateCardComponent, group, }: TemplateListProp
190
233
 
191
234
  declare const TemplateTypePicker: () => JSX.Element | null;
192
235
 
193
- export { CustomFieldValidator, EntityNamePicker, EntityNamePickerFieldExtension, EntityPicker, EntityPickerFieldExtension, EntityTagsPicker, EntityTagsPickerFieldExtension, FavouriteTemplate, FieldExtensionOptions, OwnedEntityPicker, OwnedEntityPickerFieldExtension, OwnerPicker, OwnerPickerFieldExtension, RepoUrlPicker, RepoUrlPickerFieldExtension, ScaffolderApi, ScaffolderClient, ScaffolderFieldExtensions, ScaffolderPage, TemplateList, TemplateListProps, TemplateTypePicker, TextValuePicker, createScaffolderFieldExtension, scaffolderPlugin as plugin, scaffolderApiRef, scaffolderPlugin };
236
+ export { CustomFieldValidator, EntityNamePicker, EntityNamePickerFieldExtension, EntityPicker, EntityPickerFieldExtension, EntityTagsPicker, EntityTagsPickerFieldExtension, FavouriteTemplate, FieldExtensionComponentProps, FieldExtensionOptions, OwnedEntityPicker, OwnedEntityPickerFieldExtension, OwnerPicker, OwnerPickerFieldExtension, RepoUrlPicker, RepoUrlPickerFieldExtension, RepoUrlPickerUiOptions, ScaffolderApi, ScaffolderClient, ScaffolderFieldExtensions, ScaffolderPage, TemplateList, TemplateListProps, TemplateTypePicker, TextValuePicker, createScaffolderFieldExtension, scaffolderPlugin as plugin, scaffolderApiRef, scaffolderPlugin };
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- export { a as EntityNamePicker, l as EntityNamePickerFieldExtension, E as EntityPicker, k as EntityPickerFieldExtension, b as EntityTagsPicker, m as EntityTagsPickerFieldExtension, v as FavouriteTemplate, c as OwnedEntityPicker, o as OwnedEntityPickerFieldExtension, O as OwnerPicker, n as OwnerPickerFieldExtension, R as RepoUrlPicker, p as RepoUrlPickerFieldExtension, S as ScaffolderClient, j as ScaffolderFieldExtensions, q as ScaffolderPage, f as TemplateList, T as TemplateTypePicker, u as TextValuePicker, i as createScaffolderFieldExtension, t as plugin, s as scaffolderApiRef, t as scaffolderPlugin } from './esm/index-f378943f.esm.js';
1
+ export { a as EntityNamePicker, l as EntityNamePickerFieldExtension, E as EntityPicker, k as EntityPickerFieldExtension, b as EntityTagsPicker, m as EntityTagsPickerFieldExtension, v as FavouriteTemplate, c as OwnedEntityPicker, o as OwnedEntityPickerFieldExtension, O as OwnerPicker, n as OwnerPickerFieldExtension, R as RepoUrlPicker, p as RepoUrlPickerFieldExtension, S as ScaffolderClient, j as ScaffolderFieldExtensions, q as ScaffolderPage, f as TemplateList, T as TemplateTypePicker, u as TextValuePicker, i as createScaffolderFieldExtension, t as plugin, s as scaffolderApiRef, t as scaffolderPlugin } from './esm/index-8b5d21c1.esm.js';
2
2
  import '@backstage/catalog-model';
3
3
  import '@backstage/integration-react';
4
4
  import '@backstage/core-plugin-api';
@@ -10,12 +10,13 @@ import '@material-ui/core';
10
10
  import '@material-ui/core/FormControl';
11
11
  import '@material-ui/lab/Autocomplete';
12
12
  import 'react';
13
- import 'react-use';
13
+ import 'react-use/lib/useAsync';
14
+ import 'react-use/lib/useEffectOnce';
14
15
  import '@material-ui/lab';
15
- import '@backstage/core-components';
16
16
  import '@material-ui/core/FormHelperText';
17
17
  import '@material-ui/core/Input';
18
18
  import '@material-ui/core/InputLabel';
19
+ import '@backstage/core-components';
19
20
  import '@material-ui/icons/Star';
20
21
  import '@material-ui/icons/StarBorder';
21
22
  import '@material-ui/icons/Warning';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder",
3
3
  "description": "The Backstage plugin that helps you create new things",
4
- "version": "0.11.16",
4
+ "version": "0.12.0",
5
5
  "main": "dist/index.esm.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -31,16 +31,16 @@
31
31
  "clean": "backstage-cli clean"
32
32
  },
33
33
  "dependencies": {
34
- "@backstage/catalog-client": "^0.5.3",
35
- "@backstage/catalog-model": "^0.9.7",
36
- "@backstage/config": "^0.1.11",
37
- "@backstage/core-components": "^0.8.2",
38
- "@backstage/core-plugin-api": "^0.4.0",
39
- "@backstage/errors": "^0.1.5",
40
- "@backstage/integration": "^0.7.0",
41
- "@backstage/integration-react": "^0.1.17",
42
- "@backstage/plugin-catalog-react": "^0.6.9",
43
- "@backstage/plugin-scaffolder-common": "^0.1.2",
34
+ "@backstage/catalog-client": "^0.5.5",
35
+ "@backstage/catalog-model": "^0.9.10",
36
+ "@backstage/config": "^0.1.13",
37
+ "@backstage/core-components": "^0.8.5",
38
+ "@backstage/core-plugin-api": "^0.6.0",
39
+ "@backstage/errors": "^0.2.0",
40
+ "@backstage/integration": "^0.7.2",
41
+ "@backstage/integration-react": "^0.1.19",
42
+ "@backstage/plugin-catalog-react": "^0.6.12",
43
+ "@backstage/plugin-scaffolder-common": "^0.1.3",
44
44
  "@backstage/theme": "^0.2.14",
45
45
  "@backstage/types": "^0.1.1",
46
46
  "@material-ui/core": "^4.12.2",
@@ -67,11 +67,11 @@
67
67
  "react": "^16.13.1 || ^17.0.0"
68
68
  },
69
69
  "devDependencies": {
70
- "@backstage/cli": "^0.10.4",
71
- "@backstage/core-app-api": "^0.3.0",
72
- "@backstage/dev-utils": "^0.2.15",
73
- "@backstage/plugin-catalog": "^0.7.6",
74
- "@backstage/test-utils": "^0.2.1",
70
+ "@backstage/cli": "^0.12.0",
71
+ "@backstage/core-app-api": "^0.5.0",
72
+ "@backstage/dev-utils": "^0.2.18",
73
+ "@backstage/plugin-catalog": "^0.7.9",
74
+ "@backstage/test-utils": "^0.2.3",
75
75
  "@testing-library/jest-dom": "^5.10.1",
76
76
  "@testing-library/react": "^11.2.5",
77
77
  "@testing-library/react-hooks": "^7.0.2",
@@ -86,5 +86,5 @@
86
86
  "files": [
87
87
  "dist"
88
88
  ],
89
- "gitHead": "4b2a8ed96ff427735c872a72c1864321ef698436"
89
+ "gitHead": "600d6e3c854bbfb12a0078ca6f726d1c0d1fea0b"
90
90
  }