@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.cjs
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var Conf = require('conf');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
var jwt = require('jsonwebtoken');
|
|
6
|
+
var crossKeychain = require('cross-keychain');
|
|
7
|
+
var crypto = require('crypto');
|
|
8
|
+
var path = require('path');
|
|
9
|
+
var lockfile = require('proper-lockfile');
|
|
4
10
|
var zapierSdk = require('@zapier/zapier-sdk');
|
|
5
11
|
var open = require('open');
|
|
6
|
-
var crypto = require('crypto');
|
|
7
12
|
var express = require('express');
|
|
8
13
|
var pkceChallenge = require('pkce-challenge');
|
|
9
14
|
var ora = require('ora');
|
|
@@ -12,8 +17,6 @@ var inquirer = require('inquirer');
|
|
|
12
17
|
var zod = require('zod');
|
|
13
18
|
var zapierSdkMcp = require('@zapier/zapier-sdk-mcp');
|
|
14
19
|
var esbuild = require('esbuild');
|
|
15
|
-
var fs = require('fs');
|
|
16
|
-
var path = require('path');
|
|
17
20
|
var promises = require('fs/promises');
|
|
18
21
|
var ts = require('typescript');
|
|
19
22
|
require('is-installed-globally');
|
|
@@ -42,20 +45,601 @@ function _interopNamespace(e) {
|
|
|
42
45
|
return Object.freeze(n);
|
|
43
46
|
}
|
|
44
47
|
|
|
45
|
-
var
|
|
46
|
-
var
|
|
48
|
+
var Conf__default = /*#__PURE__*/_interopDefault(Conf);
|
|
49
|
+
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
50
|
+
var jwt__namespace = /*#__PURE__*/_interopNamespace(jwt);
|
|
47
51
|
var crypto__default = /*#__PURE__*/_interopDefault(crypto);
|
|
52
|
+
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
53
|
+
var lockfile__namespace = /*#__PURE__*/_interopNamespace(lockfile);
|
|
54
|
+
var open__default = /*#__PURE__*/_interopDefault(open);
|
|
48
55
|
var express__default = /*#__PURE__*/_interopDefault(express);
|
|
49
56
|
var pkceChallenge__default = /*#__PURE__*/_interopDefault(pkceChallenge);
|
|
50
57
|
var ora__default = /*#__PURE__*/_interopDefault(ora);
|
|
51
58
|
var chalk3__default = /*#__PURE__*/_interopDefault(chalk3);
|
|
52
59
|
var inquirer__default = /*#__PURE__*/_interopDefault(inquirer);
|
|
53
|
-
var fs__namespace = /*#__PURE__*/_interopNamespace(fs);
|
|
54
|
-
var path__namespace = /*#__PURE__*/_interopNamespace(path);
|
|
55
60
|
var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
|
|
56
61
|
var Handlebars__default = /*#__PURE__*/_interopDefault(Handlebars);
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
var __defProp = Object.defineProperty;
|
|
64
|
+
var __export = (target, all) => {
|
|
65
|
+
for (var name in all)
|
|
66
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// src/login.ts
|
|
70
|
+
var login_exports = {};
|
|
71
|
+
__export(login_exports, {
|
|
72
|
+
AUTH_MODE_HEADER: () => AUTH_MODE_HEADER,
|
|
73
|
+
ZapierAuthenticationError: () => ZapierAuthenticationError,
|
|
74
|
+
createCache: () => createCache,
|
|
75
|
+
getAuthAuthorizeUrl: () => getAuthAuthorizeUrl,
|
|
76
|
+
getAuthTokenUrl: () => getAuthTokenUrl,
|
|
77
|
+
getConfig: () => getConfig,
|
|
78
|
+
getConfigPath: () => getConfigPath,
|
|
79
|
+
getLoggedInUser: () => getLoggedInUser,
|
|
80
|
+
getLoginStorageMode: () => getLoginStorageMode,
|
|
81
|
+
getPkceLoginConfig: () => getPkceLoginConfig,
|
|
82
|
+
getToken: () => getToken,
|
|
83
|
+
logout: () => logout,
|
|
84
|
+
unloadConfig: () => unloadConfig,
|
|
85
|
+
updateLogin: () => updateLogin
|
|
86
|
+
});
|
|
87
|
+
var SERVICE = "zapier-sdk-cli";
|
|
88
|
+
var ACCOUNT = "login";
|
|
89
|
+
var cachedBackendInfo;
|
|
90
|
+
async function getBackendInfo() {
|
|
91
|
+
if (!cachedBackendInfo) {
|
|
92
|
+
const keyring = await crossKeychain.getKeyring();
|
|
93
|
+
cachedBackendInfo = `${keyring.name} (${keyring.id})`;
|
|
94
|
+
}
|
|
95
|
+
return cachedBackendInfo;
|
|
96
|
+
}
|
|
97
|
+
var keychainQueue = Promise.resolve();
|
|
98
|
+
function enqueue(fn) {
|
|
99
|
+
const result = keychainQueue.then(fn, fn);
|
|
100
|
+
keychainQueue = result.then(
|
|
101
|
+
() => {
|
|
102
|
+
},
|
|
103
|
+
() => {
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
async function getTokensFromKeychain({
|
|
109
|
+
debugLog
|
|
110
|
+
} = {}) {
|
|
111
|
+
return enqueue(async () => {
|
|
112
|
+
const backendInfo = await getBackendInfo();
|
|
113
|
+
debugLog?.(`Keychain read via ${backendInfo}`);
|
|
114
|
+
const startTime = Date.now();
|
|
115
|
+
const raw = await crossKeychain.getPassword(SERVICE, ACCOUNT);
|
|
116
|
+
debugLog?.(`Keychain read completed in ${Date.now() - startTime}ms`);
|
|
117
|
+
if (!raw) {
|
|
118
|
+
debugLog?.("Keychain returned no data");
|
|
119
|
+
return void 0;
|
|
120
|
+
}
|
|
121
|
+
let parsed;
|
|
122
|
+
try {
|
|
123
|
+
parsed = JSON.parse(raw);
|
|
124
|
+
} catch {
|
|
125
|
+
debugLog?.("Keychain data is not valid JSON");
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
if (typeof parsed.login_jwt === "string" && typeof parsed.login_refresh_token === "string") {
|
|
129
|
+
return {
|
|
130
|
+
login_jwt: parsed.login_jwt,
|
|
131
|
+
login_refresh_token: parsed.login_refresh_token
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
debugLog?.("Keychain data has invalid shape", parsed);
|
|
135
|
+
return void 0;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
async function setTokensInKeychain({
|
|
139
|
+
data,
|
|
140
|
+
debugLog
|
|
141
|
+
}) {
|
|
142
|
+
return enqueue(async () => {
|
|
143
|
+
const backendInfo = await getBackendInfo();
|
|
144
|
+
debugLog?.(`Keychain write via ${backendInfo}`);
|
|
145
|
+
const startTime = Date.now();
|
|
146
|
+
await crossKeychain.setPassword(SERVICE, ACCOUNT, JSON.stringify(data));
|
|
147
|
+
debugLog?.(`Keychain write completed in ${Date.now() - startTime}ms`);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
async function clearTokensFromKeychain({
|
|
151
|
+
debugLog
|
|
152
|
+
} = {}) {
|
|
153
|
+
return enqueue(async () => {
|
|
154
|
+
try {
|
|
155
|
+
const backendInfo = await getBackendInfo();
|
|
156
|
+
debugLog?.(`Keychain clear via ${backendInfo}`);
|
|
157
|
+
await crossKeychain.deletePassword(SERVICE, ACCOUNT);
|
|
158
|
+
} catch {
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
var SERVICE2 = "zapier-sdk-cache";
|
|
163
|
+
var CONFIG_KEY = "cache";
|
|
164
|
+
var LOCK_UPDATE_MS = 5e3;
|
|
165
|
+
var LOCK_STALE_MS = 1e4;
|
|
166
|
+
var LOCK_RETRY_WAIT_MS = 100;
|
|
167
|
+
var LOCK_RETRY_MAX_WAIT_MS = 1e3;
|
|
168
|
+
var LOCK_RETRY_COUNT = 120;
|
|
169
|
+
function keychainAccount(key) {
|
|
170
|
+
return crypto.createHash("sha256").update(key).digest("hex");
|
|
171
|
+
}
|
|
172
|
+
function readConfigMap() {
|
|
173
|
+
const cfg = getConfig();
|
|
174
|
+
const stored = cfg.get(CONFIG_KEY);
|
|
175
|
+
if (stored && typeof stored === "object") {
|
|
176
|
+
return stored;
|
|
177
|
+
}
|
|
178
|
+
return {};
|
|
179
|
+
}
|
|
180
|
+
function writeConfigMap(map) {
|
|
181
|
+
getConfig().set(CONFIG_KEY, map);
|
|
182
|
+
}
|
|
183
|
+
function entryIsExpired(entry) {
|
|
184
|
+
return entry.expires_at !== void 0 && entry.expires_at <= Date.now();
|
|
185
|
+
}
|
|
186
|
+
function createCache() {
|
|
187
|
+
return {
|
|
188
|
+
async get(key) {
|
|
189
|
+
const entry = readConfigMap()[key];
|
|
190
|
+
if (!entry) return void 0;
|
|
191
|
+
if (entryIsExpired(entry)) return void 0;
|
|
192
|
+
if (entry.secret) {
|
|
193
|
+
const stored = await enqueue(async () => {
|
|
194
|
+
await getBackendInfo();
|
|
195
|
+
return crossKeychain.getPassword(SERVICE2, keychainAccount(key));
|
|
196
|
+
});
|
|
197
|
+
if (!stored) {
|
|
198
|
+
return void 0;
|
|
199
|
+
}
|
|
200
|
+
return { value: stored, expiresAt: entry.expires_at };
|
|
201
|
+
}
|
|
202
|
+
if (entry.value === void 0) return void 0;
|
|
203
|
+
return { value: entry.value, expiresAt: entry.expires_at };
|
|
204
|
+
},
|
|
205
|
+
async set(key, value, options) {
|
|
206
|
+
const secret = options?.secret ?? false;
|
|
207
|
+
const expiresAt = options?.ttl ? Date.now() + options.ttl * 1e3 : void 0;
|
|
208
|
+
if (secret) {
|
|
209
|
+
try {
|
|
210
|
+
await enqueue(async () => {
|
|
211
|
+
await getBackendInfo();
|
|
212
|
+
await crossKeychain.setPassword(SERVICE2, keychainAccount(key), value);
|
|
213
|
+
});
|
|
214
|
+
} catch {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const map = readConfigMap();
|
|
218
|
+
map[key] = { secret: true, expires_at: expiresAt };
|
|
219
|
+
try {
|
|
220
|
+
writeConfigMap(map);
|
|
221
|
+
} catch {
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
const map = readConfigMap();
|
|
225
|
+
map[key] = { secret: false, value, expires_at: expiresAt };
|
|
226
|
+
try {
|
|
227
|
+
writeConfigMap(map);
|
|
228
|
+
} catch {
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
async delete(key) {
|
|
233
|
+
const map = readConfigMap();
|
|
234
|
+
const entry = map[key];
|
|
235
|
+
if (entry) {
|
|
236
|
+
delete map[key];
|
|
237
|
+
try {
|
|
238
|
+
writeConfigMap(map);
|
|
239
|
+
} catch {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (entry?.secret) {
|
|
243
|
+
try {
|
|
244
|
+
await enqueue(async () => {
|
|
245
|
+
await getBackendInfo();
|
|
246
|
+
await crossKeychain.deletePassword(SERVICE2, keychainAccount(key));
|
|
247
|
+
});
|
|
248
|
+
} catch {
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
async withLock(_key, fn) {
|
|
253
|
+
const cfg = getConfig();
|
|
254
|
+
const lockTarget = `${cfg.path}.cache-lock`;
|
|
255
|
+
try {
|
|
256
|
+
fs.mkdirSync(path.dirname(lockTarget), { recursive: true });
|
|
257
|
+
if (!fs.existsSync(lockTarget)) {
|
|
258
|
+
fs.writeFileSync(lockTarget, "");
|
|
259
|
+
}
|
|
260
|
+
} catch {
|
|
261
|
+
return fn();
|
|
262
|
+
}
|
|
263
|
+
let release = null;
|
|
264
|
+
try {
|
|
265
|
+
release = await lockfile__namespace.lock(lockTarget, {
|
|
266
|
+
stale: LOCK_STALE_MS,
|
|
267
|
+
update: LOCK_UPDATE_MS,
|
|
268
|
+
retries: {
|
|
269
|
+
retries: LOCK_RETRY_COUNT,
|
|
270
|
+
factor: 1.2,
|
|
271
|
+
minTimeout: LOCK_RETRY_WAIT_MS,
|
|
272
|
+
maxTimeout: LOCK_RETRY_MAX_WAIT_MS
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
} catch {
|
|
276
|
+
return fn();
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
return await fn();
|
|
280
|
+
} finally {
|
|
281
|
+
try {
|
|
282
|
+
await release();
|
|
283
|
+
} catch {
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// src/login/index.ts
|
|
291
|
+
var ZapierAuthenticationError = class extends Error {
|
|
292
|
+
constructor(message) {
|
|
293
|
+
super(message);
|
|
294
|
+
this.name = "ZapierAuthenticationError";
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
var config = null;
|
|
298
|
+
var DEFAULT_AUTH_CLIENT_ID = "grwWZD5hUWGvb4V8ODBuOtXer3h0DBEZ2HR8aay6";
|
|
299
|
+
var TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1e3;
|
|
300
|
+
function createDebugLog(enabled) {
|
|
301
|
+
if (!enabled) {
|
|
302
|
+
return () => {
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
return (message, data) => {
|
|
306
|
+
if (data === void 0) {
|
|
307
|
+
console.log(`[Zapier SDK CLI Login] ${message}`);
|
|
308
|
+
} else {
|
|
309
|
+
console.log(`[Zapier SDK CLI Login] ${message}`, data);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function censorHeaderValue(value) {
|
|
314
|
+
if (value.length > 12) {
|
|
315
|
+
return `${value.substring(0, 4)}...${value.substring(value.length - 4)}`;
|
|
316
|
+
}
|
|
317
|
+
return `${value.charAt(0)}...`;
|
|
318
|
+
}
|
|
319
|
+
function getAuthClientId(clientId) {
|
|
320
|
+
return clientId || DEFAULT_AUTH_CLIENT_ID;
|
|
321
|
+
}
|
|
322
|
+
var AUTH_MODE_HEADER = "X-Auth";
|
|
323
|
+
var DEFAULT_AUTH_BASE_URL = "https://zapier.com";
|
|
324
|
+
function getAuthTokenUrl(options) {
|
|
325
|
+
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
326
|
+
return `${authBaseUrl}/oauth/token/`;
|
|
327
|
+
}
|
|
328
|
+
function getAuthAuthorizeUrl(options) {
|
|
329
|
+
const authBaseUrl = options?.baseUrl || DEFAULT_AUTH_BASE_URL;
|
|
330
|
+
return `${authBaseUrl}/oauth/authorize/`;
|
|
331
|
+
}
|
|
332
|
+
function getPkceLoginConfig(options) {
|
|
333
|
+
return {
|
|
334
|
+
clientId: getAuthClientId(options?.credentials?.clientId),
|
|
335
|
+
tokenUrl: getAuthTokenUrl({ baseUrl: options?.credentials?.baseUrl }),
|
|
336
|
+
authorizeUrl: getAuthAuthorizeUrl({
|
|
337
|
+
baseUrl: options?.credentials?.baseUrl
|
|
338
|
+
})
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
var cachedLogin;
|
|
342
|
+
function getConfig() {
|
|
343
|
+
if (!config) {
|
|
344
|
+
config = new Conf__default.default({ projectName: "zapier-sdk-cli" });
|
|
345
|
+
if (!config.has("login_storage_mode")) {
|
|
346
|
+
config.set(
|
|
347
|
+
"login_storage_mode",
|
|
348
|
+
fs.existsSync(config.path) ? "config" : "keychain"
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return config;
|
|
353
|
+
}
|
|
354
|
+
function unloadConfig() {
|
|
355
|
+
config = null;
|
|
356
|
+
cachedLogin = void 0;
|
|
357
|
+
}
|
|
358
|
+
async function updateLogin(loginData, options = {}) {
|
|
359
|
+
const debugLog = createDebugLog(options.debug ?? false);
|
|
360
|
+
const storage = options.storage ?? cachedLogin?.storage ?? "keychain";
|
|
361
|
+
const expiresAt = Date.now() + loginData.expires_in * 1e3;
|
|
362
|
+
const cfg = getConfig();
|
|
363
|
+
cfg.set("login_storage_mode", storage);
|
|
364
|
+
if (storage === "keychain") {
|
|
365
|
+
await setTokensInKeychain({
|
|
366
|
+
data: {
|
|
367
|
+
login_jwt: loginData.access_token,
|
|
368
|
+
login_refresh_token: loginData.refresh_token
|
|
369
|
+
},
|
|
370
|
+
debugLog
|
|
371
|
+
});
|
|
372
|
+
cfg.set("login_expires_at", expiresAt);
|
|
373
|
+
cfg.delete("login_jwt");
|
|
374
|
+
cfg.delete("login_refresh_token");
|
|
375
|
+
} else {
|
|
376
|
+
cfg.set("login_jwt", loginData.access_token);
|
|
377
|
+
cfg.set("login_refresh_token", loginData.refresh_token);
|
|
378
|
+
cfg.set("login_expires_at", expiresAt);
|
|
379
|
+
await clearTokensFromKeychain({ debugLog });
|
|
380
|
+
}
|
|
381
|
+
cachedLogin = {
|
|
382
|
+
jwt: loginData.access_token,
|
|
383
|
+
refreshToken: loginData.refresh_token,
|
|
384
|
+
expiresAt,
|
|
385
|
+
storage
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function decodeJwtOrThrow(token) {
|
|
389
|
+
if (typeof token !== "string") {
|
|
390
|
+
throw new Error("Expected JWT to be a string");
|
|
391
|
+
}
|
|
392
|
+
const decodedJwt = jwt__namespace.decode(token, { complete: true });
|
|
393
|
+
if (!decodedJwt) {
|
|
394
|
+
throw new Error("Could not decode JWT");
|
|
395
|
+
}
|
|
396
|
+
if (typeof decodedJwt.payload === "string") {
|
|
397
|
+
throw new Error("Did not expect JWT payload to be a string");
|
|
398
|
+
}
|
|
399
|
+
return decodedJwt;
|
|
400
|
+
}
|
|
401
|
+
async function refreshJwt(refreshToken, options = {}) {
|
|
402
|
+
const {
|
|
403
|
+
onEvent,
|
|
404
|
+
fetch: fetch2 = globalThis.fetch,
|
|
405
|
+
credentials,
|
|
406
|
+
debug = false
|
|
407
|
+
} = options;
|
|
408
|
+
const debugLog = createDebugLog(debug);
|
|
409
|
+
const tokenUrl = getAuthTokenUrl({ baseUrl: credentials?.baseUrl });
|
|
410
|
+
const clientId = getAuthClientId(credentials?.clientId);
|
|
411
|
+
const startTime = Date.now();
|
|
412
|
+
try {
|
|
413
|
+
onEvent?.({
|
|
414
|
+
type: "auth_refreshing",
|
|
415
|
+
payload: {
|
|
416
|
+
message: "Refreshing your token...",
|
|
417
|
+
operation: "token_refresh"
|
|
418
|
+
},
|
|
419
|
+
timestamp: Date.now()
|
|
420
|
+
});
|
|
421
|
+
debugLog(`\u2192 POST ${tokenUrl}`, {
|
|
422
|
+
headers: {
|
|
423
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
424
|
+
[AUTH_MODE_HEADER]: "no"
|
|
425
|
+
},
|
|
426
|
+
body: {
|
|
427
|
+
client_id: clientId,
|
|
428
|
+
refresh_token: censorHeaderValue(refreshToken),
|
|
429
|
+
grant_type: "refresh_token"
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
const response = await fetch2(tokenUrl, {
|
|
433
|
+
method: "POST",
|
|
434
|
+
headers: {
|
|
435
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
436
|
+
[AUTH_MODE_HEADER]: "no"
|
|
437
|
+
},
|
|
438
|
+
body: new URLSearchParams({
|
|
439
|
+
client_id: clientId,
|
|
440
|
+
refresh_token: refreshToken,
|
|
441
|
+
grant_type: "refresh_token"
|
|
442
|
+
})
|
|
443
|
+
});
|
|
444
|
+
const duration = Date.now() - startTime;
|
|
445
|
+
if (!response.ok) {
|
|
446
|
+
debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
|
|
447
|
+
throw new Error(
|
|
448
|
+
`Token refresh failed: ${response.status} ${response.statusText}`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
debugLog(`\u2190 ${response.status} ${response.statusText} (${duration}ms)`);
|
|
452
|
+
const data = await response.json();
|
|
453
|
+
await updateLogin(data, { debug });
|
|
454
|
+
debugLog(
|
|
455
|
+
`Token refreshed and saved to ${cachedLogin?.storage ?? "keychain"}`
|
|
456
|
+
);
|
|
457
|
+
onEvent?.({
|
|
458
|
+
type: "auth_success",
|
|
459
|
+
payload: {
|
|
460
|
+
message: "Token refreshed successfully",
|
|
461
|
+
operation: "token_refresh"
|
|
462
|
+
},
|
|
463
|
+
timestamp: Date.now()
|
|
464
|
+
});
|
|
465
|
+
return data.access_token;
|
|
466
|
+
} catch (error) {
|
|
467
|
+
const duration = Date.now() - startTime;
|
|
468
|
+
debugLog(`\u2716 Token refresh failed (${duration}ms)`, {
|
|
469
|
+
error: error instanceof Error ? error.message : error
|
|
470
|
+
});
|
|
471
|
+
cachedLogin = void 0;
|
|
472
|
+
const errorMessage = `Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`;
|
|
473
|
+
onEvent?.({
|
|
474
|
+
type: "auth_error",
|
|
475
|
+
payload: {
|
|
476
|
+
message: errorMessage,
|
|
477
|
+
error: errorMessage,
|
|
478
|
+
operation: "token_refresh"
|
|
479
|
+
},
|
|
480
|
+
timestamp: Date.now()
|
|
481
|
+
});
|
|
482
|
+
throw error;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
var pendingRefresh = null;
|
|
486
|
+
var pendingResolve = null;
|
|
487
|
+
async function resolveStoredLogin(debugLog) {
|
|
488
|
+
if (cachedLogin) {
|
|
489
|
+
debugLog("Using in-memory cached credentials");
|
|
490
|
+
return cachedLogin;
|
|
491
|
+
}
|
|
492
|
+
if (pendingResolve) {
|
|
493
|
+
debugLog("Waiting for existing keychain read to complete");
|
|
494
|
+
return pendingResolve;
|
|
495
|
+
}
|
|
496
|
+
pendingResolve = resolveStoredLoginFromStorage(debugLog).finally(() => {
|
|
497
|
+
pendingResolve = null;
|
|
498
|
+
});
|
|
499
|
+
return pendingResolve;
|
|
500
|
+
}
|
|
501
|
+
async function resolveStoredLoginFromStorage(debugLog) {
|
|
502
|
+
let cfg;
|
|
503
|
+
try {
|
|
504
|
+
cfg = getConfig();
|
|
505
|
+
} catch (error) {
|
|
506
|
+
debugLog("Failed to load config", {
|
|
507
|
+
error: error instanceof Error ? error.message : error
|
|
508
|
+
});
|
|
509
|
+
return void 0;
|
|
510
|
+
}
|
|
511
|
+
const expiresAt = cfg.get("login_expires_at");
|
|
512
|
+
const configJwt = cfg.get("login_jwt");
|
|
513
|
+
const configRefresh = cfg.get("login_refresh_token");
|
|
514
|
+
if (configJwt && configRefresh && typeof expiresAt === "number") {
|
|
515
|
+
debugLog("Loaded credentials from config (legacy format)");
|
|
516
|
+
cachedLogin = {
|
|
517
|
+
jwt: configJwt,
|
|
518
|
+
refreshToken: configRefresh,
|
|
519
|
+
expiresAt,
|
|
520
|
+
storage: "config"
|
|
521
|
+
};
|
|
522
|
+
return cachedLogin;
|
|
523
|
+
}
|
|
524
|
+
if (typeof expiresAt !== "number") {
|
|
525
|
+
debugLog("No stored login credentials found");
|
|
526
|
+
return void 0;
|
|
527
|
+
}
|
|
528
|
+
const keychainData = await getTokensFromKeychain({ debugLog });
|
|
529
|
+
if (!keychainData) {
|
|
530
|
+
debugLog("No tokens found in keychain");
|
|
531
|
+
return void 0;
|
|
532
|
+
}
|
|
533
|
+
debugLog("Loaded credentials from keychain");
|
|
534
|
+
cachedLogin = {
|
|
535
|
+
jwt: keychainData.login_jwt,
|
|
536
|
+
refreshToken: keychainData.login_refresh_token,
|
|
537
|
+
expiresAt,
|
|
538
|
+
storage: "keychain"
|
|
539
|
+
};
|
|
540
|
+
return cachedLogin;
|
|
541
|
+
}
|
|
542
|
+
async function resolveOrRefreshToken(options = {}) {
|
|
543
|
+
const { debug = false } = options;
|
|
544
|
+
const debugLog = createDebugLog(debug);
|
|
545
|
+
const stored = await resolveStoredLogin(debugLog);
|
|
546
|
+
if (!stored) {
|
|
547
|
+
return void 0;
|
|
548
|
+
}
|
|
549
|
+
const { jwt: storedJwt, refreshToken, expiresAt } = stored;
|
|
550
|
+
if (expiresAt > Date.now() + TOKEN_REFRESH_BUFFER_MS) {
|
|
551
|
+
debugLog("Using cached token (still valid)");
|
|
552
|
+
return storedJwt;
|
|
553
|
+
}
|
|
554
|
+
debugLog("Token expired, refreshing...");
|
|
555
|
+
if (pendingRefresh) {
|
|
556
|
+
debugLog("Waiting for existing refresh to complete");
|
|
557
|
+
return pendingRefresh;
|
|
558
|
+
}
|
|
559
|
+
pendingRefresh = refreshJwt(refreshToken, options).finally(() => {
|
|
560
|
+
pendingRefresh = null;
|
|
561
|
+
});
|
|
562
|
+
return await pendingRefresh;
|
|
563
|
+
}
|
|
564
|
+
async function getToken(options = {}) {
|
|
565
|
+
try {
|
|
566
|
+
return await resolveOrRefreshToken(options);
|
|
567
|
+
} catch (error) {
|
|
568
|
+
const message = error instanceof Error ? error.message : "Token refresh failed";
|
|
569
|
+
throw new ZapierAuthenticationError(
|
|
570
|
+
`${message}
|
|
571
|
+
Please run 'login' to authenticate again.`
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
async function getLoggedInUser(options = {}) {
|
|
576
|
+
const jwt2 = await getToken(options).catch(() => void 0);
|
|
577
|
+
if (!jwt2) {
|
|
578
|
+
throw new Error(
|
|
579
|
+
"No valid authentication token available. Please login first."
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
let decodedJwt = decodeJwtOrThrow(jwt2);
|
|
583
|
+
if (decodedJwt.payload["sub_type"] == "service") {
|
|
584
|
+
decodedJwt = decodeJwtOrThrow(decodedJwt.payload["njwt"]);
|
|
585
|
+
}
|
|
586
|
+
if (typeof decodedJwt.payload["zap:acc"] !== "string") {
|
|
587
|
+
throw new Error("JWT payload does not contain accountId");
|
|
588
|
+
}
|
|
589
|
+
const accountId = parseInt(decodedJwt.payload["zap:acc"], 10);
|
|
590
|
+
if (isNaN(accountId)) {
|
|
591
|
+
throw new Error("JWT accountId is not a number");
|
|
592
|
+
}
|
|
593
|
+
if (decodedJwt.payload["sub_type"] !== "customuser" || typeof decodedJwt.payload["sub"] !== "string") {
|
|
594
|
+
throw new Error("JWT payload does not contain customUserId");
|
|
595
|
+
}
|
|
596
|
+
const customUserId = parseInt(decodedJwt.payload["sub"], 10);
|
|
597
|
+
if (isNaN(customUserId)) {
|
|
598
|
+
throw new Error("JWT customUserId is not a number");
|
|
599
|
+
}
|
|
600
|
+
const email = decodedJwt.payload["zap:uname"];
|
|
601
|
+
if (typeof email !== "string") {
|
|
602
|
+
throw new Error("JWT payload does not contain email");
|
|
603
|
+
}
|
|
604
|
+
return {
|
|
605
|
+
accountId,
|
|
606
|
+
customUserId,
|
|
607
|
+
email
|
|
608
|
+
};
|
|
609
|
+
}
|
|
610
|
+
function getLoginStorageMode() {
|
|
611
|
+
const cfg = getConfig();
|
|
612
|
+
if (typeof cfg.get("login_jwt") === "string") {
|
|
613
|
+
return "config";
|
|
614
|
+
}
|
|
615
|
+
const explicitMode = cfg.get("login_storage_mode");
|
|
616
|
+
if (explicitMode === "keychain" || explicitMode === "config") {
|
|
617
|
+
return explicitMode;
|
|
618
|
+
}
|
|
619
|
+
return "keychain";
|
|
620
|
+
}
|
|
621
|
+
async function logout(options = {}) {
|
|
622
|
+
const { onEvent } = options;
|
|
623
|
+
const mode = getLoginStorageMode();
|
|
624
|
+
cachedLogin = void 0;
|
|
625
|
+
await clearTokensFromKeychain();
|
|
626
|
+
const cfg = getConfig();
|
|
627
|
+
cfg.set("login_storage_mode", mode);
|
|
628
|
+
cfg.delete("login_expires_at");
|
|
629
|
+
cfg.delete("login_jwt");
|
|
630
|
+
cfg.delete("login_refresh_token");
|
|
631
|
+
onEvent?.({
|
|
632
|
+
type: "auth_logout",
|
|
633
|
+
payload: { message: "Logged out successfully", operation: "logout" },
|
|
634
|
+
timestamp: Date.now()
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
function getConfigPath() {
|
|
638
|
+
const cfg = getConfig();
|
|
639
|
+
return cfg.path;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// src/utils/constants.ts
|
|
59
643
|
var LOGIN_PORTS = [49505, 50575, 52804, 55981, 61010, 63851];
|
|
60
644
|
var LOGIN_TIMEOUT_MS = 3e5;
|
|
61
645
|
var ZapierCliError = class extends zapierSdk.ZapierError {
|
|
@@ -209,13 +793,13 @@ var login = async ({
|
|
|
209
793
|
timeoutMs = LOGIN_TIMEOUT_MS,
|
|
210
794
|
credentials
|
|
211
795
|
}) => {
|
|
212
|
-
const { clientId, tokenUrl, authorizeUrl } =
|
|
796
|
+
const { clientId, tokenUrl, authorizeUrl } = getPkceLoginConfig({
|
|
213
797
|
credentials
|
|
214
798
|
});
|
|
215
799
|
const scope = ensureOfflineAccess(
|
|
216
800
|
credentials?.scope || "internal credentials"
|
|
217
801
|
);
|
|
218
|
-
await
|
|
802
|
+
await logout();
|
|
219
803
|
const availablePort = await findAvailablePort();
|
|
220
804
|
const redirectUri = `http://localhost:${availablePort}/oauth`;
|
|
221
805
|
log_default.info(`Using port ${availablePort} for OAuth callback`);
|
|
@@ -303,13 +887,13 @@ var login = async ({
|
|
|
303
887
|
},
|
|
304
888
|
{
|
|
305
889
|
headers: {
|
|
306
|
-
[
|
|
890
|
+
[AUTH_MODE_HEADER]: "no",
|
|
307
891
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
308
892
|
}
|
|
309
893
|
}
|
|
310
894
|
);
|
|
311
895
|
let targetStorage;
|
|
312
|
-
if (
|
|
896
|
+
if (getLoginStorageMode() === "config") {
|
|
313
897
|
const { upgrade } = await inquirer__default.default.prompt([
|
|
314
898
|
{
|
|
315
899
|
type: "confirm",
|
|
@@ -323,13 +907,13 @@ var login = async ({
|
|
|
323
907
|
targetStorage = "keychain";
|
|
324
908
|
}
|
|
325
909
|
try {
|
|
326
|
-
await
|
|
910
|
+
await updateLogin(data, { storage: targetStorage });
|
|
327
911
|
} catch (err) {
|
|
328
912
|
if (targetStorage === "keychain") {
|
|
329
913
|
log_default.warn(
|
|
330
|
-
`Could not store credentials in system keychain. Storing in plaintext at ${
|
|
914
|
+
`Could not store credentials in system keychain. Storing in plaintext at ${getConfigPath()}.`
|
|
331
915
|
);
|
|
332
|
-
await
|
|
916
|
+
await updateLogin(data, { storage: "config" });
|
|
333
917
|
} else {
|
|
334
918
|
throw err;
|
|
335
919
|
}
|
|
@@ -354,85 +938,65 @@ function toPkceCredentials(credentials) {
|
|
|
354
938
|
}
|
|
355
939
|
return void 0;
|
|
356
940
|
}
|
|
357
|
-
var loginPlugin = (
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
credentials: pkceCredentials
|
|
368
|
-
});
|
|
369
|
-
const user = await cliLogin.getLoggedInUser();
|
|
370
|
-
sdk.context.eventEmission.emit(
|
|
371
|
-
"platform.sdk.ApplicationLifecycleEvent",
|
|
372
|
-
zapierSdk.buildApplicationLifecycleEvent(
|
|
373
|
-
{ lifecycle_event_type: "login_success" },
|
|
374
|
-
{ customuser_id: user.customUserId, account_id: user.accountId }
|
|
375
|
-
)
|
|
376
|
-
);
|
|
377
|
-
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
378
|
-
};
|
|
379
|
-
return {
|
|
380
|
-
login: loginFn,
|
|
381
|
-
context: {
|
|
382
|
-
meta: {
|
|
383
|
-
login: {
|
|
384
|
-
categories: ["account"],
|
|
385
|
-
inputSchema: LoginSchema,
|
|
386
|
-
supportsJsonOutput: false
|
|
387
|
-
}
|
|
941
|
+
var loginPlugin = zapierSdk.definePlugin(
|
|
942
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
943
|
+
name: "login",
|
|
944
|
+
categories: ["account"],
|
|
945
|
+
inputSchema: LoginSchema,
|
|
946
|
+
supportsJsonOutput: false,
|
|
947
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
948
|
+
const timeoutSeconds = options.timeout ? parseInt(options.timeout, 10) : 300;
|
|
949
|
+
if (isNaN(timeoutSeconds) || timeoutSeconds <= 0) {
|
|
950
|
+
throw new Error("Timeout must be a positive number");
|
|
388
951
|
}
|
|
952
|
+
const resolvedCredentials = await sdk2.context.resolveCredentials();
|
|
953
|
+
const pkceCredentials = toPkceCredentials(resolvedCredentials);
|
|
954
|
+
await login_default({
|
|
955
|
+
timeoutMs: timeoutSeconds * 1e3,
|
|
956
|
+
credentials: pkceCredentials
|
|
957
|
+
});
|
|
958
|
+
const user = await getLoggedInUser();
|
|
959
|
+
sdk2.context.eventEmission.emit(
|
|
960
|
+
"platform.sdk.ApplicationLifecycleEvent",
|
|
961
|
+
zapierSdk.buildApplicationLifecycleEvent(
|
|
962
|
+
{ lifecycle_event_type: "login_success" },
|
|
963
|
+
{ customuser_id: user.customUserId, account_id: user.accountId }
|
|
964
|
+
)
|
|
965
|
+
);
|
|
966
|
+
console.log(`\u2705 Successfully logged in as ${user.email}`);
|
|
389
967
|
}
|
|
390
|
-
}
|
|
391
|
-
|
|
968
|
+
})
|
|
969
|
+
);
|
|
392
970
|
var LogoutSchema = zod.z.object({}).describe("Log out of your Zapier account");
|
|
393
971
|
|
|
394
972
|
// src/plugins/logout/index.ts
|
|
395
|
-
var
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
});
|
|
973
|
+
var logoutPlugin = zapierSdk.definePlugin(
|
|
974
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
975
|
+
name: "logout",
|
|
976
|
+
categories: ["account"],
|
|
977
|
+
inputSchema: LogoutSchema,
|
|
978
|
+
supportsJsonOutput: false,
|
|
979
|
+
handler: async () => {
|
|
980
|
+
await logout();
|
|
981
|
+
console.log("\u2705 Successfully logged out");
|
|
982
|
+
}
|
|
983
|
+
})
|
|
984
|
+
);
|
|
411
985
|
var McpSchema = zod.z.object({
|
|
412
986
|
port: zod.z.string().optional().describe("Port to listen on (for future HTTP transport)")
|
|
413
987
|
}).describe("Start MCP server for Zapier SDK");
|
|
414
988
|
|
|
415
989
|
// src/plugins/mcp/index.ts
|
|
416
|
-
var mcpPlugin = (
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
context: {
|
|
427
|
-
meta: {
|
|
428
|
-
mcp: {
|
|
429
|
-
categories: ["utility"],
|
|
430
|
-
inputSchema: McpSchema
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
};
|
|
990
|
+
var mcpPlugin = zapierSdk.definePlugin(
|
|
991
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
992
|
+
name: "mcp",
|
|
993
|
+
categories: ["utility"],
|
|
994
|
+
inputSchema: McpSchema,
|
|
995
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
996
|
+
await zapierSdkMcp.startMcpServer({ ...options, debug: sdk2.context.options?.debug });
|
|
997
|
+
}
|
|
998
|
+
})
|
|
999
|
+
);
|
|
436
1000
|
var BundleCodeSchema = zod.z.object({
|
|
437
1001
|
input: zod.z.string().min(1).describe("Input TypeScript file path to bundle"),
|
|
438
1002
|
output: zapierSdk.OutputPropertySchema.optional().describe(
|
|
@@ -443,22 +1007,14 @@ var BundleCodeSchema = zod.z.object({
|
|
|
443
1007
|
target: zod.z.string().optional().describe("ECMAScript target version"),
|
|
444
1008
|
cjs: zod.z.boolean().optional().describe("Output CommonJS format instead of ESM")
|
|
445
1009
|
}).describe("Bundle TypeScript code into executable JavaScript");
|
|
446
|
-
var bundleCodePlugin = (
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
bundleCode: {
|
|
455
|
-
categories: ["utility", "deprecated"],
|
|
456
|
-
inputSchema: BundleCodeSchema
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
};
|
|
1010
|
+
var bundleCodePlugin = zapierSdk.definePlugin(
|
|
1011
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
1012
|
+
name: "bundleCode",
|
|
1013
|
+
categories: ["utility", "deprecated"],
|
|
1014
|
+
inputSchema: BundleCodeSchema,
|
|
1015
|
+
handler: async ({ options }) => bundleCode(options)
|
|
1016
|
+
})
|
|
1017
|
+
);
|
|
462
1018
|
var ZapierBundleError = class extends Error {
|
|
463
1019
|
constructor(message, details, originalError) {
|
|
464
1020
|
super(message);
|
|
@@ -525,25 +1081,14 @@ async function bundleCode(options) {
|
|
|
525
1081
|
}
|
|
526
1082
|
}
|
|
527
1083
|
var GetLoginConfigPathSchema = zod.z.object({}).describe("Show the path to the login configuration file");
|
|
528
|
-
var getLoginConfigPathPlugin = (
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
)
|
|
535
|
-
|
|
536
|
-
getLoginConfigPath: getLoginConfigPathWithSdk,
|
|
537
|
-
context: {
|
|
538
|
-
meta: {
|
|
539
|
-
getLoginConfigPath: {
|
|
540
|
-
categories: ["utility"],
|
|
541
|
-
inputSchema: GetLoginConfigPathSchema
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
};
|
|
546
|
-
};
|
|
1084
|
+
var getLoginConfigPathPlugin = zapierSdk.definePlugin(
|
|
1085
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
1086
|
+
name: "getLoginConfigPath",
|
|
1087
|
+
categories: ["utility"],
|
|
1088
|
+
inputSchema: GetLoginConfigPathSchema,
|
|
1089
|
+
handler: async () => getConfigPath()
|
|
1090
|
+
})
|
|
1091
|
+
);
|
|
547
1092
|
var AddSchema = zod.z.object({
|
|
548
1093
|
apps: zod.z.array(zod.z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
|
|
549
1094
|
"One or more app keys to add (e.g., 'slack', 'github', 'trello')"
|
|
@@ -571,111 +1116,105 @@ async function detectTypesOutputDirectory() {
|
|
|
571
1116
|
}
|
|
572
1117
|
return "./zapier/apps/";
|
|
573
1118
|
}
|
|
574
|
-
var addPlugin = (
|
|
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
|
-
|
|
616
|
-
|
|
617
|
-
case "connections_lookup_start":
|
|
618
|
-
console.log(`\u{1F510} Looking up ${event.count} connection(s)...`);
|
|
619
|
-
break;
|
|
620
|
-
case "connections_lookup_complete":
|
|
621
|
-
console.log(`\u{1F510} Found ${event.count} connection(s)`);
|
|
622
|
-
break;
|
|
623
|
-
case "connection_matched":
|
|
624
|
-
const appWithConnection = appSlugAndKeyMap.get(event.app) || event.app;
|
|
625
|
-
console.log(
|
|
626
|
-
`\u{1F510} Using connection ${event.connectionId} (${event.connectionTitle}) for ${appWithConnection}`
|
|
627
|
-
);
|
|
628
|
-
break;
|
|
629
|
-
case "connection_not_matched":
|
|
630
|
-
const appWithoutConnection = appSlugAndKeyMap.get(event.app) || event.app;
|
|
631
|
-
console.warn(
|
|
632
|
-
`\u26A0\uFE0F No matching connection found for ${appWithoutConnection}`
|
|
633
|
-
);
|
|
634
|
-
break;
|
|
635
|
-
case "file_written":
|
|
636
|
-
console.log(
|
|
637
|
-
`\u{1F527} Generated types for ${event.manifestKey} at ${event.filePath}`
|
|
638
|
-
);
|
|
639
|
-
break;
|
|
640
|
-
case "app_processing_error":
|
|
641
|
-
const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
|
|
642
|
-
console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
|
|
643
|
-
break;
|
|
644
|
-
}
|
|
645
|
-
};
|
|
646
|
-
const manifestResult = await sdk.buildManifest({
|
|
647
|
-
apps: appKeys,
|
|
648
|
-
skipWrite: false,
|
|
649
|
-
configPath,
|
|
650
|
-
onProgress: handleManifestProgress
|
|
651
|
-
});
|
|
652
|
-
const typesResult = await sdk.generateAppTypes({
|
|
653
|
-
apps: appKeys,
|
|
654
|
-
connections: connectionIds,
|
|
655
|
-
skipWrite: false,
|
|
656
|
-
typesOutputDirectory: resolvedTypesOutput,
|
|
657
|
-
onProgress: handleTypesProgress
|
|
658
|
-
});
|
|
659
|
-
const results = manifestResult.manifest?.apps || {};
|
|
660
|
-
const successfulApps = Object.keys(results).filter(
|
|
661
|
-
(manifestKey) => typesResult.writtenFiles?.[manifestKey]
|
|
662
|
-
);
|
|
663
|
-
if (successfulApps.length > 0) {
|
|
664
|
-
console.log(`\u2705 Added ${successfulApps.length} app(s) to manifest`);
|
|
665
|
-
}
|
|
666
|
-
}, AddSchema);
|
|
667
|
-
return {
|
|
668
|
-
add,
|
|
669
|
-
context: {
|
|
670
|
-
meta: {
|
|
671
|
-
add: {
|
|
672
|
-
categories: ["utility"],
|
|
673
|
-
inputSchema: AddSchema
|
|
1119
|
+
var addPlugin = zapierSdk.definePlugin(
|
|
1120
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
1121
|
+
name: "add",
|
|
1122
|
+
categories: ["utility"],
|
|
1123
|
+
inputSchema: AddSchema,
|
|
1124
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
1125
|
+
const {
|
|
1126
|
+
apps: appKeys,
|
|
1127
|
+
connections: connectionIds,
|
|
1128
|
+
configPath,
|
|
1129
|
+
typesOutput = await detectTypesOutputDirectory()
|
|
1130
|
+
} = options;
|
|
1131
|
+
const resolvedTypesOutput = path.resolve(typesOutput);
|
|
1132
|
+
console.log(`\u{1F4E6} Adding ${appKeys.length} app(s)...`);
|
|
1133
|
+
const appSlugAndKeyMap = /* @__PURE__ */ new Map();
|
|
1134
|
+
const handleManifestProgress = (event) => {
|
|
1135
|
+
switch (event.type) {
|
|
1136
|
+
case "apps_lookup_start":
|
|
1137
|
+
console.log(`\u{1F4E6} Looking up ${event.count} app(s)...`);
|
|
1138
|
+
break;
|
|
1139
|
+
case "app_found":
|
|
1140
|
+
const displayName = event.app.slug ? `${event.app.slug} (${event.app.key})` : event.app.key;
|
|
1141
|
+
appSlugAndKeyMap.set(event.app.key, displayName);
|
|
1142
|
+
break;
|
|
1143
|
+
case "apps_lookup_complete":
|
|
1144
|
+
if (event.count === 0) {
|
|
1145
|
+
console.warn("\u26A0\uFE0F No apps found");
|
|
1146
|
+
}
|
|
1147
|
+
break;
|
|
1148
|
+
case "app_processing_start":
|
|
1149
|
+
const appName = event.slug ? `${event.slug} (${event.app})` : event.app;
|
|
1150
|
+
console.log(`\u{1F4E6} Adding ${appName}...`);
|
|
1151
|
+
break;
|
|
1152
|
+
case "manifest_updated":
|
|
1153
|
+
const appDisplay = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1154
|
+
console.log(
|
|
1155
|
+
`\u{1F4DD} Locked ${appDisplay} to ${event.app}@${event.version} using key '${event.manifestKey}'`
|
|
1156
|
+
);
|
|
1157
|
+
break;
|
|
1158
|
+
case "app_processing_error":
|
|
1159
|
+
const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1160
|
+
console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
|
|
1161
|
+
break;
|
|
674
1162
|
}
|
|
1163
|
+
};
|
|
1164
|
+
const handleTypesProgress = (event) => {
|
|
1165
|
+
switch (event.type) {
|
|
1166
|
+
case "connections_lookup_start":
|
|
1167
|
+
console.log(`\u{1F510} Looking up ${event.count} connection(s)...`);
|
|
1168
|
+
break;
|
|
1169
|
+
case "connections_lookup_complete":
|
|
1170
|
+
console.log(`\u{1F510} Found ${event.count} connection(s)`);
|
|
1171
|
+
break;
|
|
1172
|
+
case "connection_matched":
|
|
1173
|
+
const appWithConnection = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1174
|
+
console.log(
|
|
1175
|
+
`\u{1F510} Using connection ${event.connectionId} (${event.connectionTitle}) for ${appWithConnection}`
|
|
1176
|
+
);
|
|
1177
|
+
break;
|
|
1178
|
+
case "connection_not_matched":
|
|
1179
|
+
const appWithoutConnection = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1180
|
+
console.warn(
|
|
1181
|
+
`\u26A0\uFE0F No matching connection found for ${appWithoutConnection}`
|
|
1182
|
+
);
|
|
1183
|
+
break;
|
|
1184
|
+
case "file_written":
|
|
1185
|
+
console.log(
|
|
1186
|
+
`\u{1F527} Generated types for ${event.manifestKey} at ${event.filePath}`
|
|
1187
|
+
);
|
|
1188
|
+
break;
|
|
1189
|
+
case "app_processing_error":
|
|
1190
|
+
const errorApp = appSlugAndKeyMap.get(event.app) || event.app;
|
|
1191
|
+
console.warn(`\u26A0\uFE0F ${event.error} for ${errorApp}`);
|
|
1192
|
+
break;
|
|
1193
|
+
}
|
|
1194
|
+
};
|
|
1195
|
+
const manifestResult = await sdk2.buildManifest({
|
|
1196
|
+
apps: appKeys,
|
|
1197
|
+
skipWrite: false,
|
|
1198
|
+
configPath,
|
|
1199
|
+
onProgress: handleManifestProgress
|
|
1200
|
+
});
|
|
1201
|
+
const typesResult = await sdk2.generateAppTypes({
|
|
1202
|
+
apps: appKeys,
|
|
1203
|
+
connections: connectionIds,
|
|
1204
|
+
skipWrite: false,
|
|
1205
|
+
typesOutputDirectory: resolvedTypesOutput,
|
|
1206
|
+
onProgress: handleTypesProgress
|
|
1207
|
+
});
|
|
1208
|
+
const results = manifestResult.manifest?.apps || {};
|
|
1209
|
+
const successfulApps = Object.keys(results).filter(
|
|
1210
|
+
(manifestKey) => typesResult.writtenFiles?.[manifestKey]
|
|
1211
|
+
);
|
|
1212
|
+
if (successfulApps.length > 0) {
|
|
1213
|
+
console.log(`\u2705 Added ${successfulApps.length} app(s) to manifest`);
|
|
675
1214
|
}
|
|
676
1215
|
}
|
|
677
|
-
}
|
|
678
|
-
|
|
1216
|
+
})
|
|
1217
|
+
);
|
|
679
1218
|
var GenerateAppTypesSchema = zod.z.object({
|
|
680
1219
|
apps: zod.z.array(zod.z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
|
|
681
1220
|
"One or more app keys to generate types for (e.g., 'slack', 'github', 'trello')"
|
|
@@ -1282,150 +1821,133 @@ function createManifestEntry(app) {
|
|
|
1282
1821
|
version: app.version
|
|
1283
1822
|
};
|
|
1284
1823
|
}
|
|
1285
|
-
var generateAppTypesPlugin = (
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
}
|
|
1309
|
-
const connections = [];
|
|
1310
|
-
if (connectionIds && connectionIds.length > 0) {
|
|
1311
|
-
onProgress?.({
|
|
1312
|
-
type: "connections_lookup_start",
|
|
1313
|
-
count: connectionIds.length
|
|
1314
|
-
});
|
|
1315
|
-
const connectionsIterable = sdk.listConnections({ connections: connectionIds }).items();
|
|
1316
|
-
for await (const connection of connectionsIterable) {
|
|
1317
|
-
connections.push(connection);
|
|
1824
|
+
var generateAppTypesPlugin = zapierSdk.definePlugin(
|
|
1825
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
1826
|
+
name: "generateAppTypes",
|
|
1827
|
+
categories: ["utility"],
|
|
1828
|
+
// Cast: schema validates JSON fields only; GenerateAppTypesOptions adds
|
|
1829
|
+
// the runtime-only `onProgress` callback (passthrough via createFunction).
|
|
1830
|
+
inputSchema: GenerateAppTypesSchema,
|
|
1831
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
1832
|
+
const {
|
|
1833
|
+
apps: appKeys,
|
|
1834
|
+
connections: connectionIds,
|
|
1835
|
+
skipWrite = false,
|
|
1836
|
+
typesOutputDirectory = await detectTypesOutputDirectory(),
|
|
1837
|
+
onProgress
|
|
1838
|
+
} = options;
|
|
1839
|
+
const resolvedTypesOutput = path.resolve(typesOutputDirectory);
|
|
1840
|
+
const result = { typeDefinitions: {} };
|
|
1841
|
+
onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
|
|
1842
|
+
const appsIterable = sdk2.listApps({ apps: appKeys }).items();
|
|
1843
|
+
const apps = [];
|
|
1844
|
+
for await (const app of appsIterable) {
|
|
1845
|
+
apps.push(app);
|
|
1846
|
+
onProgress?.({ type: "app_found", app });
|
|
1318
1847
|
}
|
|
1319
|
-
onProgress?.({
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
type: "app_processing_start",
|
|
1333
|
-
app: app.key,
|
|
1334
|
-
slug: app.slug
|
|
1335
|
-
});
|
|
1336
|
-
try {
|
|
1337
|
-
if (!app.version) {
|
|
1338
|
-
const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
|
|
1339
|
-
onProgress?.({
|
|
1340
|
-
type: "app_processing_error",
|
|
1341
|
-
app: app.key,
|
|
1342
|
-
error: errorMessage
|
|
1343
|
-
});
|
|
1344
|
-
throw new zapierSdk.ZapierValidationError(errorMessage, {
|
|
1345
|
-
details: {
|
|
1346
|
-
appKey: app.key,
|
|
1347
|
-
implementationId: app.implementation_id
|
|
1348
|
-
}
|
|
1349
|
-
});
|
|
1848
|
+
onProgress?.({ type: "apps_lookup_complete", count: apps.length });
|
|
1849
|
+
if (apps.length === 0) {
|
|
1850
|
+
return result;
|
|
1851
|
+
}
|
|
1852
|
+
const connections = [];
|
|
1853
|
+
if (connectionIds && connectionIds.length > 0) {
|
|
1854
|
+
onProgress?.({
|
|
1855
|
+
type: "connections_lookup_start",
|
|
1856
|
+
count: connectionIds.length
|
|
1857
|
+
});
|
|
1858
|
+
const connectionsIterable = sdk2.listConnections({ connections: connectionIds }).items();
|
|
1859
|
+
for await (const connection of connectionsIterable) {
|
|
1860
|
+
connections.push(connection);
|
|
1350
1861
|
}
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1862
|
+
onProgress?.({
|
|
1863
|
+
type: "connections_lookup_complete",
|
|
1864
|
+
count: connections.length
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
if (!skipWrite && resolvedTypesOutput) {
|
|
1868
|
+
await promises.mkdir(resolvedTypesOutput, { recursive: true });
|
|
1869
|
+
}
|
|
1870
|
+
if (!skipWrite) {
|
|
1871
|
+
result.writtenFiles = {};
|
|
1872
|
+
}
|
|
1873
|
+
for (const app of apps) {
|
|
1874
|
+
onProgress?.({
|
|
1875
|
+
type: "app_processing_start",
|
|
1876
|
+
app: app.key,
|
|
1877
|
+
slug: app.slug
|
|
1878
|
+
});
|
|
1879
|
+
try {
|
|
1880
|
+
if (!app.version) {
|
|
1881
|
+
const errorMessage = `Invalid implementation ID format: ${app.implementation_id}. Expected format: <implementationName>@<version>`;
|
|
1358
1882
|
onProgress?.({
|
|
1359
|
-
type: "
|
|
1883
|
+
type: "app_processing_error",
|
|
1360
1884
|
app: app.key,
|
|
1361
|
-
|
|
1362
|
-
connectionTitle: matchingConnection.title || ""
|
|
1885
|
+
error: errorMessage
|
|
1363
1886
|
});
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1887
|
+
throw new zapierSdk.ZapierValidationError(errorMessage, {
|
|
1888
|
+
details: {
|
|
1889
|
+
appKey: app.key,
|
|
1890
|
+
implementationId: app.implementation_id
|
|
1891
|
+
}
|
|
1368
1892
|
});
|
|
1369
1893
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1894
|
+
let connectionId;
|
|
1895
|
+
if (connections.length > 0) {
|
|
1896
|
+
const matchingConnection = connections.find(
|
|
1897
|
+
(conn) => conn.app_key === app.key
|
|
1898
|
+
);
|
|
1899
|
+
if (matchingConnection) {
|
|
1900
|
+
connectionId = matchingConnection.id;
|
|
1901
|
+
onProgress?.({
|
|
1902
|
+
type: "connection_matched",
|
|
1903
|
+
app: app.key,
|
|
1904
|
+
connectionId: matchingConnection.id,
|
|
1905
|
+
connectionTitle: matchingConnection.title || ""
|
|
1906
|
+
});
|
|
1907
|
+
} else {
|
|
1908
|
+
onProgress?.({
|
|
1909
|
+
type: "connection_not_matched",
|
|
1910
|
+
app: app.key
|
|
1911
|
+
});
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
const manifestKey = getManifestKey(app);
|
|
1915
|
+
const generator = new AstTypeGenerator();
|
|
1916
|
+
const typeDefinitionString = await generator.generateTypes({
|
|
1917
|
+
app,
|
|
1918
|
+
connectionId,
|
|
1919
|
+
sdk: sdk2
|
|
1920
|
+
});
|
|
1921
|
+
result.typeDefinitions[manifestKey] = typeDefinitionString;
|
|
1388
1922
|
onProgress?.({
|
|
1389
|
-
type: "
|
|
1923
|
+
type: "type_generated",
|
|
1390
1924
|
manifestKey,
|
|
1391
|
-
|
|
1925
|
+
sizeBytes: typeDefinitionString.length
|
|
1392
1926
|
});
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
throw error;
|
|
1407
|
-
} else {
|
|
1408
|
-
throw new zapierSdk.ZapierUnknownError(errorMessage, {
|
|
1409
|
-
cause: error
|
|
1410
|
-
// Works for both Error and non-Error
|
|
1927
|
+
if (!skipWrite && resolvedTypesOutput && result.writtenFiles) {
|
|
1928
|
+
const filePath = path.join(resolvedTypesOutput, `${manifestKey}.d.ts`);
|
|
1929
|
+
await promises.writeFile(filePath, typeDefinitionString, "utf8");
|
|
1930
|
+
result.writtenFiles[manifestKey] = filePath;
|
|
1931
|
+
onProgress?.({ type: "file_written", manifestKey, filePath });
|
|
1932
|
+
}
|
|
1933
|
+
onProgress?.({ type: "app_processing_complete", app: app.key });
|
|
1934
|
+
} catch (error) {
|
|
1935
|
+
const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
|
|
1936
|
+
onProgress?.({
|
|
1937
|
+
type: "app_processing_error",
|
|
1938
|
+
app: app.key,
|
|
1939
|
+
error: errorMessage
|
|
1411
1940
|
});
|
|
1941
|
+
if (error instanceof zapierSdk.ZapierValidationError) {
|
|
1942
|
+
throw error;
|
|
1943
|
+
}
|
|
1944
|
+
throw new zapierSdk.ZapierUnknownError(errorMessage, { cause: error });
|
|
1412
1945
|
}
|
|
1413
1946
|
}
|
|
1947
|
+
return result;
|
|
1414
1948
|
}
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
return {
|
|
1418
|
-
generateAppTypes,
|
|
1419
|
-
context: {
|
|
1420
|
-
meta: {
|
|
1421
|
-
generateAppTypes: {
|
|
1422
|
-
categories: ["utility"],
|
|
1423
|
-
inputSchema: GenerateAppTypesSchema
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
};
|
|
1428
|
-
};
|
|
1949
|
+
})
|
|
1950
|
+
);
|
|
1429
1951
|
var BuildManifestSchema = zod.z.object({
|
|
1430
1952
|
apps: zod.z.array(zod.z.string().min(1, "App key cannot be empty")).min(1, "At least one app key is required").describe(
|
|
1431
1953
|
"One or more app keys to build manifest entries for (e.g., 'slack', 'github', 'trello')"
|
|
@@ -1441,86 +1963,80 @@ var BuildManifestSchema = zod.z.object({
|
|
|
1441
1963
|
);
|
|
1442
1964
|
|
|
1443
1965
|
// src/plugins/buildManifest/index.ts
|
|
1444
|
-
var buildManifestPlugin = (
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
type: "manifest_entry_built",
|
|
1474
|
-
app: app.key,
|
|
1475
|
-
manifestKey: manifestEntry.implementationName,
|
|
1476
|
-
version: manifestEntry.version || ""
|
|
1477
|
-
});
|
|
1478
|
-
const { key: updatedManifestKey, manifest } = await sdk.context.updateManifestEntry({
|
|
1479
|
-
appKey: app.key,
|
|
1480
|
-
entry: manifestEntry,
|
|
1481
|
-
configPath,
|
|
1482
|
-
skipWrite,
|
|
1483
|
-
manifest: updatedManifest
|
|
1484
|
-
});
|
|
1485
|
-
updatedManifest = manifest;
|
|
1486
|
-
onProgress?.({
|
|
1487
|
-
type: "manifest_updated",
|
|
1488
|
-
app: app.key,
|
|
1489
|
-
manifestKey: updatedManifestKey,
|
|
1490
|
-
version: manifestEntry.version || ""
|
|
1491
|
-
});
|
|
1492
|
-
onProgress?.({ type: "app_processing_complete", app: app.key });
|
|
1493
|
-
} catch (error) {
|
|
1494
|
-
const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
|
|
1966
|
+
var buildManifestPlugin = zapierSdk.definePlugin(
|
|
1967
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
1968
|
+
name: "buildManifest",
|
|
1969
|
+
categories: ["utility"],
|
|
1970
|
+
// Cast: BuildManifestSchema validates JSON-serializable fields only.
|
|
1971
|
+
// BuildManifestOptions adds an `onProgress` callback that rides through
|
|
1972
|
+
// `createFunction`'s passthrough spread at runtime; this widens TInput
|
|
1973
|
+
// so the handler can read it.
|
|
1974
|
+
inputSchema: BuildManifestSchema,
|
|
1975
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
1976
|
+
const {
|
|
1977
|
+
apps: appKeys,
|
|
1978
|
+
skipWrite = false,
|
|
1979
|
+
configPath,
|
|
1980
|
+
onProgress
|
|
1981
|
+
} = options;
|
|
1982
|
+
onProgress?.({ type: "apps_lookup_start", count: appKeys.length });
|
|
1983
|
+
const appsIterable = sdk2.listApps({ apps: appKeys }).items();
|
|
1984
|
+
const apps = [];
|
|
1985
|
+
for await (const app of appsIterable) {
|
|
1986
|
+
apps.push(app);
|
|
1987
|
+
onProgress?.({ type: "app_found", app });
|
|
1988
|
+
}
|
|
1989
|
+
onProgress?.({ type: "apps_lookup_complete", count: apps.length });
|
|
1990
|
+
if (apps.length === 0) {
|
|
1991
|
+
return {};
|
|
1992
|
+
}
|
|
1993
|
+
let updatedManifest;
|
|
1994
|
+
for (const app of apps) {
|
|
1495
1995
|
onProgress?.({
|
|
1496
|
-
type: "
|
|
1996
|
+
type: "app_processing_start",
|
|
1497
1997
|
app: app.key,
|
|
1498
|
-
|
|
1998
|
+
slug: app.slug
|
|
1499
1999
|
});
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
2000
|
+
try {
|
|
2001
|
+
const manifestEntry = createManifestEntry(app);
|
|
2002
|
+
onProgress?.({
|
|
2003
|
+
type: "manifest_entry_built",
|
|
2004
|
+
app: app.key,
|
|
2005
|
+
manifestKey: manifestEntry.implementationName,
|
|
2006
|
+
version: manifestEntry.version || ""
|
|
1506
2007
|
});
|
|
2008
|
+
const { key: updatedManifestKey, manifest } = await sdk2.context.updateManifestEntry({
|
|
2009
|
+
appKey: app.key,
|
|
2010
|
+
entry: manifestEntry,
|
|
2011
|
+
configPath,
|
|
2012
|
+
skipWrite,
|
|
2013
|
+
manifest: updatedManifest
|
|
2014
|
+
});
|
|
2015
|
+
updatedManifest = manifest;
|
|
2016
|
+
onProgress?.({
|
|
2017
|
+
type: "manifest_updated",
|
|
2018
|
+
app: app.key,
|
|
2019
|
+
manifestKey: updatedManifestKey,
|
|
2020
|
+
version: manifestEntry.version || ""
|
|
2021
|
+
});
|
|
2022
|
+
onProgress?.({ type: "app_processing_complete", app: app.key });
|
|
2023
|
+
} catch (error) {
|
|
2024
|
+
const errorMessage = `Failed to process app ${app.key}: ${error instanceof Error ? error.message : String(error)}`;
|
|
2025
|
+
onProgress?.({
|
|
2026
|
+
type: "app_processing_error",
|
|
2027
|
+
app: app.key,
|
|
2028
|
+
error: errorMessage
|
|
2029
|
+
});
|
|
2030
|
+
if (error instanceof zapierSdk.ZapierValidationError) {
|
|
2031
|
+
throw error;
|
|
2032
|
+
}
|
|
2033
|
+
throw new zapierSdk.ZapierUnknownError(errorMessage, { cause: error });
|
|
1507
2034
|
}
|
|
1508
2035
|
}
|
|
2036
|
+
return { manifest: updatedManifest };
|
|
1509
2037
|
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
return {
|
|
1513
|
-
buildManifest,
|
|
1514
|
-
context: {
|
|
1515
|
-
meta: {
|
|
1516
|
-
buildManifest: {
|
|
1517
|
-
categories: ["utility"],
|
|
1518
|
-
inputSchema: BuildManifestSchema
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
};
|
|
1523
|
-
};
|
|
2038
|
+
})
|
|
2039
|
+
);
|
|
1524
2040
|
var FeedbackSchema = zod.z.object({
|
|
1525
2041
|
feedback: zod.z.string().describe(
|
|
1526
2042
|
"Your feedback on the Zapier SDK. Describe what worked well, what was frustrating, or any suggestions."
|
|
@@ -1554,37 +2070,31 @@ async function postWithRetry({
|
|
|
1554
2070
|
}
|
|
1555
2071
|
return response;
|
|
1556
2072
|
}
|
|
1557
|
-
var feedbackPlugin = (
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
feedback: {
|
|
1578
|
-
categories: ["utility"],
|
|
1579
|
-
inputSchema: FeedbackSchema,
|
|
1580
|
-
resolvers: {
|
|
1581
|
-
feedback: feedbackResolver
|
|
1582
|
-
}
|
|
1583
|
-
}
|
|
2073
|
+
var feedbackPlugin = zapierSdk.definePlugin(
|
|
2074
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
2075
|
+
name: "feedback",
|
|
2076
|
+
categories: ["utility"],
|
|
2077
|
+
inputSchema: FeedbackSchema,
|
|
2078
|
+
resolvers: { feedback: feedbackResolver },
|
|
2079
|
+
handler: async ({ sdk: sdk2, options }) => {
|
|
2080
|
+
const user = await getLoggedInUser();
|
|
2081
|
+
const body = JSON.stringify({
|
|
2082
|
+
email: user.email,
|
|
2083
|
+
customuser_id: user.customUserId,
|
|
2084
|
+
feedback: options.feedback
|
|
2085
|
+
});
|
|
2086
|
+
const response = await postWithRetry({
|
|
2087
|
+
body,
|
|
2088
|
+
attemptsLeft: MAX_RETRIES
|
|
2089
|
+
});
|
|
2090
|
+
if (sdk2.context.options?.debug) {
|
|
2091
|
+
const text = await response.text();
|
|
2092
|
+
console.error("[debug] Webhook response:", text);
|
|
1584
2093
|
}
|
|
2094
|
+
return "Thank you for your feedback!";
|
|
1585
2095
|
}
|
|
1586
|
-
}
|
|
1587
|
-
|
|
2096
|
+
})
|
|
2097
|
+
);
|
|
1588
2098
|
var CurlSchema = zod.z.object({
|
|
1589
2099
|
url: zod.z.string().describe("Request URL"),
|
|
1590
2100
|
request: zod.z.enum(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"]).optional().describe("HTTP method (defaults to GET, or POST if data is provided)"),
|
|
@@ -1760,7 +2270,7 @@ async function buildFormData(formArgs, formStringArgs) {
|
|
|
1760
2270
|
}
|
|
1761
2271
|
|
|
1762
2272
|
// src/plugins/curl/index.ts
|
|
1763
|
-
var curlPlugin = (sdk) => {
|
|
2273
|
+
var curlPlugin = zapierSdk.definePlugin((sdk) => {
|
|
1764
2274
|
async function curl(options) {
|
|
1765
2275
|
const {
|
|
1766
2276
|
url: rawUrl,
|
|
@@ -2003,30 +2513,25 @@ ${Array.from(
|
|
|
2003
2513
|
}
|
|
2004
2514
|
}
|
|
2005
2515
|
};
|
|
2006
|
-
};
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
...sdk.context.meta.fetch.categories || [],
|
|
2020
|
-
"deprecated"
|
|
2021
|
-
],
|
|
2022
|
-
deprecation: {
|
|
2023
|
-
message: "This command is deprecated and will be removed soon. Use `curl` instead. Learn more: https://docs.zapier.com/sdk/cli-reference#curl"
|
|
2024
|
-
}
|
|
2516
|
+
});
|
|
2517
|
+
var cliOverridesPlugin = zapierSdk.definePlugin(
|
|
2518
|
+
(sdk) => {
|
|
2519
|
+
const meta = {};
|
|
2520
|
+
if (sdk.context.meta.fetch) {
|
|
2521
|
+
meta.fetch = {
|
|
2522
|
+
...sdk.context.meta.fetch,
|
|
2523
|
+
categories: [
|
|
2524
|
+
...sdk.context.meta.fetch.categories || [],
|
|
2525
|
+
"deprecated"
|
|
2526
|
+
],
|
|
2527
|
+
deprecation: {
|
|
2528
|
+
message: "This command is deprecated and will be removed soon. Use `curl` instead. Learn more: https://docs.zapier.com/sdk/cli-reference#curl"
|
|
2025
2529
|
}
|
|
2026
|
-
}
|
|
2530
|
+
};
|
|
2027
2531
|
}
|
|
2028
|
-
|
|
2029
|
-
}
|
|
2532
|
+
return { context: { meta } };
|
|
2533
|
+
}
|
|
2534
|
+
);
|
|
2030
2535
|
var TEMPLATES = ["basic"];
|
|
2031
2536
|
var InitSchema = zod.z.object({
|
|
2032
2537
|
projectName: zod.z.string().min(1).describe("Name of the project directory to create"),
|
|
@@ -2438,74 +2943,68 @@ function displaySummaryAndNextSteps({
|
|
|
2438
2943
|
}
|
|
2439
2944
|
|
|
2440
2945
|
// src/plugins/init/index.ts
|
|
2441
|
-
var initPlugin = (
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
);
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
}
|
|
2481
|
-
displaySummaryAndNextSteps({
|
|
2482
|
-
projectName,
|
|
2483
|
-
steps,
|
|
2484
|
-
completedSetupStepIds,
|
|
2485
|
-
packageManager
|
|
2486
|
-
});
|
|
2487
|
-
}, InitSchema);
|
|
2488
|
-
return {
|
|
2489
|
-
init,
|
|
2490
|
-
context: {
|
|
2491
|
-
meta: {
|
|
2492
|
-
init: {
|
|
2493
|
-
categories: ["utility"],
|
|
2494
|
-
inputSchema: InitSchema,
|
|
2495
|
-
supportsJsonOutput: false
|
|
2496
|
-
}
|
|
2946
|
+
var initPlugin = zapierSdk.definePlugin(
|
|
2947
|
+
(sdk) => zapierSdk.createPluginMethod(sdk, {
|
|
2948
|
+
name: "init",
|
|
2949
|
+
categories: ["utility"],
|
|
2950
|
+
inputSchema: InitSchema,
|
|
2951
|
+
supportsJsonOutput: false,
|
|
2952
|
+
handler: async ({ options }) => {
|
|
2953
|
+
const { projectName: rawName, skipPrompts = false } = options;
|
|
2954
|
+
const cwd = process.cwd();
|
|
2955
|
+
const { projectName, projectDir } = validateInitOptions({ rawName, cwd });
|
|
2956
|
+
const displayHooks = createConsoleDisplayHooks();
|
|
2957
|
+
const packageManagerInfo = detectPackageManager(cwd);
|
|
2958
|
+
if (packageManagerInfo.name === "unknown") {
|
|
2959
|
+
displayHooks.onWarn(
|
|
2960
|
+
"Could not detect package manager, defaulting to npm."
|
|
2961
|
+
);
|
|
2962
|
+
}
|
|
2963
|
+
const packageManager = packageManagerInfo.name === "unknown" ? "npm" : packageManagerInfo.name;
|
|
2964
|
+
const steps = getInitSteps({
|
|
2965
|
+
projectDir,
|
|
2966
|
+
projectName,
|
|
2967
|
+
packageManager,
|
|
2968
|
+
displayHooks
|
|
2969
|
+
});
|
|
2970
|
+
const completedSetupStepIds = [];
|
|
2971
|
+
for (let i = 0; i < steps.length; i++) {
|
|
2972
|
+
const step = steps[i];
|
|
2973
|
+
const succeeded = await withInterruptCleanup(
|
|
2974
|
+
step.cleanup,
|
|
2975
|
+
() => runStep({
|
|
2976
|
+
step,
|
|
2977
|
+
stepNumber: i + 1,
|
|
2978
|
+
totalSteps: steps.length,
|
|
2979
|
+
skipPrompts,
|
|
2980
|
+
displayHooks
|
|
2981
|
+
})
|
|
2982
|
+
);
|
|
2983
|
+
if (!succeeded) break;
|
|
2984
|
+
completedSetupStepIds.push(step.id);
|
|
2497
2985
|
}
|
|
2986
|
+
if (completedSetupStepIds.length === 0) {
|
|
2987
|
+
throw new ZapierCliExitError(
|
|
2988
|
+
"Project setup failed \u2014 no steps completed."
|
|
2989
|
+
);
|
|
2990
|
+
}
|
|
2991
|
+
displaySummaryAndNextSteps({
|
|
2992
|
+
projectName,
|
|
2993
|
+
steps,
|
|
2994
|
+
completedSetupStepIds,
|
|
2995
|
+
packageManager
|
|
2996
|
+
});
|
|
2498
2997
|
}
|
|
2499
|
-
}
|
|
2500
|
-
|
|
2998
|
+
})
|
|
2999
|
+
);
|
|
2501
3000
|
|
|
2502
3001
|
// package.json with { type: 'json' }
|
|
2503
3002
|
var package_default = {
|
|
2504
3003
|
name: "@zapier/zapier-sdk-cli",
|
|
2505
|
-
version: "0.
|
|
3004
|
+
version: "0.43.1"};
|
|
2506
3005
|
|
|
2507
3006
|
// src/sdk.ts
|
|
2508
|
-
zapierSdk.injectCliLogin(
|
|
3007
|
+
zapierSdk.injectCliLogin(login_exports);
|
|
2509
3008
|
function createZapierCliSdk(options = {}) {
|
|
2510
3009
|
return zapierSdk.createZapierSdk({
|
|
2511
3010
|
...options,
|
|
@@ -2516,7 +3015,7 @@ function createZapierCliSdk(options = {}) {
|
|
|
2516
3015
|
|
|
2517
3016
|
// package.json
|
|
2518
3017
|
var package_default2 = {
|
|
2519
|
-
version: "0.
|
|
3018
|
+
version: "0.43.1"};
|
|
2520
3019
|
|
|
2521
3020
|
// src/telemetry/builders.ts
|
|
2522
3021
|
function createCliBaseEvent(context = {}) {
|