Skip to content

[pull] main from baptisteArno:main #293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .cursor/rules/general.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ alwaysApply: true

- Never use `any` type. Always use proper TypeScript types, interfaces, or union types instead.
- Use `satisfies` instead of `as` when possible to make sure we keep strong type-safety.
- Prefer writing long and complex functions that provide good, deep abstraction. These functions should have a TSDoc comment description of what it does in great details. Avoid providing `@param` description, params name should be self-explanatory. In the function itself you can add inline comments only if the code is hard to understand.
- Prefer writing long and complex functions that provide good, deep abstraction. These functions should have a TSDoc comment description of what it does in great details. Avoid providing `@param` description, params name should be self-explanatory. IMPORTANT: Only add inline comments if a piece of logic is hard to understand, it should ideally explain what happens in the next N lines of code, never add a comment to explain a single line.
- Prefer infer the return type of a function instead of declaring it.
- Helper functions should be placed at the bottom of the file.

## Testing
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { stringify } from "querystring";
import { CopyButton } from "@/components/CopyButton";
import { TextInput } from "@/components/inputs/TextInput";
import { useWorkspace } from "@/features/workspace/WorkspaceProvider";
Expand All @@ -21,6 +20,7 @@ import { useMutation } from "@tanstack/react-query";
import type { ForgedBlockDefinition } from "@typebot.io/forge-repository/definitions";
import { Button } from "@typebot.io/ui/components/Button";
import { useState } from "react";
import { useOAuthPopup } from "./useOAuthPopup";

type Props = {
blockDef: ForgedBlockDefinition;
Expand Down Expand Up @@ -69,7 +69,6 @@ export const CreateForgedOAuthCredentialsModalContent = ({
"blockDef" | "onNewCredentials" | "defaultData" | "editorContext" | "scope"
>) => {
const { workspace } = useWorkspace();
const [isAuthorizing, setIsAuthorizing] = useState(false);
const [name, setName] = useState("");
const [tab, setTab] = useState<"default" | "your-app">(
blockDef.auth && "defaultClientEnvKeys" in blockDef.auth
Expand All @@ -95,54 +94,42 @@ export const CreateForgedOAuthCredentialsModalContent = ({
}),
);

const openOAuthPopup = async () => {
const handleOAuthSuccess = (code: string) => {
if (!workspace) return;

setIsAuthorizing(true);

window.open(
`/api/${blockDef.id}/oauth/authorize?${stringify({
clientId: clientId,
})}`,
"oauthPopup",
"width=500,height=700",
);

const handleOAuthResponse = (event: MessageEvent) => {
if (event.data?.type === "oauth") {
window.removeEventListener("message", handleOAuthResponse);
setIsAuthorizing(false);
const { code } = event.data;
const credentials = {
name,
blockType: blockDef.id,
code,
customClient:
tab === "your-app"
? {
id: clientId,
secret: clientSecret,
}
: undefined,
};
mutate(
scope === "workspace"
? {
...credentials,
scope: "workspace",
workspaceId: workspace.id,
}
: {
...credentials,
scope: "user",
},
);
}
const credentials = {
name: name.trim(),
blockType: blockDef.id,
code,
customClient:
tab === "your-app"
? {
id: clientId.trim(),
secret: clientSecret.trim(),
}
: undefined,
};

window.addEventListener("message", handleOAuthResponse);
mutate(
scope === "workspace"
? {
...credentials,
scope: "workspace",
workspaceId: workspace.id,
}
: {
...credentials,
scope: "user",
},
);
};

const { openOAuthPopup, isAuthorizing } = useOAuthPopup({
blockId: blockDef.id,
clientId,
workspace: workspace ?? null,
onSuccess: handleOAuthSuccess,
});

if (!blockDef.auth) return null;
return (
<ModalContent>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { stringify } from "querystring";
import { CopyButton } from "@/components/CopyButton";
import { TextInput } from "@/components/inputs/TextInput";
import { useWorkspace } from "@/features/workspace/WorkspaceProvider";
Expand All @@ -19,6 +18,7 @@ import { useMutation, useQuery } from "@tanstack/react-query";
import type { ForgedBlockDefinition } from "@typebot.io/forge-repository/definitions";
import { Button } from "@typebot.io/ui/components/Button";
import { useEffect, useState } from "react";
import { useOAuthPopup } from "./useOAuthPopup";

type Props = {
credentialsId: string;
Expand Down Expand Up @@ -96,42 +96,31 @@ export const UpdateForgedOAuthCredentialsModalContent = ({
}),
);

const openOAuthPopup = async () => {
const handleOAuthSuccess = (code: string) => {
if (!workspace) return;

window.open(
`/api/${blockDef.id}/oauth/authorize?${stringify({
clientId: clientId,
})}`,
"oauthPopup",
"width=500,height=700",
);

const handleOAuthResponse = (event: MessageEvent) => {
if (event.data?.type === "oauth") {
window.removeEventListener("message", handleOAuthResponse);
const { code } = event.data;
mutate({
name,
blockType: blockDef.id,
workspaceId: workspace.id,
credentialsId,
code,
customClient:
tab === "your-app"
? {
id: clientId,
secret: clientSecret,
}
: undefined,
});
}
};

window.removeEventListener("message", handleOAuthResponse);
window.addEventListener("message", handleOAuthResponse);
mutate({
name,
blockType: blockDef.id,
workspaceId: workspace.id,
credentialsId,
code,
customClient:
tab === "your-app"
? {
id: clientId,
secret: clientSecret,
}
: undefined,
});
};

const { openOAuthPopup, isAuthorizing } = useOAuthPopup({
blockId: blockDef.id,
clientId,
workspace: workspace ?? null,
onSuccess: handleOAuthSuccess,
});

if (!blockDef.auth) return null;
return (
<ModalContent>
Expand Down Expand Up @@ -196,7 +185,8 @@ export const UpdateForgedOAuthCredentialsModalContent = ({
disabled={
!name ||
isPending ||
(tab === "your-app" && (!clientId || !clientSecret))
(tab === "your-app" && (!clientId || !clientSecret)) ||
isAuthorizing
}
>
<blockDef.LightLogo />
Expand Down
Loading
Loading