0

I am trying to reference the money type onto my cart type I have tried a few different ways and keep getting this error:

:Ref function String() { [native code] } has not been implemented

In my project, I am importing my types as classes as recommended in the docs,

My types:

That are in a separate file from my server

export class CartItem { id: string; name: string; price: number; quantity: number; constructor(id: string, name: string, price: number, quantity: number) { this.id = id; this.name = name; this.price = price; this.quantity = quantity; } } 
export class Cart { id: string; items?: CartItem[]; constructor(id: string, items?: CartItem[]) { this.id = id; this.items = items; } } 
export class Money { amount: number; formatted: string; constructor(amount: number, formatted: string) { this.amount = amount; this.formatted = formatted; } } 

Here is my server:

I have two comments showing where I am likely failing

  1. In my Cart Objecttype
  2. const MoneyType

import { createServer } from '@graphql-yoga/node' import SchemaBuilder from "@pothos/core" import { CartItem, Cart, Money } from 'gql'; const CARTS = [ { id: '1', items: [ { id: '1', name: 'Item 1', price: 10, quantity: 1 }, { id: '2', name: 'Item 2', price: 20, quantity: 2 } ] }, { id: '2', items: [ { id: '3', name: 'Item 3', price: 30, quantity: 3 }, { id: '4', name: 'Item 4', price: 40, quantity: 4 } ] } ] const builder = new SchemaBuilder({}); builder.objectType(Cart, { name: "Cart", description: "A cart", fields: (t) => ({ id: t.exposeString('id', {}), items: t.field({ type: [CartItem], resolve: (cart) => cart.items ?? [], }), // This is the field that we want to USE TO REFERENCE // subTotal: t.field({ // type: Money, // resolve: (cart) => { // const total = cart.items?.reduce((acc, item) => acc + item.price * item.quantity, 0) ?? 0; // return new Money(total, `$${total}`); // } // }) }), }); builder.objectType(CartItem, { name: "CartItem", description: "A cart item", fields: (t) => ({ id: t.exposeString('id', {}), name: t.exposeString('name', {}), price: t.exposeInt('price', {}), quantity: t.exposeInt('quantity', {}), }), }); // make a reference to the Money type THAT DOESEN'T WORK const MoneyType = builder.objectRef<MoneyShape>("Money"); builder.objectType(Money, { name: "Money", description: "A money", fields: (t) => ({ amount: t.exposeInt('amount', {}), formatted: t.field({ type: String, resolve: (money) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(money.amount), }), }), }); builder.queryType({ fields: (t) => ({ cart: t.field({ type: Cart, nullable: true, args: { id: t.arg.id({ required: true, description: "the id of the cart" }), }, resolve: (_, { id }) => { const cart = CARTS.find((cart) => cart.id === id); if (!cart) { throw new Error(`Cart with id ${id} not found`) } return cart } }), carts: t.field({ type: [Cart], resolve: () => CARTS }), }), }) const server = createServer({ endpoint: '/api', schema: builder.toSchema(), }) export default server; 

2 Answers 2

1

Unfortunately Pothos' error messages are not very good when it comes to the type property. Scalars in Pothos are referenced by their name, so you should put them in quotation marks:

builder.objectType(Money, { name: "Money", description: "A money", fields: (t) => ({ amount: t.exposeInt("amount", {}), formatted: t.field({ type: "String", resolve: (money) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }).format(money.amount), }), }), }); 

Alternatively, you can also use t.string:

builder.objectType(Money, { name: "Money", description: "A money", fields: (t) => ({ amount: t.exposeInt("amount", {}), formatted: t.string({ resolve: (money) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }).format(money.amount), }), }), }); 

Some additional hints:

I would move the formatter out of the resolver as you only have to create one instance.

I personally don't like the class way of doing things in Pothos, as my types mostly come from Prisma. It works really well, if you have service classes for every object type, but if you just have them to wrap things, it is a lot of overhead. You could consider removing the Money class and using number instead:

const moneyFormatter = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }) const Money = builder.objectRef<number>('Money').implement({ description: "A money", fields: (t) => ({ amount: t.int({ resolve: money => money }), formatted: t.string({ resolve: (money) => moneyFormatter.format(money), }), }), }); 
Sign up to request clarification or add additional context in comments.

5 Comments

Ok, thanks so much for taking the time to answer my question you literally saved me. How am I supposed to know when and where to wrap the types in quotes and when not to?
Also, I am using class-based because that's what the docs recommend I just started learning pothos, but I do plan on using Prisma in the future. Would you happen to have a repository that is a good example of the method of implementing Prisma you are talking about?
Last question, everyone keeps using the term Scalar in the docs it describes Scalars as something you define as a Scalar and it has an input and an output. But that is not how I notice people using it can you breifly explain to me what exactly it is?
1) Pothos has various ways of registering types in your schema. I think in most code bases only scalars are in quotation marks. 2) I understand that this might be confusing. I think the problem is that Pothos wants to work with many different other libraries. AN approach that works for person A does not work for person B. 3) Scalars are the leaf nodes of the data tree. The usually use primitive types in their representation: String, Boolean, Number. graphql.org/learn/schema/#scalar-types I encourage you to keep lerning and join us in the GraphQL discord!
I joined the discord my name is WakyWayne if you want to friend me. It seems that not many people use pothos so it would be good to be friends with someone else using it.
0

This issue occurred to me even when I defined my scalars correctly. enter link description herethis solution helped me to resolve the issue.

Quoted from original Answer

The fix is to define the first query type: builder.queryType({}). You must only do this once, and only once. Usually, it's smart to put this next to your builder initialization.

Original Answer

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.