import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast'; import { notOk, ok, type Result } from '@prisma-next/utils/result'; import { IdentifierAst } from '../../syntax/ast/identifier'; import type { ArgType } from '../types'; import { leafDiagnostic } from './diagnostic'; export type FieldRefScope = 'self' | 'referenced'; export interface FieldRefArgType extends ArgType { readonly scope: FieldRefScope; } export function fieldRef(scope: FieldRefScope): FieldRefArgType { return { kind: 'fieldRef', label: 'field name', scope, parse: (arg, ctx): Result => { if (!(arg instanceof IdentifierAst)) { return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]); } const name = arg.name(); if (name === undefined) { return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]); } const model = scope === 'self' ? ctx.selfModel : ctx.resolveReferencedModel(); // A referenced model in another space can't be resolved here (resolveReferencedModel returns undefined); skip the existence check — it runs where that model is known. if (model !== undefined && !Object.hasOwn(model.fields, name)) { return notOk([ leafDiagnostic(ctx, arg, `Field "${name}" does not exist on model "${model.name}"`), ]); } return ok(name); }, }; }