icflorescu / trpc-sveltekit

End-to-end typesafe APIs with tRPC.io for your SvelteKit applications.
https://icflorescu.github.io/trpc-sveltekit
ISC License
775 stars 39 forks source link

Client receiving object[] instead of Serialized<Model[]> (Sequelize) #80

Closed SudoerWithAnOpinion closed 8 months ago

SudoerWithAnOpinion commented 1 year ago

I have a single working procedure that uses Sequelize to query a database. When I call this procedure from a +page.ts, it has a typeof …Asset[], when I attempt to use the other one, it says its type is object[] instead of Asset[].

export const load: PageLoad = (event) => ({
  // It does complain about string not being assignable to the model’s `createdAt: Date` but it’s fine…
  rows: trpc(event).asset.getAllWithActivities.query({ pageSize: 20, page: 0 }), // typeof …Asset[]

  // The type is wrong
 someOtherVar: trpc(event).asset.getAll.query({ pageSize: 500, page: 0 }), // typeof …object[]

});

Below is the defined procedure, when I check the types on the procedures, they are correct.

export const assetRouter = t.router({
 getall: t.procedure
    .input(pageOffsetSchema)
    .query(async ({ input }) => {    
      return await Asset.findAll({...genQueryOptions(input)});
  }),
  getAllWithActivities: t.procedure
    .input(pageOffsetSchema)
    .query(async ({ input }) => {    
      return await Asset
        .findAll({...genQueryOptions(input)})
        .then(async (list) => {
          return await Promise.all(
            list.map(async (asset) => {          
              return {
                ...asset.toJSON(),
                status: await asset.getStatus()
             };
        })
      );
    });  
  }),
});

Am I missing something critical? When I use the router.createCaller(…) pattern, it works fine. I am using the examples where t.ts handles initTRPC, must like the bookstall example. The query() call is correctly returning the data I’d like from the DB, but typed as object[] is causing type errors and does break the entire point of using tRPC

multiplehats commented 1 year ago

I think I ran into this problem at some point, You could try using superjson

import type { AppRouter } from '$core/api/root';
import type { QueryClient } from '@tanstack/svelte-query';
import type { inferRouterInputs, inferRouterOutputs } from '@trpc/server';
import superjson from 'superjson';
import { svelteQueryWrapper } from 'trpc-svelte-query-adapter';
import { type TRPCClientInit, createTRPCClient } from 'trpc-sveltekit';

let browserClient: ReturnType<typeof svelteQueryWrapper<AppRouter>>;

export function api(init?: TRPCClientInit, queryClient?: QueryClient) {
    const isBrowser = typeof window !== 'undefined';
    if (isBrowser && browserClient) return browserClient;
    const client = svelteQueryWrapper<AppRouter>({
        client: createTRPCClient<AppRouter>({ init, transformer: superjson, url: '/api/trpc' }),
        queryClient
    });
    if (isBrowser) browserClient = client;
    return client;
}

/**
 * Inference helper for inputs
 * @example type HelloInput = RouterInputs['example']['hello']
 **/
export type RouterInputs = inferRouterInputs<AppRouter>;
/**
 * Inference helper for outputs
 * @example type HelloOutput = RouterOutputs['example']['hello']
 **/
export type RouterOutputs = inferRouterOutputs<AppRouter>;
icflorescu commented 8 months ago

Superjson, or tRPC-Transformer if you're looking for a quick solution combining superjson with Decimal.js.