{"version":3,"file":"document-fields.mjs","names":["DocumentBricksFormatter","formatter"],"sources":["../../../src/libs/formatters/document-fields.ts"],"sourcesContent":["import crypto from \"node:crypto\";\nimport type { FieldRefResponse } from \"../../services/documents-bricks/helpers/fetch-ref-data.js\";\nimport type {\n\tCFConfig,\n\tConfig,\n\tDocumentField,\n\tDocumentFieldPlainValue,\n\tDocumentFieldValueMap,\n\tFieldTypes,\n\tFieldValue,\n\tInternalDocumentField,\n\tInternalDocumentFieldGroup,\n\tLucidBricksTable,\n\tLucidBrickTableName,\n\tSelect,\n} from \"../../types.js\";\nimport type BrickBuilder from \"../collection/builders/brick-builder/index.js\";\nimport type CollectionBuilder from \"../collection/builders/collection-builder/index.js\";\nimport registeredFields from \"../collection/custom-fields/registered-fields.js\";\nimport { isStorageMode } from \"../collection/custom-fields/storage/index.js\";\nimport prefixGeneratedColName from \"../collection/helpers/prefix-generated-column-name.js\";\nimport type { CollectionSchemaTable } from \"../collection/schema/types.js\";\nimport type { BrickQueryResponse } from \"../repositories/document-bricks.js\";\nimport type { DocumentQueryResponse } from \"../repositories/documents.js\";\nimport DocumentBricksFormatter from \"./document-bricks.js\";\nimport formatter from \"./index.js\";\n\nexport interface FieldFormatMeta {\n\tbuilder: BrickBuilder | CollectionBuilder;\n\thost: string;\n\tcollection: CollectionBuilder;\n\tlocalization: {\n\t\tlocales: string[];\n\t\tdefault: string;\n\t};\n\t/** Used to help workout the target brick schema item and the table name. Set to `undefined` if the brick table you're creating fields for is the `document-fields` one */\n\tbrickKey: string | undefined;\n\tconfig: Config;\n\tbricksTableSchema: Array<CollectionSchemaTable<LucidBrickTableName>>;\n}\n\ninterface FieldFormatData {\n\t/** The filtered target brick table rows, grouped by position, each row represent a different locale for the same brick instance */\n\tbrickRows: Select<LucidBricksTable>[];\n\t/** The entire bricksQuery or DocumentQueryResponse response data - used to select tree-table rows from later */\n\tbricksQuery: BrickQueryResponse | DocumentQueryResponse;\n\t/** The schema for the entire collection and all possible bricks */\n\tbricksSchema: Array<CollectionSchemaTable<LucidBrickTableName>>;\n\t/** All relation meta data, users, media, documents etc. Used to populate the field meta data based on the CF type and value */\n\trefData: FieldRefResponse;\n}\n\ninterface IntermediaryFieldValues {\n\tvalue: unknown;\n\tlocale: string;\n}\n\n/**\n * Resolves the localized values for a field from either parent rows or relation rows.\n */\nconst getFieldValues = (\n\tdata: FieldFormatData,\n\tmeta: FieldFormatMeta & {\n\t\tfieldConfig: CFConfig<FieldTypes>;\n\t},\n): IntermediaryFieldValues[] => {\n\tconst fieldInstance = meta.builder.fields.get(meta.fieldConfig.key);\n\tif (!fieldInstance) return [];\n\n\tconst databaseConfig =\n\t\tregisteredFields[meta.fieldConfig.type].config.database;\n\tif (!isStorageMode(databaseConfig, \"relation-table\")) {\n\t\tconst fieldKey = prefixGeneratedColName(meta.fieldConfig.key);\n\n\t\treturn data.brickRows.map((row) => ({\n\t\t\tvalue: row[fieldKey],\n\t\t\tlocale: row.locale,\n\t\t}));\n\t}\n\n\tconst relationRows = DocumentBricksFormatter.getRelationRows({\n\t\tbricksQuery: data.bricksQuery,\n\t\tbricksSchema: data.bricksSchema,\n\t\tcollectionKey: meta.collection.key,\n\t\tbrickKey: meta.brickKey,\n\t\tfieldKey: meta.fieldConfig.key,\n\t\trelationIds: data.brickRows.flatMap((row) => row.id),\n\t\ttableType: databaseConfig.tableType,\n\t});\n\n\treturn meta.localization.locales.map((locale) => {\n\t\tconst localeValues = relationRows\n\t\t\t.filter((row) => row.locale === locale)\n\t\t\t.sort((a, b) => a.position - b.position)\n\t\t\t.reduce<unknown[]>((acc, row) => {\n\t\t\t\tconst value = fieldInstance.extractRelationFieldValue(row);\n\t\t\t\tif (value !== null) acc.push(value);\n\t\t\t\treturn acc;\n\t\t\t}, []);\n\n\t\treturn {\n\t\t\tvalue: localeValues,\n\t\t\tlocale,\n\t\t};\n\t});\n};\n\nconst isTreeTableFieldType = (type: FieldTypes): boolean => {\n\treturn isStorageMode(registeredFields[type].config.database, \"tree-table\");\n};\n\nconst getTreeTableChildFieldConfig = (\n\tfield: CFConfig<FieldTypes>,\n): CFConfig<FieldTypes>[] | null => {\n\tif (!isTreeTableFieldType(field.type)) return null;\n\tif (!(\"fields\" in field)) return null;\n\tif (!Array.isArray(field.fields)) return null;\n\treturn field.fields as CFConfig<FieldTypes>[];\n};\n\n/**\n * The entry point for building out the InternalDocumentField array.\n *\n * Formats, creates groups, creates nested structure, marries refData etc.\n */\nconst formatMultiple = (\n\tdata: FieldFormatData,\n\tmeta: FieldFormatMeta,\n): InternalDocumentField[] => {\n\treturn buildFieldTree(data, {\n\t\tbuilder: meta.builder,\n\t\tfieldConfig: meta.builder.persistedFieldTree,\n\t\thost: meta.host,\n\t\tlocalization: meta.localization,\n\t\tcollection: meta.collection,\n\t\tbrickKey: meta.brickKey,\n\t\tconfig: meta.config,\n\t\tbricksTableSchema: meta.bricksTableSchema,\n\t});\n};\n\n/**\n *  Recursively build out the InternalDocumentField based on the nested fieldConfig\n */\nconst buildFieldTree = (\n\tdata: FieldFormatData,\n\tmeta: FieldFormatMeta & {\n\t\tfieldConfig: CFConfig<FieldTypes>[];\n\t\ttreeLevel?: number;\n\t\tgroupRef?: string;\n\t},\n): InternalDocumentField[] => {\n\tconst fieldsRes: InternalDocumentField[] = [];\n\n\t//* loop over fieldConfig (nested field structure - no tabs)\n\tfor (const config of meta.fieldConfig) {\n\t\tconst treeTableChildFields = getTreeTableChildFieldConfig(config);\n\t\tif (treeTableChildFields) {\n\t\t\t//* recursively build out tree-table groups\n\t\t\tfieldsRes.push({\n\t\t\t\tkey: config.key,\n\t\t\t\ttype: config.type,\n\t\t\t\tgroupRef: meta.groupRef,\n\t\t\t\tgroups: buildTreeGroups(data, {\n\t\t\t\t\tbuilder: meta.builder,\n\t\t\t\t\ttreeFieldConfig: config,\n\t\t\t\t\ttreeChildFields: treeTableChildFields,\n\t\t\t\t\thost: meta.host,\n\t\t\t\t\tlocalization: meta.localization,\n\t\t\t\t\tcollection: meta.collection,\n\t\t\t\t\tbrickKey: meta.brickKey,\n\t\t\t\t\ttreeLevel: meta.treeLevel || 0,\n\t\t\t\t\tgroupRef: meta.groupRef,\n\t\t\t\t\tconfig: meta.config,\n\t\t\t\t\tbricksTableSchema: meta.bricksTableSchema,\n\t\t\t\t}),\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst fieldValues = getFieldValues(data, {\n\t\t\tbuilder: meta.builder,\n\t\t\tfieldConfig: config,\n\t\t\thost: meta.host,\n\t\t\tlocalization: meta.localization,\n\t\t\tcollection: meta.collection,\n\t\t\tbrickKey: meta.brickKey,\n\t\t\tconfig: meta.config,\n\t\t\tbricksTableSchema: meta.bricksTableSchema,\n\t\t});\n\n\t\tconst fieldValue = buildField(\n\t\t\t{\n\t\t\t\tvalues: fieldValues,\n\t\t\t\trefData: data.refData,\n\t\t\t},\n\t\t\t{\n\t\t\t\tbuilder: meta.builder,\n\t\t\t\tfieldConfig: config,\n\t\t\t\thost: meta.host,\n\t\t\t\tlocalization: meta.localization,\n\t\t\t\tcollection: meta.collection,\n\t\t\t\tbrickKey: meta.brickKey,\n\t\t\t\tconfig: meta.config,\n\t\t\t\tgroupRef: meta.groupRef,\n\t\t\t\tbricksTableSchema: meta.bricksTableSchema,\n\t\t\t},\n\t\t);\n\t\tif (fieldValue) fieldsRes.push(fieldValue);\n\t}\n\n\treturn fieldsRes;\n};\n\n/**\n * Responsible for building a single InternalDocumentField object.\n *\n * Adds in empty locale values, formats the value and constructs either translations or values based on the fields config\n */\nconst buildField = (\n\tdata: {\n\t\tvalues: IntermediaryFieldValues[];\n\t\trefData: FieldRefResponse;\n\t},\n\tmeta: FieldFormatMeta & {\n\t\tfieldConfig: CFConfig<FieldTypes>;\n\t\tgroupRef?: string;\n\t},\n): InternalDocumentField | null => {\n\tconst cfInstance = meta.builder.fields.get(meta.fieldConfig.key);\n\tif (!cfInstance) return null;\n\n\t//* if the field supports translations, use the translations field key\n\tif (\n\t\t!isTreeTableFieldType(meta.fieldConfig.type) &&\n\t\tmeta.fieldConfig.type !== \"tab\" &&\n\t\tcfInstance.localizedEnabled === true &&\n\t\tmeta.collection.getData.localized === true\n\t) {\n\t\tconst fieldTranslations: Record<string, FieldValue> = {};\n\n\t\t//* populate the translations/meta\n\t\tfor (const locale of meta.localization.locales) {\n\t\t\tconst localeValue = data.values.find((v) => v.locale === locale);\n\n\t\t\tif (localeValue) {\n\t\t\t\tfieldTranslations[locale] = cfInstance.formatResponseValue(\n\t\t\t\t\tlocaleValue.value,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tfieldTranslations[locale] = null;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tkey: meta.fieldConfig.key,\n\t\t\ttype: meta.fieldConfig.type,\n\t\t\tgroupRef: meta.groupRef,\n\t\t\ttranslations: fieldTranslations,\n\t\t};\n\t}\n\n\t//* otherwise use the value key to just store the default locales value\n\tconst defaultValue = data.values.find(\n\t\t(f) => f.locale === meta.localization.default,\n\t);\n\tif (!defaultValue) return null;\n\n\treturn {\n\t\tkey: meta.fieldConfig.key,\n\t\ttype: meta.fieldConfig.type,\n\t\tvalue: cfInstance.formatResponseValue(defaultValue.value),\n\t\tgroupRef: meta.groupRef,\n\t};\n};\n\n/**\n * Responsible for building out groups for a tree-table field\n */\nconst buildTreeGroups = (\n\tdata: FieldFormatData,\n\tmeta: FieldFormatMeta & {\n\t\ttreeFieldConfig: CFConfig<FieldTypes>;\n\t\ttreeChildFields: CFConfig<FieldTypes>[];\n\t\ttreeLevel: number;\n\t\tgroupRef?: string;\n\t},\n): InternalDocumentFieldGroup[] => {\n\tconst groupsRes: InternalDocumentFieldGroup[] = [];\n\n\t//* using DocumentBricksFormatter.getBrickTreeRows, get the target tree-table rows and construct groups from them\n\tconst treeRows = DocumentBricksFormatter.getBrickTreeRows({\n\t\tbricksQuery: data.bricksQuery,\n\t\tbricksSchema: data.bricksSchema,\n\t\tcollectionKey: meta.collection.key,\n\t\tbrickKey: meta.brickKey,\n\t\ttreeFieldKey: meta.treeFieldConfig.key,\n\t\ttreeLevel: meta.treeLevel,\n\t\trelationIds: data.brickRows.flatMap((b) => b.id),\n\t});\n\n\t//* group by the position\n\tconst groups = Map.groupBy(treeRows, (item) => {\n\t\treturn item.position;\n\t});\n\tgroups.forEach((localeRows, key) => {\n\t\t//* open state is shared for now - if this is to change in the future, the insert/response format for this needs changing\n\t\tconst openState = localeRows[0]?.is_open ?? false;\n\t\tconst ref = generateGroupRef(\n\t\t\tmeta.collection.key,\n\t\t\tmeta.brickKey,\n\t\t\tmeta.treeFieldConfig.key,\n\t\t\tkey,\n\t\t\tmeta.treeLevel,\n\t\t\tmeta.groupRef,\n\t\t);\n\n\t\tgroupsRes.push({\n\t\t\tref: ref,\n\t\t\torder: key,\n\t\t\topen: formatter.formatBoolean(openState),\n\t\t\tfields: buildFieldTree(\n\t\t\t\t{\n\t\t\t\t\tbrickRows: localeRows,\n\t\t\t\t\tbricksQuery: data.bricksQuery,\n\t\t\t\t\tbricksSchema: data.bricksSchema,\n\t\t\t\t\trefData: data.refData,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbuilder: meta.builder,\n\t\t\t\t\thost: meta.host,\n\t\t\t\t\tlocalization: meta.localization,\n\t\t\t\t\tcollection: meta.collection,\n\t\t\t\t\tbrickKey: meta.brickKey,\n\t\t\t\t\tfieldConfig: meta.treeChildFields,\n\t\t\t\t\ttreeLevel: meta.treeLevel + 1,\n\t\t\t\t\tconfig: meta.config,\n\t\t\t\t\tgroupRef: ref,\n\t\t\t\t\tbricksTableSchema: meta.bricksTableSchema,\n\t\t\t\t},\n\t\t\t),\n\t\t});\n\t});\n\n\treturn groupsRes.sort((a, b) => a.order - b.order);\n};\n\n/**\n * Returns fields as an object, with the keys being the custom field keys instead of an array of fields\n */\nconst objectifyFields = (\n\tfields: InternalDocumentField[],\n): Record<string, DocumentField> => {\n\treturn fields.reduce(\n\t\t(acc, field) => {\n\t\t\tif (!field) return acc;\n\n\t\t\tacc[field.key] = {\n\t\t\t\t...field,\n\t\t\t\tgroups: field.groups?.map((g) => {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...g,\n\t\t\t\t\t\tfields: objectifyFields(g.fields || []),\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t} satisfies DocumentField;\n\t\t\treturn acc;\n\t\t},\n\t\t{} as Record<string, DocumentField>,\n\t);\n};\n\nconst flattenFieldValue = (\n\tfield: InternalDocumentField,\n): DocumentFieldPlainValue => {\n\tif (field.groups) {\n\t\treturn field.groups.map((group) => flattenFields(group.fields || []));\n\t}\n\n\tif (field.translations) {\n\t\treturn field.translations;\n\t}\n\n\tif (\"value\" in field) {\n\t\treturn field.value;\n\t}\n\n\treturn null;\n};\n\nconst isStructuralFieldConfig = (\n\tconfig: CFConfig<FieldTypes>,\n): config is CFConfig<\"section\"> | CFConfig<\"collapsible\"> => {\n\treturn config.type === \"section\" || config.type === \"collapsible\";\n};\n\n/**\n * Walks a client field tree level and collects flattened values into `target`.\n * Tabs are transparent, sections/collapsibles shape their children based on\n * their `output` config and repeater groups recurse with their child configs.\n */\nconst collectClientFieldValues = (\n\ttarget: DocumentFieldValueMap,\n\tfieldMap: Map<string, InternalDocumentField>,\n\tconfigs: CFConfig<FieldTypes>[],\n): void => {\n\tfor (const config of configs) {\n\t\tif (config.type === \"tab\") {\n\t\t\tcollectClientFieldValues(target, fieldMap, config.fields);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isStructuralFieldConfig(config)) {\n\t\t\tif (config.output === \"inline\") {\n\t\t\t\tcollectClientFieldValues(target, fieldMap, config.fields);\n\t\t\t} else {\n\t\t\t\tconst nested: DocumentFieldValueMap = {};\n\t\t\t\tcollectClientFieldValues(nested, fieldMap, config.fields);\n\t\t\t\ttarget[config.key] = nested;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst field = fieldMap.get(config.key);\n\t\tif (!field) continue;\n\n\t\tif (field.groups) {\n\t\t\tconst childConfigs =\n\t\t\t\t\"fields\" in config && Array.isArray(config.fields)\n\t\t\t\t\t? (config.fields as CFConfig<FieldTypes>[])\n\t\t\t\t\t: undefined;\n\t\t\ttarget[config.key] = field.groups.map((group) =>\n\t\t\t\tflattenFields(group.fields || [], childConfigs),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\ttarget[config.key] = flattenFieldValue(field);\n\t}\n};\n\n/**\n * Flattens fields into the client value map. When a client field tree is\n * provided, sections/collapsibles shape their children based on their\n * `output` config - nested under their key or inlined as if absent.\n */\nconst flattenFields = (\n\tfields: InternalDocumentField[],\n\tclientFieldTree?: CFConfig<FieldTypes>[],\n): DocumentFieldValueMap => {\n\tif (!clientFieldTree) {\n\t\treturn fields.reduce((acc, field) => {\n\t\t\tif (!field) return acc;\n\n\t\t\tacc[field.key] = flattenFieldValue(field);\n\t\t\treturn acc;\n\t\t}, {} as DocumentFieldValueMap);\n\t}\n\n\tconst fieldMap = new Map(\n\t\tfields.filter((field) => !!field).map((field) => [field.key, field]),\n\t);\n\tconst result: DocumentFieldValueMap = {};\n\tcollectClientFieldValues(result, fieldMap, clientFieldTree);\n\treturn result;\n};\n\n/**\n * Generates a unique deterministic reference for a group\n */\nconst generateGroupRef = (\n\tcollectionKey: string,\n\tbrickKey: string | undefined,\n\ttreeFieldKey: string,\n\tposition: number,\n\ttreeLevel: number,\n\tparentGroupRef?: string,\n): string => {\n\treturn crypto\n\t\t.createHash(\"sha256\")\n\t\t.update(\n\t\t\t`${collectionKey}-${brickKey || \"document\"}-${treeFieldKey}-${position}-${treeLevel}-${parentGroupRef || \"root\"}`,\n\t\t)\n\t\t.digest(\"hex\")\n\t\t.substring(0, 36);\n};\n\nexport default {\n\tformatMultiple,\n\tobjectifyFields,\n\tflattenFields,\n};\n"],"mappings":"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"}