import { getProjectDatabaseModels } from '../../../helpers/getProjectModelsAndDaos.js' import { findByAddressAll, getId, isObject, asArray } from 'topkat-utils' import { MaybeArray } from 'typescript-generic-types' import { AllDbIds } from '../../../cache/dbs/index.generated.js' /** Transform populated fields into their respective _ids. Will modify the passed object */ export async function unPopulate(dbName: AllDbIds, modelName: ModelName, fields: Record) { await forEachPopulateField(dbName, modelName, fields, (val, addr, parent) => { parent[addr] = val !== null ? getId(val) : val }) } const modelFlatObjCache = {} as { [dbId: string]: { [modelName: string]: { [populatedFieldNameFlat: string]: string } } } async function forEachPopulateField( dbName: AllDbIds, modelName: ModelName, fields: Record, cb: (fieldValue: string | Record, fieldAddrInParent: string | number, parent: MaybeArray>, modelName: string, addrFromRoot: string) => MaybePromise, recursive = false ) { const models = await getProjectDatabaseModels() modelFlatObjCache[dbName] ??= {} modelFlatObjCache[dbName][modelName] ??= models[dbName][modelName]._getDefinitionObjFlat(false, def => def._refValue) const populateAddresses = modelFlatObjCache[dbName][modelName] // const { populateAddrFlatWithModelName } = models // const populateAddresses = populateAddrFlatWithModelName[dbName][modelName] for (const [addr, modelName] of Object.entries(populateAddresses)) { const actualPopulatedFieldFields = findByAddressAll(fields, addr.replace(/\[\d\]/g, '[*]'), true) if (actualPopulatedFieldFields && actualPopulatedFieldFields.length) { for (const [addr, valueMaybeArr, lastElmKey, parent] of actualPopulatedFieldFields) { // Eg: ['organizations[0]', { populatedOrg: true }] OR ['organizations[0]', '1234orgId'] const isArray = Array.isArray(valueMaybeArr) let i = 0 const arrValue = asArray(valueMaybeArr) if (!arrValue) continue for (const value of arrValue) { await cb( value, isArray ? i : lastElmKey, isArray ? parent[lastElmKey] : parent, modelName, isArray ? addr + `[${i}]` : addr ) const updatedValue = isArray ? parent[lastElmKey][i] : parent[lastElmKey] // may have changed reference if (recursive && isObject(updatedValue)) { await forEachPopulateField(dbName, modelName, updatedValue, cb, recursive) } i++ } } } } } // alias for readability export const forEachPopulateFieldRecursive: typeof forEachPopulateField = async (dbName, modelName, fields, cb) => await forEachPopulateField(dbName, modelName, fields, cb, true)