Mugetsu
Mugetsu
Explore posts from servers
TTCTheo's Typesafe Cult
Created by Mugetsu on 10/8/2024 in #questions
React context in Server Component Page
I have a server component page where I want to provide a context having this file and adding it to the page it throws error?? What Im missing here
'use client';

import React, { createContext, useContext, useMemo, useState } from 'react';

import type { PropsWithChildren } from 'react';

export enum FormMode {
'VIEW' = 'VIEW',
'EDIT' = 'EDIT',
'CREATE' = 'CREATE',
}

type FormModeContextType = {
mode: FormMode;
setMode: (mode: FormMode) => void;
isViewMode: boolean;
isEditMode: boolean;
isCreateMode: boolean;
};

const FormModeContext = createContext<FormModeContextType | undefined>(
undefined,
);

export const useFormMode = (): FormModeContextType => {
const context = useContext(FormModeContext);

if (!context) {
throw new Error('useFormMode must be used within a FormModeProvider');
}

return context;
};

export const FormModeProvider = ({
children,
initialFormMode,
}: PropsWithChildren<{ initialFormMode: FormMode }>) => {
const [mode, setMode] = useState<FormMode>(() => initialFormMode);

// Memoize the context value to avoid unnecessary re-renders
const value = useMemo(
() => ({
mode,
setMode,
isViewMode: mode === FormMode.VIEW,
isEditMode: mode === FormMode.EDIT,
isCreateMode: mode === FormMode.CREATE,
}),
[mode],
);

return (
<FormModeContext.Provider value={value}>
{children}
</FormModeContext.Provider>
);
};
'use client';

import React, { createContext, useContext, useMemo, useState } from 'react';

import type { PropsWithChildren } from 'react';

export enum FormMode {
'VIEW' = 'VIEW',
'EDIT' = 'EDIT',
'CREATE' = 'CREATE',
}

type FormModeContextType = {
mode: FormMode;
setMode: (mode: FormMode) => void;
isViewMode: boolean;
isEditMode: boolean;
isCreateMode: boolean;
};

const FormModeContext = createContext<FormModeContextType | undefined>(
undefined,
);

export const useFormMode = (): FormModeContextType => {
const context = useContext(FormModeContext);

if (!context) {
throw new Error('useFormMode must be used within a FormModeProvider');
}

return context;
};

export const FormModeProvider = ({
children,
initialFormMode,
}: PropsWithChildren<{ initialFormMode: FormMode }>) => {
const [mode, setMode] = useState<FormMode>(() => initialFormMode);

// Memoize the context value to avoid unnecessary re-renders
const value = useMemo(
() => ({
mode,
setMode,
isViewMode: mode === FormMode.VIEW,
isEditMode: mode === FormMode.EDIT,
isCreateMode: mode === FormMode.CREATE,
}),
[mode],
);

return (
<FormModeContext.Provider value={value}>
{children}
</FormModeContext.Provider>
);
};
Page RSC
export default async function LocationView({
params,
}: {
params: { locationId: string };
}) {
...

return (
<FormModeProvider initialFormMode={FormMode.VIEW}>
<LocationForm defaultFormValues={defaultFormValues} />
</FormModeProvider>
);
}
export default async function LocationView({
params,
}: {
params: { locationId: string };
}) {
...

return (
<FormModeProvider initialFormMode={FormMode.VIEW}>
<LocationForm defaultFormValues={defaultFormValues} />
</FormModeProvider>
);
}
Its telling me to use it withing parent that is client component? Why to? why I cant directly use it in RSC
3 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 10/4/2024 in #questions
nextjs refresh, trpc invalidate order
Does anyone know if order does matter and has any implication in case of trpc invalidation and router.refresh ?
await apiUtils.invalidate();
router.push('/location');
router.refresh();
await apiUtils.invalidate();
router.push('/location');
router.refresh();
vs
router.push('/location');
router.refresh();
await apiUtils.invalidate();
router.push('/location');
router.refresh();
await apiUtils.invalidate();
From what I see in the network tab: 1st case network calls: 1. trpc.query 2. rsc fetch 3. rsc fetch 4. layout fetch 5. page fetch 2nd case network calls: 1. rsc fetch 2. trpc.query 3. rsc fetch 4. layout fetch 5. page fetch
2 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 10/2/2024 in #questions
tRPC mutation onError handler error type for shared logic
I have two mutations on my frontend that should handle the response in the same way. So I extract the onError function so these two mutations can re-use the logic but I have a problem on how to type the error so the in function handling is pleased with typescript and the onError handler is also pleased.
// What type of the error should be here?
const onApiError = (error: ???) => {...}


