Trader Launchpad
Trader Launchpad
Explore posts from servers
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 2/16/2024 in #questions
CTA v7.26.0 is giving "fetch is not a function" error
@cje Found the answer. I had to modify next.config:
await import("./src/env.mjs");

/** @type {import("next").NextConfig} */
const config = {
experimental: {
serverComponentsExternalPackages: ["monday-sdk-js"],
},
};

export default config;
await import("./src/env.mjs");

/** @type {import("next").NextConfig} */
const config = {
experimental: {
serverComponentsExternalPackages: ["monday-sdk-js"],
},
};

export default config;
7 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 2/16/2024 in #questions
CTA v7.26.0 is giving "fetch is not a function" error
it does. Also spinning up a ct3app and downgrading the next version to 13.4 fixes the issue. It is something to do with next between 13.4 and 14.x. I believe has something to do with no longer needing the serverAction experimental flag, or the fact that nextjs14 no longer polyfills node-fetch. i have searched for a few days, on nextjs and monday-sdk-js githubs, opened a few issues and discussions. No one has responded.
7 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 2/16/2024 in #questions
CTA v7.26.0 is giving "fetch is not a function" error
I am still struggling with this.
7 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 2/14/2024 in #questions
Thoughts on how to integrate t3 app, connectkit web3 auth, nextjs middleware, and trpc
The matcher is stock from nextjs documentation, and it runs on every route including /api and trpc calls. When I have this middleware enabled I am getting an error on the front page of t3 app, on the standard post.hello trpc call:
RequestContentLengthMismatchError: Request body length does not match content-length header
RequestContentLengthMismatchError: Request body length does not match content-length header
When I disable the middleware, this issue goes away. I believe it is due to my nextjs middleware matcher running on every request, and blocking /siwe as a publicpath if they ARE authenticated, sending them to / and something is getitng lost on the trpc side. To clarify on a page reload the middleware is hit multiple times, once on "/", once on "/siwe" which is triggered every page reload by the ClientProvider. The error only happens on the call that originated from "/siwe" Strangely if I simply move /siwe to /api/siwe, the error goes away. Also if I remove the
if (isPublicPath) {
if (isPublicPath) {
logic the error goes away. What is the correct way to setup the nextjs middleware in this situation? Should I just add /siwe as an ignored route in the middleware matcher? Should i be putting my /siwe logic in trpc routes and calling it that way (api.user.getNonce, api.user.verifyNonce. api.user.createSession, ect)?
4 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 2/14/2024 in #questions
Thoughts on how to integrate t3 app, connectkit web3 auth, nextjs middleware, and trpc
const siweConfig = {
getNonce: async () => {
const res = await fetch(`/siwe`, { method: "PUT" });
if (!res.ok) throw new Error("Failed to fetch SIWE nonce");

return res.text();
},
createMessage: ({ nonce, address, chainId }) => {
return new SiweMessage({
nonce,
chainId,
address,
version: "1",
uri: window.location.origin,
domain: window.location.host,
statement: "Sign In With Ethereum to prove you control this wallet.",
}).prepareMessage();
},
verifyMessage: ({ message, signature }) => {
return fetch(`/siwe`, {
method: "POST",
body: JSON.stringify({ message, signature }),
headers: { "Content-Type": "application/json" },
}).then((res) => res.ok);
},
getSession: async () => {
const res = await fetch(`/siwe`);
if (!res.ok) throw new Error("Failed to fetch SIWE session");

const { address, chainId } = await res.json();
return address && chainId ? { address, chainId } : null;
},
signOut: () => fetch(`/siwe`, { method: "DELETE" }).then((res) => res.ok),
} satisfies SIWEConfig;
const siweConfig = {
getNonce: async () => {
const res = await fetch(`/siwe`, { method: "PUT" });
if (!res.ok) throw new Error("Failed to fetch SIWE nonce");

return res.text();
},
createMessage: ({ nonce, address, chainId }) => {
return new SiweMessage({
nonce,
chainId,
address,
version: "1",
uri: window.location.origin,
domain: window.location.host,
statement: "Sign In With Ethereum to prove you control this wallet.",
}).prepareMessage();
},
verifyMessage: ({ message, signature }) => {
return fetch(`/siwe`, {
method: "POST",
body: JSON.stringify({ message, signature }),
headers: { "Content-Type": "application/json" },
}).then((res) => res.ok);
},
getSession: async () => {
const res = await fetch(`/siwe`);
if (!res.ok) throw new Error("Failed to fetch SIWE session");

const { address, chainId } = await res.json();
return address && chainId ? { address, chainId } : null;
},
signOut: () => fetch(`/siwe`, { method: "DELETE" }).then((res) => res.ok),
} satisfies SIWEConfig;
Then i have setup a custom nextjs middleware that checks the cookie, and redirects based on authenticated or unauthenticated status:
const PUBLIC_PATHS = ["/register", "/login", "/reset-password", "/siwe"];
...
const session = await Session.fromRequest(request);
if (session.address) {
// User is authenticated
console.log("Authenticated");
if (isPublicPath) {
// Redirect authenticated users away from public paths to the home page
url.pathname = "/";
return NextResponse.redirect(url);
}
...
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
const PUBLIC_PATHS = ["/register", "/login", "/reset-password", "/siwe"];
...
const session = await Session.fromRequest(request);
if (session.address) {
// User is authenticated
console.log("Authenticated");
if (isPublicPath) {
// Redirect authenticated users away from public paths to the home page
url.pathname = "/";
return NextResponse.redirect(url);
}
...
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};
4 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/29/2024 in #questions
Difference between NextAuth + firebase adapter, NextAuth + drizzle adapter, and just using firebase?
No description
6 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/29/2024 in #questions
Difference between NextAuth + firebase adapter, NextAuth + drizzle adapter, and just using firebase?
@Matheus Lasserre Lets say I use Nextauth + drizzle adapter (planetscale) and during the nextauth callback I generate a Firebase custom token and save it into the nextauth session:

...
session: async ({ session, token }) => {
if (session?.user) {
if (token.sub) {
session.user.id = token.sub;

const firebaseToken = await adminAuth.createCustomToken(token.sub);
session.firebaseToken = firebaseToken;
}
}
return session;
},
...

...
session: async ({ session, token }) => {
if (session?.user) {
if (token.sub) {
session.user.id = token.sub;

const firebaseToken = await adminAuth.createCustomToken(token.sub);
session.firebaseToken = firebaseToken;
}
}
return session;
},
...
and then wrap my app in a FirebaseAuthProvider that logs the user in with Firebase:
...
useEffect(() => {
if (session?.firebaseToken) {
signInWithCustomToken(auth, session.firebaseToken)
.then(() => {
console.log(
"Successfully signed in with Firebase using custom token.",
);
})
.catch((error) => {
console.error("Error signing in with custom token:", error);
});
}
}, [session]);
...
...
useEffect(() => {
if (session?.firebaseToken) {
signInWithCustomToken(auth, session.firebaseToken)
.then(() => {
console.log(
"Successfully signed in with Firebase using custom token.",
);
})
.catch((error) => {
console.error("Error signing in with custom token:", error);
});
}
}, [session]);
...
Then i use trpc and drizzle in my nextjs app to fetch and query manipulate data from my planetscale database. Their is account, user, session, and verificationToken tables in my planetscale database. There is also a user showing up in the Firebase Auth UI, with a uid that is the same as their UID in my planetscale database user table. What is the implications if I now wanted to add an EXPO app? Would I use expo/react-native firebase package to sign in the user into Firebase only using custom token? Then use the Firebase UID returned to query the planetscale database from within my expo app? Would i need to interact with the nextauth database tables at all?
6 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/28/2024 in #questions
Why is there no SessionProvider wrapping app in next13+ app router boilerplate?
So can i add SessionProvider to a app directory app, so that I can use client side firebase hooks in my client componets? or should be only be using SessionProvider in nextjs^12 with pages directory?
7 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/9/2024 in #questions
How to find single record in database using trpc and drizzle?
I am still looking for an answer on how to use findfirst with drizzle so it returns a single array rather than an object. I cannot figure out how to use drizzle, findfirst, and a where clause...
11 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/9/2024 in #questions
How to find single record in database using trpc and drizzle?
I think i figured it out:
findUserByDiscordId: publicProcedure
.input(z.object({ discordId: z.string() }))
.query(({ ctx, input }) => {
const data = ctx.db
.select()
.from(users)
.where(eq(users.discordId, input.discordId))
return data;
}),
findUserByDiscordId: publicProcedure
.input(z.object({ discordId: z.string() }))
.query(({ ctx, input }) => {
const data = ctx.db
.select()
.from(users)
.where(eq(users.discordId, input.discordId))
return data;
}),
11 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/8/2024 in #questions
How to?: Sign In With Ethereum and have a user record created?
If i do need to code in my own logic, would it look something like this, and should i go through a trpc route?:
async authorize(credentials, req) {
try {
const siwe = new SiweMessage(
JSON.parse(credentials?.message ?? "{}"),
);
const nextAuthUrl = new URL(process.env.NEXTAUTH_URL!);

const result = await siwe.verify({
signature: credentials?.signature ?? "",
domain: nextAuthUrl.host,
nonce: await getCsrfToken({ req }),
});

console.log("result", result);

if (result.success) {
// Check if the user with this Ethereum address already exists in the database
let user = await db.findUserByWalletId(siwe.address);

if (!user) {
// If the user doesn't exist, create a new user in the database
user = await db.createUser({ walletId: siwe.address });
}

return {
id: siwe.address,
...user, // Include additional user properties from the database
};
}
return null;
} catch (e) {
return null;
}
},
async authorize(credentials, req) {
try {
const siwe = new SiweMessage(
JSON.parse(credentials?.message ?? "{}"),
);
const nextAuthUrl = new URL(process.env.NEXTAUTH_URL!);

const result = await siwe.verify({
signature: credentials?.signature ?? "",
domain: nextAuthUrl.host,
nonce: await getCsrfToken({ req }),
});

console.log("result", result);

if (result.success) {
// Check if the user with this Ethereum address already exists in the database
let user = await db.findUserByWalletId(siwe.address);

if (!user) {
// If the user doesn't exist, create a new user in the database
user = await db.createUser({ walletId: siwe.address });
}

return {
id: siwe.address,
...user, // Include additional user properties from the database
};
}
return null;
} catch (e) {
return null;
}
},
5 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 1/8/2024 in #questions
How to?: Sign In With Ethereum and have a user record created?
...
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
// ...other properties
// role: UserRole;
} & DefaultSession["user"];
}
}

