| 586 | } |
| 587 | |
| 588 | export async function buildModel (options: BuildModelOptions): Promise<AttributeModel[]> { |
| 589 | // eslint-disable-next-line array-callback-return |
| 590 | const model = options.keys |
| 591 | .map((key) => (typeof key === 'string' ? { key } : key)) |
| 592 | .map(async (key) => { |
| 593 | try { |
| 594 | // Check if it is a mixin attribute configuration |
| 595 | if (key.key.startsWith('$associations')) { |
| 596 | return await getRelationPresenter(options.client, key) |
| 597 | } |
| 598 | const pos = key.key.lastIndexOf('.') |
| 599 | if (pos !== -1) { |
| 600 | const mixinName = key.key.substring(0, pos) as Ref<Class<Doc>> |
| 601 | if (!mixinName.includes('$lookup')) { |
| 602 | const realKey = key.key.substring(pos + 1) |
| 603 | const rkey = { ...key, key: realKey } |
| 604 | return { |
| 605 | ...(await getPresenter(options.client, mixinName, rkey, rkey, options.lookup)), |
| 606 | castRequest: mixinName, |
| 607 | key: key.key, |
| 608 | sortingKey: key.key |
| 609 | } |
| 610 | } |
| 611 | } |
| 612 | return await getPresenter(options.client, options._class, key, key, options.lookup) |
| 613 | } catch (err: any) { |
| 614 | if (options.ignoreMissing ?? false) { |
| 615 | return undefined |
| 616 | } |
| 617 | const stringKey = key.label ?? key.key |
| 618 | Analytics.handleError(err) |
| 619 | console.error('Failed to find presenter for', key, err) |
| 620 | const errorPresenter: AttributeModel = { |
| 621 | key: '', |
| 622 | sortingKey: '', |
| 623 | presenter: ErrorPresenter, |
| 624 | label: stringKey as IntlString, |
| 625 | _class: core.class.TypeString, |
| 626 | props: { error: err }, |
| 627 | collectionAttr: false, |
| 628 | isLookup: false |
| 629 | } |
| 630 | return errorPresenter |
| 631 | } |
| 632 | }) |
| 633 | return (await Promise.all(model)).filter((a) => a !== undefined) |
| 634 | } |
| 635 | |
| 636 | async function getRelationPresenter (client: Client, key: BuildModelKey): Promise<AttributeModel> { |
| 637 | const parts = key.key.split('.') |