@zapier/zapier-sdk 0.70.4 → 0.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +133 -15
- package/dist/api/approval-review-stream.d.ts +25 -0
- package/dist/api/approval-review-stream.d.ts.map +1 -0
- package/dist/api/approval-review-stream.js +104 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +215 -27
- package/dist/api/types.d.ts +13 -3
- package/dist/api/types.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -0
- package/dist/experimental.cjs +593 -33
- package/dist/experimental.d.mts +86 -2
- package/dist/experimental.d.ts +88 -4
- package/dist/experimental.d.ts.map +1 -1
- package/dist/experimental.js +10 -0
- package/dist/experimental.mjs +593 -34
- package/dist/{index-BNaiNmM-.d.mts → index-B43uST61.d.mts} +181 -12
- package/dist/{index-BNaiNmM-.d.ts → index-B43uST61.d.ts} +181 -12
- package/dist/index.cjs +592 -32
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +592 -33
- package/dist/plugins/api/index.d.ts.map +1 -1
- package/dist/plugins/api/index.js +2 -1
- package/dist/plugins/codeSubstrate/deleteWorkflow/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/disableWorkflow/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/enableWorkflow/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/getDurableRun/schemas.d.ts +4 -4
- package/dist/plugins/codeSubstrate/getWorkflow/index.d.ts +2 -2
- package/dist/plugins/codeSubstrate/getWorkflow/schemas.d.ts +1 -1
- package/dist/plugins/codeSubstrate/getWorkflowRun/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/getWorkflowVersion/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/listWorkflowRuns/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/listWorkflowVersions/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/listWorkflows/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/listWorkflows/schemas.d.ts +2 -2
- package/dist/plugins/codeSubstrate/publishWorkflowVersion/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/shared-schemas.d.ts +2 -2
- package/dist/plugins/codeSubstrate/triggerWorkflow/index.d.ts +1 -1
- package/dist/plugins/codeSubstrate/updateWorkflow/index.d.ts +1 -1
- package/dist/plugins/createConnection/index.d.ts +189 -0
- package/dist/plugins/createConnection/index.d.ts.map +1 -0
- package/dist/plugins/createConnection/index.js +71 -0
- package/dist/plugins/createConnection/schemas.d.ts +21 -0
- package/dist/plugins/createConnection/schemas.d.ts.map +1 -0
- package/dist/plugins/createConnection/schemas.js +38 -0
- package/dist/plugins/getConnectionStartUrl/index.d.ts +206 -0
- package/dist/plugins/getConnectionStartUrl/index.d.ts.map +1 -0
- package/dist/plugins/getConnectionStartUrl/index.js +39 -0
- package/dist/plugins/getConnectionStartUrl/schemas.d.ts +15 -0
- package/dist/plugins/getConnectionStartUrl/schemas.d.ts.map +1 -0
- package/dist/plugins/getConnectionStartUrl/schemas.js +23 -0
- package/dist/plugins/waitForNewConnection/index.d.ts +209 -0
- package/dist/plugins/waitForNewConnection/index.d.ts.map +1 -0
- package/dist/plugins/waitForNewConnection/index.js +75 -0
- package/dist/plugins/waitForNewConnection/schemas.d.ts +17 -0
- package/dist/plugins/waitForNewConnection/schemas.d.ts.map +1 -0
- package/dist/plugins/waitForNewConnection/schemas.js +39 -0
- package/dist/sdk.d.ts +126 -0
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +8 -0
- package/dist/types/errors.d.ts +13 -4
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +2 -0
- package/dist/types/sdk.d.ts +1 -0
- package/dist/types/sdk.d.ts.map +1 -1
- package/dist/types/sdk.js +5 -1
- package/dist/utils/open-url.d.ts.map +1 -1
- package/dist/utils/open-url.js +7 -0
- package/dist/utils/should-open-browser.d.ts +24 -0
- package/dist/utils/should-open-browser.d.ts.map +1 -0
- package/dist/utils/should-open-browser.js +55 -0
- package/package.json +1 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { type GetConnectionStartUrlItem } from "./schemas";
|
|
2
|
+
export declare const getConnectionStartUrlPlugin: (sdk: {
|
|
3
|
+
context: {
|
|
4
|
+
api: import("../..").ApiClient;
|
|
5
|
+
resolveCredentials: () => Promise<string | {
|
|
6
|
+
clientId: string;
|
|
7
|
+
clientSecret: string;
|
|
8
|
+
type?: "client_credentials" | undefined;
|
|
9
|
+
baseUrl?: string | undefined;
|
|
10
|
+
scope?: string | undefined;
|
|
11
|
+
} | {
|
|
12
|
+
clientId: string;
|
|
13
|
+
type?: "pkce" | undefined;
|
|
14
|
+
baseUrl?: string | undefined;
|
|
15
|
+
scope?: string | undefined;
|
|
16
|
+
} | undefined>;
|
|
17
|
+
};
|
|
18
|
+
} & {
|
|
19
|
+
context: {
|
|
20
|
+
getResolvedManifest: () => Promise<import("../manifest").Manifest | null>;
|
|
21
|
+
getVersionedImplementationId: (appKey: string) => Promise<string | null>;
|
|
22
|
+
resolveAppKeys: ({ appKeys }: {
|
|
23
|
+
appKeys: string[];
|
|
24
|
+
}) => Promise<import("../..").ResolvedAppLocator[]>;
|
|
25
|
+
updateManifestEntry: (options: import("../manifest").UpdateManifestEntryOptions) => Promise<import("../manifest").UpdateManifestEntryResult>;
|
|
26
|
+
addActionEntry: (options: import("../manifest").AddActionEntryOptions) => Promise<import("../manifest").AddActionEntryResult>;
|
|
27
|
+
findActionEntry: ({ name, manifest, }: {
|
|
28
|
+
name: string;
|
|
29
|
+
manifest: import("../manifest").Manifest;
|
|
30
|
+
}) => import("../manifest").ActionEntry | null;
|
|
31
|
+
listActionEntries: ({ configPath, }?: {
|
|
32
|
+
configPath?: string;
|
|
33
|
+
}) => Promise<Array<[string, import("../manifest").ActionEntry]>>;
|
|
34
|
+
deleteActionEntry: ({ name, configPath, skipWrite, }: {
|
|
35
|
+
name: string;
|
|
36
|
+
configPath?: string;
|
|
37
|
+
skipWrite?: boolean;
|
|
38
|
+
}) => Promise<import("../manifest").Manifest>;
|
|
39
|
+
hasActionEntry: ({ name, manifest, }: {
|
|
40
|
+
name: string;
|
|
41
|
+
manifest: import("../manifest").Manifest;
|
|
42
|
+
}) => boolean;
|
|
43
|
+
findManifestEntry: typeof import("../manifest").findManifestEntry;
|
|
44
|
+
readManifestFromFile: typeof import("../manifest").readManifestFromFile;
|
|
45
|
+
getManifestConnections: () => Promise<Record<string, {
|
|
46
|
+
connectionId: string | number;
|
|
47
|
+
}> | null>;
|
|
48
|
+
};
|
|
49
|
+
} & {
|
|
50
|
+
getApp: (options?: {
|
|
51
|
+
app: string;
|
|
52
|
+
} | {
|
|
53
|
+
appKey: string;
|
|
54
|
+
} | undefined) => Promise<{
|
|
55
|
+
data: {
|
|
56
|
+
slug: string;
|
|
57
|
+
title: string;
|
|
58
|
+
key: string;
|
|
59
|
+
implementation_id: string;
|
|
60
|
+
description?: string | undefined;
|
|
61
|
+
is_hidden?: boolean | undefined;
|
|
62
|
+
auth_type?: string | undefined;
|
|
63
|
+
actions?: {
|
|
64
|
+
read?: number | undefined;
|
|
65
|
+
read_bulk?: number | undefined;
|
|
66
|
+
write?: number | undefined;
|
|
67
|
+
search?: number | undefined;
|
|
68
|
+
search_or_write?: number | undefined;
|
|
69
|
+
search_and_write?: number | undefined;
|
|
70
|
+
filter?: number | undefined;
|
|
71
|
+
} | undefined;
|
|
72
|
+
is_deprecated?: boolean | undefined;
|
|
73
|
+
is_beta?: boolean | undefined;
|
|
74
|
+
is_premium?: boolean | undefined;
|
|
75
|
+
age_in_days?: number | undefined;
|
|
76
|
+
banner?: string | undefined;
|
|
77
|
+
categories?: {
|
|
78
|
+
id: number;
|
|
79
|
+
name: string;
|
|
80
|
+
slug: string;
|
|
81
|
+
}[] | undefined;
|
|
82
|
+
images?: {
|
|
83
|
+
url_16x16?: string | undefined;
|
|
84
|
+
url_32x32?: string | undefined;
|
|
85
|
+
url_64x64?: string | undefined;
|
|
86
|
+
url_128x128?: string | undefined;
|
|
87
|
+
} | undefined;
|
|
88
|
+
popularity?: number | undefined;
|
|
89
|
+
has_filters?: boolean | undefined;
|
|
90
|
+
has_reads?: boolean | undefined;
|
|
91
|
+
has_searches?: boolean | undefined;
|
|
92
|
+
has_searches_or_writes?: boolean | undefined;
|
|
93
|
+
has_upfront_fields?: boolean | undefined;
|
|
94
|
+
has_writes?: boolean | undefined;
|
|
95
|
+
is_built_in?: boolean | undefined;
|
|
96
|
+
is_featured?: boolean | undefined;
|
|
97
|
+
is_invite?: boolean | undefined;
|
|
98
|
+
is_public?: boolean | undefined;
|
|
99
|
+
is_upcoming?: boolean | undefined;
|
|
100
|
+
visibility?: string | undefined;
|
|
101
|
+
primary_color?: string | undefined;
|
|
102
|
+
secondary_color?: string | undefined;
|
|
103
|
+
classification?: string | undefined;
|
|
104
|
+
api_docs_url?: string | undefined;
|
|
105
|
+
image?: string | undefined;
|
|
106
|
+
version?: string | undefined;
|
|
107
|
+
};
|
|
108
|
+
}>;
|
|
109
|
+
} & {
|
|
110
|
+
context: {
|
|
111
|
+
meta: {
|
|
112
|
+
getApp: import("kitcore").PluginMeta<unknown>;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
} & {
|
|
116
|
+
listApps: (options?: ({
|
|
117
|
+
search?: string | undefined;
|
|
118
|
+
apps?: string[] | undefined;
|
|
119
|
+
appKeys?: string[] | undefined;
|
|
120
|
+
pageSize?: number | undefined;
|
|
121
|
+
maxItems?: number | undefined;
|
|
122
|
+
cursor?: string | undefined;
|
|
123
|
+
} & {
|
|
124
|
+
cursor?: string;
|
|
125
|
+
pageSize?: number;
|
|
126
|
+
maxItems?: number;
|
|
127
|
+
}) | undefined) => import("kitcore").PaginatedSdkResult<{
|
|
128
|
+
slug: string;
|
|
129
|
+
title: string;
|
|
130
|
+
key: string;
|
|
131
|
+
implementation_id: string;
|
|
132
|
+
description?: string | undefined;
|
|
133
|
+
is_hidden?: boolean | undefined;
|
|
134
|
+
auth_type?: string | undefined;
|
|
135
|
+
actions?: {
|
|
136
|
+
read?: number | undefined;
|
|
137
|
+
read_bulk?: number | undefined;
|
|
138
|
+
write?: number | undefined;
|
|
139
|
+
search?: number | undefined;
|
|
140
|
+
search_or_write?: number | undefined;
|
|
141
|
+
search_and_write?: number | undefined;
|
|
142
|
+
filter?: number | undefined;
|
|
143
|
+
} | undefined;
|
|
144
|
+
is_deprecated?: boolean | undefined;
|
|
145
|
+
is_beta?: boolean | undefined;
|
|
146
|
+
is_premium?: boolean | undefined;
|
|
147
|
+
age_in_days?: number | undefined;
|
|
148
|
+
banner?: string | undefined;
|
|
149
|
+
categories?: {
|
|
150
|
+
id: number;
|
|
151
|
+
name: string;
|
|
152
|
+
slug: string;
|
|
153
|
+
}[] | undefined;
|
|
154
|
+
images?: {
|
|
155
|
+
url_16x16?: string | undefined;
|
|
156
|
+
url_32x32?: string | undefined;
|
|
157
|
+
url_64x64?: string | undefined;
|
|
158
|
+
url_128x128?: string | undefined;
|
|
159
|
+
} | undefined;
|
|
160
|
+
popularity?: number | undefined;
|
|
161
|
+
has_filters?: boolean | undefined;
|
|
162
|
+
has_reads?: boolean | undefined;
|
|
163
|
+
has_searches?: boolean | undefined;
|
|
164
|
+
has_searches_or_writes?: boolean | undefined;
|
|
165
|
+
has_upfront_fields?: boolean | undefined;
|
|
166
|
+
has_writes?: boolean | undefined;
|
|
167
|
+
is_built_in?: boolean | undefined;
|
|
168
|
+
is_featured?: boolean | undefined;
|
|
169
|
+
is_invite?: boolean | undefined;
|
|
170
|
+
is_public?: boolean | undefined;
|
|
171
|
+
is_upcoming?: boolean | undefined;
|
|
172
|
+
visibility?: string | undefined;
|
|
173
|
+
primary_color?: string | undefined;
|
|
174
|
+
secondary_color?: string | undefined;
|
|
175
|
+
classification?: string | undefined;
|
|
176
|
+
api_docs_url?: string | undefined;
|
|
177
|
+
image?: string | undefined;
|
|
178
|
+
version?: string | undefined;
|
|
179
|
+
}>;
|
|
180
|
+
} & {
|
|
181
|
+
context: {
|
|
182
|
+
meta: {
|
|
183
|
+
listApps: import("kitcore").PluginMeta<unknown>;
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
} & {
|
|
187
|
+
context: import("../eventEmission").EventEmissionContext;
|
|
188
|
+
} & {
|
|
189
|
+
context: {
|
|
190
|
+
meta: Record<string, import("kitcore").PluginMeta>;
|
|
191
|
+
};
|
|
192
|
+
}) => {
|
|
193
|
+
getConnectionStartUrl: (options?: {
|
|
194
|
+
app: string;
|
|
195
|
+
} | undefined) => Promise<{
|
|
196
|
+
data: GetConnectionStartUrlItem;
|
|
197
|
+
}>;
|
|
198
|
+
} & {
|
|
199
|
+
context: {
|
|
200
|
+
meta: {
|
|
201
|
+
getConnectionStartUrl: import("kitcore").PluginMeta<unknown>;
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
export type GetConnectionStartUrlPluginProvides = ReturnType<typeof getConnectionStartUrlPlugin>;
|
|
206
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/getConnectionStartUrl/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,WAAW,CAAC;AAoBnB,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAmDuhX,CAAC;;;;sBAAiX,CAAC;qBAAyB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cApCp7X,yBAAyB;;;;;;;;CA+BhD,CAAC;AAEF,MAAM,MAAM,mCAAmC,GAAG,UAAU,CAC1D,OAAO,2BAA2B,CACnC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { definePlugin, createPluginMethod } from "kitcore";
|
|
2
|
+
import { setMethodMetadata } from "../eventEmission/method-metadata";
|
|
3
|
+
import { appKeyResolver } from "../../resolvers";
|
|
4
|
+
import { GetConnectionStartUrlSchema, GetConnectionStartUrlItemSchema, } from "./schemas";
|
|
5
|
+
// Server endpoint that mints a signed, single-use connection start URL.
|
|
6
|
+
const START_PATH = "/zapier/api/authentications/v1/sdk/connections/start";
|
|
7
|
+
export const getConnectionStartUrlPlugin = definePlugin((sdk) => createPluginMethod(sdk, {
|
|
8
|
+
name: "getConnectionStartUrl",
|
|
9
|
+
categories: ["connection"],
|
|
10
|
+
type: "create",
|
|
11
|
+
itemType: "ConnectionStartUrl",
|
|
12
|
+
inputSchema: GetConnectionStartUrlSchema,
|
|
13
|
+
outputSchema: GetConnectionStartUrlItemSchema,
|
|
14
|
+
resolvers: { app: appKeyResolver },
|
|
15
|
+
handler: async ({ sdk: inner, options, }) => {
|
|
16
|
+
// Send the versionless app key: the server resolves it to the freshest
|
|
17
|
+
// production version when the user opens the URL, which can be minutes
|
|
18
|
+
// after this call.
|
|
19
|
+
const versionedKey = await inner.context.getVersionedImplementationId(options.app);
|
|
20
|
+
const selectedApi = versionedKey
|
|
21
|
+
? versionedKey.split("@")[0]
|
|
22
|
+
: options.app;
|
|
23
|
+
// Tag this method's scope so eventEmission's onMethodEnd hook
|
|
24
|
+
// emits the MethodCalled event with `selected_api` set.
|
|
25
|
+
setMethodMetadata({ selectedApi });
|
|
26
|
+
const response = await inner.context.api.post(START_PATH, { selected_api: selectedApi }, { authRequired: true });
|
|
27
|
+
// Parse the mapped shape against the output schema so a server-side
|
|
28
|
+
// response change surfaces as a validation error here rather than
|
|
29
|
+
// silently producing a malformed item.
|
|
30
|
+
return {
|
|
31
|
+
data: GetConnectionStartUrlItemSchema.parse({
|
|
32
|
+
url: response.url,
|
|
33
|
+
expiresAt: response.expires_at,
|
|
34
|
+
startedAt: response.started_at,
|
|
35
|
+
app: selectedApi,
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
}));
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const GetConnectionStartUrlSchema: z.ZodObject<{
|
|
3
|
+
app: z.ZodString & {
|
|
4
|
+
_def: z.core.$ZodStringDef & import("kitcore").PositionalMetadata;
|
|
5
|
+
};
|
|
6
|
+
}, z.core.$strip>;
|
|
7
|
+
export type GetConnectionStartUrlOptions = z.infer<typeof GetConnectionStartUrlSchema>;
|
|
8
|
+
export declare const GetConnectionStartUrlItemSchema: z.ZodObject<{
|
|
9
|
+
url: z.ZodString;
|
|
10
|
+
expiresAt: z.ZodNumber;
|
|
11
|
+
startedAt: z.ZodNumber;
|
|
12
|
+
app: z.ZodString;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
export type GetConnectionStartUrlItem = z.infer<typeof GetConnectionStartUrlItemSchema>;
|
|
15
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/plugins/getConnectionStartUrl/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,2BAA2B;;;;iBAMrC,CAAC;AAEJ,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAChD,OAAO,2BAA2B,CACnC,CAAC;AAEF,eAAO,MAAM,+BAA+B;;;;;iBAyBzC,CAAC;AAEJ,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAC7C,OAAO,+BAA+B,CACvC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AppPropertySchema } from "../../types/properties";
|
|
3
|
+
export const GetConnectionStartUrlSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
app: AppPropertySchema,
|
|
6
|
+
})
|
|
7
|
+
.describe("Mint a short-lived URL that begins an SDK-initiated connection flow. The URL is signed by zapier.com and bound to the current user/account — opening it in a different browser session will fail the binding check. Returns the URL as data so the caller decides what to do with it.\n\nUse this directly (rather than the higher-level `create-connection`) when you want either of: (a) hand off the URL and *not* block waiting for completion — call this alone, skip `wait-for-new-connection` entirely, or (b) do something custom between minting the URL and waiting for the connection — call this, then email or DM the URL, render it as a QR code for mobile sign-in, etc., then call `wait-for-new-connection`. For the common case where you'd just print and poll back-to-back, `create-connection` is one call.\n\nPair with `wait-for-new-connection` to detect completion: pass the `startedAt` returned here straight through (it's the server's mint time, so polling isn't affected by client clock skew). Example (JS):\n\n```ts\nconst { data: { url, app, startedAt } } = await zapier.getConnectionStartUrl({ app: 'slack' });\n// hand `url` off — print it, DM it, email it, render a button, whatever\nconst { data: conn } = await zapier.waitForNewConnection({ app, startedAt });\n```");
|
|
8
|
+
export const GetConnectionStartUrlItemSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
url: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe("URL the user should open in their browser to complete the auth flow. Single-use, time-limited."),
|
|
13
|
+
expiresAt: z
|
|
14
|
+
.number()
|
|
15
|
+
.describe("Unix timestamp (seconds) after which the URL's signature is rejected by zapier.com."),
|
|
16
|
+
startedAt: z
|
|
17
|
+
.number()
|
|
18
|
+
.describe("Unix timestamp (seconds) when the server minted the URL. Use it as the `startedAt` for `wait-for-new-connection` so polling is anchored to server time rather than a possibly-skewed client clock."),
|
|
19
|
+
app: z
|
|
20
|
+
.string()
|
|
21
|
+
.describe("Versionless app key the URL was minted for (e.g., 'SlackCLIAPI'). Useful for downstream filtering."),
|
|
22
|
+
})
|
|
23
|
+
.describe("The signed start-URL plus metadata needed to poll for completion.");
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { type WaitForNewConnectionItem } from "./schemas";
|
|
2
|
+
export declare const waitForNewConnectionPlugin: (sdk: {
|
|
3
|
+
context: {
|
|
4
|
+
api: import("../..").ApiClient;
|
|
5
|
+
resolveCredentials: () => Promise<string | {
|
|
6
|
+
clientId: string;
|
|
7
|
+
clientSecret: string;
|
|
8
|
+
type?: "client_credentials" | undefined;
|
|
9
|
+
baseUrl?: string | undefined;
|
|
10
|
+
scope?: string | undefined;
|
|
11
|
+
} | {
|
|
12
|
+
clientId: string;
|
|
13
|
+
type?: "pkce" | undefined;
|
|
14
|
+
baseUrl?: string | undefined;
|
|
15
|
+
scope?: string | undefined;
|
|
16
|
+
} | undefined>;
|
|
17
|
+
};
|
|
18
|
+
} & {
|
|
19
|
+
context: {
|
|
20
|
+
getResolvedManifest: () => Promise<import("../manifest").Manifest | null>;
|
|
21
|
+
getVersionedImplementationId: (appKey: string) => Promise<string | null>;
|
|
22
|
+
resolveAppKeys: ({ appKeys }: {
|
|
23
|
+
appKeys: string[];
|
|
24
|
+
}) => Promise<import("../..").ResolvedAppLocator[]>;
|
|
25
|
+
updateManifestEntry: (options: import("../manifest").UpdateManifestEntryOptions) => Promise<import("../manifest").UpdateManifestEntryResult>;
|
|
26
|
+
addActionEntry: (options: import("../manifest").AddActionEntryOptions) => Promise<import("../manifest").AddActionEntryResult>;
|
|
27
|
+
findActionEntry: ({ name, manifest, }: {
|
|
28
|
+
name: string;
|
|
29
|
+
manifest: import("../manifest").Manifest;
|
|
30
|
+
}) => import("../manifest").ActionEntry | null;
|
|
31
|
+
listActionEntries: ({ configPath, }?: {
|
|
32
|
+
configPath?: string;
|
|
33
|
+
}) => Promise<Array<[string, import("../manifest").ActionEntry]>>;
|
|
34
|
+
deleteActionEntry: ({ name, configPath, skipWrite, }: {
|
|
35
|
+
name: string;
|
|
36
|
+
configPath?: string;
|
|
37
|
+
skipWrite?: boolean;
|
|
38
|
+
}) => Promise<import("../manifest").Manifest>;
|
|
39
|
+
hasActionEntry: ({ name, manifest, }: {
|
|
40
|
+
name: string;
|
|
41
|
+
manifest: import("../manifest").Manifest;
|
|
42
|
+
}) => boolean;
|
|
43
|
+
findManifestEntry: typeof import("../manifest").findManifestEntry;
|
|
44
|
+
readManifestFromFile: typeof import("../manifest").readManifestFromFile;
|
|
45
|
+
getManifestConnections: () => Promise<Record<string, {
|
|
46
|
+
connectionId: string | number;
|
|
47
|
+
}> | null>;
|
|
48
|
+
};
|
|
49
|
+
} & {
|
|
50
|
+
getApp: (options?: {
|
|
51
|
+
app: string;
|
|
52
|
+
} | {
|
|
53
|
+
appKey: string;
|
|
54
|
+
} | undefined) => Promise<{
|
|
55
|
+
data: {
|
|
56
|
+
slug: string;
|
|
57
|
+
title: string;
|
|
58
|
+
key: string;
|
|
59
|
+
implementation_id: string;
|
|
60
|
+
description?: string | undefined;
|
|
61
|
+
is_hidden?: boolean | undefined;
|
|
62
|
+
auth_type?: string | undefined;
|
|
63
|
+
actions?: {
|
|
64
|
+
read?: number | undefined;
|
|
65
|
+
read_bulk?: number | undefined;
|
|
66
|
+
write?: number | undefined;
|
|
67
|
+
search?: number | undefined;
|
|
68
|
+
search_or_write?: number | undefined;
|
|
69
|
+
search_and_write?: number | undefined;
|
|
70
|
+
filter?: number | undefined;
|
|
71
|
+
} | undefined;
|
|
72
|
+
is_deprecated?: boolean | undefined;
|
|
73
|
+
is_beta?: boolean | undefined;
|
|
74
|
+
is_premium?: boolean | undefined;
|
|
75
|
+
age_in_days?: number | undefined;
|
|
76
|
+
banner?: string | undefined;
|
|
77
|
+
categories?: {
|
|
78
|
+
id: number;
|
|
79
|
+
name: string;
|
|
80
|
+
slug: string;
|
|
81
|
+
}[] | undefined;
|
|
82
|
+
images?: {
|
|
83
|
+
url_16x16?: string | undefined;
|
|
84
|
+
url_32x32?: string | undefined;
|
|
85
|
+
url_64x64?: string | undefined;
|
|
86
|
+
url_128x128?: string | undefined;
|
|
87
|
+
} | undefined;
|
|
88
|
+
popularity?: number | undefined;
|
|
89
|
+
has_filters?: boolean | undefined;
|
|
90
|
+
has_reads?: boolean | undefined;
|
|
91
|
+
has_searches?: boolean | undefined;
|
|
92
|
+
has_searches_or_writes?: boolean | undefined;
|
|
93
|
+
has_upfront_fields?: boolean | undefined;
|
|
94
|
+
has_writes?: boolean | undefined;
|
|
95
|
+
is_built_in?: boolean | undefined;
|
|
96
|
+
is_featured?: boolean | undefined;
|
|
97
|
+
is_invite?: boolean | undefined;
|
|
98
|
+
is_public?: boolean | undefined;
|
|
99
|
+
is_upcoming?: boolean | undefined;
|
|
100
|
+
visibility?: string | undefined;
|
|
101
|
+
primary_color?: string | undefined;
|
|
102
|
+
secondary_color?: string | undefined;
|
|
103
|
+
classification?: string | undefined;
|
|
104
|
+
api_docs_url?: string | undefined;
|
|
105
|
+
image?: string | undefined;
|
|
106
|
+
version?: string | undefined;
|
|
107
|
+
};
|
|
108
|
+
}>;
|
|
109
|
+
} & {
|
|
110
|
+
context: {
|
|
111
|
+
meta: {
|
|
112
|
+
getApp: import("kitcore").PluginMeta<unknown>;
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
} & {
|
|
116
|
+
listApps: (options?: ({
|
|
117
|
+
search?: string | undefined;
|
|
118
|
+
apps?: string[] | undefined;
|
|
119
|
+
appKeys?: string[] | undefined;
|
|
120
|
+
pageSize?: number | undefined;
|
|
121
|
+
maxItems?: number | undefined;
|
|
122
|
+
cursor?: string | undefined;
|
|
123
|
+
} & {
|
|
124
|
+
cursor?: string;
|
|
125
|
+
pageSize?: number;
|
|
126
|
+
maxItems?: number;
|
|
127
|
+
}) | undefined) => import("kitcore").PaginatedSdkResult<{
|
|
128
|
+
slug: string;
|
|
129
|
+
title: string;
|
|
130
|
+
key: string;
|
|
131
|
+
implementation_id: string;
|
|
132
|
+
description?: string | undefined;
|
|
133
|
+
is_hidden?: boolean | undefined;
|
|
134
|
+
auth_type?: string | undefined;
|
|
135
|
+
actions?: {
|
|
136
|
+
read?: number | undefined;
|
|
137
|
+
read_bulk?: number | undefined;
|
|
138
|
+
write?: number | undefined;
|
|
139
|
+
search?: number | undefined;
|
|
140
|
+
search_or_write?: number | undefined;
|
|
141
|
+
search_and_write?: number | undefined;
|
|
142
|
+
filter?: number | undefined;
|
|
143
|
+
} | undefined;
|
|
144
|
+
is_deprecated?: boolean | undefined;
|
|
145
|
+
is_beta?: boolean | undefined;
|
|
146
|
+
is_premium?: boolean | undefined;
|
|
147
|
+
age_in_days?: number | undefined;
|
|
148
|
+
banner?: string | undefined;
|
|
149
|
+
categories?: {
|
|
150
|
+
id: number;
|
|
151
|
+
name: string;
|
|
152
|
+
slug: string;
|
|
153
|
+
}[] | undefined;
|
|
154
|
+
images?: {
|
|
155
|
+
url_16x16?: string | undefined;
|
|
156
|
+
url_32x32?: string | undefined;
|
|
157
|
+
url_64x64?: string | undefined;
|
|
158
|
+
url_128x128?: string | undefined;
|
|
159
|
+
} | undefined;
|
|
160
|
+
popularity?: number | undefined;
|
|
161
|
+
has_filters?: boolean | undefined;
|
|
162
|
+
has_reads?: boolean | undefined;
|
|
163
|
+
has_searches?: boolean | undefined;
|
|
164
|
+
has_searches_or_writes?: boolean | undefined;
|
|
165
|
+
has_upfront_fields?: boolean | undefined;
|
|
166
|
+
has_writes?: boolean | undefined;
|
|
167
|
+
is_built_in?: boolean | undefined;
|
|
168
|
+
is_featured?: boolean | undefined;
|
|
169
|
+
is_invite?: boolean | undefined;
|
|
170
|
+
is_public?: boolean | undefined;
|
|
171
|
+
is_upcoming?: boolean | undefined;
|
|
172
|
+
visibility?: string | undefined;
|
|
173
|
+
primary_color?: string | undefined;
|
|
174
|
+
secondary_color?: string | undefined;
|
|
175
|
+
classification?: string | undefined;
|
|
176
|
+
api_docs_url?: string | undefined;
|
|
177
|
+
image?: string | undefined;
|
|
178
|
+
version?: string | undefined;
|
|
179
|
+
}>;
|
|
180
|
+
} & {
|
|
181
|
+
context: {
|
|
182
|
+
meta: {
|
|
183
|
+
listApps: import("kitcore").PluginMeta<unknown>;
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
} & {
|
|
187
|
+
context: import("../eventEmission").EventEmissionContext;
|
|
188
|
+
} & {
|
|
189
|
+
context: {
|
|
190
|
+
meta: Record<string, import("kitcore").PluginMeta>;
|
|
191
|
+
};
|
|
192
|
+
}) => {
|
|
193
|
+
waitForNewConnection: (options?: {
|
|
194
|
+
app: string;
|
|
195
|
+
startedAt: number;
|
|
196
|
+
timeoutMs?: number | undefined;
|
|
197
|
+
pollIntervalMs?: number | undefined;
|
|
198
|
+
} | undefined) => Promise<{
|
|
199
|
+
data: WaitForNewConnectionItem;
|
|
200
|
+
}>;
|
|
201
|
+
} & {
|
|
202
|
+
context: {
|
|
203
|
+
meta: {
|
|
204
|
+
waitForNewConnection: import("kitcore").PluginMeta<unknown>;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
export type WaitForNewConnectionPluginProvides = ReturnType<typeof waitForNewConnectionPlugin>;
|
|
209
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/waitForNewConnection/index.ts"],"names":[],"mappings":"AASA,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,WAAW,CAAC;AAuBnB,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAwFuwT,CAAC;;;;sBAAiX,CAAC;qBAAyB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAzEnqU,wBAAwB;;;;;;;;CAoE/C,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG,UAAU,CACzD,OAAO,0BAA0B,CAClC,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { definePlugin, createPluginMethod } from "kitcore";
|
|
2
|
+
import { setMethodMetadata } from "../eventEmission/method-metadata";
|
|
3
|
+
import { appKeyResolver } from "../../resolvers";
|
|
4
|
+
import { ZapierTimeoutError } from "../../types/errors";
|
|
5
|
+
import { WaitForNewConnectionSchema, WaitForNewConnectionItemSchema, } from "./schemas";
|
|
6
|
+
const CONNECTIONS_PATH = "/api/v0/connections";
|
|
7
|
+
export const waitForNewConnectionPlugin = definePlugin((sdk) => createPluginMethod(sdk, {
|
|
8
|
+
name: "waitForNewConnection",
|
|
9
|
+
categories: ["connection"],
|
|
10
|
+
type: "item",
|
|
11
|
+
itemType: "Connection",
|
|
12
|
+
inputSchema: WaitForNewConnectionSchema,
|
|
13
|
+
outputSchema: WaitForNewConnectionItemSchema,
|
|
14
|
+
resolvers: { app: appKeyResolver },
|
|
15
|
+
handler: async ({ sdk: inner, options, }) => {
|
|
16
|
+
// Resolve slug → versionless app key so the `app_key` filter matches
|
|
17
|
+
// what the API stores on connection rows.
|
|
18
|
+
const versionedKey = await inner.context.getVersionedImplementationId(options.app);
|
|
19
|
+
const appKey = versionedKey ? versionedKey.split("@")[0] : options.app;
|
|
20
|
+
// Tag this method's scope so eventEmission's onMethodEnd hook
|
|
21
|
+
// emits the MethodCalled event with `selected_api` set.
|
|
22
|
+
setMethodMetadata({ selectedApi: appKey });
|
|
23
|
+
// Server-side sort newest-first + `page_size=1` lets us poll a one-row
|
|
24
|
+
// response and just check the head: if the most recently created
|
|
25
|
+
// `appKey` connection is fresh (`date >= startedAt`), it's ours by
|
|
26
|
+
// construction. No pagination concerns; no client-side disambiguation
|
|
27
|
+
// among fresh rows. Delegating the poll loop to `api.poll` also gets
|
|
28
|
+
// us backoff, timeout enforcement, and consistent `ZapierTimeoutError`
|
|
29
|
+
// behavior for free.
|
|
30
|
+
try {
|
|
31
|
+
const top = await inner.context.api.poll(CONNECTIONS_PATH, {
|
|
32
|
+
searchParams: {
|
|
33
|
+
app_key: appKey,
|
|
34
|
+
// Scope to the current user's own connections. The connection
|
|
35
|
+
// we're waiting on is by definition owned by the caller; without
|
|
36
|
+
// this the one-row head-check could match a teammate's freshly
|
|
37
|
+
// created connection for the same app.
|
|
38
|
+
owner: "me",
|
|
39
|
+
is_expired: "false",
|
|
40
|
+
ordering: "-date",
|
|
41
|
+
page_size: "1",
|
|
42
|
+
},
|
|
43
|
+
authRequired: true,
|
|
44
|
+
timeoutMs: options.timeoutMs ?? 300000,
|
|
45
|
+
initialDelay: options.pollIntervalMs ?? 3000,
|
|
46
|
+
isPending: (body) => {
|
|
47
|
+
const rows = body.data ?? [];
|
|
48
|
+
const head = rows[0];
|
|
49
|
+
if (!head?.date)
|
|
50
|
+
return true;
|
|
51
|
+
const created = Math.floor(new Date(head.date).getTime() / 1000);
|
|
52
|
+
return !Number.isFinite(created) || created < options.startedAt;
|
|
53
|
+
},
|
|
54
|
+
resultExtractor: (body) =>
|
|
55
|
+
// `isPending` guaranteed a fresh row at index 0 before this fires.
|
|
56
|
+
body.data[0],
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
data: WaitForNewConnectionItemSchema.parse({
|
|
60
|
+
id: String(top.public_id ?? top.id),
|
|
61
|
+
app: appKey,
|
|
62
|
+
title: top.title ?? null,
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
// Wrap api.poll's generic timeout with an actionable next step.
|
|
68
|
+
if (err instanceof ZapierTimeoutError) {
|
|
69
|
+
throw new ZapierTimeoutError(`Timed out waiting for a new "${appKey}" connection. ` +
|
|
70
|
+
`If the user completed the auth flow, retrieve the connection via sdk.getConnection({ id }) with the ID shown on the completion page.`);
|
|
71
|
+
}
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const WaitForNewConnectionSchema: z.ZodObject<{
|
|
3
|
+
app: z.ZodString & {
|
|
4
|
+
_def: z.core.$ZodStringDef & import("kitcore").PositionalMetadata;
|
|
5
|
+
};
|
|
6
|
+
startedAt: z.ZodNumber;
|
|
7
|
+
timeoutMs: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
pollIntervalMs: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export type WaitForNewConnectionOptions = z.infer<typeof WaitForNewConnectionSchema>;
|
|
11
|
+
export declare const WaitForNewConnectionItemSchema: z.ZodObject<{
|
|
12
|
+
id: z.ZodString;
|
|
13
|
+
app: z.ZodString;
|
|
14
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export type WaitForNewConnectionItem = z.infer<typeof WaitForNewConnectionItemSchema>;
|
|
17
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/plugins/waitForNewConnection/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,0BAA0B;;;;;;;iBA6BpC,CAAC;AAEJ,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,0BAA0B,CAClC,CAAC;AAEF,eAAO,MAAM,8BAA8B;;;;iBAoBS,CAAC;AAErD,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AppPropertySchema } from "../../types/properties";
|
|
3
|
+
export const WaitForNewConnectionSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
app: AppPropertySchema,
|
|
6
|
+
startedAt: z
|
|
7
|
+
.number()
|
|
8
|
+
.int()
|
|
9
|
+
.nonnegative()
|
|
10
|
+
.describe("Unix timestamp (seconds). Only connections whose `date` is at or after this value count as 'new'. Prefer the `startedAt` returned by `get-connection-start-url` — it's server-stamped, so the comparison isn't thrown off by client clock skew. If you mint the timestamp yourself, capture it *before* showing the start URL so a fast OAuth completion isn't missed."),
|
|
11
|
+
timeoutMs: z
|
|
12
|
+
.number()
|
|
13
|
+
.int()
|
|
14
|
+
.positive()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("How long to wait before giving up. Default 5 minutes (300_000)."),
|
|
17
|
+
pollIntervalMs: z
|
|
18
|
+
.number()
|
|
19
|
+
.int()
|
|
20
|
+
.positive()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Delay before the first poll request, in ms. Default 3 seconds (3_000). Subsequent polling cadence is managed by the SDK's polling primitive (backoff with sane defaults)."),
|
|
23
|
+
})
|
|
24
|
+
.describe("Wait for a new connection to appear for the given app. Polls `/api/v0/connections` with server-side `ordering=-date` until the most recent matching row's `date` is at or after the started-at timestamp, then returns it. Pair with `get-connection-start-url` — that mints the URL the user opens, this waits for the resulting connection to land. Errors with a timeout after the configured timeout (default 5 min). Example (JS):\n\n```ts\nconst { data: { url, app, startedAt } } = await zapier.getConnectionStartUrl({ app: 'slack' });\n// show `url` to the user via the channel they're reading from\nconst { data: conn } = await zapier.waitForNewConnection({ app, startedAt });\n```");
|
|
25
|
+
export const WaitForNewConnectionItemSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
id: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe("The new connection's ID. Public UUID when available, falling back to the numeric ID."),
|
|
30
|
+
app: z
|
|
31
|
+
.string()
|
|
32
|
+
.describe("Versionless app key the connection was created for (e.g., 'SlackCLIAPI')."),
|
|
33
|
+
title: z
|
|
34
|
+
.string()
|
|
35
|
+
.nullable()
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("Human-readable connection title set by the auth flow, when available."),
|
|
38
|
+
})
|
|
39
|
+
.describe("The new connection that was detected.");
|