( property: S.AST.PropertySignature )
| 262 | ) |
| 263 | |
| 264 | function buildFieldInfo( |
| 265 | property: S.AST.PropertySignature |
| 266 | ): FieldInfo<any> { |
| 267 | const propertyKey = property.name |
| 268 | const schema = S.make<S.Codec<unknown>>(property.type) |
| 269 | const metadata = getMetadataFromSchema(property.type) |
| 270 | const parse = S.decodeUnknownExit(schema) |
| 271 | |
| 272 | const nullableOrUndefined = S.AST.isUnion(property.type) |
| 273 | && (property.type.types.includes(S.Null.ast) || property.type.types.some((_) => _._tag === "Undefined")) |
| 274 | const realSelf = nullableOrUndefined && S.AST.isUnion(property.type) |
| 275 | ? property.type.types.find((_) => _ !== S.Null.ast && _._tag !== "Undefined")! |
| 276 | : property.type |
| 277 | const id = S.AST.resolveIdentifier(property.type) |
| 278 | const id2 = S.AST.resolveIdentifier(realSelf) |
| 279 | |
| 280 | function renderError(e: S.SchemaError, v: unknown) { |
| 281 | const err = e.toString() |
| 282 | |
| 283 | const custom = customSchemaErrors.value.get(property.type) |
| 284 | ?? customSchemaErrors.value.get(realSelf) |
| 285 | ?? (id ? customSchemaErrors.value.get(id) : undefined) |
| 286 | ?? (id2 ? customSchemaErrors.value.get(id2) : undefined) |
| 287 | |
| 288 | if (custom) { |
| 289 | return custom(err, e, v) |
| 290 | } |
| 291 | |
| 292 | // parse specific error types for better translation support. |
| 293 | // beta.107 formatters often omit ", actual/got <value>" from the issue string; |
| 294 | // fall back to the rejected input `v` when the regex has no capture. |
| 295 | const integerMatch = err.match(/Expected.*integer(?:.*(?:actual|got)\s+([^)\s]+))?/i) |
| 296 | if (integerMatch) { |
| 297 | return translate.value( |
| 298 | { defaultMessage: "Expected an integer, actual {actualValue}", id: "validation.integer.expected" }, |
| 299 | { actualValue: integerMatch[1] ?? String(v) } |
| 300 | ) |
| 301 | } |
| 302 | |
| 303 | const numberMatch = err.match(/Expected.*number(?:.*(?:actual|got)\s+([^)\s]+))?/i) |
| 304 | if (numberMatch) { |
| 305 | return translate.value( |
| 306 | { defaultMessage: "Expected a number, actual {actualValue}", id: "validation.number.expected" }, |
| 307 | { actualValue: numberMatch[1] ?? String(v) } |
| 308 | ) |
| 309 | } |
| 310 | |
| 311 | // fallback to generic error message |
| 312 | return translate.value( |
| 313 | { defaultMessage: "The entered value is not a valid {type}: {message}", id: "validation.not_a_valid" }, |
| 314 | { |
| 315 | type: translate.value({ |
| 316 | defaultMessage: capitalize(propertyKey.toString()), |
| 317 | id: `fieldNames.${String(propertyKey)}` |
| 318 | }), |
| 319 | // TODO: not translated yet |
| 320 | message: metadata.description ? "expected " + metadata.description : err.slice(err.indexOf("Expected")) |
| 321 | } |
no test coverage detected
searching dependent graphs…