export const authOptions: NextAuthOptions = {
callbacks: {
session: ({ session, token }) => {
return {
...session,
user: {
...session.user,
id: token.sub,
},
};
},
jwt: ({ token, user }) => {
return {
...token,
user,
};
},
},
adapter: DrizzleAdapter(db, mysqlTable),
providers: [
DiscordProvider({
clientId: env.DISCORD_CLIENT_ID,
clientSecret: env.DISCORD_CLIENT_SECRET,
}),
CredentialsProvider({
name: "Ethereum",
credentials: {
message: {
label: "Message",
type: "text",
placeholder: "0x0",
},
signature: {
label: "Signature",
type: "text",
placeholder: "0x0",
},
},
async authorize(credentials, req) {
try {
console.log("siwe step 1");
const siwe = new SiweMessage(
JSON.parse(credentials?.message ?? "{}"),
);
const nextAuthUrl = new URL(process.env.NEXTAUTH_URL!);

const result = await siwe.verify({
signature: credentials?.signature ?? "",
domain: nextAuthUrl.host,
nonce: await getCsrfToken({ req }),
});

console.log("result", result);

if (result.success) {
return {
id: siwe.address,
};
}
return null;
} catch (e) {
return null;
}
},
}),
],
session: { strategy: "jwt" },
};
export const getServerAuthSession = () => getServerSession(authOptions);
...
declare module "next-auth" {
interface Session extends DefaultSession {
user: {
id: string;
// ...other properties
// role: UserRole;
} & DefaultSession["user"];
}
}

