; ── Prisma / Drizzle shape ─────────────────────────────────────────────────
; db.user.findUnique(...), db.session.create(...), etc.
; Matches any <ident>.<model>.<method>() — no hardcoded DB identifier
(call_expression
  function: (member_expression
    object: (member_expression
      object: (identifier) @db.identifier
      property: (property_identifier) @db.model)
    property: (property_identifier) @db.method))

; ── Supabase shape ─────────────────────────────────────────────────────────
; <client>.from("table").<select|insert|update|delete|upsert>(...)
; Captures the table name string and the operation method. The "from_name"
; capture must equal "from" — filtered at emit time.
(call_expression
  function: (member_expression
    object: (call_expression
      function: (member_expression
        property: (property_identifier) @sb.from_name)
      arguments: (arguments
        (string (string_fragment) @sb.table)))
    property: (property_identifier) @sb.method)
  (#eq? @sb.from_name "from"))

; Supabase but the `from()` call is on a function-call result, e.g.
; getServiceClient().from("merchants").select(...)
; The `object: (call_expression...)` above already covers this case because
; tree-sitter's grammar allows any expression as `object` of a member_expression.
; No extra pattern required.
