@prefecthq/prefect-ui-library
Version:
This library is the Vue and Typescript component library for [Prefect 2](https://github.com/PrefectHQ/prefect) and [Prefect Cloud 2](https://www.prefect.io/cloud/). _The components and utilities in this project are not meant to be used independently_.
152 lines (123 loc) • 4.03 kB
text/typescript
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
}
}