const createMutation = api.location.create.useMutation({ onError: onApiError });
const editMutation = api.location.edit.useMutation({ onError: onApiError });
// What type of the error should be here?
const onApiError = (error: ???) => {...}


const createMutation = api.location.create.useMutation({ onError: onApiError });
const editMutation = api.location.edit.useMutation({ onError: onApiError });
I have tried like error: TRPCClientError<AppRouter> this does satisfy the function and internal of it but doesn't comply with the onError handlers onError: onApiError
5 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/21/2024 in #questions
Transform/map source object to target object with schema/map
I am looking for a robust way of mapping API fields to UI fields in a sense of something like DTOs but that doesn’t require much boilerplate code.
I have found what I think a great library that would fit my need but unfortunately it’s not longer maintained https://www.npmjs.com/package/morphism so can’t use it as is in newer projects so I wonder about making a copy of it or trying to do something similar as I can’t find anything else with such functionalities. I wonder if something similar could be achieved with use of zod and its transform option. Anyone aware of similar libs? Would zod fit in this case? The thing with zod that bother me is after failed parsing I only get the error and the part of successfully parsed input is lost. Or does zod support returning error alongside already parsed data?
2 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/9/2024 in #questions
New Zod schema based on an existing one, with some fields having different validation rules?
Having some schema how I could re-use the schema and access some of its fields and change their validation to make up new schema.
const schema = z.object({
details: z.object({
name: z.string(),
street: z.string(),
coordinates: z.object({
lat: z.string(),
long: z.string(),
}),
}).partial().optional(),
id: z.string().uuid(),
})
const schema = z.object({
details: z.object({
name: z.string(),
street: z.string(),
coordinates: z.object({
lat: z.string(),
long: z.string(),
}),
}).partial().optional(),
id: z.string().uuid(),
})
Given this schema I would like the name field to be required/min length and have a new schema from this initial one with the rest fields being as is. In the inital schema only id would be required with the sub-schema id and name should be required rest optional
5 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/3/2024 in #questions
typescript object util library
Is there any good typescript library for object manipulation? Ie changing values of deeply nested objects, getting values via dot notation keys. Setting via dot notation etc
9 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/3/2024 in #questions
Use Zod schema after parse & transform as a new schema
I am looking how I could handle from validation with one schema so it can be used on the ReactHookForm zod resolver and tRPC input validation. lets say my form accepts two values
const schema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),

})

type SchemaT = z.infer<typeof asd>

const asdzz: SchemaT = {
bir: 'asd',name: 'as'
}
const schema = z.object({
name: z.string(),
bir: z.object({
value: z.string(),
label: z.string(),
}).transform(val => val.value),

})

type SchemaT = z.infer<typeof asd>

const asdzz: SchemaT = {
bir: 'asd',name: 'as'
}
schema is a parser for client form input which I would like to use resulting type of that schema as a new schema for tRPC input validation. Can I do this somehow? Or my bet is just don't do the transform and use that schema both on client and backend and on backend extract needed fields and do further processing. This will be simpler but unnecessary bloat of data payload would be then sent to the server
7 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 8/30/2024 in #questions
BUILD TypeCheck and Lint disabled
I’ve seen Theo disabling typecheck and eslint during the build process, which greatly improves the build time. How can I apply these steps in a separate workflow? What are the equivalent npm commands for running typecheck and eslint independently as they run during the build? Will these separate commands execute the same steps as during the build process, or are there any differences?
3 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 8/28/2024 in #questions
Use ReactQuery to fetch different api resource than trpc resource
I have an api endpoint which I can call using fetch. How one would re-use reactquery and call that endpoint directly. Do I need separate reactquery client?
5 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 1/9/2024 in #questions
Logging trpc errors in production
What is the proper place for logging errors in production originating from trpc when I use NEXT 14 app router trpc setup. Should I log from nextjs trpc api route handler?
const createContext = async (req: NextRequest) => {
return createTRPCContext({
headers: req.headers,
});
};

const handler = (req: NextRequest) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext: () => createContext(req),
onError: ({ path, error }) => {
if (serverEnv.NODE_ENV === 'development') {
trpcLogger.error(
`❌ tRPC failed on ${path ?? '<no-path>'}: ${error.message}`,
);
}
},
});

export { handler as GET, handler as POST };
const createContext = async (req: NextRequest) => {
return createTRPCContext({
headers: req.headers,
});
};

