Nicolas
Nicolas
TtRPC
Created by Nicolas on 2/16/2024 in #❓-help
No "mutation"-procedure on path
Hello all, I am using the latest version of TRPC on my client and server. I am using React Query on my client and AWS Lambda on my server side. When trying to perform a test mutation:
export default function () {
const organizationCreate = trpc.insert_superUser.useMutation();
const insertTestOrg = async () => {
const repsonse = organizationCreate.mutate({
name: "Test Organization",
description: "Test Description",
}, {
onError: (error) => {
console.log("Error", error);
}
})
}
return (<div>
<Button variant="primary" onClick={() => insertTestOrg()}>Button</Button>
</div>)
}
export default function () {
const organizationCreate = trpc.insert_superUser.useMutation();
const insertTestOrg = async () => {
const repsonse = organizationCreate.mutate({
name: "Test Organization",
description: "Test Description",
}, {
onError: (error) => {
console.log("Error", error);
}
})
}
return (<div>
<Button variant="primary" onClick={() => insertTestOrg()}>Button</Button>
</div>)
}
I get the following error Error TRPCClientError: No "mutation"-procedure on path "insert_superUser" I am using a Meta to make sure only users of a specified role can call certain functions, like so:
interface Meta {
role: Role;
}
const t = initTRPC.context<Context>().meta<Meta>().create({
defaultMeta: {
role: Role.OrganizationUser
}
});

export const authRoleProcedure = t.procedure.use(async (opts) => {
const { meta, next, ctx } = opts;
if (!meta?.role) {
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Role not defined in meta' });
}
if (!ctx.user) {
throw new TRPCError({ code: 'BAD_REQUEST', message: 'User not defined in context'});
}
if (ctx.user.role > meta.role) {
throw new TRPCError({ code: 'UNAUTHORIZED', message: `User does not have the required role. Required: ${meta.role}, User: ${ctx.user.role}`});
}
console.log('User has the required role')
return next();
});

export const router = t.router;
interface Meta {
role: Role;
}
const t = initTRPC.context<Context>().meta<Meta>().create({
defaultMeta: {
role: Role.OrganizationUser
}
});

export const authRoleProcedure = t.procedure.use(async (opts) => {
const { meta, next, ctx } = opts;
if (!meta?.role) {
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: 'Role not defined in meta' });
}
if (!ctx.user) {
throw new TRPCError({ code: 'BAD_REQUEST', message: 'User not defined in context'});
}
if (ctx.user.role > meta.role) {
throw new TRPCError({ code: 'UNAUTHORIZED', message: `User does not have the required role. Required: ${meta.role}, User: ${ctx.user.role}`});
}
console.log('User has the required role')
return next();
});

export const router = t.router;
3 replies
TtRPC
Created by Nicolas on 11/17/2023 in #❓-help
Creating inner context for AWS Lambda Context Options
Hi All, I have been using tRPC for many routes, and I have started to realize I need to call certain routes on the server-side (lambda / serverless in my case), and so I was trying to follow the documentation on how to create an inner context / outer context so I can call my tRPC routes from other routes, but I am stuck and I am confused on how to go about doing it for AWS lambda context as the documentation example is rather simple. This is what I have so far:
import { inferAsyncReturnType } from "@trpc/server";
import type { CreateAWSLambdaContextOptions } from "@trpc/server/adapters/aws-lambda";
import type { APIGatewayProxyEventV2 } from "aws-lambda";
import { CognitoJwtVerifier } from "aws-jwt-verify";

/**
* Defines your inner context shape.
* Add fields here that the inner context brings.
*/
interface CreateInnerContextOptions extends Partial<CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>>{
context: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>["context"] | undefined;
event: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>["event"] | undefined;

}

/**
* Inner context. Will always be available in your procedures, in contrast to the outer context.
*
* Also useful for:
* - testing, so you don't have to mock Next.js' `req`/`res`
* - tRPC's `createServerSideHelpers` where we don't have `req`/`res`
*
* @see https://trpc.io/docs/context#inner-and-outer-context
*/
export async function createContextInner(opts?: CreateInnerContextOptions) {
return {
context: opts?.context,
event: opts?.event,
};
}

/**
* Outer context. Used in the routers and will e.g. bring `req` & `res` to the context as "not `undefined`".
*
* @see https://trpc.io/docs/context#inner-and-outer-context
*/

