diff --git a/components/apex/apex.app.mjs b/components/apex/apex.app.mjs index 07165160faf05..bcf7febcb6b44 100644 --- a/components/apex/apex.app.mjs +++ b/components/apex/apex.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/components/openthesaurus/openthesaurus.app.mjs b/components/openthesaurus/openthesaurus.app.mjs index 64d70b740acae..0bc5dea72a19e 100644 --- a/components/openthesaurus/openthesaurus.app.mjs +++ b/components/openthesaurus/openthesaurus.app.mjs @@ -8,4 +8,4 @@ export default { console.log(Object.keys(this.$auth)); }, }, -}; \ No newline at end of file +}; diff --git a/packages/connect-react/CHANGELOG.md b/packages/connect-react/CHANGELOG.md index 5f8fc1f5775a5..eedcf1ee6416f 100644 --- a/packages/connect-react/CHANGELOG.md +++ b/packages/connect-react/CHANGELOG.md @@ -2,6 +2,20 @@ # Changelog +## [2.0.0] - 2025-10-02 + +### Breaking Changes + +Use the new v2 version of the Pipedream SDK (i.e. `@pipedreamhq/pipedream-sdk`). +This change involves migrating to the new types mostly, but also runtime changes +involving the API calls. + +The runtime behavior should not be affected from a user's perspective, except +for consumers of the `connect-react` package itself, since some components (e.g. +`FrontendClientProvider`) expect their consumers to inject a client instance of +the same SDK version. For this reason, this change bumps the **major** version +of this package. + ## [1.5.0] - 2025-08-18 ### Fixed diff --git a/packages/connect-react/package.json b/packages/connect-react/package.json index 2325c08092601..024bd45e639bc 100644 --- a/packages/connect-react/package.json +++ b/packages/connect-react/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/connect-react", - "version": "1.6.0", + "version": "2.0.0", "description": "Pipedream Connect library for React", "files": [ "dist" @@ -30,7 +30,7 @@ "author": "Pipedream Engineering", "license": "MIT", "dependencies": { - "@pipedream/sdk": "^1.8.0", + "@pipedream/sdk": "^2.0.13", "@tanstack/react-query": "^5.59.16", "lodash.isequal": "^4.5.0", "react-markdown": "^9.0.1", diff --git a/packages/connect-react/src/components/ComponentForm.tsx b/packages/connect-react/src/components/ComponentForm.tsx index 36787255b77fb..571935e6118eb 100644 --- a/packages/connect-react/src/components/ComponentForm.tsx +++ b/packages/connect-react/src/components/ComponentForm.tsx @@ -1,12 +1,14 @@ -import { - FormContextProvider, type FormContext, -} from "../hooks/form-context"; -import { DynamicProps } from "../types"; import type { + Component, ConfigurableProps, ConfiguredProps, - V1Component, + DynamicProps, } from "@pipedream/sdk"; + +import { + type FormContext, + FormContextProvider, +} from "../hooks/form-context"; import { InternalComponentForm } from "./InternalComponentForm"; export type ComponentFormProps> = { @@ -18,7 +20,7 @@ export type ComponentFormProps; + component: Component; configuredProps?: U; // XXX value? disableQueryDisabling?: boolean; // dynamicPropsId?: string // XXX need to load this initially when passed diff --git a/packages/connect-react/src/components/Control.tsx b/packages/connect-react/src/components/Control.tsx index b7c2c661f612e..cc11ad5e781f0 100644 --- a/packages/connect-react/src/components/Control.tsx +++ b/packages/connect-react/src/components/Control.tsx @@ -38,7 +38,7 @@ export function Control return = idx} />; } - if ("options" in prop && prop.options) { + if ("options" in prop && Array.isArray(prop.options) && prop.options.length > 0) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const options: LabelValueOption[] = prop.options.map(sanitizeOption); return a.name} + getOptionLabel={(a) => a.name ?? ""} getOptionValue={(a) => a.id} onChange={(a) => { if (a) { diff --git a/packages/connect-react/src/components/ControlInput.tsx b/packages/connect-react/src/components/ControlInput.tsx index 3bbf53a08bb81..a3cd4ff7a9df6 100644 --- a/packages/connect-react/src/components/ControlInput.tsx +++ b/packages/connect-react/src/components/ControlInput.tsx @@ -1,6 +1,7 @@ import type { CSSProperties } from "react"; import { useFormFieldContext } from "../hooks/form-field-context"; import { useCustomize } from "../hooks/customization-context"; +import { isConfigurablePropOfType } from "../utils/type-guards"; export function ControlInput() { const formFieldContextProps = useFormFieldContext(); @@ -46,20 +47,23 @@ export function ControlInput() { autoComplete = "new-password"; // in chrome, this is better than "off" here } + const min = isConfigurablePropOfType(prop, "integer") + ? prop.min + : undefined; + const max = isConfigurablePropOfType(prop, "integer") + ? prop.max + : undefined; + return ( onChange(toOnChangeValue(e.target.value))} {...getProps("controlInput", baseStyles, formFieldContextProps)} - min={"min" in prop - ? prop.min - : undefined} - max={"max" in prop - ? prop.max - : undefined} + min={min} + max={max} autoComplete={autoComplete} data-lpignore="true" data-1p-ignore="true" diff --git a/packages/connect-react/src/components/ControlSelect.tsx b/packages/connect-react/src/components/ControlSelect.tsx index cb555808c9928..3d7c0a3499853 100644 --- a/packages/connect-react/src/components/ControlSelect.tsx +++ b/packages/connect-react/src/components/ControlSelect.tsx @@ -1,3 +1,4 @@ +import type { PropOptionValue } from "@pipedream/sdk"; import { useEffect, useMemo, @@ -22,7 +23,7 @@ import { import { LoadMoreButton } from "./LoadMoreButton"; // XXX T and ConfigurableProp should be related -type ControlSelectProps = { +type ControlSelectProps = { isCreatable?: boolean; options: LabelValueOption[]; selectProps?: ReactSelectProps, boolean>; @@ -31,7 +32,7 @@ type ControlSelectProps = { components?: ReactSelectProps, boolean>["components"]; }; -export function ControlSelect({ +export function ControlSelect({ isCreatable, options, selectProps, @@ -83,37 +84,29 @@ export function ControlSelect({ return null; } - let ret = rawValue; - if (Array.isArray(ret)) { + if (Array.isArray(rawValue)) { // if simple, make lv (XXX combine this with other place this happens) - if (!isOptionWithLabel(ret[0])) { - return ret.map((o) => - selectOptions.find((item) => item.value === o) || { - label: String(o), - value: o, - }); + if (!isOptionWithLabel(rawValue[0])) { + return rawValue.map((o) => + selectOptions.find((item) => item.value === o) || sanitizeOption(o as T)); } - } else if (ret && typeof ret === "object" && "__lv" in ret) { - // Extract the actual option from __lv wrapper - ret = ret.__lv; - } else if (!isOptionWithLabel(ret)) { + } else if (rawValue && typeof rawValue === "object" && "__lv" in (rawValue as Record)) { + // Extract the actual option from __lv wrapper and sanitize to LV + return sanitizeOption(((rawValue as Record).__lv) as T); + } else if (!isOptionWithLabel(rawValue)) { const lvOptions = selectOptions?.[0] && isOptionWithLabel(selectOptions[0]); if (lvOptions) { for (const item of selectOptions) { if (item.value === rawValue) { - ret = item; - break; + return item; } } } else { - ret = { - label: String(rawValue), - value: rawValue, - } + return sanitizeOption(rawValue as T); } } - return ret; + return null; }, [ rawValue, selectOptions, diff --git a/packages/connect-react/src/components/ControlSql.tsx b/packages/connect-react/src/components/ControlSql.tsx index a04dc99c1708b..7da64ce46560a 100644 --- a/packages/connect-react/src/components/ControlSql.tsx +++ b/packages/connect-react/src/components/ControlSql.tsx @@ -1,7 +1,7 @@ import { useFormFieldContext } from "../hooks/form-field-context"; import { useCustomize } from "../hooks/customization-context"; import type { CSSProperties } from "react"; -import type { ConfigurablePropSql } from "@pipedream/sdk"; +import { isConfigurablePropOfType } from "../utils/type-guards"; // Type guard to check if value is a structured SQL object const isSqlStructuredValue = (value: unknown): value is { app: string; query: string; params: unknown[] } => { @@ -16,15 +16,17 @@ const isSqlStructuredValue = (value: unknown): value is { app: string; query: st export function ControlSql() { const formFieldContext = useFormFieldContext(); const { - id, onChange, prop, value, + id, onChange, prop: sqlProp, value, } = formFieldContext; + + if (!isConfigurablePropOfType(sqlProp, "sql")) { + throw new Error("ControlSql used with non-sql prop"); + } + 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 @@ -65,11 +67,11 @@ export function ControlSql() { return (