export const authOptions: NextAuthOptions = {
callbacks: {
session: ({ session, token }) => {
return {
...session,
user: {
...session.user,
id: token.sub,
},
};
},
jwt: ({ token, user }) => {
return {
...token,
user,
};
},
},
adapter: DrizzleAdapter(db, mysqlTable),
providers: [
DiscordProvider({
clientId: env.DISCORD_CLIENT_ID,
clientSecret: env.DISCORD_CLIENT_SECRET,
}),
CredentialsProvider({
name: "Ethereum",
credentials: {
message: {
label: "Message",
type: "text",
placeholder: "0x0",
},
signature: {
label: "Signature",
type: "text",
placeholder: "0x0",
},
},
async authorize(credentials, req) {
try {
console.log("siwe step 1");
const siwe = new SiweMessage(
JSON.parse(credentials?.message ?? "{}"),
);
const nextAuthUrl = new URL(process.env.NEXTAUTH_URL!);

const result = await siwe.verify({
signature: credentials?.signature ?? "",
domain: nextAuthUrl.host,
nonce: await getCsrfToken({ req }),
});

console.log("result", result);

if (result.success) {
return {
id: siwe.address,
};
}
return null;
} catch (e) {
return null;
}
},
}),
],
session: { strategy: "jwt" },
};
export const getServerAuthSession = () => getServerSession(authOptions);
5 replies
TTCTheo's Typesafe Cult
Created by Tribe on 12/25/2023 in #questions
Adding Supabase to TRPC context
it should work locally with the edge runtime? on every t3 app I have worked in it always gives me errors developing locally with runtime=edge, on my windows pc and macbook :/
11 replies
TTCTheo's Typesafe Cult
Created by Tribe on 12/25/2023 in #questions
Adding Supabase to TRPC context
I commented out
export const runtime = "edge";
export const runtime = "edge";
and it loaded up. I forgot I had that issue on another t3 project. Why does it errror out withc that line in there? Can I make it a variable value based on development or production?
11 replies
TTCTheo's Typesafe Cult
Created by Tribe on 12/25/2023 in #questions
Adding Supabase to TRPC context
No description
11 replies
TTCTheo's Typesafe Cult
Created by Tribe on 12/25/2023 in #questions
Adding Supabase to TRPC context
I an windering if you can assist me @Benja
I am trying to get this working but am having an issue. I think i finally got the supabase pooler connection string working, and got rid of the error:
'invalid_connection_string': This connection string is meant to be used with a direct connection. Make sure to use a pooled connection string or try `createClient()` instead.]
'invalid_connection_string': This connection string is meant to be used with a direct connection. Make sure to use a pooled connection string or try `createClient()` instead.]
now that error is gone, and I am getting error:
[TypeError: Cannot read properties of undefined (reading '')]
@acme/nextjs:dev: ⨯ [TypeError: Cannot read properties of undefined (reading '')]
@acme/nextjs:dev: ⨯ [TypeError: Cannot read properties of null (reading 'default')]
[TypeError: Cannot read properties of undefined (reading '')]
@acme/nextjs:dev: ⨯ [TypeError: Cannot read properties of undefined (reading '')]
@acme/nextjs:dev: ⨯ [TypeError: Cannot read properties of null (reading 'default')]
@julius
11 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 11/10/2023 in #questions
[How To?] Generate uuids properly on cloudflare d1 sqlite...
I can seed the database with data, that does not include a uuid column and it generates the same UUID for each record, not what I want. The uuid itself looks correct, but is not unique. When i try and add a record via trpc/frontend form, with or without a uuid value supplied i get an error: TRPCClientError: Invalid hex string I have tried deleting the uuid field from the drizzle schema, running a migration to overwrite the table, and using the frontend form again. Records populate properly i found this, which I am trying next, but probably would have to pass these commands manually through a drizzle/wrangler migration file rather than through the schema and drizzle generate? https://www.kittell.net/code/auto-increment-auto-generate-guid/ Is anyone else using uuids with cloudflare d1 database? I see there are extension i could load for sqlite that allow for automatic uuids but not sure if i can execute those against cloud d1, even if i were able to get it working with local dev.
3 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 10/31/2023 in #questions
[Nextauth] How to use middleware with grouped routes?
seemed like with all the hooplah over app router nextauth would have implemented it in their middleware. I think i remember somewhere that you could use regex in the matcher. Again not sure if the regex would even pick up on the route group from the url to parse. Its middleware and i suppose doesnt have access to what route groups nextjs has.
8 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 10/31/2023 in #questions
[Nextauth] How to use middleware with grouped routes?
That is what I am using now. I dont personally care that much, just could not find any info on next auth protecting a core functionality of new nextjs, which is route groups.
8 replies
TTCTheo's Typesafe Cult
Created by Trader Launchpad on 10/31/2023 in #questions
[Nextauth] How to use middleware with grouped routes?
Hey thank you for the reply. This is how I currently have it setup, with all admin routes under app/admin/dashboard so they render https://.../admin/dashboard but if i want to use a grouped route so they render https://.../dashboard with them in a nextjs grouped route app/(admin)/dashboard, i cant figure out how to correctly use the matcher. /(admin)/:path* does not work
8 replies