diff --git a/invokeai/frontend/web/docs/WORKFLOWS_DESIGN_IMPLEMENTATION.md b/invokeai/frontend/web/docs/WORKFLOWS_DESIGN_IMPLEMENTATION.md index d5cfc9154e..77d24206f6 100644 --- a/invokeai/frontend/web/docs/WORKFLOWS_DESIGN_IMPLEMENTATION.md +++ b/invokeai/frontend/web/docs/WORKFLOWS_DESIGN_IMPLEMENTATION.md @@ -209,7 +209,7 @@ Field types are represented as structured objects: type FieldType = { name: string; isCollection: boolean; - isPolymorphic: boolean; + isCollectionOrScalar: boolean; }; ``` @@ -237,11 +237,11 @@ When a field is annotated as a list of a single type, the schema object has an ` We use the item type for field type name, adding `isCollection: true` to the field type. -##### Polymorphic Types +##### Collection or Scalar Types When a field is annotated as a union of a type and list of that type, the schema object has an `anyOf` property, which holds a list of valid types for the union. -After verifying that the union has two members (a type and list of the same type), we use the type for field type name, adding `isPolymorphic: true` to the field type. +After verifying that the union has two members (a type and list of the same type), we use the type for field type name, adding `isCollectionOrScalar: true` to the field type. ##### Optional Fields diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 3e7e26d9a9..8b5afce4a7 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -808,7 +808,7 @@ "clipFieldDescription": "Tokenizer and text_encoder submodels.", "collection": "Collection", "collectionFieldType": "{{name}} Collection", - "polymorphicFieldType": "{{name}} Polymorphic", + "collectionOrScalarFieldType": "{{name}} Collection|Scalar", "collectionDescription": "TODO", "collectionItem": "Collection Item", "collectionItemDescription": "TODO", @@ -975,7 +975,7 @@ "unableToExtractSchemaNameFromRef": "unable to extract schema name from ref", "unsupportedArrayItemType": "unsupported array item type \"{{type}}\"", "unsupportedAnyOfLength": "too many union members ({{count}})", - "unsupportedMismatchedUnion": "mismatched polymorphic type with members {{firstType}} and {{secondType}}", + "unsupportedMismatchedUnion": "mismatched CollectionOrScalar type with base types {{firstType}} and {{secondType}}", "unableToParseFieldType": "unable to parse field type", "uNetField": "UNet", "uNetFieldDescription": "UNet submodel.", diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldHandle.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldHandle.tsx index a622e5018c..83e2ef6a57 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldHandle.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/FieldHandle.tsx @@ -54,13 +54,13 @@ const FieldHandle = (props: FieldHandleProps) => { const color = getFieldColor(type); const s: CSSProperties = { backgroundColor: - type.isCollection || type.isPolymorphic + type.isCollection || type.isCollectionOrScalar ? colorTokenToCssVar('base.900') : color, position: 'absolute', width: '1rem', height: '1rem', - borderWidth: type.isCollection || type.isPolymorphic ? 4 : 0, + borderWidth: type.isCollection || type.isCollectionOrScalar ? 4 : 0, borderStyle: 'solid', borderColor: color, borderRadius: isModelType ? 4 : '100%', diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useAnyOrDirectInputFieldNames.ts b/invokeai/frontend/web/src/features/nodes/hooks/useAnyOrDirectInputFieldNames.ts index b934c6b959..4893ff1280 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useAnyOrDirectInputFieldNames.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useAnyOrDirectInputFieldNames.ts @@ -25,7 +25,7 @@ export const useAnyOrDirectInputFieldNames = (nodeId: string) => { const fields = map(nodeTemplate.inputs).filter( (field) => (['any', 'direct'].includes(field.input) || - field.type.isPolymorphic) && + field.type.isCollectionOrScalar) && keys(TEMPLATE_BUILDER_MAP).includes(field.type.name) ); return getSortedFilteredFieldNames(fields); diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useConnectionInputFieldNames.ts b/invokeai/frontend/web/src/features/nodes/hooks/useConnectionInputFieldNames.ts index a2694bd1ba..47b0d4bb21 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useConnectionInputFieldNames.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useConnectionInputFieldNames.ts @@ -26,7 +26,8 @@ export const useConnectionInputFieldNames = (nodeId: string) => { // get the visible fields const fields = map(nodeTemplate.inputs).filter( (field) => - (field.input === 'connection' && !field.type.isPolymorphic) || + (field.input === 'connection' && + !field.type.isCollectionOrScalar) || !keys(TEMPLATE_BUILDER_MAP).includes(field.type.name) ); diff --git a/invokeai/frontend/web/src/features/nodes/hooks/usePrettyFieldType.ts b/invokeai/frontend/web/src/features/nodes/hooks/usePrettyFieldType.ts index bff5873864..78d5cf9837 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/usePrettyFieldType.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/usePrettyFieldType.ts @@ -13,8 +13,8 @@ export const useFieldTypeName = (fieldType?: FieldType): string => { if (fieldType.isCollection) { return t('nodes.collectionFieldType', { name }); } - if (fieldType.isPolymorphic) { - return t('nodes.polymorphicFieldType', { name }); + if (fieldType.isCollectionOrScalar) { + return t('nodes.collectionOrScalarFieldType', { name }); } return name; }, [fieldType, t]); diff --git a/invokeai/frontend/web/src/features/nodes/store/util/validateSourceAndTargetTypes.ts b/invokeai/frontend/web/src/features/nodes/store/util/validateSourceAndTargetTypes.ts index 2770af19e3..e3ad0b9621 100644 --- a/invokeai/frontend/web/src/features/nodes/store/util/validateSourceAndTargetTypes.ts +++ b/invokeai/frontend/web/src/features/nodes/store/util/validateSourceAndTargetTypes.ts @@ -29,8 +29,8 @@ export const validateSourceAndTargetTypes = ( * Connection types must be the same for a connection, with exceptions: * - CollectionItem can connect to any non-Collection * - Non-Collections can connect to CollectionItem - * - Anything (non-Collections, Collections, Polymorphics) can connect to Polymorphics of the same base type - * - Generic Collection can connect to any other Collection or Polymorphic + * - Anything (non-Collections, Collections, CollectionOrScalar) can connect to CollectionOrScalar of the same base type + * - Generic Collection can connect to any other Collection or CollectionOrScalar * - Any Collection can connect to a Generic Collection */ @@ -40,23 +40,23 @@ export const validateSourceAndTargetTypes = ( const isNonCollectionToCollectionItem = targetType.name === 'CollectionItemField' && !sourceType.isCollection && - !sourceType.isPolymorphic; + !sourceType.isCollectionOrScalar; - const isAnythingToPolymorphicOfSameBaseType = - targetType.isPolymorphic && sourceType.name === targetType.name; + const isAnythingToCollectionOrScalarOfSameBaseType = + targetType.isCollectionOrScalar && sourceType.name === targetType.name; - const isGenericCollectionToAnyCollectionOrPolymorphic = + const isGenericCollectionToAnyCollectionOrCollectionOrScalar = sourceType.name === 'CollectionField' && - (targetType.isCollection || targetType.isPolymorphic); + (targetType.isCollection || targetType.isCollectionOrScalar); const isCollectionToGenericCollection = targetType.name === 'CollectionField' && sourceType.isCollection; const areBothTypesSingle = !sourceType.isCollection && - !sourceType.isPolymorphic && + !sourceType.isCollectionOrScalar && !targetType.isCollection && - !targetType.isPolymorphic; + !targetType.isCollectionOrScalar; const isIntToFloat = areBothTypesSingle && @@ -74,8 +74,8 @@ export const validateSourceAndTargetTypes = ( return ( isCollectionItemToNonCollection || isNonCollectionToCollectionItem || - isAnythingToPolymorphicOfSameBaseType || - isGenericCollectionToAnyCollectionOrPolymorphic || + isAnythingToCollectionOrScalarOfSameBaseType || + isGenericCollectionToAnyCollectionOrCollectionOrScalar || isCollectionToGenericCollection || isIntToFloat || isIntOrFloatToString || diff --git a/invokeai/frontend/web/src/features/nodes/types/field.ts b/invokeai/frontend/web/src/features/nodes/types/field.ts index 804f09b45f..11776d5d51 100644 --- a/invokeai/frontend/web/src/features/nodes/types/field.ts +++ b/invokeai/frontend/web/src/features/nodes/types/field.ts @@ -84,7 +84,7 @@ export type FieldOutputTemplateBase = z.infer; export const zFieldTypeBase = z.object({ isCollection: z.boolean(), - isPolymorphic: z.boolean(), + isCollectionOrScalar: z.boolean(), }); export const zFieldIdentifier = z.object({ diff --git a/invokeai/frontend/web/src/features/nodes/types/v1/fieldTypeMap.ts b/invokeai/frontend/web/src/features/nodes/types/v1/fieldTypeMap.ts index aace29d523..f11458a2d7 100644 --- a/invokeai/frontend/web/src/features/nodes/types/v1/fieldTypeMap.ts +++ b/invokeai/frontend/web/src/features/nodes/types/v1/fieldTypeMap.ts @@ -7,118 +7,146 @@ import { FieldTypeV1 } from './workflowV1'; const FIELD_TYPE_V1_TO_STATEFUL_FIELD_TYPE_V2: { [key in FieldTypeV1]?: StatefulFieldType; } = { - BoardField: { name: 'BoardField', isCollection: false, isPolymorphic: false }, - boolean: { name: 'BooleanField', isCollection: false, isPolymorphic: false }, + BoardField: { + name: 'BoardField', + isCollection: false, + isCollectionOrScalar: false, + }, + boolean: { + name: 'BooleanField', + isCollection: false, + isCollectionOrScalar: false, + }, BooleanCollection: { name: 'BooleanField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, BooleanPolymorphic: { name: 'BooleanField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, + }, + ColorField: { + name: 'ColorField', + isCollection: false, + isCollectionOrScalar: false, }, - ColorField: { name: 'ColorField', isCollection: false, isPolymorphic: false }, ColorCollection: { name: 'ColorField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, ColorPolymorphic: { name: 'ColorField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, ControlNetModelField: { name: 'ControlNetModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, + }, + enum: { name: 'EnumField', isCollection: false, isCollectionOrScalar: false }, + float: { + name: 'FloatField', + isCollection: false, + isCollectionOrScalar: false, }, - enum: { name: 'EnumField', isCollection: false, isPolymorphic: false }, - float: { name: 'FloatField', isCollection: false, isPolymorphic: false }, FloatCollection: { name: 'FloatField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, FloatPolymorphic: { name: 'FloatField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, ImageCollection: { name: 'ImageField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, + }, + ImageField: { + name: 'ImageField', + isCollection: false, + isCollectionOrScalar: false, }, - ImageField: { name: 'ImageField', isCollection: false, isPolymorphic: false }, ImagePolymorphic: { name: 'ImageField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, + }, + integer: { + name: 'IntegerField', + isCollection: false, + isCollectionOrScalar: false, }, - integer: { name: 'IntegerField', isCollection: false, isPolymorphic: false }, IntegerCollection: { name: 'IntegerField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, IntegerPolymorphic: { name: 'IntegerField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, IPAdapterModelField: { name: 'IPAdapterModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, LoRAModelField: { name: 'LoRAModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, MainModelField: { name: 'MainModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, Scheduler: { name: 'SchedulerField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, SDXLMainModelField: { name: 'SDXLMainModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, SDXLRefinerModelField: { name: 'SDXLRefinerModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, + }, + string: { + name: 'StringField', + isCollection: false, + isCollectionOrScalar: false, }, - string: { name: 'StringField', isCollection: false, isPolymorphic: false }, StringCollection: { name: 'StringField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, StringPolymorphic: { name: 'StringField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, T2IAdapterModelField: { name: 'T2IAdapterModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, VaeModelField: { name: 'VAEModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, }; @@ -138,130 +166,142 @@ const FIELD_TYPE_V1_TO_STATEFUL_FIELD_TYPE_V2: { const FIELD_TYPE_V1_TO_STATELESS_FIELD_TYPE_V2: { [key in FieldTypeV1]?: FieldType; } = { - Any: { name: 'AnyField', isCollection: false, isPolymorphic: false }, - ClipField: { name: 'ClipField', isCollection: false, isPolymorphic: false }, + Any: { name: 'AnyField', isCollection: false, isCollectionOrScalar: false }, + ClipField: { + name: 'ClipField', + isCollection: false, + isCollectionOrScalar: false, + }, Collection: { name: 'CollectionField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, CollectionItem: { name: 'CollectionItemField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, ConditioningCollection: { name: 'ConditioningField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, ConditioningField: { name: 'ConditioningField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, ConditioningPolymorphic: { name: 'ConditioningField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, ControlCollection: { name: 'ControlField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, ControlField: { name: 'ControlField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, ControlPolymorphic: { name: 'ControlField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, DenoiseMaskField: { name: 'DenoiseMaskField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, IPAdapterField: { name: 'IPAdapterField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, IPAdapterCollection: { name: 'IPAdapterField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, IPAdapterPolymorphic: { name: 'IPAdapterField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, LatentsField: { name: 'LatentsField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, LatentsCollection: { name: 'LatentsField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, LatentsPolymorphic: { name: 'LatentsField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, MetadataField: { name: 'MetadataField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, MetadataCollection: { name: 'MetadataField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, MetadataItemField: { name: 'MetadataItemField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, MetadataItemCollection: { name: 'MetadataItemField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, MetadataItemPolymorphic: { name: 'MetadataItemField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, }, ONNXModelField: { name: 'ONNXModelField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, T2IAdapterField: { name: 'T2IAdapterField', isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }, T2IAdapterCollection: { name: 'T2IAdapterField', isCollection: true, - isPolymorphic: false, + isCollectionOrScalar: false, }, T2IAdapterPolymorphic: { name: 'T2IAdapterField', isCollection: false, - isPolymorphic: true, + isCollectionOrScalar: true, + }, + UNetField: { + name: 'UNetField', + isCollection: false, + isCollectionOrScalar: false, + }, + VaeField: { + name: 'VaeField', + isCollection: false, + isCollectionOrScalar: false, }, - UNetField: { name: 'UNetField', isCollection: false, isPolymorphic: false }, - VaeField: { name: 'VaeField', isCollection: false, isPolymorphic: false }, }; export const FIELD_TYPE_V1_TO_FIELD_TYPE_V2_MAPPING = { diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts index ff6028b38e..cce34d188e 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts @@ -30,7 +30,7 @@ export const addControlNetToLinearGraph = ( const controlNetMetadata: CoreMetadataInvocation['controlnets'] = []; if (validControlNets.length) { - // Even though denoise_latents' control input is polymorphic, keep it simple and always use a collect + // Even though denoise_latents' control input is collection or scalar, keep it simple and always use a collect const controlNetIterateNode: CollectInvocation = { id: CONTROL_NET_COLLECT, type: 'collect', diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts index 9dd8b25368..ba5b839f8b 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts @@ -24,7 +24,7 @@ export const addIPAdapterToLinearGraph = ( ); if (validIPAdapters.length) { - // Even though denoise_latents' control input is polymorphic, keep it simple and always use a collect + // Even though denoise_latents' ip adapter input is collection or scalar, keep it simple and always use a collect const ipAdapterCollectNode: CollectInvocation = { id: IP_ADAPTER_COLLECT, type: 'collect', diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts index 550f9ba5f3..5106d49719 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts @@ -24,7 +24,7 @@ export const addT2IAdaptersToLinearGraph = ( ); if (validT2IAdapters.length) { - // Even though denoise_latents' control input is polymorphic, keep it simple and always use a collect + // Even though denoise_latents' t2i adapter input is collection or scalar, keep it simple and always use a collect const t2iAdapterCollectNode: CollectInvocation = { id: T2I_ADAPTER_COLLECT, type: 'collect', diff --git a/invokeai/frontend/web/src/features/nodes/util/schema/buildFieldInputTemplate.ts b/invokeai/frontend/web/src/features/nodes/util/schema/buildFieldInputTemplate.ts index 9f33c1328f..d5e333c281 100644 --- a/invokeai/frontend/web/src/features/nodes/util/schema/buildFieldInputTemplate.ts +++ b/invokeai/frontend/web/src/features/nodes/util/schema/buildFieldInputTemplate.ts @@ -31,15 +31,19 @@ type FieldInputTemplateBuilder = // valid `a schemaObject: InvocationFieldSchema; baseField: Omit; isCollection: boolean; - isPolymorphic: boolean; + isCollectionOrScalar: boolean; }) => T; const buildIntegerFieldInputTemplate: FieldInputTemplateBuilder< IntegerFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: IntegerFieldInputTemplate = { ...baseField, - type: { name: 'IntegerField', isCollection, isPolymorphic }, + type: { + name: 'IntegerField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? 0, }; @@ -74,10 +78,14 @@ const buildIntegerFieldInputTemplate: FieldInputTemplateBuilder< const buildFloatFieldInputTemplate: FieldInputTemplateBuilder< FloatFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: FloatFieldInputTemplate = { ...baseField, - type: { name: 'FloatField', isCollection, isPolymorphic }, + type: { + name: 'FloatField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? 0, }; @@ -112,10 +120,14 @@ const buildFloatFieldInputTemplate: FieldInputTemplateBuilder< const buildStringFieldInputTemplate: FieldInputTemplateBuilder< StringFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: StringFieldInputTemplate = { ...baseField, - type: { name: 'StringField', isCollection, isPolymorphic }, + type: { + name: 'StringField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? '', }; @@ -132,10 +144,14 @@ const buildStringFieldInputTemplate: FieldInputTemplateBuilder< const buildBooleanFieldInputTemplate: FieldInputTemplateBuilder< BooleanFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: BooleanFieldInputTemplate = { ...baseField, - type: { name: 'BooleanField', isCollection, isPolymorphic }, + type: { + name: 'BooleanField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? false, }; @@ -144,10 +160,14 @@ const buildBooleanFieldInputTemplate: FieldInputTemplateBuilder< const buildMainModelFieldInputTemplate: FieldInputTemplateBuilder< MainModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: MainModelFieldInputTemplate = { ...baseField, - type: { name: 'MainModelField', isCollection, isPolymorphic }, + type: { + name: 'MainModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -156,10 +176,14 @@ const buildMainModelFieldInputTemplate: FieldInputTemplateBuilder< const buildSDXLMainModelFieldInputTemplate: FieldInputTemplateBuilder< SDXLMainModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: SDXLMainModelFieldInputTemplate = { ...baseField, - type: { name: 'SDXLMainModelField', isCollection, isPolymorphic }, + type: { + name: 'SDXLMainModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -168,10 +192,14 @@ const buildSDXLMainModelFieldInputTemplate: FieldInputTemplateBuilder< const buildRefinerModelFieldInputTemplate: FieldInputTemplateBuilder< SDXLRefinerModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: SDXLRefinerModelFieldInputTemplate = { ...baseField, - type: { name: 'SDXLRefinerModelField', isCollection, isPolymorphic }, + type: { + name: 'SDXLRefinerModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -180,10 +208,14 @@ const buildRefinerModelFieldInputTemplate: FieldInputTemplateBuilder< const buildVAEModelFieldInputTemplate: FieldInputTemplateBuilder< VAEModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: VAEModelFieldInputTemplate = { ...baseField, - type: { name: 'VAEModelField', isCollection, isPolymorphic }, + type: { + name: 'VAEModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -192,10 +224,14 @@ const buildVAEModelFieldInputTemplate: FieldInputTemplateBuilder< const buildLoRAModelFieldInputTemplate: FieldInputTemplateBuilder< LoRAModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: LoRAModelFieldInputTemplate = { ...baseField, - type: { name: 'LoRAModelField', isCollection, isPolymorphic }, + type: { + name: 'LoRAModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -204,10 +240,14 @@ const buildLoRAModelFieldInputTemplate: FieldInputTemplateBuilder< const buildControlNetModelFieldInputTemplate: FieldInputTemplateBuilder< ControlNetModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: ControlNetModelFieldInputTemplate = { ...baseField, - type: { name: 'ControlNetModelField', isCollection, isPolymorphic }, + type: { + name: 'ControlNetModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -216,10 +256,14 @@ const buildControlNetModelFieldInputTemplate: FieldInputTemplateBuilder< const buildIPAdapterModelFieldInputTemplate: FieldInputTemplateBuilder< IPAdapterModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: IPAdapterModelFieldInputTemplate = { ...baseField, - type: { name: 'IPAdapterModelField', isCollection, isPolymorphic }, + type: { + name: 'IPAdapterModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -228,10 +272,14 @@ const buildIPAdapterModelFieldInputTemplate: FieldInputTemplateBuilder< const buildT2IAdapterModelFieldInputTemplate: FieldInputTemplateBuilder< T2IAdapterModelFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: T2IAdapterModelFieldInputTemplate = { ...baseField, - type: { name: 'T2IAdapterModelField', isCollection, isPolymorphic }, + type: { + name: 'T2IAdapterModelField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -240,10 +288,14 @@ const buildT2IAdapterModelFieldInputTemplate: FieldInputTemplateBuilder< const buildBoardFieldInputTemplate: FieldInputTemplateBuilder< BoardFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: BoardFieldInputTemplate = { ...baseField, - type: { name: 'BoardField', isCollection, isPolymorphic }, + type: { + name: 'BoardField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -252,10 +304,14 @@ const buildBoardFieldInputTemplate: FieldInputTemplateBuilder< const buildImageFieldInputTemplate: FieldInputTemplateBuilder< ImageFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: ImageFieldInputTemplate = { ...baseField, - type: { name: 'ImageField', isCollection, isPolymorphic }, + type: { + name: 'ImageField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? undefined, }; @@ -264,11 +320,15 @@ const buildImageFieldInputTemplate: FieldInputTemplateBuilder< const buildEnumFieldInputTemplate: FieldInputTemplateBuilder< EnumFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const options = schemaObject.enum ?? []; const template: EnumFieldInputTemplate = { ...baseField, - type: { name: 'EnumField', isCollection, isPolymorphic }, + type: { + name: 'EnumField', + isCollection, + isCollectionOrScalar, + }, options, ui_choice_labels: schemaObject.ui_choice_labels, default: schemaObject.default ?? options[0], @@ -279,10 +339,14 @@ const buildEnumFieldInputTemplate: FieldInputTemplateBuilder< const buildColorFieldInputTemplate: FieldInputTemplateBuilder< ColorFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: ColorFieldInputTemplate = { ...baseField, - type: { name: 'ColorField', isCollection, isPolymorphic }, + type: { + name: 'ColorField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? { r: 127, g: 127, b: 127, a: 255 }, }; @@ -291,10 +355,14 @@ const buildColorFieldInputTemplate: FieldInputTemplateBuilder< const buildSchedulerFieldInputTemplate: FieldInputTemplateBuilder< SchedulerFieldInputTemplate -> = ({ schemaObject, baseField, isCollection, isPolymorphic }) => { +> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => { const template: SchedulerFieldInputTemplate = { ...baseField, - type: { name: 'SchedulerField', isCollection, isPolymorphic }, + type: { + name: 'SchedulerField', + isCollection, + isCollectionOrScalar, + }, default: schemaObject.default ?? 'euler', }; @@ -361,7 +429,7 @@ export const buildFieldInputTemplate = ( schemaObject: fieldSchema, baseField, isCollection: fieldType.isCollection, - isPolymorphic: fieldType.isPolymorphic, + isCollectionOrScalar: fieldType.isCollectionOrScalar, }); } diff --git a/invokeai/frontend/web/src/features/nodes/util/schema/parseFieldType.ts b/invokeai/frontend/web/src/features/nodes/util/schema/parseFieldType.ts index 2314faaa39..634dfcb980 100644 --- a/invokeai/frontend/web/src/features/nodes/util/schema/parseFieldType.ts +++ b/invokeai/frontend/web/src/features/nodes/util/schema/parseFieldType.ts @@ -56,7 +56,7 @@ export const parseFieldType = ( return { name: ui_type, isCollection: isCollectionFieldType(ui_type), - isPolymorphic: false, + isCollectionOrScalar: false, }; } } @@ -77,7 +77,7 @@ export const parseFieldType = ( return { name, isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }; } } else if (schemaObject.anyOf) { @@ -103,14 +103,14 @@ export const parseFieldType = ( return { name, isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }; } else if (isSchemaObject(filteredAnyOf[0])) { return parseFieldType(filteredAnyOf[0]); } } /** - * Handle Polymorphic inputs, eg string | string[]. In OpenAPI, this is: + * Handle CollectionOrScalar inputs, eg string | string[]. In OpenAPI, this is: * - an `anyOf` with two items * - one is an `ArraySchemaObject` with a single `SchemaObject or ReferenceObject` of type T in its `items` * - the other is a `SchemaObject` or `ReferenceObject` of type T @@ -163,7 +163,7 @@ export const parseFieldType = ( return { name: OPENAPI_TO_FIELD_TYPE_MAP[firstType] ?? firstType, isCollection: false, - isPolymorphic: true, // <-- don't forget, polymorphic! + isCollectionOrScalar: true, // <-- don't forget, CollectionOrScalar type! }; } @@ -175,7 +175,11 @@ export const parseFieldType = ( ); } } else if (schemaObject.enum) { - return { name: 'EnumField', isCollection: false, isPolymorphic: false }; + return { + name: 'EnumField', + isCollection: false, + isCollectionOrScalar: false, + }; } else if (schemaObject.type) { if (schemaObject.type === 'array') { // We need to get the type of the items @@ -201,7 +205,7 @@ export const parseFieldType = ( return { name, isCollection: true, // <-- don't forget, collection! - isPolymorphic: false, + isCollectionOrScalar: false, }; } @@ -215,7 +219,7 @@ export const parseFieldType = ( return { name, isCollection: true, // <-- don't forget, collection! - isPolymorphic: false, + isCollectionOrScalar: false, }; } else if (!isArray(schemaObject.type)) { // This is an OpenAPI primitive - 'null', 'object', 'array', 'integer', 'number', 'string', 'boolean' @@ -231,7 +235,7 @@ export const parseFieldType = ( return { name, isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }; } } @@ -245,7 +249,7 @@ export const parseFieldType = ( return { name, isCollection: false, - isPolymorphic: false, + isCollectionOrScalar: false, }; } throw new FieldTypeParseError(t('nodes.unableToParseFieldType'));