@zapier/zapier-sdk-cli 0.42.2 → 0.43.1
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 +21 -0
- package/dist/cli.cjs +1047 -547
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.mjs +1034 -537
- package/dist/index.cjs +1037 -538
- package/dist/index.d.mts +395 -23
- package/dist/index.d.ts +395 -23
- package/dist/index.mjs +1027 -531
- package/dist/login.cjs +599 -7
- package/dist/login.d.mts +144 -1
- package/dist/login.d.ts +144 -1
- package/dist/login.mjs +565 -1
- package/dist/package.json +5 -2
- package/dist/src/login/filesystem-cache.d.ts +25 -0
- package/dist/src/login/filesystem-cache.js +195 -0
- package/dist/src/login/index.d.ts +115 -0
- package/dist/src/login/index.js +442 -0
- package/dist/src/login/keychain.d.ts +18 -0
- package/dist/src/login/keychain.js +74 -0
- package/dist/src/login.d.ts +10 -1
- package/dist/src/login.js +10 -1
- package/dist/src/plugins/add/index.d.ts +250 -11
- package/dist/src/plugins/add/index.js +8 -16
- package/dist/src/plugins/buildManifest/index.d.ts +116 -9
- package/dist/src/plugins/buildManifest/index.js +14 -23
- package/dist/src/plugins/bundleCode/index.d.ts +19 -10
- package/dist/src/plugins/bundleCode/index.js +7 -17
- package/dist/src/plugins/cliOverrides/index.d.ts +12 -10
- package/dist/src/plugins/cliOverrides/index.js +16 -20
- package/dist/src/plugins/curl/index.d.ts +69 -10
- package/dist/src/plugins/curl/index.js +3 -2
- package/dist/src/plugins/feedback/index.d.ts +18 -13
- package/dist/src/plugins/feedback/index.js +18 -26
- package/dist/src/plugins/generateAppTypes/index.d.ts +261 -9
- package/dist/src/plugins/generateAppTypes/index.js +17 -45
- package/dist/src/plugins/getLoginConfigPath/index.d.ts +12 -10
- package/dist/src/plugins/getLoginConfigPath/index.js +9 -19
- package/dist/src/plugins/init/index.d.ts +15 -11
- package/dist/src/plugins/init/index.js +9 -17
- package/dist/src/plugins/login/index.d.ts +18 -13
- package/dist/src/plugins/login/index.js +10 -18
- package/dist/src/plugins/logout/index.d.ts +12 -11
- package/dist/src/plugins/logout/index.js +11 -17
- package/dist/src/plugins/mcp/index.d.ts +18 -15
- package/dist/src/plugins/mcp/index.js +9 -21
- package/dist/src/sdk.js +1 -1
- package/dist/src/utils/auth/login.d.ts +1 -1
- package/dist/src/utils/auth/login.js +1 -1
- package/dist/src/utils/constants.d.ts +1 -1
- package/dist/src/utils/constants.js +1 -1
- package/dist/src/utils/version-checker.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -4
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
1
|
+
import Conf from 'conf';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { promises, createWriteStream, existsSync, readdirSync, rmSync, mkdirSync, writeFileSync, copyFileSync, readFileSync } from 'fs';
|
|
4
|
+
import * as jwt from 'jsonwebtoken';
|
|
5
|
+
import { getPassword, getKeyring, setPassword, deletePassword } from 'cross-keychain';
|
|
5
6
|
import crypto, { createHash } from 'crypto';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { resolve, join, dirname, basename, relative, extname } from 'path';
|
|
9
|
+
import * as lockfile from 'proper-lockfile';
|
|
10
|
+
import { definePlugin, createPluginMethod, buildApplicationLifecycleEvent, OutputPropertySchema, DEFAULT_CONFIG_PATH, ZapierValidationError, ZapierUnknownError, injectCliLogin, isCredentialsObject, batch, toSnakeCase, ZapierError, createZapierSdk, getOsInfo, getPlatformVersions, getCiPlatform, isCi, getReleaseId, getCurrentTimestamp, generateEventId } from '@zapier/zapier-sdk';
|
|
11
|
+
import open from 'open';
|
|
6
12
|
import express from 'express';
|
|
7
13
|
import pkceChallenge from 'pkce-challenge';
|
|
8
14
|
import ora from 'ora';
|
|
@@ -11,10 +17,6 @@ import inquirer from 'inquirer';
|
|
|
11
17
|
import { z } from 'zod';
|
|
12
18
|
import { startMcpServer } from '@zapier/zapier-sdk-mcp';
|
|
13
19
|
import { buildSync } from 'esbuild';
|
|
14
|
-
import * as fs from 'fs';
|
|
15
|
-
import { promises, createWriteStream, existsSync, readdirSync, rmSync, mkdirSync, writeFileSync, copyFileSync, readFileSync } from 'fs';
|
|
16
|
-
import * as path from 'path';
|
|
17
|
-
import { resolve, join, dirname, basename, relative, extname } from 'path';
|
|
18
20
|
import { mkdir, writeFile, access } from 'fs/promises';
|
|
19
21
|
import * as ts from 'typescript';
|
|
20
22
|
import 'is-installed-globally';
|
|
@@ -22,7 +24,586 @@ import { execSync } from 'child_process';
|
|
|
22
24
|
import Handlebars from 'handlebars';
|
|
23
25
|
import { fileURLToPath } from 'url';
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
var __defProp = Object.defineProperty;
|
|
28
|
+
var __export = (target, all) => {
|
|
29
|
+
for (var name in all)
|
|
30
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/login.ts
|
|
34
|
+
var login_exports = {};
|
|
35
|
+
__export(login_exports, {
|
|
36
|
+
AUTH_MODE_HEADER: () => AUTH_MODE_HEADER,
|
|
37
|
+
ZapierAuthenticationError: () => ZapierAuthenticationError,
|
|
38
|
+
createCache: () => createCache,
|
|
39
|
+
getAuthAuthorizeUrl: () => getAuthAuthorizeUrl,
|
|
40
|
+
getAuthTokenUrl: () => getAuthTokenUrl,
|
|
41
|
+
getConfig: () => getConfig,
|
|
42
|
+
getConfigPath: () => getConfigPath,
|
|
43
|
+
getLoggedInUser: () => getLoggedInUser,
|
|
44
|
+
getLoginStorageMode: () => getLoginStorageMode,
|
|
45
|
+
getPkceLoginConfig: () => getPkceLoginConfig,
|
|
46
|
+
getToken: () => getToken,
|
|
47
|
+
logout: () => logout,
|
|
48
|
+
unloadConfig: () => unloadConfig,
|
|
49
|
+
updateLogin: () => updateLogin
|
|
50
|
+
});
|
|
51
|
+
var SERVICE = "zapier-sdk-cli";
|
|
52
|
+
var ACCOUNT = "login";
|
|
53
|
+
var cachedBackendInfo;
|
|
54
|
+
async function getBackendInfo() {
|
|
55
|
+
if (!cachedBackendInfo) {
|
|
56
|
+
const keyring = await getKeyring();
|
|
57
|
+
cachedBackendInfo = `${keyring.name} (${keyring.id})`;
|
|
58
|
+
}
|
|
59
|
+
return cachedBackendInfo;
|
|
60
|
+
}
|
|
61
|
+
var keychainQueue = Promise.resolve();
|
|
62
|
+
function enqueue(fn) {
|
|
63
|
+
const result = keychainQueue.then(fn, fn);
|
|
64
|
+
keychainQueue = result.then(
|
|
65
|
+
() => {
|
|
66
|
+
},
|
|
67
|
+
() => {
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
async function getTokensFromKeychain({
|
|
73
|
+
debugLog
|
|
74
|
+
} = {}) {
|
|
75
|
+
return enqueue(async () => {
|
|
76
|
+
const backendInfo = await getBackendInfo();
|
|
77
|
+
debugLog?.(`Keychain read via ${backendInfo}`);
|
|
78
|
+
const startTime = Date.now();
|
|
79
|
+
const raw = await getPassword(SERVICE, ACCOUNT);
|
|
80
|
+
debugLog?.(`Keychain read completed in ${Date.now() - startTime}ms`);
|
|
81
|
+
if (!raw) {
|
|
82
|
+
debugLog?.("Keychain returned no data");
|
|
83
|
+
return void 0;
|
|
84
|
+
}
|
|
85
|
+
let parsed;
|
|
86
|
+
try {
|
|
87
|
+
parsed = JSON.parse(raw);
|
|
88
|
+
} catch {
|
|
89
|
+
debugLog?.("Keychain data is not valid JSON");
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
92
|
+
if (typeof parsed.login_jwt === "string" && typeof parsed.login_refresh_token === "string") {
|
|
93
|
+
return {
|
|
94
|
+
login_jwt: parsed.login_jwt,
|
|
95
|
+
login_refresh_token: parsed.login_refresh_token
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
debugLog?.("Keychain data has invalid shape", parsed);
|
|
99
|
+
return void 0;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async function setTokensInKeychain({
|
|
103
|
+
data,
|
|
104
|
+
debugLog
|
|
105
|
+
}) {
|
|
106
|
+
return enqueue(async () => {
|
|
107
|
+
const backendInfo = await getBackendInfo();
|
|
108
|
+
debugLog?.(`Keychain write via ${backendInfo}`);
|
|
109
|
+
const startTime = Date.now();
|
|
110
|
+
await setPassword(SERVICE, ACCOUNT, JSON.stringify(data));
|
|
111
|
+
debugLog?.(`Keychain write completed in ${Date.now() - startTime}ms`);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
async function clearTokensFromKeychain({
|
|
115
|
+
debugLog
|
|
116
|
+
} = {}) {
|
|
117
|
+
return enqueue(async () => {
|
|
118
|
+
try {
|
|
119
|
+
const backendInfo = await getBackendInfo();
|
|
120
|
+
debugLog?.(`Keychain clear via ${backendInfo}`);
|
|
121
|
+
await deletePassword(SERVICE, ACCOUNT);
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
var SERVICE2 = "zapier-sdk-cache";
|
|
127
|
+
var CONFIG_KEY = "cache";
|
|
128
|
+
var LOCK_UPDATE_MS = 5e3;
|
|
129
|
+
var LOCK_STALE_MS = 1e4;
|
|
130
|
+
var LOCK_RETRY_WAIT_MS = 100;
|
|
131
|
+
var LOCK_RETRY_MAX_WAIT_MS = 1e3;
|
|
132
|
+
var LOCK_RETRY_COUNT = 120;
|
|
133
|
+
function keychainAccount(key) {
|
|
134
|
+
return createHash("sha256").update(key).digest("hex");
|
|
135
|
+
}
|
|
136
|
+
function readConfigMap() {
|
|
137
|
+
const cfg = getConfig();
|
|
138
|
+
const stored = cfg.get(CONFIG_KEY);
|
|
139
|
+
if (stored && typeof stored === "object") {
|
|
140
|
+
return stored;
|
|
141
|
+
}
|
|
142
|
+
return {};
|
|
143
|
+
}
|
|
144
|
+
function writeConfigMap(map) {
|
|
145
|
+
getConfig().set(CONFIG_KEY, map);
|
|
146
|
+
}
|
|
147
|
+
function entryIsExpired(entry) {
|
|
148
|
+
return entry.expires_at !== void 0 && entry.expires_at <= Date.now();
|
|
149
|
+
}
|
|
150
|
+
function createCache() {
|
|
151
|
+
return {
|
|
152
|
+
async get(key) {
|
|
153
|
+
const entry = readConfigMap()[key];
|
|
154
|
+
if (!entry) return void 0;
|
|
155
|
+
if (entryIsExpired(entry)) return void 0;
|
|
156
|
+
if (entry.secret) {
|
|
157
|
+
const stored = await enqueue(async () => {
|
|
158
|
+
await getBackendInfo();
|
|
159
|
+
return getPassword(SERVICE2, keychainAccount(key));
|
|
160
|
+
});
|
|
161
|
+
if (!stored) {
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
return { value: stored, expiresAt: entry.expires_at };
|
|
165
|
+
}
|
|
166
|
+
if (entry.value === void 0) return void 0;
|
|
167
|
+
return { value: entry.value, expiresAt: entry.expires_at };
|
|
168
|
+
},
|
|
169
|
+
async set(key, value, options) {
|
|
170
|
+
const secret = options?.secret ?? false;
|
|
171
|
+
const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
|
|
172
|
+
if (secret) {
|
|
173
|
+
try {
|
|
174
|
+
await enqueue(async () => {
|
|
175
|
+
await getBackendInfo();
|
|
176
|
+
await setPassword(SERVICE2, keychainAccount(key), value);
|
|
177
|
+
});
|
|
178
|
+
} catch {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const map = readConfigMap();
|
|
182
|
+
map[key] = { secret: true, expires_at: expiresAt };
|
|
183
|
+
try {
|
|
184
|
+
writeConfigMap(map);
|
|
185
|
+
} catch {
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
const map = readConfigMap();
|
|
189
|
+
map[key] = { secret: false, value, expires_at: expiresAt };
|
|
190
|
+
try {
|
|
191
|
+
writeConfigMap(map);
|
|
192
|
+
} catch {
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
async delete(key) {
|
|
197
|
+
const map = readConfigMap();
|
|
198
|
+
const entry = map[key];
|
|
199
|
+
if (entry) {
|
|
200
|
+
delete map[key];
|
|
201
|
+
try {
|
|
202
|
+
writeConfigMap(map);
|
|
203
|
+
} catch {
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (entry?.secret) {
|
|
207
|
+
try {
|
|
208
|
+
await enqueue(async () => {
|
|
209
|
+
await getBackendInfo();
|
|
210
|
+
await deletePassword(SERVICE2, keychainAccount(key));
|
|
211
|
+
});
|
|
212
|
+
} catch {
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
async withLock(_key, fn) {
|
|
217
|
+
const cfg = getConfig();
|
|
218
|
+
const lockTarget = `${cfg.path}.cache-lock`;
|
|
219
|
+
try {
|
|
220
|
+
mkdirSync(dirname(lockTarget), { recursive: true });
|
|
221
|
+
if (!existsSync(lockTarget)) {
|
|
222
|
+
writeFileSync(lockTarget, "");
|
|
223
|
+
}
|
|
224
|
+
} catch {
|
|
225
|
+
return fn();
|
|
226
|
+
}
|
|
227
|
+
let release = null;
|
|
228
|
+
try {
|
|
229
|
+
release = await lockfile.lock(lockTarget, {
|
|
230
|
+
stale: LOCK_STALE_MS,
|
|
231
|
+
update: LOCK_UPDATE_MS,
|
|
232
|
+
retries: {
|
|
233
|
+
retries: LOCK_RETRY_COUNT,
|
|
234
|
+
factor: 1.2,
|
|
235
|
+
minTimeout: LOCK_RETRY_WAIT_MS,
|
|
236
|
+
maxTimeout: LOCK_RETRY_MAX_WAIT_MS
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
} catch {
|
|
240
|
+
return fn();
|
|
241
|
+
}
|
|
242
|
+
try {
|
|
243
|
+
return await fn();
|
|
244
|
+
} finally {
|
|
245
|
+
try {
|
|
246
|
+
await release();
|
|
247
|
+
} catch {
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// src/login/index.ts
|
|
255
|
+
var ZapierAuthenticationError = class extends Error {
|
|
256
|
+
constructor(message) {
|
|
257
|
+
super(message);
|
|
258
|
+
this.name = "ZapierAuthenticationError";
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
var config = null;
|
|
262
|
+
var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
|
|
263
|
+
var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
264
|
+
function createDebugLog(enabled) {
|
|
265
|
+
if (!enabled) {
|
|
266
|
+
return () => {
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return (message, data) => {
|
|
270
|
+
if (data === void 0) {
|
|
271
|
+
console.log(`[Zapier SDK CLI Login] ${message}`);
|
|
272
|
+
} else {
|
|
273
|
+
console.log(`[Zapier SDK CLI Login] ${message}`, data);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
function censorHeaderValue(value) {
|
|
278
|
+
if (value.length > 12) {
|
|
279
|
+
return `${value.substring(0, 4)}...${value.substring(value.length - 4)}`;
|
|
280
|
+
}
|
|
281
|
+
return `${value.charAt(0)}...`;
|
|
282
|
+
}
|
|
283
|
+
function getAuthClientId(clientId) {
|
|
284
|
+
return clientId || DEFAULT_AUTH_CLIENT_ID;
|
|
285
|
+
}
|
|
286
|
+
var AUTH_MODE_HEADER = "X-Auth";
|
|
287
|
+
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
288
|
+
function getAuthTokenUrl(options) {
|
|
289
|
+
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
290
|
+
return `${authBaseUrl}/oauth/token/`;
|
|
291
|
+
}
|
|
292
|
+
function getAuthAuthorizeUrl(options) {
|
|
293
|
+
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
294
|
+
return `${authBaseUrl}/oauth/authorize/`;
|
|
295
|
+
}
|
|
296
|
+
function getPkceLoginConfig(options) {
|
|
297
|
+
return {
|
|
298
|
+
clientId: getAuthClientId(options?.credentials?.clientId),
|
|
299
|
+
tokenUrl: getAuthTokenUrl({ baseUrl: options?.credentials?.baseUrl }),
|
|
300
|
+
authorizeUrl: getAuthAuthorizeUrl({
|
|
301
|
+
baseUrl: options?.credentials?.baseUrl
|
|
302
|
+
})
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
var cachedLogin;
|
|
306
|
+
function getConfig() {
|
|
307
|
+
if (!config) {
|
|
308
|
+
config = new Conf({ projectName: "zapier-sdk-cli" });
|
|
309
|
+
if (!config.has("login_storage_mode")) {
|
|
310
|
+
config.set(
|
|
311
|
+
"login_storage_mode",
|
|
312
|
+
existsSync(config.path) ? "config" : "keychain"
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return config;
|
|
317
|
+
}
|
|
318
|
+
function unloadConfig() {
|
|
319
|
+
config = null;
|
|
320
|
+
cachedLogin = void 0;
|
|
321
|
+
}
|
|
322
|
+
async function updateLogin(loginData, options = {}) {
|
|
323
|
+
const debugLog = createDebugLog(options.debug ?? false);
|
|
324
|
+
const storage = options.storage ?? cachedLogin?.storage ?? "keychain";
|
|
325
|
+
const expiresAt = Date.now() + loginData.expires_in * 1e3;
|
|
326
|
+
const cfg = getConfig();
|
|
327
|
+
cfg.set("login_storage_mode", storage);
|
|
328
|
+
if (storage === "keychain") {
|
|
329
|
+
await setTokensInKeychain({
|
|
330
|
+
data: {
|
|
331
|
+
login_jwt: loginData.access_token,
|
|
332
|
+
login_refresh_token: loginData.refresh_token
|
|
333
|
+
},
|
|
334
|
+
debugLog
|
|
335
|
+
});
|
|
336
|
+
cfg.set("login_expires_at", expiresAt);
|
|
337
|
+
cfg.delete("login_jwt");
|
|
338
|
+
cfg.delete("login_refresh_token");
|
|
339
|
+
} else {
|
|
340
|
+
cfg.set("login_jwt", loginData.access_token);
|
|
341
|
+
cfg.set("login_refresh_token", loginData.refresh_token);
|
|
342
|
+
cfg.set("login_expires_at", expiresAt);
|
|
343
|
+
await clearTokensFromKeychain({ debugLog });
|
|
344
|
+
}
|
|
345
|
+
cachedLogin = {
|
|
346
|
+
jwt: loginData.access_token,
|
|
347
|
+
refreshToken: loginData.refresh_token,
|
|
348
|
+
expiresAt,
|
|
349
|
+
storage
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function decodeJwtOrThrow(token) {
|
|
353
|
+
if (typeof token !== "string") {
|
|
354
|
+
throw new Error("Expected JWT to be a string");
|
|
355
|
+
}
|
|
356
|
+
const decodedJwt = jwt.decode(token, { complete: true });
|
|
357
|
+
if (!decodedJwt) {
|
|
358
|
+
throw new Error("Could not decode JWT");
|
|
359
|
+
}
|
|
360
|
+
if (typeof decodedJwt.payload === "string") {
|
|
361
|
+
throw new Error("Did not expect JWT payload to be a string");
|
|
362
|
+
}
|
|
363
|
+
return decodedJwt;
|
|
364
|
+
}
|
|
365
|
+
async function refreshJwt(refreshToken, options = {}) {
|
|
366
|
+
const {
|
|
367
|
+
onEvent,
|
|
368
|
+
fetch: fetch2 = globalThis.fetch,
|
|
369
|
+
credentials,
|
|
370
|
+
debug = false
|
|
371
|
+
} = options;
|
|
372
|
+
const debugLog = createDebugLog(debug);
|
|
373
|
+
const tokenUrl = getAuthTokenUrl({ baseUrl: credentials?.baseUrl });
|
|
374
|
+
const clientId = getAuthClientId(credentials?.clientId);
|
|
375
|
+
const startTime = Date.now();
|
|
376
|
+
try {
|
|
377
|
+
onEvent?.({
|
|
378
|
+
type: "auth_refreshing",
|
|
379
|
+
payload: {
|
|
380
|
+
message: "Refreshing your token...",
|
|
381
|
+
operation: "token_refresh"
|
|
382
|
+
},
|
|
383
|
+
timestamp: Date.now()
|
|
384
|
+
});
|
|
385
|
+
debugLog(`\u2192 POST ${tokenUrl}`, {
|
|
386
|
+
headers: {
|
|
387
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
388
|
+
[AUTH_MODE_HEADER]: "no"
|
|
389
|
+
},
|
|
390
|
+
body: {
|
|
391
|
+
client_id: clientId,
|
|
392
|
+
refresh_token: censorHeaderValue(refreshToken),
|
|
393
|
+
grant_type: "refresh_token"
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
const response = await fetch2(tokenUrl, {
|
|
397
|
+
method: "POST",
|
|
398
|
+
headers: {
|
|
399
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
400
|
+
[AUTH_MODE_HEADER]: "no"
|
|
401
|
+
},
|
|
402
|
+
body: new URLSearchParams({
|
|
403
|
+
client_id: clientId,
|
|
404
|
+
refresh_token: refreshToken,
|
|
405
|
+
grant_type: "refresh_token"
|
|
406
|
+
})
|
|
407
|
+
});
|
|
408
|
+
const duration = Date.now() - startTime;
|
|
409
|
+
if (!response.ok) {
|
|
410
|
+
debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
|
|
411
|
+
throw new Error(
|
|
412
|
+
`Token refresh failed: ${response.status} ${response.statusText}`
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
|
|
416
|
+
const data = await response.json();
|
|
417
|
+
await updateLogin(data, { debug });
|
|
418
|
+
debugLog(
|
|
419
|
+
`Token refreshed and saved to ${cachedLogin?.storage ?? "keychain"}`
|
|
420
|
+
);
|
|
421
|
+
onEvent?.({
|
|
422
|
+
type: "auth_success",
|
|
423
|
+
payload: {
|
|
424
|
+
message: "Token refreshed successfully",
|
|
425
|
+
operation: "token_refresh"
|
|
426
|
+
},
|
|
427
|
+
timestamp: Date.now()
|
|
428
|
+
});
|
|
429
|
+
return data.access_token;
|
|
430
|
+
} catch (error) {
|
|
431
|
+
const duration = Date.now() - startTime;
|
|
432
|
+
debugLog(`\u2716 Token refresh failed (${duration}ms)`, {
|
|
433
|
+
error: error instanceof Error ? error.message : error
|
|
434
|
+
});
|
|
435
|
+
cachedLogin = void 0;
|
|
436
|
+
const errorMessage = `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`;
|
|
437
|
+
onEvent?.({
|
|
438
|
+
type: "auth_error",
|
|
439
|
+
payload: {
|
|
440
|
+
message: errorMessage,
|
|
441
|
+
error: errorMessage,
|
|
442
|
+
operation: "token_refresh"
|
|
443
|
+
},
|
|
444
|
+
timestamp: Date.now()
|
|
445
|
+
});
|
|
446
|
+
throw error;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
var pendingRefresh = null;
|
|
450
|
+
var pendingResolve = null;
|
|
451
|
+
async function resolveStoredLogin(debugLog) {
|
|
452
|
+
if (cachedLogin) {
|
|
453
|
+
debugLog("Using in-memory cached credentials");
|
|
454
|
+
return cachedLogin;
|
|
455
|
+
}
|
|
456
|
+
if (pendingResolve) {
|
|
457
|
+
debugLog("Waiting for existing keychain read to complete");
|
|
458
|
+
return pendingResolve;
|
|
459
|
+
}
|
|
460
|
+
pendingResolve = resolveStoredLoginFromStorage(debugLog).finally(() => {
|
|
461
|
+
pendingResolve = null;
|
|
462
|
+
});
|
|
463
|
+
return pendingResolve;
|
|
464
|
+
}
|
|
465
|
+
async function resolveStoredLoginFromStorage(debugLog) {
|
|
466
|
+
let cfg;
|
|
467
|
+
try {
|
|
468
|
+
cfg = getConfig();
|
|
469
|
+
} catch (error) {
|
|
470
|
+
debugLog("Failed to load config", {
|
|
471
|
+
error: error instanceof Error ? error.message : error
|
|
472
|
+
});
|
|
473
|
+
return void 0;
|
|
474
|
+
}
|
|
475
|
+
const expiresAt = cfg.get("login_expires_at");
|
|
476
|
+
const configJwt = cfg.get("login_jwt");
|
|
477
|
+
const configRefresh = cfg.get("login_refresh_token");
|
|
478
|
+
if (configJwt && configRefresh && typeof expiresAt === "number") {
|
|
479
|
+
debugLog("Loaded credentials from config (legacy format)");
|
|
480
|
+
cachedLogin = {
|
|
481
|
+
jwt: configJwt,
|
|
482
|
+
refreshToken: configRefresh,
|
|
483
|
+
expiresAt,
|
|
484
|
+
storage: "config"
|
|
485
|
+
};
|
|
486
|
+
return cachedLogin;
|
|
487
|
+
}
|
|
488
|
+
if (typeof expiresAt !== "number") {
|
|
489
|
+
debugLog("No stored login credentials found");
|
|
490
|
+
return void 0;
|
|
491
|
+
}
|
|
492
|
+
const keychainData = await getTokensFromKeychain({ debugLog });
|
|
493
|
+
if (!keychainData) {
|
|
494
|
+
debugLog("No tokens found in keychain");
|
|
495
|
+
return void 0;
|
|
496
|
+
}
|
|
497
|
+
debugLog("Loaded credentials from keychain");
|
|
498
|
+
cachedLogin = {
|
|
499
|
+
jwt: keychainData.login_jwt,
|
|
500
|
+
refreshToken: keychainData.login_refresh_token,
|
|
501
|
+
expiresAt,
|
|
502
|
+
storage: "keychain"
|
|
503
|
+
};
|
|
504
|
+
return cachedLogin;
|
|
505
|
+
}
|
|
506
|
+
async function resolveOrRefreshToken(options = {}) {
|
|
507
|
+
const { debug = false } = options;
|
|
508
|
+
const debugLog = createDebugLog(debug);
|
|
509
|
+
const stored = await resolveStoredLogin(debugLog);
|
|
510
|
+
if (!stored) {
|
|
511
|
+
return void 0;
|
|
512
|
+
}
|
|
513
|
+
const { jwt: storedJwt, refreshToken, expiresAt } = stored;
|
|
514
|
+
if (expiresAt > Date.now() + TOKEN_REFRESH_BUFFER_MS) {
|
|
515
|
+
debugLog("Using cached token (still valid)");
|
|
516
|
+
return storedJwt;
|
|
517
|
+
}
|
|
518
|
+
debugLog("Token expired, refreshing...");
|
|
519
|
+
if (pendingRefresh) {
|
|
520
|
+
debugLog("Waiting for existing refresh to complete");
|
|
521
|
+
return pendingRefresh;
|
|
522
|
+
}
|
|
523
|
+
pendingRefresh = refreshJwt(refreshToken, options).finally(() => {
|
|
524
|
+
pendingRefresh = null;
|
|
525
|
+
});
|
|
526
|
+
return await pendingRefresh;
|
|
527
|
+
}
|
|
528
|
+
async function getToken(options = {}) {
|
|
529
|
+
try {
|
|
530
|
+
return await resolveOrRefreshToken(options);
|
|
531
|
+
} catch (error) {
|
|
532
|
+
const message = error instanceof Error ? error.message : "Token refresh failed";
|
|
533
|
+
throw new ZapierAuthenticationError(
|
|
534
|
+
`${message}
|
|
535
|
+
Please run 'login' to authenticate again.`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
async function getLoggedInUser(options = {}) {
|
|
540
|
+
const jwt2 = await getToken(options).catch(() => void 0);
|
|
541
|
+
if (!jwt2) {
|
|
542
|
+
throw new Error(
|
|
543
|
+
"No valid authentication token available. Please login first."
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
let decodedJwt = decodeJwtOrThrow(jwt2);
|
|
547
|
+
if (decodedJwt.payload["sub_type"] == "service") {
|
|
548
|
+
decodedJwt = decodeJwtOrThrow(decodedJwt.payload["njwt"]);
|
|
549
|
+
}
|
|
550
|
+
if (typeof decodedJwt.payload["zap:acc"] !== "string") {
|
|
551
|
+
throw new Error("JWT payload does not contain accountId");
|
|
552
|
+
}
|
|
553
|
+
const accountId = parseInt(decodedJwt.payload["zap:acc"], 10);
|
|
554
|
+
if (isNaN(accountId)) {
|
|
555
|
+
throw new Error("JWT accountId is not a number");
|
|
556
|
+
}
|
|
557
|
+
if (decodedJwt.payload["sub_type"] !== "customuser" || typeof decodedJwt.payload["sub"] !== "string") {
|
|
558
|
+
throw new Error("JWT payload does not contain customUserId");
|
|
559
|
+
}
|
|
560
|
+
const customUserId = parseInt(decodedJwt.payload["sub"], 10);
|
|
561
|
+
if (isNaN(customUserId)) {
|
|
562
|
+
throw new Error("JWT customUserId is not a number");
|
|
563
|
+
}
|
|
564
|
+
const email = decodedJwt.payload["zap:uname"];
|
|
565
|
+
if (typeof email !== "string") {
|
|
566
|
+
throw new Error("JWT payload does not contain email");
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
accountId,
|
|
570
|
+
customUserId,
|
|
571
|
+
email
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function getLoginStorageMode() {
|
|
575
|
+
const cfg = getConfig();
|
|
576
|
+
if (typeof cfg.get("login_jwt") === "string") {
|
|
577
|
+
return "config";
|
|
578
|
+
}
|
|
579
|
+
const explicitMode = cfg.get("login_storage_mode");
|
|
580
|
+
if (explicitMode === "keychain" || explicitMode === "config") {
|
|
581
|
+
return explicitMode;
|
|
582
|
+
}
|
|
583
|
+
return "keychain";
|
|
584
|
+
}
|
|
585
|
+
async function logout(options = {}) {
|
|
586
|
+
const { onEvent } = options;
|
|
587
|
+
const mode = getLoginStorageMode();
|
|
588
|
+
cachedLogin = void 0;
|
|
589
|
+
await clearTokensFromKeychain();
|
|
590
|
+
const cfg = getConfig();
|
|
591
|
+
cfg.set("login_storage_mode", mode);
|
|
592
|
+
cfg.delete("login_expires_at");
|
|
593
|
+
cfg.delete("login_jwt");
|
|
594
|
+
cfg.delete("login_refresh_token");
|
|
595
|
+
onEvent?.({
|
|
596
|
+
type: "auth_logout",
|
|
597
|
+
payload: { message: "Logged out successfully", operation: "logout" },
|
|
598
|
+
timestamp: Date.now()
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
function getConfigPath() {
|
|
602
|
+
const cfg = getConfig();
|
|
603
|
+
return cfg.path;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// src/utils/constants.ts
|
|
26
607
|
var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
|
|
27
608
|
var LOGIN_TIMEOUT_MS = 3e5;
|
|
28
609
|
var ZapierCliError = class extends ZapierError {
|
|
@@ -321,85 +902,65 @@ function toPkceCredentials(credentials) {
|
|
|
321
902
|
}
|
|
322
903
|
return void 0;
|
|
323
904
|
}
|
|
324
|
-
var loginPlugin = (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
credentials: pkceCredentials
|
|
335
|
-
});
|
|
336
|
-
const user = await getLoggedInUser();
|
|
337
|
-
sdk.context.eventEmission.emit(
|
|
338
|
-
"platform.sdk.ApplicationLifecycleEvent",
|
|
339
|
-
buildApplicationLifecycleEvent(
|
|
340
|
-
{ lifecycle_event_type: "login_success" },
|
|
341
|
-
{ customuser_id: user.customUserId, account_id: user.accountId }
|
|
342
|
-
)
|
|
343
|
-
);
|
|
344
|
-
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
345
|
-
};
|
|
346
|
-
return {
|
|
347
|
-
login: loginFn,
|
|
348
|
-
context: {
|
|
349
|
-
meta: {
|
|
350
|
-
login: {
|
|
351
|
-
categories: ["account"],
|
|
352
|
-
inputSchema: LoginSchema,
|
|
353
|
-
supportsJsonOutput: false
|
|
354
|
-
}
|
|
905
|
+
var loginPlugin = definePlugin(
|
|
906
|
+
(sdk) => createPluginMethod(sdk, {
|
|
907
|
+
name: "login",
|
|
908
|
+
categories: ["account"],
|
|
909
|
+
inputSchema: LoginSchema,
|
|
910
|
+
supportsJsonOutput: false,
|
|
911
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
912
|
+
const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
|
|
913
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
914
|
+
throw new Error("Timeout must be a positive number");
|
|
355
915
|
}
|
|
916
|
+
const resolvedCredentials = await sdk2.context.resolveCredentials();
|
|
917
|
+
const pkceCredentials = toPkceCredentials(resolvedCredentials);
|
|
918
|
+
await login_default({
|
|
919
|
+
timeoutMs: timeoutSeconds * 1e3,
|
|
920
|
+
credentials: pkceCredentials
|
|
921
|
+
});
|
|
922
|
+
const user = await getLoggedInUser();
|
|
923
|
+
sdk2.context.eventEmission.emit(
|
|
924
|
+
"platform.sdk.ApplicationLifecycleEvent",
|
|
925
|
+
buildApplicationLifecycleEvent(
|
|
926
|
+
{ lifecycle_event_type: "login_success" },
|
|
927
|
+
{ customuser_id: user.customUserId, account_id: user.accountId }
|
|
928
|
+
)
|
|
929
|
+
);
|
|
930
|
+
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
356
931
|
}
|
|
357
|
-
}
|
|
358
|
-
|
|
932
|
+
})
|
|
933
|
+
);
|
|
359
934
|
var LogoutSchema = z.object({}).describe("Log out of your Zapier account");
|
|
360
935
|
|
|
361
936
|
// src/plugins/logout/index.ts
|
|
362
|
-
var
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
});
|
|
937
|
+
var logoutPlugin = definePlugin(
|
|
938
|
+
(sdk) => createPluginMethod(sdk, {
|
|
939
|
+
name: "logout",
|
|
940
|
+
categories: ["account"],
|
|
941
|
+
inputSchema: LogoutSchema,
|
|
942
|
+
supportsJsonOutput: false,
|
|
943
|
+
handler: async () => {
|
|
944
|
+
await logout();
|
|
945
|
+
console.log("\u2705 Successfully logged out");
|
|
946
|
+
}
|
|
947
|
+
})
|
|
948
|
+
);
|
|
378
949
|
var McpSchema = z.object({
|
|
379
950
|
port: z.string().optional().describe("Port to listen on (for future HTTP transport)")
|
|
380
951
|
}).describe("Start MCP server for Zapier SDK");
|
|
381
952
|
|
|
382
953
|
// src/plugins/mcp/index.ts
|
|
383
|
-
var mcpPlugin = (
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
context: {
|
|
394
|
-
meta: {
|
|
395
|
-
mcp: {
|
|
396
|
-
categories: ["utility"],
|
|
397
|
-
inputSchema: McpSchema
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
};
|
|
402
|
-
};
|
|
954
|
+
var mcpPlugin = definePlugin(
|
|
955
|
+
(sdk) => createPluginMethod(sdk, {
|
|
956
|
+
name: "mcp",
|
|
957
|
+
categories: ["utility"],
|
|
958
|
+
inputSchema: McpSchema,
|
|
959
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
960
|
+
await startMcpServer({ ...options, debug: sdk2.context.options?.debug });
|
|
961
|
+
}
|
|
962
|
+
})
|
|
963
|
+
);
|
|
403
964
|
var BundleCodeSchema = z.object({
|
|
404
965
|
input: z.string().min(1).describe("Input TypeScript file path to bundle"),
|
|
405
966
|
output: OutputPropertySchema.optional().describe(
|
|
@@ -410,22 +971,14 @@ var BundleCodeSchema = z.object({
|
|
|
410
971
|
target: z.string().optional().describe("ECMAScript target version"),
|
|
411
972
|
cjs: z.boolean().optional().describe("Output CommonJS format instead of ESM")
|
|
412
973
|
}).describe("Bundle TypeScript code into executable JavaScript");
|
|
413
|
-
var bundleCodePlugin = (
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
bundleCode: {
|
|
422
|
-
categories: ["utility", "deprecated"],
|
|
423
|
-
inputSchema: BundleCodeSchema
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
};
|
|
974
|
+
var bundleCodePlugin = definePlugin(
|
|
975
|
+
(sdk) => createPluginMethod(sdk, {
|
|
976
|
+
name: "bundleCode",
|
|
977
|
+
categories: ["utility", "deprecated"],
|
|
978
|
+
inputSchema: BundleCodeSchema,
|
|
979
|
+
handler: async ({ options }) => bundleCode(options)
|
|
980
|
+
})
|
|
981
|
+
);
|
|
429
982
|
var ZapierBundleError = class extends Error {
|
|
430
983
|
constructor(message, details, originalError) {
|
|
431
984
|
super(message);
|
|
@@ -492,25 +1045,14 @@ async function bundleCode(options) {
|
|
|
492
1045
|
}
|
|
493
1046
|
}
|
|
494
1047
|
var GetLoginConfigPathSchema = z.object({}).describe("Show the path to the login configuration file");
|
|
495
|
-
var getLoginConfigPathPlugin = (
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
getLoginConfigPath: getLoginConfigPathWithSdk,
|
|
504
|
-
context: {
|
|
505
|
-
meta: {
|
|
506
|
-
getLoginConfigPath: {
|
|
507
|
-
categories: ["utility"],
|
|
508
|
-
inputSchema: GetLoginConfigPathSchema
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
};
|
|
1048
|
+
var getLoginConfigPathPlugin = definePlugin(
|
|
1049
|
+
(sdk) => createPluginMethod(sdk, {
|
|
1050
|
+
name: "getLoginConfigPath",
|
|
1051
|
+
categories: ["utility"],
|
|
1052
|
+
inputSchema: GetLoginConfigPathSchema,
|
|
1053
|
+
handler: async () => getConfigPath()
|
|
1054
|
+
})
|
|
1055
|
+
);
|
|
514
1056
|
var AddSchema = z.object({
|
|
515
1057
|
apps: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
|
|
516
1058
|
"One or more app keys to add (e.g., 'slack', 'github', 'trello')"
|
|
@@ -538,111 +1080,105 @@ async function detectTypesOutputDirectory() {
|
|
|
538
1080
|
}
|
|
539
1081
|
return "./zapier/apps/";
|
|
540
1082
|
}
|
|
541
|
-
var addPlugin = (
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
skipWrite: false,
|
|
616
|
-
configPath,
|
|
617
|
-
onProgress: handleManifestProgress
|
|
618
|
-
});
|
|
619
|
-
const typesResult = await sdk.generateAppTypes({
|
|
620
|
-
apps: appKeys,
|
|
621
|
-
connections: connectionIds,
|
|
622
|
-
skipWrite: false,
|
|
623
|
-
typesOutputDirectory: resolvedTypesOutput,
|
|
624
|
-
onProgress: handleTypesProgress
|
|
625
|
-
});
|
|
626
|
-
const results = manifestResult.manifest?.apps || {};
|
|
627
|
-
const successfulApps = Object.keys(results).filter(
|
|
628
|
-
(manifestKey) => typesResult.writtenFiles?.[manifestKey]
|
|
629
|
-
);
|
|
630
|
-
if (successfulApps.length > 0) {
|
|
631
|
-
console.log(`\u2705 Added ${successfulApps.length} app(s) to manifest`);
|
|
632
|
-
}
|
|
633
|
-
}, AddSchema);
|
|
634
|
-
return {
|
|
635
|
-
add,
|
|
636
|
-
context: {
|
|
637
|
-
meta: {
|
|
638
|
-
add: {
|
|
639
|
-
categories: ["utility"],
|
|
640
|
-
inputSchema: AddSchema
|
|
1083
|
+
var addPlugin = definePlugin(
|
|
1084
|
+
(sdk) => createPluginMethod(sdk, {
|
|
1085
|
+
name: "add",
|
|
1086
|
+
categories: ["utility"],
|
|
1087
|
+
inputSchema: AddSchema,
|
|
1088
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
1089
|
+
const {
|
|
1090
|
+
apps: appKeys,
|
|
1091
|
+
connections: connectionIds,
|
|
1092
|
+
configPath,
|
|
1093
|
+
typesOutput = await detectTypesOutputDirectory()
|
|
1094
|
+
} = options;
|
|
1095
|
+
const resolvedTypesOutput = resolve(typesOutput);
|
|
1096
|
+
console.log(`\u{1F4E6} Adding ${appKeys.length} app(s)...`);
|
|
1097
|
+
const appSlugAndKeyMap = /* @__PURE__ */ new Map();
|
|
1098
|
+
const handleManifestProgress = (event) => {
|
|
1099
|
+
switch (event.type) {
|
|
1100
|
+
case "apps_lookup_start":
|
|
1101
|
+
console.log(`\u{1F4E6} Looking up ${event.count} app(s)...`);
|
|
1102
|
+
break;
|
|
1103
|
+
case "app_found":
|
|
1104
|
+
const displayName = event.app.slug ? `${event.app.slug} (${event.app.key})` : event.app.key;
|
|
1105
|
+
appSlugAndKeyMap.set(event.app.key, displayName);
|
|
1106
|
+
break;
|
|
1107
|
+
case "apps_lookup_complete":
|
|
1108
|
+
if (event.count === 0) {
|
|
1109
|
+
console.warn("\u26A0\uFE0F No apps found");
|
|
1110
|
+
}
|
|
1111
|
+
break;
|
|
1112
|
+
case "app_processing_start":
|
|
1113
|
+
const appName = event.slug ? `${event.slug} (${event.app})` : event.app;
|
|
1114
|
+
console.log(`\u{1F4E6} Adding ${appName}...`);
|
|
1115
|
+
break;
|
|
1116
|
+
case "manifest_updated":
|
|
1117
|
+
const appDisplay = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1118
|
+
console.log(
|
|
1119
|
+
`\u{1F4DD} Locked ${appDisplay} to ${event.app}@${event.version} using key '${event.manifestKey}'`
|
|
1120
|
+
);
|
|
1121
|
+
break;
|
|
1122
|
+
case "app_processing_error":
|
|
1123
|
+
const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1124
|
+
console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
1127
|
+
};
|
|
1128
|
+
const handleTypesProgress = (event) => {
|
|
1129
|
+
switch (event.type) {
|
|
1130
|
+
case "connections_lookup_start":
|
|
1131
|
+
console.log(`\u{1F510} Looking up ${event.count} connection(s)...`);
|
|
1132
|
+
break;
|
|
1133
|
+
case "connections_lookup_complete":
|
|
1134
|
+
console.log(`\u{1F510} Found ${event.count} connection(s)`);
|
|
1135
|
+
break;
|
|
1136
|
+
case "connection_matched":
|
|
1137
|
+
const appWithConnection = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1138
|
+
console.log(
|
|
1139
|
+
`\u{1F510} Using connection ${event.connectionId} (${event.connectionTitle}) for ${appWithConnection}`
|
|
1140
|
+
);
|
|
1141
|
+
break;
|
|
1142
|
+
case "connection_not_matched":
|
|
1143
|
+
const appWithoutConnection = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1144
|
+
console.warn(
|
|
1145
|
+
`\u26A0\uFE0F No matching connection found for ${appWithoutConnection}`
|
|
1146
|
+
);
|
|
1147
|
+
break;
|
|
1148
|
+
case "file_written":
|
|
1149
|
+
console.log(
|
|
1150
|
+
`\u{1F527} Generated types for ${event.manifestKey} at ${event.filePath}`
|
|
1151
|
+
);
|
|
1152
|
+
break;
|
|
1153
|
+
case "app_processing_error":
|
|
1154
|
+
const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1155
|
+
console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
|
|
1156
|
+
break;
|
|
641
1157
|
}
|
|
1158
|
+
};
|
|
1159
|
+
const manifestResult = await sdk2.buildManifest({
|
|
1160
|
+
apps: appKeys,
|
|
1161
|
+
skipWrite: false,
|
|
1162
|
+
configPath,
|
|
1163
|
+
onProgress: handleManifestProgress
|
|
1164
|
+
});
|
|
1165
|
+
const typesResult = await sdk2.generateAppTypes({
|
|
1166
|
+
apps: appKeys,
|
|
1167
|
+
connections: connectionIds,
|
|
1168
|
+
skipWrite: false,
|
|
1169
|
+
typesOutputDirectory: resolvedTypesOutput,
|
|
1170
|
+
onProgress: handleTypesProgress
|
|
1171
|
+
});
|
|
1172
|
+
const results = manifestResult.manifest?.apps || {};
|
|
1173
|
+
const successfulApps = Object.keys(results).filter(
|
|
1174
|
+
(manifestKey) => typesResult.writtenFiles?.[manifestKey]
|
|
1175
|
+
);
|
|
1176
|
+
if (successfulApps.length > 0) {
|
|
1177
|
+
console.log(`\u2705 Added ${successfulApps.length} app(s) to manifest`);
|
|
642
1178
|
}
|
|
643
1179
|
}
|
|
644
|
-
}
|
|
645
|
-
|
|
1180
|
+
})
|
|
1181
|
+
);
|
|
646
1182
|
var GenerateAppTypesSchema = z.object({
|
|
647
1183
|
apps: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
|
|
648
1184
|
"One or more app keys to generate types for (e.g., 'slack', 'github', 'trello')"
|
|
@@ -1249,150 +1785,133 @@ function createManifestEntry(app) {
|
|
|
1249
1785
|
version: app.version
|
|
1250
1786
|
};
|
|
1251
1787
|
}
|
|
1252
|
-
var generateAppTypesPlugin = (
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
}
|
|
1276
|
-
const connections = [];
|
|
1277
|
-
if (connectionIds && connectionIds.length > 0) {
|
|
1278
|
-
onProgress?.({
|
|
1279
|
-
type: "connections_lookup_start",
|
|
1280
|
-
count: connectionIds.length
|
|
1281
|
-
});
|
|
1282
|
-
const connectionsIterable = sdk.listConnections({ connections: connectionIds }).items();
|
|
1283
|
-
for await (const connection of connectionsIterable) {
|
|
1284
|
-
connections.push(connection);
|
|
1788
|
+
var generateAppTypesPlugin = definePlugin(
|
|
1789
|
+
(sdk) => createPluginMethod(sdk, {
|
|
1790
|
+
name: "generateAppTypes",
|
|
1791
|
+
categories: ["utility"],
|
|
1792
|
+
// Cast: schema validates JSON fields only; GenerateAppTypesOptions adds
|
|
1793
|
+
// the runtime-only `onProgress` callback (passthrough via createFunction).
|
|
1794
|
+
inputSchema: GenerateAppTypesSchema,
|
|
1795
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
1796
|
+
const {
|
|
1797
|
+
apps: appKeys,
|
|
1798
|
+
connections: connectionIds,
|
|
1799
|
+
skipWrite = false,
|
|
1800
|
+
typesOutputDirectory = await detectTypesOutputDirectory(),
|
|
1801
|
+
onProgress
|
|
1802
|
+
} = options;
|
|
1803
|
+
const resolvedTypesOutput = resolve(typesOutputDirectory);
|
|
1804
|
+
const result = { typeDefinitions: {} };
|
|
1805
|
+
onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
|
|
1806
|
+
const appsIterable = sdk2.listApps({ apps: appKeys }).items();
|
|
1807
|
+
const apps = [];
|
|
1808
|
+
for await (const app of appsIterable) {
|
|
1809
|
+
apps.push(app);
|
|
1810
|
+
onProgress?.({ type: "app_found", app });
|
|
1285
1811
|
}
|
|
1286
|
-
onProgress?.({
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
type: "app_processing_start",
|
|
1300
|
-
app: app.key,
|
|
1301
|
-
slug: app.slug
|
|
1302
|
-
});
|
|
1303
|
-
try {
|
|
1304
|
-
if (!app.version) {
|
|
1305
|
-
const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
|
|
1306
|
-
onProgress?.({
|
|
1307
|
-
type: "app_processing_error",
|
|
1308
|
-
app: app.key,
|
|
1309
|
-
error: errorMessage
|
|
1310
|
-
});
|
|
1311
|
-
throw new ZapierValidationError(errorMessage, {
|
|
1312
|
-
details: {
|
|
1313
|
-
appKey: app.key,
|
|
1314
|
-
implementationId: app.implementation_id
|
|
1315
|
-
}
|
|
1316
|
-
});
|
|
1812
|
+
onProgress?.({ type: "apps_lookup_complete", count: apps.length });
|
|
1813
|
+
if (apps.length === 0) {
|
|
1814
|
+
return result;
|
|
1815
|
+
}
|
|
1816
|
+
const connections = [];
|
|
1817
|
+
if (connectionIds && connectionIds.length > 0) {
|
|
1818
|
+
onProgress?.({
|
|
1819
|
+
type: "connections_lookup_start",
|
|
1820
|
+
count: connectionIds.length
|
|
1821
|
+
});
|
|
1822
|
+
const connectionsIterable = sdk2.listConnections({ connections: connectionIds }).items();
|
|
1823
|
+
for await (const connection of connectionsIterable) {
|
|
1824
|
+
connections.push(connection);
|
|
1317
1825
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1826
|
+
onProgress?.({
|
|
1827
|
+
type: "connections_lookup_complete",
|
|
1828
|
+
count: connections.length
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
if (!skipWrite && resolvedTypesOutput) {
|
|
1832
|
+
await mkdir(resolvedTypesOutput, { recursive: true });
|
|
1833
|
+
}
|
|
1834
|
+
if (!skipWrite) {
|
|
1835
|
+
result.writtenFiles = {};
|
|
1836
|
+
}
|
|
1837
|
+
for (const app of apps) {
|
|
1838
|
+
onProgress?.({
|
|
1839
|
+
type: "app_processing_start",
|
|
1840
|
+
app: app.key,
|
|
1841
|
+
slug: app.slug
|
|
1842
|
+
});
|
|
1843
|
+
try {
|
|
1844
|
+
if (!app.version) {
|
|
1845
|
+
const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
|
|
1325
1846
|
onProgress?.({
|
|
1326
|
-
type: "
|
|
1847
|
+
type: "app_processing_error",
|
|
1327
1848
|
app: app.key,
|
|
1328
|
-
|
|
1329
|
-
connectionTitle: matchingConnection.title || ""
|
|
1849
|
+
error: errorMessage
|
|
1330
1850
|
});
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1851
|
+
throw new ZapierValidationError(errorMessage, {
|
|
1852
|
+
details: {
|
|
1853
|
+
appKey: app.key,
|
|
1854
|
+
implementationId: app.implementation_id
|
|
1855
|
+
}
|
|
1335
1856
|
});
|
|
1336
1857
|
}
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1858
|
+
let connectionId;
|
|
1859
|
+
if (connections.length > 0) {
|
|
1860
|
+
const matchingConnection = connections.find(
|
|
1861
|
+
(conn) => conn.app_key === app.key
|
|
1862
|
+
);
|
|
1863
|
+
if (matchingConnection) {
|
|
1864
|
+
connectionId = matchingConnection.id;
|
|
1865
|
+
onProgress?.({
|
|
1866
|
+
type: "connection_matched",
|
|
1867
|
+
app: app.key,
|
|
1868
|
+
connectionId: matchingConnection.id,
|
|
1869
|
+
connectionTitle: matchingConnection.title || ""
|
|
1870
|
+
});
|
|
1871
|
+
} else {
|
|
1872
|
+
onProgress?.({
|
|
1873
|
+
type: "connection_not_matched",
|
|
1874
|
+
app: app.key
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
const manifestKey = getManifestKey(app);
|
|
1879
|
+
const generator = new AstTypeGenerator();
|
|
1880
|
+
const typeDefinitionString = await generator.generateTypes({
|
|
1881
|
+
app,
|
|
1882
|
+
connectionId,
|
|
1883
|
+
sdk: sdk2
|
|
1884
|
+
});
|
|
1885
|
+
result.typeDefinitions[manifestKey] = typeDefinitionString;
|
|
1355
1886
|
onProgress?.({
|
|
1356
|
-
type: "
|
|
1887
|
+
type: "type_generated",
|
|
1357
1888
|
manifestKey,
|
|
1358
|
-
|
|
1889
|
+
sizeBytes: typeDefinitionString.length
|
|
1359
1890
|
});
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
throw error;
|
|
1374
|
-
} else {
|
|
1375
|
-
throw new ZapierUnknownError(errorMessage, {
|
|
1376
|
-
cause: error
|
|
1377
|
-
// Works for both Error and non-Error
|
|
1891
|
+
if (!skipWrite && resolvedTypesOutput && result.writtenFiles) {
|
|
1892
|
+
const filePath = join(resolvedTypesOutput, `${manifestKey}.d.ts`);
|
|
1893
|
+
await writeFile(filePath, typeDefinitionString, "utf8");
|
|
1894
|
+
result.writtenFiles[manifestKey] = filePath;
|
|
1895
|
+
onProgress?.({ type: "file_written", manifestKey, filePath });
|
|
1896
|
+
}
|
|
1897
|
+
onProgress?.({ type: "app_processing_complete", app: app.key });
|
|
1898
|
+
} catch (error) {
|
|
1899
|
+
const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
|
|
1900
|
+
onProgress?.({
|
|
1901
|
+
type: "app_processing_error",
|
|
1902
|
+
app: app.key,
|
|
1903
|
+
error: errorMessage
|
|
1378
1904
|
});
|
|
1905
|
+
if (error instanceof ZapierValidationError) {
|
|
1906
|
+
throw error;
|
|
1907
|
+
}
|
|
1908
|
+
throw new ZapierUnknownError(errorMessage, { cause: error });
|
|
1379
1909
|
}
|
|
1380
1910
|
}
|
|
1911
|
+
return result;
|
|
1381
1912
|
}
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
return {
|
|
1385
|
-
generateAppTypes,
|
|
1386
|
-
context: {
|
|
1387
|
-
meta: {
|
|
1388
|
-
generateAppTypes: {
|
|
1389
|
-
categories: ["utility"],
|
|
1390
|
-
inputSchema: GenerateAppTypesSchema
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
};
|
|
1395
|
-
};
|
|
1913
|
+
})
|
|
1914
|
+
);
|
|
1396
1915
|
var BuildManifestSchema = z.object({
|
|
1397
1916
|
apps: z.array(z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
|
|
1398
1917
|
"One or more app keys to build manifest entries for (e.g., 'slack', 'github', 'trello')"
|
|
@@ -1408,86 +1927,80 @@ var BuildManifestSchema = z.object({
|
|
|
1408
1927
|
);
|
|
1409
1928
|
|
|
1410
1929
|
// src/plugins/buildManifest/index.ts
|
|
1411
|
-
var buildManifestPlugin = (
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
type: "manifest_entry_built",
|
|
1441
|
-
app: app.key,
|
|
1442
|
-
manifestKey: manifestEntry.implementationName,
|
|
1443
|
-
version: manifestEntry.version || ""
|
|
1444
|
-
});
|
|
1445
|
-
const { key: updatedManifestKey, manifest } = await sdk.context.updateManifestEntry({
|
|
1446
|
-
appKey: app.key,
|
|
1447
|
-
entry: manifestEntry,
|
|
1448
|
-
configPath,
|
|
1449
|
-
skipWrite,
|
|
1450
|
-
manifest: updatedManifest
|
|
1451
|
-
});
|
|
1452
|
-
updatedManifest = manifest;
|
|
1453
|
-
onProgress?.({
|
|
1454
|
-
type: "manifest_updated",
|
|
1455
|
-
app: app.key,
|
|
1456
|
-
manifestKey: updatedManifestKey,
|
|
1457
|
-
version: manifestEntry.version || ""
|
|
1458
|
-
});
|
|
1459
|
-
onProgress?.({ type: "app_processing_complete", app: app.key });
|
|
1460
|
-
} catch (error) {
|
|
1461
|
-
const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
|
|
1930
|
+
var buildManifestPlugin = definePlugin(
|
|
1931
|
+
(sdk) => createPluginMethod(sdk, {
|
|
1932
|
+
name: "buildManifest",
|
|
1933
|
+
categories: ["utility"],
|
|
1934
|
+
// Cast: BuildManifestSchema validates JSON-serializable fields only.
|
|
1935
|
+
// BuildManifestOptions adds an `onProgress` callback that rides through
|
|
1936
|
+
// `createFunction`'s passthrough spread at runtime; this widens TInput
|
|
1937
|
+
// so the handler can read it.
|
|
1938
|
+
inputSchema: BuildManifestSchema,
|
|
1939
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
1940
|
+
const {
|
|
1941
|
+
apps: appKeys,
|
|
1942
|
+
skipWrite = false,
|
|
1943
|
+
configPath,
|
|
1944
|
+
onProgress
|
|
1945
|
+
} = options;
|
|
1946
|
+
onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
|
|
1947
|
+
const appsIterable = sdk2.listApps({ apps: appKeys }).items();
|
|
1948
|
+
const apps = [];
|
|
1949
|
+
for await (const app of appsIterable) {
|
|
1950
|
+
apps.push(app);
|
|
1951
|
+
onProgress?.({ type: "app_found", app });
|
|
1952
|
+
}
|
|
1953
|
+
onProgress?.({ type: "apps_lookup_complete", count: apps.length });
|
|
1954
|
+
if (apps.length === 0) {
|
|
1955
|
+
return {};
|
|
1956
|
+
}
|
|
1957
|
+
let updatedManifest;
|
|
1958
|
+
for (const app of apps) {
|
|
1462
1959
|
onProgress?.({
|
|
1463
|
-
type: "
|
|
1960
|
+
type: "app_processing_start",
|
|
1464
1961
|
app: app.key,
|
|
1465
|
-
|
|
1962
|
+
slug: app.slug
|
|
1466
1963
|
});
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1964
|
+
try {
|
|
1965
|
+
const manifestEntry = createManifestEntry(app);
|
|
1966
|
+
onProgress?.({
|
|
1967
|
+
type: "manifest_entry_built",
|
|
1968
|
+
app: app.key,
|
|
1969
|
+
manifestKey: manifestEntry.implementationName,
|
|
1970
|
+
version: manifestEntry.version || ""
|
|
1473
1971
|
});
|
|
1972
|
+
const { key: updatedManifestKey, manifest } = await sdk2.context.updateManifestEntry({
|
|
1973
|
+
appKey: app.key,
|
|
1974
|
+
entry: manifestEntry,
|
|
1975
|
+
configPath,
|
|
1976
|
+
skipWrite,
|
|
1977
|
+
manifest: updatedManifest
|
|
1978
|
+
});
|
|
1979
|
+
updatedManifest = manifest;
|
|
1980
|
+
onProgress?.({
|
|
1981
|
+
type: "manifest_updated",
|
|
1982
|
+
app: app.key,
|
|
1983
|
+
manifestKey: updatedManifestKey,
|
|
1984
|
+
version: manifestEntry.version || ""
|
|
1985
|
+
});
|
|
1986
|
+
onProgress?.({ type: "app_processing_complete", app: app.key });
|
|
1987
|
+
} catch (error) {
|
|
1988
|
+
const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
|
|
1989
|
+
onProgress?.({
|
|
1990
|
+
type: "app_processing_error",
|
|
1991
|
+
app: app.key,
|
|
1992
|
+
error: errorMessage
|
|
1993
|
+
});
|
|
1994
|
+
if (error instanceof ZapierValidationError) {
|
|
1995
|
+
throw error;
|
|
1996
|
+
}
|
|
1997
|
+
throw new ZapierUnknownError(errorMessage, { cause: error });
|
|
1474
1998
|
}
|
|
1475
1999
|
}
|
|
2000
|
+
return { manifest: updatedManifest };
|
|
1476
2001
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
return {
|
|
1480
|
-
buildManifest,
|
|
1481
|
-
context: {
|
|
1482
|
-
meta: {
|
|
1483
|
-
buildManifest: {
|
|
1484
|
-
categories: ["utility"],
|
|
1485
|
-
inputSchema: BuildManifestSchema
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
};
|
|
1490
|
-
};
|
|
2002
|
+
})
|
|
2003
|
+
);
|
|
1491
2004
|
var FeedbackSchema = z.object({
|
|
1492
2005
|
feedback: z.string().describe(
|
|
1493
2006
|
"Your feedback on the Zapier SDK. Describe what worked well, what was frustrating, or any suggestions."
|
|
@@ -1521,37 +2034,31 @@ async function postWithRetry({
|
|
|
1521
2034
|
}
|
|
1522
2035
|
return response;
|
|
1523
2036
|
}
|
|
1524
|
-
var feedbackPlugin = (
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
feedback: {
|
|
1545
|
-
categories: ["utility"],
|
|
1546
|
-
inputSchema: FeedbackSchema,
|
|
1547
|
-
resolvers: {
|
|
1548
|
-
feedback: feedbackResolver
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
2037
|
+
var feedbackPlugin = definePlugin(
|
|
2038
|
+
(sdk) => createPluginMethod(sdk, {
|
|
2039
|
+
name: "feedback",
|
|
2040
|
+
categories: ["utility"],
|
|
2041
|
+
inputSchema: FeedbackSchema,
|
|
2042
|
+
resolvers: { feedback: feedbackResolver },
|
|
2043
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
2044
|
+
const user = await getLoggedInUser();
|
|
2045
|
+
const body = JSON.stringify({
|
|
2046
|
+
email: user.email,
|
|
2047
|
+
customuser_id: user.customUserId,
|
|
2048
|
+
feedback: options.feedback
|
|
2049
|
+
});
|
|
2050
|
+
const response = await postWithRetry({
|
|
2051
|
+
body,
|
|
2052
|
+
attemptsLeft: MAX_RETRIES
|
|
2053
|
+
});
|
|
2054
|
+
if (sdk2.context.options?.debug) {
|
|
2055
|
+
const text = await response.text();
|
|
2056
|
+
console.error("[debug] Webhook response:", text);
|
|
1551
2057
|
}
|
|
2058
|
+
return "Thank you for your feedback!";
|
|
1552
2059
|
}
|
|
1553
|
-
}
|
|
1554
|
-
|
|
2060
|
+
})
|
|
2061
|
+
);
|
|
1555
2062
|
var CurlSchema = z.object({
|
|
1556
2063
|
url: z.string().describe("Request URL"),
|
|
1557
2064
|
request: z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method (defaults to GET, or POST if data is provided)"),
|
|
@@ -1727,7 +2234,7 @@ async function buildFormData(formArgs, formStringArgs) {
|
|
|
1727
2234
|
}
|
|
1728
2235
|
|
|
1729
2236
|
// src/plugins/curl/index.ts
|
|
1730
|
-
var curlPlugin = (sdk) => {
|
|
2237
|
+
var curlPlugin = definePlugin((sdk) => {
|
|
1731
2238
|
async function curl(options) {
|
|
1732
2239
|
const {
|
|
1733
2240
|
url: rawUrl,
|
|
@@ -1970,30 +2477,25 @@ ${Array.from(
|
|
|
1970
2477
|
}
|
|
1971
2478
|
}
|
|
1972
2479
|
};
|
|
1973
|
-
};
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
...sdk.context.meta.fetch.categories || [],
|
|
1987
|
-
"deprecated"
|
|
1988
|
-
],
|
|
1989
|
-
deprecation: {
|
|
1990
|
-
message: "This command is deprecated and will be removed soon. Use `curl` instead. Learn more: https://docs.zapier.com/sdk/cli-reference#curl"
|
|
1991
|
-
}
|
|
2480
|
+
});
|
|
2481
|
+
var cliOverridesPlugin = definePlugin(
|
|
2482
|
+
(sdk) => {
|
|
2483
|
+
const meta = {};
|
|
2484
|
+
if (sdk.context.meta.fetch) {
|
|
2485
|
+
meta.fetch = {
|
|
2486
|
+
...sdk.context.meta.fetch,
|
|
2487
|
+
categories: [
|
|
2488
|
+
...sdk.context.meta.fetch.categories || [],
|
|
2489
|
+
"deprecated"
|
|
2490
|
+
],
|
|
2491
|
+
deprecation: {
|
|
2492
|
+
message: "This command is deprecated and will be removed soon. Use `curl` instead. Learn more: https://docs.zapier.com/sdk/cli-reference#curl"
|
|
1992
2493
|
}
|
|
1993
|
-
}
|
|
2494
|
+
};
|
|
1994
2495
|
}
|
|
1995
|
-
|
|
1996
|
-
}
|
|
2496
|
+
return { context: { meta } };
|
|
2497
|
+
}
|
|
2498
|
+
);
|
|
1997
2499
|
var TEMPLATES = ["basic"];
|
|
1998
2500
|
var InitSchema = z.object({
|
|
1999
2501
|
projectName: z.string().min(1).describe("Name of the project directory to create"),
|
|
@@ -2405,74 +2907,68 @@ function displaySummaryAndNextSteps({
|
|
|
2405
2907
|
}
|
|
2406
2908
|
|
|
2407
2909
|
// src/plugins/init/index.ts
|
|
2408
|
-
var initPlugin = (
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
);
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
packageManager,
|
|
2425
|
-
displayHooks
|
|
2426
|
-
});
|
|
2427
|
-
const completedSetupStepIds = [];
|
|
2428
|
-
for (let i = 0; i < steps.length; i++) {
|
|
2429
|
-
const step = steps[i];
|
|
2430
|
-
const succeeded = await withInterruptCleanup(
|
|
2431
|
-
step.cleanup,
|
|
2432
|
-
() => runStep({
|
|
2433
|
-
step,
|
|
2434
|
-
stepNumber: i + 1,
|
|
2435
|
-
totalSteps: steps.length,
|
|
2436
|
-
skipPrompts,
|
|
2437
|
-
displayHooks
|
|
2438
|
-
})
|
|
2439
|
-
);
|
|
2440
|
-
if (!succeeded) break;
|
|
2441
|
-
completedSetupStepIds.push(step.id);
|
|
2442
|
-
}
|
|
2443
|
-
if (completedSetupStepIds.length === 0) {
|
|
2444
|
-
throw new ZapierCliExitError(
|
|
2445
|
-
"Project setup failed \u2014 no steps completed."
|
|
2446
|
-
);
|
|
2447
|
-
}
|
|
2448
|
-
displaySummaryAndNextSteps({
|
|
2449
|
-
projectName,
|
|
2450
|
-
steps,
|
|
2451
|
-
completedSetupStepIds,
|
|
2452
|
-
packageManager
|
|
2453
|
-
});
|
|
2454
|
-
}, InitSchema);
|
|
2455
|
-
return {
|
|
2456
|
-
init,
|
|
2457
|
-
context: {
|
|
2458
|
-
meta: {
|
|
2459
|
-
init: {
|
|
2460
|
-
categories: ["utility"],
|
|
2461
|
-
inputSchema: InitSchema,
|
|
2462
|
-
supportsJsonOutput: false
|
|
2463
|
-
}
|
|
2910
|
+
var initPlugin = definePlugin(
|
|
2911
|
+
(sdk) => createPluginMethod(sdk, {
|
|
2912
|
+
name: "init",
|
|
2913
|
+
categories: ["utility"],
|
|
2914
|
+
inputSchema: InitSchema,
|
|
2915
|
+
supportsJsonOutput: false,
|
|
2916
|
+
handler: async ({ options }) => {
|
|
2917
|
+
const { projectName: rawName, skipPrompts = false } = options;
|
|
2918
|
+
const cwd = process.cwd();
|
|
2919
|
+
const { projectName, projectDir } = validateInitOptions({ rawName, cwd });
|
|
2920
|
+
const displayHooks = createConsoleDisplayHooks();
|
|
2921
|
+
const packageManagerInfo = detectPackageManager(cwd);
|
|
2922
|
+
if (packageManagerInfo.name === "unknown") {
|
|
2923
|
+
displayHooks.onWarn(
|
|
2924
|
+
"Could not detect package manager, defaulting to npm."
|
|
2925
|
+
);
|
|
2464
2926
|
}
|
|
2927
|
+
const packageManager = packageManagerInfo.name === "unknown" ? "npm" : packageManagerInfo.name;
|
|
2928
|
+
const steps = getInitSteps({
|
|
2929
|
+
projectDir,
|
|
2930
|
+
projectName,
|
|
2931
|
+
packageManager,
|
|
2932
|
+
displayHooks
|
|
2933
|
+
});
|
|
2934
|
+
const completedSetupStepIds = [];
|
|
2935
|
+
for (let i = 0; i < steps.length; i++) {
|
|
2936
|
+
const step = steps[i];
|
|
2937
|
+
const succeeded = await withInterruptCleanup(
|
|
2938
|
+
step.cleanup,
|
|
2939
|
+
() => runStep({
|
|
2940
|
+
step,
|
|
2941
|
+
stepNumber: i + 1,
|
|
2942
|
+
totalSteps: steps.length,
|
|
2943
|
+
skipPrompts,
|
|
2944
|
+
displayHooks
|
|
2945
|
+
})
|
|
2946
|
+
);
|
|
2947
|
+
if (!succeeded) break;
|
|
2948
|
+
completedSetupStepIds.push(step.id);
|
|
2949
|
+
}
|
|
2950
|
+
if (completedSetupStepIds.length === 0) {
|
|
2951
|
+
throw new ZapierCliExitError(
|
|
2952
|
+
"Project setup failed \u2014 no steps completed."
|
|
2953
|
+
);
|
|
2954
|
+
}
|
|
2955
|
+
displaySummaryAndNextSteps({
|
|
2956
|
+
projectName,
|
|
2957
|
+
steps,
|
|
2958
|
+
completedSetupStepIds,
|
|
2959
|
+
packageManager
|
|
2960
|
+
});
|
|
2465
2961
|
}
|
|
2466
|
-
}
|
|
2467
|
-
|
|
2962
|
+
})
|
|
2963
|
+
);
|
|
2468
2964
|
|
|
2469
2965
|
// package.json with { type: 'json' }
|
|
2470
2966
|
var package_default = {
|
|
2471
2967
|
name: "@zapier/zapier-sdk-cli",
|
|
2472
|
-
version: "0.
|
|
2968
|
+
version: "0.43.1"};
|
|
2473
2969
|
|
|
2474
2970
|
// src/sdk.ts
|
|
2475
|
-
injectCliLogin(
|
|
2971
|
+
injectCliLogin(login_exports);
|
|
2476
2972
|
function createZapierCliSdk(options = {}) {
|
|
2477
2973
|
return createZapierSdk({
|
|
2478
2974
|
...options,
|
|
@@ -2483,7 +2979,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
2483
2979
|
|
|
2484
2980
|
// package.json
|
|
2485
2981
|
var package_default2 = {
|
|
2486
|
-
version: "0.
|
|
2982
|
+
version: "0.43.1"};
|
|
2487
2983
|
|
|
2488
2984
|
// src/telemetry/builders.ts
|
|
2489
2985
|
function createCliBaseEvent(context = {}) {
|