From 6858d81f0e8c78f0289a75d97aa3f11d92fc42e6 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 6 Dec 2024 14:01:43 -0800 Subject: [PATCH 1/9] Amend the Component API methods in the SDK * Fix the naming of the new methods for the Components API to follow the existing convention * Deprecate old methods and types * Document public methods and types * Fix some linter issues * Bump minor version --- packages/sdk/package.json | 2 +- packages/sdk/src/shared/index.ts | 475 ++++++++++++++++++++++++++----- 2 files changed, 410 insertions(+), 67 deletions(-) diff --git a/packages/sdk/package.json b/packages/sdk/package.json index e0a1b0c14544b..37cca219591be 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/sdk", - "version": "1.0.10", + "version": "1.1.0", "description": "Pipedream SDK", "main": "dist/server/server/index.js", "module": "dist/server/server/index.js", diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index 1b10340030ae6..bf28c2bb4dcf1 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -5,6 +5,8 @@ import type { AsyncResponseManager, } from "./async.js"; import type { + ConfigurableProps, + ConfiguredProps, V1Component, V1DeployedComponent, } from "./component.js"; @@ -62,7 +64,7 @@ export enum AppAuthType { /** * Response object for a Pipedream app's metadata */ -export type AppResponse = AppInfo & { +export type App = AppInfo & { /** * The human-readable name of the app. */ @@ -89,12 +91,23 @@ export type AppResponse = AppInfo & { categories: string[]; }; -export type ComponentConfigureResponse = { +/** + * @deprecated Use `App` instead. + */ +export type AppResponse = App; + +// TODO: Add docstring +export type ConfigureComponentResponse = { options: { label: string; value: string; }[]; stringOptions: string[]; errors: string[]; }; +/** + * @deprecated Use `ConfigureComponentResponse` instead. + */ +export type ComponentConfigureResponse = ConfigureComponentResponse; + /** * Parameters for the retrieval of apps from the Connect API */ @@ -185,28 +198,97 @@ export type Account = { credentials?: Record; }; -export type ComponentReloadPropsOpts = { +export type ReloadComponentPropsOpts = { + /** + * Your end user ID, for whom you're configuring the component. + */ + externalUserId: string; + + /** + * @deprecated Use `externalUserId` instead. + */ userId: string; - componentId: string; - configuredProps: any; // eslint-disable-line @typescript-eslint/no-explicit-any + + /** + * The ID of the component you're configuring. This is the key that uniquely + * identifies the component. + */ + componentId: string | ComponentId; + + /** + * The props that have already been configured for the component. This is a + * JSON-serializable object with the prop names as keys and the configured + * values as values. + */ + configuredProps: ConfiguredProps; + dynamicPropsId?: string; }; -export type ComponentConfigureOpts = { +/** + * @deprecated Use `ReloadComponentPropsOpts` instead. + */ +export type ComponentReloadPropsOpts = ReloadComponentPropsOpts; + +export type ConfigureComponentOpts = { + /** + * Your end user ID, for whom you're configuring the component. + */ + externalUserId: string; + + /** + * @deprecated Use `externalUserId` instead. + */ userId: string; - componentId: string; + + /** + * The ID of the component you're configuring. This is the key that uniquely + * identifies the component. + */ + componentId: string | ComponentId; + + /** + * The name of the prop you're configuring. + */ propName: string; - configuredProps: any; // eslint-disable-line @typescript-eslint/no-explicit-any + + /** + * The props that have already been configured for the component. This is a + * JSON-serializable object with the prop names as keys and the configured + * values as values. + */ + configuredProps: ConfiguredProps; + dynamicPropsId?: string; query?: string; }; -export type GetComponentOpts = { +/** + * @deprecated Use `ConfigureComponentOpts` instead. + */ +export type ComponentConfigureOpts = ConfigureComponentOpts; + +export type GetComponentsOpts = { q?: string; app?: string; componentType?: "trigger" | "action"; }; +/** + * @deprecated Use `GetComponentsOpts` instead. + */ +export type GetComponentOpts = GetComponentsOpts; + +export type ComponentId = { + /** + * The key that uniquely identifies the component. + * + * @example "gitlab-list-commits" + * @example "slack-send-message" + */ + key: string; +} + /** * Response received after creating a connect token. */ @@ -226,17 +308,108 @@ export type ConnectTokenResponse = { connect_link_url: string; }; -export type AccountsRequestResponse = { data: Account[]; }; +export type GetAccountsResponse = { data: Account[]; }; -export type AppsRequestResponse = { data: AppResponse[]; }; +/** + * @deprecated Use `GetAccountsResponse` instead. + */ +export type AccountsRequestResponse = GetAccountsResponse; -export type AppRequestResponse = { data: AppResponse; }; +export type GetAppsResponse = { data: App[]; }; -export type ComponentsRequestResponse = { +/** + * @deprecated Use `GetAppsResponse` instead. + */ +export type AppsRequestResponse = GetAppsResponse; + +export type GetAppResponse = { data: App; }; + +/** + * @deprecated Use `GetAppResponse` instead. + */ +export type AppRequestResponse = GetAppResponse; + +export type GetComponentsResponse = { data: Omit[]; }; -export type ComponentRequestResponse = { data: V1Component; }; +/** + * @deprecated Use `GetComponentsResponse` instead. + */ +export type ComponentsRequestResponse = GetComponentsResponse; + +export type GetComponentResponse = { data: V1Component; }; + +/** + * @deprecated Use `GetComponentResponse` instead. + */ +export type ComponentRequestResponse = GetComponentResponse; + +export type RunActionOpts = { + /** + * Your end user ID, for whom you're running the action. + */ + externalUserId: string; + + /** + * @deprecated Use `externalUserId` instead. + */ + userId: string; + + /** + * The ID of the action you're running. This is the key that uniquely + * identifies the action. + */ + actionId: string | ComponentId; + + /** + * The props that have already been configured for the action. This is a + * JSON-serializable object with the prop names as keys and the configured + * values as values. + */ + configuredProps: ConfiguredProps; + + dynamicPropsId?: string; +}; + +// TODO: Add docstring +export type RunActionResponse = { + exports: unknown; + os: unknown[]; + ret: unknown; +}; + +export type DeployTriggerOpts = { + /** + * Your end user ID, for whom you're deploying the trigger. + */ + externalUserId: string; + + /** + * @deprecated Use `externalUserId` instead. + */ + userId: string; + + /** + * The ID of the trigger you're deploying. This is the key that uniquely + * identifies the trigger. + */ + triggerId: string | ComponentId; + + /** + * The props that have already been configured for the trigger. This is a + * JSON-serializable object with the prop names as keys and the configured + * values as values. + */ + configuredProps: ConfiguredProps; + + dynamicPropsId?: string; + + /** + * The webhook URL that the trigger will use to send the events it generates. + */ + webhookUrl?: string; +}; /** * Different ways in which customers can authorize requests to HTTP endpoints @@ -502,24 +675,33 @@ export abstract class BaseClient { * console.log(accounts); * ``` */ - public async getAccounts( - params: GetAccountOpts = {}, - ): Promise { - const resp = await this.makeConnectRequest("/accounts", { + public getAccounts(params: GetAccountOpts = {}) { + return this.makeConnectRequest("/accounts", { method: "GET", params, }); - - return resp; } - // XXX only here while need project auth - public async apps(opts?: GetAppsOpts) { + /** + * Retrieves the list of apps available in Pipedream. + * + * @param params - The query parameters for retrieving apps. + * @param params.q - A search query to filter the apps. + * + * @returns A promise resolving to a list of apps. + * + * @example + * ```typescript + * const apps = await client.getApps({ q: "slack" }); + * console.log(apps); + * ``` + */ + public async getApps(opts?: GetAppsOpts) { const params: Record = {}; if (opts?.q) { params.q = opts.q; } - const resp = await this.makeAuthorizedRequest( + const resp = await this.makeAuthorizedRequest( "/apps", { method: "GET", @@ -529,16 +711,56 @@ export abstract class BaseClient { return resp; } - public async app(idOrNameSlug: string) { + /** + * @deprecated Use `getApps` instead. + */ + public apps(opts?: GetAppsOpts) { + return this.getApps(opts); + } + + /** + * Retrieves the metadata for a specific app. + * + * @param idOrNameSlug - The ID or name slug of the app. + * @returns A promise resolving to the app metadata. + * + * @example + * ```typescript + * const app = await client.getApp("slack"); + * console.log(app); + * ``` + */ + public async getApp(idOrNameSlug: string) { const url = `/apps/${idOrNameSlug}`; - const resp = await this.makeAuthorizedRequest(url, { + const resp = await this.makeAuthorizedRequest(url, { method: "GET", }); return resp; } - // XXX only here while need project auth - public async components(opts?: GetComponentOpts) { + /** + * @deprecated Use `getApp` instead. + */ + public app(idOrNameSlug: string) { + return this.getApp(idOrNameSlug); + } + + /** + * Retrieves the list of components available in Pipedream. + * + * @param opts - The options for retrieving components. + * @param opts.q - A search query to filter the components. + * @param opts.app - The ID or name slug of the app to filter the components. + * @param opts.componentType - The type of component to filter (either "trigger" or "action"). + * @returns A promise resolving to a list of components. + * + * @example + * ```typescript + * const components = await client.getComponents({ q: "slack" }); + * console.log(components); + * ``` + */ + public async getComponents(opts?: GetComponentsOpts) { const params: Record = { limit: "20", }; @@ -563,90 +785,211 @@ export abstract class BaseClient { return resp; } - public async component({ key }: { key: string; }) { - const url = `/components/${key}`; - const resp = await this.makeConnectRequest(url, { + /** + * @deprecated Use `getComponents` instead. + */ + public components(opts?: GetComponentOpts) { + return this.getComponents(opts); + } + + /** + * Retrieves the metadata for a specific component. + * + * @param id - The identifier of the component. + * @param id.key - The key that uniquely identifies the component. + * @returns A promise resolving to the component metadata. + * + * @example + * ```typescript + * const component = await client.getComponent("slack-send-message"); + * console.log(component); + * ``` + */ + public async getComponent(id: ComponentId) { + const { key } = id; + const path = `/components/${key}`; + const resp = await this.makeConnectRequest(path, { method: "GET", }); return resp; } - public async componentConfigure(opts: ComponentConfigureOpts) { + /** + * @deprecated Use `getComponent` instead. + */ + public component({ key }: { key: string; }) { + return this.getComponent({ + key, + }); + } + + /** + * Configure the next component's prop, based on the current component's + * configuration. + * @param opts - The options for configuring the component. + * @returns + */ + public configureComponent(opts: ConfigureComponentOpts) { + const { + userId, + externalUserId = userId, + componentId, + } = opts; + + const id = typeof componentId === "object" + ? componentId.key + : componentId; + const body = { async_handle: this.asyncResponseManager.createAsyncHandle(), - external_user_id: opts.userId, - id: opts.componentId, + external_user_id: externalUserId, + id, prop_name: opts.propName, configured_props: opts.configuredProps, dynamic_props_id: opts.dynamicPropsId, }; - return await this.makeConnectRequestAsync("/components/configure", { + return this.makeConnectRequestAsync("/components/configure", { method: "POST", body, }); } - public async componentReloadProps(opts: ComponentReloadPropsOpts) { + /** + * @deprecated Use `configureComponent` instead. + */ + public componentConfigure(opts: ComponentConfigureOpts) { + return this.configureComponent(opts); + } + + // TODO: Add docstring + public reloadComponentProps(opts: ReloadComponentPropsOpts) { + const { + userId, + externalUserId = userId, + componentId, + } = opts; + + const id = typeof componentId === "object" + ? componentId.key + : componentId; + // RpcActionReloadPropsInput const body = { async_handle: this.asyncResponseManager.createAsyncHandle(), - external_user_id: opts.userId, - id: opts.componentId, + external_user_id: externalUserId, + id, configured_props: opts.configuredProps, dynamic_props_id: opts.dynamicPropsId, }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return await this.makeConnectRequestAsync>("/components/props", { + + return this.makeConnectRequestAsync>( + "/components/props", { // TODO trigger - method: "POST", - body, - }); + method: "POST", + body, + }, + ); + } + + /** + * @deprecated Use `reloadComponentProps` instead. + */ + public componentReloadProps(opts: ComponentReloadPropsOpts) { + return this.reloadComponentProps(opts); } - public async actionRun(opts: { - userId: string; - actionId: string; - configuredProps: Record; // eslint-disable-line @typescript-eslint/no-explicit-any - dynamicPropsId?: string; - }) { + /** + * Invoke an action component for a Pipedream Connect user in a project + * + * @param opts + * @returns A promise resolving to the response from the action's execution. + * + * @example + * ```typescript + * const response = await client.runAction({ + * externalUserId: "jverce", + * actionId: { + * key: "gitlab-list-commits", + * }, + * configuredProps: { + * gitlab: { + * authProvisionId: "apn_z8hD1b4" + * }, + * projectId: 21208123, + * refName: "10-0-stable-ee", + * }, + * }); + * ``` + */ + public runAction(opts: RunActionOpts) { + const { + userId, + externalUserId = userId, + actionId, + } = opts; + + const id = typeof actionId === "object" + ? actionId.key + : actionId; + const body = { async_handle: this.asyncResponseManager.createAsyncHandle(), - external_user_id: opts.userId, - id: opts.actionId, + external_user_id: externalUserId, + id, configured_props: opts.configuredProps, dynamic_props_id: opts.dynamicPropsId, }; - return await this.makeConnectRequestAsync<{ - exports: unknown; - os: unknown[]; - ret: unknown; - }>("/actions/run", { + return this.makeConnectRequestAsync("/actions/run", { method: "POST", body, }); } - public async triggerDeploy(opts: { - userId: string; - triggerId: string; - configuredProps: Record; // eslint-disable-line @typescript-eslint/no-explicit-any - dynamicPropsId?: string; - webhookUrl?: string; - }) { + /** + * @deprecated Use `runAction` instead. + */ + public actionRun(opts: RunActionOpts) { + return this.runAction(opts); + } + + /** + * Deploy a trigger component for a Pipedream Connect user in a project + * + * @param opts + * @returns A promise resolving to the response from the trigger's deployment. + */ + public deployTrigger(opts: DeployTriggerOpts) { + const { + userId, + externalUserId = userId, + triggerId, + } = opts; + + const id = typeof triggerId === "object" + ? triggerId.key + : triggerId; + const body = { async_handle: this.asyncResponseManager.createAsyncHandle(), - external_user_id: opts.userId, - id: opts.triggerId, + external_user_id: externalUserId, + id, configured_props: opts.configuredProps, dynamic_props_id: opts.dynamicPropsId, webhook_url: opts.webhookUrl, - } - return await this.makeConnectRequestAsync("/triggers/deploy", { + }; + return this.makeConnectRequestAsync("/triggers/deploy", { method: "POST", body, }); } + /** + * @deprecated Use `triggerDeploy` instead. + */ + public triggerDeploy(opts: DeployTriggerOpts) { + return this.triggerDeploy(opts); + } + /** * Builds a full workflow URL based on the input. * From 506c0124d7c531a81495d79bd06205a490082d89 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 6 Dec 2024 14:14:56 -0800 Subject: [PATCH 2/9] Update packages/sdk/src/shared/index.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- packages/sdk/src/shared/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index bf28c2bb4dcf1..d3ab2d93b2df6 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -987,7 +987,7 @@ export abstract class BaseClient { * @deprecated Use `triggerDeploy` instead. */ public triggerDeploy(opts: DeployTriggerOpts) { - return this.triggerDeploy(opts); + return this.deployTrigger(opts); } /** From d3feb8a73d8635f079c0043b947681ec8d14a59e Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 6 Dec 2024 16:34:50 -0800 Subject: [PATCH 3/9] Fix type issues --- packages/sdk/src/shared/index.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index d3ab2d93b2df6..2eb0362e2e8cf 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -13,6 +13,12 @@ import type { export * from "./component.js"; import { version as sdkVersion } from "../version.js"; +export type RequireAtLeastOne = + Pick> + & { + [K in Keys]-?: Required> & Partial>> + }[Keys] + type RequestInit = globalThis.RequestInit; /** @@ -198,16 +204,16 @@ export type Account = { credentials?: Record; }; -export type ReloadComponentPropsOpts = { +export type ReloadComponentPropsOpts = RequireAtLeastOne<{ /** * Your end user ID, for whom you're configuring the component. */ - externalUserId: string; + externalUserId?: string; /** * @deprecated Use `externalUserId` instead. */ - userId: string; + userId?: string; /** * The ID of the component you're configuring. This is the key that uniquely @@ -223,14 +229,14 @@ export type ReloadComponentPropsOpts = { configuredProps: ConfiguredProps; dynamicPropsId?: string; -}; +}, "externalUserId" | "userId">; /** * @deprecated Use `ReloadComponentPropsOpts` instead. */ export type ComponentReloadPropsOpts = ReloadComponentPropsOpts; -export type ConfigureComponentOpts = { +export type ConfigureComponentOpts = RequireAtLeastOne<{ /** * Your end user ID, for whom you're configuring the component. */ @@ -261,7 +267,7 @@ export type ConfigureComponentOpts = { dynamicPropsId?: string; query?: string; -}; +}, "externalUserId" | "userId">; /** * @deprecated Use `ConfigureComponentOpts` instead. @@ -345,7 +351,7 @@ export type GetComponentResponse = { data: V1Component; }; */ export type ComponentRequestResponse = GetComponentResponse; -export type RunActionOpts = { +export type RunActionOpts = RequireAtLeastOne<{ /** * Your end user ID, for whom you're running the action. */ @@ -370,7 +376,7 @@ export type RunActionOpts = { configuredProps: ConfiguredProps; dynamicPropsId?: string; -}; +}, "externalUserId" | "userId">; // TODO: Add docstring export type RunActionResponse = { From 329578beb22df0b4d6ee8a01a64d05c50d3d0737 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 6 Dec 2024 16:41:43 -0800 Subject: [PATCH 4/9] Update PNPM lock file --- pnpm-lock.yaml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8b5c6b1cf95c..c8ddefc8502bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12320,7 +12320,7 @@ importers: version: 3.1.7 ts-jest: specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2) + version: 29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2) typescript: specifier: ^5.6 version: 5.7.2 @@ -24472,22 +24472,22 @@ packages: superagent@3.8.1: resolution: {integrity: sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==} engines: {node: '>= 4.0'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at . superagent@4.1.0: resolution: {integrity: sha512-FT3QLMasz0YyCd4uIi5HNe+3t/onxMyEho7C3PSqmti3Twgy2rXT4fmkTz6wRL6bTF4uzPcfkUCa8u4JWHw8Ag==} engines: {node: '>= 6.0'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at . superagent@5.3.1: resolution: {integrity: sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==} engines: {node: '>= 7.0.0'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net + deprecated: Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at . superagent@7.1.6: resolution: {integrity: sha512-gZkVCQR1gy/oUXr+kxJMLDjla434KmSOKbx5iGD30Ql+AkJQ/YlPKECJy2nhqOsHLjGHzoDTXNSjhnvWhzKk7g==} engines: {node: '>=6.4.0 <13 || >=14'} - deprecated: Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net + deprecated: Please downgrade to v7.1.5 if you need IE/ActiveXObject support OR upgrade to v8.0.0 as we no longer support IE and published an incorrect patch version (see https://github.com/visionmedia/superagent/issues/1731) supports-color@2.0.0: resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} @@ -43108,7 +43108,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2): + ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.6.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -43119,15 +43119,15 @@ snapshots: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.7.2 + typescript: 5.6.3 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.26.0 + '@babel/core': 8.0.0-alpha.13 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.0) + babel-jest: 29.7.0(@babel/core@8.0.0-alpha.13) - ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.6.3): + ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -43138,7 +43138,7 @@ snapshots: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.6.3 + typescript: 5.7.2 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 8.0.0-alpha.13 From 8b37dbb8c809f739594f34e5fd5dea9988e8d70d Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Fri, 6 Dec 2024 16:42:44 -0800 Subject: [PATCH 5/9] Update PNPM lock file --- pnpm-lock.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8ddefc8502bc..fca0576bc0dfc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12320,7 +12320,7 @@ importers: version: 3.1.7 ts-jest: specifier: ^29.2.5 - version: 29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2) + version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2) typescript: specifier: ^5.6 version: 5.7.2 @@ -43108,7 +43108,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.6.3): + ts-jest@29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -43119,15 +43119,15 @@ snapshots: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.6.3 + typescript: 5.7.2 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 8.0.0-alpha.13 + '@babel/core': 7.26.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@8.0.0-alpha.13) + babel-jest: 29.7.0(@babel/core@7.26.0) - ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.7.2): + ts-jest@29.2.5(@babel/core@8.0.0-alpha.13)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@8.0.0-alpha.13))(jest@29.7.0(@types/node@20.17.6)(babel-plugin-macros@3.1.0))(typescript@5.6.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -43138,7 +43138,7 @@ snapshots: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.7.2 + typescript: 5.6.3 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 8.0.0-alpha.13 From d6988cfb3feae93ab240e166f541c7c45cdefebe Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Mon, 9 Dec 2024 14:36:23 -0800 Subject: [PATCH 6/9] Remove unnecessary awaits --- packages/sdk/src/shared/index.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index bc65e49a94b0f..974bac144dd4a 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -742,12 +742,11 @@ export abstract class BaseClient { * console.log(app); * ``` */ - public async getApp(idOrNameSlug: string) { + public getApp(idOrNameSlug: string) { const url = `/apps/${idOrNameSlug}`; - const resp = await this.makeAuthorizedRequest(url, { + return this.makeAuthorizedRequest(url, { method: "GET", }); - return resp; } /** @@ -772,7 +771,7 @@ export abstract class BaseClient { * console.log(components); * ``` */ - public async getComponents(opts?: GetComponentsOpts) { + public getComponents(opts?: GetComponentsOpts) { const params: Record = {}; if (opts?.app) { params.app = opts.app; @@ -789,11 +788,10 @@ export abstract class BaseClient { path = "/actions"; } // XXX Is V1Component the correct type for triggers and actions? - const resp = await this.makeConnectRequest(path, { + return this.makeConnectRequest(path, { method: "GET", params, }); - return resp; } /** @@ -816,13 +814,12 @@ export abstract class BaseClient { * console.log(component); * ``` */ - public async getComponent(id: ComponentId) { + public getComponent(id: ComponentId) { const { key } = id; const path = `/components/${key}`; - const resp = await this.makeConnectRequest(path, { + return this.makeConnectRequest(path, { method: "GET", }); - return resp; } /** From 4c8e57cfdd4a06afee3100fd36513b4a8493466b Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Mon, 9 Dec 2024 14:41:55 -0800 Subject: [PATCH 7/9] Cleanup --- packages/sdk/src/shared/index.ts | 265 ++++++++++++++++++++++++------- 1 file changed, 205 insertions(+), 60 deletions(-) diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index 974bac144dd4a..03a4fa49e15e5 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -13,12 +13,27 @@ import type { export * from "./component.js"; import { version as sdkVersion } from "../version.js"; -export type RequireAtLeastOne = +type RequireAtLeastOne = Pick> & { [K in Keys]-?: Required> & Partial>> }[Keys] +// Using `RequireAtLeastOne` here prevents the renaming of the attribute to +// break existing SDK users, by keeping the old attribute name, while ensuring +// that at least one of the two attributes is present. +type ExternalUserId = RequireAtLeastOne<{ + /** + * Your end user ID, for whom you're configuring the component. + */ + externalUserId: string; + + /** + * @deprecated Use `externalUserId` instead. + */ + userId: string; +}, "externalUserId" | "userId">; + type RequestInit = globalThis.RequestInit; /** @@ -45,6 +60,9 @@ export type ClientOpts = { workflowDomain?: string; }; +/** + * Basic ID information of a Pipedream app. + */ export type AppInfo = { /** * ID of the app. Only applies for OAuth apps. @@ -102,16 +120,56 @@ export type App = AppInfo & { */ export type AppResponse = App; -// TODO: Add docstring +/** + * The response received after configuring a component's prop. + */ export type ConfigureComponentResponse = { + /** + * The options for the prop that's being configured. This field is applicable + * when the values don't nicely map to a descriptive string. Useful when the + * values for each option are meaningless numeric IDs, unless mapped to a + * human-readable string. + * + * @example a branch with ID `21208123` and name `my-repo/foo` in a Gitlab + * repo + * ```json + * { + * "label": "my-repo/foo", + * "value": 21208123 + * } + * ``` + */ options: { label: string; value: string; }[]; + + /** + * The options for the prop that's being configured. This field is applicable + * when the values themselves are already human-readable strings. + */ stringOptions: string[]; + + /** + * A list of errors that occurred during the configuration process. + */ errors: string[]; }; +/** + * Attributes to use for pagination in API requests. + */ export type RelationOpts = { + /** + * The retrieve records starting from a certain cursor. + */ after?: string; + + /** + * To retrieve records up until a certain cursor. + */ before?: string; + + /** + * The maximum number of records to retrieve. + */ limit?: number; }; @@ -210,17 +268,11 @@ export type Account = { credentials?: Record; }; -export type ReloadComponentPropsOpts = RequireAtLeastOne<{ - /** - * Your end user ID, for whom you're configuring the component. - */ - externalUserId?: string; - - /** - * @deprecated Use `externalUserId` instead. - */ - userId?: string; - +/** + * The request options for reconfiguring a component's props when dealing with + * dynamic props. + */ +export type ReloadComponentPropsOpts = ExternalUserId & { /** * The ID of the component you're configuring. This is the key that uniquely * identifies the component. @@ -234,25 +286,22 @@ export type ReloadComponentPropsOpts = RequireAtLeastOne<{ */ configuredProps: ConfiguredProps; + /** + * The ID of the last prop reconfiguration (or none when reconfiguring the + * props for the first time). + */ dynamicPropsId?: string; -}, "externalUserId" | "userId">; +}; /** * @deprecated Use `ReloadComponentPropsOpts` instead. */ export type ComponentReloadPropsOpts = ReloadComponentPropsOpts; -export type ConfigureComponentOpts = RequireAtLeastOne<{ - /** - * Your end user ID, for whom you're configuring the component. - */ - externalUserId: string; - - /** - * @deprecated Use `externalUserId` instead. - */ - userId: string; - +/** + * The request options for configuring a component's prop. + */ +export type ConfigureComponentOpts = ExternalUserId & { /** * The ID of the component you're configuring. This is the key that uniquely * identifies the component. @@ -271,19 +320,37 @@ export type ConfigureComponentOpts = RequireAtLeastOne<{ */ configuredProps: ConfiguredProps; + /** + * The ID of the last prop reconfiguration (if any). + */ dynamicPropsId?: string; + query?: string; -}, "externalUserId" | "userId">; +}; /** * @deprecated Use `ConfigureComponentOpts` instead. */ export type ComponentConfigureOpts = ConfigureComponentOpts; +/** + * The request options for retrieving a list of components. + */ export type GetComponentsOpts = RelationOpts & { + /** + * A search query to filter the components. + */ q?: string; + + /** + * The ID or name slug of the app to filter the components. + */ app?: string; - componentType?: "trigger" | "action"; + + /** + * The type of component to filter (either "trigger" or "action"). + */ + componentType?: ComponentType; }; /** @@ -299,7 +366,12 @@ export type ComponentId = { * @example "slack-send-message" */ key: string; -} +}; + +/** + * Components can be either triggers or actions. + */ +export type ComponentType = "trigger" | "action"; /** * Response received after creating a connect token. @@ -314,12 +386,16 @@ export type ConnectTokenResponse = { * The expiration time of the token in ISO 8601 format. */ expires_at: string; + /** * The Connect Link URL */ connect_link_url: string; }; +/** + * The response received when retrieving a list of accounts. + */ export type GetAccountsResponse = { data: Account[]; }; /** @@ -327,6 +403,9 @@ export type GetAccountsResponse = { data: Account[]; }; */ export type AccountsRequestResponse = GetAccountsResponse; +/** + * The response received when retrieving a list of apps. + */ export type GetAppsResponse = { data: App[]; }; /** @@ -334,6 +413,9 @@ export type GetAppsResponse = { data: App[]; }; */ export type AppsRequestResponse = GetAppsResponse; +/** + * The response received when retrieving a specific app. + */ export type GetAppResponse = { data: App; }; /** @@ -341,6 +423,9 @@ export type GetAppResponse = { data: App; }; */ export type AppRequestResponse = GetAppResponse; +/** + * The response received when retrieving a list of components. + */ export type GetComponentsResponse = { data: Omit[]; }; @@ -350,6 +435,9 @@ export type GetComponentsResponse = { */ export type ComponentsRequestResponse = GetComponentsResponse; +/** + * The response received when retrieving a specific component. + */ export type GetComponentResponse = { data: V1Component; }; /** @@ -357,17 +445,10 @@ export type GetComponentResponse = { data: V1Component; }; */ export type ComponentRequestResponse = GetComponentResponse; -export type RunActionOpts = RequireAtLeastOne<{ - /** - * Your end user ID, for whom you're running the action. - */ - externalUserId: string; - - /** - * @deprecated Use `externalUserId` instead. - */ - userId: string; - +/** + * The request options for running an action. + */ +export type RunActionOpts = ExternalUserId & { /** * The ID of the action you're running. This is the key that uniquely * identifies the action. @@ -381,27 +462,38 @@ export type RunActionOpts = RequireAtLeastOne<{ */ configuredProps: ConfiguredProps; + /** + * The ID of the last prop reconfiguration (if any). + */ dynamicPropsId?: string; -}, "externalUserId" | "userId">; +}; -// TODO: Add docstring +/** + * The response received after running an action. See + * https://pipedream.com/docs/components/api#returning-data-from-steps for more + * details. + */ export type RunActionResponse = { + /** + * The key-value pairs resulting from calls to `$.export` + */ exports: unknown; - os: unknown[]; - ret: unknown; -}; -export type DeployTriggerOpts = { /** - * Your end user ID, for whom you're deploying the trigger. + * Any logs produced during the execution of the action */ - externalUserId: string; + os: unknown[]; /** - * @deprecated Use `externalUserId` instead. + * The value returned by the action */ - userId: string; + ret: unknown; +}; +/** + * The request options for deploying a trigger. + */ +export type DeployTriggerOpts = ExternalUserId & { /** * The ID of the trigger you're deploying. This is the key that uniquely * identifies the trigger. @@ -415,6 +507,9 @@ export type DeployTriggerOpts = { */ configuredProps: ConfiguredProps; + /** + * The ID of the last prop reconfiguration (if any). + */ dynamicPropsId?: string; /** @@ -697,9 +792,7 @@ export abstract class BaseClient { /** * Retrieves the list of apps available in Pipedream. * - * @param params - The query parameters for retrieving apps. - * @param params.q - A search query to filter the apps. - * + * @param opts - The options for retrieving apps. * @returns A promise resolving to a list of apps. * * @example @@ -760,9 +853,6 @@ export abstract class BaseClient { * Retrieves the list of components available in Pipedream. * * @param opts - The options for retrieving components. - * @param opts.q - A search query to filter the components. - * @param opts.app - The ID or name slug of the app to filter the components. - * @param opts.componentType - The type of component to filter (either "trigger" or "action"). * @returns A promise resolving to a list of components. * * @example @@ -805,7 +895,6 @@ export abstract class BaseClient { * Retrieves the metadata for a specific component. * * @param id - The identifier of the component. - * @param id.key - The key that uniquely identifies the component. * @returns A promise resolving to the component metadata. * * @example @@ -834,8 +923,23 @@ export abstract class BaseClient { /** * Configure the next component's prop, based on the current component's * configuration. + * * @param opts - The options for configuring the component. - * @returns + * @returns A promise resolving to the response from the configuration. + * + * @example + * ```typescript + * const { options } = await client.configureComponent({ + * externalUserId: "jverce", + * componentId: { + * key: "slack-send-message", + * }, + * propName: "channel", + * configuredProps: { + * authProvisionId: "apn_z8hD1b4", + * } + * }); + * console.log(options); */ public configureComponent(opts: ConfigureComponentOpts) { const { @@ -869,7 +973,30 @@ export abstract class BaseClient { return this.configureComponent(opts); } - // TODO: Add docstring + /** + * Reload the component prop's based on the current component's configuration. + * This applies to dynamic props (see the docs for more info: + * https://pipedream.com/docs/components/api#dynamic-props). + * + * @param opts - The options for reloading the component's props. + * @returns A promise resolving to the response from the reload. + * + * @example + * ```typescript + * const { dynamicProps } = await client.reloadComponentProps({ + * externalUserId: "jverce", + * componentId: { + * key: "slack-send-message", + * }, + * configuredProps: { + * authProvisionId: "apn_z8hD1b4", + * } + * }); + * + * const { configurableProps, id: dynamicPropsId } = dynamicProps; + * // Use `dynamicPropsId` to configure the next prop + * // Use `configurableProps` to display the new set of props to the user + */ public reloadComponentProps(opts: ReloadComponentPropsOpts) { const { userId, @@ -909,7 +1036,7 @@ export abstract class BaseClient { /** * Invoke an action component for a Pipedream Connect user in a project * - * @param opts + * @param opts - The options for running the action. * @returns A promise resolving to the response from the action's execution. * * @example @@ -927,6 +1054,7 @@ export abstract class BaseClient { * refName: "10-0-stable-ee", * }, * }); + * console.log(response); * ``` */ public runAction(opts: RunActionOpts) { @@ -963,8 +1091,25 @@ export abstract class BaseClient { /** * Deploy a trigger component for a Pipedream Connect user in a project * - * @param opts + * @param opts - The options for deploying the trigger. * @returns A promise resolving to the response from the trigger's deployment. + * + * @example + * ```typescript + * const response = await client.deployTrigger({ + * externalUserId: "jverce", + * triggerId: { + * key: "gitlab-new-issue", + * }, + * configuredProps: { + * gitlab: { + * authProvisionId: "apn_z8hD1b4", + * }, + * projectId: 21208123, + * }, + * webhookUrl: "https://dest.mydomain.com", + * }); + * console.log(response); */ public deployTrigger(opts: DeployTriggerOpts) { const { From c5c9684d0454c1505b49d332a5f2605572bd98fd Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Tue, 10 Dec 2024 10:31:01 -0800 Subject: [PATCH 8/9] Apply suggestions from coderabbit Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- packages/sdk/src/shared/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index 03a4fa49e15e5..0880047463528 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -878,7 +878,7 @@ export abstract class BaseClient { path = "/actions"; } // XXX Is V1Component the correct type for triggers and actions? - return this.makeConnectRequest(path, { + return this.makeConnectRequest(path, { method: "GET", params, }); @@ -1137,7 +1137,7 @@ export abstract class BaseClient { } /** - * @deprecated Use `triggerDeploy` instead. + * @deprecated Use `deployTrigger` instead. */ public triggerDeploy(opts: DeployTriggerOpts) { return this.deployTrigger(opts); From b2b46455bf0b65fec04711347d9b2e29ebbff477 Mon Sep 17 00:00:00 2001 From: Jay Vercellone Date: Tue, 10 Dec 2024 10:32:48 -0800 Subject: [PATCH 9/9] Add missing doc to type --- packages/sdk/src/shared/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/sdk/src/shared/index.ts b/packages/sdk/src/shared/index.ts index 0880047463528..da8fce0b9bc45 100644 --- a/packages/sdk/src/shared/index.ts +++ b/packages/sdk/src/shared/index.ts @@ -358,6 +358,9 @@ export type GetComponentsOpts = RelationOpts & { */ export type GetComponentOpts = GetComponentsOpts; +/** + * An object that identifies a single, unique component in Pipedream. + */ export type ComponentId = { /** * The key that uniquely identifies the component.