export async function createContext({ event }: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) {
async function getUserFromHeader() {
// Verifier that expects valid access tokens:
if (process.env.USER_POOL_ID === undefined || process.env.USER_POOL_CLIENT_ID == undefined) {
throw new Error("Missing environment variables");
}
if (event.headers.authorization) {
const token = event.headers.authorization.split(" ")[1];
const verifier = CognitoJwtVerifier.create({
userPoolId: process.env.USER_POOL_ID,
tokenUse: "id",
clientId: process.env.USER_POOL_CLIENT_ID,
});
// the Authorization header will contain the JWT token as a Bearer token, we need to remove the Bearer part before we can verify the token
const payload = await verifier.verify(token);
return {
role: payload["cognito:groups"],
username: payload["cognito:username"],
orgId: payload["custom:organizationId"] ? (payload["custom:organizationId"] as string) : undefined,
};
}
throw new Error("No authorization header");
}
const user = await getUserFromHeader();

const contextInner = await createContextInner({ context: undefined, event: undefined });

return {
...contextInner,
event: event,
apiVersion: (event as { version?: string }).version ?? "1.0",
user: user,
};
}



export type Context = inferAsyncReturnType<typeof createContextInner>;
import { inferAsyncReturnType } from "@trpc/server";
import type { CreateAWSLambdaContextOptions } from "@trpc/server/adapters/aws-lambda";
import type { APIGatewayProxyEventV2 } from "aws-lambda";
import { CognitoJwtVerifier } from "aws-jwt-verify";

/**
* Defines your inner context shape.
* Add fields here that the inner context brings.
*/
interface CreateInnerContextOptions extends Partial<CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>>{
context: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>["context"] | undefined;
event: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>["event"] | undefined;

}

/**
* Inner context. Will always be available in your procedures, in contrast to the outer context.
*
* Also useful for:
* - testing, so you don't have to mock Next.js' `req`/`res`
* - tRPC's `createServerSideHelpers` where we don't have `req`/`res`
*
* @see https://trpc.io/docs/context#inner-and-outer-context
*/
export async function createContextInner(opts?: CreateInnerContextOptions) {
return {
context: opts?.context,
event: opts?.event,
};
}

/**
* Outer context. Used in the routers and will e.g. bring `req` & `res` to the context as "not `undefined`".
*
* @see https://trpc.io/docs/context#inner-and-outer-context
*/

export async function createContext({ event }: CreateAWSLambdaContextOptions<APIGatewayProxyEventV2>) {
async function getUserFromHeader() {
// Verifier that expects valid access tokens:
if (process.env.USER_POOL_ID === undefined || process.env.USER_POOL_CLIENT_ID == undefined) {
throw new Error("Missing environment variables");
}
if (event.headers.authorization) {
const token = event.headers.authorization.split(" ")[1];
const verifier = CognitoJwtVerifier.create({
userPoolId: process.env.USER_POOL_ID,
tokenUse: "id",
clientId: process.env.USER_POOL_CLIENT_ID,
});
// the Authorization header will contain the JWT token as a Bearer token, we need to remove the Bearer part before we can verify the token
const payload = await verifier.verify(token);
return {
role: payload["cognito:groups"],
username: payload["cognito:username"],
orgId: payload["custom:organizationId"] ? (payload["custom:organizationId"] as string) : undefined,
};
}
throw new Error("No authorization header");
}
const user = await getUserFromHeader();

const contextInner = await createContextInner({ context: undefined, event: undefined });

return {
...contextInner,
event: event,
apiVersion: (event as { version?: string }).version ?? "1.0",
user: user,
};
}



export type Context = inferAsyncReturnType<typeof createContextInner>;
5 replies
TtRPC
Created by Nicolas on 9/30/2023 in #❓-help
Basic Inference not Working
I have been struggling to get basic type inferencing to work with trpc, react, and Drizzle ORM. This is what my server-side router is returning from the list method:
export const organizationRouter = router({
list: adminProcedure.query(async () => {
const response = await listOrganizations.all();
return response;
}),
export const organizationRouter = router({
list: adminProcedure.query(async () => {
const response = await listOrganizations.all();
return response;
}),
Where, if I hover over the response in the return, it says the type is:
const response: {
id: number;
name: string;
description: string | null;
}[]
const response: {
id: number;
name: string;
description: string | null;
}[]
However, on my client side, it says the type is any for the following:
const organizationData = trpc.organization.list.useQuery();
organizationData.data <---- ANY
const organizationData = trpc.organization.list.useQuery();
organizationData.data <---- ANY
Why is this basic type inferencing not happening? I am using Drizzle ORM to infer the return type on the router response; could this have something to do with it? Does trpc not work well with ORM's that use inference?
4 replies
TtRPC
Created by Nicolas on 8/31/2023 in #❓-help
Issue Inferring Type on Frontend with ElectroDB Query Return Statement
No description
3 replies