diff --git a/.github/workflows/pipedream-sdk-markdown-lint.yaml b/.github/workflows/pipedream-sdk-markdown-lint.yaml
deleted file mode 100644
index 8332eee516a6b..0000000000000
--- a/.github/workflows/pipedream-sdk-markdown-lint.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-name: Lint SDK Markdown Files
-
-on:
- pull_request:
- types: [opened, edited, synchronize]
- paths:
- - 'packages/sdk/**/*.md'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- test:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Lint markdown files
- uses: DavidAnson/markdownlint-cli2-action@v17
- with:
- globs: 'packages/sdk/**/*.md'
diff --git a/.github/workflows/pipedream-sdk-test.yaml b/.github/workflows/pipedream-sdk-test.yaml
deleted file mode 100644
index a9bdf279681fc..0000000000000
--- a/.github/workflows/pipedream-sdk-test.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
-name: Run SDK Tests
-
-on:
- pull_request:
- types: [opened, edited, synchronize]
- paths:
- - 'packages/sdk/**'
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- test:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - uses: pnpm/action-setup@v4.0.0
- with:
- version: 9.14.2
- - name: Get pnpm store directory
- id: pnpm-cache
- run: |
- echo "::set-output name=pnpm_cache_dir::$(pnpm store path)"
- - uses: actions/cache@v4
- name: Setup pnpm cache
- with:
- path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
- key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
- restore-keys: |
- ${{ runner.os }}-pnpm-store-
-
- - name: Set up Node.js
- uses: actions/setup-node@v3
- with:
- node-version: '22'
-
- - name: Install dependencies
- run: pnpm install
- working-directory: packages/sdk
-
- - name: Run tests
- run: pnpm test
- working-directory: packages/sdk
diff --git a/packages/sdk/.eslintignore b/packages/sdk/.eslintignore
deleted file mode 100644
index 1521c8b7652b1..0000000000000
--- a/packages/sdk/.eslintignore
+++ /dev/null
@@ -1 +0,0 @@
-dist
diff --git a/packages/sdk/.gitignore b/packages/sdk/.gitignore
deleted file mode 100644
index b12c26f6f2e29..0000000000000
--- a/packages/sdk/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-dist
-node_modules
-*.env*
diff --git a/packages/sdk/.tool-versions b/packages/sdk/.tool-versions
deleted file mode 100644
index 38ba13262919f..0000000000000
--- a/packages/sdk/.tool-versions
+++ /dev/null
@@ -1 +0,0 @@
-nodejs 22.10.0
diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md
deleted file mode 100644
index d5125e8b1675b..0000000000000
--- a/packages/sdk/CHANGELOG.md
+++ /dev/null
@@ -1,368 +0,0 @@
-
-
-# Changelog
-
-## [1.8.0] - 2025-08-13
-
-### Added
-
-- Added `categoryIds` parameter to `getApps` method for filtering
- apps by category IDs
-- Added `getAppCategories` method to retrieve available app categories
-
-## [1.7.0] - 2025-07-03
-
-### Added
-
-- Added optional scope parameter to backendClient creation.
-
-## [1.6.11] - 2025-07-02
-
-### Added
-
-- Added `stash` to `V1Component`
-
-## [1.6.10] - 2025-07-01
-
-### Added
-
-- Added `sortKey` and `sortDirection` options to the `getApps` method
-
-## [1.6.9] - 2025-06-10
-
-### Added
-
-- Added types for the missing configurable props
-
-## Changed
-
-- Fixed the `Defaultable` type to correctly handle arrays
-- Fixed the `ConfigurablePropTimer` type to define cron expressions and
- time intervals
-- Marked the `auth` field in the SQL prop type as optional
-- Fixed the `App` type to include the `description` field returned by the API
-- Fixed the `GetAppsResponse` type to include the pagination stuff
-
-## [1.6.8] - 2025-06-07
-
-### Added
-
-- Added `endpoint_url` field to the component metadata, providing the URL to the
- HTTP interface of the component.
-- Added missing pagination fields to the `GetComponentsResponse` and
- `GetAccountsResponse` types.
-
-## [1.6.7] - 2025-06-06
-
-### Added
-
-- Added `stashId` option to the `runAction` method, which allows files to be
- persisted between action runs.
-
-## [1.6.6] - 2025-06-05
-
-### Added
-
-- Added support for `sql` prop type for `connect-react` package
-
-## [1.6.5] - 2025-06-02
-
-### Changed
-
-- Fix the `deployTrigger` method so that it sends the workflow ID to the API
-
-## [1.6.4] - 2025-05-30
-
-### Added
-
-- Added `onClose` callback to `connectAccount` method that receives a
- `ConnectStatus` object with `successful` and `completed` boolean properties
-
-## [1.6.3] - 2025-05-20b
-
-### Added
-
-- Added `rawAccessToken` getter to `BackendClient`
-
-## [1.6.2] - 2025-05-20a
-
-### Added
-
-- Added ability to create a `BackendClient` with just an `AccessToken`
-
-## [1.6.1] - 2025-05-20
-
-### Added
-
-- Added `rawToken` getter to `BrowserClient`
-
-### Changed
-
-- changed `GetComponentsResponse` type to include `configurable_props`
-
-## [1.6.0] - 2025-04-30
-
-### Added
-
-- Added `configuredProps` argument to the `updateTrigger` method.
-
-### Changed
-
-- Corrected the return type of `updateTrigger`.
-- Changed the type of property values of `ConfigureComponentContext` from
- explicit `any` to `unknown`.
-
-## [1.5.5] - 2025-04-28
-
-### Changed
-
-- Types and documentation around `configureComponent` `prevContext` and `context`.
-
-## [1.5.4] - 2025-04-25
-
-### Added
-
-- Changed server-side authorized requests to refresh its auth token if it expires
- within 1 second.
-
-## [1.5.3] - 2025-04-18
-
-### Added
-
-- Added `ProxyResponse` type for makeProxyRequest
-- changed the location of connect DEBUG calls so they'll still show in the
- error case.
-
-## [1.5.2] - 2025-04-15
-
-### Added
-
-- PD_SDK_DEBUG env var. Set it to true to enable debugging of Pipedream Connect
- API requests. Simple sanitization is performed to prevent sensitive field leakage
- but use caution.
-
-## [1.5.1] - 2025-04-15
-
-### Added
-
-- `withLabel` to `BaseConfigurableProp` type definition
-- documentation describing various fields in `BaseConfigurableProp`
-- `featured_weight` to `App` type definition now that API returns this value
-
-## [1.5.0] - 2025-04-08
-
-### Added
-
-- Added support for the `query` option to the `configureComponent` method,
- enabling API-based search using the specified query.
-
-## [1.4.0] - 2025-03-12
-
-### Changed
-
-- Added `description` and `component_type` to `V1Component`
-
-## [1.3.3] - 2025-02-5
-
-### Changed
-
-- Add makeProxyRequest function to BaseClient
-
-## [1.3.2] - 2025-02-3
-
-### Changed
-
-- Add getEnvironment function to BaseClient
-
-## [1.3.1] - 2025-01-30
-
-### Changed
-
-- Fix cjs build to transpile and include `oauth4webapi`
-
-## [1.3.0] - 2025-01-30
-
-### Added
-
-- Edge compatible (or closer to it) by replacing `simple-oauth2` with `oauth4webapi`
-- Output esm and cjs instead of just cjs
-- Minimized bundle size
-
-### Chore
-
-- Modernized package to be type: "module"
-- Removed `jest-fetch-mock`
-
-## [1.2.1] - 2025-01-24
-
-### Added
-
-- New types related to API paginated responses
-- New type for a prop configuration options
-
-### Changed
-
-- Fixed the types of the trigger retrieval and deployment methods in the backend
- client to correctly reflect the actual response (which is nested inside a
- `data` field).
-
-## [1.2.0] - 2025-01-23
-
-### Added
-
-- New methods and types to interact with the deployed triggers API
-
-## [1.1.6] - 2025-01-21
-
-### Changed
-
-- Fixed the docs of the `getAccountById` method in the backend client to remove
- arguments that are not actually supported.
-
-## [1.1.5] - 2025-01-14
-
-### Changed
-
-- Corrected the return type of `reloadComponentProps`
-
-## [1.1.4] - 2025-01-08
-
-### Added
-
-- Add pagination parameters to component configuration (`page` and `prevContext`)
-
-## [1.1.3] - 2024-12-13
-
-### Added
-
-- Can now filter `getApps` by whether app `hasComponents`,
- `hasActions`, or `hasTriggers` in the registry
-
-## [1.1.2] - 2024-12-12
-
-### Changed
-
-- Fixed the docstring referring to the `componentConfigure` and
- `reloadComponentProps` methods of the components API
-
-## [1.1.1] - 2024-12-11
-
-### Changed
-
-- Remove deprecated asynchronous response handling code.
-
-## [1.1.0] - 2024-12-10
-
-### Added
-
-- Documented the public methods and types for the components API
-
-### Changed
-
-- Renamed the methods involved with the components API (e.g.
- `componentConfigure` -> `configureComponent`)
-- Renamed the types used for passing options and accessing responses from the
- components API endpoints (e.g. `ComponentRequestResponse` ->
- `GetComponentResponse`)
-- Marked the renamed methods and types as deprecated
-
-## [1.0.12] - 2024-12-06
-
-### Added
-
-- Allow passing `before`, `after` pagination cursors for apps, accounts,
- components endpoints
-
-## [1.0.11] - 2024-12-06
-
-### Added
-
-- Configurable `limit` option for apps, accounts, components endpoints
-
-## [1.0.10] - 2024-12-04
-
-### Changed
-
-- Handle correct casing of `stringOptions` in configure prop response
-
-## [1.0.9] - 2024-12-04
-
-### Added
-
-- `triggerDeploy` preview API
-- `client.version` and `x-pd-sdk-version` header
-
-## [1.0.8] - 2024-11-29
-
-### Changed
-
-- Fix fallback WebSocket import (for new components API)
-
-## [1.0.7] - 2024-11-21
-
-### Changed
-
-- The backend client now correctly uses asynchronous messaging to handle long
- running operations.
-- Updated the backend command line tool to respect the `ENVIRONMENT` env variable
- if set.
-
-## [1.0.6] - 2024-11-20
-
-### Changed
-
-- Use client Connect tokens to make api calls directly from the client.
-- Deprecated the `environments` property on `createFrontendClient` since it is
- now stored in the token
-
-## [1.0.5] - 2024-11-18
-
-### Changed
-
-- The backend client used to default to `production` if the environment was not
- specified. Now `environment` is a required argument for `createBackendClient`
- and must be one of `production` or `development`.
-
-## [1.0.4] - 2024-11-15
-
-### Changed
-
-- Improved the docs of the `getAccountById` method in the backend client to
- clarify the behavior of the new argument.
-
-- Fixed the exported `HTTPAuthType` enum so that it can be used by the consumers
- of the SDK.
-
-## [1.0.3] - 2024-11-14
-
-### Added
-
-- Added a new argument to the `getAccountById` method in the backend client to
- allow the client to retrieve the credentials of the corresponding account.
-
-## [1.0.2] - 2024-11-14
-
-### Changed
-
-- Deprecated the `environment_name` field in the `ConnectTokenOpts` type, as it
- is no longer used by the SDK nor the Connect API. The environment name is now
- exclusively determined by the `environment` field in the `BackendClientOpts`
- type, read during the client creation.
-
-### Added
-
-- Added a new optional flag to `RequestOptions` called `fullResponse`, which
- allows the user to get the full HTTP response object, including the headers
- and status code.
-
-## [1.0.0] - 2024-11-01
-
-### Changed
-
-- Renamed the server-side client class from `ServerClient` to `BackendClient` to
- better indicate its purpose.
-- Removed the `oauthClient` optional argument to the `BackendClient` constructor
-- Renamed the client factory methods so that developers can know exactly the
- kind of client they are creating.
-- Removed project-key-based authentication in favor of a more secure
- token-based authentication using OAuth.
diff --git a/packages/sdk/CONTRIBUTING.md b/packages/sdk/CONTRIBUTING.md
deleted file mode 100644
index db2171db77866..0000000000000
--- a/packages/sdk/CONTRIBUTING.md
+++ /dev/null
@@ -1,96 +0,0 @@
-# How to Contribute to the SDK
-
-## Local Environment Setup
-
-### Global Dependencies
-
-Clone the repo (ideally your own fork of it) and initialize the global
-dependencies like Node.js, NPM, etc. We use [`asdf`](https://asdf-vm.com/) to
-manage these, so assuming we're located in this directory (i.e. `packages/sdk/`)
-we can run the following command to install them:
-
-```shell
-asdf install
-```
-
-If you prefer to use another tool make sure you use the same versions that are
-specified in the `.tool-versions` files [in this current directory, and
-recursively going up until you reach the root of the
-repo](https://asdf-vm.com/guide/getting-started.html#_6-set-a-version).
-
-### Local Dependencies
-
-You can install the package's dependencies by using `pnpm` or `npm`:
-
-```shell
-pnpm install
-```
-
-Since other packages in this repository already use `pnpm`, we recommend you use
-it in this case too to keep your `node_modules` footprint low.
-
-## Build the Package
-
-There's a script that you can invoke with `pnpm` to build the package artifacts:
-
-```shell
-pnpm build
-```
-
-You can also watch the code for changes, and automatically build a new artifact
-after each change with the `watch` script:
-
-```shell
-pnpm watch
-```
-
-### Use the Package
-
-You can use pnpm's `link` command to point other code to your local version of
-this package during development. This lets you test the SDK in other local apps,
-end-to-end.
-
-In this `packages/sdk/` directory:
-
-```shell
-pnpm link --global
-```
-
-> [!NOTE]
-When using the version of Node.js specified in
-[`.tool-versions`](./.tool-versions) (via `asdf`), the command above will
-install the package in the `asdf` Node.js environment. To use this package
-elsewhere, you'll need to use the same version of Node.js. Please reference the
-latest version of [the `.tool-versions` file](./.tool-versions) and add that to
-the `.tool-versions` file in your local project where you'd like to use the SDK.
-
-For example, in your app's directory:
-
-```shell
-# Replace /path/to/pipedream with the actual path to this repository
-grep nodejs /path/to/pipedream/packages/sdk/.tool-versions >> .tool-versions
-asdf install
-pnpm install @pipedream/sdk
-```
-
-Then, link the SDK package to it's local path:
-
-```shell
-pnpm link @pipedream/sdk
-```
-
-To confirm you successfully installed the correct version of the SDK, and that
-it's tied to your local copy of the Pipedream SDK:
-
-```shell
-ls -l node_modules/@pipedream
-```
-
-You should see an output like this one (notice the last line):
-
-```text
-total 0
-drwxr-xr-x 9 jay staff 288 30 Oct 14:01 mysql
-drwxr-xr-x 10 jay staff 320 30 Oct 14:01 platform
-lrwxr-xr-x 1 jay staff 31 30 Oct 14:06 sdk -> ../../../pipedream/packages/sdk
-```
diff --git a/packages/sdk/README.md b/packages/sdk/README.md
index f9438aaaeb30b..dd11556fb2de3 100644
--- a/packages/sdk/README.md
+++ b/packages/sdk/README.md
@@ -1,5 +1,9 @@
# `@pipedream/sdk`
+> **Note:** This package is now maintained in the
+> [pipedream-sdk-typescript](https://github.com/PipedreamHQ/pipedream-sdk-typescript)
+> repository. Visit that to view the most up-to-date code of the SDK.
+
TypeScript SDK for [Pipedream](https://pipedream.com). [See the
docs](https://pipedream.com/docs/connect) for usage instructions.
diff --git a/packages/sdk/examples/browser/Makefile b/packages/sdk/examples/browser/Makefile
deleted file mode 100644
index 31dc6402c352d..0000000000000
--- a/packages/sdk/examples/browser/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-default:
- make -j2 server delayed-open
-
-server:
- cd ../.. && python -m http.server
-
-delayed-open:
- sleep 1 && xdg-open http://localhost:8000/examples/browser/index.html
diff --git a/packages/sdk/examples/browser/index.html b/packages/sdk/examples/browser/index.html
deleted file mode 100644
index 14ca5d69c402c..0000000000000
--- a/packages/sdk/examples/browser/index.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
Load SDK in browser
-
-
-
-
diff --git a/packages/sdk/examples/server/Makefile b/packages/sdk/examples/server/Makefile
deleted file mode 100644
index ff7b4a60c3538..0000000000000
--- a/packages/sdk/examples/server/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-default:
- @node index.mjs
diff --git a/packages/sdk/examples/server/index.mjs b/packages/sdk/examples/server/index.mjs
deleted file mode 100644
index deb30ff419124..0000000000000
--- a/packages/sdk/examples/server/index.mjs
+++ /dev/null
@@ -1,10 +0,0 @@
-import { createBackendClient } from "../../dist/server/server/index.js";
-
-const client = createBackendClient({
- environment: "development",
- credentials: {
- clientId: "not-empty",
- clientSecret: "not-empty",
- },
-});
-console.log("sdk version: " + client.version);
diff --git a/packages/sdk/jest.config.js b/packages/sdk/jest.config.js
deleted file mode 100644
index 67e93f088a952..0000000000000
--- a/packages/sdk/jest.config.js
+++ /dev/null
@@ -1,31 +0,0 @@
-export default {
- testEnvironment: "node",
- roots: [
- "/src",
- ],
- testMatch: [
- "**/__tests__/**/*.ts",
- "**/?(*.)+(spec|test).ts",
- ],
- moduleFileExtensions: [
- "ts",
- "js",
- ],
- moduleNameMapper: {
- "^(.+)\\.js$": "$1",
- },
- extensionsToTreatAsEsm: [
- ".ts",
- ],
- transform: {
- // '^.+\\.[tj]sx?$' to process ts,js,tsx,jsx with `ts-jest`
- // '^.+\\.m?[tj]sx?$' to process ts,js,tsx,jsx,mts,mjs,mtsx,mjsx with `ts-jest`
- "^.+\\.[jt]sx?$": [
- "ts-jest",
- {
- tsconfig: "tsconfig.node.json",
- useESM: true,
- },
- ],
- },
-};
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
deleted file mode 100644
index 5f01499c23dab..0000000000000
--- a/packages/sdk/package.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "name": "@pipedream/sdk",
- "type": "module",
- "version": "1.8.0",
- "description": "Pipedream SDK",
- "main": "./dist/server.js",
- "module": "./dist/server.js",
- "types": "./dist/server.d.ts",
- "browser": "./dist/browser.js",
- "exports": {
- ".": {
- "types": "./dist/server.d.ts",
- "browser": "./dist/browser.js",
- "import": "./dist/server.js",
- "require": "./dist/server.cjs",
- "default": "./dist/server.js"
- },
- "./server": {
- "types": "./dist/server.d.ts",
- "import": "./dist/server.js",
- "require": "./dist/server.cjs"
- },
- "./browser": {
- "types": "./dist/browser.d.ts",
- "import": "./dist/browser.js",
- "require": "./dist/browser.cjs"
- }
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "keywords": [
- "pipedream"
- ],
- "license": "SEE LICENSE IN LICENSE",
- "publishConfig": {
- "access": "public"
- },
- "scripts": {
- "prepublish": "pnpm run build",
- "prebuild": "node scripts/updateVersion.js",
- "build": "rm -rf dist && pnpm run prebuild && tsup --config tsup.server.cjs.config.js && tsup --config tsup.server.esm.config.js && tsup --config tsup.browser.config.js",
- "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest",
- "watch": "nodemon --watch src --exec 'pnpm run build'",
- "cli": "node dist/server/cli.js"
- },
- "files": [
- "dist"
- ],
- "devDependencies": {
- "@types/jest": "^29.5.13",
- "@types/node": "^20.17.6",
- "@types/rails__actioncable": "^6.1.11",
- "@types/ws": "^8.5.13",
- "jest": "^29.7.0",
- "lodash.isequal": "^4.5.0",
- "nodemon": "^3.1.7",
- "ts-jest": "^29.2.5",
- "tsup": "^8.3.6",
- "typescript": "^5.6"
- },
- "dependencies": {
- "@rails/actioncable": "^8.0.0",
- "commander": "^12.1.0",
- "oauth4webapi": "^3.1.4",
- "ws": "^8.18.0"
- }
-}
diff --git a/packages/sdk/scripts/updateVersion.js b/packages/sdk/scripts/updateVersion.js
deleted file mode 100644
index 4b6ed8894a5e3..0000000000000
--- a/packages/sdk/scripts/updateVersion.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import fs from "fs";
-import cp from "child_process";
-
-if (!process.env.CI) {
- // make sure people building locally automatically do not track changes to version file
- cp.execSync("git update-index --skip-worktree src/version.ts");
-}
-
-const pkg = JSON.parse(String(fs.readFileSync("./package.json", "utf8")))
-const versionTsPath = "./src/version.ts";
-const data = String(fs.readFileSync(versionTsPath, "utf8"));
-const newData = data.replace(/"(.*)"/, `"${pkg.version}"`);
-fs.writeFileSync(versionTsPath, newData);
diff --git a/packages/sdk/src/browser/index.ts b/packages/sdk/src/browser/index.ts
deleted file mode 100644
index 38a9bf439b7bb..0000000000000
--- a/packages/sdk/src/browser/index.ts
+++ /dev/null
@@ -1,357 +0,0 @@
-// This code is meant to be run client-side. Never provide project keys to the
-// browser client, or make API requests to the Pipedream API to fetch
-// credentials. The browser client is meant for initiating browser-specific
-// operations, like connecting accounts via Pipedream Connect. See the server/
-// directory for the server client.
-
-import {
- AccountsRequestResponse,
- BaseClient,
- GetAccountOpts,
- type ConnectTokenResponse,
-} from "../shared/index.js";
-export type * from "../shared/index.js";
-
-/**
- * Options for creating a browser-side client. This is used to configure the
- * BrowserClient instance.
- */
-type CreateBrowserClientOpts = {
- /**
- * @deprecated environment is set on the server when generating the client token
- */
- environment?: string;
-
- /**
- * The frontend host URL. Used by Pipedream employees only. Defaults to
- * "pipedream.com" if not provided.
- */
- frontendHost?: string;
-
- /**
- * The API host URL. Used by Pipedream employees. Defaults to
- * "api.pipedream.com" if not provided.
- */
- apiHost?: string;
-
- /**
- * Will be called whenever we need a new token.
- *
- * The callback function should return the response from
- * `serverClient.createConnectToken`.
- */
- tokenCallback?: TokenCallback;
-
- /**
- * An external user ID associated with the token.
- */
- externalUserId?: string;
-};
-
-export type TokenCallback = (opts: {
- externalUserId: string;
-}) => Promise;
-
-/**
- * The name slug for an app, a unique, human-readable identifier like "github"
- * or "google_sheets". Find this in the Authentication section for any app's
- * page at https://pipedream.com/apps. For more information about name slugs,
- * see https://pipedream.com/docs/connect/quickstart#find-your-apps-name-slug.
- */
-type AppNameSlug = string;
-
-/**
- * The result of a successful connection.
- */
-type ConnectResult = {
- /**
- * The unique identifier of the connected account.
- */
- id: string;
-};
-
-/**
- * The status when the Connect dialog is closed.
- */
-type ConnectStatus = {
- /**
- * Whether the connection was successful (account was connected).
- */
- successful: boolean;
- /**
- * Whether the connection process was completed (vs user closing early).
- */
- completed: boolean;
-};
-
-/**
- * Custom error class for handling connection errors.
- */
-class ConnectError extends Error {}
-
-/**
- * Options for starting the connection process.
- */
-type StartConnectOpts = {
- /**
- * The token used for authenticating the connection.
- *
- * Optional if client already initialized with token
- */
- token?: string;
-
- /**
- * The app to connect to, either as an ID or an object containing the ID.
- */
- app: AppNameSlug;
-
- /**
- * The OAuth app ID to connect to.
- */
- oauthAppId?: string;
-
- /**
- * Callback function to be called upon successful connection.
- *
- * @param res - The result of the connection.
- */
- onSuccess?: (res: ConnectResult) => void;
-
- /**
- * Callback function to be called if an error occurs during the connection.
- *
- * @param err - The error that occurred during the connection.
- */
- onError?: (err: ConnectError) => void;
-
- /**
- * Callback function to be called when the Connect iFrame is closed.
- *
- * @param status - The status of the connection when closed.
- */
- onClose?: (status: ConnectStatus) => void;
-};
-
-/**
- * Creates a new instance of `BrowserClient` with the provided options.
- *
- * @example
- * ```typescript
- const client = createFrontendClient({
- tokenCallback,
- externalUserId,
- });
- * ```
- * @param opts - The options for creating the browser client.
- * @returns A new instance of `BrowserClient`.
- */
-export function createFrontendClient(opts: CreateBrowserClientOpts = {}) {
- return new BrowserClient(opts);
-}
-
-/**
- * A client for interacting with the Pipedream Connect API from the browser.
- */
-export class BrowserClient extends BaseClient {
- private baseURL: string;
- private iframeURL: string;
- private iframe?: HTMLIFrameElement;
- private iframeId = 0;
- private tokenCallback?: TokenCallback;
- private _token?: string;
- private _tokenExpiresAt?: Date;
- private _tokenRequest?: Promise;
- externalUserId?: string;
-
- /**
- * Constructs a new `BrowserClient` instance.
- *
- * @param opts - The options for configuring the browser client.
- */
- constructor(opts: CreateBrowserClientOpts) {
- super(opts);
- this.baseURL = `https://${opts.frontendHost || "pipedream.com"}`;
- this.iframeURL = `${this.baseURL}/_static/connect.html`;
- this.tokenCallback = opts.tokenCallback;
- this.externalUserId = opts.externalUserId;
- }
-
- private async token() {
- if (
- this._token &&
- this._tokenExpiresAt &&
- this._tokenExpiresAt > new Date()
- ) {
- return this._token;
- }
-
- if (this._tokenRequest) {
- return this._tokenRequest;
- }
-
- const tokenCallback = this.tokenCallback;
- const externalUserId = this.externalUserId;
-
- if (!tokenCallback) {
- throw new Error("No token callback provided");
- }
- if (!externalUserId) {
- throw new Error("No external user ID provided");
- }
-
- // Ensure only one token request is in-flight at a time.
- this._tokenRequest = (async () => {
- const {
- token, expires_at,
- } = await tokenCallback({
- externalUserId: externalUserId,
- });
- this._token = token;
- this._tokenExpiresAt = new Date(expires_at);
- this._tokenRequest = undefined;
- return token;
- })();
-
- return this._tokenRequest;
- }
-
- private refreshToken() {
- this._token = undefined;
- }
-
- /**
- * Retrieves the raw token string.
- *
- * @return {string} The raw token value.
- */
- public rawToken(): string | undefined {
- return this._token;
- }
-
- /**
- * Initiates the process of connecting an account.
- *
- * @param opts - The options for starting the connection process.
- *
- * @example
- * ```typescript
- * client.connectAccount({
- * token: "your-token",
- * app: "your-app-id",
- * onSuccess: (res) => {
- * console.log("Connected account ID:", res.id);
- * },
- * onError: (err) => {
- * console.error("Connection error:", err);
- * },
- * onClose: (status) => {
- * if (!status.successful) {
- * console.log("User closed without connecting");
- * }
- * },
- * });
- * ```
- */
- public async connectAccount(opts: StartConnectOpts) {
- let connectionSuccessful = false;
- let connectionCompleted = false;
-
- const onMessage = (e: MessageEvent) => {
- switch (e.data?.type) {
- case "success":
- connectionSuccessful = true;
- connectionCompleted = true;
- opts.onSuccess?.({
- id: e.data?.authProvisionId,
- });
- break;
- case "error":
- connectionCompleted = true;
- opts.onError?.(new ConnectError(e.data.error));
- break;
- case "close":
- this.cleanup(onMessage);
- opts.onClose?.({
- successful: connectionSuccessful,
- completed: connectionCompleted,
- });
- break;
- default:
- break;
- }
- };
-
- window.addEventListener("message", onMessage);
-
- try {
- await this.createIframe(opts);
- } catch (err) {
- opts.onError?.(err as ConnectError);
- }
- this.refreshToken(); // token expires once it's used to create a connected account. We need to get a new token for the next requests.
- }
-
- /**
- * Cleans up the iframe and message event listener after the connection
- * process is complete.
- *
- * @param onMessage - The message event handler to remove.
- */
- private cleanup(onMessage: (e: MessageEvent) => void) {
- this.iframe?.remove();
- window.removeEventListener("message", onMessage);
- }
-
- /**
- * Creates an iframe for the connection process and appends it to the document
- * body.
- *
- * @param opts - The options for starting the connection process.
- *
- * @throws {ConnectError} If the app option is not a string.
- */
- private async createIframe(opts: StartConnectOpts) {
- const token = opts.token || (await this.token());
- const qp = new URLSearchParams({
- token,
- });
-
- if (typeof opts.app === "string") {
- qp.set("app", opts.app);
- } else {
- throw new ConnectError("Object app not yet supported");
- }
-
- if (opts.oauthAppId) {
- qp.set("oauthAppId", opts.oauthAppId);
- }
-
- const iframe = document.createElement("iframe");
- iframe.id = `pipedream-connect-iframe-${this.iframeId++}`;
- iframe.title = "Pipedream Connect";
- iframe.src = `${this.iframeURL}?${qp.toString()}`;
- iframe.style.cssText =
- "position:fixed;inset:0;z-index:2147483647;border:0;display:block;overflow:hidden auto";
- iframe.width = "100%";
- iframe.height = "100%";
-
- iframe.onload = () => {
- this.iframe = iframe;
- };
-
- document.body.appendChild(iframe);
- }
-
- protected async authHeaders(): Promise {
- if (!(await this.token())) {
- throw new Error("No token provided");
- }
- return `Bearer ${await this.token()}`;
- }
-
- public getAccounts(
- params?: Omit,
- ): Promise {
- return super.getAccounts(params);
- }
-}
diff --git a/packages/sdk/src/server/__tests__/server.test.ts b/packages/sdk/src/server/__tests__/server.test.ts
deleted file mode 100644
index 18efed23bcc54..0000000000000
--- a/packages/sdk/src/server/__tests__/server.test.ts
+++ /dev/null
@@ -1,875 +0,0 @@
-import { jest } from "@jest/globals"
-import {
- BackendClient,
- BackendClientOpts,
- createBackendClient,
- HTTPAuthType,
-} from "../index.js";
-import isEqual from "lodash.isequal"
-
-const fetchMock = setupFetchMock() // see bottom of file
-
-const projectId = "proj_abc123";
-const clientParams: BackendClientOpts = {
- environment: "production",
- credentials: {
- clientId: "test-client-id",
- clientSecret: "test-client-secret",
- },
- projectId,
-};
-
-let client: BackendClient;
-let customDomainClient: BackendClient;
-
-beforeEach(() => {
- client = new BackendClient(
- clientParams,
- );
- customDomainClient = new BackendClient({
- ...clientParams,
- workflowDomain: "example.com",
- });
-});
-
-afterEach(() => {
- jest.clearAllMocks();
-});
-
-describe("BackendClient", () => {
- describe("createBackendClient", () => {
- it("should mock the createBackendClient method and return a BackendClient instance", () => {
- const client = createBackendClient(clientParams);
- expect(client).toBeInstanceOf(BackendClient);
- });
- });
-
- describe("makeRequest", () => {
- it("should make a GET request successfully", async () => {
- fetchMock.expect({
- request: {
- url: "https://api.pipedream.com/v1/test-path",
- },
- response: {
- json: {
- data: "test-response",
- },
- },
- })
-
- const result = await client.makeRequest("/test-path", {
- method: "GET",
- });
-
- expect(result).toEqual({
- data: "test-response",
- });
- });
-
- it("should make a POST request with JSON body", async () => {
- fetchMock.expect({
- request: {
- url: "https://api.pipedream.com/v1/test-path",
- json: {
- key: "value",
- },
- },
- response: {
- json: {
- success: true,
- },
- },
- })
-
- const result = await client.makeRequest("/test-path", {
- method: "POST",
- body: {
- key: "value",
- },
- });
-
- expect(result).toEqual({
- success: true,
- });
- });
-
- it("should handle non-200 HTTP responses", async () => {
- fetchMock.expect({
- request: {
- url: "https://api.pipedream.com/v1/bad-path",
- },
- response: new Response("Not Found", {
- status: 404,
- headers: {
- "Content-Type": "text/plain",
- },
- }),
- });
-
- await expect(client.makeRequest("/bad-path")).rejects.toThrow("HTTP error! status: 404, body: Not Found");
- });
- });
-
- describe("makeAuthorizedRequest", () => {
- it("should include OAuth Authorization header and make an API request", async () => {
- const accessToken = fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: "https://api.pipedream.com/v1/test-path",
- headersContaining: {
- authorization: `Bearer ${accessToken}`,
- },
- },
- response: {
- json: {
- success: true,
- },
- },
- })
-
- const result = await client["makeAuthorizedRequest"]("/test-path");
-
- expect(result).toEqual({
- success: true,
- });
- });
-
- it("should handle OAuth token retrieval failure", async () => {
- fetchMock.expectAccessTokenFailure();
- await expect(client.makeAuthorizedRequest("/test-path")).rejects.toThrow();
- });
- });
-
- describe("makeConnectRequest", () => {
- it("should include Connect Authorization header and make a request", async () => {
- const accessToken = fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/test-path`,
- headersContaining: {
- authorization: `Bearer ${accessToken}`,
- },
- },
- response: {
- json: {
- success: true,
- },
- },
- })
-
- const result = await client["makeConnectRequest"]("/test-path");
-
- expect(result).toEqual({
- success: true,
- });
- });
- });
-
- describe("createConnectToken", () => {
- it("should create a connect token", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/tokens`,
- headersContaining: {
- "X-PD-Environment": "production",
- },
- json: {
- external_user_id: "user-id",
- external_id: "user-id",
- },
- },
- response: {
- json: {
- token: "connect-token",
- expires_at: "2024-01-01T00:00:00Z",
- },
- },
- });
-
- const result = await client.createConnectToken({
- external_user_id: "user-id",
- });
-
- expect(result).toEqual({
- token: "connect-token",
- expires_at: "2024-01-01T00:00:00Z",
- });
- });
-
- it("should create a connect token with optional redirect URIs", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/tokens`,
- json: {
- external_user_id: "user-id",
- success_redirect_uri: "https://example.com/success",
- error_redirect_uri: "https://example.com/error",
- external_id: "user-id",
- },
- },
- response: {
- json: {
- token: "connect-token-with-redirects",
- expires_at: "2024-01-01T00:00:00Z",
- },
- },
- });
-
- const result = await client.createConnectToken({
- external_user_id: "user-id",
- success_redirect_uri: "https://example.com/success",
- error_redirect_uri: "https://example.com/error",
- });
-
- expect(result).toEqual({
- token: "connect-token-with-redirects",
- expires_at: "2024-01-01T00:00:00Z",
- });
- });
- });
-
- describe("getAccounts", () => {
- it("should retrieve accounts", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts?include_credentials=true`,
- },
- response: {
- json: {
- data: [
- {
- id: "account-1",
- name: "Test Account",
- },
- ],
- },
- },
- })
-
- const result = await client.getAccounts({
- include_credentials: true,
- });
-
- expect(result.data).toEqual([
- {
- id: "account-1",
- name: "Test Account",
- },
- ]);
- });
- });
-
- describe("getAccountById", () => {
- it("should retrieve a specific account by ID", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts/account-1`,
- },
- response: {
- json: {
- id: "account-1",
- name: "Test Account",
- },
- },
- });
-
- const result = await client.getAccountById("account-1");
-
- expect(result).toEqual({
- id: "account-1",
- name: "Test Account",
- });
- });
-
- it("should include credentials when the flag is set", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts/account-1?include_credentials=true`,
- },
- response: {
- json: {
- id: "account-1",
- name: "Test Account",
- credentials: {},
- },
- },
- });
-
- const result = await client.getAccountById("account-1", {
- include_credentials: true,
- });
-
- expect(result).toEqual({
- id: "account-1",
- name: "Test Account",
- credentials: {},
- });
- });
- });
-
- describe("Get accounts by app", () => {
- it("should retrieve accounts associated with a specific app", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts?app=app-1`,
- },
- response: {
- json: [
- {
- id: "account-1",
- name: "Test Account",
- },
- ],
- },
- });
-
- const result = await client.getAccounts({
- app: "app-1",
- });
-
- expect(result).toEqual([
- {
- id: "account-1",
- name: "Test Account",
- },
- ]);
- });
- });
-
- describe("Get accounts by external user ID", () => {
- it("should retrieve accounts associated with a specific external ID", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts?external_user_id=external-id-1`,
- },
- response: {
- json: [
- {
- id: "account-1",
- name: "Test Account",
- },
- ],
- },
- });
-
- const result = await client.getAccounts({
- external_user_id: "external-id-1",
- });
-
- expect(result).toEqual([
- {
- id: "account-1",
- name: "Test Account",
- },
- ]);
- });
- });
-
- describe("deleteAccount", () => {
- it("should delete a specific account by ID", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- method: "DELETE",
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts/account-1`,
- },
- response: {
- status: 204,
- },
- });
-
- await client.deleteAccount("account-1");
- });
- });
-
- describe("deleteAccountsByApp", () => {
- it("should delete all accounts associated with a specific app", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- method: "DELETE",
- url: `https://api.pipedream.com/v1/connect/${projectId}/accounts/app/app-1`,
- },
- response: {
- status: 204,
- },
- });
-
- await client.deleteAccountsByApp("app-1");
- });
- });
-
- describe("deleteExternalUser", () => {
- it("should delete all accounts associated with a specific external ID", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- method: "DELETE",
- url: `https://api.pipedream.com/v1/connect/${projectId}/users/external-id-1`,
- },
- response: {
- status: 204,
- },
- });
-
- await client.deleteExternalUser("external-id-1");
- });
- });
-
- describe("getProjectInfo", () => {
- it("should retrieve project info", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- method: "GET",
- url: `https://api.pipedream.com/v1/connect/${projectId}/projects/info`,
- },
- response: {
- json: {
- apps: [
- {
- id: "app-1",
- name_slug: "test-app",
- },
- ],
- },
- },
- })
-
- const result = await client.getProjectInfo();
-
- expect(result).toEqual({
- apps: [
- {
- id: "app-1",
- name_slug: "test-app",
- },
- ],
- });
- });
- });
-
- describe("invokeWorkflow", () => {
- beforeEach(() => {
- client = new BackendClient({
- ...clientParams,
- workflowDomain: "example.com",
- });
- });
-
- it("should invoke a workflow with provided URL and body, with no auth type", async () => {
- fetchMock.expect({
- request: {
- method: "POST",
- url: "https://example.com/workflow",
- json: {
- foo: "bar",
- },
- headersContaining: {
- "X-PD-Environment": "production",
- },
- },
- response: {
- json: {
- result: "workflow-response",
- },
- },
- })
-
- const result = await client.invokeWorkflow("https://example.com/workflow", {
- body: {
- foo: "bar",
- },
- });
-
- expect(result).toEqual({
- result: "workflow-response",
- });
- });
-
- it("should invoke a workflow with OAuth auth type", async () => {
- const token = "" + Math.random()
- fetchMock.expectAccessTokenSuccess({
- accessToken: token,
- });
- fetchMock.expect({
- request: {
- url: "https://example.com/workflow",
- headersContaining: {
- authorization: `Bearer ${token}`,
- },
- },
- response: {
- json: {
- result: "workflow-response",
- },
- },
- })
-
- const result = await client.invokeWorkflow("https://example.com/workflow", {}, HTTPAuthType.OAuth);
-
- expect(result).toEqual({
- result: "workflow-response",
- });
- });
-
- it("should invoke a workflow with static bearer auth type", async () => {
- const token = "" + Math.random()
- fetchMock.expect({
- request: {
- url: "https://example.com/workflow",
- headersContaining: {
- Authorization: `Bearer ${token}`,
- },
- },
- response: {
- json: {
- result: "workflow-response",
- },
- },
- })
-
- const result = await client.invokeWorkflow("https://example.com/workflow", {
- headers: {
- "Authorization": `Bearer ${token}`,
- },
- }, HTTPAuthType.StaticBearer);
-
- expect(result).toEqual({
- result: "workflow-response",
- });
- });
- });
-
- describe("OAuth Token Handling", () => {
- it("should refresh token when expired", async () => {
- // First request will get the expired token and fetch a new one
- fetchMock.expectAccessTokenFailure();
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: "https://api.pipedream.com/v1/test-path",
- },
- response: {
- json: {
- success: true,
- },
- },
- })
-
- const result1 = await client["makeAuthorizedRequest"]("/test-path");
-
- expect(result1).toEqual({
- success: true,
- });
- });
- });
-
- describe("invokeWorkflowForExternalUser", () => {
- let client: BackendClient;
-
- beforeEach(() => {
- client = new BackendClient({
- ...clientParams,
- workflowDomain: "example.com",
- });
- });
-
- it("should include externalUserId and environment headers", async () => {
- fetchMock.expectAccessTokenSuccess();
- fetchMock.expect({
- request: {
- url: "https://example.com/workflow",
- headersContaining: {
- "X-PD-External-User-ID": "external-user-id",
- "X-PD-Environment": "production",
- },
- },
- response: {
- json: {
- result: "workflow-response",
- },
- },
- })
-
- const result = await client.invokeWorkflowForExternalUser("https://example.com/workflow", "external-user-id", {
- body: {
- foo: "bar",
- },
- });
-
- expect(result).toEqual({
- result: "workflow-response",
- });
- });
-
- it("should throw error when externalUserId is missing", async () => {
- await expect(client.invokeWorkflowForExternalUser("https://example.com/workflow", "", {
- body: {
- foo: "bar",
- },
- })).rejects.toThrow("External user ID is required");
- });
-
- it("should throw error when externalUserId is blank", async () => {
- await expect(client.invokeWorkflowForExternalUser("https://example.com/workflow", " ", {
- body: {
- foo: "bar",
- },
- })).rejects.toThrow("External user ID is required");
- });
-
- it("should throw error when the URL is blank", async () => {
- await expect(client.invokeWorkflowForExternalUser(" ", "external-user-id", {
- body: {
- foo: "bar",
- },
- })).rejects.toThrow("Workflow URL is required");
- });
- });
-
- describe("BackendClient - buildWorkflowUrl", () => {
- describe("Validations", () => {
- it("should throw an error when the input is blank", () => {
- expect(() => client["buildWorkflowUrl"](" ")).toThrow("URL or endpoint ID is required");
- });
-
- it("should throw an error when the URL doesn't match the workflow domain", () => {
- const url = "https://example.com";
- expect(() => client["buildWorkflowUrl"](url)).toThrow("Invalid workflow domain");
- });
-
- it("should throw an error when the endpoint ID doesn't match the expected format", () => {
- const input = "foo123";
- expect(() => client["buildWorkflowUrl"](input)).toThrow("Invalid endpoint ID format");
- });
- });
-
- describe("Default domain (m.pipedream.net)", () => {
- it("should return full URL if input is a full URL with protocol", () => {
- const input = "https://en123.m.pipedream.net";
- const expected = "https://en123.m.pipedream.net/";
- expect(client["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should return full URL if input is a URL without protocol", () => {
- const input = "en123.m.pipedream.net";
- const expected = "https://en123.m.pipedream.net/";
- expect(client["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should construct URL with 'm.pipedream.net' if input is an endpoint ID", () => {
- const input = "en123";
- const expected = "https://en123.m.pipedream.net";
- expect(client["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should handle input with a path in full URL with protocol", () => {
- const input = "https://en123.m.pipedream.net/foo";
- const expected = "https://en123.m.pipedream.net/foo";
- expect(client["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should handle input with a path when no protocol is provided", () => {
- const input = "en123.m.pipedream.net/foo";
- const expected = "https://en123.m.pipedream.net/foo";
- expect(client["buildWorkflowUrl"](input)).toBe(expected);
- });
- });
-
- describe("Custom domain (example.com)", () => {
- it("should return full URL if input is a full URL with protocol", () => {
- const input = "https://en123.example.com";
- const expected = "https://en123.example.com/";
- expect(customDomainClient["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should return full URL if input is a URL without protocol", () => {
- const input = "en123.example.com";
- const expected = "https://en123.example.com/";
- expect(customDomainClient["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should construct URL with 'example.com' if input is an endpoint ID", () => {
- const input = "en123";
- const expected = "https://en123.example.com";
- expect(customDomainClient["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should handle input with a path in full URL with protocol", () => {
- const input = "https://en123.example.com/foo";
- const expected = "https://en123.example.com/foo";
- expect(customDomainClient["buildWorkflowUrl"](input)).toBe(expected);
- });
-
- it("should handle input with a path when no protocol is provided", () => {
- const input = "en123.example.com/foo";
- const expected = "https://en123.example.com/foo";
- expect(customDomainClient["buildWorkflowUrl"](input)).toBe(expected);
- });
- });
- });
-});
-
-type ExpectRequest = {
- method?: string
- url?: string | RegExp
- json?: Record
- headersContaining?: Record
-}
-type MockResponse =
- | Response
- | { status?: number; json?: unknown }
-type IfOpts = {
- method: string
- url: string
- headers: Record // NonNullable
- json?: unknown // body json
- // XXX etc.
-}
-function setupFetchMock() {
- let intercepts: {
- if: (opts: IfOpts) => boolean
- response: () => Response
- }[] = []
-
- const jsonResponse = (o: unknown, opts?: { status?: number }) => {
- return new Response(JSON.stringify(o), {
- status: opts?.status,
- headers: {
- "content-type": "application/json",
- },
- })
- }
-
- beforeEach(() => {
- intercepts = [];
- // without these generics this fails typecheck and can't figure out why
- jest.spyOn(global, "fetch").mockImplementation(jest.fn(async (...args: Parameters) => { // eslint-disable-line @typescript-eslint/no-explicit-any
- const [
- url,
- init,
- ] = args
- let json: unknown
- if (init?.body && typeof init.body === "string") {
- try {
- json = JSON.parse(init.body)
- } catch {
- // pass
- }
- }
- if (url instanceof Request) {
- throw new Error("not supported")
- }
- const ifOpts: IfOpts = {
- method: init?.method || "GET",
- url: url.toString(),
- headers: init?.headers as Record || {},
- json,
- }
- for (let i = 0; i < intercepts.length; i++) {
- const intercept = intercepts[i]
- if (intercept.if(ifOpts)) {
- intercepts.splice(i, 1)
- return intercept.response()
- }
- }
- throw new Error(`Request to ${url} not intercepted`)
- }) as jest.Mock);
- })
-
- afterEach(() => {
- if (intercepts.length) {
- throw new Error("Expected requests not yet intercepted")
- }
- })
-
- // const _expect = (opts: { if: (opts: IfOpts) => boolean, jsonResponse?: any, response?: Response }) => {
- const _expect = (opts: { request: ExpectRequest, response: MockResponse }) => {
- const {
- method, url, headersContaining, json,
- } = opts.request
- intercepts.push({
- if: (ifOpts) => {
- if (method && ifOpts.method !== method) return false
- if (url) {
- if (typeof url === "string") return url === ifOpts.url
- if (url instanceof RegExp) return !!ifOpts.url.match(url)
- throw new Error(`unexpected type for request.url: ${url}`)
- }
- if (headersContaining) {
- for (const header in headersContaining) {
- if (ifOpts.headers[header.toLowerCase()] !== headersContaining[header.toLowerCase()]) {
- return false
- }
- }
- }
- if (json && !isEqual(json, ifOpts.json)) {
- return false
- }
- return true
- },
- response: () => {
- if (opts.response instanceof Response) {
- return opts.response
- }
- if (opts.response.json) {
- return jsonResponse(opts.response.json, {
- status: opts.response.status,
- // XXX...
- })
- }
- return new Response(null, {
- status: opts.response.status,
- headers: {
- "content-type": "text/plain",
- },
- })
- },
- })
- }
-
- const expectAccessTokenSuccess = (opts?: { accessToken?: string; expiresIn?: number }) => {
- const accessToken = opts?.accessToken || "" + Math.random()
- _expect({
- request: {
- url: /\/v1\/oauth\/token$/,
- },
- response: {
- json: {
- access_token: accessToken,
- token_type: "Bearer",
- expires_in: opts?.expiresIn ?? 3600,
- },
- },
- })
- return accessToken
- }
-
- const expectAccessTokenFailure = () => {
- _expect({
- request: {
- url: /\/v1\/oauth\/token$/,
- },
- response: new Response("", {
- status: 401,
- headers: {
- "content-type": "application/json",
- },
- }),
- })
- }
-
- return {
- expect: _expect,
- expectAccessTokenSuccess,
- expectAccessTokenFailure,
- }
-}
diff --git a/packages/sdk/src/server/cli.ts b/packages/sdk/src/server/cli.ts
deleted file mode 100644
index 92831a663921a..0000000000000
--- a/packages/sdk/src/server/cli.ts
+++ /dev/null
@@ -1,269 +0,0 @@
-import { createBackendClient } from "./index.js";
-import { program } from "commander";
-
-const {
- CLIENT_ID, CLIENT_SECRET, PROJECT_ID, API_HOST, ENVIRONMENT,
-} = process.env;
-
-if (!CLIENT_ID || !CLIENT_SECRET || !PROJECT_ID) {
- console.error("Error: Missing required environment variables (CLIENT_ID, CLIENT_SECRET, PROJECT_ID).");
- process.exit(1);
-}
-
-const client = createBackendClient({
- credentials: {
- clientId: CLIENT_ID,
- clientSecret: CLIENT_SECRET,
- },
- projectId: PROJECT_ID,
- apiHost: API_HOST,
- environment: ENVIRONMENT === "production"
- ? "production"
- : "development",
-});
-
-program
- .name("connect-cli")
- .description("CLI for interacting with the Pipedream Connect API")
- .version("1.0.0");
-
-const handleError = (error: unknown, message: string) => {
- if (error instanceof Error) {
- console.error(`${message}:`, error.message);
- } else {
- console.error(`${message}:`, String(error));
- }
-};
-
-program
- .command("list-project-info")
- .description("List information about the project, including linked apps.")
- .action(async () => {
- try {
- const projectInfo = await client.getProjectInfo();
- console.log(JSON.stringify(projectInfo, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch project info");
- }
- });
-
-program
- .command("delete-account ")
- .description("Delete an account by its ID.")
- .action(async (accountId) => {
- try {
- await client.deleteAccount(accountId);
- console.log(`Account with ID ${accountId} has been deleted.`);
- } catch (error) {
- handleError(error, "Failed to delete account");
- }
- });
-
-program
- .command("delete-accounts-by-app ")
- .description("Delete all accounts associated with a specific app.")
- .action(async (appId) => {
- try {
- await client.deleteAccountsByApp(appId);
- console.log(`All accounts associated with app ID ${appId} have been deleted.`);
- } catch (error) {
- handleError(error, "Failed to delete accounts by app");
- }
- });
-
-program
- .command("delete-external-user ")
- .description("Delete all accounts associated with a specific external ID.")
- .action(async (externalId) => {
- try {
- await client.deleteExternalUser(externalId);
- console.log(`All accounts associated with external ID ${externalId} have been deleted.`);
- } catch (error) {
- handleError(error, "Failed to delete external user");
- }
- });
-
-program
- .command("create-connect-token ")
- .description("Create a new Pipedream Connect token.")
- .option("--success-redirect-uri ", "URL to redirect the user to upon successful connection")
- .option("--error-redirect-uri ", "URL to redirect the user to upon failed connection")
- .option("--webhook-uri ", "Webhook URI that Pipedream can invoke on success or failure of connection requests")
- .option("--allowed-origins ", "Comma-separated list of allowed origins")
- .action(async (externalUserId, options) => {
- try {
- const tokenResponse = await client.createConnectToken({
- external_user_id: externalUserId,
- success_redirect_uri: options.successRedirectUri,
- error_redirect_uri: options.errorRedirectUri,
- webhook_uri: options.webhookUri,
- allowed_origins: options.allowedOrigins
- ? options.allowedOrigins.split(",")
- : undefined,
- });
- console.log(JSON.stringify(tokenResponse, null, 2));
- } catch (error) {
- handleError(error, "Failed to create connect token");
- }
- });
-
-program
- .command("get-accounts")
- .description("Retrieve the list of accounts associated with the project.")
- .option("--include-credentials ", "Include credentials in the response")
- .action(async (options) => {
- try {
- const params = options.includeCredentials
- ? {
- include_credentials: options.includeCredentials,
- }
- : {};
- const accounts = await client.getAccounts(params);
- console.log(JSON.stringify(accounts, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch accounts");
- }
- });
-
-program
- .command("get-account-by-id ")
- .description("Retrieve a specific account by ID.")
- .action(async (accountId) => {
- try {
- const account = await client.getAccountById(accountId);
- console.log(JSON.stringify(account, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch account by ID");
- }
- });
-
-program
- .command("list-apps")
- .description("Retrieve the list of apps.")
- .option("--query ", "Query string to filter apps")
- .action(async (options) => {
- try {
- const apps = await client.apps({
- q: options.query,
- });
- console.log(JSON.stringify(apps, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch apps");
- }
- });
-
-program
- .command("get-app ")
- .description("Retrieve a specific app by ID or name slug.")
- .action(async (idOrNameSlug) => {
- try {
- const app = await client.app(idOrNameSlug);
- console.log(JSON.stringify(app, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch app");
- }
- });
-
-program
- .command("list-components")
- .description("Retrieve the list of components.")
- .option("--app ", "Filter components by app")
- .option("--query ", "Query string to filter components")
- .option("--component-type ", "Filter components by type (trigger or action)")
- .action(async (options) => {
- try {
- const components = await client.components({
- app: options.app,
- q: options.query,
- componentType: options.componentType,
- });
- console.log(JSON.stringify(components, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch components");
- }
- });
-
-program
- .command("get-component ")
- .description("Retrieve a specific component by key.")
- .action(async (key) => {
- try {
- const component = await client.component({
- key,
- });
- console.log(JSON.stringify(component, null, 2));
- } catch (error) {
- handleError(error, "Failed to fetch component");
- }
- });
-
-program
- .command("configure-component")
- .description("Configure a component.")
- .requiredOption("--user-id ", "User ID")
- .requiredOption("--component-id ", "Component ID")
- .requiredOption("--prop-name ", "Property name")
- .requiredOption("--configured-props ", "Configured properties as JSON string")
- .option("--dynamic-props-id ", "Dynamic properties ID")
- .action(async (options) => {
- try {
- const configuredProps = JSON.parse(options.configuredProps);
- const response = await client.componentConfigure({
- userId: options.userId,
- componentId: options.componentId,
- propName: options.propName,
- configuredProps,
- dynamicPropsId: options.dynamicPropsId,
- });
- console.log(JSON.stringify(response, null, 2));
- } catch (error) {
- handleError(error, "Failed to configure component");
- }
- });
-
-program
- .command("reload-component-props")
- .description("Reload component properties.")
- .requiredOption("--user-id ", "User ID")
- .requiredOption("--component-id ", "Component ID")
- .requiredOption("--configured-props ", "Configured properties as JSON string")
- .option("--dynamic-props-id ", "Dynamic properties ID")
- .action(async (options) => {
- try {
- const configuredProps = JSON.parse(options.configuredProps);
- const response = await client.componentReloadProps({
- userId: options.userId,
- componentId: options.componentId,
- configuredProps,
- dynamicPropsId: options.dynamicPropsId,
- });
- console.log(JSON.stringify(response, null, 2));
- } catch (error) {
- handleError(error, "Failed to reload component properties");
- }
- });
-
-program
- .command("run-action")
- .description("Run an action.")
- .requiredOption("--user-id ", "User ID")
- .requiredOption("--action-id ", "Action ID")
- .requiredOption("--configured-props ", "Configured properties as JSON string")
- .option("--dynamic-props-id ", "Dynamic properties ID")
- .action(async (options) => {
- try {
- const configuredProps = JSON.parse(options.configuredProps);
- const response = await client.actionRun({
- userId: options.userId,
- actionId: options.actionId,
- configuredProps,
- dynamicPropsId: options.dynamicPropsId,
- });
- console.log(JSON.stringify(response, null, 2));
- } catch (error) {
- handleError(error, "Failed to run action");
- }
- });
-
-// Parse and execute commands
-program.parse(process.argv);
diff --git a/packages/sdk/src/server/index.ts b/packages/sdk/src/server/index.ts
deleted file mode 100644
index 610f424652b4f..0000000000000
--- a/packages/sdk/src/server/index.ts
+++ /dev/null
@@ -1,491 +0,0 @@
-// This code is meant to be run server-side, where you can securely store your
-// Pipedream project's public and secret keys and access customer credentials.
-// See the browser/ directory for the browser client.
-
-import * as oauth from "oauth4webapi";
-import {
- Account, BaseClient, type AppInfo, type ConnectTokenResponse, type RequestOptions,
-} from "../shared/index.js";
-export * from "../shared/index.js";
-
-/**
- * OAuth credentials for your Pipedream account, containing client ID and
- * secret.
- */
-export type OAuthCredentials = {
- clientId: string;
- clientSecret: string;
-};
-
-/**
- * The environment in which the server client is running.
- */
-export type ProjectEnvironment = "development" | "production";
-
-/**
- * Options for creating a server-side client.
- * This is used to configure the ServerClient instance.
- */
-export type BackendClientOpts = {
- /**
- * The environment in which the server client is running (e.g., "production",
- * "development").
- */
- environment?: ProjectEnvironment;
-
- /**
- * The credentials to use for authentication against the Pipedream API.
- */
- credentials: OAuthCredentials | {
- accessToken: string;
- };
-
- /**
- * The base project ID tied to relevant API requests
- */
- projectId: string;
-
- /**
- * The API host URL. Used by Pipedream employees. Defaults to
- * "api.pipedream.com" if not provided.
- */
- apiHost?: string;
-
- /**
- * Base domain for workflows. Used for custom domains:
- * https://pipedream.com/docs/workflows/domains
- */
- workflowDomain?: string;
-
- /**
- * OAuth scope to request when obtaining access tokens
- */
- scope?: string[];
-};
-
-/**
- * Options for creating a Connect token.
- */
-export type ConnectTokenCreateOpts = {
- /**
- * The ID of the user in your system.
- */
- external_user_id: string;
-
- /**
- * The optional url to redirect the user to upon successful connection.
- */
- success_redirect_uri?: string;
-
- /**
- * The optional url to redirect the user to upon failed connection.
- */
- error_redirect_uri?: string;
-
- /**
- * An optional webhook uri that Pipedream can invoke on success or failure of
- * connection requests.
- */
- webhook_uri?: string;
-
- /**
- * Specify which origins can use the token to call the Pipedream API.
- */
- allowed_origins?: string[];
-};
-
-/**
- * Response received after requesting a project's info.
- */
-export type ProjectInfoResponse = {
- /**
- * An array of apps linked to the project.
- */
- apps: AppInfo[];
-};
-
-/**
- * Parameters for the retrieval of an account from the Connect API
- */
-export type GetAccountByIdOpts = {
- /**
- * Whether to retrieve the account's credentials or not.
- */
- include_credentials?: boolean;
-};
-
-/**
- * Options used to determine the external user and account to be used in Connect Proxy API
- */
-export type ProxyApiOpts = {
- /**
- * Search parameters to be added to the proxy request. external_user_id and account_id are required.
- */
- searchParams: Record;
-};
-
-/**
- * fetch-like options for the Target of the Connect Proxy Api Request
- */
-export type ProxyTargetApiOpts = {
- /**
- * http method for the request
- */
- method: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
- /**
- * http headers for the request
- */
- headers?: Record;
- /**
- * http body for the request
- */
- body?: string;
-};
-
-/**
- * object that contains the url and options for the target of the Connect Proxy Api Request
- */
-export type ProxyTargetApiRequest = {
- /**
- * URL for the target of the request. Search parameters must be included here.
- */
- url: string;
- /**
- * fetch-like options for the target of the Connect Proxy Request
- */
- options: ProxyTargetApiOpts;
-};
-
-/**
- * The parsed response body from a proxied API request.
- *
- * If the response has a Content-Type of application/json, the body will be parsed
- * and returned as an object. Otherwise the type will be a string.
- */
-export type ProxyResponse = Record | string;
-
-/**
- * Creates a new instance of BackendClient with the provided options.
- *
- * @example
- *
- * ```typescript
- const serverClient = createBackendClient({
- environment: "development",
- projectId: "",
- credentials: {
- clientId: "",
- clientSecret: "",
- },
- })
- * ```
- *
- * @param opts - The options for creating the server client.
- * @returns A new instance of ServerClient.
- */
-export function createBackendClient(opts: BackendClientOpts) {
- return new BackendClient(opts);
-}
-
-/**
- * A client for interacting with the Pipedream Connect API on the server-side.
- */
-export class BackendClient extends BaseClient {
- private oauthClient: {
- client: oauth.Client
- clientAuth: oauth.ClientAuth
- as: oauth.AuthorizationServer
- } | undefined;
- private oauthAccessToken?: {
- token: string
- expiresAt: number
- };
- protected override projectId: string = "";
- private staticAccessToken?: string;
- private scope?: string[];
-
- /**
- * Constructs a new ServerClient instance.
- *
- * @param opts - The options for configuring the server client.
- * @param oauthClient - An optional OAuth client to use for authentication in tests
- */
- constructor(opts: BackendClientOpts) {
- super(opts);
-
- this.ensureValidEnvironment(opts.environment);
- this.projectId = opts.projectId;
- this.scope = opts.scope;
- if ("accessToken" in opts.credentials) {
- this.staticAccessToken = opts.credentials.accessToken;
- } else {
- this.oauthClient = this.newOauthClient(opts.credentials, this.apiHost);
- }
- }
-
- private ensureValidEnvironment(environment?: string) {
- if (!environment || ![
- "development",
- "production",
- ].includes(environment)) {
- throw new Error(
- "Project environment is required. Supported environments are development and production.",
- );
- }
- }
-
- private newOauthClient(
- {
- clientId, clientSecret,
- }: OAuthCredentials,
- tokenHost: string,
- ) {
- if (!clientId || !clientSecret) {
- throw new Error("OAuth client ID and secret are required");
- }
- const client: oauth.Client = {
- client_id: clientId,
- }
- const clientAuth = oauth.ClientSecretPost(clientSecret)
- const as: oauth.AuthorizationServer = {
- issuer: tokenHost,
- token_endpoint: `https://${tokenHost}/v1/oauth/token`,
- }
- return {
- client,
- clientAuth,
- as,
- }
- }
-
- /**
- * Returns the raw access token string or a promise resolving to it.
- * This can be used when you need the token directly without Authorization header formatting.
- *
- * @returns A string or promise resolving to the access token.
- */
- public rawAccessToken(): string | Promise {
- if (this.staticAccessToken) {
- return this.staticAccessToken;
- }
- return this.ensureValidOauthAccessToken();
- }
-
- protected authHeaders(): string | Promise {
- if (this.staticAccessToken) {
- return `Bearer ${this.staticAccessToken}`;
- }
- return this.oauthAuthorizationHeader();
- }
-
- private async ensureValidOauthAccessToken(): Promise {
- if (!this.oauthClient) {
- throw new Error("OAuth client not configured")
- }
- const {
- client,
- clientAuth,
- as,
- } = this.oauthClient
-
- let attempts = 0;
- const maxAttempts = 2;
-
- while (!this.oauthAccessToken || this.oauthAccessToken.expiresAt - Date.now() < 1000) {
- if (attempts > maxAttempts) {
- throw new Error("ran out of attempts trying to retrieve oauth access token");
- }
- if (attempts > 0) {
- // Wait for a short duration before retrying to avoid rapid retries
- await new Promise((resolve) => setTimeout(resolve, 100));
- }
-
- const parameters = new URLSearchParams();
- if (this.scope && this.scope.length > 0) {
- parameters.set("scope", this.scope.join(" "));
- }
- parameters.set("project_id", this.projectId);
- parameters.set("environment", this.environment);
- try {
- const response = await oauth.clientCredentialsGrantRequest(as, client, clientAuth, parameters);
- const oauthTokenResponse = await oauth.processClientCredentialsResponse(as, client, response);
- this.oauthAccessToken = {
- token: oauthTokenResponse.access_token,
- expiresAt: Date.now() + (oauthTokenResponse.expires_in || 0) * 1000,
- };
- } catch {
- // pass
- }
-
- attempts++;
- }
-
- return this.oauthAccessToken.token;
- }
-
- private async oauthAuthorizationHeader(): Promise {
- const accessToken = await this.ensureValidOauthAccessToken();
-
- return `Bearer ${accessToken}`;
- }
-
- /**
- * Creates a new Pipedream Connect token. See
- * https://pipedream.com/docs/connect/quickstart#connect-to-the-pipedream-api-from-your-server-and-create-a-token
- *
- * @param opts - The options for creating the connect token.
- * @returns A promise resolving to the connect token response.
- *
- * @example
- *
- * ```typescript
- * const tokenResponse = await client.connectTokenCreate({
- * external_user_id: "external-user-id", });
- * console.log(tokenResponse.token);
- * ```
- */
- public createConnectToken(
- opts: ConnectTokenCreateOpts,
- ): Promise {
- const body = {
- ...opts,
- external_id: opts.external_user_id,
- };
- return this.makeConnectRequest("/tokens", {
- method: "POST",
- body,
- });
- }
-
- /**
- * Retrieves a specific account by ID.
- *
- * @param accountId - The ID of the account to retrieve.
- * @param params - Additional options for the request.
- * @returns A promise resolving to the account.
- *
- * @example
- * ```typescript
- * const account = await client.getAccountById("account-id");
- * console.log(account);
- * ```
- *
- * @example
- * ```typescript
- * const account = await client.getAccountById("account-id", {
- * include_credentials: true,
- * });
- * console.log(account);
- * ```
- */
- public getAccountById(
- accountId: string,
- params: GetAccountByIdOpts = {},
- ): Promise {
- return this.makeConnectRequest(`/accounts/${accountId}`, {
- method: "GET",
- params,
- });
- }
-
- /**
- * Deletes a specific account by ID.
- *
- * @param accountId - The ID of the account to delete.
- * @returns A promise resolving when the account is deleted.
- *
- * @example
- * ```typescript
- * await client.deleteAccount("account-id");
- * console.log("Account deleted");
- * ```
- */
- public deleteAccount(accountId: string): Promise {
- return this.makeConnectRequest(`/accounts/${accountId}`, {
- method: "DELETE",
- });
- }
-
- /**
- * Deletes all accounts associated with a specific app.
- *
- * @param appId - The ID of the app.
- * @returns A promise resolving when all accounts are deleted.
- *
- * @example
- * ```typescript
- * await client.deleteAccountsByApp("app-id");
- * console.log("All accounts deleted");
- * ```
- */
- public deleteAccountsByApp(appId: string): Promise {
- return this.makeConnectRequest(`/accounts/app/${appId}`, {
- method: "DELETE",
- });
- }
-
- /**
- * Deletes all accounts associated with a specific external ID.
- *
- * @param externalId - The external ID associated with the accounts.
- * @returns A promise resolving when all accounts are deleted.
- *
- * @example
- * ```typescript
- * await client.deleteExternalUser("external-id");
- * console.log("All accounts deleted");
- * ```
- */
- public deleteExternalUser(externalId: string): Promise {
- return this.makeConnectRequest(`/users/${externalId}`, {
- method: "DELETE",
- });
- }
-
- /**
- * Retrieves the project's information, such as the list of apps linked to it.
- *
- * @returns A promise resolving to the project info response.
- *
- * @example
- * ```typescript
- * const projectInfo = await client.getProjectInfo();
- * console.log(projectInfo);
- * ```
- */
- public getProjectInfo(): Promise {
- return this.makeConnectRequest("/projects/info", {
- method: "GET",
- });
- }
-
- /**
- * Makes a proxy request to the target app API with the specified query parameters and options.
- *
- * @returns A promise resolving to the response from the downstream service
- */
- public makeProxyRequest(proxyOptions: ProxyApiOpts, targetRequest: ProxyTargetApiRequest): Promise {
- const url64 = btoa(targetRequest.url).replace(/\+/g, "-")
- .replace(/\//g, "_")
- .replace(/=+$/, "");
-
- const headers = targetRequest.options.headers || {};
-
- const newHeaders = Object.keys(headers).reduce<{ [key: string]: string }>((acc, key) => {
- acc[`x-pd-proxy-${key}`] = headers[key];
- return acc;
- }, {});
-
- const newOpts: RequestOptions = {
- method: targetRequest.options.method,
- headers: newHeaders,
- params: proxyOptions.searchParams,
- }
-
- if (targetRequest.options.body) {
- newOpts.body = targetRequest.options.body
- }
-
- return this.makeConnectRequest(`/proxy/${url64}`, newOpts);
- }
-}
diff --git a/packages/sdk/src/shared/component.ts b/packages/sdk/src/shared/component.ts
deleted file mode 100644
index 08aecefbc770f..0000000000000
--- a/packages/sdk/src/shared/component.ts
+++ /dev/null
@@ -1,279 +0,0 @@
-// eslint-disable @typescript-eslint/no-explicit-any
-type BaseConfigurableProp = {
- /**
- * When building `configuredProps`, make sure to use this field as the key when
- * setting the prop value.
- */
- name: string;
- type: string;
-
- // XXX don't actually apply to all, fix
-
- /**
- * Value to use as an input label. In cases where `type` is "app", should load
- * the app via `getApp`, etc. and show `app.name` instead.
- */
- label?: string;
-
- description?: string;
- optional?: boolean;
- disabled?: boolean;
-
- /**
- * If true, should not expose this prop to the user.
- */
- hidden?: boolean;
-
- /**
- * If true, call `configureComponent` for this prop to load remote options.
- * It is safe, and preferred, given a returned list of
- * { label: string; value: any } objects to set the prop
- * value to { __lv: { label: string; value: any } }. This way, on load, you
- * can access label for the value without necessarily reloading these options.
- */
- remoteOptions?: boolean;
-
- /**
- * If true, calls to `configureComponent` for this prop support receiving a
- * `query` parameter to filter remote options.
- */
- useQuery?: boolean;
-
- /**
- * If true, after setting a value for this prop, a call to `reloadComponentProps` is
- * required as the component has dynamic configurable props dependent on this
- * one.
- */
- reloadProps?: boolean;
-
- /**
- * If true, you must save the configured prop value as a "label-value" object
- * which should look like: { __lv: { label: string; value: any } }
- * because the execution needs to access the label.
- */
- withLabel?: boolean;
-};
-
-// XXX fix duplicating mapping to value type here and with PropValue
-
-type LabelValueOption = {
- label: string;
- value: T;
-};
-
-type Defaultable = {
- default?: T;
- options?: SingleT[] | Array>;
-}
-
-export type ConfigurablePropAlert = BaseConfigurableProp & {
- type: "alert";
- alertType?: "info" | "neutral" | "warning" | "error"; // TODO check the types
- content: string;
-};
-
-export type ConfigurablePropAny = BaseConfigurableProp & {
- type: "any";
-} & Defaultable; // eslint-disable-line @typescript-eslint/no-explicit-any
-
-export type ConfigurablePropApp = BaseConfigurableProp & {
- type: "app";
- app: string;
-};
-
-export type ConfigurablePropBoolean = BaseConfigurableProp & {
- type: "boolean";
-} & Defaultable;
-
-export type ConfigurablePropInteger = BaseConfigurableProp & {
- type: "integer";
- min?: number;
- max?: number;
-} & Defaultable;
-
-export type ConfigurablePropObject = BaseConfigurableProp & {
- type: "object";
-} & Defaultable