Skip to content

Adding support for oauthAppId in connect-react #17116

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
11 changes: 10 additions & 1 deletion components/discord/actions/common/common.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
export default {
props: {
discord,
channel: {

Check warning on line 7 in components/discord/actions/common/common.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop channel must have a description. See https://pipedream.com/docs/components/guidelines/#props

Check warning on line 7 in components/discord/actions/common/common.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop channel must have a label. See https://pipedream.com/docs/components/guidelines/#props
type: "$.discord.channel",
appProp: "discord",
},
Expand Down Expand Up @@ -66,7 +66,16 @@
},
getSentViaPipedreamText() {
const workflowId = process.env.PIPEDREAM_WORKFLOW_ID;
return `Sent via [Pipedream](<https://pipedream.com/@/${workflowId}?o=a&a=discord>)`;
const baseLink = "https://pipedream.com";
const linkText = !workflowId
? "Pipedream Connect"
: "Pipedream";

const link = !workflowId
? `${baseLink}/connect`
: `${baseLink}/@/${encodeURIComponent(workflowId)}?o=a&a=discord`;

return `Sent via [${linkText}](<${link}>)`;
},
getMessageFlags(suppressNotifications) {
let flags = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
key: "discord-send-message-advanced",
name: "Send Message (Advanced)",
description: "Send a simple or structured message (using embeds) to a Discord channel",
version: "1.0.2",
version: "1.0.3",
type: "action",
props: {
...common.props,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
key: "discord-send-message-with-file",
name: "Send Message With File",
description: "Post a message with an attached file",
version: "1.1.1",
version: "1.1.2",
type: "action",
props: {
...common.props,
Expand Down
2 changes: 1 addition & 1 deletion components/discord/actions/send-message/send-message.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default {
key: "discord-send-message",
name: "Send Message",
description: "Send a simple message to a Discord channel",
version: "1.0.2",
version: "1.0.3",
type: "action",
async run({ $ }) {
const {
Expand Down
4 changes: 2 additions & 2 deletions components/discord/discord.app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export default {
type: "boolean",
optional: true,
default: true,
label: "Include link to workflow",
description: "Defaults to `true`, includes a link to this workflow at the end of your Discord message.",
label: "Include link to Pipedream",
description: "Defaults to `true`, includes a link to Pipedream at the end of your Discord message.",
},
embeds: {
type: "any",
Expand Down
2 changes: 1 addition & 1 deletion components/discord/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/discord",
"version": "1.2.4",
"version": "1.2.5",
"description": "Pipedream Discord Components",
"main": "discord.app.mjs",
"keywords": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

export default {
key: "discord-message-deleted",
name: "Message Deleted (Instant)",

Check warning on line 5 in components/discord/sources/message-deleted/message-deleted.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Source names should start with "New". See https://pipedream.com/docs/components/guidelines/#source-name
description: "Emit new event for each message deleted",
version: "0.0.3",
version: "0.0.4",
dedupe: "unique",
type: "source",
props: {
Expand All @@ -16,7 +16,7 @@
description: "Select the channel(s) you'd like to be notified for",
optional: true,
},
discordApphook: {

Check warning on line 19 in components/discord/sources/message-deleted/message-deleted.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop discordApphook must have a description. See https://pipedream.com/docs/components/guidelines/#props

Check warning on line 19 in components/discord/sources/message-deleted/message-deleted.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop discordApphook must have a label. See https://pipedream.com/docs/components/guidelines/#props
type: "$.interface.apphook",
appProp: "discord",
eventNames() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
key: "discord-new-command-received",
name: "New Command Received (Instant)",
description: "Emit new event for each command posted to one or more channels in a Discord server",
version: "0.0.3",
version: "0.0.4",
dedupe: "unique",
props: {
discord,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
key: "discord-new-guild-member",
name: "New Guild Member (Instant)",
description: "Emit new event for each new member added to a guild",
version: "0.0.3",
version: "0.0.4",
dedupe: "unique",
type: "source",
props: {
discord,
discordApphook: {

Check warning on line 12 in components/discord/sources/new-guild-member/new-guild-member.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop discordApphook must have a description. See https://pipedream.com/docs/components/guidelines/#props

Check warning on line 12 in components/discord/sources/new-guild-member/new-guild-member.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop discordApphook must have a label. See https://pipedream.com/docs/components/guidelines/#props
type: "$.interface.apphook",
appProp: "discord",
eventNames: [
Expand Down
2 changes: 1 addition & 1 deletion components/discord/sources/new-message/new-message.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
key: "discord-new-message",
name: "New Message (Instant)",
description: "Emit new event for each message posted to one or more channels in a Discord server",
version: "1.0.3",
version: "1.0.4",

dedupe: "unique",
props: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

export default {
key: "discord-reaction-added",
name: "Reaction Added (Instant)",

Check warning on line 5 in components/discord/sources/reaction-added/reaction-added.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Source names should start with "New". See https://pipedream.com/docs/components/guidelines/#source-name
description: "Emit new event for each reaction added to a message",
version: "0.0.3",
version: "0.0.4",
type: "source",
props: {
discord,
Expand All @@ -15,7 +15,7 @@
description: "Select the channel(s) you'd like to be notified for",
optional: true,
},
discordApphook: {

Check warning on line 18 in components/discord/sources/reaction-added/reaction-added.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop discordApphook must have a description. See https://pipedream.com/docs/components/guidelines/#props

Check warning on line 18 in components/discord/sources/reaction-added/reaction-added.mjs

View workflow job for this annotation

GitHub Actions / Lint Code Base

Component prop discordApphook must have a label. See https://pipedream.com/docs/components/guidelines/#props
type: "$.interface.apphook",
appProp: "discord",
eventNames() {
Expand Down
2 changes: 1 addition & 1 deletion components/slack/actions/common/send-message.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export default {

const link = !workflowId
? `${baseLink}/connect`
: `${baseLink}/@/${workflowId}?o=a&a=slack`;
: `${baseLink}/@/${encodeURIComponent(workflowId)}?o=a&a=slack`;

return {
"type": "context",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
key: "slack-reply-to-a-message",
name: "Reply to a Message Thread",
description: "Send a message as a threaded reply. See [postMessage](https://api.slack.com/methods/chat.postMessage) or [scheduleMessage](https://api.slack.com/methods/chat.scheduleMessage) docs here",
version: "0.1.28",
version: "0.1.29",
type: "action",
props: {
slack: common.props.slack,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
key: "slack-send-block-kit-message",
name: "Build and Send a Block Kit Message",
description: "Configure custom blocks and send to a channel, group, or user. [See the documentation](https://api.slack.com/tools/block-kit-builder).",
version: "0.4.4",
version: "0.4.5",
type: "action",
props: {
slack: common.props.slack,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default {
key: "slack-send-large-message",
name: "Send a Large Message (3000+ characters)",
description: "Send a large message (more than 3000 characters) to a channel, group or user. See [postMessage](https://api.slack.com/methods/chat.postMessage) or [scheduleMessage](https://api.slack.com/methods/chat.scheduleMessage) docs here",
version: "0.0.23",
version: "0.0.24",
type: "action",
props: {
slack: common.props.slack,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
key: "slack-send-message-advanced",
name: "Send Message (Advanced)",
description: "Customize advanced setttings and send a message to a channel, group or user. See [postMessage](https://api.slack.com/methods/chat.postMessage) or [scheduleMessage](https://api.slack.com/methods/chat.scheduleMessage) docs here",
version: "0.0.6",
version: "0.0.7",
type: "action",
props: {
slack: common.props.slack,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
key: "slack-send-message-to-channel",
name: "Send Message to Channel",
description: "Send a message to a public or private channel. [See the documentation](https://api.slack.com/methods/chat.postMessage)",
version: "0.0.4",
version: "0.0.5",
type: "action",
props: {
slack: common.props.slack,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
key: "slack-send-message-to-user-or-group",
name: "Send Message to User or Group",
description: "Send a message to a user or group. [See the documentation](https://api.slack.com/methods/chat.postMessage)",
version: "0.0.4",
version: "0.0.5",
type: "action",
props: {
slack: common.props.slack,
Expand Down
2 changes: 1 addition & 1 deletion components/slack/actions/send-message/send-message.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default {
key: "slack-send-message",
name: "Send Message",
description: "Send a message to a user, group, private channel or public channel. [See the documentation](https://api.slack.com/methods/chat.postMessage)",
version: "0.0.19",
version: "0.0.20",
type: "action",
props: {
slack: common.props.slack,
Expand Down
2 changes: 1 addition & 1 deletion components/slack/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/slack",
"version": "0.9.5",
"version": "0.9.6",
"description": "Pipedream Slack Components",
"main": "slack.app.mjs",
"keywords": [
Expand Down
20 changes: 20 additions & 0 deletions packages/connect-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@

# Changelog

# [1.4.0] - 2025-06-13

## Added

- Support for `oauthAppId` parameter in `ComponentForm` and `ComponentFormContainer` components
- Pass `oauthAppId` through to `ControlApp` component for OAuth app-specific account connections

## Usage

```typescript
<ComponentForm
externalUserId="user123"
component={component}
oauthAppId="your-oauth-app-id" // New optional prop
// ... other props
/>
```

This allows you to specify which OAuth app to use when connecting accounts, matching the behavior of the SDK's `connectAccount` method.

# [1.3.0] - 2025-06-10

## Added
Expand Down
47 changes: 37 additions & 10 deletions packages/connect-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ import { fetchToken } from "./actions";

export default function Page() {
// https://pipedream.com/docs/connect/api#external-users
const userId = "my-authed-user-id";
const externalUserId = "my-authed-user-id";
const client = createFrontendClient({
environment: "development",
externalUserId: userId,
externalUserId: externalUserId,
tokenCallback: fetchToken,
});
const [configuredProps, setConfiguredProps] = useState({
Expand All @@ -97,7 +97,7 @@ export default function Page() {
<div>My application</div>
<FrontendClientProvider client={client}>
<ComponentFormContainer
userId={userId}
externalUserId={externalUserId}
componentKey="slack-send-message"
configuredProps={configuredProps}
onUpdateConfiguredProps={setConfiguredProps}
Expand Down Expand Up @@ -137,25 +137,51 @@ type ComponentFormContainerProps = {
type ComponentFormProps = {
component: typeof import("@pipedream/sdk").V1Component;
/** External user configuring the form */
userId: string;
externalUserId: string;
/** @deprecated Use externalUserId instead */
userId?: string;
/** Form configured values */
configuredProps?: Record<string, any>;
/** Filtering configurable props */
propNames?: string[];
/** Shows submit button + callback when clicked */
onSubmit: (ctx: FormContext) => Awaitable<void>;
onSubmit?: (ctx: FormContext) => Awaitable<void>;
/** To control and store configured values on form updates, can be used to call actionRun or triggerDeploy */
onUpdateConfiguredProps: (v: Record<string, any>) => void;
onUpdateConfiguredProps?: (v: Record<string, any>) => void;
/** Hide optional props section */
hideOptionalProps: boolean;
hideOptionalProps?: boolean;
/** SDK response payload. Used in conjunction with enableDebugging to
* show errors in the form. */
sdkResponse: unknown[] | unknown | undefined;
/** Whether to show show errors in the form. Requires sdkErrors to be set. */
sdkResponse?: unknown[] | unknown | undefined;
/** Whether to show errors in the form. Requires sdkResponse to be set. */
enableDebugging?: boolean;
/** Optional OAuth app ID for app-specific account connections */
oauthAppId?: string;
};
```

## OAuth Configuration

By default, apps use Pipedream OAuth clients. To configured your own, refer to the docs [here](https://pipedream.com/docs/connect/managed-auth/oauth-clients).

### Using a custom OAuth client

1. Create an OAuth app in your target service (e.g., Slack, Google, etc.)
2. Configure the client in Pipedream ([refer to the docs](https://pipedream.com/docs/connect/managed-auth/oauth-clients))
3. Use the `oauthAppId` prop to specify which OAuth client to use for account connections

```typescript
<ComponentFormContainer
externalUserId={externalUserId}
componentKey="slack-send-message-to-channel"
configuredProps={configuredProps}
onUpdateConfiguredProps={setConfiguredProps}
oauthAppId="your-custom-oauth-app-id" // oa_xxxxxxx
/>
```

When `oauthAppId` is provided, all app connections within that component form will use your specified OAuth app instead of Pipedream's default.

## Customization

Style individual components using the `CustomizeProvider` and a `CustomizationConfig`.
Expand All @@ -164,7 +190,8 @@ Style individual components using the `CustomizeProvider` and a `CustomizationCo
<FrontendClientProvider client={client}>
<CustomizeProvider {...customizationConfig}>
<ComponentFormContainer
key="slack-send-message"
externalUserId={externalUserId}
componentKey="slack-send-message"
configuredProps={configuredProps}
onUpdateConfiguredProps={setConfiguredProps}
/>
Expand Down
2 changes: 1 addition & 1 deletion packages/connect-react/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/connect-react",
"version": "1.3.0",
"version": "1.4.0",
"description": "Pipedream Connect library for React",
"files": [
"dist"
Expand Down
22 changes: 15 additions & 7 deletions packages/connect-react/src/components/ComponentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
V1Component,
} from "@pipedream/sdk";
import { InternalComponentForm } from "./InternalComponentForm";
import { OAuthAppProvider } from "../hooks/oauth-app-context";

export type ComponentFormProps<T extends ConfigurableProps, U = ConfiguredProps<T>> = {
/**
Expand All @@ -29,15 +30,22 @@ export type ComponentFormProps<T extends ConfigurableProps, U = ConfiguredProps<
hideOptionalProps?: boolean;
sdkResponse?: unknown | undefined;
enableDebugging?: boolean;
} & (
| { externalUserId: string; userId?: never }
| { userId: string; externalUserId?: never }
);
/**
* Optional OAuth app ID for app-specific account connections
*/
oauthAppId?: string;
};

export function ComponentForm<T extends ConfigurableProps>(props: ComponentFormProps<T>) {
const {
oauthAppId, ...formProps
} = props;

return (
<FormContextProvider props={props}>
<InternalComponentForm />
</FormContextProvider>
<OAuthAppProvider oauthAppId={oauthAppId}>
<FormContextProvider props={formProps}>
<InternalComponentForm />
</FormContextProvider>
</OAuthAppProvider>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,9 @@ export function ComponentFormContainer<T extends ConfigurableProps>(props: Compo
}

// TODO move / improve lib.ts and make sure V1Component and it match / are shared
return <ComponentForm component={component} {...props} />;
const {
componentKey, ...componentFormProps
} = props;
void componentKey; // Mark as intentionally unused
return <ComponentForm component={component} {...componentFormProps} />;
}
5 changes: 3 additions & 2 deletions packages/connect-react/src/components/ControlApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useAccounts } from "../hooks/use-accounts";
import { useFormFieldContext } from "../hooks/form-field-context";
import { useFormContext } from "../hooks/form-context";
import { useCustomize } from "../hooks/customization-context";
import { useOAuthAppContext } from "../hooks/oauth-app-context";
import type { BaseReactSelectProps } from "../hooks/customization-context";
import { useMemo } from "react";
import type { CSSProperties } from "react";
Expand All @@ -30,6 +31,7 @@ type ControlAppProps = {
export function ControlApp({ app }: ControlAppProps) {
const client = useFrontendClient();
const { externalUserId } = useFormContext();
const { oauthAppId } = useOAuthAppContext();
const formFieldCtx = useFormFieldContext<ConfigurablePropApp>();
const {
id, prop, value, onChange,
Expand Down Expand Up @@ -67,15 +69,14 @@ export function ControlApp({ app }: ControlAppProps) {
};
const selectProps = select.getProps("controlAppSelect", baseSelectProps);

const oauthAppId = undefined; // XXX allow customizing
const {
isLoading: isLoadingAccounts,
// TODO error
accounts,
refetch: refetchAccounts,
} = useAccounts(
{
externalUserId,
external_user_id: externalUserId,
app: app.name_slug,
oauth_app_id: oauthAppId,
},
Expand Down
Loading
Loading