UNPKG

@lucidcms/core

Version:

The core of the Lucid CMS. It's responsible for spinning up the API and serving the CMS.

1,575 lines (1,552 loc) 44.7 kB
import { create_cdn_url_default, formatters_default, objectify_translations_default } from "./chunk-URI3PAN7.js"; import { constants_default, translations_default } from "./chunk-ZMWDUGJW.js"; // src/libs/custom-fields/fields/checkbox.ts import z from "zod"; // src/libs/custom-fields/utils/zod-safe-parse.ts import { fromError } from "zod-validation-error"; var zodSafeParse = (value, schema) => { const response = schema.safeParse(value); if (response?.success) { return { valid: true }; } const errorMessage = fromError(response.error).message.replace( "Validation error: ", "" ); return { valid: false, message: errorMessage ?? translations_default("an_unknown_error_occurred_validating_the_field") }; }; var zod_safe_parse_default = zodSafeParse; // src/libs/custom-fields/custom-field.ts var CustomField = class { repeater = null; // Methods validate(props) { if (this.config.type === "tab") return { valid: true }; const fieldTypeRes = this.fieldTypeValidation(props.type); if (fieldTypeRes.valid === false) return fieldTypeRes; const requiredRes = this.requiredCheck(props.value); if (!requiredRes.valid) return requiredRes; const zodRes = this.zodCheck(props.value); if (!zodRes.valid) return zodRes; if (props.value === null || props.value === void 0) { return { valid: true }; } return this.cfSpecificValidation(props.value, props.relationData); } fieldTypeValidation(type) { if (this.errors.fieldType.condition?.(type)) { return { valid: false, message: translations_default("field_type_mismatch", { received: type, expected: this.config.type }) }; } return { valid: true }; } requiredCheck(value) { if (this.config.type === "tab") return { valid: true }; if (this.config.type === "repeater") return { valid: true }; if (this.config.validation?.required === true && this.errors.required.condition?.(value)) { return { valid: false, message: this.errors.required.message }; } return { valid: true }; } zodCheck(value) { if (this.config.type === "tab") return { valid: true }; if (this.config.type === "repeater") return { valid: true }; if (this.config.type === "media") return { valid: true }; if (this.config.type === "checkbox") return { valid: true }; if (this.config.type === "select") return { valid: true }; if (this.config.type === "colour") return { valid: true }; if (this.config.type === "link") return { valid: true }; if (this.config.type === "user") return { valid: true }; if (this.config.type === "wysiwyg") return { valid: true }; if (this.config.type === "document") return { valid: true }; if (!this.config.validation?.zod) return { valid: true }; return zod_safe_parse_default(value, this.config.validation?.zod); } // Getters get errors() { return { fieldType: { condition: (value) => value !== this.type, message: translations_default("field_type_mismatch", { received: "unknown", expected: this.config.type }) }, required: { condition: (value) => value === void 0 || value === null || value === "", message: translations_default("generic_field_required") }, zod: { message: translations_default("generic_field_invalid") } }; } }; var custom_field_default = CustomField; // src/libs/custom-fields/fields/checkbox.ts import merge from "lodash.merge"; // src/libs/custom-fields/utils/key-to-title.ts var keyToTitle = (key) => { if (typeof key !== "string") return key; const title = key.split(/[-_]/g).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" "); return title; }; var key_to_title_default = keyToTitle; // src/libs/custom-fields/fields/checkbox.ts var CheckboxCustomField = class extends custom_field_default { type = "checkbox"; column = "bool_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, true: this.props?.details?.true, false: this.props?.details?.false }, config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default ?? 0, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.bool_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { let value = props.item.value; if (typeof value === "string") { value = value === "true" ? 1 : 0; } else if (typeof value === "boolean") { value = value ? 1 : 0; } else if (typeof value === "number") { value = value === 1 ? 1 : 0; } else { value = void 0; } return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: null, intValue: null, boolValue: value, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z.union([z.literal(1), z.literal(0), z.boolean()]); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; return { valid: true }; } // Getters get errors() { return merge(super.errors, { required: { condition: (value) => value === void 0 || value === null || value === 0, message: translations_default("checkbox_field_required") } }); } }; var checkbox_default = CheckboxCustomField; // src/libs/custom-fields/fields/colour.ts import z2 from "zod"; var ColourCustomField = class extends custom_field_default { type = "colour"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary }, presets: this.props?.presets ?? [], config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default ?? "", isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.text_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: props.item.value, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z2.string(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; return { valid: true }; } }; var colour_default = ColourCustomField; // src/libs/custom-fields/fields/datetime.ts import z3 from "zod"; import { isValid } from "date-fns"; var DatetimeCustomField = class extends custom_field_default { type = "datetime"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default ?? "", isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.text_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: props.item.value, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z3.union([z3.string(), z3.number(), z3.date()]); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; const date = new Date(value); if (!isValid(date)) { return { valid: false, message: translations_default("field_date_invalid") }; } return { valid: true }; } }; var datetime_default = DatetimeCustomField; // src/libs/custom-fields/fields/json.ts import z4 from "zod"; var JsonCustomField = class extends custom_field_default { type = "json"; column = "json_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default || {}, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: formatters_default.parseJSON(props.data.json_value) ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: null, intValue: null, boolValue: null, jsonValue: formatters_default.stringifyJSON(props.item.value), mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z4.record(z4.unknown()); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; return { valid: true }; } }; var json_default = JsonCustomField; // src/libs/custom-fields/fields/link.ts import z5 from "zod"; var LinkCustomField = class extends custom_field_default { type = "link"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default ?? { url: null, label: null, target: null }, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { const linkVal = formatters_default.parseJSON(props.data.json_value); return { value: { url: linkVal?.url ?? this.config.config.default.url ?? null, label: linkVal?.label ?? this.config.config.default.label ?? null, target: linkVal?.target ?? this.config.config.default.target ?? null }, meta: null }; } getInsertField(props) { const value = props.item.value; return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: value ? value.url : null, intValue: null, boolValue: null, jsonValue: value ? formatters_default.stringifyJSON({ target: value.target, label: value.label }) : null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z5.object({ url: z5.string().optional().nullable(), target: z5.string().optional().nullable(), label: z5.string().optional().nullable() }); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; const val = value; if (val.target && !constants_default.customFields.link.targets.includes(val.target)) { return { valid: false, message: translations_default("field_link_target_error_message", { valid: constants_default.customFields.link.targets.join(", ") }) }; } return { valid: true }; } }; var link_default = LinkCustomField; // src/libs/custom-fields/fields/media.ts import z6 from "zod"; var MediaCustomField = class extends custom_field_default { type = "media"; column = "media_id"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary }, config: { useTranslations: this.props?.config?.useTranslations ?? false, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data?.media_id ?? null, meta: { id: props.data?.media_id ?? null, url: create_cdn_url_default(props.formatMeta.host, props.data?.media_key ?? ""), key: props.data?.media_key ?? null, mimeType: props.data?.media_mime_type ?? null, extension: props.data?.media_file_extension ?? null, fileSize: props.data?.media_file_size ?? null, width: props.data?.media_width ?? null, height: props.data?.media_height ?? null, blurHash: props.data?.media_blur_hash ?? null, averageColour: props.data?.media_average_colour ?? null, isDark: props.data?.media_is_dark ?? null, isLight: props.data?.media_is_light ?? null, title: objectify_translations_default( props.data?.media_title_translations || [], props.formatMeta.localisation.locales ), alt: objectify_translations_default( props.data?.media_alt_translations || [], props.formatMeta.localisation.locales ), type: props.data?.media_type ?? null } }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: null, intValue: null, boolValue: null, jsonValue: null, mediaId: props.item.value, userId: null }; } cfSpecificValidation(value, relationData) { const valueSchema = z6.number(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; const findMedia = relationData?.find((m) => m.id === value); if (findMedia === void 0) { return { valid: false, message: translations_default("field_media_not_found") }; } if (this.config.validation?.extensions?.length) { const extension = findMedia.file_extension; if (!this.config.validation.extensions.includes(extension)) { return { valid: false, message: translations_default("field_media_extension", { extensions: this.config.validation.extensions.join(", ") }) }; } } if (this.config.validation?.type) { const type = findMedia.type; if (!type) { return { valid: false, message: translations_default("field_media_doenst_have_type") }; } if (this.config.validation.type !== type) { return { valid: false, message: translations_default("field_media_type", { type: this.config.validation.type }) }; } } if (this.config.validation?.width && findMedia.type === "image") { const width = findMedia.width; if (!width) { return { valid: false, message: translations_default("field_media_doenst_have_width") }; } if (this.config.validation.width.min && width < this.config.validation.width.min) { return { valid: false, message: translations_default("field_media_min_width", { min: this.config.validation.width.min }) }; } if (this.config.validation.width.max && width > this.config.validation.width.max) { return { valid: false, message: translations_default("field_media_max_width", { max: this.config.validation.width.max }) }; } } if (this.config.validation?.height && findMedia.type === "image") { const height = findMedia.height; if (!height) { return { valid: false, message: translations_default("field_media_doenst_have_height") }; } if (this.config.validation.height.min && height < this.config.validation.height.min) { return { valid: false, message: translations_default("field_media_min_height", { min: this.config.validation.height.min }) }; } if (this.config.validation.height.max && height > this.config.validation.height.max) { return { valid: false, message: translations_default("field_media_max_height", { max: this.config.validation.height.max }) }; } } return { valid: true }; } }; var media_default = MediaCustomField; // src/libs/custom-fields/fields/number.ts import z7 from "zod"; var NumberCustomField = class extends custom_field_default { type = "number"; column = "int_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.int_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: null, intValue: props.item.value, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z7.number(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; return { valid: true }; } }; var number_default = NumberCustomField; // src/libs/custom-fields/fields/repeater.ts var RepeaterCustomField = class extends custom_field_default { type = "repeater"; column = null; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary }, config: { isDisabled: this.props?.config?.isDisabled }, fields: [], validation: this.props?.validation }; } // Methods responseValueFormat() { return { value: null, meta: null }; } getInsertField() { return null; } cfSpecificValidation() { return { valid: true }; } }; var repeater_default = RepeaterCustomField; // src/libs/custom-fields/fields/select.ts import z8 from "zod"; import merge2 from "lodash.merge"; var SelectCustomField = class extends custom_field_default { type = "select"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, options: this.props?.options ?? [], config: { useTranslations: this.props?.config?.useTranslations ?? false, default: this.props?.config?.default ?? "", isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.text_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: props.item.value, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z8.string(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; if (this.config.options) { const optionValues = this.config.options.map((option) => option.value); if (!optionValues.includes(value)) { return { valid: false, message: translations_default("please_ensure_a_valid_option_is_selected") }; } } return { valid: true }; } // Getters get errors() { return merge2(super.errors, { required: { message: translations_default("select_field_required") } }); } }; var select_default = SelectCustomField; // src/libs/custom-fields/fields/text.ts import z9 from "zod"; var TextCustomField = class extends custom_field_default { type = "text"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? true, default: this.props?.config?.default ?? "", isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.text_value ?? this.config.config.default, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: props.item.value, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z9.string(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; return { valid: true }; } }; var text_default = TextCustomField; // src/libs/custom-fields/fields/textarea.ts import z10 from "zod"; var TextareaCustomField = class extends custom_field_default { type = "textarea"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? true, default: this.props?.config?.default ?? "", isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.text_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: props.item.value, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z10.string(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; return { valid: true }; } }; var textarea_default = TextareaCustomField; // src/libs/custom-fields/fields/user.ts import z11 from "zod"; var UserCustomField = class extends custom_field_default { type = "user"; column = "user_id"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary }, config: { useTranslations: this.props?.config?.useTranslations ?? false, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.user_id ?? null, meta: { email: props.data?.user_email ?? null, username: props.data?.user_username ?? null, firstName: props.data?.user_first_name ?? null, lastName: props.data?.user_last_name ?? null } }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: null, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: props.item.value }; } cfSpecificValidation(value, relationData) { const valueSchema = z11.number(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; const findUser = relationData?.find((u) => u.id === value); if (findUser === void 0) { return { valid: false, message: translations_default("field_user_not_found") }; } return { valid: true }; } }; var user_default = UserCustomField; // src/libs/custom-fields/fields/wysiwyg.ts import z12 from "zod"; import sanitizeHtml from "sanitize-html"; var WysiwygCustomField = class extends custom_field_default { type = "wysiwyg"; column = "text_value"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary, placeholder: this.props?.details?.placeholder }, config: { useTranslations: this.props?.config?.useTranslations ?? true, default: this.props?.config?.default ?? "", isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { return { value: props.data.text_value ?? this.config.config.default ?? null, meta: null }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: props.item.value, intValue: null, boolValue: null, jsonValue: null, mediaId: null, userId: null }; } cfSpecificValidation(value) { const valueSchema = z12.string(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; const sanitizedValue = sanitizeHtml(value); if (this.config.validation?.zod) { return zod_safe_parse_default(sanitizedValue, this.config.validation?.zod); } return { valid: true }; } }; var wysiwyg_default = WysiwygCustomField; // src/libs/custom-fields/fields/document.ts import z13 from "zod"; var FieldsFormatter = formatters_default.get("collection-document-fields"); var DocumentCustomField = class extends custom_field_default { type = "document"; column = "document_id"; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, collection: this.props.collection, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary }, config: { useTranslations: this.props?.config?.useTranslations ?? false, isHidden: this.props?.config?.isHidden, isDisabled: this.props?.config?.isDisabled }, validation: this.props?.validation }; } // Methods responseValueFormat(props) { const CollectionBuilder2 = props.formatMeta.collections.find( (c) => c.key === this.props.collection ); if (!CollectionBuilder2) { return { value: props.data?.document_id ?? null, meta: { id: props.data.document_id ?? null, fields: null } }; } const documentFields = FieldsFormatter.objectifyFields( FieldsFormatter.formatMultiple( { fields: props.data.document_fields || [], groups: props.data.document_groups || [] }, { builder: CollectionBuilder2, collectionTranslations: CollectionBuilder2.getData.config.useTranslations, localisation: props.formatMeta.localisation, collections: props.formatMeta.collections, host: props.formatMeta.host } ) ); return { value: props.data?.document_id ?? null, meta: { id: props.data.document_id ?? null, fields: Object.keys(documentFields).length > 0 ? documentFields : null } }; } getInsertField(props) { return { key: this.config.key, type: this.config.type, localeCode: props.item.localeCode, collectionBrickId: props.brickId, groupId: props.groupId, textValue: null, intValue: null, boolValue: null, jsonValue: null, mediaId: null, documentId: props.item.value, userId: null }; } cfSpecificValidation(value, relationData) { const valueSchema = z13.number(); const valueValidate = zod_safe_parse_default(value, valueSchema); if (!valueValidate.valid) return valueValidate; const findDocument = relationData?.find((d) => d.id === value); if (findDocument === void 0) { return { valid: false, message: translations_default("field_document_not_found") }; } if (findDocument.collection_key !== this.config.collection) { return { valid: false, message: translations_default("field_document_collection_key_mismatch", { expected: this.config.collection, received: findDocument.collection_key }) }; } return { valid: true }; } }; var document_default = DocumentCustomField; // src/libs/builders/field-builder/index.ts var FieldBuilder = class { fields = /* @__PURE__ */ new Map(); repeaterStack = []; meta = { fieldKeys: [], repeaterDepth: {} }; // Custom Fields addRepeater(key, props) { this.meta.repeaterDepth[key] = this.repeaterStack.length; this.fields.set(key, new repeater_default(key, props)); this.repeaterStack.push(key); return this; } addText(key, props) { this.fields.set(key, new text_default(key, props)); this.meta.fieldKeys.push(key); return this; } addWysiwyg(key, props) { this.fields.set(key, new wysiwyg_default(key, props)); this.meta.fieldKeys.push(key); return this; } addMedia(key, props) { this.fields.set(key, new media_default(key, props)); this.meta.fieldKeys.push(key); return this; } addDocument(key, props) { this.fields.set(key, new document_default(key, props)); this.meta.fieldKeys.push(key); return this; } addNumber(key, props) { this.fields.set(key, new number_default(key, props)); this.meta.fieldKeys.push(key); return this; } addCheckbox(key, props) { this.fields.set(key, new checkbox_default(key, props)); this.meta.fieldKeys.push(key); return this; } addSelect(key, props) { this.fields.set(key, new select_default(key, props)); this.meta.fieldKeys.push(key); return this; } addTextarea(key, props) { this.fields.set(key, new textarea_default(key, props)); this.meta.fieldKeys.push(key); return this; } addJSON(key, props) { this.fields.set(key, new json_default(key, props)); this.meta.fieldKeys.push(key); return this; } addColour(key, props) { this.fields.set(key, new colour_default(key, props)); this.meta.fieldKeys.push(key); return this; } addDateTime(key, props) { this.fields.set(key, new datetime_default(key, props)); this.meta.fieldKeys.push(key); return this; } addLink(key, props) { this.fields.set(key, new link_default(key, props)); this.meta.fieldKeys.push(key); return this; } addUser(key, props) { this.fields.set(key, new user_default(key, props)); this.meta.fieldKeys.push(key); return this; } endRepeater() { const key = this.repeaterStack.pop(); if (!key) return this; const fields = Array.from(this.fields.values()); const selectedRepeaterIndex = fields.findIndex( (field) => field.type === "repeater" && field.key === key ); if (selectedRepeaterIndex === -1) return this; const fieldsAfter = fields.slice(selectedRepeaterIndex + 1); for (const field of fieldsAfter) { if (field.type === "tab" || field.repeater) continue; field.repeater = key; } return this; } // Private Methods nestFields(excludeTabs) { const fields = Array.from(this.fields.values()).filter((field) => { if (excludeTabs) { return field.type !== "tab"; } return true; }); const result = []; let currentTab = null; const repeaterStack = /* @__PURE__ */ new Map(); for (const field of fields) { const config = JSON.parse(JSON.stringify(field.config)); if (field.type === "tab") { if (currentTab) result.push(currentTab); currentTab = config; continue; } if (field.type === "repeater") repeaterStack.set(field.key, config); const targetPush = currentTab ? currentTab.fields : result; if (field.repeater) { const repeater = repeaterStack.get(field.repeater); if (repeater) repeater.fields.push( config ); } else { targetPush.push(config); } } if (currentTab) result.push(currentTab); return result; } // Getters get fieldTree() { return this.nestFields(false); } get fieldTreeNoTab() { return this.nestFields(true); } get flatFields() { const config = []; for (const [_, value] of this.fields) { config.push(value.config); } return config; } }; var field_builder_default = FieldBuilder; // src/libs/custom-fields/fields/tab.ts var TabCustomField = class extends custom_field_default { type = "tab"; column = null; config; key; props; constructor(key, props) { super(); this.key = key; this.props = props; this.config = { key: this.key, type: this.type, details: { label: this.props?.details?.label ?? key_to_title_default(this.key), summary: this.props?.details?.summary }, fields: [] }; } // Methods responseValueFormat() { return { value: null, meta: null }; } getInsertField() { return null; } cfSpecificValidation() { return { valid: true }; } }; var tab_default = TabCustomField; // src/libs/builders/brick-builder/index.ts var BrickBuilder = class extends field_builder_default { key; config; constructor(key, config) { super(); this.key = key; this.config = { details: { name: config?.details?.name || key, summary: config?.details?.summary }, preview: config?.preview || {} }; } // Builder methods addFields(Builder) { const fields = Array.from(Builder.fields.values()); for (const field of fields) { this.fields.set(field.key, field); this.meta.fieldKeys.push(field.key); } return this; } addTab(key, props) { this.fields.set(key, new tab_default(key, props)); this.meta.fieldKeys.push(key); return this; } }; var brick_builder_default = BrickBuilder; // src/libs/builders/collection-builder/index.ts var CollectionBuilder = class extends field_builder_default { key; config; includeFieldKeys = []; filterableFieldKeys = []; constructor(key, config) { super(); this.key = key; this.config = config; if (this.config.bricks?.fixed) { this.config.bricks.fixed = this.#removeDuplicateBricks( config.bricks?.fixed ); } if (this.config.bricks?.builder) { this.config.bricks.builder = this.#removeDuplicateBricks( config.bricks?.builder ); } } // ------------------------------------ // Builder Methods addText(key, props) { this.#fieldCollectionHelper(key, "text", props?.collection); super.addText(key, props); return this; } addNumber(key, props) { this.#fieldCollectionHelper(key, "number", props?.collection); super.addNumber(key, props); return this; } addCheckbox(key, props) { this.#fieldCollectionHelper(key, "checkbox", props?.collection); super.addCheckbox(key, props); return this; } addSelect(key, props) { this.#fieldCollectionHelper(key, "select", props?.collection); super.addSelect(key, props); return this; } addTextarea(key, props) { this.#fieldCollectionHelper(key, "textarea", props?.collection); super.addTextarea(key, props); return this; } addDateTime(key, props) { this.#fieldCollectionHelper(key, "datetime", props?.collection); super.addDateTime(key, props); return this; } addUser(key, props) { this.#fieldCollectionHelper(key, "user", props?.collection); super.addUser(key, props); return this; } addMedia(key, props) { this.#fieldCollectionHelper(key, "media", props?.collection); super.addMedia(key, props); return this; } // ------------------------------------ // Public Methods documentFieldFilters(filters, allowAll) { if (!filters) return []; const fields = allowAll ? this.flatFields : this.filterableFieldKeys; return fields.reduce((acc, field) => { const filterValue = filters[field.key]; if (filterValue === void 0) return acc; const fieldInstance = this.fields.get(field.key); if (!fieldInstance) return acc; acc.push({ key: field.key, value: filterValue.value, operator: filterValue.operator ?? "=", column: fieldInstance.column }); return acc; }, []); } queryIncludeFields(all) { if (all) return this.flatFields.filter((f) => f.type !== "tab").map((f) => f.key); const fieldKeys = Array.from(this.includeFieldKeys); for (const field of this.filterableFieldKeys) { if (fieldKeys.includes(field.key)) continue; fieldKeys.push(field.key); } return fieldKeys; } // ------------------------------------ // Private Methods #removeDuplicateBricks = (bricks) => { if (!bricks) return void 0; return bricks.filter( (brick, index) => bricks.findIndex((b) => b.key === brick.key) === index ); }; #fieldCollectionHelper = (key, type, config) => { if (config?.column) this.includeFieldKeys.push(key); if (config?.filterable) this.filterableFieldKeys.push({ key, type }); }; // ------------------------------------ // Getters get getData() { return { key: this.key, mode: this.config.mode, details: { name: this.config.details.name, singularName: this.config.details.singularName, summary: this.config.details.summary ?? null }, config: { isLocked: this.config.config?.isLocked ?? constants_default.collectionBuilder.isLocked, useDrafts: this.config.config?.useDrafts ?? constants_default.collectionBuilder.useDrafts, useRevisions: this.config.config?.useRevisions ?? constants_default.collectionBuilder.useRevisions, useTranslations: this.config.config?.useTranslations ?? constants_default.collectionBuilder.useTranslations, fields: { filter: this.filterableFieldKeys, include: this.includeFieldKeys } } }; } get fixedBricks() { return this.config.bricks?.fixed?.map((brick) => ({ key: brick.key, details: brick.config.details, preview: brick.config.preview, fields: brick.fieldTree })) ?? []; } get builderBricks() { return this.config.bricks?.builder?.map((brick) => ({ key: brick.key, details: brick.config.details, preview: brick.config.preview, fields: brick.fieldTree })) ?? []; } get brickInstances() { return (this.config.bricks?.builder || []).concat( this.config.bricks?.fixed || [] ); } }; var collection_builder_default = CollectionBuilder; export { brick_builder_default as BrickBuilder, collection_builder_default as CollectionBuilder, field_builder_default as FieldBuilder }; //# sourceMappingURL=builders.js.map