|
| 1 | +/* eslint-disable @typescript-eslint/no-explicit-any */ |
| 2 | +import { resolveField } from './model-meta'; |
| 3 | +import { ModelMeta } from './types'; |
| 4 | + |
| 5 | +/** |
| 6 | + * Callback for @see ModelDataVisitor. |
| 7 | + */ |
| 8 | +export type ModelDataVisitorCallback = (model: string, data: any, scalarData: any) => void; |
| 9 | + |
| 10 | +/** |
| 11 | + * Visitor that traverses data returned by a Prisma query. |
| 12 | + */ |
| 13 | +export class ModelDataVisitor { |
| 14 | + constructor(private modelMeta: ModelMeta) {} |
| 15 | + |
| 16 | + /** |
| 17 | + * Visits the given model data. |
| 18 | + */ |
| 19 | + visit(model: string, data: any, callback: ModelDataVisitorCallback) { |
| 20 | + if (!data || typeof data !== 'object') { |
| 21 | + return; |
| 22 | + } |
| 23 | + |
| 24 | + const scalarData: Record<string, unknown> = {}; |
| 25 | + const subTasks: Array<{ model: string; data: any }> = []; |
| 26 | + |
| 27 | + for (const [k, v] of Object.entries(data)) { |
| 28 | + const field = resolveField(this.modelMeta, model, k); |
| 29 | + if (field && field.isDataModel) { |
| 30 | + if (field.isArray && Array.isArray(v)) { |
| 31 | + subTasks.push(...v.map((item) => ({ model: field.type, data: item }))); |
| 32 | + } else { |
| 33 | + subTasks.push({ model: field.type, data: v }); |
| 34 | + } |
| 35 | + } else { |
| 36 | + scalarData[k] = v; |
| 37 | + } |
| 38 | + } |
| 39 | + |
| 40 | + callback(model, data, scalarData); |
| 41 | + subTasks.forEach(({ model, data }) => this.visit(model, data, callback)); |
| 42 | + } |
| 43 | +} |
0 commit comments