const handler = (req: NextRequest) =>
fetchRequestHandler({
endpoint: '/api/trpc',
req,
router: appRouter,
createContext: () => createContext(req),
onError: ({ path, error }) => {
if (serverEnv.NODE_ENV === 'development') {
trpcLogger.error(
`❌ tRPC failed on ${path ?? '<no-path>'}: ${error.message}`,
);
}
},
});

export { handler as GET, handler as POST };
Or maybe from server trpcproxyclient handler??
export const api = createTRPCProxyClient<AppRouter>({
transformer,
links: [
loggerLink({
enabled: (op) =>
process.env.NODE_ENV === 'development' ||
(op.direction === 'down' && op.result instanceof Error),
}),
/**
* Custom RSC link that lets us invoke procedures without using http requests. Since Server
* Components always run on the server, we can just call the procedure as a function.
*/
() =>
({ op }) =>
observable((observer) => {
createContext()
.then((ctx) => {
return callProcedure({
procedures: appRouter._def.procedures,
path: op.path,
rawInput: op.input,
ctx,
type: op.type,
});
})
.then((data) => {
observer.next({ result: { data } });
observer.complete();
})
.catch((cause: TRPCErrorResponse) => {
observer.error(TRPCClientError.from(cause));
});
}),
],
});
export const api = createTRPCProxyClient<AppRouter>({
transformer,
links: [
loggerLink({
enabled: (op) =>
process.env.NODE_ENV === 'development' ||
(op.direction === 'down' && op.result instanceof Error),
}),
/**
* Custom RSC link that lets us invoke procedures without using http requests. Since Server
* Components always run on the server, we can just call the procedure as a function.
*/
() =>
({ op }) =>
observable((observer) => {
createContext()
.then((ctx) => {
return callProcedure({
procedures: appRouter._def.procedures,
path: op.path,
rawInput: op.input,
ctx,
type: op.type,
});
})
.then((data) => {
observer.next({ result: { data } });
observer.complete();
})
.catch((cause: TRPCErrorResponse) => {
observer.error(TRPCClientError.from(cause));
});
}),
],
});
In the loggerlink? or catch of the observable?? Im but confused where errors originate from
4 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 11/30/2023 in #questions
TRPC Server error handling?
So I've been refactoring my old project with T3 +app router that @julius recently added to T3 stack and I was just fiddling around trpc and its context I stumbled upon a problem. I have a trpc middleware that checks for authed user enforceUserIsAuthed
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.sessionIdToken) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}

