John
John
CCConvex Community
Created by Abhishek on 2/7/2024 in #support-community
getUserIdentity() resulting none
I think these are the docs for what you're tryinging to do. for example, here's a snippet for an nextjs api route where I used the auth token from clerk to call a mutation that requires a logged in user:
import { NextRequest, NextResponse } from "next/server";
import { api } from "@/convex/_generated/api";
import { fetchMutation } from "convex/nextjs";
import { auth } from "@clerk/nextjs";

// Clerk auth token for server-side requests
export async function getAuthToken() {
return (await auth().getToken({ template: "convex" })) ?? undefined;
}

export async function POST(req: NextRequest) {
const token = await getAuthToken();

///... do stuff

const postUrl = await fetchMutation(api.images.generateUploadUrl);

const result = await fetch(postUrl, {
method: "POST",
headers: { "Content-Type": "image/jpeg" },
body: blobImage,
});

const { storageId } = await result.json();

// pass in token here
await fetchMutation(api.images.storeStorageId, { storageId }, { token });

return new NextResponse(...);
}
import { NextRequest, NextResponse } from "next/server";
import { api } from "@/convex/_generated/api";
import { fetchMutation } from "convex/nextjs";
import { auth } from "@clerk/nextjs";

// Clerk auth token for server-side requests
export async function getAuthToken() {
return (await auth().getToken({ template: "convex" })) ?? undefined;
}

export async function POST(req: NextRequest) {
const token = await getAuthToken();

///... do stuff

const postUrl = await fetchMutation(api.images.generateUploadUrl);

const result = await fetch(postUrl, {
method: "POST",
headers: { "Content-Type": "image/jpeg" },
body: blobImage,
});

const { storageId } = await result.json();

// pass in token here
await fetchMutation(api.images.storeStorageId, { storageId }, { token });

return new NextResponse(...);
}
I can't remember if you also need a middleware.ts file for clerk, but heres the one I used for reference:
import { authMiddleware } from "@clerk/nextjs";

export default authMiddleware({
publicRoutes: ["/", "/images-pool"],
});

export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
import { authMiddleware } from "@clerk/nextjs";

export default authMiddleware({
publicRoutes: ["/", "/images-pool"],
});

export const config = {
matcher: ["/((?!.+\\.[\\w]+$|_next).*)", "/", "/(api|trpc)(.*)"],
};
20 replies
CCConvex Community
Created by John on 2/6/2024 in #support-community
{"code":"BadJsonBody","message":"Failed to buffer the request body: length limit exceeded"}
Instance name: precious-squid-669
6 replies
CCConvex Community
Created by John on 2/6/2024 in #support-community
{"code":"BadJsonBody","message":"Failed to buffer the request body: length limit exceeded"}
These are the helper functions used in the action:
async function store(ctx: ActionCtx, base64Image: string, userId: Id<"users">) {
const blob = base64ToBlob(base64Image);
const storageId: Id<"_storage"> = await ctx.storage.store(blob as Blob);
await ctx.runMutation(internal.images.storeResult, {
storageId: storageId,
user: userId,
});
}

function base64ToBlob(base64: string) {
const byteCharacters = atob(base64.split(",")[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
return new Blob([byteArray], { type: "image/png" });
}
async function store(ctx: ActionCtx, base64Image: string, userId: Id<"users">) {
const blob = base64ToBlob(base64Image);
const storageId: Id<"_storage"> = await ctx.storage.store(blob as Blob);
await ctx.runMutation(internal.images.storeResult, {
storageId: storageId,
user: userId,
});
}

function base64ToBlob(base64: string) {
const byteCharacters = atob(base64.split(",")[1]);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
return new Blob([byteArray], { type: "image/png" });
}
6 replies
CCConvex Community
Created by John on 2/6/2024 in #support-community
{"code":"BadJsonBody","message":"Failed to buffer the request body: length limit exceeded"}
This is the Convex action that times out when called directly.
"use node";
import { v } from "convex/values";
import { ActionCtx, action } from "./_generated/server";
import { internal } from "./_generated/api";
import { Id } from "./_generated/dataModel";

interface GenerationResponse {
artifacts: Array<{
base64: string;
seed: number;
finishReason: string;
}>;
}

export const generateImage = action({
args: { base64Image: v.string() },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
throw new Error("you must be logged in to upload images");
}
const user = await ctx.runQuery(internal.users.getUserById, {
userId: identity.subject,
});

if (!user) {
throw new Error("user not found");
}

const sourceImage = args.base64Image;
const imageBlob = base64ToBlob(sourceImage);

const formData = new FormData();
formData.append("init_image", imageBlob);
formData.append("samples", "10"); // number of images to generate
//... more params, out of text space for discord

const response = await fetch(
"https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/image-to-image",
{
headers: {
Authorization: `Bearer ${process.env.STABLE_DIFFUSION_API_KEY}`,
},
body: formData,
method: "POST",
},
);

const responseJSON = (await response.json()) as GenerationResponse;

const images = responseJSON.artifacts.map(
(artifact) => `data:image/jpeg;base64,${artifact.base64}`,
);

const storeImagePromises = images.map((image) => {
console.log("storing", image);
return store(ctx, image, user._id);
});

await Promise.all(storeImagePromises);

return images;
},
});
"use node";
import { v } from "convex/values";
import { ActionCtx, action } from "./_generated/server";
import { internal } from "./_generated/api";
import { Id } from "./_generated/dataModel";

interface GenerationResponse {
artifacts: Array<{
base64: string;
seed: number;
finishReason: string;
}>;
}

export const generateImage = action({
args: { base64Image: v.string() },
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) {
throw new Error("you must be logged in to upload images");
}
const user = await ctx.runQuery(internal.users.getUserById, {
userId: identity.subject,
});

if (!user) {
throw new Error("user not found");
}

const sourceImage = args.base64Image;
const imageBlob = base64ToBlob(sourceImage);

const formData = new FormData();
formData.append("init_image", imageBlob);
formData.append("samples", "10"); // number of images to generate
//... more params, out of text space for discord

const response = await fetch(
"https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/image-to-image",
{
headers: {
Authorization: `Bearer ${process.env.STABLE_DIFFUSION_API_KEY}`,
},
body: formData,
method: "POST",
},
);

const responseJSON = (await response.json()) as GenerationResponse;

const images = responseJSON.artifacts.map(
(artifact) => `data:image/jpeg;base64,${artifact.base64}`,
);

const storeImagePromises = images.map((image) => {
console.log("storing", image);
return store(ctx, image, user._id);
});

await Promise.all(storeImagePromises);

return images;
},
});
6 replies
CCConvex Community
Created by John on 2/1/2024 in #support-community
WorkOS Authkit as Custom Auth Integration with Convex
was mainly curious about workos since it says 1million free users going to just using clerk, the templates/doc and web dev cody yt videos were great references!
7 replies
CCConvex Community
Created by jamwt on 6/7/2023 in #support-community
Looking for something?
this search tool is awesome! especially that it also indexes discord 🤯 Are these the relevant repos for the search? Frontend Doc/Stack index Discord index
32 replies