@internal
(
entityName: EntityName<Entity>,
options: Pick<
FindOptions<Entity, any, any, any>,
'populate' | 'strategy' | 'fields' | 'flags' | 'filters' | 'exclude' | 'populateHints'
>,
validate = true,
)
| 2872 | |
| 2873 | /** @internal */ |
| 2874 | async preparePopulate<Entity extends object>( |
| 2875 | entityName: EntityName<Entity>, |
| 2876 | options: Pick< |
| 2877 | FindOptions<Entity, any, any, any>, |
| 2878 | 'populate' | 'strategy' | 'fields' | 'flags' | 'filters' | 'exclude' | 'populateHints' |
| 2879 | >, |
| 2880 | validate = true, |
| 2881 | ): Promise<PopulateOptions<Entity>[]> { |
| 2882 | if (options.populate === false) { |
| 2883 | return []; |
| 2884 | } |
| 2885 | |
| 2886 | const meta = this.metadata.find(entityName)!; |
| 2887 | |
| 2888 | // infer populate hints from `fields` when present; merge with explicit `populate` if both are set. |
| 2889 | // `populateArray` is only kept when the entries are user-provided strings — when this method runs a |
| 2890 | // second time (e.g. from `lockAndPopulate`) the populate is already normalized and merging would be a no-op. |
| 2891 | const fields = options.fields ? this.buildFields(options.fields) : undefined; |
| 2892 | const populateArray = |
| 2893 | Array.isArray(options.populate) && options.populate.every(p => typeof p === 'string') |
| 2894 | ? (options.populate as string[]) |
| 2895 | : undefined; |
| 2896 | const hasNestedFields = fields?.some(f => f.includes('.')) ?? false; |
| 2897 | const shouldInfer = fields !== undefined && options.populate === undefined; |
| 2898 | const shouldMerge = |
| 2899 | fields !== undefined && populateArray !== undefined && populateArray.length > 0 && hasNestedFields; |
| 2900 | |
| 2901 | if (shouldInfer || shouldMerge) { |
| 2902 | // we need to prune the `populate` hint from to-one relations, as partially loading them does not require their population, we want just the FK |
| 2903 | const pruneToOneRelations = (meta: EntityMetadata, fields: string[]): string[] => { |
| 2904 | const ret: string[] = []; |
| 2905 | |
| 2906 | for (let field of fields) { |
| 2907 | if (field === PopulatePath.ALL || field.startsWith(`${PopulatePath.ALL}.`)) { |
| 2908 | ret.push( |
| 2909 | ...meta.props |
| 2910 | .filter(prop => prop.lazy || [ReferenceKind.SCALAR, ReferenceKind.EMBEDDED].includes(prop.kind)) |
| 2911 | .map(prop => prop.name), |
| 2912 | ); |
| 2913 | continue; |
| 2914 | } |
| 2915 | |
| 2916 | field = field.split(':')[0]; |
| 2917 | |
| 2918 | if ( |
| 2919 | !field.includes('.') && |
| 2920 | ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(meta.properties[field].kind) |
| 2921 | ) { |
| 2922 | ret.push(field); |
| 2923 | continue; |
| 2924 | } |
| 2925 | |
| 2926 | const parts = field.split('.'); |
| 2927 | const key = parts.shift()!; |
| 2928 | |
| 2929 | if (parts.length === 0) { |
| 2930 | continue; |
| 2931 | } |
no test coverage detected