(sectionId, field, value, mark = "draft")
| 474 | } |
| 475 | |
| 476 | function validateFieldValue(sectionId, field, value, mark = "draft") { |
| 477 | const schema = getFieldSchemaForSection(sectionId, field); |
| 478 | if (!schema) { |
| 479 | return; |
| 480 | } |
| 481 | const text = safeString(value, ""); |
| 482 | const trimmed = text.trim(); |
| 483 | const required = Boolean(schema.required); |
| 484 | if (required && mark === "final" && !trimmed) { |
| 485 | throw new CanvasError("required_field_missing", `"${field}" is required for ${sectionId}.`); |
| 486 | } |
| 487 | if (!trimmed) { |
| 488 | return; |
| 489 | } |
| 490 | if (isSamplePlaceholder(trimmed)) { |
| 491 | return; |
| 492 | } |
| 493 | const maxLength = Number.isInteger(schema.maxLength) ? schema.maxLength : null; |
| 494 | if (maxLength && text.length > maxLength) { |
| 495 | throw new CanvasError("max_length_exceeded", `"${field}" exceeds max length (${maxLength}).`); |
| 496 | } |
| 497 | const type = safeString(schema.type, "text"); |
| 498 | if (type === "url" && !isValidUrl(trimmed)) { |
| 499 | throw new CanvasError("invalid_url", `"${field}" must be a valid http/https URL.`); |
| 500 | } |
| 501 | if (type === "email" && !isValidEmail(trimmed)) { |
| 502 | throw new CanvasError("invalid_email", `"${field}" must be a valid email address.`); |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | function applyTemplatePack(packId, author = "agent") { |
| 507 | const { id, pack } = getTemplatePackOrThrow(packId); |
no test coverage detected