Skip to content
Merged
4 changes: 4 additions & 0 deletions packages/connect-react/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

# Changelog

# [1.2.0] - 2025-06-05

- Adding basic support for 'sql' prop types

# [1.1.0] - 2025-06-04

- Adding support for 'object' prop types
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.1.0",
"version": "1.2.0",
"description": "Pipedream Connect library for React",
"files": [
"dist"
Expand Down
3 changes: 3 additions & 0 deletions packages/connect-react/src/components/Control.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ControlBoolean } from "./ControlBoolean";
import { ControlInput } from "./ControlInput";
import { ControlObject } from "./ControlObject";
import { ControlSelect } from "./ControlSelect";
import { ControlSql } from "./ControlSql";
import { RemoteOptionsContainer } from "./RemoteOptionsContainer";

export type ControlProps<T extends ConfigurableProps, U extends ConfigurableProp> = {
Expand Down Expand Up @@ -82,6 +83,8 @@ export function Control<T extends ConfigurableProps, U extends ConfigurableProp>
return <ControlInput />;
case "object":
return <ControlObject />;
case "sql":
return <ControlSql />;
default:
// TODO "not supported prop type should bubble up"
throw new Error("Unsupported property type: " + prop.type);
Expand Down
76 changes: 76 additions & 0 deletions packages/connect-react/src/components/ControlSql.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { useFormFieldContext } from "../hooks/form-field-context";
import { useCustomize } from "../hooks/customization-context";
import type { CSSProperties } from "react";
import type { ConfigurablePropSql } from "@pipedream/sdk";

// Type guard to check if value is a structured SQL object
const isSqlStructuredValue = (value: unknown): value is { app: string; query: string; params: unknown[] } => {
return (
typeof value === "object" &&
value !== null &&
"query" in value &&
typeof (value as Record<string, unknown>).query === "string"
);
};

export function ControlSql() {
const formFieldContext = useFormFieldContext();
const {
id, onChange, prop, value,
} = formFieldContext;
const {
getProps, theme,
} = useCustomize();

// Cast prop to SQL prop type (this component is only used for SQL props)
const sqlProp = prop as ConfigurablePropSql;

// Get the app name from the SQL prop's auth configuration
const appName = sqlProp.auth?.app || "postgresql"; // Default to postgresql

// Extract the query string from the structured value or use empty string
let queryValue = "";
if (isSqlStructuredValue(value)) {
queryValue = value.query;
} else if (typeof value === "string") {
queryValue = value;
}

const handleChange = (queryText: string) => {
// Transform the simple query string into the structured SQL object
const sqlObject = {
app: appName,
query: queryText,
params: [], // For now, always empty array
};
onChange(sqlObject);
};

const baseStyles: CSSProperties = {
color: theme.colors.neutral60,
display: "block",
border: "1px solid",
borderColor: theme.colors.neutral20,
padding: 6,
width: "100%",
borderRadius: theme.borderRadius,
gridArea: "control",
boxShadow: theme.boxShadow.input,
fontSize: "0.875rem",
fontFamily: "monospace",
minHeight: "120px",
resize: "vertical",
};

return (
<textarea
id={id}
name={prop.name}
value={queryValue}
onChange={(e) => handleChange(e.target.value)}
placeholder="SELECT * FROM table_name"
required={!prop.optional}
{...getProps("controlSql", baseStyles, formFieldContext)}
/>
);
}
2 changes: 2 additions & 0 deletions packages/connect-react/src/hooks/customization-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { ControlBoolean } from "../components/ControlBoolean";
import { ControlInput } from "../components/ControlInput";
import { ControlObject } from "../components/ControlObject";
import { ControlSelect } from "../components/ControlSelect";
import { ControlSql } from "../components/ControlSql";
import { ControlSubmit } from "../components/ControlSubmit";
import { Description } from "../components/Description";
import { Errors } from "../components/Errors";
Expand Down Expand Up @@ -73,6 +74,7 @@ export type CustomizableProps = {
controlBoolean: ComponentProps<typeof ControlBoolean> & FormFieldContext<ConfigurableProp>;
controlInput: ComponentProps<typeof ControlInput> & FormFieldContext<ConfigurableProp>;
controlObject: ComponentProps<typeof ControlObject> & FormFieldContext<ConfigurableProp>;
controlSql: ComponentProps<typeof ControlSql> & FormFieldContext<ConfigurableProp>;
controlSubmit: ComponentProps<typeof ControlSubmit>;
description: ComponentProps<typeof Description>;
error: ComponentProps<typeof Errors>;
Expand Down
1 change: 1 addition & 0 deletions packages/connect-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { ControlApp } from "./components/ControlApp";
export { ControlBoolean } from "./components/ControlBoolean";
export { ControlInput } from "./components/ControlInput";
export { ControlSelect } from "./components/ControlSelect";
export { ControlSql } from "./components/ControlSql";
export { ControlSubmit } from "./components/ControlSubmit";
export { Description } from "./components/Description";
export { ErrorBoundary } from "./components/ErrorBoundary";
Expand Down
Loading