mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix enum parsing for optional enums
Closes #5121 - Parse `anyOf` for enums (present when they are optional) - Consolidate `FieldTypeParseError` and `UnsupportedFieldTypeError` into `FieldParseError` (there was no difference in handling and it simplifies things a bit)
This commit is contained in:
parent
3e01c396e1
commit
a6d4e4ed57
@ -978,6 +978,7 @@
|
|||||||
"unsupportedAnyOfLength": "too many union members ({{count}})",
|
"unsupportedAnyOfLength": "too many union members ({{count}})",
|
||||||
"unsupportedMismatchedUnion": "mismatched CollectionOrScalar type with base types {{firstType}} and {{secondType}}",
|
"unsupportedMismatchedUnion": "mismatched CollectionOrScalar type with base types {{firstType}} and {{secondType}}",
|
||||||
"unableToParseFieldType": "unable to parse field type",
|
"unableToParseFieldType": "unable to parse field type",
|
||||||
|
"unableToExtractEnumOptions": "unable to extract enum options",
|
||||||
"uNetField": "UNet",
|
"uNetField": "UNet",
|
||||||
"uNetFieldDescription": "UNet submodel.",
|
"uNetFieldDescription": "UNet submodel.",
|
||||||
"unhandledInputProperty": "Unhandled input property",
|
"unhandledInputProperty": "Unhandled input property",
|
||||||
|
@ -43,10 +43,10 @@ export class NodeUpdateError extends Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FieldTypeParseError
|
* FieldParseError
|
||||||
* Raised when a field cannot be parsed from a field schema.
|
* Raised when a field cannot be parsed from a field schema.
|
||||||
*/
|
*/
|
||||||
export class FieldTypeParseError extends Error {
|
export class FieldParseError extends Error {
|
||||||
/**
|
/**
|
||||||
* Create FieldTypeParseError
|
* Create FieldTypeParseError
|
||||||
* @param {String} message
|
* @param {String} message
|
||||||
@ -56,18 +56,3 @@ export class FieldTypeParseError extends Error {
|
|||||||
this.name = this.constructor.name;
|
this.name = this.constructor.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* UnsupportedFieldTypeError
|
|
||||||
* Raised when an unsupported field type is parsed.
|
|
||||||
*/
|
|
||||||
export class UnsupportedFieldTypeError extends Error {
|
|
||||||
/**
|
|
||||||
* Create UnsupportedFieldTypeError
|
|
||||||
* @param {String} message
|
|
||||||
*/
|
|
||||||
constructor(message: string) {
|
|
||||||
super(message);
|
|
||||||
this.name = this.constructor.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -23,7 +23,12 @@ import {
|
|||||||
VAEModelFieldInputTemplate,
|
VAEModelFieldInputTemplate,
|
||||||
isStatefulFieldType,
|
isStatefulFieldType,
|
||||||
} from 'features/nodes/types/field';
|
} from 'features/nodes/types/field';
|
||||||
import { InvocationFieldSchema } from 'features/nodes/types/openapi';
|
import {
|
||||||
|
InvocationFieldSchema,
|
||||||
|
isSchemaObject,
|
||||||
|
} from 'features/nodes/types/openapi';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { FieldParseError } from 'features/nodes/types/error';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
type FieldInputTemplateBuilder<T extends FieldInputTemplate = any> = // valid `any`!
|
type FieldInputTemplateBuilder<T extends FieldInputTemplate = any> = // valid `any`!
|
||||||
@ -321,7 +326,28 @@ const buildImageFieldInputTemplate: FieldInputTemplateBuilder<
|
|||||||
const buildEnumFieldInputTemplate: FieldInputTemplateBuilder<
|
const buildEnumFieldInputTemplate: FieldInputTemplateBuilder<
|
||||||
EnumFieldInputTemplate
|
EnumFieldInputTemplate
|
||||||
> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => {
|
> = ({ schemaObject, baseField, isCollection, isCollectionOrScalar }) => {
|
||||||
const options = schemaObject.enum ?? [];
|
let options: EnumFieldInputTemplate['options'] = [];
|
||||||
|
if (schemaObject.anyOf) {
|
||||||
|
const filteredAnyOf = schemaObject.anyOf.filter((i) => {
|
||||||
|
if (isSchemaObject(i)) {
|
||||||
|
if (i.type === 'null') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
const firstAnyOf = filteredAnyOf[0];
|
||||||
|
if (filteredAnyOf.length !== 1 || !isSchemaObject(firstAnyOf)) {
|
||||||
|
options = [];
|
||||||
|
} else {
|
||||||
|
options = firstAnyOf.enum ?? [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
options = schemaObject.enum ?? [];
|
||||||
|
}
|
||||||
|
if (options.length === 0) {
|
||||||
|
throw new FieldParseError(t('nodes.unableToExtractEnumOptions'));
|
||||||
|
}
|
||||||
const template: EnumFieldInputTemplate = {
|
const template: EnumFieldInputTemplate = {
|
||||||
...baseField,
|
...baseField,
|
||||||
type: {
|
type: {
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import { t } from 'i18next';
|
import { FieldParseError } from 'features/nodes/types/error';
|
||||||
import { isArray } from 'lodash-es';
|
|
||||||
import { OpenAPIV3_1 } from 'openapi-types';
|
|
||||||
import {
|
|
||||||
FieldTypeParseError,
|
|
||||||
UnsupportedFieldTypeError,
|
|
||||||
} from 'features/nodes/types/error';
|
|
||||||
import { FieldType } from 'features/nodes/types/field';
|
import { FieldType } from 'features/nodes/types/field';
|
||||||
import {
|
import {
|
||||||
OpenAPIV3_1SchemaOrRef,
|
OpenAPIV3_1SchemaOrRef,
|
||||||
@ -14,6 +8,9 @@ import {
|
|||||||
isRefObject,
|
isRefObject,
|
||||||
isSchemaObject,
|
isSchemaObject,
|
||||||
} from 'features/nodes/types/openapi';
|
} from 'features/nodes/types/openapi';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { isArray } from 'lodash-es';
|
||||||
|
import { OpenAPIV3_1 } from 'openapi-types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms an invocation output ref object to field type.
|
* Transforms an invocation output ref object to field type.
|
||||||
@ -70,7 +67,7 @@ export const parseFieldType = (
|
|||||||
// This is a single ref type
|
// This is a single ref type
|
||||||
const name = refObjectToSchemaName(allOf[0]);
|
const name = refObjectToSchemaName(allOf[0]);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new FieldTypeParseError(
|
throw new FieldParseError(
|
||||||
t('nodes.unableToExtractSchemaNameFromRef')
|
t('nodes.unableToExtractSchemaNameFromRef')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -95,7 +92,7 @@ export const parseFieldType = (
|
|||||||
if (isRefObject(filteredAnyOf[0])) {
|
if (isRefObject(filteredAnyOf[0])) {
|
||||||
const name = refObjectToSchemaName(filteredAnyOf[0]);
|
const name = refObjectToSchemaName(filteredAnyOf[0]);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new FieldTypeParseError(
|
throw new FieldParseError(
|
||||||
t('nodes.unableToExtractSchemaNameFromRef')
|
t('nodes.unableToExtractSchemaNameFromRef')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -120,7 +117,7 @@ export const parseFieldType = (
|
|||||||
|
|
||||||
if (filteredAnyOf.length !== 2) {
|
if (filteredAnyOf.length !== 2) {
|
||||||
// This is a union of more than 2 types, which we don't support
|
// This is a union of more than 2 types, which we don't support
|
||||||
throw new UnsupportedFieldTypeError(
|
throw new FieldParseError(
|
||||||
t('nodes.unsupportedAnyOfLength', {
|
t('nodes.unsupportedAnyOfLength', {
|
||||||
count: filteredAnyOf.length,
|
count: filteredAnyOf.length,
|
||||||
})
|
})
|
||||||
@ -167,7 +164,7 @@ export const parseFieldType = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new UnsupportedFieldTypeError(
|
throw new FieldParseError(
|
||||||
t('nodes.unsupportedMismatchedUnion', {
|
t('nodes.unsupportedMismatchedUnion', {
|
||||||
firstType,
|
firstType,
|
||||||
secondType,
|
secondType,
|
||||||
@ -186,7 +183,7 @@ export const parseFieldType = (
|
|||||||
if (isSchemaObject(schemaObject.items)) {
|
if (isSchemaObject(schemaObject.items)) {
|
||||||
const itemType = schemaObject.items.type;
|
const itemType = schemaObject.items.type;
|
||||||
if (!itemType || isArray(itemType)) {
|
if (!itemType || isArray(itemType)) {
|
||||||
throw new UnsupportedFieldTypeError(
|
throw new FieldParseError(
|
||||||
t('nodes.unsupportedArrayItemType', {
|
t('nodes.unsupportedArrayItemType', {
|
||||||
type: itemType,
|
type: itemType,
|
||||||
})
|
})
|
||||||
@ -196,7 +193,7 @@ export const parseFieldType = (
|
|||||||
const name = OPENAPI_TO_FIELD_TYPE_MAP[itemType];
|
const name = OPENAPI_TO_FIELD_TYPE_MAP[itemType];
|
||||||
if (!name) {
|
if (!name) {
|
||||||
// it's 'null', 'object', or 'array' - skip
|
// it's 'null', 'object', or 'array' - skip
|
||||||
throw new UnsupportedFieldTypeError(
|
throw new FieldParseError(
|
||||||
t('nodes.unsupportedArrayItemType', {
|
t('nodes.unsupportedArrayItemType', {
|
||||||
type: itemType,
|
type: itemType,
|
||||||
})
|
})
|
||||||
@ -212,7 +209,7 @@ export const parseFieldType = (
|
|||||||
// This is a ref object, extract the type name
|
// This is a ref object, extract the type name
|
||||||
const name = refObjectToSchemaName(schemaObject.items);
|
const name = refObjectToSchemaName(schemaObject.items);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new FieldTypeParseError(
|
throw new FieldParseError(
|
||||||
t('nodes.unableToExtractSchemaNameFromRef')
|
t('nodes.unableToExtractSchemaNameFromRef')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -226,7 +223,7 @@ export const parseFieldType = (
|
|||||||
const name = OPENAPI_TO_FIELD_TYPE_MAP[schemaObject.type];
|
const name = OPENAPI_TO_FIELD_TYPE_MAP[schemaObject.type];
|
||||||
if (!name) {
|
if (!name) {
|
||||||
// it's 'null', 'object', or 'array' - skip
|
// it's 'null', 'object', or 'array' - skip
|
||||||
throw new UnsupportedFieldTypeError(
|
throw new FieldParseError(
|
||||||
t('nodes.unsupportedArrayItemType', {
|
t('nodes.unsupportedArrayItemType', {
|
||||||
type: schemaObject.type,
|
type: schemaObject.type,
|
||||||
})
|
})
|
||||||
@ -242,9 +239,7 @@ export const parseFieldType = (
|
|||||||
} else if (isRefObject(schemaObject)) {
|
} else if (isRefObject(schemaObject)) {
|
||||||
const name = refObjectToSchemaName(schemaObject);
|
const name = refObjectToSchemaName(schemaObject);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new FieldTypeParseError(
|
throw new FieldParseError(t('nodes.unableToExtractSchemaNameFromRef'));
|
||||||
t('nodes.unableToExtractSchemaNameFromRef')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
@ -252,5 +247,5 @@ export const parseFieldType = (
|
|||||||
isCollectionOrScalar: false,
|
isCollectionOrScalar: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
throw new FieldTypeParseError(t('nodes.unableToParseFieldType'));
|
throw new FieldParseError(t('nodes.unableToParseFieldType'));
|
||||||
};
|
};
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import { logger } from 'app/logging/logger';
|
import { logger } from 'app/logging/logger';
|
||||||
import { parseify } from 'common/util/serialize';
|
import { parseify } from 'common/util/serialize';
|
||||||
import { t } from 'i18next';
|
import { FieldParseError } from 'features/nodes/types/error';
|
||||||
import { reduce } from 'lodash-es';
|
|
||||||
import { OpenAPIV3_1 } from 'openapi-types';
|
|
||||||
import {
|
|
||||||
FieldTypeParseError,
|
|
||||||
UnsupportedFieldTypeError,
|
|
||||||
} from 'features/nodes/types/error';
|
|
||||||
import {
|
import {
|
||||||
FieldInputTemplate,
|
FieldInputTemplate,
|
||||||
FieldOutputTemplate,
|
FieldOutputTemplate,
|
||||||
@ -18,6 +12,9 @@ import {
|
|||||||
isInvocationOutputSchemaObject,
|
isInvocationOutputSchemaObject,
|
||||||
isInvocationSchemaObject,
|
isInvocationSchemaObject,
|
||||||
} from 'features/nodes/types/openapi';
|
} from 'features/nodes/types/openapi';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { reduce } from 'lodash-es';
|
||||||
|
import { OpenAPIV3_1 } from 'openapi-types';
|
||||||
import { buildFieldInputTemplate } from './buildFieldInputTemplate';
|
import { buildFieldInputTemplate } from './buildFieldInputTemplate';
|
||||||
import { buildFieldOutputTemplate } from './buildFieldOutputTemplate';
|
import { buildFieldOutputTemplate } from './buildFieldOutputTemplate';
|
||||||
import { parseFieldType } from './parseFieldType';
|
import { parseFieldType } from './parseFieldType';
|
||||||
@ -133,10 +130,7 @@ export const parseSchema = (
|
|||||||
|
|
||||||
inputsAccumulator[propertyName] = fieldInputTemplate;
|
inputsAccumulator[propertyName] = fieldInputTemplate;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (
|
if (e instanceof FieldParseError) {
|
||||||
e instanceof FieldTypeParseError ||
|
|
||||||
e instanceof UnsupportedFieldTypeError
|
|
||||||
) {
|
|
||||||
logger('nodes').warn(
|
logger('nodes').warn(
|
||||||
{
|
{
|
||||||
node: type,
|
node: type,
|
||||||
@ -225,10 +219,7 @@ export const parseSchema = (
|
|||||||
|
|
||||||
outputsAccumulator[propertyName] = fieldOutputTemplate;
|
outputsAccumulator[propertyName] = fieldOutputTemplate;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (
|
if (e instanceof FieldParseError) {
|
||||||
e instanceof FieldTypeParseError ||
|
|
||||||
e instanceof UnsupportedFieldTypeError
|
|
||||||
) {
|
|
||||||
logger('nodes').warn(
|
logger('nodes').warn(
|
||||||
{
|
{
|
||||||
node: type,
|
node: type,
|
||||||
|
Loading…
Reference in New Issue
Block a user