import { PNumberInput, PCombobox, PTextarea, PDateInput } from '@prefecthq/prefect-design' import { format, isValid, parseISO } from 'date-fns' import DateInput from '@/components/DateInput.vue' import JsonInput from '@/components/JsonInput.vue' import { InvalidSchemaValueError } from '@/models' import { SchemaPropertyService } from '@/services/schemas/properties/SchemaPropertyService' import { SchemaPropertyComponentWithProps } from '@/services/schemas/utilities' import { SchemaPropertyInputAttrs, SchemaValue } from '@/types/schemas' import { isDate } from '@/utilities/dates' import { stringifyUnknownJson } from '@/utilities/stringifyUnknownJson' import { isString } from '@/utilities/strings' import { isEmail, isJson, ValidationMethodFactory } from '@/utilities/validation' export class SchemaPropertyString extends SchemaPropertyService { protected override get attrs(): SchemaPropertyInputAttrs { if (this.componentIs(PTextarea)) { return { rows: 1, } } return {} } protected override get component(): SchemaPropertyComponentWithProps { if (this.has('enum')) { return this.withProps(PCombobox, { options: this.getSelectOptions(), }) } switch (this.property.format) { case 'date': // date uses PDateInput because timezone SHOULD NOT be factored into a date string return this.withProps(PDateInput) case 'date-time': // date-time uses DateInput because timezone SHOULD be factored into a date-time string return this.withProps(DateInput, { showTime: true }) case 'json-string': return this.withProps(JsonInput) case 'time-delta': return this.withProps(PNumberInput) default: return this.withProps(PTextarea) } } protected override get default(): SchemaValue { if (this.componentIs(PCombobox)) { return this.property.default ?? null } if (this.componentIs(DateInput) || this.componentIs(PDateInput)) { return isString(this.property.default) ? parseISO(this.property.default) : null } if (this.componentIs(JsonInput)) { return stringifyUnknownJson(this.property.default) ?? '' } if (this.componentIs(PNumberInput)) { return this.property.default ?? null } return this.property.default ?? '' } protected get validators(): ValidationMethodFactory[] { const { format } = this.property if (format === 'email') { return [isEmail] } if (format === 'json-string') { return [isJson] } return [] } protected override request(value: SchemaValue): unknown { switch (this.property.format) { case 'date': return this.requestDateValue(value) case 'date-time': return this.requestDateTimeValue(value) default: return value } } protected override response(value: SchemaValue): unknown { if (!isString(value)) { throw new InvalidSchemaValueError() } switch (this.property.format) { case 'date': return this.responseDateValue(value) case 'date-time': return this.responseDateTimeValue(value) default: return value } } private requestDateValue(value: SchemaValue): SchemaValue { if (isDate(value)) { return format(value, 'yyyy-MM-dd') } return value } private responseDateValue(value: SchemaValue): SchemaValue { if (!isString(value)) { throw new InvalidSchemaValueError() } const date = parseISO(value) if (!isValid(date)) { return this.invalid() } return date } private requestDateTimeValue(value: SchemaValue): SchemaValue { if (isDate(value)) { return value.toISOString() } return value } private responseDateTimeValue(value: SchemaValue): Date { if (!isString(value)) { throw new InvalidSchemaValueError() } const date = parseISO(value) if (!isValid(date)) { this.invalid() } return date } }