return next({
ctx: {
...
},
});
});
const enforceUserIsAuthed = t.middleware(({ ctx, next }) => {
if (!ctx.sessionIdToken) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}

return next({
ctx: {
...
},
});
});
And there is a problem. When I use the client trpc calls (react) I have a onError props for queryclient that I can check for that error and react (especially for 401 and redirect). But when it throws in the RSC this triggers error boundaries and throws uncaught TRPCClienterror. How am I supposed to handle server errors in this case? createTRPCProxyClient doesnt seem to have any onerror handler.
6 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 11/7/2023 in #questions
CSP with NextJs 14 and express
Hello, I am having a problem with CSP when using NExtjs with custom express server. I use app router and wanted to add CSP headers using helmet for express. As soon as I add the helmet middleware I see that CSP is blocking all my scripts and can't figure it out how to tackle this. Has someone such setup or any tips how do I work it out? All I can find online is for pages dir...
1 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 10/15/2023 in #questions
trpc nextjs and expressjs middleware
I've custom expressjs server with Nextjs + im using internal package for handling OneLogin (OIDC) hooked as express middleware which runs. before the Nextjs handler for custom server. I encounter a problem where I do fire a request api call via trpc query or mutation and the OIDC middleware catches that the request is 401 then trpc throws TRPCClientError: Unexpected token 'U', "Unauthorized" is not valid JSON if I change the response of the middleware as a json instead of text something like
app.use((req, res, next) => {
if (/* some condition checking for the cookie */) {
next();
} else {
// Respond with a 401 status and a JSON body
res.status(401).json({ error: "Unauthorized" });
}
});
app.use((req, res, next) => {
if (/* some condition checking for the cookie */) {
next();
} else {
// Respond with a 401 status and a JSON body
res.status(401).json({ error: "Unauthorized" });
}
});
Then I get app-index.js:31 TRPCClientError: Unexpected non-whitespace character after JSON at position 14 (line 1 column 15) with tRPC. What do i need to do to handle the 401 via trpc and be able to redirect the user to login "client side redirect at this point"
1 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/27/2023 in #questions
T3 env in nextjs custom typescript server
Hello, Im trying to setup Nextjs 13 app router with custom server with typescript. So far so good I was able to get the latest tRPC setup with nextjs13 app router and custom express server entry point all in typescript. But I would Like to use T3Env in that custom express server entry point but Im failing to do so. Complaining about the esm module inported in that cusotm server file. This is insane how much you need to fiddle to get something like that working in 2023 😄 anyway... I've followed this repo from vercel to get express server entry point working but dunno how to reconfigure it so I could use env.mjs Version I've used for T3 Stack https://discord.com/channels/966627436387266600/988912020558602331/1150912514322870322 Ts custom server example from vercel https://github.com/vercel/next.js/tree/canary/examples/custom-server I would appreciate any suggestions. Fighting with it for 2 days already
1 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/21/2023 in #questions
tsx Unexpected response from worker: undefined
Anyone using nextjs with custom server as .ts file ?? I can't get it to work to run in development with watch mode using tsx or ts-node-dev keep getting
TypeError: Unexpected response from worker: undefined
at ChildProcessWorker._onMessage (.......\node_modules\next\dist\compiled\jest-worker\index.js:1:12492)
TypeError: Unexpected response from worker: undefined
at ChildProcessWorker._onMessage (.......\node_modules\next\dist\compiled\jest-worker\index.js:1:12492)
2 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 9/19/2023 in #questions
T3 Env - Remix
https://env.t3.gg/docs/core
The core package can be used in any framework of your choice.
Would it work no problem in remix app ??
3 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 8/3/2023 in #questions
RPC like endpoints
Anyone had used NextJs server routes as a RPC like endpoints? I would like just to use NextJs backend as a proxy to my 3rd party API (which is the source of truth backend) but without any additional middle man setup. So just having Fetch client to talk to the API and call it directly from my client but with the ability to hide internals from the client (any secrets/auth etc). I found this one https://telefunc.com/ which seems like a good fit but seems barely used. Also from my understanding about new React Server Components I should be able to call my FetchClientAPI directly from RSC and pass data to the client component but still it leaves the mutations part to be covered. Maybe https://trpc.io/ would be better here? (yet still there is a bit of boilerplate just to be able to call the API). Are there any more alternatives that I can look into? P.S. - NextJs 13 app folder - Application is only used as an admin panel for serving the data of the API.
1 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 7/12/2023 in #questions
NextJs 13 app folder - SPA
I want to migrate 3yrs old React-Express app. Im considering migrating to Nextjs App folder. What is the current state with making SPA with the NextJS 13 app folder. Is it viable? I really dont care about RSC for now but it might be useful once it matures so I want to go full SPA at this time anyway. This is an admin dashboard app with OAuth wall so no need for any SEO and you can only interact with the app once logged in. It must be dockerized and no plans to host on vercel. Also it currently uses passport and trpc so I expect I would need to use express server with nextjs to keep the passport oauth flow to be compatible with what its for now (I would need to keep both apps simultaneously and serve nextjs app page by page with swap to the old app until its fully migrated to the nextjs) Are there any problems with App dir and SPA approach? Is there anything to keep in mind when using app dir? Do I need to mark every component with 'use client'? Appreciate any help 😉 P.S. Any link to github repo with example SPA App folder would be awesome ❤️
5 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 6/21/2023 in #questions
Typed API contract builder
I've external third party API which doesn't expose any types (no typescript compatible). I would like to be able to define type safe contracts for that API so body, query params, response type etc. is all type safe. Ideally it should be based/wrapped on fetch or implemented with https://github.com/elbywan/wretch or https://github.com/unjs/ofetch. This won't be exposed for anyone. It will be used only internally and only on the backend side so no need for any browser compatibilty. I just want an easy type safe way to define input/outputs and use it from within my express/trpc calls I've found these which resonate a bit with my need but im not sure if there any better ones or should I build something myself. https://ts-rest.com/ https://www.zodios.org/ Any recommendations?
10 replies
TTCTheo's Typesafe Cult
Created by Mugetsu on 5/6/2023 in #questions
Handling UI components (SR) libs with Next13/app
How one would handle an UI component library wich supports Server rendering of those components within the new Next13 app folder? Up until now there was hook points in _app and _document Where you could setup the library to work on Server/Client but How about now.? How about Server components ?
1 replies