Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for decimal.js. Support for Prisma.Decimal. #158

Conversation

michaeljonsampson
Copy link

Allows using Prisma Decimal type in getServerSideProps.
This fixes #152

@Skn0tt
Copy link
Collaborator

Skn0tt commented Nov 1, 2021

Hi @michaeljonsampson! Thanks for opening this PR. When you opened the issue, I somehow thought that Decimal was a built-in type like BigInt. It's apparently a proposal in Stage 1: https://github.com/tc39/proposal-decimal

To keep bundle size down, SuperJSON needs to stay as lean as possible. I've adapted your changes into #159, which adds a test for Decimal.js and mentions how to integrate in the README.

@michaeljonsampson
Copy link
Author

@Skn0tt wasn't my issue but I ran into the same problem an came across it. Didn't know about registerCustom. That covers my use case. Tested #159 and I can still serialize Prisma.Decimal. Thanks.

@michaelhays
Copy link

michaelhays commented Jan 18, 2022

Just a heads up for anyone using superjson with tRPC Data Transformers, make sure to put the Decimal.js registerCustom recipe in both your client and router.

I'd recommend making a utils/superjson.ts file and importing superjson from there, to keep them in sync.

@michealroberts
Copy link

Hi @michaelhays ... do you have a minimal reproduction of your superjson transformer with decimal.js support? I'd love to use it one of our projects ...

@michaelhays
Copy link

michaelhays commented Mar 16, 2023

Sure, here are the relevant files for a Next.js project:

src/utils/superjson.ts
import Decimal from 'decimal.js'
import superjson from 'superjson'

superjson.registerCustom<Decimal, string>(
  {
    isApplicable: (v): v is Decimal => Decimal.isDecimal(v),
    serialize: (v) => v.toJSON(),
    deserialize: (v) => new Decimal(v),
  },
  'decimal.js',
)

export default superjson
src/utils/trpc.ts
import type { AppRouter } from '@/server/appRouter'
import { createTRPCNext } from '@trpc/next'
import superjson from './superjson'

export const trpc = createTRPCNext<AppRouter>({
  config() {
    return {
      transformer: superjson,
      links: [...],
    }
  },
})
src/server/trpc.ts
import { initTRPC, TRPCError } from '@trpc/server'
import superjson from '../utils/superjson'
import type { Context } from './context'

const t = initTRPC.context<Context>().create({ transformer: superjson })

export const publicProcedure = t.procedure

@AmruthPillai
Copy link

Thank you for the code examples. The workaround for Decimal.js works with trpc, but how do I register custom when using it with the next-superjson-plugin (swc)? I'm unable to pass Decimal properties as props from a Server Component to a Client Component.

@Skn0tt
Copy link
Collaborator

Skn0tt commented Jun 24, 2024

You need to execute the registerCustom call is on both the client and the server. I‘m unsure what the right files for that are in Next.js nowadays - maybe something like app.server.js and app.client.js, if they exist? Let us know what works for you, i‘m sure this is super useful for many folks.

@AmruthPillai
Copy link

Yes, I did try this. I added the registerCustom function on the server component level (at layout.tsx) and inside a client component (inside a useEffect of a ClientComponent and outside). Adding it to the client component seemed to do nothing, but adding it on the server component threw the same error.

I'm not sure if there's a way to run a function before the build even begins, with either webpack or SWC, that might be a good place to add this.

@pedro757
Copy link

pedro757 commented Sep 2, 2024

Did you find a solution?

@AmruthPillai

@AmruthPillai
Copy link

AmruthPillai commented Sep 3, 2024

@pedro757 Nope, just reverted back to using Number datatype in Prisma for now. Would love to make use of Decimal, but I believe this is something Next.js needs to get straight, adding middlewares for client and server individually, and not just a single Edge runtime variant.

@pedro757
Copy link

pedro757 commented Sep 3, 2024

I was able to make it work, setting the registerCustom in a page.tsx and in passing data-superjson prop to client component

See the Code

Server Component

// page.tsx
import { Temporal } from "temporal-polyfill";
import Button from "./client";
import SuperJSON from "superjson";
import PlainDate, { startOfMonth, weekNumber } from 'plain-date'
SuperJSON.registerCustom<Temporal.PlainDate, string>(
{
  isApplicable: (v): v is Temporal.PlainDate =>
    v instanceof Temporal.PlainDate ||
    (typeof v === "string" &&
      RegExp(
        /^(19[0-9]{2}|2[0-9]{3})-(0[1-9]|1[012])-([123]0|[012][1-9]|31)$/,
      ).test(v)),
  serialize: (v) => v.toJSON(),
  deserialize: (v) => Temporal.PlainDate.from(v),
},
"PlainDate",
)

export default function Home() {
return (
  <main className="flex min-h-screen flex-col items-center justify-between p-24">
    <Button date={new Temporal.PlainDate(2023, 1, 1)} data-superjson />
  </main>
);
}

With that I receive my custom type in the client component

@AmruthPillai

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

issue with Next.js Decimal data type (data fetched from prisma/postgres)
6 participants