From da25293910f208d00296af7c7de497a8f8ff7278 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Fri, 11 Nov 2022 14:11:42 -0500 Subject: [PATCH] refactor(scaffolder): wrap full field schema and prop type def in helper Signed-off-by: Phil Kuang --- .../writing-custom-field-extensions.md | 25 ++-- plugins/scaffolder/api-report.md | 116 ++++++++++-------- .../EntityNamePicker/EntityNamePicker.tsx | 7 +- .../fields/EntityNamePicker/schema.ts | 11 +- .../fields/EntityPicker/EntityPicker.tsx | 10 +- .../components/fields/EntityPicker/index.ts | 5 +- .../components/fields/EntityPicker/schema.ts | 17 ++- .../EntityTagsPicker/EntityTagsPicker.tsx | 13 +- .../fields/EntityTagsPicker/index.ts | 2 +- .../fields/EntityTagsPicker/schema.ts | 21 ++-- .../OwnedEntityPicker/OwnedEntityPicker.tsx | 14 +-- .../fields/OwnedEntityPicker/index.ts | 2 +- .../fields/OwnedEntityPicker/schema.ts | 17 +-- .../fields/OwnerPicker/OwnerPicker.tsx | 10 +- .../components/fields/OwnerPicker/index.ts | 5 +- .../components/fields/OwnerPicker/schema.ts | 16 +-- .../fields/RepoUrlPicker/RepoUrlPicker.tsx | 10 +- .../components/fields/RepoUrlPicker/index.ts | 2 +- .../components/fields/RepoUrlPicker/schema.ts | 18 ++- .../scaffolder/src/components/fields/index.ts | 2 +- .../scaffolder/src/components/fields/utils.ts | 45 +++++-- plugins/scaffolder/src/extensions/types.ts | 2 +- 22 files changed, 169 insertions(+), 201 deletions(-) diff --git a/docs/features/software-templates/writing-custom-field-extensions.md b/docs/features/software-templates/writing-custom-field-extensions.md index d0a36ecaf7..1d28bd5db9 100644 --- a/docs/features/software-templates/writing-custom-field-extensions.md +++ b/docs/features/software-templates/writing-custom-field-extensions.md @@ -212,7 +212,7 @@ export const MyCustomExtensionWithOptions = ({ rawErrors, required, formData, -}: FieldProps) => { +}: FieldExtensionComponentProps) => { return ( ) => { +}: MyCustomExtensionWithOptionsProps) => { return ( ( // @public export type CustomFieldExtensionSchema = { + returnValue: JSONSchema7; uiOptions?: JSONSchema7; - returnValue?: JSONSchema7; }; // @public @@ -90,19 +90,20 @@ export const EntityPickerFieldExtension: FieldExtensionComponent< } >; -// @public -export type EntityPickerUiOptions = typeof EntityPickerUiOptionsSchema.type; - // @public (undocumented) -export const EntityPickerUiOptionsSchema: { - schema: JSONSchema7; - type: { +export const EntityPickerFieldSchema: FieldSchema< + string, + { defaultKind?: string | undefined; defaultNamespace?: string | false | undefined; allowedKinds?: string[] | undefined; allowArbitraryValues?: boolean | undefined; - }; -}; + } +>; + +// @public +export type EntityPickerUiOptions = + typeof EntityPickerFieldSchema.uiOptionsType; // @public export const EntityTagsPickerFieldExtension: FieldExtensionComponent< @@ -114,19 +115,19 @@ export const EntityTagsPickerFieldExtension: FieldExtensionComponent< } >; -// @public -export type EntityTagsPickerUiOptions = - typeof EntityTagsPickerUiOptionsSchema.type; - // @public (undocumented) -export const EntityTagsPickerUiOptionsSchema: { - schema: JSONSchema7; - type: { +export const EntityTagsPickerFieldSchema: FieldSchema< + string[], + { showCounts?: boolean | undefined; kinds?: string[] | undefined; helperText?: string | undefined; - }; -}; + } +>; + +// @public +export type EntityTagsPickerUiOptions = + typeof EntityTagsPickerFieldSchema.uiOptionsType; // @public export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; @@ -155,6 +156,16 @@ export type FieldExtensionOptions< schema?: CustomFieldExtensionSchema; }; +// @public +export interface FieldSchema { + // (undocumented) + readonly schema: CustomFieldExtensionSchema; + // (undocumented) + readonly type: FieldExtensionComponentProps; + // (undocumented) + readonly uiOptionsType: TUiOptions; +} + // @public export type LayoutComponent<_TInputProps> = () => null; @@ -193,12 +204,18 @@ export type LogEvent = { }; // @public -export function makeJsonSchemaFromZod( - schema: T, -): { - schema: JSONSchema7; - type: T extends z.ZodType ? I : never; -}; +export function makeFieldSchemaFromZod< + TReturnSchema extends z.ZodType, + TUiOptionsSchema extends z.ZodType = z.ZodType, +>( + returnSchema: TReturnSchema, + uiOptionsSchema?: TUiOptionsSchema, +): FieldSchema< + TReturnSchema extends z.ZodType ? IReturn : never, + TUiOptionsSchema extends z.ZodType + ? IUiOptions + : never +>; // @alpha export type NextCustomFieldValidator = ( @@ -268,20 +285,20 @@ export const OwnedEntityPickerFieldExtension: FieldExtensionComponent< } >; -// @public -export type OwnedEntityPickerUiOptions = - typeof OwnedEntityPickerUiOptionsSchema.type; - // @public (undocumented) -export const OwnedEntityPickerUiOptionsSchema: { - schema: JSONSchema7; - type: { +export const OwnedEntityPickerFieldSchema: FieldSchema< + string, + { defaultKind?: string | undefined; defaultNamespace?: string | false | undefined; allowedKinds?: string[] | undefined; allowArbitraryValues?: boolean | undefined; - }; -}; + } +>; + +// @public +export type OwnedEntityPickerUiOptions = + typeof OwnedEntityPickerFieldSchema.uiOptionsType; // @public export const OwnerPickerFieldExtension: FieldExtensionComponent< @@ -293,18 +310,18 @@ export const OwnerPickerFieldExtension: FieldExtensionComponent< } >; -// @public -export type OwnerPickerUiOptions = typeof OwnerPickerUiOptionsSchema.type; - // @public (undocumented) -export const OwnerPickerUiOptionsSchema: { - schema: JSONSchema7; - type: { +export const OwnerPickerFieldSchema: FieldSchema< + string, + { defaultNamespace?: string | false | undefined; allowedKinds?: string[] | undefined; allowArbitraryValues?: boolean | undefined; - }; -}; + } +>; + +// @public +export type OwnerPickerUiOptions = typeof OwnerPickerFieldSchema.uiOptionsType; // @public export const repoPickerValidation: ( @@ -340,13 +357,10 @@ export const RepoUrlPickerFieldExtension: FieldExtensionComponent< } >; -// @public -export type RepoUrlPickerUiOptions = typeof RepoUrlPickerUiOptionsSchema.type; - // @public (undocumented) -export const RepoUrlPickerUiOptionsSchema: { - schema: JSONSchema7; - type: { +export const RepoUrlPickerFieldSchema: FieldSchema< + string, + { allowedOwners?: string[] | undefined; allowedOrganizations?: string[] | undefined; allowedRepos?: string[] | undefined; @@ -365,8 +379,12 @@ export const RepoUrlPickerUiOptionsSchema: { secretsKey: string; } | undefined; - }; -}; + } +>; + +// @public +export type RepoUrlPickerUiOptions = + typeof RepoUrlPickerFieldSchema.uiOptionsType; // @public (undocumented) export const rootRouteRef: RouteRef; diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx index eba05cfb92..555b726917 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/EntityNamePicker.tsx @@ -14,8 +14,7 @@ * limitations under the License. */ import React from 'react'; -import { FieldExtensionComponentProps } from '../../../extensions'; -import { EntityNamePickerReturnValue } from './schema'; +import { EntityNamePickerProps } from './schema'; import { TextField } from '@material-ui/core'; export { EntityNamePickerSchema } from './schema'; @@ -23,9 +22,7 @@ export { EntityNamePickerSchema } from './schema'; /** * EntityName Picker */ -export const EntityNamePicker = ( - props: FieldExtensionComponentProps, -) => { +export const EntityNamePicker = (props: EntityNamePickerProps) => { const { onChange, required, diff --git a/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts index 3139839bf4..27e33befb5 100644 --- a/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityNamePicker/schema.ts @@ -14,13 +14,10 @@ * limitations under the License. */ import { z } from 'zod'; -import { makeJsonSchemaFromZod } from '../utils'; +import { makeFieldSchemaFromZod } from '../utils'; -const EntityNamePickerReturnValueSchema = makeJsonSchemaFromZod(z.string()); +const EntityNamePickerFieldSchema = makeFieldSchemaFromZod(z.string()); -export type EntityNamePickerReturnValue = - typeof EntityNamePickerReturnValueSchema.type; +export const EntityNamePickerSchema = EntityNamePickerFieldSchema.schema; -export const EntityNamePickerSchema = { - returnValue: EntityNamePickerReturnValueSchema.schema, -}; +export type EntityNamePickerProps = typeof EntityNamePickerFieldSchema.type; diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 8fcc412d0a..bc78e00576 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -23,8 +23,7 @@ import FormControl from '@material-ui/core/FormControl'; import Autocomplete from '@material-ui/lab/Autocomplete'; import React, { useCallback, useEffect } from 'react'; import useAsync from 'react-use/lib/useAsync'; -import { FieldExtensionComponentProps } from '../../../extensions'; -import { EntityPickerReturnValue, EntityPickerUiOptions } from './schema'; +import { EntityPickerProps } from './schema'; export { EntityPickerSchema } from './schema'; @@ -34,12 +33,7 @@ export { EntityPickerSchema } from './schema'; * * @public */ -export const EntityPicker = ( - props: FieldExtensionComponentProps< - EntityPickerReturnValue, - EntityPickerUiOptions - >, -) => { +export const EntityPicker = (props: EntityPickerProps) => { const { onChange, schema: { title = 'Entity', description = 'An entity from the catalog' }, diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/index.ts b/plugins/scaffolder/src/components/fields/EntityPicker/index.ts index d1044e4e67..b8df596c98 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/EntityPicker/index.ts @@ -13,7 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { - type EntityPickerUiOptions, - EntityPickerUiOptionsSchema, -} from './schema'; +export { EntityPickerFieldSchema, type EntityPickerUiOptions } from './schema'; diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts index 3d14a2bf3e..9236457fc0 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityPicker/schema.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import { z } from 'zod'; -import { makeJsonSchemaFromZod } from '../utils'; +import { makeFieldSchemaFromZod } from '../utils'; /** * @public */ -export const EntityPickerUiOptionsSchema = makeJsonSchemaFromZod( +export const EntityPickerFieldSchema = makeFieldSchemaFromZod( + z.string(), z.object({ allowedKinds: z .array(z.string()) @@ -44,19 +45,15 @@ export const EntityPickerUiOptionsSchema = makeJsonSchemaFromZod( }), ); -const EntityPickerReturnValueSchema = makeJsonSchemaFromZod(z.string()); - /** * The input props that can be specified under `ui:options` for the * `EntityPicker` field extension. * * @public */ -export type EntityPickerUiOptions = typeof EntityPickerUiOptionsSchema.type; +export type EntityPickerUiOptions = + typeof EntityPickerFieldSchema.uiOptionsType; -export type EntityPickerReturnValue = typeof EntityPickerReturnValueSchema.type; +export type EntityPickerProps = typeof EntityPickerFieldSchema.type; -export const EntityPickerSchema = { - uiOptions: EntityPickerUiOptionsSchema.schema, - returnValue: EntityPickerReturnValueSchema.schema, -}; +export const EntityPickerSchema = EntityPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx index 6d5404cee1..549ccdb8aa 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx @@ -22,11 +22,7 @@ import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { FormControl, TextField } from '@material-ui/core'; import { Autocomplete } from '@material-ui/lab'; -import { FieldExtensionComponentProps } from '../../../extensions'; -import { - EntityTagsPickerReturnValue, - EntityTagsPickerUiOptions, -} from './schema'; +import { EntityTagsPickerProps } from './schema'; export { EntityTagsPickerSchema } from './schema'; @@ -36,12 +32,7 @@ export { EntityTagsPickerSchema } from './schema'; * * @public */ -export const EntityTagsPicker = ( - props: FieldExtensionComponentProps< - EntityTagsPickerReturnValue, - EntityTagsPickerUiOptions - >, -) => { +export const EntityTagsPicker = (props: EntityTagsPickerProps) => { const { formData, onChange, uiSchema } = props; const catalogApi = useApi(catalogApiRef); const [tagOptions, setTagOptions] = useState([]); diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/index.ts b/plugins/scaffolder/src/components/fields/EntityTagsPicker/index.ts index 850fc17c8e..52bad9a80d 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/index.ts @@ -14,6 +14,6 @@ * limitations under the License. */ export { + EntityTagsPickerFieldSchema, type EntityTagsPickerUiOptions, - EntityTagsPickerUiOptionsSchema, } from './schema'; diff --git a/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts b/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts index d3a5391385..6677d16e98 100644 --- a/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/EntityTagsPicker/schema.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import { z } from 'zod'; -import { makeJsonSchemaFromZod } from '../utils'; +import { makeFieldSchemaFromZod } from '../utils'; /** * @public */ -export const EntityTagsPickerUiOptionsSchema = makeJsonSchemaFromZod( +export const EntityTagsPickerFieldSchema = makeFieldSchemaFromZod( + z.array(z.string()), z.object({ kinds: z .array(z.string()) @@ -33,9 +34,9 @@ export const EntityTagsPickerUiOptionsSchema = makeJsonSchemaFromZod( }), ); -const EntityTagsPickerReturnValueSchema = makeJsonSchemaFromZod( - z.array(z.string()), -); +export const EntityTagsPickerSchema = EntityTagsPickerFieldSchema.schema; + +export type EntityTagsPickerProps = typeof EntityTagsPickerFieldSchema.type; /** * The input props that can be specified under `ui:options` for the @@ -44,12 +45,4 @@ const EntityTagsPickerReturnValueSchema = makeJsonSchemaFromZod( * @public */ export type EntityTagsPickerUiOptions = - typeof EntityTagsPickerUiOptionsSchema.type; - -export type EntityTagsPickerReturnValue = - typeof EntityTagsPickerReturnValueSchema.type; - -export const EntityTagsPickerSchema = { - uiOptions: EntityTagsPickerUiOptionsSchema.schema, - returnValue: EntityTagsPickerReturnValueSchema.schema, -}; + typeof EntityTagsPickerFieldSchema.uiOptionsType; diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index 47bcb6c9b8..01a174a6a3 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -26,25 +26,17 @@ import Autocomplete from '@material-ui/lab/Autocomplete'; import React, { useMemo } from 'react'; import useAsync from 'react-use/lib/useAsync'; -import { FieldExtensionComponentProps } from '../../../extensions'; -import { - OwnedEntityPickerReturnValue, - OwnedEntityPickerUiOptions, -} from './schema'; +import { OwnedEntityPickerProps } from './schema'; export { OwnedEntityPickerSchema } from './schema'; + /** * The underlying component that is rendered in the form for the `OwnedEntityPicker` * field extension. * * @public */ -export const OwnedEntityPicker = ( - props: FieldExtensionComponentProps< - OwnedEntityPickerReturnValue, - OwnedEntityPickerUiOptions - >, -) => { +export const OwnedEntityPicker = (props: OwnedEntityPickerProps) => { const { onChange, schema: { title = 'Entity', description = 'An entity from the catalog' }, diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/index.ts b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/index.ts index 0101eb8845..985dae1d3c 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/index.ts @@ -14,6 +14,6 @@ * limitations under the License. */ export { + OwnedEntityPickerFieldSchema, type OwnedEntityPickerUiOptions, - OwnedEntityPickerUiOptionsSchema, } from './schema'; diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts index c967448729..4190b89f95 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/schema.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import { z } from 'zod'; -import { makeJsonSchemaFromZod } from '../utils'; +import { makeFieldSchemaFromZod } from '../utils'; /** * @public */ -export const OwnedEntityPickerUiOptionsSchema = makeJsonSchemaFromZod( +export const OwnedEntityPickerFieldSchema = makeFieldSchemaFromZod( + z.string(), z.object({ allowedKinds: z .array(z.string()) @@ -44,8 +45,6 @@ export const OwnedEntityPickerUiOptionsSchema = makeJsonSchemaFromZod( }), ); -const OwnedEntityPickerReturnValueSchema = makeJsonSchemaFromZod(z.string()); - /** * The input props that can be specified under `ui:options` for the * `OwnedEntityPicker` field extension. @@ -53,12 +52,8 @@ const OwnedEntityPickerReturnValueSchema = makeJsonSchemaFromZod(z.string()); * @public */ export type OwnedEntityPickerUiOptions = - typeof OwnedEntityPickerUiOptionsSchema.type; + typeof OwnedEntityPickerFieldSchema.uiOptionsType; -export type OwnedEntityPickerReturnValue = - typeof OwnedEntityPickerReturnValueSchema.type; +export type OwnedEntityPickerProps = typeof OwnedEntityPickerFieldSchema.type; -export const OwnedEntityPickerSchema = { - uiOptions: OwnedEntityPickerUiOptionsSchema.schema, - returnValue: OwnedEntityPickerReturnValueSchema.schema, -}; +export const OwnedEntityPickerSchema = OwnedEntityPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx index 10333684d0..1c4c356906 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx @@ -15,8 +15,7 @@ */ import React from 'react'; import { EntityPicker } from '../EntityPicker/EntityPicker'; -import { FieldExtensionComponentProps } from '../../../extensions'; -import { OwnerPickerReturnValue, OwnerPickerUiOptions } from './schema'; +import { OwnerPickerProps } from './schema'; export { OwnerPickerSchema } from './schema'; @@ -26,12 +25,7 @@ export { OwnerPickerSchema } from './schema'; * * @public */ -export const OwnerPicker = ( - props: FieldExtensionComponentProps< - OwnerPickerReturnValue, - OwnerPickerUiOptions - >, -) => { +export const OwnerPicker = (props: OwnerPickerProps) => { const { schema: { title = 'Owner', description = 'The owner of the component' }, uiSchema, diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts b/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts index 5d436358b3..9d94650e04 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts @@ -13,7 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { - type OwnerPickerUiOptions, - OwnerPickerUiOptionsSchema, -} from './schema'; +export { OwnerPickerFieldSchema, type OwnerPickerUiOptions } from './schema'; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts b/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts index accc8f80fc..56edef1343 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/schema.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import { z } from 'zod'; -import { makeJsonSchemaFromZod } from '../utils'; +import { makeFieldSchemaFromZod } from '../utils'; /** * @public */ -export const OwnerPickerUiOptionsSchema = makeJsonSchemaFromZod( +export const OwnerPickerFieldSchema = makeFieldSchemaFromZod( + z.string(), z.object({ allowedKinds: z .array(z.string()) @@ -41,19 +42,14 @@ export const OwnerPickerUiOptionsSchema = makeJsonSchemaFromZod( }), ); -const OwnerPickerReturnValueSchema = makeJsonSchemaFromZod(z.string()); - /** * The input props that can be specified under `ui:options` for the * `OwnerPicker` field extension. * * @public */ -export type OwnerPickerUiOptions = typeof OwnerPickerUiOptionsSchema.type; +export type OwnerPickerUiOptions = typeof OwnerPickerFieldSchema.uiOptionsType; -export type OwnerPickerReturnValue = typeof OwnerPickerReturnValueSchema.type; +export type OwnerPickerProps = typeof OwnerPickerFieldSchema.type; -export const OwnerPickerSchema = { - uiOptions: OwnerPickerUiOptionsSchema.schema, - returnValue: OwnerPickerReturnValueSchema.schema, -}; +export const OwnerPickerSchema = OwnerPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 8aca07e995..827eff6ea2 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -24,11 +24,10 @@ import { GitlabRepoPicker } from './GitlabRepoPicker'; import { AzureRepoPicker } from './AzureRepoPicker'; import { BitbucketRepoPicker } from './BitbucketRepoPicker'; import { GerritRepoPicker } from './GerritRepoPicker'; -import { FieldExtensionComponentProps } from '../../../extensions'; import { RepoUrlPickerHost } from './RepoUrlPickerHost'; import { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName'; import { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils'; -import { RepoUrlPickerReturnValue, RepoUrlPickerUiOptions } from './schema'; +import { RepoUrlPickerProps } from './schema'; import { RepoUrlPickerState } from './types'; import useDebounce from 'react-use/lib/useDebounce'; import { useTemplateSecrets } from '../../secrets'; @@ -41,12 +40,7 @@ export { RepoUrlPickerSchema } from './schema'; * * @public */ -export const RepoUrlPicker = ( - props: FieldExtensionComponentProps< - RepoUrlPickerReturnValue, - RepoUrlPickerUiOptions - >, -) => { +export const RepoUrlPicker = (props: RepoUrlPickerProps) => { const { uiSchema, onChange, rawErrors, formData } = props; const [state, setState] = useState( parseRepoPickerUrl(formData), diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/index.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/index.ts index 34124d0ccd..33e5ef1715 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/index.ts @@ -14,7 +14,7 @@ * limitations under the License. */ export { + RepoUrlPickerFieldSchema, type RepoUrlPickerUiOptions, - RepoUrlPickerUiOptionsSchema, } from './schema'; export { repoPickerValidation } from './validation'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/schema.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/schema.ts index bf8fa3cf5c..8f8674a0a7 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/schema.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/schema.ts @@ -14,12 +14,13 @@ * limitations under the License. */ import { z } from 'zod'; -import { makeJsonSchemaFromZod } from '../utils'; +import { makeFieldSchemaFromZod } from '../utils'; /** * @public */ -export const RepoUrlPickerUiOptionsSchema = makeJsonSchemaFromZod( +export const RepoUrlPickerFieldSchema = makeFieldSchemaFromZod( + z.string(), z.object({ allowedHosts: z .array(z.string()) @@ -77,23 +78,18 @@ export const RepoUrlPickerUiOptionsSchema = makeJsonSchemaFromZod( }), ); -const RepoUrlPickerReturnValueSchema = makeJsonSchemaFromZod(z.string()); - /** * The input props that can be specified under `ui:options` for the * `RepoUrlPicker` field extension. * * @public */ -export type RepoUrlPickerUiOptions = typeof RepoUrlPickerUiOptionsSchema.type; +export type RepoUrlPickerUiOptions = + typeof RepoUrlPickerFieldSchema.uiOptionsType; -export type RepoUrlPickerReturnValue = - typeof RepoUrlPickerReturnValueSchema.type; +export type RepoUrlPickerProps = typeof RepoUrlPickerFieldSchema.type; // NOTE: There is a bug with this failing validation in the custom field explorer due // to https://github.com/rjsf-team/react-jsonschema-form/issues/675 even if // requestUserCredentials is not defined -export const RepoUrlPickerSchema = { - uiOptions: RepoUrlPickerUiOptionsSchema.schema, - returnValue: RepoUrlPickerReturnValueSchema.schema, -}; +export const RepoUrlPickerSchema = RepoUrlPickerFieldSchema.schema; diff --git a/plugins/scaffolder/src/components/fields/index.ts b/plugins/scaffolder/src/components/fields/index.ts index e78b92da00..8d86f601ce 100644 --- a/plugins/scaffolder/src/components/fields/index.ts +++ b/plugins/scaffolder/src/components/fields/index.ts @@ -18,4 +18,4 @@ export * from './OwnerPicker'; export * from './RepoUrlPicker'; export * from './OwnedEntityPicker'; export * from './EntityTagsPicker'; -export { makeJsonSchemaFromZod } from './utils'; +export { type FieldSchema, makeFieldSchemaFromZod } from './utils'; diff --git a/plugins/scaffolder/src/components/fields/utils.ts b/plugins/scaffolder/src/components/fields/utils.ts index 2f56e31db5..2d3e2aab1e 100644 --- a/plugins/scaffolder/src/components/fields/utils.ts +++ b/plugins/scaffolder/src/components/fields/utils.ts @@ -16,20 +16,47 @@ import { JSONSchema7 } from 'json-schema'; import { z } from 'zod'; import zodToJsonSchema from 'zod-to-json-schema'; +import { + CustomFieldExtensionSchema, + FieldExtensionComponentProps, +} from '../../extensions'; /** * @public - * Utility function to convert zod schemas to JSON schemas with - * type inference extraction that abstracts away zod typings + * FieldSchema encapsulates a JSONSchema7 along with the + * matching FieldExtensionComponentProps type for a field extension. */ -export function makeJsonSchemaFromZod( - schema: T, -): { - schema: JSONSchema7; - type: T extends z.ZodType ? I : never; -} { +export interface FieldSchema { + readonly schema: CustomFieldExtensionSchema; + readonly type: FieldExtensionComponentProps; + readonly uiOptionsType: TUiOptions; +} + +/** + * @public + * Utility function to convert zod return and UI options schemas to a + * CustomFieldExtensionSchema with FieldExtensionComponentProps type inference + */ +export function makeFieldSchemaFromZod< + TReturnSchema extends z.ZodType, + TUiOptionsSchema extends z.ZodType = z.ZodType, +>( + returnSchema: TReturnSchema, + uiOptionsSchema?: TUiOptionsSchema, +): FieldSchema< + TReturnSchema extends z.ZodType ? IReturn : never, + TUiOptionsSchema extends z.ZodType + ? IUiOptions + : never +> { return { - schema: zodToJsonSchema(schema) as JSONSchema7, + schema: { + returnValue: zodToJsonSchema(returnSchema) as JSONSchema7, + uiOptions: uiOptionsSchema + ? (zodToJsonSchema(uiOptionsSchema) as JSONSchema7) + : undefined, + }, type: null as any, + uiOptionsType: null as any, }; } diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index b15de56fc1..3834b39c0a 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -41,8 +41,8 @@ export type CustomFieldValidator = ( * @public */ export type CustomFieldExtensionSchema = { + returnValue: JSONSchema7; uiOptions?: JSONSchema7; - returnValue?: JSONSchema7; }; /**